Пример #1
0
        public void BoolInfixExpressionsParseTest()
        {
            var infixTests = new BoolInfixTest[]
            {
                new() { Input = "true == true", LeftValue = true, RightValue = true, Operator = "==" },
                new() { Input = "true != false", LeftValue = true, RightValue = false, Operator = "!=" },
                new() { Input = "false == false", LeftValue = false, RightValue = false, Operator = "==" }
            };

            foreach (var infixTest in infixTests)
            {
                var lexer   = new Lexer(infixTest.Input);
                var parser  = new Parser(lexer);
                var program = parser.ParseCode();
                StaticTests.CheckParserErrors(parser);

                Assert.AreEqual(1, program.Statements.Count,
                                $"program should have 1 statement, got={program.Statements.Count}");

                var stmt = program.Statements.First() as ExpressionStatement;

                Assert.AreEqual("ExpressionStatement", stmt.GetType().Name,
                                $"first statement not of type 'ExpressionStatement', got={stmt.GetType().Name}");

                var exp = stmt.Expression as InfixExpression;

                StaticTests.TestInfixExpression(stmt.Expression, exp.Left, exp.Operator, exp.Right);
            }
        }
    }
Пример #2
0
        public void BuiltinFunctionsTest()
        {
            var workingCases = new IntegerTests[]
            {
                new() { Input = "length(\"\");", Expected = 0 },
                new() { Input = "length('something');", Expected = 9 },
                new() { Input = "length('hello world');", Expected = 11 }
            };
            var casesWithErrors = new OperatorTest[]
            {
                new() { Input = "length(1);", Expected = "[SC8] invalid operation: {op} has no length." },
                new() { Input = "length('one', '2');", Expected = "[SC7] wrong number of arguments: expected 1, got 2" }
            };

            foreach (var lengthWorkingTest in workingCases)
            {
                StaticTests.TestBuiltinFunction(lengthWorkingTest.Input, lengthWorkingTest.Expected);
            }

            foreach (var casesWithError in casesWithErrors)
            {
                StaticTests.TestBuiltinFunction(casesWithError.Input, casesWithError.Expected);
            }
        }
    }
}
Пример #3
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);
            }
        }
Пример #4
0
        public void IndexExpressionParsingTest()
        {
            var input = "someList[1 + 1]";

            var lexer   = new Lexer(input);
            var parser  = new Parser(lexer);
            var program = parser.ParseCode();

            StaticTests.CheckParserErrors(parser);

            Assert.AreEqual(nameof(ExpressionStatement), program.Statements.First().GetType().Name);

            var stmt = (ExpressionStatement)program.Statements.First();

            Assert.AreEqual(nameof(IndexExpression), stmt.Expression.GetType().Name);

            var indexExp = (IndexExpression)stmt.Expression;

            StaticTests.TestIdentifier(indexExp.Left, "someList");

            var int1 = new IntegerLiteral {
                Token = new Token {
                    Type = Token.Int, Literal = "1"
                }, Value = 1
            };

            StaticTests.TestInfixExpression(indexExp.Index, int1, "+", int1);
        }
Пример #5
0
        public void IfExpressionTest()
        {
            const string input   = "if (x < y) { x }";
            var          lexer   = new Lexer(input);
            var          parser  = new Parser(lexer);
            var          program = parser.ParseCode();

            StaticTests.CheckParserErrors(parser);

            Assert.AreEqual(1, program.Statements.Count,
                            $"program should have 1 statement, got={program.Statements.Count}");

            var stmt = program.Statements.First() as ExpressionStatement;

            Assert.AreEqual("ExpressionStatement", stmt.GetType().Name,
                            $"first statement not of type 'ExpressionStatement', got={stmt.GetType().Name}");

            Assert.AreEqual("IfExpression", stmt.Expression.GetType().Name);

            var exp = stmt.Expression as IfExpression;

            Assert.AreEqual("(x < y)", exp.Condition.Str());

            Assert.AreEqual(1, exp.Consequence.Statements.Count);

            Assert.AreEqual("ExpressionStatement", exp.Consequence.Statements.First().GetType().Name);

            var consequence = exp.Consequence.Statements.First() as ExpressionStatement;

            StaticTests.TestIdentifier(consequence.Expression, "x");

            Assert.AreEqual(null, exp.Alternative);
        }
