Esempio n. 1
0
def test_function_parameter_parsing():
    class Test(NamedTuple):
        input: str
        expected_params: List[str]

    tests = [
        Test('fn() {};', []),
        Test('fn(x) {};', ['x']),
        Test('fn(x, y, z) {};', ['x', 'y', 'z']),
    ]

    for tt in tests:
        l = lexer.Lexer(tt.input)
        p = parser.Parser(l)
        program = p.parse_program()
        check_parser_errors(p)

        stmt = program.statements[0]
        function = stmt.expression

        assert len(function.parameters) == len(tt.expected_params), \
            'length parameters wrong. want {}, got={}'.format(len(tt.expected_params), len(function.parameters))

        for i, ident in enumerate(tt.expected_params):
            _test_literal_expression(function.parameters[i], ident)
Esempio n. 2
0
def test_function_literal_parsing():
    input = 'fn(x, y) { x + y; }'

    l = lexer.Lexer(input)
    p = parser.Parser(l)
    program = p.parse_program()
    check_parser_errors(p)

    assert len(program.statements) == 1, \
        'program.statements does not contain {} statements. got={}'.format(1, len(program.statements))

    stmt = program.statements[0]
    assert issubclass(stmt.__class__, ast.ExpressionStatement), \
        'program.statements[0] is not ast.ExpressionStatement. got={}'.format(stmt.__class__.__name__)

    function = stmt.expression
    assert issubclass(function.__class__, ast.FunctionLiteral), \
        'stmt.expression is not ast.FunctionLiteral. got={}'.format(function.__class__.__name__)

    assert len(function.parameters) == 2, \
        'function literal parameters wrong. want 2, got={}'.format(len(function.parameters))

    _test_literal_expression(function.parameters[0], 'x')
    _test_literal_expression(function.parameters[1], 'y')

    assert len(function.body.statements) == 1, \
        'function.body.statements has not 1 statements. got={}'.format(len(function.body.statements))

    body_stmt = function.body.statements[0]
    assert issubclass(body_stmt.__class__, ast.ExpressionStatement), \
        'function body stmt is not ast.ExpressionStatement. got={}'.format(body_stmt.__class__.__name__)

    _test_infix_expression(body_stmt.expression, 'x', '+', 'y')
Esempio n. 3
0
def test_return_statements():
    class Test(NamedTuple):
        input: str
        expected_value: Any

    tests = [
        Test('return 5;', 5),
        Test('return true;', True),
        Test('return foobar;', 'foobar'),
    ]

    for tt in tests:
        l = lexer.Lexer(tt.input)
        p = parser.Parser(l)
        program = p.parse_program()
        check_parser_errors(p)

        assert len(program.statements) == 1, \
            'program.statements does not contain 1 statements. got={}'.format(len(program.statements))

        return_stmt = program.statements[0]
        assert issubclass(return_stmt.__class__, ast.ReturnStatement), \
            'stmt not ast.ReturnStatement. got={}'.format(return_stmt.__class__.__name__)
        assert return_stmt.token_literal() == 'return', \
            "return_stmt.token_literal not 'return', got {}".format(return_stmt.token_literal())
        if _test_literal_expression(return_stmt.return_value,
                                    tt.expected_value):
            return
