예제 #1
0
        public void IfElseExpressionTest1()
        {
            var tests = new StatementEvalTestCase[]
            {
                new() { Input = "if (true) { 10 }", Expected = 10 },
                new() { Input = "if (false) { 10 }", Expected = null },
                new() { Input = "if (1) { 10 }", Expected = 10 },
                new() { Input = "if (1 < 2) { 10 }", Expected = 10 },
                new() { Input = "if (1 > 2) { 10 }", Expected = null },
                new() { Input = "if (1 > 2) { 10 } else { 20 }", Expected = 20 },
                new() { Input = "if (1 < 2) { 10 } else { 20 }", Expected = 10 }
            };

            foreach (var boolEvalTestCase in tests)
            {
                var evaluated = StaticTests.TestEval(boolEvalTestCase.Input);
                if (boolEvalTestCase.Expected is null)
                {
                    Assert.True(StaticTests.TestNullObject(evaluated),
                                $"evaluated object is not Null, got {evaluated}");
                }
                else
                {
                    StaticTests.TestIntegerObject(evaluated, boolEvalTestCase.Expected);
                }
            }
        }
예제 #2
0
        public void BooleanExpressionEvalTest()
        {
            var tests = new BooleanTest[]
            {
                new() { Input = "true", Value = true },
                new() { Input = "false", Value = false },
                new() { Input = "1 < 2", Value = true },
                new() { Input = "1 > 2", Value = false },
                new() { Input = "1 < 1", Value = false },
                new() { Input = "1 > 1", Value = false },
                new() { Input = "1 == 1", Value = true },
                new() { Input = "1 != 1", Value = false },
                new() { Input = "1 == 2", Value = false },
                new() { Input = "1 != 2", Value = true },
                new() { Input = "true == true", Value = true },
                new() { Input = "false == false", Value = true },
                new() { Input = "true == false", Value = false },
                new() { Input = "true != false", Value = true },
                new() { Input = "false != true", Value = true },
                new() { Input = "(1 < 2) == true", Value = true },
                new() { Input = "(1 < 2) == false", Value = false },
                new() { Input = "(1 > 2) == true", Value = false },
                new() { Input = "(1 > 2) == false", Value = true }
            };

            foreach (var booleanTest in tests)
            {
                var evaluated = StaticTests.TestEval(booleanTest.Input);
                StaticTests.TestBooleanObject(evaluated, booleanTest.Value);
            }
        }
예제 #3
0
        public void HashIndexExpressionTest()
        {
            var passingTests = new IntegerTests[]
            {
                new() { Input = "{'a': 5}['a']", Expected = 5 },
                new() { Input = "let key = 'k'; {'k': 5}[key]", Expected = 5 },
                new() { Input = "{5: 5}[5]", Expected = 5 },
                new() { Input = "{true: 5}[true]", Expected = 5 },
                new() { Input = "{false: 5}[false]", Expected = 5 }
            };

            var failingTests = new OperatorTest[]
            {
                new() { Input = "{}[5]", Expected = "ERROR: [SC16] `{}` does not contain key `5`" },
                new() { Input = "{'a': 5}[5]", Expected = "ERROR: [SC16] `{'a': 5}` does not contain key `5`" }
            };

            foreach (var passingTest in passingTests)
            {
                var evaluated = StaticTests.TestEval(passingTest.Input);
                StaticTests.TestIntegerObject(evaluated, passingTest.Expected);
            }

            foreach (var failingTest in failingTests)
            {
                var evaluated = StaticTests.TestEval(failingTest.Input);
                Assert.AreEqual(failingTest.Expected, evaluated.Inspect());
            }
        }
    }
}
예제 #4
0
        public void HashLiteralTest()
        {
            const string input     = @"let two = 'two';
{
  'one': 10 -9,
  two: 2,
  'thr' + 'ee': 6/2,
  4: 4,
  true: 5,
  false: 6
};";
            var          evaluated = StaticTests.TestEval(input);

            Assert.AreEqual(nameof(ScriptyHash), evaluated.GetType().Name);
            var result   = (ScriptyHash)evaluated;
            var expected = new Dictionary <HashKey, int>
            {
                { ((ScriptyString)"one").HashKey(), 1 },
                { ((ScriptyString)"two").HashKey(), 2 },
                { ((ScriptyString)"three").HashKey(), 3 },
                { ((ScriptyInteger)4).HashKey(), 4 },
                { Evaluator.True.HashKey(), 5 },
                { Evaluator.False.HashKey(), 6 }
            };

            Assert.AreEqual(expected.Count, result.Pairs.Count);

            foreach (var(hkey, hval) in expected)
            {
                var pairExists = result.Pairs.TryGetValue(hkey, out var pair);
                Assert.True(pairExists);
                StaticTests.TestIntegerObject(pair.Value, hval);
            }
        }