Пример #6
0
        public void LetStatementsTest()
        {
            const string input  = @"let x = 5; 
let y = 10; 
let foo = 123456789; ";
            var          lexer  = new Lexer(input);
            var          parser = new Parser(lexer);

            var program = parser.ParseCode();

            StaticTests.CheckParserErrors(parser);
            Assert.IsNotNull(program, "ParseProgram returned null");
            Assert.AreEqual(program.Statements.Count, 3,
                            $"program.Statements does not contain 3 statements, got={program.Statements.Count}");
            var tests = new Identifier[]
            {
                new() { Value = "x" },
                new() { Value = "y" },
                new() { Value = "foo" }
            };

            for (var i = 0; i < tests.Length; i++)
            {
                var stmt = program.Statements[i];
                var tt   = tests[i];
                StaticTests.TestLetStatement(stmt as LetStatement, tt.Value);
            }
        }
Пример #7
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);
                }
            }
        }
Пример #8
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);
            }
        }
Пример #9
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());
            }
        }
    }
}
Пример #10
0
        public void CallExpressionTest()
        {
            const string input   = "sub(1, 2 * 3, 4 + 5)";
            var          lexer   = new Lexer(input);
            var          parser  = new Parser(lexer);
            var          program = parser.ParseCode();

            StaticTests.CheckParserErrors(parser);

            Assert.AreEqual(1, program.Statements.Count,
                            $"program should have 1 statement, got={program.Statements.Count}");

            Assert.AreEqual("ExpressionStatement", program.Statements.First().GetType().Name,
                            $"first statement not of type 'ExpressionStatement', got={program.Statements.First().GetType().Name}");

            var stmt = program.Statements.First() as ExpressionStatement;

            Assert.AreEqual("CallExpression", stmt.Expression.GetType().Name,
                            $"first statement not of type 'CallExpression', got={stmt.Expression.GetType().Name}");

            var exp = stmt.Expression as CallExpression;

            StaticTests.TestIdentifier(exp.Function, "sub");

            Assert.AreEqual(3, exp.Arguments.Count);

            Assert.AreEqual("1", exp.Arguments.First().Str());
            Assert.AreEqual("(2 * 3)", exp.Arguments[1].Str());
            Assert.AreEqual("(4 + 5)", exp.Arguments.Last().Str());
        }
Пример #11
0
        public void IntegerLiteralTest()
        {
            const string input   = "100500;";
            var          lexer   = new Lexer(input);
            var          parser  = new Parser(lexer);
            var          program = parser.ParseCode();

            StaticTests.CheckParserErrors(parser);
            Assert.AreEqual(1, program.Statements.Count,
                            $"program should have 1 statement, got={program.Statements.Count}");

            var stmt = program.Statements.First() as ExpressionStatement;

            Assert.AreEqual("ExpressionStatement", stmt.GetType().Name,
                            $"first statement not of type 'ExpressionStatement', got={stmt.GetType().Name}");

            Assert.AreEqual("IntegerLiteral", stmt.Expression.GetType().Name,
                            $"expression not of type 'IntegerLiteral', got={stmt.Expression.GetType().Name}");

            var int64Literal = stmt.Expression as IntegerLiteral;

            Assert.AreEqual(100500, int64Literal.Value, $"literal not 100500, got={int64Literal.Value}");

            Assert.AreEqual("100500", int64Literal.TokenLiteral(),
                            $"literals token literal not 100500, got={int64Literal.TokenLiteral()}");
        }
Пример #12
0
        public void PrefixExpressionsParseTest()
        {
            var prefixTests = new PrefixTest[]
            {
                new() { Input = "!5", Operator = "!", IntegerValue = 5 },
                new() { Input = "-50", Operator = "-", IntegerValue = 50 }
            };

            foreach (var prefixTest in prefixTests)
            {
                var lexer   = new Lexer(prefixTest.Input);
                var parser  = new Parser(lexer);
                var program = parser.ParseCode();
                StaticTests.CheckParserErrors(parser);

                Assert.AreEqual(1, program.Statements.Count,
                                $"program should have 1 statement, got={program.Statements.Count}");

                var stmt = program.Statements.First() as ExpressionStatement;

                Assert.AreEqual("ExpressionStatement", stmt.GetType().Name,
                                $"first statement not of type 'ExpressionStatement', got={stmt.GetType().Name}");

                Assert.AreEqual("PrefixExpression", stmt.Expression.GetType().Name,
                                $"expression not of type 'PrefixExpression', got={stmt.Expression.GetType().Name}");

                var exp = stmt.Expression as PrefixExpression;

                Assert.AreEqual(prefixTest.Operator, exp.Operator,
                                $"operator is not {prefixTest.Operator}, got={exp.Operator}");

                StaticTests.TestIntegerLiteral(exp.Right, prefixTest.IntegerValue);
            }
        }
    }