Esempio n. 4
0
def test_if_expression():
    input = 'if (x < y) { x }'

    l = lexer.Lexer(input)
    p = parser.Parser(l)
    program = p.parse_program()
    check_parser_errors(p)

    assert len(program.statements) == 1, \
        'program.statements does not contain {} statements. got={}'.format(1, len(program.statements))

    stmt = program.statements[0]
    assert issubclass(stmt.__class__, ast.ExpressionStatement), \
        'program.statements[0] is not ast.ExpressionStatement. got={}'.format(stmt.__class__.__name__)

    exp = stmt.expression
    assert issubclass(exp.__class__, ast.IfExpression), \
        'stmt.expression is not ast.IfExpression. got={}'.format(exp.__class__.__name__)

    if not _test_infix_expression(exp.condition, 'x', '<', 'y'):
        return

    assert len(exp.consequence.statements) == 1, \
        'consequence is not 1 statements. got={}'.format(len(exp.consequence.statements))

    consequnce = exp.consequence.statements[0]
    assert issubclass(consequnce.__class__, ast.ExpressionStatement), \
        'statements[0] is not ast.ExpressionStatement. got={}'.format(consequnce.__class__.__name__)

    if not _test_identifier(consequnce.expression, 'x'):
        return

    assert exp.alternative is None, 'exp.alternative was not None. got={}'.format(
        exp.alternative)
Esempio n. 5
0
def test_call_expression_parsing():
    input = 'add(1, 2 * 3, 4 + 5);'

    l = lexer.Lexer(input)
    p = parser.Parser(l)
    program = p.parse_program()
    check_parser_errors(p)

    assert len(program.statements) == 1, \
        'program.statements does not contain {} statements. got={}'.format(1, len(program.statements))

    stmt = program.statements[0]
    assert issubclass(stmt.__class__, ast.ExpressionStatement), \
        'program.statements[0] is not ast.ExpressionStatement. got={}'.format(stmt.__class__.__name__)

    exp = stmt.expression
    assert issubclass(exp.__class__, ast.CallExpression), \
        'stmt.expression is not ast.CallExpression. got={}'.format(exp.__class__.__name__)

    if not _test_identifier(exp.function, 'add'):
        return

    assert len(exp.arguments) == 3, 'wrong length of arguments. got={}'.format(
        len(exp.arguments))

    _test_literal_expression(exp.arguments[0], 1)
    _test_infix_expression(exp.arguments[1], 2, '*', 3)
    _test_infix_expression(exp.arguments[2], 4, '+', 5)
Esempio n. 6
0
def test_let_statements():
    class Test(NamedTuple):
        input: str
        expected_identifier: str
        expected_value: Any

    tests = [
        Test('let x = 5;', 'x', 5),
        Test('let y = true;', 'y', True),
        Test('let foobar = y;', 'foobar', 'y')
    ]

    for tt in tests:
        l = lexer.Lexer(tt.input)
        p = parser.Parser(l)
        program = p.parse_program()
        check_parser_errors(p)

        assert len(program.statements) == 1, \
            'program.statements does not contain 1 statements. got={}'.format(len(program.statements))

        stmt = program.statements[0]
        if not _test_let_statement(stmt, tt.expected_identifier):
            return

        val = stmt.value
        if not _test_literal_expression(val, tt.expected_value):
            return
Esempio n. 7
0
def _test_eval(input: str) -> object.Object:
    l = lexer.Lexer(input)
    p = parser.Parser(l)
    program = p.parse_program()
    env = object.Environment()

    return evaluator.eval(program, env)
Esempio n. 8
0
def test_parsing_hash_literals_integer_keys():
    input = '{1: 1, 2: 2, 3: 3}'

    l = lexer.Lexer(input)
    p = parser.Parser(l)
    program = p.parse_program()
    check_parser_errors(p)

    stmt = program.statements[0]
    hash = stmt.expression
    assert issubclass(hash.__class__, ast.HashLiteral), \
        'exp not ast.HashLiteral. got={}'.format(hash.__class__.__name__)

    expected = {
        '1': 1,
        '2': 2,
        '3': 3,
    }

    assert len(hash.pairs) == len(expected), \
        'hash.Pairs has wrong length. got={}'.format(len(hash.pairs))

    for key, value in hash.pairs.items():
        assert issubclass(key.__class__, ast.IntegerLiteral), \
            'key is not ast.IntegerLiteral. got={}'.format(key.__class__.__name__)

        assert key.string() in expected
        expected_value = expected[key.string()]
        _test_integer_literal(value, expected_value)
