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_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_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 expr_leaf(s): if isinstance(s[0], ast.AstNode): return s[0] else: handlers = { 'INTEGER': lambda t: ast.Integer(int(t.getstr())), 'FLOAT': lambda t: ast.Float(float(t.getstr())), } default_handler = lambda t: t # noqa return handlers.get(s[0].gettokentype(), default_handler)(s[0])
def test_binop_error(self): '''An error with given program: `int more_cowbell; more_cowbell = 2000.0 + 1;`''' given = ast.Block([ ast.Declaration('int', [ast.ID('more_cowbell')]), ast.Assignment(ast.ID('more_cowbell'), ast.BinOp('+', ast.Float(2000.0), ast.Integer(1))) ]) report = typechecker.typecheck(given) expected_errors = [ TypecheckerError( ast.Assignment( ast.ID('more_cowbell'), ast.BinOp('+', ast.Float(2000.0), ast.Integer(1)))) ] for (r, e) in zip_longest(report.get_errors(), expected_errors): assert r == e
def test_arrayref_expr_error(self): '''An error with given program: `int x[3]; x[0] = 1.0;`''' 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.Float(1)) ]) report = typechecker.typecheck(given) expected_errors = [ TypecheckerError( ast.Assignment(ast.ArrayRef(ast.ID('x'), ast.Integer(0)), ast.Float(1))) ] 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_float_expression(self): '''Expression with floats and integers: `1.0 + 2;`''' given = iter([ Token('FLOAT', '1.0'), Token('PLUS', '+'), Token('INTEGER', '2'), Token('SEMI', ';') ]) result = parser.parse(given) expected = ast.Block([ ast.Statement( ast.BinOp( '+', ast.Float(1.0), ast.Integer(2) ) ) ]) assert result == expected