Пример #13
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);
            }
        }
Пример #14
0
        public void ArrayLiteralParsingTest()
        {
            const string input = "[1, 2 * 2, 3 + 3]";

            var lexer   = new Lexer(input);
            var parser  = new Parser(lexer);
            var program = parser.ParseCode();

            StaticTests.CheckParserErrors(parser);

            Assert.AreEqual(nameof(ExpressionStatement), program.Statements.First().GetType().Name);

            var stmt = (ExpressionStatement)program.Statements.First();

            Assert.AreEqual(nameof(ArrayLiteral), stmt.Expression.GetType().Name);

            var array = (ArrayLiteral)stmt.Expression;

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

            StaticTests.TestIntegerLiteral(array.Elements.First(), 1);
            IntegerLiteral two   = 2;
            IntegerLiteral three = 3;

            StaticTests.TestInfixExpression(array.Elements[1], two, "*", two);
            StaticTests.TestInfixExpression(array.Elements[2], three, "+", three);
        }
Пример #15
0
        public void StringLiteralExpressionTest1()
        {
            var tests = new[]
            {
                "'hello'", "\"world\""
            };


            foreach (var test in tests)
            {
                var lexer   = new Lexer(test);
                var parser  = new Parser(lexer);
                var program = parser.ParseCode();
                StaticTests.CheckParserErrors(parser);

                Assert.AreEqual(nameof(ExpressionStatement), program.Statements.First().GetType().Name);

                var stmt = (ExpressionStatement)program.Statements.First();

                Assert.AreEqual(nameof(StringLiteral), stmt.Expression.GetType().Name);

                var literal = (StringLiteral)stmt.Expression;

                Assert.AreEqual(test.Replace("'", "").Replace("\"", ""), literal.Value);
            }
        }
Пример #16
0
        public void InfixExpressionsParseTest()
        {
            var infixTests = new InfixTest[]
            {
                new() { Input = "5 + 5", LeftValue = 5, RightValue = 5, Operator = "+" },
                new() { Input = "5 - 5", LeftValue = 5, RightValue = 5, Operator = "-" },
                new() { Input = "5 * 5", LeftValue = 5, RightValue = 5, Operator = "*" },
                new() { Input = "5 / 5", LeftValue = 5, RightValue = 5, Operator = "/" },
                new() { Input = "5 > 5", LeftValue = 5, RightValue = 5, Operator = ">" },
                new() { Input = "5 < 5", LeftValue = 5, RightValue = 5, Operator = "<" },
                new() { Input = "5 == 5", LeftValue = 5, RightValue = 5, Operator = "==" },
                new() { Input = "5 != 5", LeftValue = 5, RightValue = 5, Operator = "!=" }
            };

            foreach (var infixTest in infixTests)
            {
                var lexer   = new Lexer(infixTest.Input);
                var parser  = new Parser(lexer);
                var program = parser.ParseCode();
                StaticTests.CheckParserErrors(parser);

                Assert.AreEqual(1, program.Statements.Count,
                                $"program should have 1 statement, got={program.Statements.Count}");

                var stmt = program.Statements.First() as ExpressionStatement;

                Assert.AreEqual("ExpressionStatement", stmt.GetType().Name,
                                $"first statement not of type 'ExpressionStatement', got={stmt.GetType().Name}");

                var exp = stmt.Expression as InfixExpression;

                StaticTests.TestInfixExpression(stmt.Expression, exp.Left, exp.Operator, exp.Right);
            }
        }
