added method calls
This commit is contained in:
@@ -29,9 +29,9 @@ This language is under active development, progress will be marked here as the l
|
||||
- [x] Getter
|
||||
- [x] Setter
|
||||
- [x] Type Aliases
|
||||
- [ ] Methods
|
||||
- [x] Methods
|
||||
- [x] Declaration
|
||||
- [ ] Use
|
||||
- [x] Use
|
||||
- [ ] Traits
|
||||
- [ ] Generics
|
||||
- [ ] Basic
|
||||
|
||||
@@ -33,7 +33,7 @@ if __name__ == "__main__":
|
||||
alias_resolver.with_module(AliasContex([]), result)
|
||||
# pretty_print(result)
|
||||
type_checker = TypeChecker()
|
||||
while type_checker.with_module(Context(builtins, None), result):
|
||||
while type_checker.with_module(Context(builtins, None, result), result):
|
||||
print("loop")
|
||||
# type_checker.with_module({}, result)
|
||||
pretty_print(result)
|
||||
|
||||
@@ -178,7 +178,10 @@ class AliasTypeDeclaration:
|
||||
old: TypeUsage
|
||||
|
||||
|
||||
TypeDeclaration = Union[StructTypeDeclaration, PrimitiveTypeDeclaration, AliasTypeDeclaration]
|
||||
TypeDeclaration = Union[
|
||||
StructTypeDeclaration, PrimitiveTypeDeclaration, AliasTypeDeclaration
|
||||
]
|
||||
|
||||
|
||||
@dataclass
|
||||
class Impl:
|
||||
|
||||
@@ -32,13 +32,12 @@ def process_type(ctx: Context, type: parse.TypeUsage) -> parse.TypeUsage:
|
||||
elif isinstance(type, parse.FunctionTypeUsage):
|
||||
return parse.FunctionTypeUsage(
|
||||
return_type=process_type(ctx, type.return_type),
|
||||
arguments=[process_type(ctx, argument) for argument in type.arguments]
|
||||
arguments=[process_type(ctx, argument) for argument in type.arguments],
|
||||
)
|
||||
else:
|
||||
return type
|
||||
|
||||
|
||||
|
||||
class TypeAliasResolver:
|
||||
def with_module(self, ctx: Context, module: parse.Module):
|
||||
for type_declaration in module.types:
|
||||
@@ -48,11 +47,18 @@ class TypeAliasResolver:
|
||||
for type_declaration in module.types:
|
||||
if isinstance(type_declaration, parse.StructTypeDeclaration):
|
||||
for field in type_declaration.fields:
|
||||
type_declaration.fields[field] = process_type(ctx, type_declaration.fields[field])
|
||||
type_declaration.fields[field] = process_type(
|
||||
ctx, type_declaration.fields[field]
|
||||
)
|
||||
|
||||
for impl in module.impls:
|
||||
impl_ctx = ctx.copy()
|
||||
impl_ctx.type_aliases.append(parse.AliasTypeDeclaration(new=parse.DataTypeUsage("Self"), old=parse.DataTypeUsage(impl.struct)))
|
||||
impl_ctx.type_aliases.append(
|
||||
parse.AliasTypeDeclaration(
|
||||
new=parse.DataTypeUsage("Self"),
|
||||
old=parse.DataTypeUsage(impl.struct),
|
||||
)
|
||||
)
|
||||
for function in impl.functions:
|
||||
self.with_function(impl_ctx, function)
|
||||
|
||||
@@ -88,9 +94,7 @@ class TypeAliasResolver:
|
||||
else:
|
||||
assert False
|
||||
|
||||
def with_let_statement(
|
||||
self, ctx: Context, let_statement: parse.LetStatement
|
||||
):
|
||||
def with_let_statement(self, ctx: Context, let_statement: parse.LetStatement):
|
||||
self.with_expression(ctx, let_statement.expression)
|
||||
let_statement.type = process_type(ctx, let_statement.type)
|
||||
|
||||
@@ -140,9 +144,7 @@ class TypeAliasResolver:
|
||||
assert False
|
||||
return
|
||||
|
||||
def with_variable_usage(
|
||||
self, ctx: Context, variable_usage: parse.VariableUsage
|
||||
):
|
||||
def with_variable_usage(self, ctx: Context, variable_usage: parse.VariableUsage):
|
||||
variable_usage.type = process_type(ctx, variable_usage.type)
|
||||
|
||||
def with_operation(self, ctx: Context, operation: parse.Operation):
|
||||
@@ -151,25 +153,19 @@ class TypeAliasResolver:
|
||||
operation.type = process_type(ctx, operation.type)
|
||||
return
|
||||
|
||||
def with_function_call(
|
||||
self, ctx: Context, function_call: parse.FunctionCall
|
||||
):
|
||||
def with_function_call(self, ctx: Context, function_call: parse.FunctionCall):
|
||||
self.with_expression(ctx, function_call.source)
|
||||
for argument in function_call.arguments:
|
||||
self.with_expression(ctx, argument)
|
||||
function_call.type = process_type(ctx, function_call.type)
|
||||
return
|
||||
|
||||
def with_struct_getter(
|
||||
self, ctx: Context, struct_getter: parse.StructGetter
|
||||
):
|
||||
def with_struct_getter(self, ctx: Context, struct_getter: parse.StructGetter):
|
||||
self.with_expression(ctx, struct_getter.source)
|
||||
struct_getter.type = process_type(ctx, struct_getter.type)
|
||||
return
|
||||
|
||||
def with_literal_float(
|
||||
self, ctx: Context, literal_float: parse.LiteralFloat
|
||||
):
|
||||
def with_literal_float(self, ctx: Context, literal_float: parse.LiteralFloat):
|
||||
literal_float.type = process_type(ctx, literal_float.type)
|
||||
return
|
||||
|
||||
@@ -177,9 +173,7 @@ class TypeAliasResolver:
|
||||
literal_int.type = process_type(ctx, literal_int.type)
|
||||
return
|
||||
|
||||
def with_literal_struct(
|
||||
self, ctx: Context, literal_struct: parse.LiteralStruct
|
||||
):
|
||||
def with_literal_struct(self, ctx: Context, literal_struct: parse.LiteralStruct):
|
||||
for name, expression in literal_struct.fields.items():
|
||||
self.with_expression(ctx, expression)
|
||||
literal_struct.type = process_type(ctx, literal_struct.type)
|
||||
|
||||
@@ -15,9 +15,12 @@ Environment = Dict[str, Identified]
|
||||
class Context:
|
||||
environment: Environment
|
||||
current_function: Optional[parse.Function]
|
||||
current_module: parse.Module
|
||||
|
||||
def copy(self):
|
||||
return Context(self.environment.copy(), self.current_function)
|
||||
return Context(
|
||||
self.environment.copy(), self.current_function, self.current_module
|
||||
)
|
||||
|
||||
|
||||
def unify(ctx: Context, first, second) -> bool:
|
||||
@@ -28,6 +31,10 @@ def unify(ctx: Context, first, second) -> bool:
|
||||
return changed
|
||||
|
||||
|
||||
def function_to_method(type: parse.FunctionTypeUsage) -> parse.FunctionTypeUsage:
|
||||
return parse.FunctionTypeUsage(type.arguments[1:], type.return_type)
|
||||
|
||||
|
||||
def type_compare(
|
||||
ctx: Context, first: parse.TypeUsage, second: parse.TypeUsage
|
||||
) -> Tuple[parse.TypeUsage, bool]:
|
||||
@@ -334,10 +341,30 @@ class TypeChecker:
|
||||
assert isinstance(struct_getter.source.type, parse.DataTypeUsage)
|
||||
struct_declaration = ctx.environment[struct_getter.source.type.name]
|
||||
assert isinstance(struct_declaration, parse.StructTypeDeclaration)
|
||||
assert struct_getter.attribute in struct_declaration.fields
|
||||
if struct_getter.attribute in struct_declaration.fields:
|
||||
result_type, changed_getter = type_compare(
|
||||
ctx, struct_getter.type, struct_declaration.fields[struct_getter.attribute]
|
||||
ctx,
|
||||
struct_getter.type,
|
||||
struct_declaration.fields[struct_getter.attribute],
|
||||
)
|
||||
else: # check methods and traits
|
||||
impls = []
|
||||
for module_impl in ctx.current_module.impls:
|
||||
if module_impl.struct == struct_getter.source.type.name:
|
||||
impls.append(module_impl)
|
||||
assert len(impls) != 0
|
||||
found = False
|
||||
for impl in impls:
|
||||
for function in impl.functions:
|
||||
if function.name == struct_getter.attribute:
|
||||
assert isinstance(function.type, parse.FunctionTypeUsage)
|
||||
result_type, changed_getter = type_compare(
|
||||
ctx, struct_getter.type, function_to_method(function.type)
|
||||
)
|
||||
found = True
|
||||
break
|
||||
assert found, "Method not found"
|
||||
|
||||
if changed_getter:
|
||||
changed = True
|
||||
struct_getter.type = result_type
|
||||
|
||||
@@ -45,6 +45,10 @@ fn get_user_id(): U64 {
|
||||
return user.id;
|
||||
}
|
||||
|
||||
fn use_method(user: User): U64 {
|
||||
return user.get_id();
|
||||
}
|
||||
|
||||
type User struct {
|
||||
id: U64,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user