WASM demo - manual


In [ ]:
import wasmfun as wf

Let's start with a simple example


In [ ]:
instructions = [('f64.const', 42), ('call', 'print_ln'),
                ('call', 'make_background_blue')]

Wrap these in a function, and in a module


In [ ]:
m = wf.Module(
    wf.ImportedFuncion('print_ln', ['f64'], [], 'js', 'print_ln'),
    wf.ImportedFuncion('make_background_blue', [], [], 'js', 'make_background_blue'),
    wf.Function('$main', params=[], returns=[], locals=[], instructions=instructions),
    )

A module contains of a series of sections


In [ ]:
m.show()

WASM is a compact binary format. Note the \x00asm at the start:


In [ ]:
print(m.to_bytes())
print(len(m.to_bytes()))

Prepare the browser for running our WASM module

The host environment (in this case JavaScript can provide functions that WASM can call


In [ ]:
JS = """
function print_ln(x) {
    var el = document.getElementById('wasm_output');
    el.innerHTML += String(x).replace('\\n', '<br>') + '<br>';
}

function make_background_blue () {
    document.body.style = 'background:#5AF;'
}

var providedfuncs = {
    print_ln: print_ln,
    make_background_blue: make_background_blue,
    alert: window.alert,
};

function compile_my_wasm(wasm_data) {
    var m = new WebAssembly.Module(wasm_data);
    var i = new WebAssembly.Instance(m, {js: providedfuncs});
}
"""

Define a Python funtion to transfer the module to JS and run it


In [ ]:
from IPython.display import display, HTML, Javascript
import uuid

def run_wasm(m):
    id = uuid.uuid1().hex
    js = JS.replace('wasm_output', 'wasm_output_' + id)
    js += "compile_my_wasm(new Uint8Array(%s));" % str(list(m.to_bytes()))
    
    display(HTML("<div style='border: 2px solid blue;' id='wasm_output_%s'>WASM output goes here<br></div>" % id))
    display(Javascript(js))

Now we can run our module


In [ ]:
run_wasm(m)

Next, let's write a loop


In [ ]:
instructions = [
    ('loop', 'emptyblock'),
        # write iter
        ('get_local', 0), ('call', 'print_ln'),
        # Increase iter
        ('f64.const', 1), ('get_local', 0), ('f64.add'),
        ('tee_local', 0), ('f64.const', 10),
        ('f64.lt'), ('br_if', 0),
    ('end'),
    ]

In [ ]:
m = wf.Module(
    wf.ImportedFuncion('print_ln', ['f64'], [], 'js', 'print_ln'),
    wf.Function('$main', params=[], returns=[], locals=['f64'], instructions=instructions),
    )

In [ ]:
m.to_bytes()

In [ ]:
run_wasm(m)

We can also execute our module on the desktop (via Node)


In [ ]:
wf.run_wasm_in_node(m)

In [ ]: