MVP #1
@ -39,6 +39,23 @@ class Visitor:
|
||||
if isinstance(name, ast.expr):
|
||||
if isinstance(name, ast.Name):
|
||||
name = name.id
|
||||
elif isinstance(name, ast.Subscript) and isinstance(name.value, ast.Name) and name.value.id == 'Tuple':
|
||||
assert isinstance(name.ctx, ast.Load)
|
||||
assert isinstance(name.slice, ast.Index)
|
||||
assert isinstance(name.slice.value, ast.Tuple)
|
||||
|
||||
args: List[wasm.TupleMember] = []
|
||||
offset = 0
|
||||
for name_arg in name.slice.value.elts:
|
||||
arg = wasm.TupleMember(
|
||||
self._get_type(name_arg),
|
||||
offset
|
||||
)
|
||||
|
||||
args.append(arg)
|
||||
offset += arg.type.alloc_size()
|
||||
|
||||
return wasm.OurTypeTuple(args)
|
||||
else:
|
||||
raise NotImplementedError(f'_get_type(ast.{type(name).__name__})')
|
||||
|
||||
@ -332,11 +349,17 @@ class Visitor:
|
||||
if isinstance(node, ast.Constant):
|
||||
return self.visit_Constant(exp_type, node)
|
||||
|
||||
if isinstance(node, ast.Attribute):
|
||||
return self.visit_Attribute(module, wlocals, exp_type, node)
|
||||
|
||||
if isinstance(node, ast.Subscript):
|
||||
return self.visit_Subscript(module, wlocals, exp_type, node)
|
||||
|
||||
if isinstance(node, ast.Name):
|
||||
return self.visit_Name(wlocals, exp_type, node)
|
||||
|
||||
if isinstance(node, ast.Attribute):
|
||||
return self.visit_Attribute(module, wlocals, exp_type, node)
|
||||
if isinstance(node, ast.Tuple):
|
||||
return self.visit_Tuple(wlocals, exp_type, node)
|
||||
|
||||
raise NotImplementedError(node)
|
||||
|
||||
@ -470,7 +493,7 @@ class Visitor:
|
||||
This instantiates the class
|
||||
"""
|
||||
|
||||
# TODO: malloc call
|
||||
# TODO: free call
|
||||
|
||||
yield wasm.Statement('i32.const', str(cls.alloc_size()))
|
||||
yield wasm.Statement('call', '$___new_reference___')
|
||||
@ -586,6 +609,77 @@ class Visitor:
|
||||
yield wasm.Statement('local.get', '$' + node.value.id)
|
||||
yield wasm.Statement(exp_type.to_wasm() + '.load', 'offset=' + str(member.offset))
|
||||
|
||||
def visit_Subscript(
|
||||
self,
|
||||
module: wasm.Module,
|
||||
wlocals: WLocals,
|
||||
exp_type: wasm.OurType,
|
||||
node: ast.Subscript,
|
||||
) -> StatementGenerator:
|
||||
"""
|
||||
Visits an Subscript node as (part of) an expression
|
||||
"""
|
||||
if not isinstance(node.value, ast.Name):
|
||||
raise NotImplementedError
|
||||
|
||||
if not isinstance(node.slice, ast.Index):
|
||||
raise NotImplementedError
|
||||
|
||||
if not isinstance(node.slice.value, ast.Constant):
|
||||
raise NotImplementedError
|
||||
|
||||
if not isinstance(node.slice.value.value, int):
|
||||
raise NotImplementedError
|
||||
|
||||
if not isinstance(node.ctx, ast.Load):
|
||||
raise NotImplementedError
|
||||
|
||||
tpl_idx = node.slice.value.value
|
||||
|
||||
tpl = wlocals[node.value.id]
|
||||
|
||||
assert isinstance(tpl, wasm.OurTypeTuple), f'Cannot take index of {tpl}'
|
||||
|
||||
assert 0 <= tpl_idx < len(tpl.members), \
|
||||
f'Tuple index out of bounds; {node.value.id} has {len(tpl.members)} members'
|
||||
|
||||
member = tpl.members[tpl_idx]
|
||||
|
||||
yield wasm.Statement('local.get', '$' + node.value.id)
|
||||
yield wasm.Statement(exp_type.to_wasm() + '.load', 'offset=' + str(member.offset))
|
||||
|
||||
def visit_Tuple(
|
||||
self,
|
||||
wlocals: WLocals,
|
||||
exp_type: wasm.OurType,
|
||||
node: ast.Tuple,
|
||||
) -> StatementGenerator:
|
||||
"""
|
||||
Visits an Tuple node as (part of) an expression
|
||||
"""
|
||||
assert isinstance(exp_type, wasm.OurTypeTuple), 'Expression is not expecting a tuple'
|
||||
|
||||
# TODO: free call
|
||||
|
||||
tpl = exp_type
|
||||
|
||||
yield wasm.Statement('nop', comment='Start tuple allocation')
|
||||
|
||||
yield wasm.Statement('i32.const', str(tpl.alloc_size()))
|
||||
yield wasm.Statement('call', '$___new_reference___')
|
||||
yield wasm.Statement('local.set', '$___new_reference___addr', comment='Allocate for tuple')
|
||||
|
||||
for member, arg in zip(tpl.members, node.elts):
|
||||
if not isinstance(arg, ast.Constant):
|
||||
raise NotImplementedError('TODO: Non-const tuple members')
|
||||
|
||||
yield wasm.Statement('local.get', '$___new_reference___addr')
|
||||
yield wasm.Statement(f'{member.type.to_wasm()}.const', str(arg.value))
|
||||
yield wasm.Statement(f'{member.type.to_wasm()}.store', 'offset=' + str(member.offset),
|
||||
comment='Write tuple value to memory')
|
||||
|
||||
yield wasm.Statement('local.get', '$___new_reference___addr', comment='Store tuple address on stack')
|
||||
|
||||
def visit_Name(self, wlocals: WLocals, exp_type: wasm.OurType, node: ast.Name) -> StatementGenerator:
|
||||
"""
|
||||
Visits a Name node as (part of) an expression
|
||||
|
||||
@ -80,6 +80,27 @@ class OurTypeClass(OurType):
|
||||
def alloc_size(self) -> int:
|
||||
return sum(x.type.alloc_size() for x in self.members)
|
||||
|
||||
class TupleMember:
|
||||
"""
|
||||
Represents a tuple member
|
||||
"""
|
||||
def __init__(self, type_: OurType, offset: int) -> None:
|
||||
self.type = type_
|
||||
self.offset = offset
|
||||
|
||||
class OurTypeTuple(OurType):
|
||||
"""
|
||||
Represents a tuple
|
||||
"""
|
||||
def __init__(self, members: List[TupleMember]) -> None:
|
||||
self.members = members
|
||||
|
||||
def to_wasm(self) -> str:
|
||||
return 'i32' # WASM uses 32 bit pointers
|
||||
|
||||
def alloc_size(self) -> int:
|
||||
return sum(x.type.alloc_size() for x in self.members)
|
||||
|
||||
|
||||
Param = Tuple[str, OurType]
|
||||
|
||||
|
||||
@ -317,3 +317,20 @@ def helper(shape1: Rectangle, shape2: Rectangle) -> i32:
|
||||
|
||||
assert 545 == result.returned_value
|
||||
assert [] == result.log_int32_list
|
||||
|
||||
@pytest.mark.integration_test
|
||||
def test_tuple_int():
|
||||
code_py = """
|
||||
|
||||
@exported
|
||||
def testEntry() -> i32:
|
||||
return helper((24, 57, 80, ))
|
||||
|
||||
def helper(vector: Tuple[i32, i32, i32]) -> i32:
|
||||
return vector[0] + vector[1] + vector[2]
|
||||
"""
|
||||
|
||||
result = Suite(code_py, 'test_call').run_code()
|
||||
|
||||
assert 161 == result.returned_value
|
||||
assert [] == result.log_int32_list
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user