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] Getter
- [x] Setter - [x] Setter
- [x] Type Aliases - [x] Type Aliases
- [ ] Methods - [x] Methods
- [x] Declaration - [x] Declaration
- [ ] Use - [x] Use
- [ ] Traits - [ ] Traits
- [ ] Generics - [ ] Generics
- [ ] Basic - [ ] Basic

View File

@@ -33,7 +33,7 @@ if __name__ == "__main__":
alias_resolver.with_module(AliasContex([]), result) alias_resolver.with_module(AliasContex([]), result)
# pretty_print(result) # pretty_print(result)
type_checker = TypeChecker() type_checker = TypeChecker()
while type_checker.with_module(Context(builtins, None), result): while type_checker.with_module(Context(builtins, None, result), result):
print("loop") print("loop")
# type_checker.with_module({}, result) # type_checker.with_module({}, result)
pretty_print(result) pretty_print(result)

View File

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

View File

@@ -32,13 +32,12 @@ def process_type(ctx: Context, type: parse.TypeUsage) -> parse.TypeUsage:
elif isinstance(type, parse.FunctionTypeUsage): elif isinstance(type, parse.FunctionTypeUsage):
return parse.FunctionTypeUsage( return parse.FunctionTypeUsage(
return_type=process_type(ctx, type.return_type), 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: else:
return type return type
class TypeAliasResolver: class TypeAliasResolver:
def with_module(self, ctx: Context, module: parse.Module): def with_module(self, ctx: Context, module: parse.Module):
for type_declaration in module.types: for type_declaration in module.types:
@@ -48,11 +47,18 @@ class TypeAliasResolver:
for type_declaration in module.types: for type_declaration in module.types:
if isinstance(type_declaration, parse.StructTypeDeclaration): if isinstance(type_declaration, parse.StructTypeDeclaration):
for field in type_declaration.fields: 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: for impl in module.impls:
impl_ctx = ctx.copy() 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: for function in impl.functions:
self.with_function(impl_ctx, function) self.with_function(impl_ctx, function)
@@ -88,9 +94,7 @@ class TypeAliasResolver:
else: else:
assert False assert False
def with_let_statement( def with_let_statement(self, ctx: Context, let_statement: parse.LetStatement):
self, ctx: Context, let_statement: parse.LetStatement
):
self.with_expression(ctx, let_statement.expression) self.with_expression(ctx, let_statement.expression)
let_statement.type = process_type(ctx, let_statement.type) let_statement.type = process_type(ctx, let_statement.type)
@@ -140,9 +144,7 @@ class TypeAliasResolver:
assert False assert False
return return
def with_variable_usage( def with_variable_usage(self, ctx: Context, variable_usage: parse.VariableUsage):
self, ctx: Context, variable_usage: parse.VariableUsage
):
variable_usage.type = process_type(ctx, variable_usage.type) variable_usage.type = process_type(ctx, variable_usage.type)
def with_operation(self, ctx: Context, operation: parse.Operation): def with_operation(self, ctx: Context, operation: parse.Operation):
@@ -151,25 +153,19 @@ class TypeAliasResolver:
operation.type = process_type(ctx, operation.type) operation.type = process_type(ctx, operation.type)
return return
def with_function_call( def with_function_call(self, ctx: Context, function_call: parse.FunctionCall):
self, ctx: Context, function_call: parse.FunctionCall
):
self.with_expression(ctx, function_call.source) self.with_expression(ctx, function_call.source)
for argument in function_call.arguments: for argument in function_call.arguments:
self.with_expression(ctx, argument) self.with_expression(ctx, argument)
function_call.type = process_type(ctx, function_call.type) function_call.type = process_type(ctx, function_call.type)
return return
def with_struct_getter( def with_struct_getter(self, ctx: Context, struct_getter: parse.StructGetter):
self, ctx: Context, struct_getter: parse.StructGetter
):
self.with_expression(ctx, struct_getter.source) self.with_expression(ctx, struct_getter.source)
struct_getter.type = process_type(ctx, struct_getter.type) struct_getter.type = process_type(ctx, struct_getter.type)
return return
def with_literal_float( def with_literal_float(self, ctx: Context, literal_float: parse.LiteralFloat):
self, ctx: Context, literal_float: parse.LiteralFloat
):
literal_float.type = process_type(ctx, literal_float.type) literal_float.type = process_type(ctx, literal_float.type)
return return
@@ -177,9 +173,7 @@ class TypeAliasResolver:
literal_int.type = process_type(ctx, literal_int.type) literal_int.type = process_type(ctx, literal_int.type)
return return
def with_literal_struct( def with_literal_struct(self, ctx: Context, literal_struct: parse.LiteralStruct):
self, ctx: Context, literal_struct: parse.LiteralStruct
):
for name, expression in literal_struct.fields.items(): for name, expression in literal_struct.fields.items():
self.with_expression(ctx, expression) self.with_expression(ctx, expression)
literal_struct.type = process_type(ctx, literal_struct.type) literal_struct.type = process_type(ctx, literal_struct.type)

View File

@@ -15,9 +15,12 @@ Environment = Dict[str, Identified]
class Context: class Context:
environment: Environment environment: Environment
current_function: Optional[parse.Function] current_function: Optional[parse.Function]
current_module: parse.Module
def copy(self): 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: def unify(ctx: Context, first, second) -> bool:
@@ -28,6 +31,10 @@ def unify(ctx: Context, first, second) -> bool:
return changed return changed
def function_to_method(type: parse.FunctionTypeUsage) -> parse.FunctionTypeUsage:
return parse.FunctionTypeUsage(type.arguments[1:], type.return_type)
def type_compare( def type_compare(
ctx: Context, first: parse.TypeUsage, second: parse.TypeUsage ctx: Context, first: parse.TypeUsage, second: parse.TypeUsage
) -> Tuple[parse.TypeUsage, bool]: ) -> Tuple[parse.TypeUsage, bool]:
@@ -334,10 +341,30 @@ class TypeChecker:
assert isinstance(struct_getter.source.type, parse.DataTypeUsage) assert isinstance(struct_getter.source.type, parse.DataTypeUsage)
struct_declaration = ctx.environment[struct_getter.source.type.name] struct_declaration = ctx.environment[struct_getter.source.type.name]
assert isinstance(struct_declaration, parse.StructTypeDeclaration) 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( 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: if changed_getter:
changed = True changed = True
struct_getter.type = result_type struct_getter.type = result_type

View File

@@ -45,6 +45,10 @@ fn get_user_id(): U64 {
return user.id; return user.id;
} }
fn use_method(user: User): U64 {
return user.get_id();
}
type User struct { type User struct {
id: U64, id: U64,
} }