Пример #17
0
        public void OperatorPrecedenceParseTest()
        {
            var tests = new OperatorTest[]
            {
                new() { Input = "-a * b", Expected = "((-a) * b)" },
                new() { Input = "!-a", Expected = "(!(-a))" },
                new() { Input = "a + b + c", Expected = "((a + b) + c)" },
                new() { Input = "a * b * c", Expected = "((a * b) * c)" },
                new() { Input = "a + b - c", Expected = "((a + b) - c)" },
                new() { Input = "a * b / c", Expected = "((a * b) / c)" },
                new() { Input = "a + b / c", Expected = "(a + (b / c))" },
                new() { Input = "a + b * c + d / e - f", Expected = "(((a + (b * c)) + (d / e)) - f)" },
                new() { Input = "a > b == c < b", Expected = "((a > b) == (c < b))" },
                new() { Input = "a + b; -c * c", Expected = "(a + b)((-c) * c)" },
                new() { Input = "a < b != c > b", Expected = "((a < b) != (c > b))" },
                new()
                {
                    Input    = "3 + 4 * 5 == 3 * 1 + 4 * 5",
                    Expected = "((3 + (4 * 5)) == ((3 * 1) + (4 * 5)))"
                },
                new() { Input = "true", Expected = "true" },
                new() { Input = "false", Expected = "false" },
                new() { Input = "3 > 5 == false", Expected = "((3 > 5) == false)" },
                new() { Input = "3 < 5 == true", Expected = "((3 < 5) == true)" },
                new() { Input = "!(true == true)", Expected = "(!(true == true))" },
                new() { Input = "a + add(b * c) + d", Expected = "((a + add((b * c))) + d)" },
                new()
                {
                    Input    = "add(a, b, 1, 2 * 3, 4 + 5, add(6, 7 * 8))",
                    Expected = "add(a, b, 1, (2 * 3), (4 + 5), add(6, (7 * 8)))"
                },
                new()
                {
                    Input    = "add(a + b + c * d / f + g)",
                    Expected = "add((((a + b) + ((c * d) / f)) + g))"
                },
                new()
                {
                    Input    = "a * [1, 2, 3, 4][b * c] * d",
                    Expected = "((a * ([1, 2, 3, 4][(b * c)])) * d)"
                },
                new()
                {
                    Input    = "add(a * b[2], b[1], 2 * [1,2][1])",
                    Expected = "add((a * (b[2])), (b[1]), (2 * ([1, 2][1])))"
                }
            };

            foreach (var operatorTest in tests)
            {
                var lexer   = new Lexer(operatorTest.Input);
                var parser  = new Parser(lexer);
                var program = parser.ParseCode();
                StaticTests.CheckParserErrors(parser);
                var actual = program.Str();
                Assert.AreEqual(operatorTest.Expected, actual);
            }
        }
    }
Пример #18
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);
        }
Пример #19
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);
        }
Пример #20
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);
        }
Пример #21
0
        public void HashLiteralWithExpressionParsingTest()
        {
            const string input   = "{'one': 0 + 1, 'two': 228 - 226, 'three': 45 / 15}";
            var          lexer   = new Lexer(input);
            var          parser  = new Parser(lexer);
            var          program = parser.ParseCode();

            StaticTests.CheckParserErrors(parser);

            Assert.AreEqual(nameof(ExpressionStatement), program.Statements.First().GetType().Name);

            var stmt = (ExpressionStatement)program.Statements.First();

            Assert.AreEqual(nameof(HashLiteral), stmt.Expression.GetType().Name);

            var hash = (HashLiteral)stmt.Expression;

            Assert.AreEqual(3, hash.Pairs.Count);

            var tests = new Dictionary <string, ExpressionTestDelegate>
            {
                {
                    "one",
                    expression =>
                    StaticTests.TestInfixExpression(expression, (IntegerLiteral)0, "+", (IntegerLiteral)1)
                },
                {
                    "two",
                    expression =>
                    StaticTests.TestInfixExpression(expression, (IntegerLiteral)228, "-", (IntegerLiteral)226)
                },
                {
                    "three",
                    expression =>
                    StaticTests.TestInfixExpression(expression, (IntegerLiteral)45, "/", (IntegerLiteral)15)
                }
            };

            foreach (var pairsKey in hash.Pairs.Keys)
            {
                var value = hash.Pairs[pairsKey];
                Assert.AreEqual(nameof(StringLiteral), pairsKey.GetType().Name);
                var literal = (StringLiteral)pairsKey;

                var keyExists = tests.TryGetValue(literal.Str(), out var testFunc);

                Assert.True(keyExists);

                testFunc(value);
            }
        }
Пример #22
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);
        }
Пример #23
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);
        }
Пример #24
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);
            }
        }
    }
Пример #25
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);
        }
Пример #26
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());
        }
Пример #27
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);
            }
        }
    }
Пример #28
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);
            }
        }
Пример #29
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);
            }
        }
Пример #30
0
        public void IdentifierExpressionTest()
        {
            const string input   = "fooBar;";
            var          lexer   = new Lexer(input);
            var          parser  = new Parser(lexer);
            var          program = parser.ParseCode();

            StaticTests.CheckParserErrors(parser);
            Assert.AreEqual(1, program.Statements.Count,
                            $"program should have 1 statement, got={program.Statements.Count}");

            var stmt = program.Statements.First() as ExpressionStatement;

            Assert.AreEqual("ExpressionStatement", stmt.GetType().Name,
                            $"first statement not of type 'ExpressionStatement', got={stmt.GetType().Name}");

            StaticTests.TestIdentifier(stmt.Expression, "fooBar");
        }