diff --git a/ml-proto/README.md b/ml-proto/README.md index f947c479d1..067b7946de 100644 --- a/ml-proto/README.md +++ b/ml-proto/README.md @@ -132,7 +132,7 @@ local: ( local * ) | ( local ) module: ( module * * * * * ? ? ) type: ( type ? ( func * ? ) ) import: ( import ? "" "" (param * ) (result )* ) -export: ( export "*" ) +export: ( export "*" ) | ( export "*" memory) start: ( start ) table: ( table * ) memory: ( memory ? * ) diff --git a/ml-proto/host/parser.mly b/ml-proto/host/parser.mly index 10af448d6a..e065c285b6 100644 --- a/ml-proto/host/parser.mly +++ b/ml-proto/host/parser.mly @@ -394,7 +394,9 @@ import : export : | LPAR EXPORT TEXT var RPAR - { let at = at () in fun c -> {name = $3; func = $4 c func} @@ at } + { let at = at () in fun c -> ExportFunc ($3, ($4 c func)) @@ at } + | LPAR EXPORT TEXT MEMORY RPAR + { let at = at () in fun c -> ExportMemory $3 @@ at } ; module_fields : diff --git a/ml-proto/host/print.ml b/ml-proto/host/print.ml index 4fa08b2a8e..bd64e9be78 100644 --- a/ml-proto/host/print.ml +++ b/ml-proto/host/print.ml @@ -21,8 +21,11 @@ let print_var_sig prefix i t = let print_func_sig m prefix i f = printf "%s %d : %s\n" prefix i (string_of_func_type (func_type m f)) -let print_export_sig m prefix n f = - printf "%s \"%s\" : %s\n" prefix n (string_of_func_type (func_type m f)) +let print_export_sig m n f = + printf "export \"%s\" : %s\n" n (string_of_func_type (func_type m f)) + +let print_export_mem n = + printf "export \"%s\" : memory\n" n let print_table_elem i x = printf "table [%d] = func %d\n" i x.it @@ -36,7 +39,9 @@ let print_func m i f = print_func_sig m "func" i f let print_export m i ex = - print_export_sig m "export" ex.it.name (List.nth m.it.funcs ex.it.func.it) + match ex.it with + | ExportFunc (n, x) -> print_export_sig m n (List.nth m.it.funcs x.it) + | ExportMemory n -> print_export_mem n let print_module m = let {funcs; start; exports; table} = m.it in diff --git a/ml-proto/spec/check.ml b/ml-proto/spec/check.ml index 35f6b54f15..241bcdbb34 100644 --- a/ml-proto/spec/check.ml +++ b/ml-proto/spec/check.ml @@ -289,8 +289,9 @@ let check_elem c x = module NameSet = Set.Make(String) let check_export c set ex = - let {name; func = x} = ex.it in - ignore (func c x); + let name = match ex.it with + | ExportFunc (n, x) -> ignore (func c x); n + | ExportMemory n -> require (c.has_memory) ex.at "no memory to export"; n in require (not (NameSet.mem name set)) ex.at "duplicate export name"; NameSet.add name set diff --git a/ml-proto/spec/eval.ml b/ml-proto/spec/eval.ml index 3acb624593..43e1c0bbb0 100644 --- a/ml-proto/spec/eval.ml +++ b/ml-proto/spec/eval.ml @@ -314,7 +314,9 @@ let init_memory {it = {initial; segments; _}} = mem let add_export funcs ex = - ExportMap.add ex.it.name (List.nth funcs ex.it.func.it) + match ex.it with + | ExportFunc (n, x) -> ExportMap.add n (List.nth funcs x.it) + | ExportMemory n -> fun x -> x let init m imports host = assert (List.length imports = List.length m.it.Kernel.imports); diff --git a/ml-proto/spec/kernel.ml b/ml-proto/spec/kernel.ml index c90675a79a..fcde373130 100644 --- a/ml-proto/spec/kernel.ml +++ b/ml-proto/spec/kernel.ml @@ -126,7 +126,9 @@ and memory' = and segment = Memory.segment Source.phrase type export = export' Source.phrase -and export' = {name : string; func : var} +and export' = + | ExportFunc of string * var + | ExportMemory of string type import = import' Source.phrase and import' = diff --git a/ml-proto/test/exports.wast b/ml-proto/test/exports.wast index 089603fe40..3a75499ae3 100644 --- a/ml-proto/test/exports.wast +++ b/ml-proto/test/exports.wast @@ -20,3 +20,7 @@ ) (assert_return (invoke "e" (i32.const 42)) (i32.const 43)) + +(module (memory 0 0) (export "a" memory)) +(module (memory 0 0) (export "a" memory) (export "b" memory)) +(assert_invalid (module (export "a" memory)) "no memory to export")