예제 #5
0
        public void BuiltinTest2()
        {
            var input = $@"{MapReduceAndSum} 
let a = fun(x) {{ x + 2 }};

map([1,2,3,4], a);";

            var evaluated = StaticTests.TestEval(input);

            Assert.AreEqual(nameof(ScriptyArray), evaluated.GetType().Name);

            var arr      = (ScriptyArray)evaluated;
            var expected = new List <IObject>
            {
                (ScriptyInteger)3,
                (ScriptyInteger)4,
                (ScriptyInteger)5,
                (ScriptyInteger)6
            };

            for (var i = 0; i < expected.Count; i++)
            {
                var ex     = (ScriptyInteger)expected[i];
                var evaled = (ScriptyInteger)arr.Elements[i];
                Assert.AreEqual(ex.Value, evaled.Value);
            }
        }
예제 #6
0
        public void StringEvalTest()
        {
            const string input = "\"Allo, da-da, Tyulen u apparata, da.\"";

            var evaluated = StaticTests.TestEval(input);

            Assert.AreEqual(nameof(ScriptyString), evaluated.GetType().Name);

            var str = (ScriptyString)evaluated;

            Assert.AreEqual(input.Replace("\"", "").Replace("'", ""), str.Value);
        }
예제 #7
0
        public void BuiltinTest1()
        {
            var input = $"{MapReduceAndSum} sum([1,2,3,4]);";

            var evaluated = StaticTests.TestEval(input);

            Assert.AreEqual(nameof(ScriptyInteger), evaluated.GetType().Name);

            var integer = (ScriptyInteger)evaluated;

            Assert.AreEqual(10, integer.Value);
        }
예제 #8
0
        public void StringConcatinationEvalTest()
        {
            const string input    = "\"Allo, da-da,\" + \" \" + \"Tyulen u apparata, da.\"";
            const string expected = "Allo, da-da, Tyulen u apparata, da.";

            var evaluated = StaticTests.TestEval(input);

            Assert.AreEqual(nameof(ScriptyString), evaluated.GetType().Name);

            var str = (ScriptyString)evaluated;

            Assert.AreEqual(expected, str.Value);
        }
예제 #9
0
        public void ClosureTest()
        {
            const string input = @"
let newAdder = fun(x) {
  fun(y) {x + y; };
};

let addTwo = newAdder(2);
addTwo(2);";

            var evaluated = StaticTests.TestEval(input);

            StaticTests.TestIntegerObject(evaluated, 4);
        }
예제 #10
0
        public void ArrayObjectTest()
        {
            const string input     = "[1, 2 * 2, 3 + 3]";
            var          evaluated = StaticTests.TestEval(input);

            Assert.AreEqual(nameof(ScriptyArray), evaluated.GetType().Name);

            var array = (ScriptyArray)evaluated;

            Assert.AreEqual(3, array.Elements.Count);

            StaticTests.TestIntegerObject(array.Elements.First(), 1);
            StaticTests.TestIntegerObject(array.Elements[1], 4);
            StaticTests.TestIntegerObject(array.Elements[2], 6);
        }
예제 #11
0
        public void ErrorHandlingTest()
        {
            var tests = new OperatorTest[]
            {
                new() { Input = "5 + true;", Expected = "[SC3] type mismatch: INTEGER + BOOLEAN" },
                new() { Input = "5 + true; 12;", Expected = "[SC3] type mismatch: INTEGER + BOOLEAN" },
                new() { Input = "-true;", Expected = "[SC4] unknown operator: -BOOLEAN" },
                new() { Input = "false + true;", Expected = "[SC2] unknown operator: BOOLEAN + BOOLEAN" },
                new()
                {
                    Input    = "5; true + false; 6;",
                    Expected = "[SC2] unknown operator: BOOLEAN + BOOLEAN"
                },
                new()
                {
                    Input    = "if (10 > 1) { true + false; }",
                    Expected = "[SC2] unknown operator: BOOLEAN + BOOLEAN"
                },
                new()
                {
                    Input    = "if (10 > 1) { if (9 > 1) { return true + true; } return false; }",
                    Expected = "[SC2] unknown operator: BOOLEAN + BOOLEAN"
                },
                new()
                {
                    Input    = "kekpuk",
                    Expected = "[SC5] identifier not found: kekpuk"
                },
                new()
                {
                    Input    = "'foo' - 'bar'",
                    Expected = "[SC2] unknown operator: STRING - STRING"
                }
            };

            foreach (var errorTest in tests)
            {
                var evaluated = StaticTests.TestEval(errorTest.Input);

                Assert.AreEqual(nameof(ScriptyError), evaluated.GetType().Name);

                var errObj = (ScriptyError)evaluated;

                Assert.AreEqual(errorTest.Expected, errObj.Message);
            }
        }
    }
예제 #12
0
        public void RecursionTest()
        {
            const string input = @"
let recursion = fun(x) {
  if(x > 100) {
    return true;
  } else {
    recursion(x + 1);
  }
};

recursion(0)";

            var evaluated = StaticTests.TestEval(input);

            StaticTests.TestBooleanObject(evaluated, true);
        }