Esempio n. 9
0
def test_boolean_expression():
    class Test(NamedTuple):
        input: str
        expected_boolean: bool

    tests = [
        Test('true;', True),
        Test('false;', False),
    ]

    for tt in tests:
        l = lexer.Lexer(tt.input)
        p = parser.Parser(l)
        program = p.parse_program()
        check_parser_errors(p)

        assert len(program.statements) == 1, \
            'program has not enough statements. got={}'.format(len(program.statements))

        stmt = program.statements[0]
        assert issubclass(stmt.__class__, ast.ExpressionStatement), \
            'program.statements[0] is not ast.ExpressionStatement. got={}'.format(stmt.__class__.__name__)

        boolean = stmt.expression
        assert issubclass(boolean.__class__, ast.Boolean), \
            'exp not ast.Boolean. got={}'.format(boolean.__class__.__name__)
        assert boolean.value == tt.expected_boolean, \
            'boolean.value not {}. got={}'.format(tt.expected_boolean, boolean.value)
    def test_operator_precedence_parsing(self):
        tests = [
            ("-a * b", "((-a) * b)"), ("!-a", "(!(-a))"),
            ("a + b + c", "((a + b) + c)"), ("a + b - c", "((a + b) - c)"),
            ("a * b * c", "((a * b) * c)"), ("a * b / c", "((a * b) / c)"),
            ("a + b / c", "(a + (b / c))"),
            ("a + b * c + d / e - f", "(((a + (b * c)) + (d / e)) - f)"),
            ("3 + 4; -5 * 5", "(3 + 4)((-5) * 5)"),
            ("5 > 4 == 3 < 4", "((5 > 4) == (3 < 4))"),
            ("5 < 4 != 3 > 4", "((5 < 4) != (3 > 4))"),
            ("3 + 4 * 5 == 3 * 1 + 4 * 5",
             "((3 + (4 * 5)) == ((3 * 1) + (4 * 5)))"), ("true", "true"),
            ("false", "false"), ("3 > 5 == false", "((3 > 5) == false)"),
            ("3 < 5 == true", "((3 < 5) == true)"),
            ("1 + (2 + 3) + 4", "((1 + (2 + 3)) + 4)"),
            ("(5 + 5) * 2", "((5 + 5) * 2)"), ("2 / (5 + 5)", "(2 / (5 + 5))"),
            ("-(5 + 5)", "(-(5 + 5))"),
            ("!(true == true)", "(!(true == true))"),
            ("a + add(b * c) + d", "((a + add((b * c))) + d)"),
            ("add(a, b, 1, 2 * 3, 4 + 5, add(6, 7 * 8))",
             "add(a, b, 1, (2 * 3), (4 + 5), add(6, (7 * 8)))"),
            ("add(a + b + c * d / f + g)",
             "add((((a + b) + ((c * d) / f)) + g))")
        ]
        for input, expected in tests:
            with self.subTest(input):
                lex = lexer.Lexer(input)
                psr = parser.Parser(lex)
                program = psr.parse()
                self.check_parser_errors(psr)

                self.assertEqual(str(program), expected)
    def test_if_expression(self):
        tests = [("if (x < y) { x }", ("x", "<", "y"), "x", None),
                 ("if (x < y) { x } else { y }", ("x", "<", "y"), "x", "y")]

        for input, cond, consequence, alternative in tests:
            with self.subTest(input):
                lex = lexer.Lexer(input)
                psr = parser.Parser(lex)
                program = psr.parse()
                self.check_parser_errors(psr)

                self.assertEqual(len(program.statements), 1)
                self.assertIsInstance(program.statements[0],
                                      ast.ExpressionStatement)
                stmt = cast(ast.ExpressionStatement, program.statements[0])

                self.assertIsInstance(stmt.expression, ast.IfExpression)
                ifexp = cast(ast.IfExpression, stmt.expression)
                self.assert_infix_expression(ifexp.condition, *cond)

                self.assertEqual(len(ifexp.consequence.statements), 1)
                self.assertIsInstance(ifexp.consequence.statements[0],
                                      ast.ExpressionStatement)
                cnsq = cast(ast.ExpressionStatement,
                            ifexp.consequence.statements[0])
                self.assert_identifier(cnsq.expression, consequence)

                if alternative:
                    self.assertEqual(len(ifexp.alternative.statements), 1)
                    self.assertIsInstance(ifexp.alternative.statements[0],
                                          ast.ExpressionStatement)
                    alt = cast(ast.ExpressionStatement,
                               ifexp.alternative.statements[0])
                    self.assert_identifier(alt.expression, alternative)
