@@ -88,16 +88,20 @@ Result<Action> action(Lexer& in) {
8888 return in.err (" expected action" );
8989}
9090
91- // (module id? binary string*)
92- // (module id? quote string*)
93- // (module ...)
91+ // (module id binary string*)
92+ // (module id quote string*)
93+ // (module definition id? ...)
9494Result<WASTModule> wastModule (Lexer& in, bool maybeInvalid = false ) {
9595 Lexer reset = in;
9696 if (!in.takeSExprStart (" module" sv)) {
9797 return in.err (" expected module" );
9898 }
99- // TODO: use ID?
100- [[maybe_unused]] auto id = in.takeID ();
99+
100+ bool isDefinition = in.takeKeyword (" definition" sv);
101+
102+ // We'll read this again in the 'inline module' case
103+ (void )in.takeID ();
104+
101105 QuotedModuleType type;
102106 if (in.takeKeyword (" quote" sv)) {
103107 type = QuotedModuleType::Text;
@@ -118,14 +122,31 @@ Result<WASTModule> wastModule(Lexer& in, bool maybeInvalid = false) {
118122 }
119123 }
120124 std::string mod (reset.next ().substr (0 , in.getPos () - reset.getPos ()));
121- return QuotedModule{QuotedModuleType::Text, mod};
125+ return QuotedModule{!isDefinition, QuotedModuleType::Text, mod};
122126 } else {
123- // This is a normal inline module that should be parseable. Reset to the
124- // start and parse it normally.
127+ // In this case the module is mostly valid WAT, unless it is a module
128+ // definition in which case it will begin with (module definition ...)
125129 in = std::move (reset);
130+
131+ // We already checked this before resetting
132+ if (!in.takeSExprStart (" module" sv)) {
133+ return in.err (" expected module" );
134+ }
135+
136+ bool isDefinition = in.takeKeyword (" definition" sv);
137+
126138 auto wasm = std::make_shared<Module>();
139+ if (auto id = in.takeID ()) {
140+ wasm->name = *id;
141+ }
142+
127143 wasm->features = FeatureSet::All;
128- CHECK_ERR (parseModule (*wasm, in));
144+ CHECK_ERR (parseModuleBody (*wasm, in));
145+ if (!in.takeRParen ()) {
146+ return in.err (" expected end of module" );
147+ }
148+
149+ wasm->isDefinition = isDefinition;
129150 return wasm;
130151 }
131152
@@ -139,7 +160,7 @@ Result<WASTModule> wastModule(Lexer& in, bool maybeInvalid = false) {
139160 return in.err (" expected end of module" );
140161 }
141162
142- return QuotedModule{type, ss.str ()};
163+ return QuotedModule{isDefinition, type, ss.str ()};
143164}
144165
145166Result<NaNKind> nan (Lexer& in) {
@@ -440,17 +461,64 @@ MaybeResult<Register> register_(Lexer& in) {
440461 return in.err (" expected name" );
441462 }
442463
443- // TODO: Do we need to use this optional id?
444- in.takeID ();
464+ auto instanceName = in.takeID ();
445465
446466 if (!in.takeRParen ()) {
447- // TODO: handle optional module id.
448467 return in.err (" expected end of register command" );
449468 }
450- return Register{*name};
469+
470+ return Register{.name = *name, .instanceName = instanceName};
471+ }
472+
473+ // (module instance instance_name module_name)
474+ MaybeResult<ModuleInstantiation> instantiation (Lexer& in) {
475+ if (!in.takeSExprStart (" module" sv)) {
476+ std::optional<std::string_view> actual = in.peekKeyword ();
477+ return in.err ((std::stringstream () << " expected `module` keyword but got "
478+ << actual.value_or (" <not a keyword>" ))
479+ .str ());
480+ }
481+
482+ if (!in.takeKeyword (" instance" sv)) {
483+ // This is not a module instance and probably a module instead.
484+ return {};
485+ }
486+
487+ auto instanceId = in.takeID ();
488+ if (!instanceId.has_value ()) {
489+ return in.err (" expected an instance id in module instantiation" );
490+ }
491+ auto moduleId = in.takeID ();
492+ if (!moduleId.has_value ()) {
493+ return in.err (" expected a module id in module instantiation" );
494+ }
495+
496+ if (!in.takeRParen ()) {
497+ return in.err (" expected end of module instantiation" );
498+ }
499+
500+ return ModuleInstantiation{.moduleName = *moduleId,
501+ .instanceName = *instanceId};
502+ }
503+
504+ using ModuleOrInstantiation = std::variant<ModuleInstantiation, WASTModule>;
505+
506+ // (module instance ...) | (module ...)
507+ Result<ModuleOrInstantiation> moduleOrInstantiation (Lexer& in) {
508+ auto reset = in;
509+
510+ if (auto inst = instantiation (in)) {
511+ CHECK_ERR (inst);
512+ return *inst;
513+ }
514+ in = reset;
515+
516+ auto module = wastModule (in);
517+ CHECK_ERR (module );
518+ return *module ;
451519}
452520
453- // module | register | action | assertion
521+ // instantiate | module | register | action | assertion
454522Result<WASTCommand> command (Lexer& in) {
455523 if (auto cmd = register_ (in)) {
456524 CHECK_ERR (cmd);
@@ -464,9 +532,12 @@ Result<WASTCommand> command(Lexer& in) {
464532 CHECK_ERR (cmd);
465533 return *cmd;
466534 }
467- auto mod = wastModule (in);
468- CHECK_ERR (mod);
469- return *mod;
535+ auto cmd = moduleOrInstantiation (in);
536+ CHECK_ERR (cmd);
537+
538+ return std::visit (
539+ [](const auto & modOrInstantiation) -> WASTCommand { return modOrInstantiation; },
540+ *cmd);
470541}
471542
472543#pragma GCC diagnostic push
0 commit comments