diff --git a/boring/parse.py b/boring/parse.py index f3ca19f..bb6f253 100644 --- a/boring/parse.py +++ b/boring/parse.py @@ -156,7 +156,14 @@ class VariableDeclaration: class Function: declaration: "FunctionDeclaration" block: Block - type: TypeUsage + + @property + def type(self): + return self.declaration.type + + @type.setter + def type(self, value): + self.declaration.type = value @dataclass @@ -317,6 +324,7 @@ boring_grammar = r""" type_declaration : struct_type_declaration | type_alias_declaration + | trait_declaration impl : "impl" identifier "{" function* "}" | "impl" identifier "for" identifier "{" function* "}" @@ -470,22 +478,22 @@ class TreeToBoring(Transformer): def function_declaration_without_return(self, fdwr) -> FunctionDeclaration: return FunctionDeclaration( - name=function[0], - arguments=function[1:], + name=fdwr[0], + arguments=fdwr[1:], return_type=DataTypeUsage(name=UNIT_TYPE), type=FunctionTypeUsage( - arguments=[arg.type for arg in function[1:]], + arguments=[arg.type for arg in fdwr[1:]], return_type=DataTypeUsage(name=UNIT_TYPE), ), ) def function_declaration_with_return(self, fdwr) -> FunctionDeclaration: - return Function( - name=function[0], - arguments=function[1:-1], - return_type=function[-1], + return FunctionDeclaration( + name=fdwr[0], + arguments=fdwr[1:-1], + return_type=fdwr[-1], type=FunctionTypeUsage( - arguments=[arg.type for arg in function[1:-1]], return_type=function[-1] + arguments=[arg.type for arg in fdwr[1:-1]], return_type=fdwr[-1] ), ) @@ -494,27 +502,9 @@ class TreeToBoring(Transformer): assert isinstance(fd, FunctionDeclaration) return fd - def function(self, function) -> Function: - return Function( - declaration=function[0], - block=function[1], - type=UnknownTypeUsage(), - ) - - def function_with_return(self, function) -> Function: - return Function( - name=function[0], - arguments=function[1:-2], - return_type=function[-2], - block=function[-1], - type=FunctionTypeUsage( - arguments=[arg.type for arg in function[1:-2]], return_type=function[-2] - ), - ) - def function(self, function): - (function,) = function - return function + (declaration, block) = function + return Function(declaration, block) def struct_definition_field(self, struct_definition_field): (field, type_usage) = struct_definition_field diff --git a/boring/type_alias_resolution.py b/boring/type_alias_resolution.py index e430650..93ca462 100644 --- a/boring/type_alias_resolution.py +++ b/boring/type_alias_resolution.py @@ -67,10 +67,10 @@ class TypeAliasResolver: return def with_function(self, ctx: Context, function: parse.Function): - for argument in function.arguments: + for argument in function.declaration.arguments: argument.type = process_type(ctx, argument.type) - function.return_type = process_type(ctx, function.return_type) - function.type = process_type(ctx, function.type) + function.declaration.return_type = process_type(ctx, function.declaration.return_type) + function.declaration.type = process_type(ctx, function.declaration.type) self.with_block(ctx, function.block) return diff --git a/boring/type_checking.py b/boring/type_checking.py index 954c135..1b1f148 100644 --- a/boring/type_checking.py +++ b/boring/type_checking.py @@ -104,7 +104,7 @@ class TypeChecker: for name, field in type_declaration.fields.items(): assert_exists(ctx, field) for function in module.functions: - ctx.environment[function.name] = function + ctx.environment[function.declaration.name] = function changed = False for impl in module.impls: @@ -120,9 +120,9 @@ class TypeChecker: def with_function(self, ctx: Context, function: parse.Function) -> bool: function_ctx = ctx.copy() function_ctx.current_function = function - for argument in function.arguments: + for argument in function.declaration.arguments: function_ctx.environment[argument.name] = argument - assert isinstance(function.type, parse.FunctionTypeUsage) + assert isinstance(function.declaration.type, parse.FunctionTypeUsage) changed = self.with_block(function_ctx, function.block) @@ -131,10 +131,10 @@ class TypeChecker: and function.block.type.name == parse.NEVER_TYPE ): type, compare_changed = type_compare( - function_ctx, function.block.type, function.type.return_type + function_ctx, function.block.type, function.declaration.type.return_type ) function.block.type = type - function.type.return_type = type + function.declaration.type.return_type = type if compare_changed is True: changed = True return changed @@ -224,12 +224,12 @@ class TypeChecker: and return_statement.source.type.name == parse.NEVER_TYPE ): assert isinstance(ctx.current_function, parse.Function) - assert isinstance(ctx.current_function.type, parse.FunctionTypeUsage) + assert isinstance(ctx.current_function.declaration.type, parse.FunctionTypeUsage) type, compare_changed = type_compare( - ctx, return_statement.source.type, ctx.current_function.type.return_type + ctx, return_statement.source.type, ctx.current_function.declaration.type.return_type ) return_statement.source.type = type - ctx.current_function.type.return_type = type + ctx.current_function.declaration.type.return_type = type if compare_changed is True: changed = True return changed @@ -356,10 +356,10 @@ class TypeChecker: found = False for impl in impls: for function in impl.functions: - if function.name == struct_getter.attribute: - assert isinstance(function.type, parse.FunctionTypeUsage) + if function.declaration.name == struct_getter.attribute: + assert isinstance(function.declaration.type, parse.FunctionTypeUsage) result_type, changed_getter = type_compare( - ctx, struct_getter.type, function_to_method(function.type) + ctx, struct_getter.type, function_to_method(function.declaration.type) ) found = True break diff --git a/examples/math/main.bl b/examples/math/main.bl index e4e4454..d1c676f 100644 --- a/examples/math/main.bl +++ b/examples/math/main.bl @@ -64,3 +64,20 @@ impl User { return self.id; } } + +type TestTrait trait { + fn classMethod(id: I64): Self; + fn instanceMethod(self: Self): I64; + fn defaultImpl(self: Self): I64 { + return self.instanceMethod; + } +} + +impl TestTrait for User { + fn classMethod(id: I64): Self { + return User{id: id,}; + } + fn instanceMethod(self: Self): I64 { + return self.get_id(); + } +}