Esempio n. 12
0
def test_parsing_hash_literals_integer_keys():
    input = '{"one": 0 + 1, "two": 10 - 8, "three": 15 / 5}'

    l = lexer.Lexer(input)
    p = parser.Parser(l)
    program = p.parse_program()
    check_parser_errors(p)

    stmt = program.statements[0]
    hash = stmt.expression
    assert issubclass(hash.__class__, ast.HashLiteral), \
        'exp not ast.HashLiteral. got={}'.format(hash.__class__.__name__)

    assert len(hash.pairs) == 3, \
        'hash.Pairs has wrong length. got={}'.format(len(hash.pairs))

    tests = {
        'one': lambda e: _test_infix_expression(e, 0, '+', 1),
        'two': lambda e: _test_infix_expression(e, 10, '-', 8),
        'three': lambda e: _test_infix_expression(e, 15, '/', 5),
    }

    for key, value in hash.pairs.items():
        assert issubclass(key.__class__, ast.StringLiteral), \
            'key is not ast.StringLiteral. got={}'.format(key.__class__.__name__)

        assert key.string() in tests, \
            "No test function for key '{}' found".format(key.string())
        test_func = tests[key.string()]

        test_func(value)
Esempio n. 13
0
def test_parsing_prefix_expression():
    class PrefixTest(NamedTuple):
        input: str
        operator: str
        value: Any

    prefix_tests = [
        PrefixTest('!5;', '!', 5),
        PrefixTest('-15;', '-', 15),
        PrefixTest('!true', '!', True),
        PrefixTest('!false', '!', False),
    ]

    for tt in prefix_tests:
        l = lexer.Lexer(tt.input)
        p = parser.Parser(l)
        program = p.parse_program()
        check_parser_errors(p)

        assert len(program.statements) == 1, \
            'program.statements does not contain {} statements. got={}'.format(1, len(program.statements))

        stmt = program.statements[0]
        assert issubclass(stmt.__class__, ast.ExpressionStatement), \
            'program statements[0] is not ast.ExpressionStatement. got={}'.format(stmt.__class__.__name__)

        exp = stmt.expression
        assert issubclass(exp.__class__, ast.PrefixExpression), \
            'stmt is not ast.PrefixExpression. got={}'.format(stmt.expression.__class__.__name__)
        assert exp.operator == tt.operator, "exp.operator is not '{}'. got={}".format(
            tt.operator, exp.operator)
        assert _test_literal_expression(exp.right, tt.value)
    def test_identifier_expression(self):
        input = "foobar;"

        lex = lexer.Lexer(input)
        psr = parser.Parser(lex)
        program = psr.parse()
        self.check_parser_errors(psr)

        self.assertEqual(len(program.statements), 1)
        self.assertIsInstance(program.statements[0], ast.ExpressionStatement)
        stmt = cast(ast.ExpressionStatement, program.statements[0])
        self.assert_identifier(stmt.expression, "foobar")
