def test_simple_block_of_statements(self): '''Can parse a nested block of statements: `int x; { int y; x = 5; }` ''' given = iter([ Token('INT_TYPE', 'int'), Token('ID', 'x'), Token('SEMI', ';'), Token('LCURLY', '{'), Token('INT_TYPE', 'int'), Token('ID', 'y'), Token('SEMI', ';'), Token('ID', 'x'), Token('EQUAL', '='), Token('INTEGER', '5'), Token('SEMI', ';'), Token('RCURLY', '}'), ]) expected = ast.Block([ ast.Declaration('int', [ast.ID('x')]), ast.Block([ ast.Declaration('int', [ast.ID('y')]), ast.Assignment(ast.ID('x'), ast.Integer(5)) ]) ]) result = parser.parse(given) assert expected == result
def test_id_expr_error(self): '''No error with given program: `int ducks; float wildcats; ducks = 100; wildcats = 200 % ducks;`''' given = ast.Block([ ast.Declaration('int', [ast.ID('ducks')]), ast.Declaration('float', [ast.ID('wildcats')]), ast.Assignment(ast.ID('ducks'), ast.Integer(100)), ast.Assignment(ast.ID('wildcats'), ast.BinOp('%', ast.Integer(200), ast.ID('ducks'))) ]) report = typechecker.typecheck(given) expected_errors = [ TypecheckerError( ast.Assignment( ast.ID('wildcats'), ast.BinOp('%', ast.Integer(200), ast.ID('ducks')))) ] for (r, e) in zip_longest(report.get_errors(), expected_errors): assert r == e
def test_simple_program_correct(self): '''Can typecheck a simple program: `int wildcat, animals[2]; float duck; wildcat = 1; duck = 1.0; if(duck) { animals[0] = wildcat; animals[1] = 2; } else { animals[0] = 1; } duck = (duck + 2.5) * 33.0 / 2.0; ` ''' given = ast.Block([ ast.Declaration('int', [ ast.ID('wildcat'), ast.ArrayRef(ast.ID('animals'), ast.Integer(2)) ]), ast.Declaration('float', [ast.ID('duck')]), ast.Assignment(ast.ID('wildcat'), ast.Integer(1)), ast.Assignment(ast.ID('duck'), ast.Float(1.0)), ast.IfStatement( ast.ID('duck'), ast.Block([ ast.Assignment( ast.ArrayRef(ast.ID('animals'), ast.Integer(0)), ast.ID('wildcat')), ast.Assignment( ast.ArrayRef(ast.ID('animals'), ast.Integer(1)), ast.Integer(2)) ]), ast.Block([ ast.Assignment( ast.ArrayRef(ast.ID('animals'), ast.Integer(0)), ast.Integer(1)) ])), ast.Assignment( ast.ID('duck'), ast.BinOp( '/', ast.BinOp('*', ast.BinOp('+', ast.ID('duck'), ast.Float(2.5)), ast.Float(33.0)), ast.Float(2.0))) ]) report = typechecker.typecheck(given) expected_errors = [] for (r, e) in zip_longest(report.get_errors(), expected_errors): assert r == e
def test_compiler_parse(self): '''Can parse a simple program:''' given = ''' float duck, goose, birds[2]; int wildcat; duck = 1.0; goose = -1; wildcat = 1; birds[0] = duck; if (duck) { birds[1] = goose; } else { birds[1] = wildcat; } ''' result = compiler.parse(given) expected = ast.Block([ ast.Declaration('float', [ ast.ID('duck'), ast.ID('goose'), ast.ArrayRef(ast.ID('birds'), ast.Integer(2)) ]), ast.Declaration('int', [ast.ID('wildcat')]), ast.Assignment(ast.ID('duck'), ast.Float(1.0)), ast.Assignment(ast.ID('goose'), ast.UnaryOp('-', ast.Integer(1))), ast.Assignment(ast.ID('wildcat'), ast.Integer(1)), ast.Assignment(ast.ArrayRef(ast.ID('birds'), ast.Integer(0)), ast.ID('duck')), ast.IfStatement( ast.ID('duck'), ast.Block([ ast.Assignment( ast.ArrayRef(ast.ID('birds'), ast.Integer(1)), ast.ID('goose')) ]), ast.Block([ ast.Assignment( ast.ArrayRef(ast.ID('birds'), ast.Integer(1)), ast.ID('wildcat')) ])), ]) assert result == expected
def test_if_statement_error(self): '''An error with given program: `int x; if (x) { x = 1.0; } else { x = 0; }`''' given = ast.Block([ ast.Declaration('int', [ast.ID('x')]), ast.IfStatement( ast.ID('x'), ast.Block([ast.Assignment(ast.ID('x'), ast.Float(1.0))]), ast.Block([ast.Assignment(ast.ID('x'), ast.Integer(0))]), ) ]) report = typechecker.typecheck(given) expected_errors = [ TypecheckerError(ast.Assignment(ast.ID('x'), ast.Float(1.0))) ] for (r, e) in zip_longest(report.get_errors(), expected_errors): assert r == e
def test_simple_declaration(self): '''Can parse a simple declaration: `int a;`''' given = iter([ Token('INT_TYPE', 'int'), Token('ID', 'a'), Token('SEMI', ';') ]) expected = ast.Block([ ast.Declaration('int', [ast.ID('a')]) ]) result = parser.parse(given) assert expected == result
def test_simple_correct(self): '''No errors with given program: `int cowbell; cowbell = 2000;`''' given = ast.Block([ ast.Declaration('int', [ast.ID('cowbell')]), ast.Assignment(ast.ID('cowbell'), ast.Integer(2000)) ]) report = typechecker.typecheck(given) expected_errors = [] for (r, e) in zip_longest(report.get_errors(), expected_errors): assert r == e
def test_binop_correct(self): '''An error with given program: `int more_cowbell; more_cowbell = 2000 + 1;`''' given = ast.Block([ ast.Declaration('int', [ast.ID('more_cowbell')]), ast.Assignment(ast.ID('more_cowbell'), ast.BinOp('+', ast.Integer(2000), ast.Integer(1))) ]) report = typechecker.typecheck(given) expected_errors = [] for (r, e) in zip_longest(report.get_errors(), expected_errors): assert r == e
def test_arrayref_expr_correct(self): '''No error with given program: `int x[3]; x[0] = 1;`''' given = ast.Block([ ast.Declaration('int', [ast.ArrayRef(ast.ID('x'), ast.Integer(3))]), ast.Assignment(ast.ArrayRef(ast.ID('x'), ast.Integer(0)), ast.Integer(1)) ]) report = typechecker.typecheck(given) expected_errors = [] for (r, e) in zip_longest(report.get_errors(), expected_errors): assert r == e
def test_float_declaration(self): '''Can parse float declaration: `float duck;`''' given = iter([ Token('FLOAT_TYPE', 'float'), Token('ID', 'duck'), Token('SEMI', ';') ]) expected = ast.Block([ ast.Declaration( 'float', [ast.ID('duck')] ) ]) result = parser.parse(given) assert expected == result
def test_simple_error(self): '''An error with given program: `int cowbell; cowbell = 2000.0;`''' given = ast.Block([ ast.Declaration('int', [ast.ID('cowbell')]), ast.Assignment(ast.ID('cowbell'), ast.Float(2000.0)) ]) report = typechecker.typecheck(given) expected_errors = [ TypecheckerError( ast.Assignment(ast.ID('cowbell'), ast.Float(2000.0))) ] for (r, e) in zip_longest(report.get_errors(), expected_errors): assert r == e
def test_unary_op_error(self): '''An error with given program: `int negative_cowbell; negative_cowbell = -2000.00;`''' given = ast.Block([ ast.Declaration('int', [ast.ID('negative_cowbell')]), ast.Assignment(ast.ID('negative_cowbell'), ast.UnaryOp('-', ast.Float(2000.00))) ]) report = typechecker.typecheck(given) expected_errors = [ TypecheckerError( ast.Assignment(ast.ID('negative_cowbell'), ast.UnaryOp('-', ast.Float(2000.00)))) ] for (r, e) in zip_longest(report.get_errors(), expected_errors): assert r == e
def test_multiple_declaration(self): '''Can parse multiple declaration: `int ducks, and, wildcats;`''' given = iter([ Token('INT_TYPE', 'int'), Token('ID', 'ducks'), Token('COMMA', ','), Token('ID', 'and'), Token('COMMA', ','), Token('ID', 'wildcats'), Token('SEMI', ';') ]) expected = ast.Block([ ast.Declaration( 'int', [ast.ID('ducks'), ast.ID('and'), ast.ID('wildcats')] ) ]) result = parser.parse(given) assert expected == result
def test_simple_program(self): '''Can parse a simple program `int x[3], duck, goose, wildcat; duck = 1; goose = 2; x[0] = duck; x[duck] = goose; if (duck + x[duck]) { wildcat = duck; } else { wildcat = goose; } x[2] = wildcat;` ''' given = iter([ Token('INT_TYPE', 'int'), Token('ID', 'x'), Token('LBRACE', '['), Token('INTEGER', '3'), Token('RBRACE', ']'), Token('COMMA', ','), Token('ID', 'duck'), Token('COMMA', ','), Token('ID', 'goose'), Token('COMMA', ','), Token('ID', 'wildcat'), Token('SEMI', ';'), Token('ID', 'duck'), Token('EQUAL', '='), Token('INTEGER', '1'), Token('SEMI', ';'), Token('ID', 'goose'), Token('EQUAL', '='), Token('INTEGER', '2'), Token('SEMI', ';'), Token('ID', 'x'), Token('LBRACE', '['), Token('INTEGER', '0'), Token('RBRACE', ']'), Token('EQUAL', '='), Token('ID', 'duck'), Token('SEMI', ';'), Token('ID', 'x'), Token('LBRACE', '['), Token('ID', 'duck'), Token('RBRACE', ']'), Token('EQUAL', '='), Token('ID', 'goose'), Token('SEMI', ';'), Token('IF', 'if'), Token('LPAREN', '('), Token('ID', 'duck'), Token('PLUS', '+'), Token('ID', 'x'), Token('LBRACE', '['), Token('ID', 'duck'), Token('RBRACE', ']'), Token('RPAREN', ')'), Token('LCURLY', '{'), Token('ID', 'wildcat'), Token('EQUAL', '='), Token('ID', 'duck'), Token('SEMI', ';'), Token('RCURLY', '}'), Token('ELSE', 'else'), Token('LCURLY', '{'), Token('ID', 'wildcat'), Token('EQUAL', '='), Token('ID', 'goose'), Token('SEMI', ';'), Token('RCURLY', '}'), Token('ID', 'x'), Token('LBRACE', '['), Token('INTEGER', '2'), Token('RBRACE', ']'), Token('EQUAL', '='), Token('ID', 'wildcat'), Token('SEMI', ';') ]) expected = ast.Block([ ast.Declaration( 'int', [ast.ArrayRef(ast.ID('x'), ast.Integer(3)), ast.ID('duck'), ast.ID('goose'), ast.ID('wildcat')] ), ast.Assignment(ast.ID('duck'), ast.Integer(1)), ast.Assignment(ast.ID('goose'), ast.Integer(2)), ast.Assignment(ast.ArrayRef(ast.ID('x'), ast.Integer(0)), ast.ID('duck')), ast.Assignment(ast.ArrayRef(ast.ID('x'), ast.ID('duck')), ast.ID('goose')), ast.IfStatement( ast.BinOp('+', ast.ID('duck'), ast.ArrayRef(ast.ID('x'), ast.ID('duck'))), ast.Block([ ast.Assignment(ast.ID('wildcat'), ast.ID('duck')) ]), ast.Block([ ast.Assignment(ast.ID('wildcat'), ast.ID('goose')) ]) ), ast.Assignment(ast.ArrayRef(ast.ID('x'), ast.Integer(2)), ast.ID('wildcat')), ]) result = parser.parse(given) assert expected == result
def statement_declaration(s): return ast.Declaration( s[0], [s[1]] if isinstance(s[1], ast.AstNode) else s[1])