Re-implemented if statements

This commit is contained in:
Johan B.W. de Vries 2023-01-06 15:59:22 +01:00
parent da6e306fad
commit 0fa076bb93
5 changed files with 89 additions and 18 deletions

View File

@ -273,6 +273,20 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
assert isinstance(inp.type3, type3types.Type3), type3types.TYPE3_ASSERTION_ERROR assert isinstance(inp.type3, type3types.Type3), type3types.TYPE3_ASSERTION_ERROR
# FIXME: Re-implement build-in operators # 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 inp.type3 == type3types.u8:
if operator := U8_OPERATOR_MAP.get(inp.operator, None): 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}') wgn.add_statement(f'f64.{operator}')
return 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): if isinstance(inp, ourlang.UnaryOp):
expression(wgn, inp.right) expression(wgn, inp.right)

View File

@ -123,6 +123,9 @@ class BinaryOp(Expression):
self.left = left self.left = left
self.right = right self.right = right
def __repr__(self) -> str:
return f'BinaryOp({repr(self.operator)}, {repr(self.left)}, {repr(self.right)})'
class FunctionCall(Expression): class FunctionCall(Expression):
""" """
A function call expression within a statement A function call expression within a statement

View File

@ -231,11 +231,11 @@ class MustImplementTypeClassConstraint(ConstraintBase):
type3: types.Type3OrPlaceholder type3: types.Type3OrPlaceholder
DATA = { DATA = {
'u8': {'BitWiseOperation', 'BasicMathOperation'}, 'u8': {'BitWiseOperation', 'BasicMathOperation', 'EqualComparison', 'StrictPartialOrder'},
'u32': {'BitWiseOperation', 'BasicMathOperation'}, 'u32': {'BitWiseOperation', 'BasicMathOperation', 'EqualComparison', 'StrictPartialOrder'},
'u64': {'BitWiseOperation', 'BasicMathOperation'}, 'u64': {'BitWiseOperation', 'BasicMathOperation', 'EqualComparison', 'StrictPartialOrder'},
'i32': {'BasicMathOperation'}, 'i32': {'BasicMathOperation', 'EqualComparison', 'StrictPartialOrder'},
'i64': {'BasicMathOperation'}, 'i64': {'BasicMathOperation', 'EqualComparison', 'StrictPartialOrder'},
'bytes': {'Foldable', 'Sized'}, 'bytes': {'Foldable', 'Sized'},
'f32': {'BasicMathOperation', 'FloatingPoint'}, 'f32': {'BasicMathOperation', 'FloatingPoint'},
'f64': {'BasicMathOperation', 'FloatingPoint'}, 'f64': {'BasicMathOperation', 'FloatingPoint'},

View File

@ -17,19 +17,21 @@ from .constraints import (
from . import types as type3types from . import types as type3types
ConstraintGenerator = Generator[ConstraintBase, None, None]
def phasm_type3_generate_constraints(inp: ourlang.Module) -> List[ConstraintBase]: def phasm_type3_generate_constraints(inp: ourlang.Module) -> List[ConstraintBase]:
ctx = Context() ctx = Context()
return [*module(ctx, inp)] 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)): if isinstance(inp, (ourlang.ConstantPrimitive, ourlang.ConstantTuple, ourlang.ConstantStruct)):
yield LiteralFitsConstraint(inp.type3, inp) yield LiteralFitsConstraint(inp.type3, inp)
return return
raise NotImplementedError(constant, inp) 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): if isinstance(inp, ourlang.Constant):
yield from constant(ctx, inp) yield from constant(ctx, inp)
return return
@ -87,6 +89,28 @@ def expression(ctx: Context, inp: ourlang.Expression) -> Generator[ConstraintBas
comment=f'({inp.operator}) :: a -> a -> a') comment=f'({inp.operator}) :: a -> a -> a')
return 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) raise NotImplementedError(expression, inp)
if isinstance(inp, ourlang.FunctionCall): if isinstance(inp, ourlang.FunctionCall):
@ -141,26 +165,50 @@ def expression(ctx: Context, inp: ourlang.Expression) -> Generator[ConstraintBas
raise NotImplementedError(expression, inp) 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 assert not inp.imported
if isinstance(inp, ourlang.StructConstructor): if isinstance(inp, ourlang.StructConstructor):
return return
if len(inp.statements) != 1 or not isinstance(inp.statements[0], ourlang.StatementReturn): for stmt in inp.statements:
raise NotImplementedError('Functions with not just a return statement') yield from statement(ctx, inp, stmt)
yield from expression(ctx, inp.statements[0].value) def module_constant_def(ctx: Context, inp: ourlang.ModuleConstantDef) -> ConstraintGenerator:
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]:
yield from constant(ctx, inp.constant) yield from constant(ctx, inp.constant)
yield SameTypeConstraint(inp.type3, inp.constant.type3, 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') 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(): for cdef in inp.constant_defs.values():
yield from module_constant_def(ctx, cdef) yield from module_constant_def(ctx, cdef)

View File

@ -202,6 +202,11 @@ none = PrimitiveType3('none')
The none type, for when functions simply don't return anything. e.g., IO(). 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') u8 = PrimitiveType3('u8')
""" """
The unsigned 8-bit integer type. The unsigned 8-bit integer type.
@ -280,6 +285,7 @@ determined length, and each argument can be different.
LOOKUP_TABLE: Dict[str, Type3] = { LOOKUP_TABLE: Dict[str, Type3] = {
'none': none, 'none': none,
'bool': bool_,
'u8': u8, 'u8': u8,
'u32': u32, 'u32': u32,
'u64': u64, 'u64': u64,