Esempio n. 15
0
def test_string_literal_expression():
    input = '"hello world";'

    l = lexer.Lexer(input)
    p = parser.Parser(l)
    program = p.parse_program()
    check_parser_errors(p)

    stmt = program.statements[0]
    literal = stmt.expression
    assert issubclass(literal.__class__, ast.StringLiteral), \
        'exp not ast.StringLiteral. got={}'.format(stmt.expression.__class__.__name__)
    assert literal.value == 'hello world', \
        "literal.value not '{}'. got='{}'".format('hello world', literal.value)
Esempio n. 16
0
def test_parsing_empty_hash_literal():
    input = '{}'

    l = lexer.Lexer(input)
    p = parser.Parser(l)
    program = p.parse_program()
    check_parser_errors(p)

    stmt = program.statements[0]
    hash = stmt.expression
    assert issubclass(hash.__class__, ast.HashLiteral), \
        'exp not ast.HashLiteral. got={}'.format(hash.__class__.__name__)

    assert len(hash.pairs) == 0, \
        'hash.Pairs has wrong length. got={}'.format(len(hash.pairs))
    def test_integer_literal(self):
        input = "5;"

        lex = lexer.Lexer(input)
        psr = parser.Parser(lex)
        program = psr.parse()
        self.check_parser_errors(psr)

        self.assertEqual(len(program.statements), 1)
        self.assertIsInstance(program.statements[0], ast.ExpressionStatement)
        stmt = cast(ast.ExpressionStatement, program.statements[0])
        self.assertIsInstance(stmt.expression, ast.IntegerLiteral)
        ident = cast(ast.IntegerLiteral, stmt.expression)
        self.assertEqual(ident.value, 5)
        self.assertEqual(ident.token_literal(), "5")
Esempio n. 18
0
def test_parsing_empty_array_literals():
    input = '[]'

    l = lexer.Lexer(input)
    p = parser.Parser(l)
    program = p.parse_program()
    check_parser_errors(p)

    stmt = program.statements[0]
    array = stmt.expression
    assert issubclass(array.__class__, ast.ArrayLiteral), \
        'exp not ast.ArrayLiteral. got={}'.format(array.__class__.__name__)

    assert len(array.elements) == 0, \
        'len(array.Elements) not 0. got={}'.format(len(array.elements))
Esempio n. 19
0
def test_parsing_index_expressions():
    input = 'myArray[1 + 1]'

    l = lexer.Lexer(input)
    p = parser.Parser(l)
    program = p.parse_program()
    check_parser_errors(p)

    stmt = program.statements[0]
    index_exp = stmt.expression
    assert issubclass(index_exp.__class__, ast.IndexExpression), \
        'exp not ast.IndexExpression. got={}'.format(index_exp.__class__.__name__)

    assert _test_identifier(index_exp.left, 'myArray')

    assert _test_infix_expression(index_exp.index, 1, '+', 1)
    def test_return_statements(self):
        tests = [("return 5;", 5), ("return true;", True),
                 ("return foobar;", "foobar")]
        for input, expected_value in tests:
            with self.subTest(input):
                lex = lexer.Lexer(input)
                psr = parser.Parser(lex)
                program = psr.parse()
                self.check_parser_errors(psr)

                self.assertEqual(len(program.statements), 1)
                stmt = program.statements[0]
                self.assertIsInstance(stmt, ast.ReturnStatement)
                self.assertEqual(stmt.token_literal(), "return")
                ret_stmt = cast(ast.ReturnStatement, stmt)
                self.assert_literal_expression(ret_stmt.return_value,
                                               expected_value)
    def test_boolean_expression(self):
        tests = [("true;", "true", True), ("false;", "false", False)]

        for input, literal, value in tests:
            with self.subTest(input):
                lex = lexer.Lexer(input)
                psr = parser.Parser(lex)
                program = psr.parse()
                self.check_parser_errors(psr)

                self.assertEqual(len(program.statements), 1)
                self.assertIsInstance(program.statements[0],
                                      ast.ExpressionStatement)
                stmt = cast(ast.ExpressionStatement, program.statements[0])
                self.assertIsInstance(stmt.expression, ast.Boolean)
                boolean = cast(ast.Boolean, stmt.expression)
                self.assertEqual(boolean.value, value)
                self.assertEqual(boolean.token_literal(), literal)
