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__()
|
super().__init__()
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f'ConstantPrimitive({repr(self.value)})'
|
||||||
|
|
||||||
class ConstantTuple(Constant):
|
class ConstantTuple(Constant):
|
||||||
"""
|
"""
|
||||||
A Tuple constant value expression within a statement
|
A Tuple constant value expression within a statement
|
||||||
|
|||||||
@ -60,14 +60,16 @@ class SameTypeConstraint(ConstraintBase):
|
|||||||
"""
|
"""
|
||||||
Verifies that an expression has an expected type
|
Verifies that an expression has an expected type
|
||||||
"""
|
"""
|
||||||
__slots__ = ('expected', 'actual', )
|
__slots__ = ('expected', 'actual', 'message', )
|
||||||
|
|
||||||
expected: types.Type3
|
expected: types.Type3
|
||||||
actual: types.Type3OrPlaceholder
|
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.expected = expected
|
||||||
self.actual = actual
|
self.actual = actual
|
||||||
|
self.message = message
|
||||||
|
|
||||||
def check(self) -> CheckResult:
|
def check(self) -> CheckResult:
|
||||||
if isinstance(self.actual, types.PlaceholderForType):
|
if isinstance(self.actual, types.PlaceholderForType):
|
||||||
@ -91,6 +93,9 @@ class SameTypeConstraint(ConstraintBase):
|
|||||||
self.actual.get_substituted(smap[self.actual])
|
self.actual.get_substituted(smap[self.actual])
|
||||||
self.actual = 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):
|
class LiteralFitsConstraint(ConstraintBase):
|
||||||
"""
|
"""
|
||||||
A literal value fits a given type
|
A literal value fits a given type
|
||||||
@ -148,3 +153,11 @@ class LiteralFitsConstraint(ConstraintBase):
|
|||||||
return Error('Must be real') # FIXME: Add line information
|
return Error('Must be real') # FIXME: Add line information
|
||||||
|
|
||||||
raise NotImplementedError
|
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]:
|
def constant(ctx: Context, inp: ourlang.Constant) -> Generator[ConstraintBase, None, None]:
|
||||||
if isinstance(inp, ourlang.ConstantPrimitive):
|
if isinstance(inp, ourlang.ConstantPrimitive):
|
||||||
# A constant by itself doesn't have any constraints
|
yield LiteralFitsConstraint(inp.type3, inp)
|
||||||
yield from ()
|
|
||||||
return
|
|
||||||
|
|
||||||
if isinstance(inp, ourlang.ConstantTuple):
|
|
||||||
# A constant by itself doesn't have any constraints
|
|
||||||
yield from ()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
raise NotImplementedError(constant, inp)
|
raise NotImplementedError(constant, inp)
|
||||||
@ -39,7 +33,19 @@ def expression(ctx: Context, inp: ourlang.Expression) -> Generator[ConstraintBas
|
|||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(inp, ourlang.VariableReference):
|
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
|
return
|
||||||
|
|
||||||
raise NotImplementedError(expression, inp)
|
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 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]:
|
def module_constant_def(ctx: Context, inp: ourlang.ModuleConstantDef) -> Generator[ConstraintBase, None, None]:
|
||||||
|
|
||||||
yield from constant(ctx, inp.constant)
|
yield from constant(ctx, inp.constant)
|
||||||
|
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')
|
||||||
# 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)
|
|
||||||
|
|
||||||
def module(ctx: Context, inp: ourlang.Module) -> Generator[ConstraintBase, None, None]:
|
def module(ctx: Context, inp: ourlang.Module) -> Generator[ConstraintBase, None, None]:
|
||||||
for cdef in inp.constant_defs.values():
|
for cdef in inp.constant_defs.values():
|
||||||
|
|||||||
@ -9,6 +9,8 @@ from .constraints import Error, RequireTypeSubstitutes
|
|||||||
from .constraintsgenerator import phasm_type3_generate_constraints
|
from .constraintsgenerator import phasm_type3_generate_constraints
|
||||||
from .types import PlaceholderForType, Type3
|
from .types import PlaceholderForType, Type3
|
||||||
|
|
||||||
|
MAX_RESTACK_COUNT = 10
|
||||||
|
|
||||||
class Type3Exception(BaseException):
|
class Type3Exception(BaseException):
|
||||||
"""
|
"""
|
||||||
Thrown when the Type3 system detects constraints that do not hold
|
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] = {}
|
placeholder_substitutes: Dict[PlaceholderForType, Type3] = {}
|
||||||
|
|
||||||
|
restack_counter = 0
|
||||||
|
|
||||||
error_list: List[Error] = []
|
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 = constraint_list.pop(0)
|
||||||
|
|
||||||
constraint.substitute_placeholders(placeholder_substitutes)
|
constraint.substitute_placeholders(placeholder_substitutes)
|
||||||
@ -36,6 +40,11 @@ def phasm_type3(inp: ourlang.Module) -> None:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if isinstance(check_result, RequireTypeSubstitutes):
|
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)
|
constraint_list.append(constraint)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -45,4 +54,3 @@ def phasm_type3(inp: ourlang.Module) -> None:
|
|||||||
raise Type3Exception(error_list)
|
raise Type3Exception(error_list)
|
||||||
|
|
||||||
# TODO: Implement type substitution on the AST
|
# TODO: Implement type substitution on the AST
|
||||||
print('placeholder_substitutes', placeholder_substitutes)
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user