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] 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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user