예제 #13
0
        public void FunctionObjectTest()
        {
            const string input     = "fun(x) { x + 2; };";
            var          evaluated = StaticTests.TestEval(input);

            Assert.AreEqual(nameof(ScriptyFunction), evaluated.GetType().Name);

            var fn = (ScriptyFunction)evaluated;

            Assert.AreEqual(1, fn.Parameters.Count);

            Assert.AreEqual("x", fn.Parameters.First().Str());

            const string expectedBody = "(x + 2)";

            Assert.AreEqual(expectedBody, fn.Body.Str());
        }
예제 #14
0
        public void LetStatementsTest2()
        {
            var tests = new LetStatementWithIntegerValueEvalTestCase[]
            {
                new() { Input = "let a = 5; a;", Expected = 5 },
                new() { Input = "let a = 5 * 5; a;", Expected = 25 },
                new() { Input = "let a = 5; let b = a; b;", Expected = 5 },
                new() { Input = "let a = 5; let b = a; let c = a + b + 5; c;", Expected = 15 }
            };

            foreach (var letStatementWithIntegerValueEvalTestCase in tests)
            {
                var evaledValue = StaticTests.TestEval(letStatementWithIntegerValueEvalTestCase.Input);
                StaticTests.TestIntegerObject(evaledValue, letStatementWithIntegerValueEvalTestCase.Expected);
            }
        }
    }
예제 #15
0
        public void BangOperatorTest()
        {
            var tests = new BooleanTest[]
            {
                new() { Input = "!true", Value = false },
                new() { Input = "!false", Value = true },
                new() { Input = "!5", Value = false },
                new() { Input = "!!5", Value = true },
                new() { Input = "!!true", Value = true },
                new() { Input = "!!false", Value = false }
            };

            foreach (var booleanTest in tests)
            {
                var evaluated = StaticTests.TestEval(booleanTest.Input);
                StaticTests.TestBooleanObject(evaluated, booleanTest.Value);
            }
        }
예제 #16
0
        public void FunctionApplicationTest()
        {
            var tests = new LetStatementWithIntegerValueEvalTestCase[]
            {
                new() { Input = "let id = fun(x) { x; }; id(5);", Expected = 5 },
                new() { Input = "let id = fun(x) { return x; }; id(5);", Expected = 5 },
                new() { Input = "let double = fun(x) { x * 2; }; double(5);", Expected = 10 },
                new() { Input = "let add = fun(x, y) { x + y; }; add(228, 322)", Expected = 550 },
                new() { Input = "let add = fun(x, y) { x + y; }; add(5 + 5, add(5, 5));", Expected = 20 },
                new() { Input = "fun(x) { x; }(5);", Expected = 5 }
            };

            foreach (var functionTests in tests)
            {
                var evaluated = StaticTests.TestEval(functionTests.Input);
                StaticTests.TestIntegerObject(evaluated, functionTests.Expected);
            }
        }
예제 #17
0
        public void ReturnStatementTest()
        {
            var tests = new StatementEvalTestCase[]
            {
                new() { Input = "return 10;", Expected = 10 },
                new() { Input = "return 10; 9;", Expected = 10 },
                new() { Input = "return 2 * 5; 9;", Expected = 10 },
                new() { Input = "9; return 2 * 5; 9;", Expected = 10 },
                new()
                {
                    Input = "if (10 > 1) { if (15 > 1) { return 10; } return 1; }", Expected = 10
                }
            };

            foreach (var statementEvalTestCase in tests)
            {
                var evaluated = StaticTests.TestEval(statementEvalTestCase.Input);
                StaticTests.TestIntegerObject(evaluated, statementEvalTestCase.Expected);
            }
        }
예제 #18
0
        private void ArrayIndexExpressionIterationTest(string input, object expected)
        {
            var evaluated = StaticTests.TestEval(input);

            switch (expected.GetType().Name)
            {
            case "Int64":
                var integer = (long)expected;
                StaticTests.TestIntegerObject(evaluated, integer);
                break;

            case "String":
                var str = (string)expected;
                var err = (ScriptyError)evaluated;
                Assert.AreEqual(str, err.Message);
                break;

            default:
                Console.WriteLine(expected.GetType().Name);
                break;
            }
        }
예제 #19
0
        public void IntegerExpressionEvalTest()
        {
            var tests = new IntegerTests[]
            {
                new() { Input = "5", Expected = 5 },
                new() { Input = "228322", Expected = 228322 },
                new() { Input = "-322", Expected = -322 },
                new() { Input = "-228", Expected = -228 },
                new() { Input = "5 + 5 + 5 + 5 - 10", Expected = 10 },
                new() { Input = "2 * 2 * 2 * 2 * 2", Expected = 32 },
                new() { Input = "100 + -50", Expected = 50 },
                new() { Input = "-50 + 100 + -50", Expected = 0 },
                new() { Input = "50 / 2 * 2 + 10", Expected = 60 },
                new() { Input = "20 + 2 * -10", Expected = 0 },
                new() { Input = "2 * (5 + 10)", Expected = 30 },
                new() { Input = "(5 + 10 * 2 + 15 / 3) * 2 + -10", Expected = 50 }
            };

            foreach (var integerTest in tests)
            {
                var evaluated = StaticTests.TestEval(integerTest.Input);
                StaticTests.TestIntegerObject(evaluated, integerTest.Expected);
            }
        }