def test_type1(): """ Test canoncocal form of import and func and inline typedefs. """ # The canonical form CODE0 = dedent(""" (module (type $0 (func (param i32))) (type $1 (func (param i32 i32) (result i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $0))) (start $main) (func $add (type $1) (get_local 0) (get_local 1) (i32.add) ) (func $main (type $2) (i32.const 4) (i32.const 3) (call $add) (call $print) ) ) """) # Test main code m0 = Module(CODE0) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 if has_node(): assert run_wasm_in_node(m0, True) == '7' # Abbreviation: inline typedefs CODE1 = """ (module (import "js" "print_ln" (func $print (param i32))) (start $main) (func $add (param i32 i32) (result i32) (get_local 0) (get_local 1) (i32.add) ) (func $main (i32.const 4) (i32.const 3) (call $add) (call $print) ) ) """ m1 = Module(CODE1) assert m1.to_string() == CODE0 assert m1.to_bytes() == b0
def test_global1(): CODE0 = dedent(r""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (global $foo i32 i32.const 7) (start $main) (func $main (type $2) global.get $foo call $print) ) """) # Test main code m0 = Module(CODE0) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 if has_node(): assert run_wasm_in_node(m0, True) == '7'
def test_table1(): # The canonical form CODE0 = dedent(r""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (table $0 2 2 funcref) (start $main) (elem i32.const 0 $f1 $f2) (func $f1 (type $2) i32.const 101 call $print) (func $f2 (type $2) i32.const 102 call $print) (func $main (type $2) i32.const 0 call_indirect (type $2) i32.const 1 call_indirect (type $2)) ) """) # Test main code m0 = Module(CODE0) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 html_report = 'table_and_element_compilation_report.html' with open(html_report, 'w') as f, HtmlReportGenerator(f) as reporter: printed_numbers = [] def print_ln(x: int) -> None: printed_numbers.append(x) imports = { 'js': { 'print_ln': print_ln, }, } instantiate(m0, imports, target='python', reporter=reporter) assert [101, 102] == printed_numbers if is_platform_supported(): printed_numbers = [] def print_ln(x: int) -> None: printed_numbers.append(x) imports = { 'js': { 'print_ln': print_ln, }, } instantiate(m0, imports, target='native', reporter=reporter) assert [101, 102] == printed_numbers if has_node(): assert run_wasm_in_node(m0, True) == '101\n102' # Abbreviation: imported table m3 = Module('(module (table $t1 (import "foo" "bar_table1") funcref) )') assert m3.to_string() == dedent(""" (module (import "foo" "bar_table1" (table $t1 funcref)) ) """) m3 = Module('(module (table (import "foo" "bar_table1") 2 3 funcref) )') assert m3.to_string() == dedent(""" (module (import "foo" "bar_table1" (table 2 3 funcref)) ) """) # Abbeviation: inline data and unspecified (default) alignment CODE1 = r""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (table funcref (elem $f1 $f2)) (start $main) (func $f1 (type $2) (i32.const 101) (call $print) ) (func $f2 (type $2) (i32.const 102) (call $print) ) (func $main (type $2) (i32.const 0) (call_indirect (type $2)) (i32.const 1) (call_indirect (type $2)) ) ) """ m1 = Module(CODE1) assert m1.to_string() == CODE0 assert m1.to_bytes() == b0
def test_func1(): # The canonical form CODE0 = dedent(""" (module (type $0 (func (param i32))) (type $1 (func (param i32 i32) (result i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $0))) (start $main) (func $add (type $1) (get_local 0) (get_local 1) (i32.add) ) (func $main (type $2) (local $foo i32) (i32.const 4) (i32.const 3) (call $add) (set_local $foo) (get_local $foo) (call $print) ) ) """) # Test main code m0 = Module(CODE0) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 # TODO: figure out what is wrong below: if False: printed_numbers = [] def print_ln(x: int) -> None: printed_numbers.append(x) imports = { 'js': { 'print_ln': print_ln, }, } instantiate(m0, imports, target='python') assert [7] == printed_numbers if has_node(): assert run_wasm_in_node(m0, True) == '7' # Abbreviation: inline typedefs CODE1 = """ (module (import "js" "print_ln" (func $print (param i32))) (start $main) (func $add (param i32 i32) (result i32) (get_local 0) (get_local 1) (i32.add) ) (func $main (local $foo i32) (set_local $foo (call $add (i32.const 4) (i32.const 3) ) ) (call $print (get_local $foo) ) ) ) """ m1 = Module(CODE1) assert m1.to_string() == CODE0 # look at the indentation! assert m1.to_bytes() == b0
def tst_module1(): instructions1 = [ ('loop', None, 'emptyblock'), # print iter ('get_local', 0), ('call', '$print'), # Increase iter ('f64.const', 1), ('get_local', 0), ('f64.add', ), ('tee_local', 0), ('f64.const', 10), ('f64.lt', ), ('br_if', 0), ('end', ), ] instructions2 = [ ('loop', 'emptyblock'), # write iter ('get_local', 0), ('call', '$print'), # Increase iter ('f64.const', 1), ('get_local', 0), ('f64.add', ), ('tee_local', 0), ('f64.const', 10), ('f64.lt', ), ('br_if', 0), ('end', ), ] CODE0 = dedent(""" (module (type $print (func (param f64))) (type $1 (func)) (import "js" "print_ln" (func $print (type $print))) (start $main) (func $main (type $1) (local f64) loop (get_local 0) (call $print) (f64.const 1) (get_local 0) (f64.add) (tee_local 0) (f64.const 10) (f64.lt) (br_if 0) (end) ) ) """) # ----- Test main code m0 = wasm.Module(CODE0) assert m0.to_string() == CODE0 b0 = m0.to_bytes() if wasm.has_node(): assert wasm.run_wasm_in_node(m0, True) == '0\n1\n2\n3\n4\n5\n6\n7\n8\n9' # ----- Abbreviated text m1 = wasm.Module(""" (module (import "js" "print_ln" (func $print (param f64))) (start $main) (func $main (local f64) (loop ;; print iter (get_local 0) (call $print) ;; increase iter (f64.const 1) (get_local 0) (f64.add) (tee_local 0) (f64.const 10) (f64.lt) (br_if 0) ) ) )""") assert m1.to_bytes() == b0 # ------ Tuples with tuple instructions m2 = wasm.Module( '(import "js" "print_ln" (func $print (param f64)))', ('start', '$main'), ('func', '$main', ('local', 'f64')) + tuple(instructions1), ) assert m2.to_bytes() == b0 # ------ Tuples with Instruction instances m3 = wasm.Module( '(import "js" "print_ln" (func $print (param f64)))', ('start', '$main'), ('func', '$main', ('local', 'f64')) + tuple(instructions2), ) assert m3.to_bytes() == b0 # ------ Definition instances with tuple instructions m4 = wasm.Module( wasm.Type('$print_sig', [(0, 'f64')], []), wasm.Type('$main_sig', [], []), wasm.Import( 'js', 'print_ln', 'func', '$print', ('$print_sig', ), ), wasm.Start('$main'), wasm.Func('$main', wasm.Ref('type', name='$main_sig'), [(None, 'f64')], instructions1), ) assert m4.to_bytes() == b0 # ------ Definition instances with Instruction instances m5 = wasm.Module( wasm.Type('$print_sig', [(0, 'f64')], []), wasm.Type('$main_sig', [], []), wasm.Import( 'js', 'print_ln', 'func', '$print', ('$print_sig', ), ), wasm.Start('$main'), wasm.Func('$main', wasm.Ref('type', name='$main_sig'), [(None, 'f64')], instructions2), ) assert m5.to_bytes() == b0 # ------ From module elements m6 = wasm.Module(*m0) assert m6.to_bytes() == b0 # ------ to_string() m7 = wasm.Module(m0.to_string()) assert m7.to_bytes() == b0 # ------ to_bytes() m8 = wasm.Module(b0) assert m8.to_bytes() == b0
def test_instructions1(): """ Test canoncocal form of import and func and inline typedefs. """ # The canonical form CODE0 = dedent(""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (start $main) (func $main (type $2) (i32.const 1) (if) (i32.const 4) (i32.const 3) (i32.add) (call $print) (else) (i32.const 5) (call $print) (end) ) ) """) # Test main code m0 = Module(CODE0) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 if has_node(): assert run_wasm_in_node(m0, True) == '7' # Variant 1 - no inentation, nested test for if CODE1 = dedent(""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (start $main) (func $main (type $2) (if (i32.const 1)) (i32.const 4) (i32.const 3) (i32.add) (call $print) (else) (i32.const 5) (call $print) (end) ) ) """) m1 = Module(CODE1) assert m1.to_string() == CODE0 assert m1.to_bytes() == b0 # Variant 2 - nesting all the way CODE2 = dedent(""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (start $main) (func $main (type $2) (if (i32.const 1) (i32.const 4) (i32.const 3) (i32.add) (call $print) (else) (i32.const 5) (call $print) ) ) ) """) m2 = Module(CODE2) assert m2.to_string() == CODE0 assert m2.to_bytes() == b0 # Variant 3 - leave out the else clause # This is described as an "abbreviation", but it seems that we don't # have to always output an else clause in binary form either. CODE3 = dedent(""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (start $main) (func $main (type $2) (if (i32.const 1) (i32.const 4) (i32.const 3) (i32.add) (call $print) ) ) ) """) m3 = Module(CODE3) assert m3.to_string() != CODE0 assert m3.to_bytes() != b0 if has_node(): assert run_wasm_in_node(m3, True) == '7'
def test_type2(): """ Test inline typedefs with various number of args and results. """ # Canonical form CODE0 = dedent(""" (module (type $0 (func (param i32))) (type $1 (func (param i32) (result i32))) (type $2 (func (result i32))) (type $3 (func)) (import "js" "print_ln" (func $print (type $0))) (start $main) (func $test_11 (type $1) (i32.const 111) (call $print) (i32.const 0) ) (func $test_10 (type $0) (i32.const 110) (call $print) ) (func $test_01 (type $2) (i32.const 101) (call $print) (i32.const 0) ) (func $test_00 (type $3) (i32.const 100) (call $print) ) (func $main (type $3) (i32.const 0) (call $test_11) (drop) (i32.const 0) (call $test_10) (call $test_01) (drop) (call $test_00) ) ) """) # Test main code m0 = Module(CODE0) assert m0.to_string() == CODE0 b0 = m0.to_bytes() if has_node(): assert run_wasm_in_node(m0, True) == '111\n110\n101\n100' # Abbreviated CODE1 = """ (module (import "js" "print_ln" (func $print (param i32))) (start $main) (func $test_11 (param i32) (result i32) (i32.const 111) (call $print) (i32.const 0) ) (func $test_10 (param i32) (i32.const 110) (call $print) ) (func $test_01 (result i32) (i32.const 101) (call $print) (i32.const 0) ) (func $test_00 (i32.const 100) (call $print) ) (func $main (i32.const 0) (call $test_11) (drop) (i32.const 0) (call $test_10) (call $test_01) (drop) (call $test_00) ) ) """ m1 = Module(CODE1) assert m1.to_string() == CODE0 assert m1.to_bytes() == b0
wasm.components.Start(wasm.components.Ref('func', name='$main', index=1)), wasm.components.Func( '$main', wasm.components.Ref('type', name='$main_sig', index=1), [(None, 'f64')], instructions), ) # Result is exactly the same! assert wa3.to_bytes() == wa1.to_bytes() ## Recursion ... # The text representation of a module produces an exact copy assert wasm.Module(wa1.to_string()).to_bytes() == wa1.to_bytes() # Using the elements (definitions) of a module to create a new module too assert wasm.Module(*[d for d in wa1]).to_bytes() == wa1.to_bytes() # We can reconstruct the module from its binary form assert wasm.Module(wa1.to_bytes()).to_bytes() == wa1.to_bytes() ## Let's run it wasm.run_wasm_in_node(wa1) import webbrowser wasm.export_wasm_example(__file__[:-3] + '.html', wa1.to_string(), wa1) webbrowser.open(__file__[:-3] + '.html')
def test_memory1(): # The canonical form CODE0 = dedent(r""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (memory $0 1 1) (start $main) (func $main (type $2) i32.const 0 i32.load8_u call $print i32.const 1 i32.load8_u call $print) (data i32.const 0 "\04\03\02") ) """) # Test main code m0 = Module(CODE0) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 printed_numbers = [] def print_ln(x: int) -> None: printed_numbers.append(x) imports = { 'js': { 'print_ln': print_ln, } } instantiate(m0, imports=imports, target='python') assert [4, 3] == printed_numbers if has_node(): assert run_wasm_in_node(m0, True) == '4\n3' # Abbreviation: imported memory m3 = Module('(module (memory $m1 (import "foo" "bar_mem1") 1) )') assert m3.to_string() == dedent(""" (module (import "foo" "bar_mem1" (memory $m1 1)) ) """) m3 = Module('(module (memory (import "foo" "bar_mem1") 2 3) )') assert m3.to_string() == dedent(""" (module (import "foo" "bar_mem1" (memory 2 3)) ) """) # Abbeviation: inline data and unspecified (default) alignment CODE1 = r""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (memory (data "\04\03\02")) (start $main) (func $main (type $2) i32.const 0 i32.load8_u call $print i32.const 1 i32.load8_u call $print ) ) """ m1 = Module(CODE1) assert m1.to_string() == CODE0 assert m1.to_bytes() == b0