From 13f3f3374032dc2f796bf183b99a426f40eedf31 Mon Sep 17 00:00:00 2001 From: "Johan B.W. de Vries" Date: Thu, 17 Nov 2022 15:23:56 +0100 Subject: [PATCH] PlaceHolder all the things --- phasm/ourlang.py | 18 +++++++++++------- phasm/parser.py | 2 +- phasm/type3/constraints.py | 7 +++++-- phasm/type3/constraintsgenerator.py | 23 +++++++---------------- phasm/type3/entry.py | 1 + phasm/type3/types.py | 23 ++++++++++------------- 6 files changed, 35 insertions(+), 39 deletions(-) diff --git a/phasm/ourlang.py b/phasm/ourlang.py index d3c8222..273d82e 100644 --- a/phasm/ourlang.py +++ b/phasm/ourlang.py @@ -16,7 +16,8 @@ from .typing import ( TypeVar, ) -from .type3.types import Type3 +from .type3 import types as type3types +from .type3.types import Type3, Type3OrPlaceholder, PlaceholderForType class Expression: """ @@ -24,12 +25,12 @@ class Expression: """ __slots__ = ('type3', 'type_var', ) - type3: Optional[Type3] + type3: Type3OrPlaceholder type_var: Optional[TypeVar] def __init__(self) -> None: - self.type3 = None + self.type3 = PlaceholderForType([self]) self.type_var = None class Constant(Expression): @@ -209,15 +210,17 @@ class FunctionParam: """ A parameter for a Function """ - __slots__ = ('name', 'type_str', 'type_var', ) + __slots__ = ('name', 'type3', 'type_str', 'type_var', ) name: str + type3: Type3 type_str: str type_var: Optional[TypeVar] - def __init__(self, name: str, type_str: str) -> None: + def __init__(self, name: str, type3: Type3) -> None: self.name = name - self.type_str = type_str + self.type3 = type3 + self.type_str = type3.name self.type_var = None class Function: @@ -231,7 +234,7 @@ class Function: exported: bool imported: bool statements: List[Statement] - returns_type3: Optional[Type3] + returns_type3: Type3 returns_str: str returns_type_var: Optional[TypeVar] posonlyargs: List[FunctionParam] @@ -242,6 +245,7 @@ class Function: self.exported = False self.imported = False self.statements = [] + self.returns_type3 = type3types.none self.returns_str = 'None' self.returns_type_var = None self.posonlyargs = [] diff --git a/phasm/parser.py b/phasm/parser.py index 2f8ade6..641ad39 100644 --- a/phasm/parser.py +++ b/phasm/parser.py @@ -131,7 +131,7 @@ class OurVisitor: function.posonlyargs.append(FunctionParam( arg.arg, - self.visit_type(module, arg.annotation).name, + self.visit_type(module, arg.annotation), )) _not_implemented(not node.args.vararg, 'FunctionDef.args.vararg') diff --git a/phasm/type3/constraints.py b/phasm/type3/constraints.py index dd73775..f2027c9 100644 --- a/phasm/type3/constraints.py +++ b/phasm/type3/constraints.py @@ -13,6 +13,9 @@ class Error: def __init__(self, msg: str) -> None: self.msg = msg + def __repr__(self) -> str: + return f'Error({repr(self.msg)})' + class RequireTypeSubstitutes: pass @@ -73,7 +76,7 @@ class SameTypeConstraint(ConstraintBase): if self.expected is self.actual: return None - raise NotImplementedError + return Error(f'{self.expected:s} must be {self.actual:s} instead') def get_new_placeholder_substitutes(self) -> SubstitutionMap: if isinstance(self.actual, types.PlaceholderForType): @@ -84,7 +87,7 @@ class SameTypeConstraint(ConstraintBase): return {} def substitute_placeholders(self, smap: SubstitutionMap) -> None: - if isinstance(self.actual, types.PlaceholderForType) and self.actual in smap: + if isinstance(self.actual, types.PlaceholderForType) and self.actual in smap: # FIXME: Check recursive? self.actual.get_substituted(smap[self.actual]) self.actual = smap[self.actual] diff --git a/phasm/type3/constraintsgenerator.py b/phasm/type3/constraintsgenerator.py index 3f61cd7..447d5d1 100644 --- a/phasm/type3/constraintsgenerator.py +++ b/phasm/type3/constraintsgenerator.py @@ -38,6 +38,10 @@ def expression(ctx: Context, inp: ourlang.Expression) -> Generator[ConstraintBas yield from constant(ctx, inp) return + if isinstance(inp, ourlang.VariableReference): + yield SameTypeConstraint(inp.variable.type3, inp.type3) + return + raise NotImplementedError(expression, inp) def function(ctx: Context, inp: ourlang.Function) -> Generator[ConstraintBase, None, None]: @@ -46,22 +50,14 @@ def function(ctx: Context, inp: ourlang.Function) -> Generator[ConstraintBase, N yield from expression(ctx, inp.statements[0].value) - if inp.returns_type3 is None: - raise NotImplementedError - - actual: types.Type3OrPlaceholder - if inp.statements[0].value.type3 is None: - print('inp.statements[0].value', inp.statements[0].value) - actual = types.PlaceholderForType([inp.statements[0].value]) - else: - actual = inp.statements[0].value.type3 - - yield SameTypeConstraint(inp.returns_type3, actual) + yield SameTypeConstraint(inp.returns_type3, inp.statements[0].value.type3) def module_constant_def(ctx: Context, inp: ourlang.ModuleConstantDef) -> Generator[ConstraintBase, None, None]: yield from constant(ctx, inp.constant) + # FIXME: Redo this part + if ( inp.type3 is types.u8 or inp.type3 is types.u32 @@ -86,11 +82,6 @@ def module_constant_def(ctx: Context, inp: ourlang.ModuleConstantDef) -> Generat raise NotImplementedError(constant, inp, inp.type3) def module(ctx: Context, inp: ourlang.Module) -> Generator[ConstraintBase, None, None]: - for func in inp.functions.values(): - assert func.returns_type3 is not None, 'TODO' - for param in func.posonlyargs: - assert False, 'TODO' - for cdef in inp.constant_defs.values(): yield from module_constant_def(ctx, cdef) diff --git a/phasm/type3/entry.py b/phasm/type3/entry.py index 82a9a4d..d6c822e 100644 --- a/phasm/type3/entry.py +++ b/phasm/type3/entry.py @@ -33,6 +33,7 @@ def phasm_type3(inp: ourlang.Module) -> None: if isinstance(check_result, Error): error_list.append(check_result) + continue if isinstance(check_result, RequireTypeSubstitutes): constraint_list.append(constraint) diff --git a/phasm/type3/types.py b/phasm/type3/types.py index 21b522a..66b9a11 100644 --- a/phasm/type3/types.py +++ b/phasm/type3/types.py @@ -4,14 +4,14 @@ Contains the final types for use in Phasm These are actual, instantiated types; not the abstract types that the constraint generator works with. """ -from typing import Any, ClassVar, Dict, Iterable, Optional, List, Protocol, Union +from typing import Any, Dict, Iterable, List, Protocol, Union class ExpressionProtocol(Protocol): """ A protocol for classes that should be updated on substitution """ - type3: Optional['Type3'] + type3: 'Type3OrPlaceholder' """ The type to update """ @@ -38,7 +38,7 @@ class Type3: def __format__(self, format_spec: str) -> str: if format_spec != 's': - raise TypeError('unsupported format string passed to Type3.__format__') + raise TypeError(f'unsupported format string passed to Type3.__format__: {format_spec}') return str(self) @@ -58,17 +58,11 @@ class PlaceholderForType: """ A placeholder type, for when we don't know the final type yet """ - __slots__ = ('number', 'update_on_substitution', ) + __slots__ = ('update_on_substitution', ) - number: int update_on_substitution: List[ExpressionProtocol] - NEXT_NUMBER: ClassVar[int] = 1 - def __init__(self, update_on_substitution: Iterable[ExpressionProtocol]) -> None: - self.number = PlaceholderForType.NEXT_NUMBER - PlaceholderForType.NEXT_NUMBER += 1 - self.update_on_substitution = [*update_on_substitution] def get_substituted(self, result_type: Type3) -> None: @@ -85,10 +79,10 @@ class PlaceholderForType: def __repr__(self) -> str: uos = ', '.join(repr(x) for x in self.update_on_substitution) - return f'PlaceholderForType({self.number} [{uos}])' + return f'PlaceholderForType({id(self)}, [{uos}])' def __str__(self) -> str: - return f'T{self.number}' + return f'PhFT_{id(self)}' def __format__(self, format_spec: str) -> str: if format_spec != 's': @@ -97,7 +91,10 @@ class PlaceholderForType: return str(self) def __eq__(self, other: Any) -> bool: - raise NotImplementedError + if not isinstance(other, PlaceholderForType): + raise NotImplementedError + + return self is other def __ne__(self, other: Any) -> bool: raise NotImplementedError