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); } } }
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); } } } }
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); } }
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); }
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); }
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); } }
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); } } }
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); } }
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()); } } } }
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()); }
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()}"); }
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); } } }
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); } }
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); }
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); } }
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); } }
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); } } }
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); }
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); }
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); }
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); } }
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); }
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); }
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); } } }
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); }
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()); }
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); } } }
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); } }
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); } }
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"); }