Let’s embrace WebAssembly!

Presentation made at EuroPython 2018 - Edinburgh (by Almar Klein)

This Notebook is:

WASM has a compact binary format

And a human readable counterpart:

wasm
(module
    (type $print (func (param i32))
    (func $main
        (i32.const 42)
        (call $print)
    )
    (start $main)
)

It's safe

Because browsers.

Use case 1: Compile a subset of Python to WASM


In [ ]:
# in RISE mode, click <Shift>+<Enter> to execute a cell
def find_prime(nth):
    n = 0
    i = -1       
    while n < nth:
        i = i + 1        
        if i <= 1:
            continue  # nope
        elif i == 2:
            n = n + 1
        else:
            gotit = 1
            for j in range(2,  i//2+1):
                if i % j == 0:
                    gotit = 0
                    break
            if gotit == 1:
                n = n + 1    
    return i

In [ ]:
%time find_prime(1000)

Compiling 'find_prime()' to WASM

Note:

  • The python-to-wasm compiler is just a POC!
  • Assumes a (reliable) wasm-to-native compiler

In [ ]:
# in RISE mode, click <Shift>+<Enter> to execute a cell
from ppci import wasm

In [ ]:
from ppci.lang.python import python_to_wasm

def main():
    print(find_prime(1000))

m = python_to_wasm(main, find_prime)

In [ ]:
# WASM (somewhat) readable machine code
m.show()

In [ ]:
# WASM binary format
m.show_bytes()

In [ ]:
# WASM interface
m.show_interface()

Run in Browser


In [ ]:
wasm.run_wasm_in_notebook(m)

Run in NodeJS


In [ ]:
wasm.run_wasm_in_node(m)

Compile 'find_prime()' to WASM then to Machine code


In [ ]:
# this doesn't currently work on a Python 32 bit, when run on a Windows 64 bit
@wasm.wasmify
def find_prime2(nth):
    n = 0
    i = -1       
    while n < nth:
        i = i + 1        
        if i <= 1:
            continue  # nope
        elif i == 2:
            n = n + 1
        else:
            gotit = 1
            for j in range(2,  i//2+1):
                if i % j == 0:
                    gotit = 0
                    break
            if gotit == 1:
                n = n + 1    
    return i

In [ ]:
%time find_prime2(1000)

Use case 2: Python as a platform to bind and run WASM modules

... and allow that code to call into Python functions

the Rocket game from github.com/aochagavia

The rocket game is in a single binary WASM file (58 KB)


In [ ]:
from ppci import wasm

m = wasm.Module(open(r'wasm/rocket.wasm', 'rb'))
m

In [ ]:
m.show_interface()

rocket wasm controlled per javascript

abstract of rocket.html file

same rocket wasm controlled per python


In [ ]:
# abstract of rocket_qt.py (do not run)
class PythonRocketGame:
    
    # ...
    
    def wasm_sin(self, a:float) -> float:
        return math.sin(a)
    
    def wasm_cos(self, a:float) -> float:
        return math.cos(a)
    
    def wasm_Math_atan(self, a:float) -> float:
        return math.atan(a)
    
    def wasm_clear_screen(self) -> None:
        # ...
    
    def wasm_draw_bullet(self, x:float, y:float) -> None:
        # ...
    
    def wasm_draw_enemy(self, x:float, y:float) -> None:
        # ...
    
    def wasm_draw_particle(self, x:float, y:float, a:float) -> None:
        # ...
    
    def wasm_draw_player(self, x:float, y:float, a:float) -> None:
       # ...
    
    def wasm_draw_score(self, score:float) -> None:
        # ...

Run Rocket in Python with Qt


In [ ]:
from rocket_qt import QtRocketGame
game = QtRocketGame()

In [ ]:
# you may have to switch to the QT window appearing on the side of your browser session
game.run()

This game is not that hard to play ...

Let's make an AI!

Game in rust compiled in WASM

AI in C compiled in WASM

Glue in Python


In [ ]:
# let's write the AI in C
print(open('wasm/ai2.c', 'rt').read())

In [ ]:
# use https://wasdk.github.io/WasmFiddle/ to convert ai.c in ai2.wasm
from ppci import wasm
ai2 = wasm.Module(open('wasm/ai2.wasm', 'rb'))

In [ ]:
ai2.show_interface()

In [ ]:
from rocket_ai import AiRocketGame
game = AiRocketGame(ai2)
game.run()

Wrapping up ...

WASM is coming, and its awesome!

  • Open, low-level, fast, compact and safe
  • Already works in most browsers
  • Not limited to the web

We Pythonista's should embrace it!

  • E.g. run a Python VM in the browser
  • E.g. compile subset of Python to fast, crossplatform code
  • E.g. use Python as a platform to bind and execute WASM modules

Thanks!