Esempio n. 22
0
def test_parsing_array_literals():
    input = '[1, 2 * 2, 3 + 3]'

    l = lexer.Lexer(input)
    p = parser.Parser(l)
    program = p.parse_program()
    check_parser_errors(p)

    stmt = program.statements[0]
    array = stmt.expression
    assert issubclass(array.__class__, ast.ArrayLiteral), \
        'exp not ast.ArrayLiteral. got={}'.format(array.__class__.__name__)

    assert len(array.elements) == 3, \
        'len(array.Elements) not 3. got={}'.format(len(array.elements))

    _test_integer_literal(array.elements[0], 1)
    _test_infix_expression(array.elements[1], 2, '*', 2)
    _test_infix_expression(array.elements[2], 3, '+', 3)
Esempio n. 23
0
def start():
    env = object.Environment()

    while True:
        line = input(PROMPT)
        if not line:
            return

        l = lexer.Lexer(line)
        p = parser.Parser(l)

        program = p.parse_program()
        if len(p.errors) != 0:
            print_parse_errors(p.errors)
            continue

        evaluated = evaluator.eval(program, env)
        if evaluated is not None:
            print(evaluated.inspect())
    def test_let_statements(self):
        tests = [
            ("let x = 5;", "x", 5),
            ("let y = true;", "y", True),
            ("let foobar = y;", "foobar", "y"),
        ]
        for input, expected_ident, expected_value in tests:
            with self.subTest(input):
                lex = lexer.Lexer(input)
                psr = parser.Parser(lex)
                program = psr.parse()
                self.check_parser_errors(psr)

                self.assertEqual(len(program.statements), 1)
                stmt = program.statements[0]
                self.assertEqual(stmt.token_literal(), "let")
                self.assertIsInstance(stmt, ast.LetStatement)
                let_stmt = cast(ast.LetStatement, stmt)
                self.assert_identifier(let_stmt.name, expected_ident)
                self.assert_literal_expression(let_stmt.value, expected_value)
