MVP #1
@ -39,6 +39,23 @@ class Visitor:
|
|||||||
if isinstance(name, ast.expr):
|
if isinstance(name, ast.expr):
|
||||||
if isinstance(name, ast.Name):
|
if isinstance(name, ast.Name):
|
||||||
name = name.id
|
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:
|
else:
|
||||||
raise NotImplementedError(f'_get_type(ast.{type(name).__name__})')
|
raise NotImplementedError(f'_get_type(ast.{type(name).__name__})')
|
||||||
|
|
||||||
@ -332,11 +349,17 @@ class Visitor:
|
|||||||
if isinstance(node, ast.Constant):
|
if isinstance(node, ast.Constant):
|
||||||
return self.visit_Constant(exp_type, node)
|
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):
|
if isinstance(node, ast.Name):
|
||||||
return self.visit_Name(wlocals, exp_type, node)
|
return self.visit_Name(wlocals, exp_type, node)
|
||||||
|
|
||||||
if isinstance(node, ast.Attribute):
|
if isinstance(node, ast.Tuple):
|
||||||
return self.visit_Attribute(module, wlocals, exp_type, node)
|
return self.visit_Tuple(wlocals, exp_type, node)
|
||||||
|
|
||||||
raise NotImplementedError(node)
|
raise NotImplementedError(node)
|
||||||
|
|
||||||
@ -470,7 +493,7 @@ class Visitor:
|
|||||||
This instantiates the class
|
This instantiates the class
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# TODO: malloc call
|
# TODO: free call
|
||||||
|
|
||||||
yield wasm.Statement('i32.const', str(cls.alloc_size()))
|
yield wasm.Statement('i32.const', str(cls.alloc_size()))
|
||||||
yield wasm.Statement('call', '$___new_reference___')
|
yield wasm.Statement('call', '$___new_reference___')
|
||||||
@ -586,6 +609,77 @@ class Visitor:
|
|||||||
yield wasm.Statement('local.get', '$' + node.value.id)
|
yield wasm.Statement('local.get', '$' + node.value.id)
|
||||||
yield wasm.Statement(exp_type.to_wasm() + '.load', 'offset=' + str(member.offset))
|
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:
|
def visit_Name(self, wlocals: WLocals, exp_type: wasm.OurType, node: ast.Name) -> StatementGenerator:
|
||||||
"""
|
"""
|
||||||
Visits a Name node as (part of) an expression
|
Visits a Name node as (part of) an expression
|
||||||
|
|||||||
@ -80,6 +80,27 @@ class OurTypeClass(OurType):
|
|||||||
def alloc_size(self) -> int:
|
def alloc_size(self) -> int:
|
||||||
return sum(x.type.alloc_size() for x in self.members)
|
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]
|
Param = Tuple[str, OurType]
|
||||||
|
|
||||||
|
|||||||
@ -317,3 +317,20 @@ def helper(shape1: Rectangle, shape2: Rectangle) -> i32:
|
|||||||
|
|
||||||
assert 545 == result.returned_value
|
assert 545 == result.returned_value
|
||||||
assert [] == result.log_int32_list
|
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