def test_read_wat(): for text in (TEXT1, TEXT2): m = Module(text) m.to_string() b = m.to_bytes() assert isinstance(b, bytes)
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_memory_i32_load_behavior(load_op, mem): source = ('module', ('func', ('export', 'my_func'), ('result', 'i32'), load_op), ('memory', 1), ('data', ('i32.const', 0), mem)) m = Module(source) assert_equal_behavior(m)
def test_memory_i64_store_behavior(store_op, mem): source = ('module', ('func', ('export', 'my_func'), store_op), ('memory', ('export', 'mem'), 1), ('data', ('i32.const', 0), mem)) m = Module(source) assert_equal_memory(m)
def tst_expression_behavior(v64, mem): # assume(s != 0) # print('code', v64, v32) source = ('module', # ('func', '$func3', ('result', 'i32'), # v64, # ('i32.wrap_i64',) # ), # ('func', '$func2', ('result', 'i64'), # expr32, # ('i64.extend_i32_s',), # ), ('func', ('export', 'my_func'), ('result', 'i64'), v64 # ('i64.const', s), # ('i64.const', s), # ('i64.add'), # ('i64.const', s), # ('i64.mul'), # ('i64.const', s), # ('i64.sub'), # ('i64.const', s), # ('i64.rem_u'), ), ('memory', 2), ('data', ('i32.const', 0), mem) ) # Create wasm module m = Module(source) assert_equal_behavior(m)
def test_coremark_crc16(v1, v2): coremark_wasm_snippet = r""" (module (func $crc8 (param i32 i32) (result i32) local.get 0 local.get 1 i32.add) (func (export "crc16") (param i32 i32) (result i32) local.get 0 i32.const 16 i32.shr_u local.get 0 i32.const 65535 i32.and local.get 1 call $crc8 call $crc8) ) """ m = Module(coremark_wasm_snippet) py_inst = instantiate(m, target='python') native_inst = instantiate(m, target='native') res1 = py_inst.exports['crc16'](v1, v2) res2 = native_inst.exports['crc16'](v1, v2) print('results', res1, 'should be equal to', res2) assert res1 == res2
def take_root(self, bits, target): # Function parameters and result: a = 4.0 b = 9.0 expected_result = 6.0 # Python cross check: python_result = math.sqrt(a) * math.sqrt(b) assert math.isclose(python_result, expected_result, rel_tol=0.0001, abs_tol=0.0000001) # Now via wasm instantiation: module = Module(src) # report_filename = 'root_{}_{}.html'.format(bits, target) # with html_reporter(report_filename) as reporter: #, reporter=reporter) instance = instantiate(module, target=target) # print('root ', bits, 'instance', inst, 'for target', target) funcname = 'f{}.mul_sqrts'.format(bits) res = instance.exports[funcname](a, b) # print('Result:', res, 'expected=', expected_result, 'python says', python_result) assert math.isclose(res, expected_result, rel_tol=0.0001, abs_tol=0.0000001)
def test_export1(): # The canonical form CODE0 = dedent(""" (module (type $sig (func)) (table $t1 2 anyfunc) (memory $m1 1) (global $g1 i32 (i32.const 7)) (export "bar_table1" (table $t1)) (export "bar_mem1" (memory $m1)) (export "bar_global" (global $g1)) (export "bar_func1" (func $f1)) (export "bar_func2" (func $f1)) (func $f1 (type $sig) ) ) """) # Test main code m0 = Module(CODE0) print(m0.to_string()) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 # Export abbreviations: definitions of func/memory/table/global # that are really exports. CODE1 = dedent(""" (module (type $sig (func)) (table $t1 (export "bar_table1") 2 anyfunc) (memory $m1 (export "bar_mem1") 1) (global $g1 (export "bar_global") i32 (i32.const 7)) (func $f1 (export "bar_func1") (export "bar_func2") (type $sig) ) ) """) m1 = Module(CODE1) assert m1.to_string() == CODE0 assert m1.to_bytes() == b0
def test_i64_comparison_behavior(cmp_op, v1, v2): opcode = 'i64.' + cmp_op source = ( 'module', ('func', ('export', 'my_func'), ('result', 'i32'), (opcode, v1, v2)), ) m = Module(source) assert_equal_behavior(m)
def test_import1(): # The canonical form CODE0 = dedent(""" (module (type $bar_func (func)) (import "foo" "bar_func" (func $bar_func (type $bar_func))) (import "foo" "bar_table1" (table $t1 2 funcref)) (import "foo" "bar_mem1" (memory $m1 1)) (import "foo" "bar_mem2" (memory $m2 1 2)) (import "foo" "bar_global" (global $bar_global i32)) ) """) # (import "foo" "bar_table" (table $bar_table (type $bar_func))) # Test main code m0 = Module(CODE0) print(m0.to_string()) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 # Import abbreviations: definitions of func/memory/table/global # that are really imports. CODE1 = dedent(""" (module (type $bar_func (func)) (func $bar_func (import "foo" "bar_func") (type $bar_func)) (table $t1 (import "foo" "bar_table1") 2 funcref) (memory $m1 (import "foo" "bar_mem1") 1) (memory $m2 (import "foo" "bar_mem2") 1 2) (global $bar_global (import "foo" "bar_global") i32) ) """) 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_callbacks(self): """ Test various stuff around wasm instantiation. See examples/wasm/callbacks.py """ module = Module( ('import', 'py', 'add', ('func', '$add', ('param', 'i64', 'i64'), ('result', 'i64'))), ('global', '$g1', ('export', 'var1'), ('mut', 'i64'), ('i64.const', 42)), ('func', ('export', 'main'), ('param', 'i64'), ('result', 'i64'), ('local.get', 0), ('global.get', '$g1'), ('call', '$add'), ), ('func', ('export', 'add'), ('param', 'i64', 'i64'), ('result', 'i64'), ('local.get', 0), ('local.get', 1), ('call', '$add'), ), ('memory', ('export', 'mem0ry'), ('data', 'abcd'), ), ) def my_add(x: int, y: int) -> int: print('my add called', x, y) return x + y + 1 imports = { 'py_add': my_add } instance = instantiate( module, imports={ 'py': { 'add': my_add, } }) self.assertEqual(1380, instance.exports.main(1337)) self.assertEqual(85, instance.exports.add(42, 42)) self.assertEqual(3, instance.exports['add'](1, 1)) self.assertEqual(42, instance.exports.var1.read()) instance.exports.var1.write(7) self.assertEqual(7, instance.exports.var1.read()) self.assertEqual(1345, instance.exports.main(1337)) self.assertEqual(b"abcd", instance.exports.mem0ry[0:4]) instance.exports.mem0ry[1:3] = bytes([1,2]) self.assertEqual(b'a\x01\x02d', instance.exports.mem0ry[0:4])
def parse_module(self, s_expr): if 'binary' in s_expr: # We have (module binary "") # Iterate: elems = iter(s_expr) # Skip to binary tag: while next(elems) != 'binary': pass # fetch data from last tuple elements: parts = [] for elem in elems: data = datastring2bytes(elem) parts.append(data) data = reduce(add, parts) # Load module from binary data: m1 = Module(data) # Go back data2 = m1.to_bytes() # Wont always be the same, e.g. some tests use non-minimal LEB ints # assert data == data2 data3 = Module(data2).to_bytes() # Check that reading it in result in the same module ... assert data2 == data3 else: # Load module from tuples: m1 = Module(s_expr) # # Convert module to text form and parse again # # This should yield the same binary form: # m2 = Module(m1.to_string()) # assert m1.to_bytes() == m2.to_bytes() # NOTE: going to string format and back does not # guarantee that parsing was correct. self.reporter.dump_wasm(m1) self.logger.debug('loaded wasm module %s (id=%s)', m1, m1.id) return m1
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 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'
f.write(data) files = [ 'clang.wasm', 'clang-format.wasm', 'runtime.wasm', ] for local_filename in files: url = 'https://tbfleming.github.io/cib/{}'.format(local_filename) if not os.path.exists(local_filename): download_file(url, local_filename) with open('runtime.wasm', 'rb') as f: # with open('clang-format.wasm', 'rb') as f: wasm_module = Module(f.read()) print(wasm_module) wasm_module.show_interface() arch = get_arch('x86_64') ptr_info = arch.info.get_type_info('ptr') ir_module = wasm_to_ir(wasm_module, ptr_info) print(ir_module) print(ir_module.stats()) obj = ir_to_object([ir_module], arch)
def load_module(self, s_expr): if 'binary' in s_expr: # We have (module binary "") # Iterate: elems = iter(s_expr) # Skip to binary tag: while next(elems) != 'binary': pass # fetch data from last tuple elements: parts = [] for elem in elems: data = datastring2bytes(elem) parts.append(data) data = reduce(add, parts) # Load module from binary data: m1 = Module(data) # Go back data2 = m1.to_bytes() # Wont always be the same, e.g. some tests use non-minimal LEB ints # assert data == data2 data3 = Module(data2).to_bytes() # Check that reading it in result in the same module ... assert data2 == data3 else: # Load module from tuples: m1 = Module(s_expr) # # Convert module to text form and parse again # # This should yield the same binary form: # m2 = Module(m1.to_string()) # assert m1.to_bytes() == m2.to_bytes() # NOTE: going to string format and back does not # guarantee that parsing was correct. self.reporter.dump_wasm(m1) self.logger.debug('loaded wasm module %s', m1) # Next step: Instantiate: if self.target: def my_print() -> None: pass def print_i32(x: int) -> None: pass imports = { 'spectest': { 'print_i32': print_i32, 'print': my_print, } } self.mod_instance = instantiate( m1, imports, target=self.target, reporter=self.reporter) self.logger.debug('Instantiated wasm module %s', self.mod_instance) else: self.mod_instance = None
def do_func(fname): """ Test parsing on a single test file. Its great to call this at the botton during dev! """ print('Testing {} - "{}"'.format(fname, os.path.join(get_spec_suite_dir(), fname))) for text in get_test_script_parts(fname): sexpr = parse_sexpr(text) # Assert that the toplevel expression makes sense assert sexpr[0] in ( 'module', 'invoke', 'register', 'assert_return', 'assert_invalid', 'assert_trap', 'assert_malformed', 'assert_exhaustion', 'assert_unlinkable', 'assert_return_canonical_nan', 'assert_return_arithmetic_nan', 'func', 'memory', # inline-module.wast ), '{}: unexpected expression in'.format(fname) # But in this script we only do modules if sexpr[0] != 'module': continue if 'binary' in sexpr: continue # todo: skipping a few here, for now if fname in ( 'names.wast', 'comments.wast', # because sending Unicode over Pipes seems to go wrong ): continue wasm_bin0 = wabt.wat2wasm(text) m1 = Module(wasm_bin0) m2 = Module(text) m3 = Module(sexpr) wasm_bin1 = m1.to_bytes() wasm_bin2 = m2.to_bytes() wasm_bin3 = m3.to_bytes() assert wasm_bin0 == wasm_bin1, '{}: our binary parsing is broken'.format( fname) assert wasm_bin2 == wasm_bin3, '{}: our text/tuple paring differs'.format( fname) assert wasm_bin0 == wasm_bin2, '{}: our text parsing is broken'.format( fname) if False: # debug helpers print(len(wasm_bin1), len(wasm_bin2)) print(len(m1.definitions), len(m2.definitions)) hexdump(wasm_bin1) print() hexdump(wasm_bin2)
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
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_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
(func $fac-f32 (export "fac-f32") (type $over-f32) (if (result f32) (f32.eq (local.get 0) (f32.const 0.0)) (then (f32.const 1.0)) (else (f32.mul (local.get 0) (call $fac-f32 (f32.sub (local.get 0) (f32.const 1.0)) ) ) ) ) ) ) """ m = Module(src) obj = api.wasmcompile(src, 'x86_64', opt_level=0) api.objcopy(obj, None, 'elf', 'fac_f32.o') print(m.to_string()) inst = instantiate(m, {}) inst2 = instantiate(m, {}, target='python') for number in [1.0, 5.0, 10.0]: print('number', number, 'fac', inst.exports['fac-f32'](number), 'fac_python', inst2.exports['fac-f32'](number))
import argparse import numpy as np import pygame from pygame.locals import QUIT from ppci.wasm import Module, instantiate from ppci.utils import reporting parser = argparse.ArgumentParser() parser.add_argument('--rom', default='cpu_instrs.gb') args = parser.parse_args() logging.basicConfig(level=logging.INFO) with open('wasmboy.wasm', 'rb') as f: wasm_module = Module(f) def log(a: int, b: int, c: int, d: int, e: int, f: int, g: int) -> None: print('Log:', a, b, c, d, e, f, g) this_dir = os.path.dirname(os.path.abspath(__file__)) html_report = os.path.join(this_dir, 'wasmboy_report.html') with reporting.html_reporter(html_report) as reporter: wasm_boy = instantiate(wasm_module, imports={'env': { 'log': log }}, target='native', reporter=reporter)
def do_func(fname): """ Test running on a single test file. Its great to call this at the botton during dev! """ print('Testing {} - "{}"'.format(fname, os.path.join(get_spec_suite_dir(), fname))) mod = None for text in get_test_script_parts(fname): sexpr = parse_sexpr(text) exp_kind = sexpr[0] # Triage over toplevel expressions # https://github.com/WebAssembly/spec/blob/master/interpreter/README.md#s-expression-syntax if exp_kind == 'module': if 'binary' in sexpr: # Combine binary parts parts = None for elem in sexpr: if parts is None: if elem == 'binary': parts = [] else: parts.append(datastring2bytes(elem)) data = b''.join(parts) # Load module from binary data mod = Module(data) else: # Load module from text, via wabt data = wabt.wat2wasm(text) mod = Module(data) elif exp_kind == 'register': raise NotImplementedError( 'I suppose we need this, but not sure how to do it yet.') elif exp_kind == 'invoke': raise NotImplementedError() elif exp_kind == 'assert_return': assert len(sexpr) == 3 and sexpr[1][0] == 'invoke' _, func_id, params = sexpr[1] expected_result = sexpr[2] raise NotImplementedError() elif expr_kind in ( 'assert_invalid', 'assert_trap', 'assert_malformed', 'assert_exhaustion', 'assert_unlinkable', 'assert_return_canonical_nan', 'assert_return_arithmetic_nan', 'func', 'memory', # inline-module.wast ): pass # not implemented yet else: assert False, '{}: unexpected expression in'.format(fname)