@@ -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,30 @@ 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 definition in which case it will begin with (module definition ...)
125128 in = std::move (reset);
129+
130+ // We already checked this before resetting
131+ if (!in.takeSExprStart (" module" sv)) {
132+ return in.err (" expected module" );
133+ }
134+
135+ bool isDefinition = in.takeKeyword (" definition" sv);
136+
126137 auto wasm = std::make_shared<Module>();
138+ if (auto id = in.takeID ()) {
139+ wasm->name = *id;
140+ }
141+
127142 wasm->features = FeatureSet::All;
128- CHECK_ERR (parseModule (*wasm, in));
143+ CHECK_ERR (parseModuleBody (*wasm, in));
144+ if (!in.takeRParen ()) {
145+ return in.err (" expected end of module" );
146+ }
147+
148+ wasm->isDefinition = isDefinition;
129149 return wasm;
130150 }
131151
@@ -139,7 +159,7 @@ Result<WASTModule> wastModule(Lexer& in, bool maybeInvalid = false) {
139159 return in.err (" expected end of module" );
140160 }
141161
142- return QuotedModule{type, ss.str ()};
162+ return QuotedModule{isDefinition, type, ss.str ()};
143163}
144164
145165Result<NaNKind> nan (Lexer& in) {
@@ -440,17 +460,61 @@ MaybeResult<Register> register_(Lexer& in) {
440460 return in.err (" expected name" );
441461 }
442462
443- // TODO: Do we need to use this optional id?
444- in.takeID ();
463+ auto instanceName = in.takeID ();
445464
446465 if (!in.takeRParen ()) {
447- // TODO: handle optional module id.
448466 return in.err (" expected end of register command" );
449467 }
450- return Register{*name};
468+
469+ return Register{.name =*name, .instanceName =instanceName};
451470}
452471
453- // module | register | action | assertion
472+ // (module instance instance_name module_name)
473+ MaybeResult<ModuleInstantiation> instantiation (Lexer& in) {
474+ if (!in.takeSExprStart (" module" sv)) {
475+ std::optional<std::string_view> actual = in.peekKeyword ();
476+ return in.err ((std::stringstream ()<<" expected `module` keyword but got " << actual.value_or (" <not a keyword>" )).str ());
477+ }
478+
479+ if (!in.takeKeyword (" instance" sv)) {
480+ // This is not a module instance and probably a module instead.
481+ return {};
482+ }
483+
484+ auto instanceId = in.takeID ();
485+ if (!instanceId.has_value ()) {
486+ return in.err (" expected an instance id in module instantiation" );
487+ }
488+ auto moduleId = in.takeID ();
489+ if (!moduleId.has_value ()) {
490+ return in.err (" expected a module id in module instantiation" );
491+ }
492+
493+ if (!in.takeRParen ()) {
494+ return in.err (" expected end of module instantiation" );
495+ }
496+
497+ return ModuleInstantiation{.moduleName = *moduleId, .instanceName = *instanceId};
498+ }
499+
500+ using ModuleOrInstantiation = std::variant<ModuleInstantiation, WASTModule>;
501+
502+ // (module instance ...) | (module ...)
503+ Result<ModuleOrInstantiation> moduleOrInstantiation (Lexer& in) {
504+ auto reset = in;
505+
506+ if (auto inst = instantiation (in)) {
507+ CHECK_ERR (inst);
508+ return *inst;
509+ }
510+ in = reset;
511+
512+ auto module = wastModule (in);
513+ CHECK_ERR (module );
514+ return *module ;
515+ }
516+
517+ // instantiate | module | register | action | assertion
454518Result<WASTCommand> command (Lexer& in) {
455519 if (auto cmd = register_ (in)) {
456520 CHECK_ERR (cmd);
@@ -464,9 +528,10 @@ Result<WASTCommand> command(Lexer& in) {
464528 CHECK_ERR (cmd);
465529 return *cmd;
466530 }
467- auto mod = wastModule (in);
468- CHECK_ERR (mod);
469- return *mod;
531+ auto cmd = moduleOrInstantiation (in);
532+ CHECK_ERR (cmd);
533+
534+ return std::visit ([](auto && modOrInstantiation) -> WASTCommand { return modOrInstantiation; }, *cmd);
470535}
471536
472537#pragma GCC diagnostic push
0 commit comments