shithub: MicroHs

Download patch

ref: 30c0f95205f8f5ec8d312ff6d687e0481b916b90
parent: 70ce3fe80e78c41590f8cd79d98d447c06f8c448
author: Lennart Augustsson <lennart@augustsson.net>
date: Wed Oct 11 08:30:27 EDT 2023

Use more compact (and readable) combinator file.

--- a/TODO
+++ b/TODO
@@ -32,3 +32,5 @@
 * Generate C file directly from compiler
 * Implement IORef
   - The IORef will need GC support
+* Redo type synonym expansion
+  - Only non-injective synonyms necessitate expansion(?)
--- a/comb/mhs.comb
+++ b/comb/mhs.comb
@@ -1,3 +1,3 @@
-v3.5
+v4.0
 973
-(($A :0 _857) (($A :1 (($B _903) _0)) (($A :2 ((($S' _903) _0) $I)) (($A :3 _827) (($A :4 (_3 "undefined")) (($A :5 $I) (($A :6 ((($C' $B) _856) (($C _74) _5))) (($A :7 ((($C' _6) (_874 _71)) ((_74 _872) _70))) (($A :8 (($B (($S _903) _872)) _3)) (($A :9 $T) (($A :10 ($T $I)) (($A :11 (($B (_74 _188)) _10)) (($A :12 (($B ($B (_73 _9))) ((($C' $B) (($B $C) _10)) ($B _10)))) (($A :13 (($B ($B (_73 _9))) ((($C' $B) (($B $C) _10)) ($BK _10)))) (($A :14 (($B (_73 _9)) $P)) (($A :15 (($B ($B (_73 _9))) (($B (($C' $C) _10)) ($B $P)))) (($A :16 _15) (($A :17 (($B (_73 _9)) ($B ($P _785)))) (($A :18 (($B (_73 _9)) ($BK ($P _785)))) (($A :19 ((_73 _9) (($S $P) $I))) (($A :20 (($B (_73 _9)) (($C ($S' $P)) $I))) (($A :21 (($B $Y) (($B ($B ($P (_14 _114)))) ((($C' $B) (($B ($C' $B)) ($B _12))) ((($C' ($C' $B)) ($B _12)) (($B ($B _14)) _115)))))) (($A :22 (($B $Y) (($B ($B ($P (_14 _785)))) (($B ($C' $B)) ($B _13))))) (($A :23 _3) (($A :24 ($T (_14 _785))) (($A :25 (_21 _75)) (($A :26 (($C $C) _33)) (($A :27 ($T _32)) (($A :28 (($P _33) _32)) (($A :29 _33) (($A :30 (($C (($C $S') _28)) $I)) (($A :31 (($C $S) _28)) (($A :32 $K) (($A :33 $A) (($A :34 _832) (($A :35 _833) (($A :36 ((($S' _27) (_824 97)) (($C _824) 122))) (($A :37 ((($S' _27) (_824 65)) (($C _824) 90))) (($A :38 ((($S' _26) _36) _37)) (($A :39 ((($S' _27) (_824 48)) (($C _824) 57))) (($A :40 ((($S' _27) (_824 32)) (($C _824) 126))) (($A :41 _821) (($A :42 _822) (($A :43 _824) (($A :44 _823) (($A :45 ((($S' _26) (($C _41) 32)) ((($S' _26) (($C _41) 9)) (($C _41) 10)))) (($A :46 (($S (($S ((($S' _27) (_43 65)) (($C _43) 90))) (_33 (((_784 "lib/Data/Char.hs") 3) 8)))) (($B _34) ((($C' _81) ((($C' _82) _35) (_35 65))) (_35 97))))) (($A :47 (($S (($S ((($S' _27) (_43 97)) (($C _43) 97))) (_33 (((_784 "lib/Data/Char.hs") 3) 8)))) (($B _34) ((($C' _81) ((($C' _82) _35) (_35 97))) (_35 65))))) (($A :48 _792) (($A :49 _793) (($A :50 _794) (($A :51 _795) (($A :52 (_49 %0.0)) (($A :53 _48) (($A :54 _49) (($A :55 _50) (($A :56 _51) (($A :57 _796) (($A :58 _797) (($A :59 _57) (($A :60 _58) (($A :61 _798) (($A :62 _799) (($A :63 _800) (($A :64 _801) (($A :65 _61) (($A :66 _62) (($A :67 _63) (($A :68 _64) (($A :69 _802) (($A :70 (($B $BK) $T)) (($A :71 ($BK $T)) (($A :72 $P) (($A :73 $I) (($A :74 $B) (($A :75 $I) (($A :76 $K) (($A :77 $C) (($A :78 _828) (($A :79 (($C (($C $S') _188)) _189)) (($A :80 ((($C' ($S' ($C' $B))) $B) $I)) (($A :81 _786) (($A :82 _787) (($A :83 _788) (($A :84 _789) (($A :85 _790) (($A :86 _791) (($A :87 (_82 0)) (($A :88 _809) (($A :89 _810) (($A :90 _811) (($A :91 _812) (($A :92 _813) (($A :93 _814) (($A :94 _88) (($A :95 ($BK $K)) (($A :96 (($B $BK) (($B ($B $BK)) $P))) (($A :97 (($B ($B ($B $BK))) (($B ($B ($B $BK))) (($B ($B ($B $C))) (($B ($B $C)) $P))))) (($A :98 ((($S' $S) ((($S' ($S' $C)) ((($C' ($C' $S)) ((($C' $B) (($B ($S' $S')) ((($C' $B) (($B _26) (_91 0))) (_88 0)))) (($B ($B (($C' $P) (_86 1)))) _81))) ($C $P))) _84)) _85)) (($A :99 _95) (($A :100 ((($S' $C) (($B ($P _176)) ((($C' ($C' $B)) ((($C' $C) _88) _176)) _177))) (($B (($C' ($C' ($C' $C))) ((($C' ($C' ($C' $C))) ((($C' ($C' ($C' ($C' $S')))) (($B ($B ($B ($B $C)))) (($B (($C' ($C' ($C' $C))) (($B ($B ($B (($S' $S') (_88 0))))) (($B (($C' ($C' $C)) (($B ($B (($S' $S') (_88 1)))) (($B (($C' $C) (($B (($C' $S') (_88 2))) ($C _100)))) ($C _100))))) ($C _100))))) ($C _100)))) ($T $K))) ($T $A)))) (($C _98) 4)))) (($A :101 (_107 _76)) (($A :102 ((_122 (_79 _101)) _99)) (($A :103 (($C ((($C' $B) (($P _114) ((($C' ($C' $O)) $P) $K))) ((($S' ($C' ($C' ($C' $B)))) (($B ($B ($B ($B _104)))) ((($S' ($C' ($C' $B))) (($B ($B ($B _104))) ((($S' ($C' $B)) (($B ($B _104)) ((($C' $B) (($B _120) ($T 0))) _103))) ((($C' $B) (($B _120) ($T 1))) _103)))) ((($C' $B) (($B _120) ($T 2))) _103)))) ((($C' $B) (($B _120) ($T 3))) _103)))) (($B $T) (($B ($B $P)) (($C' _81) (_83 4)))))) (($A :104 (($S $S) (($B $BK) (($B $BK) ((($S' $S) $T) (($B $BK) (($B $BK) (($C ((($S' $C') $S) (($B ($B ($B ($S $B)))) (($B ($B ($B ($B ($B $BK))))) (($B (($S' ($C' $B)) (($B $B') $B'))) (($B ($B ($B ($B ($B ($S $B)))))) (($B ($B ($B (
\ No newline at end of file
+((A :0 _857) ((A :1 ((B _903) _0)) ((A :2 (((S' _903) _0) I)) ((A :3 _827) ((A :4 (_3 "undefined")) ((A :5 I) ((A :6 (((C' B) _856) ((C _74) _5))) ((A :7 (((C' _6) (_874 _71)) ((_74 _872) _70))) ((A :8 ((B ((S _903) _872)) _3)) ((A :9 T) ((A :10 (T I)) ((A :11 ((B (_74 _188)) _10)) ((A :12 ((B (B (_73 _9))) (((C' B) ((B C) _10)) (B _10)))) ((A :13 ((B (B (_73 _9))) (((C' B) ((B C) _10)) (BK _10)))) ((A :14 ((B (_73 _9)) P)) ((A :15 ((B (B (_73 _9))) ((B ((C' C) _10)) (B P)))) ((A :16 _15) ((A :17 ((B (_73 _9)) (B (P _785)))) ((A :18 ((B (_73 _9)) (BK (P _785)))) ((A :19 ((_73 _9) ((S P) I))) ((A :20 ((B (_73 _9)) ((C (S' P)) I))) ((A :21 ((B Y) ((B (B (P (_14 _114)))) (((C' B) ((B (C' B)) (B _12))) (((C' (C' B)) (B _12)) ((B (B _14)) _115)))))) ((A :22 ((B Y) ((B (B (P (_14 _785)))) ((B (C' B)) (B _13))))) ((A :23 _3) ((A :24 (T (_14 _785))) ((A :25 (_21 _75)) ((A :26 ((C C) _33)) ((A :27 (T _32)) ((A :28 ((P _33) _32)) ((A :29 _33) ((A :30 ((C ((C S') _28)) I)) ((A :31 ((C S) _28)) ((A :32 K) ((A :33 A) ((A :34 _832) ((A :35 _833) ((A :36 (((S' _27) (_824 #97)) ((C _824) #122))) ((A :37 (((S' _27) (_824 #65)) ((C _824) #90))) ((A :38 (((S' _26) _36) _37)) ((A :39 (((S' _27) (_824 #48)) ((C _824) #57))) ((A :40 (((S' _27) (_824 #32)) ((C _824) #126))) ((A :41 _821) ((A :42 _822) ((A :43 _824) ((A :44 _823) ((A :45 (((S' _26) ((C _41) #32)) (((S' _26) ((C _41) #9)) ((C _41) #10)))) ((A :46 ((S ((S (((S' _27) (_43 #65)) ((C _43) #90))) (_33 (((_784 "lib/Data/Char.hs") #3) #8)))) ((B _34) (((C' _81) (((C' _82) _35) (_35 #65))) (_35 #97))))) ((A :47 ((S ((S (((S' _27) (_43 #97)) ((C _43) #97))) (_33 (((_784 "lib/Data/Char.hs") #3) #8)))) ((B _34) (((C' _81) (((C' _82) _35) (_35 #97))) (_35 #65))))) ((A :48 _792) ((A :49 _793) ((A :50 _794) ((A :51 _795) ((A :52 (_49 %0.0)) ((A :53 _48) ((A :54 _49) ((A :55 _50) ((A :56 _51) ((A :57 _796) ((A :58 _797) ((A :59 _57) ((A :60 _58) ((A :61 _798) ((A :62 _799) ((A :63 _800) ((A :64 _801) ((A :65 _61) ((A :66 _62) ((A :67 _63) ((A :68 _64) ((A :69 _802) ((A :70 ((B BK) T)) ((A :71 (BK T)) ((A :72 P) ((A :73 I) ((A :74 B) ((A :75 I) ((A :76 K) ((A :77 C) ((A :78 _828) ((A :79 ((C ((C S') _188)) _189)) ((A :80 (((C' (S' (C' B))) B) I)) ((A :81 _786) ((A :82 _787) ((A :83 _788) ((A :84 _789) ((A :85 _790) ((A :86 _791) ((A :87 (_82 #0)) ((A :88 _809) ((A :89 _810) ((A :90 _811) ((A :91 _812) ((A :92 _813) ((A :93 _814) ((A :94 _88) ((A :95 (BK K)) ((A :96 ((B BK) ((B (B BK)) P))) ((A :97 ((B (B (B BK))) ((B (B (B BK))) ((B (B (B C))) ((B (B C)) P))))) ((A :98 (((S' S) (((S' (S' C)) (((C' (C' S)) (((C' B) ((B (S' S')) (((C' B) ((B _26) (_91 #0))) (_88 #0)))) ((B (B ((C' P) (_86 #1)))) _81))) (C P))) _84)) _85)) ((A :99 _95) ((A :100 (((S' C) ((B (P _176)) (((C' (C' B)) (((C' C) _88) _176)) _177))) ((B ((C' (C' (C' C))) (((C' (C' (C' C))) (((C' (C' (C' (C' S')))) ((B (B (B (B C)))) ((B ((C' (C' (C' C))) ((B (B (B ((S' S') (_88 #0))))) ((B ((C' (C' C)) ((B (B ((S' S') (_88 #1)))) ((B ((C' C) ((B ((C' S') (_88 #2))) (C _100)))) (C _100))))) (C _100))))) (C _100)))) (T K))) (T A)))) ((C _98) #4)))) ((A :101 (_107 _76)) ((A :102 ((_122 (_79 _101)) _99)) ((A :103 ((C (((C' B) ((P _114) (((C' (C' O)) P) K))) (((S' (C' (C' (C' B)))) ((B (B (B (B _104)))) (((S' (C' (C' B))) ((B (B (B _104))) (((S' (C' B)) ((B (B _104)) (((C' B) ((B _120) (T #0))) _103))) (((C' B) ((B _120) (T #1))) _103)))) (((C' B) ((B _120) (T #2))) _103)))) (((C' B) ((B _120) (T #3))) _103)))) ((B T) ((B (B P)) ((C' _81) (_83 #4)))))) ((A :104 ((S S) ((B BK) ((B BK) (((S' S) T) ((B BK) ((B BK) ((C (((S' C') S) ((B (B (B (S B)))) ((B (B (B (B (B BK))))) ((B ((S' (C' B)) ((B B') B'))) ((B (B (B (B (B (S B)))))) ((B (B (B (B (B (B (B BK))))))) (((C' B) (B' (B' ((B (C' (C' (C' C)))) ((B ((C' B) (B' ((B C) _90)))) ((B ((C' B) _115)) _104)))))) ((B ((C' B) _115)) (C _104)))))))))) (((_784 "lib/Data/IntMap.hs") #3) #8))))))))) ((A :105 ((_74 (_120 _188)) _103)) ((A :106 (((C' C) (((C' C) (C _100)) (_3 "Data.IntMap.!"))) I)) ((A :107 ((B ((C' B) T)) ((B (B Y)) (((C' (C' (S' (S' C)))) ((B ((S' B) ((B (S' P)) (C _96)))) ((B (B ((C' (
\ No newline at end of file
--- a/src/MicroHs/Expr.hs
+++ b/src/MicroHs/Expr.hs
@@ -442,15 +442,22 @@
 showCon (ConNew s) = showIdent s
 showCon (ConLit l) = showLit l
 
+-- Literals are tagged the way they appear in the combinator file:
+--  #   Int
+--  %   Double
+--  '   Char    (not in file)
+--  "   String
+--  ^   FFI function
+--      primitive
 showLit :: Lit -> String
 showLit l =
   case l of
-    LInt i -> showInt i
+    LInt i    -> '#' : showInt i
     LDouble d -> '%' : D.showDouble d
-    LChar c -> showChar c
-    LStr s -> showString s
-    LPrim s -> '$' : s
-    LForImp s -> '#' : s
+    LChar c   -> showChar c
+    LStr s    -> showString s
+    LPrim s   -> s
+    LForImp s -> '^' : s
 
 showEStmt :: EStmt -> String
 showEStmt as =
--- a/src/MicroHs/Main.hs
+++ b/src/MicroHs/Main.hs
@@ -47,7 +47,7 @@
         e -> e
     def :: ((Ident, Exp), Int) -> (String -> String) -> (String -> String)
     def ((_, e), i) r =
-      (("(($A :" ++ showInt i ++ " ") ++) . toStringP (substv e) . (") " ++) . r . (")" ++)
+      (("((A :" ++ showInt i ++ " ") ++) . toStringP (substv e) . (") " ++) . r . (")" ++)
     res = foldr def (toStringP emain) (zip ds (enumFrom 0)) ""
     numDefs = M.size defs
   when (verbose flags > 0) $
@@ -68,4 +68,4 @@
       putStrLn $ "final pass            " ++ padLeft 6 (showInt (t2-t1)) ++ "ms"
 
 version :: String
-version = "v3.5\n"
+version = "v4.0\n"
--- a/src/runtime/eval.c
+++ b/src/runtime/eval.c
@@ -135,7 +135,7 @@
 
 /***************************************/
 
-#define VERSION "v3.5\n"
+#define VERSION "v4.0\n"
 
 /* Keep permanent nodes for LOW_INT <= i < HIGH_INT */
 #define LOW_INT (-10)
@@ -991,7 +991,12 @@
 parse_int(BFILE *f)
 {
   value_t i = 0;
+  value_t neg = 1;
   int c = f->getb(f);
+  if (c == '-') {
+    neg = -1;
+    c = f->getb(f);
+  }
   for(;;) {
     i = i * 10 + c - '0';
     c = f->getb(f);
@@ -1000,7 +1005,7 @@
       break;
     }
   }
-  return i;
+  return neg * i;
 }
 
 double
@@ -1063,7 +1068,6 @@
   heapoffs_t l;
   value_t i;
   double d;
-  value_t neg;
   int c;
   char buf[80];                 /* store names of primitives. */
 
@@ -1078,6 +1082,15 @@
     ARG(r) = parse(f);
     if (!gobble(f, ')')) ERR("parse ')'");
     return r;
+  case '%':
+    d = parse_double(f);
+    r = mkDouble(d);
+    return r;
+  case '#':
+    i = parse_int(f);
+    r = mkInt(i);
+    return r;
+#if 0
   case '-':
     c = f->getb(f);
     neg = -1;
@@ -1086,10 +1099,6 @@
     } else {
       ERR("got -");
     }
-  case '%':
-    d = parse_double(f);
-    r = mkDouble(d);
-    return r;
   case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':
     /* integer [0-9]+*/
     neg = 1;
@@ -1098,18 +1107,7 @@
     i = neg * parse_int(f);
     r = mkInt(i);
     return r;
-  case '$':
-    /* A primitive, keep getting char's until end */
-    for (int j = 0; (buf[j] = getNT(f)); j++)
-      ;
-    /* Look up the primop and use the preallocated node. */
-    for (int j = 0; j < sizeof primops / sizeof primops[0]; j++) {
-      if (strcmp(primops[j].name, buf) == 0) {
-        return primops[j].node;
-      }
-    }
-    fprintf(stderr, "eval: bad primop %s\n", buf);
-    ERR("no primop");
+#endif
   case '_' :
     /* Reference to a shared value: _label */
     l = parse_int(f);  /* The label */
@@ -1161,7 +1159,7 @@
       r = mkStrNode(realloc(buffer, p - buffer));
       return r;
     }
-  case '#':
+  case '^':
     /* An FFI name */
     for (int j = 0; (buf[j] = getNT(f)); j++)
       ;
@@ -1169,8 +1167,18 @@
     SETVALUE(r, lookupFFIname(buf));
     return r;
   default:
-    fprintf(stderr, "parse '%c'\n", c);
-    ERR("parse default");
+    buf[0] = c;
+    /* A primitive, keep getting char's until end */
+    for (int j = 1; (buf[j] = getNT(f)); j++)
+      ;
+    /* Look up the primop and use the preallocated node. */
+    for (int j = 0; j < sizeof primops / sizeof primops[0]; j++) {
+      if (strcmp(primops[j].name, buf) == 0) {
+        return primops[j].node;
+      }
+    }
+    fprintf(stderr, "eval: bad primop %s\n", buf);
+    ERR("no primop");
   }
 }
 
@@ -1320,8 +1328,8 @@
     printrec(f, ARG(n));
     fputc(')', f);
     break;
-  case T_INT: fprintf(f, "%"PRIvalue, GETVALUE(n)); break;
-  case T_DOUBLE: fprintf(f, "%f", GETDOUBLEVALUE(n)); break;
+  case T_INT: fprintf(f, "#%"PRIvalue, GETVALUE(n)); break;
+  case T_DOUBLE: fprintf(f, "%%%f", GETDOUBLEVALUE(n)); break;
   case T_STR:
     {
       const char *p = STR(n);
@@ -1339,84 +1347,84 @@
     }
   case T_HDL:
     if (HANDLE(n) == stdin)
-      fprintf(f, "$IO.stdin");
+      fprintf(f, "IO.stdin");
     else if (HANDLE(n) == stdout)
-      fprintf(f, "$IO.stdout");
+      fprintf(f, "IO.stdout");
     else if (HANDLE(n) == stderr)
-      fprintf(f, "$IO.stderr");
+      fprintf(f, "IO.stderr");
     else
       ERR("Cannot serialize handles");
     break;
-  case T_S: fprintf(f, "$S"); break;
-  case T_K: fprintf(f, "$K"); break;
-  case T_I: fprintf(f, "$I"); break;
-  case T_C: fprintf(f, "$C"); break;
-  case T_B: fprintf(f, "$B"); break;
-  case T_A: fprintf(f, "$A"); break;
-  case T_T: fprintf(f, "$T"); break;
-  case T_Y: fprintf(f, "$Y"); break;
-  case T_P: fprintf(f, "$P"); break;
-  case T_O: fprintf(f, "$O"); break;
-  case T_SS: fprintf(f, "$S'"); break;
-  case T_BB: fprintf(f, "$B'"); break;
-  case T_BK: fprintf(f, "$BK"); break;
-  case T_CC: fprintf(f, "$C'"); break;
-  case T_ADD: fprintf(f, "$+"); break;
-  case T_SUB: fprintf(f, "$-"); break;
-  case T_MUL: fprintf(f, "$*"); break;
-  case T_QUOT: fprintf(f, "$quot"); break;
-  case T_REM: fprintf(f, "$rem"); break;
-  case T_UQUOT: fprintf(f, "$uquot"); break;
-  case T_UREM: fprintf(f, "$urem"); break;
-  case T_SUBR: fprintf(f, "$subtract"); break;
-  case T_FADD: fprintf(f, "$fadd"); break;
-  case T_FSUB: fprintf(f, "$fsub"); break;
-  case T_FMUL: fprintf(f, "$fmul"); break;
-  case T_FDIV: fprintf(f, "$fdiv"); break;
-  case T_FEQ: fprintf(f, "$feq"); break;
-  case T_FNE: fprintf(f, "$fne"); break;
-  case T_FLT: fprintf(f, "$flt"); break;
-  case T_FLE: fprintf(f, "$fle"); break;
-  case T_FGT: fprintf(f, "$fgt"); break;
-  case T_FGE: fprintf(f, "$fge"); break;
-  case T_FSHOW: fprintf(f, "$fshow"); break;
-  case T_FREAD: fprintf(f, "$fread"); break;
-  case T_EQ: fprintf(f, "$=="); break;
-  case T_NE: fprintf(f, "$/="); break;
-  case T_LT: fprintf(f, "$<"); break;
-  case T_LE: fprintf(f, "$<="); break;
-  case T_GT: fprintf(f, "$>"); break;
-  case T_GE: fprintf(f, "$>="); break;
-  case T_ULT: fprintf(f, "$u<"); break;
-  case T_ULE: fprintf(f, "$u<="); break;
-  case T_UGT: fprintf(f, "$u>"); break;
-  case T_UGE: fprintf(f, "$u>="); break;
-  case T_ERROR: fprintf(f, "$error"); break;
-  case T_EQUAL: fprintf(f, "$equal"); break;
-  case T_COMPARE: fprintf(f, "$compare"); break;
-  case T_RNF: fprintf(f, "$rnf"); break;
-  case T_SEQ: fprintf(f, "$seq"); break;
-  case T_IO_BIND: fprintf(f, "$IO.>>="); break;
-  case T_IO_THEN: fprintf(f, "$IO.>>"); break;
-  case T_IO_RETURN: fprintf(f, "$IO.return"); break;
-  case T_IO_GETCHAR: fprintf(f, "$IO.getChar"); break;
-  case T_IO_GETRAW: fprintf(f, "$IO.getRaw"); break;
-  case T_IO_PUTCHAR: fprintf(f, "$IO.putChar"); break;
-  case T_IO_SERIALIZE: fprintf(f, "$IO.serialize"); break;
-  case T_IO_PRINT: fprintf(f, "$IO.print"); break;
-  case T_IO_DESERIALIZE: fprintf(f, "$IO.deserialize"); break;
-  case T_IO_OPEN: fprintf(f, "$IO.open"); break;
-  case T_IO_CLOSE: fprintf(f, "$IO.close"); break;
-  case T_IO_FLUSH: fprintf(f, "$IO.flush"); break;
-  case T_IO_ISNULLHANDLE: fprintf(f, "$IO.isNullHandle"); break;
-  case T_IO_GETARGS: fprintf(f, "$IO.getArgs"); break;
-  case T_IO_DROPARGS: fprintf(f, "$IO.dropArgs"); break;
-  case T_IO_GETTIMEMILLI: fprintf(f, "$IO.getTimeMilli"); break;
-  case T_IO_PERFORMIO: fprintf(f, "$IO.performIO"); break;
-  case T_IO_CCALL: fprintf(f, "#%s", ffi_table[GETVALUE(n)].ffi_name); break;
-  case T_IO_CATCH: fprintf(f, "$IO.catch"); break;
-  case T_ISINT: fprintf(f, "$isInt"); break;
-  case T_ISIO: fprintf(f, "$isIO"); break;
+  case T_S: fprintf(f, "S"); break;
+  case T_K: fprintf(f, "K"); break;
+  case T_I: fprintf(f, "I"); break;
+  case T_C: fprintf(f, "C"); break;
+  case T_B: fprintf(f, "B"); break;
+  case T_A: fprintf(f, "A"); break;
+  case T_T: fprintf(f, "T"); break;
+  case T_Y: fprintf(f, "Y"); break;
+  case T_P: fprintf(f, "P"); break;
+  case T_O: fprintf(f, "O"); break;
+  case T_SS: fprintf(f, "S'"); break;
+  case T_BB: fprintf(f, "B'"); break;
+  case T_BK: fprintf(f, "BK"); break;
+  case T_CC: fprintf(f, "C'"); break;
+  case T_ADD: fprintf(f, "+"); break;
+  case T_SUB: fprintf(f, "-"); break;
+  case T_MUL: fprintf(f, "*"); break;
+  case T_QUOT: fprintf(f, "quot"); break;
+  case T_REM: fprintf(f, "rem"); break;
+  case T_UQUOT: fprintf(f, "uquot"); break;
+  case T_UREM: fprintf(f, "urem"); break;
+  case T_SUBR: fprintf(f, "subtract"); break;
+  case T_FADD: fprintf(f, "fadd"); break;
+  case T_FSUB: fprintf(f, "fsub"); break;
+  case T_FMUL: fprintf(f, "fmul"); break;
+  case T_FDIV: fprintf(f, "fdiv"); break;
+  case T_FEQ: fprintf(f, "feq"); break;
+  case T_FNE: fprintf(f, "fne"); break;
+  case T_FLT: fprintf(f, "flt"); break;
+  case T_FLE: fprintf(f, "fle"); break;
+  case T_FGT: fprintf(f, "fgt"); break;
+  case T_FGE: fprintf(f, "fge"); break;
+  case T_FSHOW: fprintf(f, "fshow"); break;
+  case T_FREAD: fprintf(f, "fread"); break;
+  case T_EQ: fprintf(f, "=="); break;
+  case T_NE: fprintf(f, "/="); break;
+  case T_LT: fprintf(f, "<"); break;
+  case T_LE: fprintf(f, "<="); break;
+  case T_GT: fprintf(f, ">"); break;
+  case T_GE: fprintf(f, ">="); break;
+  case T_ULT: fprintf(f, "u<"); break;
+  case T_ULE: fprintf(f, "u<="); break;
+  case T_UGT: fprintf(f, "u>"); break;
+  case T_UGE: fprintf(f, "u>="); break;
+  case T_ERROR: fprintf(f, "error"); break;
+  case T_EQUAL: fprintf(f, "equal"); break;
+  case T_COMPARE: fprintf(f, "compare"); break;
+  case T_RNF: fprintf(f, "rnf"); break;
+  case T_SEQ: fprintf(f, "seq"); break;
+  case T_IO_BIND: fprintf(f, "IO.>>="); break;
+  case T_IO_THEN: fprintf(f, "IO.>>"); break;
+  case T_IO_RETURN: fprintf(f, "IO.return"); break;
+  case T_IO_GETCHAR: fprintf(f, "IO.getChar"); break;
+  case T_IO_GETRAW: fprintf(f, "IO.getRaw"); break;
+  case T_IO_PUTCHAR: fprintf(f, "IO.putChar"); break;
+  case T_IO_SERIALIZE: fprintf(f, "IO.serialize"); break;
+  case T_IO_PRINT: fprintf(f, "IO.print"); break;
+  case T_IO_DESERIALIZE: fprintf(f, "IO.deserialize"); break;
+  case T_IO_OPEN: fprintf(f, "IO.open"); break;
+  case T_IO_CLOSE: fprintf(f, "IO.close"); break;
+  case T_IO_FLUSH: fprintf(f, "IO.flush"); break;
+  case T_IO_ISNULLHANDLE: fprintf(f, "IO.isNullHandle"); break;
+  case T_IO_GETARGS: fprintf(f, "IO.getArgs"); break;
+  case T_IO_DROPARGS: fprintf(f, "IO.dropArgs"); break;
+  case T_IO_GETTIMEMILLI: fprintf(f, "IO.getTimeMilli"); break;
+  case T_IO_PERFORMIO: fprintf(f, "IO.performIO"); break;
+  case T_IO_CCALL: fprintf(f, "^%s", ffi_table[GETVALUE(n)].ffi_name); break;
+  case T_IO_CATCH: fprintf(f, "IO.catch"); break;
+  case T_ISINT: fprintf(f, "isInt"); break;
+  case T_ISIO: fprintf(f, "isIO"); break;
   default: ERR("print tag");
   }
 }
@@ -2249,6 +2257,12 @@
 
   PUSH(prog); gc(); prog = TOP(0); POP(1);
   heapoffs_t start_size = num_marked;
+  if (0) {
+    /* Save GCed file, it's smaller */
+    FILE *out = fopen("gc.comb", "w");
+    print(out, prog, 1);
+    fclose(out);
+  }
   if (verbose > 2) {
     //pp(stdout, prog);
     print(stdout, prog, 1);
--- a/tests/Fac.ref
+++ b/tests/Fac.ref
@@ -1,2 +1,2 @@
-720
-6321337
+#720
+#6321337
--- a/tests/IOTest.ref
+++ b/tests/IOTest.ref
@@ -2,7 +2,7 @@
 hello
 hello
 hello
-$+
++
 ('a','z')
 "more\n"
 11
--- a/tests/Misc.ref
+++ b/tests/Misc.ref
@@ -1,1 +1,1 @@
-10
+#10
--