Beispiel #1
0
def wasmify(ast):
    """ Turn ast of this toy language into WASM.
    """
    # Generate WASM instructions from the ast
    instructions = [('f64.const', 0)
                    ]  # the initial value of the number is zero
    for op in ast:
        instructions.append(('f64.const', op.operand.value))
        if op.value == '+':
            instructions.append(('f64.add'))
        elif op.value == '-':
            instructions.append(('f64.sub'))
        elif op.value == '*':
            instructions.append(('f64.mul'))
        elif op.value == '/':
            instructions.append(('f64.div'))

    # Add call to print the result
    instructions.append(('call', 0))

    # Put instructions in a the main function of a WASM module
    module = wf.Module(
        wf.ImportedFuncion('print_ln', ['f64'], [], 'js', 'print_ln'),
        wf.Function('$main', [], [], [], instructions),
    )
    return module
Beispiel #2
0
def simplepy2wasm(code):
    """ Compile Python code to wasm, by using Python's ast parser
    and compiling a very specific subset to WASM instructions.
    """
    # Verify / convert input
    if isinstance(code, ast.AST):
        root = code
    elif isinstance(code, str):
        root = ast.parse(code)
    else:
        raise TypeError('simplepy2wasm() requires (str) code or AST.')
    if not isinstance(root, ast.Module):
        raise ValueError(
            'simplepy2wasm() expecteded root node to be a ast.Module.')

    # Compile to instructions
    ctx = Context()
    for node in root.body:
        _compile_expr(node, ctx, False)
    locals = ['f64' for i in ctx.names]

    # Produce wasm
    module = wf.Module(
        wf.ImportedFuncion('print_ln', ['f64'], [], 'js', 'print_ln'),
        wf.ImportedFuncion('perf_counter', [], ['f64'], 'js', 'perf_counter'),
        wf.Function('$main', [], [], locals, ctx.instructions),
    )
    return module
Beispiel #3
0
    def to_wasm(self):
        """ Create wasm Function object.
        """
        arg_types = self._arg_types
        ret_types = self._ret_types or []
        locals = ['f64' for i in self.names]

        return wf.Function(self._name, arg_types, ret_types, locals,
                           self.instructions)
Beispiel #4
0
def brainfuck2wasm(code):
    """ Compile brainfuck code to a WASM module.
    """
    commands = [c for c in code if c in '><+-.,[]']
    
    instructions = _commands2instructions(commands)
    
    module = wf.Module(
        wf.ImportedFuncion('print_charcode', ['i32'], [], 'js', 'print_charcode'),
        wf.Function('$main', [], [], ['i32'], instructions),
        wf.MemorySection((1, 1)),  # 1 page of 64KiB > 30000 minimum for Brainfuck
        wf.DataSection(),  # no initial data
        )
    return module
Beispiel #5
0
    def to_wasm(self):
        """ Create wasm Module object.
        """
        # This is also the main function
        locals = ['f64' for i in self.names]
        main_func = wf.Function('$main', [], [], locals, self.instructions)

        # Add imported funcs
        funcs = []
        funcs.append(
            wf.ImportedFuncion('print_ln', ['f64'], [], 'js', 'print_ln'))
        funcs.append(
            wf.ImportedFuncion('perf_counter', [], ['f64'], 'js',
                               'perf_counter'))

        # Add main funcs and other funcs
        funcs.append(main_func)
        for ctx in self.all_functions[1:]:
            funcs.append(ctx.to_wasm())

        # Compose module
        return wf.Module(*funcs)
Beispiel #6
0
# These instructions are equivalent. The latter might be easier to write thanks
# to autocompletion, but the former looks nicer IMO
instructions = [(I.loop, 'emptyblock'), (I.get_local, 0), (I.call, 'print_ln'),
                (I.f64.const, 1), (I.get_local, 0), (I.f64.add),
                (I.tee_local, 0), (I.f64.const, 10), (I.f64.lt), (I.br_if, 0),
                (I.end)]

# Compose functions into a module
root = wf.Module(
    wf.ImportedFuncion('alert', ['f64'], [], 'js', 'alert'),
    wf.ImportedFuncion('print_ln', ['f64'], [], 'js', 'print_ln'),
    wf.Function(
        'add',
        params=['f64', 'f64'],
        returns=['f64'],
        locals=[],
        instructions=[('get_local', 0), ('get_local', 1), ('f64.add')],
    ),
    wf.Function('$main',
                params=[],
                returns=[],
                locals=['f64'],
                instructions=instructions),
)

# For reference, one could also write it like this, using an explicit TypeSection
# and CodeSection. It needs more work to get the binding right, which in the above
# is done automatically.
#
# root = wf.Module(