Generation of disassembler

We can reuse the encoding interface, since the assembly stuff is an implementation of it.
<*>= [D->]
link pretty
procedure emit_disassembler(outfilename)
  local constypes, constype
  verbose("Emitting disassemblers")
  f := openfile(outfilename, "w") |
    error("Could not open ", image(outfilename), " for writing")
  pp := PPnew(f)

  every create_input_print_proc(pp, inputs_of(kept_constructors()))
  PPxwrite(pp, "$t")
  constypes := set([&null])
  every insert(constypes, kept_constructors().type)
  every constype := !constypes do {
    PPwrite(pp, "match pc to")
    l := []
    every push(l, kept_constructors(constype)) # reverse order
    every emit_disassembler_match(pp, !l)
    PPwrite(pp, "endmatch")
  PPwrite(pp)   # flush prettyprinter
Defines emit_disassembler (links are to index).

emit_disassembler_match emits a line in a matching statement for constructor cons. Right now we emit a bunch of print statments flagrantly borrowed from the assembler encoding stuff. Eventually, we will just want indirect calls on encoding procedures.

<*>+= [<-D]
procedure emit_disassembler_match(pp, cons) 
  local asmname
  PPxwrites(pp, "| $t$t$t${",, "(")
  <emit operands separated by commas>
  PPxwrites(pp, ")$} => $b$o")
  asmname := consname2asm(cons)
  if *asmname > 0 & /postfix then
    emit_asm_printf(pp, "%s", image(asmname))
  every o := !asmoperands(cons) do
    case type(o) of {
      "literal" : emit_asm_printf(pp, "%s", image(o.s))
      "input"  : 
          PPxwrites(pp, "$n", 
                        create_input_print_proc(pp, o), "(", Cnoreserve(, ");")
      default : impossible("operand type")
  if *asmname > 0 & \postfix then
    emit_asm_printf(pp, "%s", image(asmname))
  if cons.type === instructionctype then
    emit_asm_printf(pp, "\n")
  PPxwrite(pp, "$b$b")
Defines emit_disassembler_match (links are to index).

<emit operands separated by commas>= (U->)
pfx := ""
every ipt := inputs_of(cons) do {
  PPxwrites(pp, pfx,
  pfx := ", $o"