Re-implemented if statements
This commit is contained in:
parent
da6e306fad
commit
0fa076bb93
@ -273,6 +273,20 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
|
||||
|
||||
assert isinstance(inp.type3, type3types.Type3), type3types.TYPE3_ASSERTION_ERROR
|
||||
# FIXME: Re-implement build-in operators
|
||||
# Maybe operator_annotation is the way to go
|
||||
# Maybe the older stuff below that is the way to go
|
||||
|
||||
operator_annotation = f'({inp.operator}) :: {inp.left.type3:s} -> {inp.right.type3:s} -> {inp.type3:s}'
|
||||
if operator_annotation == '(>) :: i32 -> i32 -> bool':
|
||||
wgn.add_statement('i32.gt_s')
|
||||
return
|
||||
|
||||
if operator_annotation == '(<) :: u64 -> u64 -> bool':
|
||||
wgn.add_statement('i64.lt_u')
|
||||
return
|
||||
if operator_annotation == '(==) :: u64 -> u64 -> bool':
|
||||
wgn.add_statement('i64.eq')
|
||||
return
|
||||
|
||||
if inp.type3 == type3types.u8:
|
||||
if operator := U8_OPERATOR_MAP.get(inp.operator, None):
|
||||
@ -321,7 +335,7 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
|
||||
wgn.add_statement(f'f64.{operator}')
|
||||
return
|
||||
|
||||
raise NotImplementedError(expression, inp.type3, inp.operator)
|
||||
raise NotImplementedError(expression, inp.operator, inp.left.type3, inp.right.type3, inp.type3)
|
||||
|
||||
if isinstance(inp, ourlang.UnaryOp):
|
||||
expression(wgn, inp.right)
|
||||
|
||||
@ -123,6 +123,9 @@ class BinaryOp(Expression):
|
||||
self.left = left
|
||||
self.right = right
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'BinaryOp({repr(self.operator)}, {repr(self.left)}, {repr(self.right)})'
|
||||
|
||||
class FunctionCall(Expression):
|
||||
"""
|
||||
A function call expression within a statement
|
||||
|
||||
@ -231,11 +231,11 @@ class MustImplementTypeClassConstraint(ConstraintBase):
|
||||
type3: types.Type3OrPlaceholder
|
||||
|
||||
DATA = {
|
||||
'u8': {'BitWiseOperation', 'BasicMathOperation'},
|
||||
'u32': {'BitWiseOperation', 'BasicMathOperation'},
|
||||
'u64': {'BitWiseOperation', 'BasicMathOperation'},
|
||||
'i32': {'BasicMathOperation'},
|
||||
'i64': {'BasicMathOperation'},
|
||||
'u8': {'BitWiseOperation', 'BasicMathOperation', 'EqualComparison', 'StrictPartialOrder'},
|
||||
'u32': {'BitWiseOperation', 'BasicMathOperation', 'EqualComparison', 'StrictPartialOrder'},
|
||||
'u64': {'BitWiseOperation', 'BasicMathOperation', 'EqualComparison', 'StrictPartialOrder'},
|
||||
'i32': {'BasicMathOperation', 'EqualComparison', 'StrictPartialOrder'},
|
||||
'i64': {'BasicMathOperation', 'EqualComparison', 'StrictPartialOrder'},
|
||||
'bytes': {'Foldable', 'Sized'},
|
||||
'f32': {'BasicMathOperation', 'FloatingPoint'},
|
||||
'f64': {'BasicMathOperation', 'FloatingPoint'},
|
||||
|
||||
@ -17,19 +17,21 @@ from .constraints import (
|
||||
|
||||
from . import types as type3types
|
||||
|
||||
ConstraintGenerator = Generator[ConstraintBase, None, None]
|
||||
|
||||
def phasm_type3_generate_constraints(inp: ourlang.Module) -> List[ConstraintBase]:
|
||||
ctx = Context()
|
||||
|
||||
return [*module(ctx, inp)]
|
||||
|
||||
def constant(ctx: Context, inp: ourlang.Constant) -> Generator[ConstraintBase, None, None]:
|
||||
def constant(ctx: Context, inp: ourlang.Constant) -> ConstraintGenerator:
|
||||
if isinstance(inp, (ourlang.ConstantPrimitive, ourlang.ConstantTuple, ourlang.ConstantStruct)):
|
||||
yield LiteralFitsConstraint(inp.type3, inp)
|
||||
return
|
||||
|
||||
raise NotImplementedError(constant, inp)
|
||||
|
||||
def expression(ctx: Context, inp: ourlang.Expression) -> Generator[ConstraintBase, None, None]:
|
||||
def expression(ctx: Context, inp: ourlang.Expression) -> ConstraintGenerator:
|
||||
if isinstance(inp, ourlang.Constant):
|
||||
yield from constant(ctx, inp)
|
||||
return
|
||||
@ -87,6 +89,28 @@ def expression(ctx: Context, inp: ourlang.Expression) -> Generator[ConstraintBas
|
||||
comment=f'({inp.operator}) :: a -> a -> a')
|
||||
return
|
||||
|
||||
if inp.operator == '==':
|
||||
yield from expression(ctx, inp.left)
|
||||
yield from expression(ctx, inp.right)
|
||||
|
||||
yield MustImplementTypeClassConstraint('EqualComparison', inp.left.type3)
|
||||
yield SameTypeConstraint(inp.left.type3, inp.right.type3,
|
||||
comment=f'({inp.operator}) :: a -> a -> bool')
|
||||
yield SameTypeConstraint(inp.type3, type3types.bool_,
|
||||
comment=f'({inp.operator}) :: a -> a -> bool')
|
||||
return
|
||||
|
||||
if inp.operator in ('<', '>'):
|
||||
yield from expression(ctx, inp.left)
|
||||
yield from expression(ctx, inp.right)
|
||||
|
||||
yield MustImplementTypeClassConstraint('StrictPartialOrder', inp.left.type3)
|
||||
yield SameTypeConstraint(inp.left.type3, inp.right.type3,
|
||||
comment=f'({inp.operator}) :: a -> a -> bool')
|
||||
yield SameTypeConstraint(inp.type3, type3types.bool_,
|
||||
comment=f'({inp.operator}) :: a -> a -> bool')
|
||||
return
|
||||
|
||||
raise NotImplementedError(expression, inp)
|
||||
|
||||
if isinstance(inp, ourlang.FunctionCall):
|
||||
@ -141,26 +165,50 @@ def expression(ctx: Context, inp: ourlang.Expression) -> Generator[ConstraintBas
|
||||
|
||||
raise NotImplementedError(expression, inp)
|
||||
|
||||
def function(ctx: Context, inp: ourlang.Function) -> Generator[ConstraintBase, None, None]:
|
||||
def statement_return(ctx: Context, fun: ourlang.Function, inp: ourlang.StatementReturn) -> ConstraintGenerator:
|
||||
yield from expression(ctx, inp.value)
|
||||
|
||||
yield SameTypeConstraint(fun.returns_type3, inp.value.type3,
|
||||
comment=f'The type of the value returned from function {fun.name} should match its return type')
|
||||
|
||||
def statement_if(ctx: Context, fun: ourlang.Function, inp: ourlang.StatementIf) -> ConstraintGenerator:
|
||||
yield from expression(ctx, inp.test)
|
||||
|
||||
yield SameTypeConstraint(inp.test.type3, type3types.bool_,
|
||||
comment=f'Must pass a boolean expression to if')
|
||||
|
||||
for stmt in inp.statements:
|
||||
yield from statement(ctx, fun, stmt)
|
||||
|
||||
for stmt in inp.else_statements:
|
||||
yield from statement(ctx, fun, stmt)
|
||||
|
||||
def statement(ctx: Context, fun: ourlang.Function, inp: ourlang.Statement) -> ConstraintGenerator:
|
||||
if isinstance(inp, ourlang.StatementReturn):
|
||||
yield from statement_return(ctx, fun, inp)
|
||||
return
|
||||
|
||||
if isinstance(inp, ourlang.StatementIf):
|
||||
yield from statement_if(ctx, fun, inp)
|
||||
return
|
||||
|
||||
raise NotImplementedError(statement, fun, inp)
|
||||
|
||||
def function(ctx: Context, inp: ourlang.Function) -> ConstraintGenerator:
|
||||
assert not inp.imported
|
||||
|
||||
if isinstance(inp, ourlang.StructConstructor):
|
||||
return
|
||||
|
||||
if len(inp.statements) != 1 or not isinstance(inp.statements[0], ourlang.StatementReturn):
|
||||
raise NotImplementedError('Functions with not just a return statement')
|
||||
for stmt in inp.statements:
|
||||
yield from statement(ctx, inp, stmt)
|
||||
|
||||
yield from expression(ctx, inp.statements[0].value)
|
||||
|
||||
yield SameTypeConstraint(inp.returns_type3, inp.statements[0].value.type3,
|
||||
comment=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) -> ConstraintGenerator:
|
||||
yield from constant(ctx, inp.constant)
|
||||
yield SameTypeConstraint(inp.type3, inp.constant.type3,
|
||||
comment=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]:
|
||||
def module(ctx: Context, inp: ourlang.Module) -> ConstraintGenerator:
|
||||
for cdef in inp.constant_defs.values():
|
||||
yield from module_constant_def(ctx, cdef)
|
||||
|
||||
|
||||
@ -202,6 +202,11 @@ none = PrimitiveType3('none')
|
||||
The none type, for when functions simply don't return anything. e.g., IO().
|
||||
"""
|
||||
|
||||
bool_ = PrimitiveType3('bool')
|
||||
"""
|
||||
The bool type, either True or False
|
||||
"""
|
||||
|
||||
u8 = PrimitiveType3('u8')
|
||||
"""
|
||||
The unsigned 8-bit integer type.
|
||||
@ -280,6 +285,7 @@ determined length, and each argument can be different.
|
||||
|
||||
LOOKUP_TABLE: Dict[str, Type3] = {
|
||||
'none': none,
|
||||
'bool': bool_,
|
||||
'u8': u8,
|
||||
'u32': u32,
|
||||
'u64': u64,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user