Cleanup to module_constant_def, function calls
This commit is contained in:
parent
13f3f33740
commit
8cc47ae63e
@ -53,6 +53,9 @@ class ConstantPrimitive(Constant):
|
||||
super().__init__()
|
||||
self.value = value
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'ConstantPrimitive({repr(self.value)})'
|
||||
|
||||
class ConstantTuple(Constant):
|
||||
"""
|
||||
A Tuple constant value expression within a statement
|
||||
|
||||
@ -60,14 +60,16 @@ class SameTypeConstraint(ConstraintBase):
|
||||
"""
|
||||
Verifies that an expression has an expected type
|
||||
"""
|
||||
__slots__ = ('expected', 'actual', )
|
||||
__slots__ = ('expected', 'actual', 'message', )
|
||||
|
||||
expected: types.Type3
|
||||
actual: types.Type3OrPlaceholder
|
||||
message: str
|
||||
|
||||
def __init__(self, expected: types.Type3, actual: types.Type3OrPlaceholder) -> None:
|
||||
def __init__(self, expected: types.Type3, actual: types.Type3OrPlaceholder, message: str) -> None:
|
||||
self.expected = expected
|
||||
self.actual = actual
|
||||
self.message = message
|
||||
|
||||
def check(self) -> CheckResult:
|
||||
if isinstance(self.actual, types.PlaceholderForType):
|
||||
@ -91,6 +93,9 @@ class SameTypeConstraint(ConstraintBase):
|
||||
self.actual.get_substituted(smap[self.actual])
|
||||
self.actual = smap[self.actual]
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'SameTypeConstraint({repr(self.expected)}, {repr(self.actual)}, {repr(self.message)})'
|
||||
|
||||
class LiteralFitsConstraint(ConstraintBase):
|
||||
"""
|
||||
A literal value fits a given type
|
||||
@ -148,3 +153,11 @@ class LiteralFitsConstraint(ConstraintBase):
|
||||
return Error('Must be real') # FIXME: Add line information
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
def substitute_placeholders(self, smap: SubstitutionMap) -> None: # FIXME: Duplicate code
|
||||
if isinstance(self.type3, types.PlaceholderForType) and self.type3 in smap: # FIXME: Check recursive?
|
||||
self.type3.get_substituted(smap[self.type3])
|
||||
self.type3 = smap[self.type3]
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'LiteralFitsConstraint({repr(self.type3)}, {repr(self.literal)})'
|
||||
|
||||
@ -22,13 +22,7 @@ def phasm_type3_generate_constraints(inp: ourlang.Module) -> List[ConstraintBase
|
||||
|
||||
def constant(ctx: Context, inp: ourlang.Constant) -> Generator[ConstraintBase, None, None]:
|
||||
if isinstance(inp, ourlang.ConstantPrimitive):
|
||||
# A constant by itself doesn't have any constraints
|
||||
yield from ()
|
||||
return
|
||||
|
||||
if isinstance(inp, ourlang.ConstantTuple):
|
||||
# A constant by itself doesn't have any constraints
|
||||
yield from ()
|
||||
yield LiteralFitsConstraint(inp.type3, inp)
|
||||
return
|
||||
|
||||
raise NotImplementedError(constant, inp)
|
||||
@ -39,7 +33,19 @@ def expression(ctx: Context, inp: ourlang.Expression) -> Generator[ConstraintBas
|
||||
return
|
||||
|
||||
if isinstance(inp, ourlang.VariableReference):
|
||||
yield SameTypeConstraint(inp.variable.type3, inp.type3)
|
||||
yield SameTypeConstraint(inp.variable.type3, inp.type3, f'The type of a variable reference is the same as the type of variable {inp.variable.name}')
|
||||
return
|
||||
|
||||
if isinstance(inp, ourlang.FunctionCall):
|
||||
yield SameTypeConstraint(inp.function.returns_type3, inp.type3, f'The type of a function call to {inp.function.name} is the same as the type that the function returns')
|
||||
|
||||
assert len(inp.arguments) == len(inp.function.posonlyargs) # FIXME: Make this a Constraint
|
||||
|
||||
for fun_arg, call_arg in zip(inp.function.posonlyargs, inp.arguments):
|
||||
yield from expression(ctx, call_arg)
|
||||
yield SameTypeConstraint(fun_arg.type3, call_arg.type3,
|
||||
f'The type of the value passed to argument {fun_arg.name} of function {inp.function.name} should match the type of that argument')
|
||||
|
||||
return
|
||||
|
||||
raise NotImplementedError(expression, inp)
|
||||
@ -50,36 +56,11 @@ def function(ctx: Context, inp: ourlang.Function) -> Generator[ConstraintBase, N
|
||||
|
||||
yield from expression(ctx, inp.statements[0].value)
|
||||
|
||||
yield SameTypeConstraint(inp.returns_type3, inp.statements[0].value.type3)
|
||||
yield SameTypeConstraint(inp.returns_type3, inp.statements[0].value.type3, f'The type of the value returned from function {inp.name} should match its return type')
|
||||
|
||||
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
|
||||
or inp.type3 is types.u64
|
||||
or inp.type3 is types.i32
|
||||
or inp.type3 is types.i64
|
||||
or inp.type3 is types.f32
|
||||
or inp.type3 is types.f64
|
||||
) and isinstance(inp.constant, ourlang.ConstantPrimitive):
|
||||
yield LiteralFitsConstraint(inp.type3, inp.constant)
|
||||
inp.constant.type3 = inp.type3
|
||||
return
|
||||
|
||||
if isinstance(inp.type3, types.AppliedType3):
|
||||
if inp.type3.base is types.static_array and isinstance(inp.constant, ourlang.ConstantTuple):
|
||||
for lit in inp.constant.value:
|
||||
yield LiteralFitsConstraint(inp.type3.args[0], lit)
|
||||
# lit.type3 = inp.type3.args[0]
|
||||
raise NotImplementedError
|
||||
return
|
||||
|
||||
raise NotImplementedError(constant, inp, inp.type3)
|
||||
yield SameTypeConstraint(inp.type3, inp.constant.type3, f'The type of the value for module constant definition {inp.name} should match the type of that constant')
|
||||
|
||||
def module(ctx: Context, inp: ourlang.Module) -> Generator[ConstraintBase, None, None]:
|
||||
for cdef in inp.constant_defs.values():
|
||||
|
||||
@ -9,6 +9,8 @@ from .constraints import Error, RequireTypeSubstitutes
|
||||
from .constraintsgenerator import phasm_type3_generate_constraints
|
||||
from .types import PlaceholderForType, Type3
|
||||
|
||||
MAX_RESTACK_COUNT = 10
|
||||
|
||||
class Type3Exception(BaseException):
|
||||
"""
|
||||
Thrown when the Type3 system detects constraints that do not hold
|
||||
@ -20,8 +22,10 @@ def phasm_type3(inp: ourlang.Module) -> None:
|
||||
|
||||
placeholder_substitutes: Dict[PlaceholderForType, Type3] = {}
|
||||
|
||||
restack_counter = 0
|
||||
|
||||
error_list: List[Error] = []
|
||||
while constraint_list: # FIXME: How to detect infinite loop? Is that necessary?
|
||||
while constraint_list:
|
||||
constraint = constraint_list.pop(0)
|
||||
|
||||
constraint.substitute_placeholders(placeholder_substitutes)
|
||||
@ -36,6 +40,11 @@ def phasm_type3(inp: ourlang.Module) -> None:
|
||||
continue
|
||||
|
||||
if isinstance(check_result, RequireTypeSubstitutes):
|
||||
# FIXME: How to detect infinite loop? Is that necessary?
|
||||
restack_counter += 1
|
||||
if restack_counter > MAX_RESTACK_COUNT:
|
||||
raise Exception('This looks like an infinite loop', constraint_list)
|
||||
|
||||
constraint_list.append(constraint)
|
||||
continue
|
||||
|
||||
@ -45,4 +54,3 @@ def phasm_type3(inp: ourlang.Module) -> None:
|
||||
raise Type3Exception(error_list)
|
||||
|
||||
# TODO: Implement type substitution on the AST
|
||||
print('placeholder_substitutes', placeholder_substitutes)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user