List ideas. How do we keep it safe?
This commit is contained in:
parent
467d409d80
commit
109423fe34
@ -29,6 +29,17 @@ class OurType:
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError(self, 'alloc_size')
|
raise NotImplementedError(self, 'alloc_size')
|
||||||
|
|
||||||
|
class OurTypeAny(OurType):
|
||||||
|
"""
|
||||||
|
The Any type
|
||||||
|
|
||||||
|
In places where the types really does not matter, such as len([array])
|
||||||
|
"""
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def render(self) -> str:
|
||||||
|
raise Exception('Internal only')
|
||||||
|
|
||||||
class OurTypeNone(OurType):
|
class OurTypeNone(OurType):
|
||||||
"""
|
"""
|
||||||
The None (or Void) type
|
The None (or Void) type
|
||||||
@ -121,6 +132,20 @@ class OurTypeTuple(OurType):
|
|||||||
for x in self.members
|
for x in self.members
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class OurTypeList(OurType):
|
||||||
|
"""
|
||||||
|
The tuple type
|
||||||
|
"""
|
||||||
|
__slots__ = ('member_type', )
|
||||||
|
|
||||||
|
member_type: OurType
|
||||||
|
|
||||||
|
def __init__(self, member_type: OurType) -> None:
|
||||||
|
self.member_type = member_type
|
||||||
|
|
||||||
|
def render(self) -> str:
|
||||||
|
return f'[{self.member_type.render()}]'
|
||||||
|
|
||||||
class Expression:
|
class Expression:
|
||||||
"""
|
"""
|
||||||
An expression within a statement
|
An expression within a statement
|
||||||
@ -260,6 +285,9 @@ class UnaryOp(Expression):
|
|||||||
if self.operator in WEBASSEMBLY_BUILDIN_FLOAT_OPS:
|
if self.operator in WEBASSEMBLY_BUILDIN_FLOAT_OPS:
|
||||||
return f'{self.operator}({self.right.render()})'
|
return f'{self.operator}({self.right.render()})'
|
||||||
|
|
||||||
|
if self.operator == 'len':
|
||||||
|
return f'{self.operator}({self.right.render()})'
|
||||||
|
|
||||||
return f'{self.operator}{self.right.render()}'
|
return f'{self.operator}{self.right.render()}'
|
||||||
|
|
||||||
class FunctionCall(Expression):
|
class FunctionCall(Expression):
|
||||||
@ -327,6 +355,23 @@ class AccessTupleMember(Expression):
|
|||||||
def render(self) -> str:
|
def render(self) -> str:
|
||||||
return f'{self.varref.render()}[{self.member.idx}]'
|
return f'{self.varref.render()}[{self.member.idx}]'
|
||||||
|
|
||||||
|
class CreateList(Expression):
|
||||||
|
"""
|
||||||
|
Creates a list
|
||||||
|
"""
|
||||||
|
__slots__ = ('arguments', )
|
||||||
|
|
||||||
|
arguments: List[Expression]
|
||||||
|
|
||||||
|
def __init__(self, type_: OurTypeList) -> None:
|
||||||
|
super().__init__(type_)
|
||||||
|
|
||||||
|
self.arguments = []
|
||||||
|
|
||||||
|
def render(self) -> str:
|
||||||
|
mems = ', '.join(x.render() for x in self.arguments)
|
||||||
|
return f'[{mems}]'
|
||||||
|
|
||||||
class Statement:
|
class Statement:
|
||||||
"""
|
"""
|
||||||
A statement within a function
|
A statement within a function
|
||||||
@ -851,6 +896,20 @@ class OurVisitor:
|
|||||||
|
|
||||||
return VariableReference(act_type, node.id)
|
return VariableReference(act_type, node.id)
|
||||||
|
|
||||||
|
if isinstance(node, ast.List):
|
||||||
|
if not isinstance(node.ctx, ast.Load):
|
||||||
|
_raise_static_error(node, 'Must be load context')
|
||||||
|
|
||||||
|
if not isinstance(exp_type, OurTypeList):
|
||||||
|
_raise_static_error(node, f'Expression is expecting a {exp_type.render()}, not a list')
|
||||||
|
|
||||||
|
result_cl = CreateList(exp_type)
|
||||||
|
result_cl.arguments = [
|
||||||
|
self.visit_Module_FunctionDef_expr(module, function, our_locals, exp_type.member_type, arg_node)
|
||||||
|
for arg_node in node.elts
|
||||||
|
]
|
||||||
|
return result_cl
|
||||||
|
|
||||||
if isinstance(node, ast.Tuple):
|
if isinstance(node, ast.Tuple):
|
||||||
if not isinstance(node.ctx, ast.Load):
|
if not isinstance(node.ctx, ast.Load):
|
||||||
_raise_static_error(node, 'Must be load context')
|
_raise_static_error(node, 'Must be load context')
|
||||||
@ -900,6 +959,19 @@ 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 == 'len':
|
||||||
|
if not isinstance(exp_type, OurTypeInt32):
|
||||||
|
_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')
|
||||||
|
|
||||||
|
return UnaryOp(
|
||||||
|
exp_type,
|
||||||
|
'len',
|
||||||
|
self.visit_Module_FunctionDef_expr(module, function, our_locals, OurTypeList(OurTypeAny()), node.args[0]),
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if node.func.id not in module.functions:
|
if node.func.id not in module.functions:
|
||||||
_raise_static_error(node, 'Call to undefined function')
|
_raise_static_error(node, 'Call to undefined function')
|
||||||
@ -1034,6 +1106,17 @@ class OurVisitor:
|
|||||||
|
|
||||||
_raise_static_error(node, f'Unrecognized type {node.id}')
|
_raise_static_error(node, f'Unrecognized type {node.id}')
|
||||||
|
|
||||||
|
if isinstance(node, ast.List):
|
||||||
|
if not isinstance(node.ctx, ast.Load):
|
||||||
|
_raise_static_error(node, 'Must be load context')
|
||||||
|
|
||||||
|
if len(node.elts) != 1:
|
||||||
|
_raise_static_error(node, 'Must provide one type parameter')
|
||||||
|
|
||||||
|
return OurTypeList(
|
||||||
|
self.visit_type(module, node.elts[0])
|
||||||
|
)
|
||||||
|
|
||||||
if isinstance(node, ast.Tuple):
|
if isinstance(node, ast.Tuple):
|
||||||
if not isinstance(node.ctx, ast.Load):
|
if not isinstance(node.ctx, ast.Load):
|
||||||
_raise_static_error(node, 'Must be load context')
|
_raise_static_error(node, 'Must be load context')
|
||||||
|
|||||||
@ -366,6 +366,24 @@ def helper(v: (f32, f32, f32, )) -> f32:
|
|||||||
assert 3.74 < result.returned_value < 3.75
|
assert 3.74 < result.returned_value < 3.75
|
||||||
assert [] == result.log_int32_list
|
assert [] == result.log_int32_list
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', ['f32', 'f64'])
|
||||||
|
# @pytest.mark.xfail(reason='Working on it')
|
||||||
|
def test_list(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> i32:
|
||||||
|
return helper([1.0, 2.0, 3.0])
|
||||||
|
|
||||||
|
def helper(v: [{type_}]) -> i32:
|
||||||
|
return len(v)
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py, 'test_call').run_code()
|
||||||
|
|
||||||
|
assert 3 == result.returned_value
|
||||||
|
assert [] == result.log_int32_list
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@pytest.mark.integration_test
|
||||||
@pytest.mark.skip('SIMD support is but a dream')
|
@pytest.mark.skip('SIMD support is but a dream')
|
||||||
def test_tuple_i32x4():
|
def test_tuple_i32x4():
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user