def infer_type(variable_name: str) -> types.Type: if variable_name.startswith("person"): return types.TypeRef(name="Person") if variable_name.startswith("tail"): return types.TypeRef(name="VectorArray") elif variable_name.startswith("vectorArray"): return types.TypeRef(name="VectorArray") elif variable_name.startswith("vector"): return types.TypeRef(name="Vector") else: return types.I32()
def as_language_type(type_: types.Type, symbol_table: SymbolTable) -> types.Type: assert isinstance(type_, types.Placeholder) text = type_.text if text == "i32": return types.I32() if text == "void": return types.Void() if text == "boolean": return types.Boolean() if symbol_table.has(text): symbol = symbol_table.get(text) assert symbol.type.is_data() or symbol.type.is_trait() return types.TypeRef(name=text) else: raise TypeError(f"Type not supported: {type_}")
def visit_data_def(self, data: ast.DataDef): implements = [] for implement in data.implements: implements.append(types.TypeRef(name=implement)) data_def_type = types.Data( name=data.name, implements=implements, fields=[], functions=[] ) data.type = data_def_type self.symbol_table.add( Symbol(name=data.name, type=data_def_type, kind=SymbolKind.DATA) ) for field in data.params: field.type = types.Field( name=field.name, type=as_language_type(field.type, self.symbol_table) ) data_def_type.fields.append(field.type) self.symbol_table = self.symbol_table.enter_scope() for function in data.functions: function.accept(self) self.symbol_table = self.symbol_table.exit_scope() return data
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=[], ), )
def test_data_vector_with_complex_function(): source = """ import System::Output; export data Vector(x: i32, y: i32) { function add(self: Vector, other: Vector): Vector { Vector(x = self.x + other.x, y = self.y + other.y); } } export function Main(): void { } """ result = get_semantic_analysis(source) assert_equal_programs( result, ast.Program( imports=[ast.Import(value="System::Output")], traits=[], data_defs=[ ast.DataDef( name="Vector", implements=[], is_exported=True, params=[ ast.Param(name="x", type=types.Field(name="x", type=types.I32())), ast.Param(name="y", type=types.Field(name="y", type=types.I32())), ], functions=[ ast.Function( name="add", is_exported=False, params=[ ast.Param( name="self", type=types.Param( name="self", type=types.TypeRef(name="Vector")), ), ast.Param( name="other", type=types.Param( name="other", type=types.TypeRef(name="Vector")), ), ], type=types.Function( name="add", params=[ types.Param( name="self", type=types.TypeRef(name="Vector")), types.Param( name="other", type=types.TypeRef(name="Vector")), ], result=types.TypeRef(name="Vector"), ), body=[ ast.FunctionCall( name="Vector", arguments=[ ast.Argument( name="x", value=ast.BinaryOperation( operator=ast.BinaryOperator. ADD, left=ast.MemberAccess( value=ast.Variable( name="self"), member="x", ), right=ast.MemberAccess( value=ast.Variable( name="other"), member="x", ), ), ), ast.Argument( name="y", value=ast.BinaryOperation( operator=ast.BinaryOperator. ADD, left=ast.MemberAccess( value=ast.Variable( name="self"), member="y", ), right=ast.MemberAccess( value=ast.Variable( name="other"), member="y", ), ), ), ], ) ], ) ], type=types.Data( name="Vector", implements=[], fields=[ types.Field(name="x", type=types.I32()), types.Field(name="y", type=types.I32()), ], functions=[], ), ) ], functions=[ ast.Function( name="Main", is_exported=True, params=[], type=types.Function(name="Main", params=[], result=types.Void()), body=[], ) ], ), )