def test_while_loop(self): buf = """ fn loopTest(int x) -> int { while (x < 5) { print("blah"); } return 0; } """ exprs = [ ast.Function( "loopTest", [("x", ast.Type(ast.TypeKind.INT))], [ ast.WhileLoop( ast.BinaryOp(ast.VariableRef("x"), ast.Number(5), Token(TokenType.LESS_THAN, "<")), [ ast.ExprStatement( ast.FunctionCall("print", [ast.String("blah")])) ], ), ast.ReturnStatement(ast.Number(0)), ], ast.Type(ast.TypeKind.INT), ) ] self._test_parse_impl(buf, exprs)
def test_if_statements(self): buf = """ fn foo() -> string { if (3 == 3) { return "foo"; } return "bar"; } """ exprs = [ ast.Function( "foo", [], [ ast.IfStatement( ast.BinaryOp(ast.Number(3), ast.Number(3), Token(TokenType.EQUALS, "==")), [ast.ReturnStatement(ast.String("foo"))], list(), ), ast.ReturnStatement(ast.String("bar")), ], ast.Type(ast.TypeKind.STRING), ) ] self._test_parse_impl(buf, exprs)
def test_precedence(self): buf = """ fn prec() -> int { 2 + 3 * 2 + 2 / 8; } """ exprs = [ ast.Function( "prec", [], [ ast.ExprStatement( ast.BinaryOp( ast.BinaryOp( ast.Number(2), ast.BinaryOp(ast.Number(3), ast.Number(2), Token(TokenType.MULTIPLY, "*")), Token(TokenType.ADD, "+"), ), ast.BinaryOp(ast.Number(2), ast.Number(8), Token(TokenType.DIVIDE, "/")), Token(TokenType.ADD, "+"), )) ], ast.Type(ast.TypeKind.INT), ) ] self._test_parse_impl(buf, exprs)
def test_constructor(self): buf = """ fn constructorTest() -> int { let foo = new Foo(name, age); return 0; } """ exprs = [ ast.Function( "constructorTest", [], [ ast.LetStatement( "foo", ast.Constructor( "Foo", [ast.VariableRef("name"), ast.VariableRef("age")]), ), ast.ReturnStatement(ast.Number(0)), ], ast.Type(ast.TypeKind.INT), ) ] self._test_parse_impl(buf, exprs)
def test_simple_expression(): source = """ export function Main(): void { let a = 1 + 2 * 3; } """ result = get_semantic_analysis(source) assert_equal_programs( result, ast.Program( imports=[], traits=[], data_defs=[], functions=[ ast.Function( name="Main", is_exported=True, params=[], type=types.Function(name="Main", params=[], result=types.Void()), body=[ ast.Let( name="a", value=ast.BinaryOperation( operator=ast.BinaryOperator.ADD, left=ast.Number(value=1), right=ast.BinaryOperation( operator=ast.BinaryOperator.MULTIPLY, left=ast.Number(value=2), right=ast.Number(value=3), ), ), ) ], ) ], ), )
def test_function(self): buf = """ fn fooFunc(string name, int age) -> int { return 1; } """ exprs = [ ast.Function( "fooFunc", [("name", ast.Type(ast.TypeKind.STRING)), ("age", ast.Type(ast.TypeKind.INT))], [ast.ReturnStatement(ast.Number(1))], ast.Type(ast.TypeKind.INT), ) ] self._test_parse_impl(buf, exprs)
def test_let_statement(self): buf = """ fn letFunc() -> int { let x = 1; return x; } """ exprs = [ ast.Function( "letFunc", [], [ ast.LetStatement("x", ast.Number(1)), ast.ReturnStatement(ast.VariableRef("x")) ], ast.Type(ast.TypeKind.INT), ) ] self._test_parse_impl(buf, exprs)
def _parse_primary_expr(self): value = self.cur_tok.value expr = None if self._consume_token(TokenType.NUMBER_LITERAL): expr = ast.Number(int(value)) elif self._consume_token(TokenType.STRING_LITERAL): expr = ast.String(value) elif self._consume_token(TokenType.L_PAREN): expr = self._parse_vector() elif self._consume_token(TokenType.L_BRACE): expr = self._parse_map() elif self._consume_token(TokenType.NEW): expr = self._parse_constructor() elif self._consume_token(TokenType.IDENTIFIER): if self._consume_token(TokenType.L_BRACKET): return self._parse_function_call(value) return ast.VariableRef(value) else: raise RuntimeError("unrecognised primary expression: Token=({0})".format(self.cur_tok)) return expr
def test_trait_with_multiple_implementations(): source = """ trait List { function length(self: List): i32; function sum(self: List): i32; } data EmptyList() implements List { function length(self: List): i32 { 0; } function sum(self: List): i32 { 0; } } data Cons(head: i32, tail: List) implements List { function length(self: List): i32 { 1 + self.tail.length(); } function sum(self: List): i32 { self.head + self.tail.sum(); } } """ result = get_semantic_analysis(source) assert_equal_programs( result, ast.Program( imports=[], traits=[ ast.Trait( name="List", is_exported=False, functions=[ ast.Function( name="length", is_exported=False, params=[ ast.Param( name="self", type=types.Param( name="self", type=types.TypeRef(name="List")), ) ], type=types.Function( name="length", params=[ types.Param( name="self", type=types.TypeRef(name="List")) ], result=types.I32(), ), body=None, ), ast.Function( name="sum", is_exported=False, params=[ ast.Param( name="self", type=types.Param( name="self", type=types.TypeRef(name="List")), ) ], type=types.Function( name="sum", params=[ types.Param( name="self", type=types.TypeRef(name="List")) ], result=types.I32(), ), body=None, ), ], type=types.Trait(name="List", functions=[]), ) ], data_defs=[ ast.DataDef( name="EmptyList", is_exported=False, implements=["List"], params=[], functions=[ ast.Function( name="length", is_exported=False, params=[ ast.Param( name="self", type=types.Param( name="self", type=types.TypeRef(name="List")), ) ], type=types.Function( name="length", params=[ types.Param( name="self", type=types.TypeRef(name="List")) ], result=types.I32(), ), body=[ast.Number(value=0)], ), ast.Function( name="sum", is_exported=False, params=[ ast.Param( name="self", type=types.Param( name="self", type=types.TypeRef(name="List")), ) ], type=types.Function( name="sum", params=[ types.Param( name="self", type=types.TypeRef(name="List")) ], result=types.I32(), ), body=[ast.Number(value=0)], ), ], type=types.Data( name="EmptyList", implements=[types.TypeRef("List")], fields=[], functions=[], ), ), ast.DataDef( name="Cons", is_exported=False, implements=["List"], params=[ ast.Param(name="head", type=types.Field(name="head", type=types.I32())), ast.Param( name="tail", type=types.Field(name="tail", type=types.TypeRef(name="List")), ), ], functions=[ ast.Function( name="length", is_exported=False, params=[ ast.Param( name="self", type=types.Param( name="self", type=types.TypeRef(name="List")), ) ], type=types.Function( name="length", params=[ types.Param( name="self", type=types.TypeRef(name="List")) ], result=types.I32(), ), body=[ ast.BinaryOperation( operator=ast.BinaryOperator.ADD, left=ast.Number(value=1), right=ast.FunctionCall( name="self.tail.length", arguments=[]), ) ], ), ast.Function( name="sum", is_exported=False, params=[ ast.Param( name="self", type=types.Param( name="self", type=types.TypeRef(name="List")), ) ], type=types.Function( name="sum", params=[ types.Param( name="self", type=types.TypeRef(name="List")) ], result=types.I32(), ), body=[ ast.BinaryOperation( operator=ast.BinaryOperator.ADD, left=ast.MemberAccess( value=ast.Variable(name="self"), member="head"), right=ast.FunctionCall( name="self.tail.sum", arguments=[]), ) ], ), ], type=types.Data( name="Cons", implements=[types.TypeRef("List")], fields=[ types.Field(name="head", type=types.I32()), types.Field(name="tail", type=types.TypeRef(name="List")), ], functions=[], ), ), ], functions=[], ), )