149 lines
3.7 KiB
Python
149 lines
3.7 KiB
Python
"""
|
|
Python classes for storing the representation of Web Assembly code
|
|
"""
|
|
|
|
from typing import Iterable, List, Optional, Tuple, Union
|
|
|
|
Param = Tuple[str, str]
|
|
|
|
class Import:
|
|
"""
|
|
Represents a Web Assembly import
|
|
"""
|
|
def __init__(
|
|
self,
|
|
module: str,
|
|
name: str,
|
|
intname: str,
|
|
params: Iterable[Param],
|
|
) -> None:
|
|
self.module = module
|
|
self.name = name
|
|
self.intname = intname
|
|
self.params = [*params]
|
|
self.result: str = 'None'
|
|
|
|
def generate(self) -> str:
|
|
"""
|
|
Generates the text version
|
|
"""
|
|
return '(import "{}" "{}" (func ${}{}))'.format(
|
|
self.module,
|
|
self.name,
|
|
self.intname,
|
|
''.join(' (param {})'.format(x[1]) for x in self.params)
|
|
)
|
|
|
|
class Statement:
|
|
"""
|
|
Represents a Web Assembly statement
|
|
"""
|
|
def __init__(self, name: str, *args: str, comment: Optional[str] = None):
|
|
self.name = name
|
|
self.args = args
|
|
self.comment = comment
|
|
|
|
def generate(self) -> str:
|
|
"""
|
|
Generates the text version
|
|
"""
|
|
args = ' '.join(self.args)
|
|
comment = f' ;; {self.comment}' if self.comment else ''
|
|
|
|
return f'{self.name} {args}{comment}'
|
|
|
|
class Function:
|
|
"""
|
|
Represents a Web Assembly function
|
|
"""
|
|
def __init__(
|
|
self,
|
|
name: str,
|
|
exported: bool,
|
|
params: Iterable[Param],
|
|
locals_: Iterable[Param],
|
|
result: Optional[str],
|
|
statements: Iterable[Statement],
|
|
) -> None:
|
|
self.name = name
|
|
self.exported = exported
|
|
self.params = [*params]
|
|
self.locals = [*locals_]
|
|
self.result = result
|
|
self.statements = [*statements]
|
|
|
|
def generate(self) -> str:
|
|
"""
|
|
Generates the text version
|
|
"""
|
|
header = ('(export "{}")' if self.exported else '${}').format(self.name)
|
|
|
|
for nam, typ in self.params:
|
|
header += f' (param ${nam} {typ})'
|
|
|
|
if self.result:
|
|
header += f' (result {self.result})'
|
|
|
|
for nam, typ in self.locals:
|
|
header += f' (local ${nam} {typ})'
|
|
|
|
return '(func {}\n {}\n )'.format(
|
|
header,
|
|
'\n '.join(x.generate() for x in self.statements),
|
|
)
|
|
|
|
class Constant:
|
|
"""
|
|
TODO
|
|
"""
|
|
def __init__(self, value: Union[None, bool, int, float]) -> None:
|
|
self.value = value
|
|
|
|
class ClassMember:
|
|
"""
|
|
Represents a Web Assembly class member
|
|
"""
|
|
def __init__(self, name: str, type_: str, offset: int, default: Optional[Constant]) -> None:
|
|
self.name = name
|
|
self.type = type_
|
|
self.offset = offset
|
|
self.default = default
|
|
|
|
def alloc_size(self) -> int:
|
|
SIZE_MAP = {
|
|
'i32': 4,
|
|
'i64': 4,
|
|
}
|
|
|
|
return SIZE_MAP[self.type]
|
|
|
|
class Class:
|
|
"""
|
|
Represents a Web Assembly class
|
|
"""
|
|
def __init__(self, name: str, members: List[ClassMember]) -> None:
|
|
self.name = name
|
|
self.members = members
|
|
|
|
def alloc_size(self) -> int:
|
|
return sum(x.alloc_size() for x in self.members)
|
|
|
|
class Module:
|
|
"""
|
|
Represents a Web Assembly module
|
|
"""
|
|
def __init__(self) -> None:
|
|
self.imports: List[Import] = []
|
|
self.functions: List[Function] = []
|
|
self.classes: List[Class] = []
|
|
|
|
def generate(self) -> str:
|
|
"""
|
|
Generates the text version
|
|
"""
|
|
return '(module\n (memory 1)\n (data (memory 0) (i32.const 0) {})\n {}\n {})\n'.format(
|
|
'"\\04\\00\\00\\00"',
|
|
'\n '.join(x.generate() for x in self.imports),
|
|
'\n '.join(x.generate() for x in self.functions),
|
|
)
|