First uint cast, more options for folding

This commit is contained in:
Johan B.W. de Vries 2022-08-16 20:38:41 +02:00
parent ad6ca71c53
commit 75d7e05519
4 changed files with 50 additions and 5 deletions

View File

@ -97,6 +97,9 @@ def expression(inp: ourlang.Expression) -> str:
or inp.operator in ourlang.WEBASSEMBLY_BUILDIN_BYTES_OPS): or inp.operator in ourlang.WEBASSEMBLY_BUILDIN_BYTES_OPS):
return f'{inp.operator}({expression(inp.right)})' return f'{inp.operator}({expression(inp.right)})'
if inp.operator == 'cast':
return f'{type_(inp.type)}({expression(inp.right)})'
return f'{inp.operator}{expression(inp.right)}' return f'{inp.operator}{expression(inp.right)}'
if isinstance(inp, ourlang.BinaryOp): if isinstance(inp, ourlang.BinaryOp):

View File

@ -219,6 +219,11 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
wgn.i32.load() wgn.i32.load()
return return
if inp.operator == 'cast':
if isinstance(inp.type, typing.TypeUInt32) and isinstance(inp.right.type, typing.TypeUInt8):
# Nothing to do, you can use an u8 value as a u32 no problem
return
raise NotImplementedError(expression, inp.type, inp.operator) raise NotImplementedError(expression, inp.type, inp.operator)
if isinstance(inp, ourlang.FunctionCall): if isinstance(inp, ourlang.FunctionCall):

View File

@ -380,6 +380,20 @@ class OurVisitor:
'sqrt', 'sqrt',
self.visit_Module_FunctionDef_expr(module, function, our_locals, exp_type, node.args[0]), self.visit_Module_FunctionDef_expr(module, function, our_locals, exp_type, node.args[0]),
) )
elif node.func.id == 'u32':
if not isinstance(exp_type, TypeUInt32):
_raise_static_error(node, f'Cannot make {node.func.id} result in {exp_type}')
if 1 != len(node.args):
_raise_static_error(node, f'Function {node.func.id} requires 1 arguments but {len(node.args)} are given')
# FIXME: This is a stub, proper casting is todo
return UnaryOp(
exp_type,
'cast',
self.visit_Module_FunctionDef_expr(module, function, our_locals, module.types['u8'], node.args[0]),
)
elif node.func.id == 'len': elif node.func.id == 'len':
if not isinstance(exp_type, TypeInt32): if not isinstance(exp_type, TypeInt32):
_raise_static_error(node, f'Cannot make {node.func.id} result in {exp_type}') _raise_static_error(node, f'Cannot make {node.func.id} result in {exp_type}')
@ -398,14 +412,9 @@ class OurVisitor:
# In the future, we should probably infer the type of the second argument, # In the future, we should probably infer the type of the second argument,
# and use it as expected types for the other u8s and the Iterable[u8] (i.e. bytes) # and use it as expected types for the other u8s and the Iterable[u8] (i.e. bytes)
if not isinstance(exp_type, TypeUInt8):
_raise_static_error(node, f'Cannot make {node.func.id} result in {exp_type} - not implemented yet')
if 3 != len(node.args): if 3 != len(node.args):
_raise_static_error(node, f'Function {node.func.id} requires 3 arguments but {len(node.args)} are given') _raise_static_error(node, f'Function {node.func.id} requires 3 arguments but {len(node.args)} are given')
t_u8 = module.types['u8']
# TODO: This is not generic # TODO: This is not generic
subnode = node.args[0] subnode = node.args[0]
if not isinstance(subnode, ast.Name): if not isinstance(subnode, ast.Name):
@ -415,6 +424,19 @@ class OurVisitor:
if subnode.id not in module.functions: if subnode.id not in module.functions:
_raise_static_error(subnode, 'Reference to undefined function') _raise_static_error(subnode, 'Reference to undefined function')
func = module.functions[subnode.id] func = module.functions[subnode.id]
if 2 != len(func.posonlyargs):
_raise_static_error(node, f'Function {node.func.id} requires a function with 2 arguments but a function with {len(func.posonlyargs)} args is given')
if exp_type.__class__ != func.returns.__class__:
_raise_static_error(node, f'Expected {codestyle.type_(exp_type)}, {func.name} actually returns {codestyle.type_(func.returns)}')
if func.returns.__class__ != func.posonlyargs[0][1].__class__:
_raise_static_error(node, f'Expected a foldable function, {func.name} returns a {codestyle.type_(func.returns)} but expects a {codestyle.type_(func.posonlyargs[0][1])}')
t_u8 = module.types['u8']
if t_u8.__class__ != func.posonlyargs[1][1].__class__:
_raise_static_error(node, 'Only folding over bytes (u8) is supported at this time')
return Fold( return Fold(
exp_type, exp_type,

View File

@ -63,3 +63,18 @@ def testEntry(a: bytes, b: bytes) -> u8:
result = suite.run_code(b'\x55\x0F', b'\x33\x80') result = suite.run_code(b'\x55\x0F', b'\x33\x80')
assert 233 == result.returned_value assert 233 == result.returned_value
@pytest.mark.integration_test
def test_foldl_3():
code_py = """
def xor(l: u32, r: u8) -> u32:
return l ^ u32(r)
@exported
def testEntry(a: bytes) -> u32:
return foldl(xor, 0, a)
"""
suite = Suite(code_py)
result = suite.run_code(b'\x55\x0F\x33\x80')
assert 233 == result.returned_value