added method calls

This commit is contained in:
Andrew Segavac
2021-06-26 17:47:52 -06:00
parent 142497573f
commit 75a042741e
6 changed files with 60 additions and 32 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -178,7 +178,10 @@ class AliasTypeDeclaration:
old: TypeUsage
TypeDeclaration = Union[StructTypeDeclaration, PrimitiveTypeDeclaration, AliasTypeDeclaration]
TypeDeclaration = Union[
StructTypeDeclaration, PrimitiveTypeDeclaration, AliasTypeDeclaration
]
@dataclass
class Impl:

View File

@@ -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)

View File

@@ -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

View File

@@ -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,
}