MVP #1
@ -21,6 +21,11 @@ def type_(inp: ourlang.OurType) -> wasm.OurType:
|
|||||||
if isinstance(inp, ourlang.OurTypeFloat64):
|
if isinstance(inp, ourlang.OurTypeFloat64):
|
||||||
return wasm.OurTypeFloat64()
|
return wasm.OurTypeFloat64()
|
||||||
|
|
||||||
|
if isinstance(inp, ourlang.Struct):
|
||||||
|
# Structs are passed as pointer
|
||||||
|
# And pointers are i32
|
||||||
|
return wasm.OurTypeInt32()
|
||||||
|
|
||||||
raise NotImplementedError(type_, inp)
|
raise NotImplementedError(type_, inp)
|
||||||
|
|
||||||
OPERATOR_MAP = {
|
OPERATOR_MAP = {
|
||||||
@ -89,6 +94,19 @@ def expression(inp: ourlang.Expression) -> Statements:
|
|||||||
yield wasm.Statement('call', '${}'.format(inp.function.name))
|
yield wasm.Statement('call', '${}'.format(inp.function.name))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if isinstance(inp, ourlang.AccessStructMember):
|
||||||
|
# FIXME: Properly implement this
|
||||||
|
# inp.type.render() is also a hack that doesn't really work consistently
|
||||||
|
if not isinstance(inp.type, (
|
||||||
|
ourlang.OurTypeInt32, ourlang.OurTypeFloat32,
|
||||||
|
ourlang.OurTypeInt64, ourlang.OurTypeFloat64,
|
||||||
|
)):
|
||||||
|
raise NotImplementedError(inp, inp.type)
|
||||||
|
|
||||||
|
yield from expression(inp.varref)
|
||||||
|
yield wasm.Statement(inp.type.render() + '.load', 'offset=' + str(inp.member.offset))
|
||||||
|
return
|
||||||
|
|
||||||
raise NotImplementedError(expression, inp)
|
raise NotImplementedError(expression, inp)
|
||||||
|
|
||||||
def statement_return(inp: ourlang.StatementReturn) -> Statements:
|
def statement_return(inp: ourlang.StatementReturn) -> Statements:
|
||||||
@ -125,6 +143,21 @@ def function_argument(inp: Tuple[str, ourlang.OurType]) -> wasm.Param:
|
|||||||
return (inp[0], type_(inp[1]), )
|
return (inp[0], type_(inp[1]), )
|
||||||
|
|
||||||
def function(inp: ourlang.Function) -> wasm.Function:
|
def function(inp: ourlang.Function) -> wasm.Function:
|
||||||
|
if isinstance(inp, ourlang.StructConstructor):
|
||||||
|
statements = [
|
||||||
|
*_generate_struct_constructor(inp)
|
||||||
|
]
|
||||||
|
locals_ = [
|
||||||
|
('___new_reference___addr', wasm.OurTypeInt32(), ),
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
statements = [
|
||||||
|
x
|
||||||
|
for y in inp.statements
|
||||||
|
for x in statement(y)
|
||||||
|
]
|
||||||
|
locals_ = [] # TODO
|
||||||
|
|
||||||
return wasm.Function(
|
return wasm.Function(
|
||||||
inp.name,
|
inp.name,
|
||||||
inp.exported,
|
inp.exported,
|
||||||
@ -132,20 +165,63 @@ def function(inp: ourlang.Function) -> wasm.Function:
|
|||||||
function_argument(x)
|
function_argument(x)
|
||||||
for x in inp.posonlyargs
|
for x in inp.posonlyargs
|
||||||
],
|
],
|
||||||
[], # TODO
|
locals_,
|
||||||
type_(inp.returns),
|
type_(inp.returns),
|
||||||
[
|
statements
|
||||||
x
|
|
||||||
for y in inp.statements
|
|
||||||
for x in statement(y)
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def module(inp: ourlang.Module) -> wasm.Module:
|
def module(inp: ourlang.Module) -> wasm.Module:
|
||||||
result = wasm.Module()
|
result = wasm.Module()
|
||||||
|
|
||||||
result.functions = [*map(
|
result.functions = [
|
||||||
function, inp.functions.values(),
|
_generate_allocator(inp),
|
||||||
)]
|
] + [
|
||||||
|
function(x)
|
||||||
|
for x in inp.functions.values()
|
||||||
|
]
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def _generate_allocator(mod: ourlang.Module) -> wasm.Function:
|
||||||
|
return wasm.Function(
|
||||||
|
'___new_reference___',
|
||||||
|
False,
|
||||||
|
[
|
||||||
|
('alloc_size', type_(mod.types['i32']), ),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
('result', type_(mod.types['i32']), ),
|
||||||
|
],
|
||||||
|
type_(mod.types['i32']),
|
||||||
|
[
|
||||||
|
wasm.Statement('i32.const', '0'),
|
||||||
|
wasm.Statement('i32.const', '0'),
|
||||||
|
wasm.Statement('i32.load'),
|
||||||
|
wasm.Statement('local.tee', '$result', comment='Address for this call'),
|
||||||
|
wasm.Statement('local.get', '$alloc_size'),
|
||||||
|
wasm.Statement('i32.add'),
|
||||||
|
wasm.Statement('i32.store', comment='Address for the next call'),
|
||||||
|
wasm.Statement('local.get', '$result'),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
def _generate_struct_constructor(inp: ourlang.StructConstructor) -> Statements:
|
||||||
|
yield wasm.Statement('i32.const', str(inp.struct.alloc_size()))
|
||||||
|
yield wasm.Statement('call', '$___new_reference___')
|
||||||
|
|
||||||
|
yield wasm.Statement('local.set', '$___new_reference___addr')
|
||||||
|
|
||||||
|
for member in inp.struct.members:
|
||||||
|
# FIXME: Properly implement this
|
||||||
|
# inp.type.render() is also a hack that doesn't really work consistently
|
||||||
|
if not isinstance(member.type, (
|
||||||
|
ourlang.OurTypeInt32, ourlang.OurTypeFloat32,
|
||||||
|
ourlang.OurTypeInt64, ourlang.OurTypeFloat64,
|
||||||
|
)):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
yield wasm.Statement('local.get', '$___new_reference___addr')
|
||||||
|
yield wasm.Statement('local.get', f'${member.name}')
|
||||||
|
yield wasm.Statement(f'{member.type.render()}.store', 'offset=' + str(member.offset))
|
||||||
|
|
||||||
|
yield wasm.Statement('local.get', '$___new_reference___addr')
|
||||||
|
|||||||
@ -217,7 +217,9 @@ class UnaryOp(Expression):
|
|||||||
operator: str
|
operator: str
|
||||||
right: Expression
|
right: Expression
|
||||||
|
|
||||||
def __init__(self, operator: str, right: Expression) -> None:
|
def __init__(self, type_: OurType, operator: str, right: Expression) -> None:
|
||||||
|
super().__init__(type_)
|
||||||
|
|
||||||
self.operator = operator
|
self.operator = operator
|
||||||
self.right = right
|
self.right = right
|
||||||
|
|
||||||
@ -234,6 +236,8 @@ class FunctionCall(Expression):
|
|||||||
arguments: List[Expression]
|
arguments: List[Expression]
|
||||||
|
|
||||||
def __init__(self, function: 'Function') -> None:
|
def __init__(self, function: 'Function') -> None:
|
||||||
|
super().__init__(function.returns)
|
||||||
|
|
||||||
self.function = function
|
self.function = function
|
||||||
self.arguments = []
|
self.arguments = []
|
||||||
|
|
||||||
@ -258,6 +262,8 @@ class AccessStructMember(Expression):
|
|||||||
member: 'StructMember'
|
member: 'StructMember'
|
||||||
|
|
||||||
def __init__(self, varref: VariableReference, member: 'StructMember') -> None:
|
def __init__(self, varref: VariableReference, member: 'StructMember') -> None:
|
||||||
|
super().__init__(member.type)
|
||||||
|
|
||||||
self.varref = varref
|
self.varref = varref
|
||||||
self.member = member
|
self.member = member
|
||||||
|
|
||||||
@ -275,6 +281,8 @@ class AccessTupleMember(Expression):
|
|||||||
member_type: 'OurType'
|
member_type: 'OurType'
|
||||||
|
|
||||||
def __init__(self, varref: VariableReference, member_idx: int, member_type: 'OurType') -> None:
|
def __init__(self, varref: VariableReference, member_idx: int, member_type: 'OurType') -> None:
|
||||||
|
super().__init__(member_type)
|
||||||
|
|
||||||
self.varref = varref
|
self.varref = varref
|
||||||
self.member_idx = member_idx
|
self.member_idx = member_idx
|
||||||
self.member_type = member_type
|
self.member_type = member_type
|
||||||
@ -286,13 +294,14 @@ class TupleCreation(Expression):
|
|||||||
"""
|
"""
|
||||||
Create a tuple instance
|
Create a tuple instance
|
||||||
"""
|
"""
|
||||||
__slots__ = ('type', 'members', )
|
__slots__ = ('members', )
|
||||||
|
|
||||||
type: OurTypeTuple
|
type: OurTypeTuple
|
||||||
members: List[Expression]
|
members: List[Expression]
|
||||||
|
|
||||||
def __init__(self, type_: OurTypeTuple) -> None:
|
def __init__(self, type_: OurTypeTuple) -> None:
|
||||||
self.type = type_
|
super().__init__(type_)
|
||||||
|
|
||||||
self.members = []
|
self.members = []
|
||||||
|
|
||||||
def render(self) -> str:
|
def render(self) -> str:
|
||||||
@ -488,6 +497,12 @@ class Struct(OurType):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def alloc_size(self) -> int:
|
||||||
|
return sum(
|
||||||
|
x.type.alloc_size()
|
||||||
|
for x in self.members
|
||||||
|
)
|
||||||
|
|
||||||
class Module:
|
class Module:
|
||||||
"""
|
"""
|
||||||
A module is a file and consists of functions
|
A module is a file and consists of functions
|
||||||
@ -747,6 +762,7 @@ class OurVisitor:
|
|||||||
raise NotImplementedError(f'Operator {node.op}')
|
raise NotImplementedError(f'Operator {node.op}')
|
||||||
|
|
||||||
return UnaryOp(
|
return UnaryOp(
|
||||||
|
exp_type,
|
||||||
operator,
|
operator,
|
||||||
self.visit_Module_FunctionDef_expr(module, function, our_locals, exp_type, node.operand),
|
self.visit_Module_FunctionDef_expr(module, function, our_locals, exp_type, node.operand),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -199,7 +199,7 @@ class Visitor:
|
|||||||
params.append((arg.arg, self._get_type(arg.annotation), ))
|
params.append((arg.arg, self._get_type(arg.annotation), ))
|
||||||
|
|
||||||
locals_: List[wasm.Param] = [
|
locals_: List[wasm.Param] = [
|
||||||
('___new_reference___addr', self._get_type('i32')), # For the ___new_reference__ method
|
('___new_reference___addr', self._get_type('i32')), # For the ___new_reference___ method
|
||||||
]
|
]
|
||||||
|
|
||||||
return wasm.Function(node.name, exported, params, locals_, result, [])
|
return wasm.Function(node.name, exported, params, locals_, result, [])
|
||||||
|
|||||||
@ -232,6 +232,18 @@ class Function:
|
|||||||
'\n '.join(x.generate() for x in self.statements),
|
'\n '.join(x.generate() for x in self.statements),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class ModuleMemory:
|
||||||
|
def __init__(self, data: bytes = b'') -> None:
|
||||||
|
self.data = data
|
||||||
|
|
||||||
|
def generate(self) -> str:
|
||||||
|
return '(memory 1)\n (data (memory 0) (i32.const 0) "{}")\n'.format(
|
||||||
|
''.join(
|
||||||
|
f'\\{x:02x}'
|
||||||
|
for x in self.data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
class Module:
|
class Module:
|
||||||
"""
|
"""
|
||||||
Represents a Web Assembly module
|
Represents a Web Assembly module
|
||||||
@ -239,13 +251,14 @@ class Module:
|
|||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.imports: List[Import] = []
|
self.imports: List[Import] = []
|
||||||
self.functions: List[Function] = []
|
self.functions: List[Function] = []
|
||||||
|
self.memory = ModuleMemory(b'\x04') # For ___new_reference___
|
||||||
|
|
||||||
def generate(self) -> str:
|
def generate(self) -> str:
|
||||||
"""
|
"""
|
||||||
Generates the text version
|
Generates the text version
|
||||||
"""
|
"""
|
||||||
return '(module\n (memory 1)\n (data (memory 0) (i32.const 0) {})\n {}\n {})\n'.format(
|
return '(module\n {}\n {}\n {})\n'.format(
|
||||||
'"\\04\\00\\00\\00"',
|
self.memory.generate(),
|
||||||
'\n '.join(x.generate() for x in self.imports),
|
'\n '.join(x.generate() for x in self.imports),
|
||||||
'\n '.join(x.generate() for x in self.functions),
|
'\n '.join(x.generate() for x in self.functions),
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user