Summary
vihaco has a round-trippable text reader but no matching writer, so a parse → Module → emit → parse cycle isn't possible today.
- Reader:
ParsedModule<I, H>::parser() (syntax/parse.rs) parses the source grammar — header lines terminated by ; plus fn @name(...) -> ret { <body> } function blocks — and a Resolve impl turns it into a Module.
- Writer: the only text output for a
Module is its Display impl (module.rs), which is a disassembly / debug view — .text / .const / .string / .machine / .feature sections with 0x{addr}-prefixed lines. This grammar is not what ParsedModule::parser() accepts, so Module's Display output cannot be fed back into the parser.
Why it matters
Downstream consumers that want an assemble/disassemble workflow (e.g. bloqade-lanes' bytecode CLI: text .sst ⇄ binary) need a canonical, re-parseable text form. Right now each consumer has to hand-roll an emitter that reproduces the fn @name { ... } parse grammar, because Module::Display is debug-only. That re-introduces exactly the parser/printer drift the derive was meant to eliminate (the printer lives outside the crate that owns the grammar).
Proposal
Provide a canonical text emitter for Module (and/or ParsedModule) that produces output the parser round-trips:
parse(emit(module)) == module // modulo resolution/interning
Options (non-exclusive):
- A dedicated emitter — e.g.
Module::to_source() / a Display-sibling — that writes the fn @name(...) { <body> } grammar using each instruction's own Display, plus the header lines.
- Or document
Module::Display explicitly as a non-round-trippable debug view and add the round-trippable emitter alongside it, so the two roles are clearly separated.
Element rendering can reuse the per-instruction Display impls (as #[derive(Parse)] variants already have a canonical token); the missing piece is the module/function framing that mirrors the parser.
Context
Surfaced while migrating bloqade-lanes' bytecode onto vihaco (QuEraComputing/bloqade-lanes#769): we adopt vihaco's Module + ParsedModule parser for the text format, but must hand-roll the fn @main { ... } emitter for disassemble since Module::Display isn't re-parseable.
Summary
vihaco has a round-trippable text reader but no matching writer, so a parse →
Module→ emit → parse cycle isn't possible today.ParsedModule<I, H>::parser()(syntax/parse.rs) parses the source grammar — header lines terminated by;plusfn @name(...) -> ret { <body> }function blocks — and aResolveimpl turns it into aModule.Moduleis itsDisplayimpl (module.rs), which is a disassembly / debug view —.text/.const/.string/.machine/.featuresections with0x{addr}-prefixed lines. This grammar is not whatParsedModule::parser()accepts, soModule'sDisplayoutput cannot be fed back into the parser.Why it matters
Downstream consumers that want an assemble/disassemble workflow (e.g. bloqade-lanes' bytecode CLI: text
.sst⇄ binary) need a canonical, re-parseable text form. Right now each consumer has to hand-roll an emitter that reproduces thefn @name { ... }parse grammar, becauseModule::Displayis debug-only. That re-introduces exactly the parser/printer drift the derive was meant to eliminate (the printer lives outside the crate that owns the grammar).Proposal
Provide a canonical text emitter for
Module(and/orParsedModule) that produces output the parser round-trips:Options (non-exclusive):
Module::to_source()/ aDisplay-sibling — that writes thefn @name(...) { <body> }grammar using each instruction's ownDisplay, plus the header lines.Module::Displayexplicitly as a non-round-trippable debug view and add the round-trippable emitter alongside it, so the two roles are clearly separated.Element rendering can reuse the per-instruction
Displayimpls (as#[derive(Parse)]variants already have a canonical token); the missing piece is the module/function framing that mirrors the parser.Context
Surfaced while migrating bloqade-lanes' bytecode onto vihaco (QuEraComputing/bloqade-lanes#769): we adopt vihaco's
Module+ParsedModuleparser for the text format, but must hand-roll thefn @main { ... }emitter fordisassemblesinceModule::Displayisn't re-parseable.