Esempio n. 25
0
def test_identifier_expression():
    input = 'foobar;'

    l = lexer.Lexer(input)
    p = parser.Parser(l)
    program = p.parse_program()
    check_parser_errors(p)

    assert len(program.statements) == 1, \
        'program has not enough statements. got={}'.format(len(program.statements))

    stmt = program.statements[0]
    assert issubclass(stmt.__class__, ast.ExpressionStatement), \
        'program statements[0] is not ast.ExpressionStatement. got={}'.format(stmt.__class__.__name__)

    ident = stmt.expression
    assert ident.value == 'foobar', 'ident.value not {}. got={}'.format(
        'foobar', ident.value)
    assert ident.token_literal() == 'foobar', \
        'ident.token_literal not {}. got={}'.format('foobar', ident.token_literal())
    def test_call_expression_parsing(self):
        input = "add(1, 2 * 3, 4 + 5)"

        lex = lexer.Lexer(input)
        psr = parser.Parser(lex)
        program = psr.parse()
        self.check_parser_errors(psr)

        self.assertEqual(len(program.statements), 1)
        self.assertIsInstance(program.statements[0], ast.ExpressionStatement)
        stmt = cast(ast.ExpressionStatement, program.statements[0])
        self.assertIsInstance(stmt.expression, ast.CallExpression)
        call = cast(ast.CallExpression, stmt.expression)

        self.assert_identifier(call.function, "add")

        self.assertEqual(len(call.arguments), 3)

        self.assert_literal_expression(call.arguments[0], 1)
        self.assert_infix_expression(call.arguments[1], 2, "*", 3)
        self.assert_infix_expression(call.arguments[2], 4, "+", 5)
    def test_function_parameter_parsing(self):
        tests = [("fn() {}", []), ("fn(x) {}", ["x"]),
                 ("fn(x, y, z) {}", ["x", "y", "z"])]
        for input, expectedparmas in tests:
            self.subTest(input)

            lex = lexer.Lexer(input)
            psr = parser.Parser(lex)
            program = psr.parse()
            self.check_parser_errors(psr)

            self.assertEqual(len(program.statements), 1)
            self.assertIsInstance(program.statements[0],
                                  ast.ExpressionStatement)
            stmt = cast(ast.ExpressionStatement, program.statements[0])
            self.assertIsInstance(stmt.expression, ast.FunctionLiteral)
            func = cast(ast.FunctionLiteral, stmt.expression)

            self.assertEqual(len(func.parameters), len(expectedparmas))
            for param, expectedparam in zip(func.parameters, expectedparmas):
                self.assert_literal_expression(param, expectedparam)
    def test_parse_infix_expression(self):
        infixTests = [("5 + 5;", 5, "+", 5), ("5 - 5;", 5, "-", 5),
                      ("5 * 5;", 5, "*", 5), ("5 / 5;", 5, "/", 5),
                      ("5 > 5;", 5, ">", 5), ("5 < 5;", 5, "<", 5),
                      ("5 == 5;", 5, "==", 5), ("5 != 5;", 5, "!=", 5),
                      ("true == true;", True, "==", True),
                      ("true != false;", True, "!=", False),
                      ("false == false;", False, "==", False)]
        for input, left, operator, right in infixTests:
            with self.subTest(input):
                lex = lexer.Lexer(input)
                psr = parser.Parser(lex)
                program = psr.parse()
                self.check_parser_errors(psr)

                self.assertEqual(len(program.statements), 1)
                self.assertIsInstance(program.statements[0],
                                      ast.ExpressionStatement)
                stmt = cast(ast.ExpressionStatement, program.statements[0])
                self.assert_infix_expression(stmt.expression, left, operator,
                                             right)
    def test_parse_prefix_expression(self):
        prefixTests = [
            ("!5;", "!", 5),
            ("-15;", "-", 15),
            ("!true;", "!", True),
            ("!false;", "!", False),
        ]
        for input, operator, value in prefixTests:
            with self.subTest(input):
                lex = lexer.Lexer(input)
                psr = parser.Parser(lex)
                program = psr.parse()
                self.check_parser_errors(psr)

                self.assertEqual(len(program.statements), 1)
                self.assertIsInstance(program.statements[0],
                                      ast.ExpressionStatement)
                stmt = cast(ast.ExpressionStatement, program.statements[0])
                self.assertIsInstance(stmt.expression, ast.PrefixExpression)
                exp = cast(ast.PrefixExpression, stmt.expression)
                self.assertEqual(exp.operator, operator)
                self.assert_literal_expression(exp.right, value)
    def test_function_literal_parsing(self):
        input = "fn(x, y) { x + y; }"

        lex = lexer.Lexer(input)
        psr = parser.Parser(lex)
        program = psr.parse()
        self.check_parser_errors(psr)

        self.assertEqual(len(program.statements), 1)
        self.assertIsInstance(program.statements[0], ast.ExpressionStatement)
        stmt = cast(ast.ExpressionStatement, program.statements[0])

        self.assertIsInstance(stmt.expression, ast.FunctionLiteral)
        func = cast(ast.FunctionLiteral, stmt.expression)
        self.assertEqual(len(func.parameters), 2)
        self.assert_literal_expression(func.parameters[0], "x")
        self.assert_literal_expression(func.parameters[1], "y")

        self.assertEqual(len(func.body.statements), 1)
        self.assertIsInstance(func.body.statements[0], ast.ExpressionStatement)
        body = cast(ast.ExpressionStatement, func.body.statements[0])
        self.assert_infix_expression(body.expression, "x", "+", "y")