1*37da2899SCharles.ForsythPPrint: adt 2*37da2899SCharles.Forsyth{ 3*37da2899SCharles.Forsyth ex: ref Exec; 4*37da2899SCharles.Forsyth code: ref Code; 5*37da2899SCharles.Forsyth stack: array of string; 6*37da2899SCharles.Forsyth sp: int; 7*37da2899SCharles.Forsyth}; 8*37da2899SCharles.Forsyth 9*37da2899SCharles.Forsythmkpprint(ex: ref Exec, code: ref Code): ref PPrint 10*37da2899SCharles.Forsyth{ 11*37da2899SCharles.Forsyth return ref PPrint(ex, code, array[4] of string, 0); 12*37da2899SCharles.Forsyth} 13*37da2899SCharles.Forsyth 14*37da2899SCharles.Forsythfuncprint(ex: ref Exec, func: ref Ecmascript->Obj): string 15*37da2899SCharles.Forsyth{ 16*37da2899SCharles.Forsyth params := func.call.params; 17*37da2899SCharles.Forsyth (nil, name) := str->splitr(func.val.str, "."); 18*37da2899SCharles.Forsyth s := "function " + name + "("; 19*37da2899SCharles.Forsyth sep := ""; 20*37da2899SCharles.Forsyth for(i := 0; i < len params; i++){ 21*37da2899SCharles.Forsyth s += sep + params[i]; 22*37da2899SCharles.Forsyth sep = ", "; 23*37da2899SCharles.Forsyth } 24*37da2899SCharles.Forsyth s += "){"; 25*37da2899SCharles.Forsyth if(func.host != nil) 26*37da2899SCharles.Forsyth s += "[host code]"; 27*37da2899SCharles.Forsyth else 28*37da2899SCharles.Forsyth s += "\n" + pprint(ex, func.call.code, " "); 29*37da2899SCharles.Forsyth s += "}"; 30*37da2899SCharles.Forsyth return s; 31*37da2899SCharles.Forsyth} 32*37da2899SCharles.Forsyth 33*37da2899SCharles.Forsythpprint(ex: ref Exec, code: ref Code, indent: string): string 34*37da2899SCharles.Forsyth{ 35*37da2899SCharles.Forsyth pp := ref PPrint(ex, code, array[4] of string, 0); 36*37da2899SCharles.Forsyth#for(i:=0; i < code.npc; i++) sys->print("%d: %d\n", i, int code.ops[i]); 37*37da2899SCharles.Forsyth s := pstmt(pp, 0, code.npc, indent); 38*37da2899SCharles.Forsyth 39*37da2899SCharles.Forsyth if(pp.sp != 0) 40*37da2899SCharles.Forsyth fatal(ex, "pprint stack not balanced"); 41*37da2899SCharles.Forsyth 42*37da2899SCharles.Forsyth return s; 43*37da2899SCharles.Forsyth} 44*37da2899SCharles.Forsyth 45*37da2899SCharles.Forsythpstmt(pp: ref PPrint, pc, epc: int, indent: string): string 46*37da2899SCharles.Forsyth{ 47*37da2899SCharles.Forsyth e, e1, e2: string; 48*37da2899SCharles.Forsyth c, apc: int; 49*37da2899SCharles.Forsyth 50*37da2899SCharles.Forsyth code := pp.code; 51*37da2899SCharles.Forsyth s := ""; 52*37da2899SCharles.Forsyth while(pc < epc){ 53*37da2899SCharles.Forsyth op := int code.ops[pc++]; 54*37da2899SCharles.Forsyth while(op == Llabel){ 55*37da2899SCharles.Forsyth (pc, c) = getconst(code.ops, pc); 56*37da2899SCharles.Forsyth s += code.strs[c] + ":\n"; 57*37da2899SCharles.Forsyth op = int code.ops[pc++]; 58*37da2899SCharles.Forsyth } 59*37da2899SCharles.Forsyth s += indent; 60*37da2899SCharles.Forsyth case op{ 61*37da2899SCharles.Forsyth Lbreak or 62*37da2899SCharles.Forsyth Lcontinue or 63*37da2899SCharles.Forsyth Lreturn => 64*37da2899SCharles.Forsyth s += tokname(op); 65*37da2899SCharles.Forsyth if(op == Lreturn){ 66*37da2899SCharles.Forsyth (pc, e) = pexp(pp, pc, code.npc); 67*37da2899SCharles.Forsyth s += " " + e; 68*37da2899SCharles.Forsyth } 69*37da2899SCharles.Forsyth s += ";\n"; 70*37da2899SCharles.Forsyth Lbreaklab or 71*37da2899SCharles.Forsyth Lcontinuelab => 72*37da2899SCharles.Forsyth s += tokname(op); 73*37da2899SCharles.Forsyth (pc, c) = getconst(code.ops, pc); 74*37da2899SCharles.Forsyth s += " " + code.strs[c] + ";\n"; 75*37da2899SCharles.Forsyth '{' => 76*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, pc); 77*37da2899SCharles.Forsyth s += "{\n" + pstmt(pp, pc, apc, indent+" ") + indent + "}\n"; 78*37da2899SCharles.Forsyth pc = apc; 79*37da2899SCharles.Forsyth Lif or 80*37da2899SCharles.Forsyth Lwith or 81*37da2899SCharles.Forsyth Lwhile => 82*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, pc); 83*37da2899SCharles.Forsyth (pc, e) = pexp(pp, pc, apc); 84*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, pc); 85*37da2899SCharles.Forsyth s += tokname(op) + "(" + e + "){\n"; 86*37da2899SCharles.Forsyth s += pstmt(pp, pc, apc, indent+" "); 87*37da2899SCharles.Forsyth if(op == Lif){ 88*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, apc); 89*37da2899SCharles.Forsyth if(pc != apc) 90*37da2899SCharles.Forsyth s += indent + "}else{\n"; 91*37da2899SCharles.Forsyth s += pstmt(pp, pc, apc, indent+" "); 92*37da2899SCharles.Forsyth } 93*37da2899SCharles.Forsyth s += indent + "}\n"; 94*37da2899SCharles.Forsyth pc = apc; 95*37da2899SCharles.Forsyth Ldo => 96*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, pc); 97*37da2899SCharles.Forsyth e = pstmt(pp, pc, apc, indent+" "); 98*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, apc); 99*37da2899SCharles.Forsyth (pc, e1) = pexp(pp, pc, apc); 100*37da2899SCharles.Forsyth s += "do{\n" + e + indent + "}(while(" + e1 + ");\n"; 101*37da2899SCharles.Forsyth pc = apc; 102*37da2899SCharles.Forsyth Lfor or 103*37da2899SCharles.Forsyth Lforvar or 104*37da2899SCharles.Forsyth Lforin or 105*37da2899SCharles.Forsyth Lforvarin => 106*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, pc); 107*37da2899SCharles.Forsyth (pc, e) = pexp(pp, pc, apc); 108*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, pc); 109*37da2899SCharles.Forsyth (pc, e1) = pexp(pp, pc, apc); 110*37da2899SCharles.Forsyth s += "for("; 111*37da2899SCharles.Forsyth if(op == Lforvar || op == Lforvarin) 112*37da2899SCharles.Forsyth s += "var "; 113*37da2899SCharles.Forsyth s += e; 114*37da2899SCharles.Forsyth if(op == Lfor || op == Lforvar){ 115*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, pc); 116*37da2899SCharles.Forsyth (pc, e2) = pexp(pp, pc, apc); 117*37da2899SCharles.Forsyth s += "; " + e1 + "; " + e2; 118*37da2899SCharles.Forsyth }else 119*37da2899SCharles.Forsyth s += " in " + e1; 120*37da2899SCharles.Forsyth s += "){\n"; 121*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, pc); 122*37da2899SCharles.Forsyth s += pstmt(pp, pc, apc, indent+" "); 123*37da2899SCharles.Forsyth s += indent + "}\n"; 124*37da2899SCharles.Forsyth pc = apc; 125*37da2899SCharles.Forsyth ';' => 126*37da2899SCharles.Forsyth s += ";\n"; 127*37da2899SCharles.Forsyth Lvar => 128*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, pc); 129*37da2899SCharles.Forsyth (pc, e) = pexp(pp, pc, apc); 130*37da2899SCharles.Forsyth s += "var " + e + ";\n"; 131*37da2899SCharles.Forsyth Lswitch => 132*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, pc); 133*37da2899SCharles.Forsyth (pc, e) = pexp(pp, pc, apc); 134*37da2899SCharles.Forsyth s += "switch (" + e + ") {\n"; 135*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, pc); 136*37da2899SCharles.Forsyth (pc, e) = pcaseblk(pp, pc, apc, indent); 137*37da2899SCharles.Forsyth s += e + indent + "}\n"; 138*37da2899SCharles.Forsyth pc = apc; 139*37da2899SCharles.Forsyth Lthrow => 140*37da2899SCharles.Forsyth (pc, e) = pexp(pp, pc, code.npc); 141*37da2899SCharles.Forsyth s += "throw " + e + "\n"; 142*37da2899SCharles.Forsyth Ltry => 143*37da2899SCharles.Forsyth s += "try\n"; 144*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, pc); 145*37da2899SCharles.Forsyth s += pstmt(pp, pc, apc, indent+" "); 146*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, apc); 147*37da2899SCharles.Forsyth if(pc != apc){ 148*37da2899SCharles.Forsyth (pc, c) = getconst(code.ops, ++pc); 149*37da2899SCharles.Forsyth s += "catch(" + code.strs[c] + ")\n"; 150*37da2899SCharles.Forsyth s += pstmt(pp, pc, apc, indent+" "); 151*37da2899SCharles.Forsyth } 152*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, apc); 153*37da2899SCharles.Forsyth if(pc != apc){ 154*37da2899SCharles.Forsyth s += "finally\n"; 155*37da2899SCharles.Forsyth s += pstmt(pp, pc, apc, indent+" "); 156*37da2899SCharles.Forsyth } 157*37da2899SCharles.Forsyth pc = apc; 158*37da2899SCharles.Forsyth * => 159*37da2899SCharles.Forsyth (pc, e) = pexp(pp, pc-1, code.npc); 160*37da2899SCharles.Forsyth s += e + ";\n"; 161*37da2899SCharles.Forsyth } 162*37da2899SCharles.Forsyth } 163*37da2899SCharles.Forsyth return s; 164*37da2899SCharles.Forsyth} 165*37da2899SCharles.Forsyth 166*37da2899SCharles.Forsythpexp(pp: ref PPrint, pc, epc: int): (int, string) 167*37da2899SCharles.Forsyth{ 168*37da2899SCharles.Forsyth c, apc: int; 169*37da2899SCharles.Forsyth s, f, a, a1, a2: string; 170*37da2899SCharles.Forsyth 171*37da2899SCharles.Forsyth code := pp.code; 172*37da2899SCharles.Forsyth savesp := pp.sp; 173*37da2899SCharles.Forsythout: while(pc < epc){ 174*37da2899SCharles.Forsyth case op := int code.ops[pc++]{ 175*37da2899SCharles.Forsyth Lthis => 176*37da2899SCharles.Forsyth s = "this"; 177*37da2899SCharles.Forsyth Lid or 178*37da2899SCharles.Forsyth Lnum or 179*37da2899SCharles.Forsyth Lstr or 180*37da2899SCharles.Forsyth Lregexp => 181*37da2899SCharles.Forsyth (pc, c) = getconst(code.ops, pc); 182*37da2899SCharles.Forsyth if(op == Lnum) 183*37da2899SCharles.Forsyth s = string code.nums[c]; 184*37da2899SCharles.Forsyth else{ 185*37da2899SCharles.Forsyth s = code.strs[c]; 186*37da2899SCharles.Forsyth if(op == Lstr) 187*37da2899SCharles.Forsyth s = "\""+escstr(code.strs[c])+"\""; 188*37da2899SCharles.Forsyth } 189*37da2899SCharles.Forsyth '*' or 190*37da2899SCharles.Forsyth '/' or 191*37da2899SCharles.Forsyth '%' or 192*37da2899SCharles.Forsyth '+' or 193*37da2899SCharles.Forsyth '-' or 194*37da2899SCharles.Forsyth Llsh or 195*37da2899SCharles.Forsyth Lrsh or 196*37da2899SCharles.Forsyth Lrshu or 197*37da2899SCharles.Forsyth '<' or 198*37da2899SCharles.Forsyth '>' or 199*37da2899SCharles.Forsyth Lleq or 200*37da2899SCharles.Forsyth Lgeq or 201*37da2899SCharles.Forsyth Lin or 202*37da2899SCharles.Forsyth Linstanceof or 203*37da2899SCharles.Forsyth Leq or 204*37da2899SCharles.Forsyth Lneq or 205*37da2899SCharles.Forsyth Lseq or 206*37da2899SCharles.Forsyth Lsne or 207*37da2899SCharles.Forsyth '&' or 208*37da2899SCharles.Forsyth '^' or 209*37da2899SCharles.Forsyth '|' or 210*37da2899SCharles.Forsyth '=' or 211*37da2899SCharles.Forsyth '.' or 212*37da2899SCharles.Forsyth ',' or 213*37da2899SCharles.Forsyth '[' => 214*37da2899SCharles.Forsyth a2 = ppop(pp); 215*37da2899SCharles.Forsyth a1 = ppop(pp); 216*37da2899SCharles.Forsyth s = tokname(op); 217*37da2899SCharles.Forsyth if(a1[0] == '='){ 218*37da2899SCharles.Forsyth s += "="; 219*37da2899SCharles.Forsyth a1 = a1[1:]; 220*37da2899SCharles.Forsyth } 221*37da2899SCharles.Forsyth if(op == '[') 222*37da2899SCharles.Forsyth s = a1 + "[" + a2 + "]"; 223*37da2899SCharles.Forsyth else{ 224*37da2899SCharles.Forsyth if(op != '.'){ 225*37da2899SCharles.Forsyth if(op != ',') 226*37da2899SCharles.Forsyth s = " " + s; 227*37da2899SCharles.Forsyth s = s + " "; 228*37da2899SCharles.Forsyth } 229*37da2899SCharles.Forsyth s = a1 + s + a2; 230*37da2899SCharles.Forsyth } 231*37da2899SCharles.Forsyth Ltypeof or 232*37da2899SCharles.Forsyth Ldelete or 233*37da2899SCharles.Forsyth Lvoid or 234*37da2899SCharles.Forsyth Lnew or 235*37da2899SCharles.Forsyth Linc or 236*37da2899SCharles.Forsyth Ldec or 237*37da2899SCharles.Forsyth Lpreadd or 238*37da2899SCharles.Forsyth Lpresub or 239*37da2899SCharles.Forsyth '~' or 240*37da2899SCharles.Forsyth '!' or 241*37da2899SCharles.Forsyth Lpostinc or 242*37da2899SCharles.Forsyth Lpostdec => 243*37da2899SCharles.Forsyth a = ppop(pp); 244*37da2899SCharles.Forsyth s = tokname(op); 245*37da2899SCharles.Forsyth if(op == Lpostinc || op == Lpostdec) 246*37da2899SCharles.Forsyth s = a + s; 247*37da2899SCharles.Forsyth else{ 248*37da2899SCharles.Forsyth if(op == Ltypeof || op == Ldelete || op == Lvoid || op == Lnew) 249*37da2899SCharles.Forsyth s += " "; 250*37da2899SCharles.Forsyth s += a; 251*37da2899SCharles.Forsyth } 252*37da2899SCharles.Forsyth '(' => 253*37da2899SCharles.Forsyth s = "("; 254*37da2899SCharles.Forsyth ')' => 255*37da2899SCharles.Forsyth s = ppop(pp); 256*37da2899SCharles.Forsyth if(ppop(pp) != "(") 257*37da2899SCharles.Forsyth fatal(pp.ex, "unbalanced () in pexp"); 258*37da2899SCharles.Forsyth s = "(" + s + ")"; 259*37da2899SCharles.Forsyth Lgetval or 260*37da2899SCharles.Forsyth Las => 261*37da2899SCharles.Forsyth continue; 262*37da2899SCharles.Forsyth Lasop => 263*37da2899SCharles.Forsyth s = "=" + ppop(pp); 264*37da2899SCharles.Forsyth Lcall or 265*37da2899SCharles.Forsyth Lnewcall => 266*37da2899SCharles.Forsyth (pc, c) = getconst(code.ops, pc); 267*37da2899SCharles.Forsyth a = ""; 268*37da2899SCharles.Forsyth sep := ""; 269*37da2899SCharles.Forsyth for(sp := pp.sp-c; sp < pp.sp; sp++){ 270*37da2899SCharles.Forsyth a += sep + pp.stack[sp]; 271*37da2899SCharles.Forsyth sep = ", "; 272*37da2899SCharles.Forsyth } 273*37da2899SCharles.Forsyth pp.sp -= c; 274*37da2899SCharles.Forsyth f = ppop(pp); 275*37da2899SCharles.Forsyth if(op == Lnewcall) 276*37da2899SCharles.Forsyth f = "new " + f; 277*37da2899SCharles.Forsyth s = f + "(" + a + ")"; 278*37da2899SCharles.Forsyth ';' => 279*37da2899SCharles.Forsyth break out; 280*37da2899SCharles.Forsyth Landand or 281*37da2899SCharles.Forsyth Loror or 282*37da2899SCharles.Forsyth '?' => 283*37da2899SCharles.Forsyth s = ppop(pp); 284*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, pc); 285*37da2899SCharles.Forsyth (pc, a1) = pexp(pp, pc, apc); 286*37da2899SCharles.Forsyth s += " " + tokname(op) + " " + a1; 287*37da2899SCharles.Forsyth if(op == '?'){ 288*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, pc); 289*37da2899SCharles.Forsyth (pc, a2) = pexp(pp, pc, apc); 290*37da2899SCharles.Forsyth s += " : "+ a2; 291*37da2899SCharles.Forsyth } 292*37da2899SCharles.Forsyth * => 293*37da2899SCharles.Forsyth fatal(pp.ex, "pexp: unknown op " + tokname(op)); 294*37da2899SCharles.Forsyth } 295*37da2899SCharles.Forsyth ppush(pp, s); 296*37da2899SCharles.Forsyth } 297*37da2899SCharles.Forsyth 298*37da2899SCharles.Forsyth if(savesp == pp.sp) 299*37da2899SCharles.Forsyth return (pc, ""); 300*37da2899SCharles.Forsyth 301*37da2899SCharles.Forsyth if(savesp != pp.sp-1) 302*37da2899SCharles.Forsyth fatal(pp.ex, "unbalanced stack in pexp"); 303*37da2899SCharles.Forsyth return (pc, ppop(pp)); 304*37da2899SCharles.Forsyth} 305*37da2899SCharles.Forsyth 306*37da2899SCharles.Forsythpcaseblk(pp: ref PPrint, pc, epc: int, indent: string): (int, string) 307*37da2899SCharles.Forsyth{ 308*37da2899SCharles.Forsyth code := pp.code; 309*37da2899SCharles.Forsyth defpc, clausepc, nextpc, apc: int; 310*37da2899SCharles.Forsyth s, a: string; 311*37da2899SCharles.Forsyth 312*37da2899SCharles.Forsyth (pc, defpc) = getjmp(code.ops, pc); 313*37da2899SCharles.Forsyth clausepc = pc; 314*37da2899SCharles.Forsyth (pc, nextpc) = getjmp(code.ops, pc); 315*37da2899SCharles.Forsyth for (; pc < epc; (clausepc, (pc, nextpc)) = (nextpc, getjmp(code.ops, nextpc))) { 316*37da2899SCharles.Forsyth if (clausepc == defpc) { 317*37da2899SCharles.Forsyth s += indent + "default:\n"; 318*37da2899SCharles.Forsyth } else { 319*37da2899SCharles.Forsyth (pc, apc) = getjmp(code.ops, pc); 320*37da2899SCharles.Forsyth (pc, a) = pexp(pp, pc, apc); 321*37da2899SCharles.Forsyth s += indent + "case " + a + ":\n"; 322*37da2899SCharles.Forsyth } 323*37da2899SCharles.Forsyth s += pstmt(pp, pc, nextpc, indent+"\t"); 324*37da2899SCharles.Forsyth } 325*37da2899SCharles.Forsyth return (epc, s); 326*37da2899SCharles.Forsyth} 327*37da2899SCharles.Forsyth 328*37da2899SCharles.Forsythppush(pp: ref PPrint, s: string) 329*37da2899SCharles.Forsyth{ 330*37da2899SCharles.Forsyth if(pp.sp >= len pp.stack){ 331*37da2899SCharles.Forsyth st := array[2 * len pp.stack] of string; 332*37da2899SCharles.Forsyth st[:] = pp.stack; 333*37da2899SCharles.Forsyth pp.stack = st; 334*37da2899SCharles.Forsyth } 335*37da2899SCharles.Forsyth pp.stack[pp.sp++] = s; 336*37da2899SCharles.Forsyth} 337*37da2899SCharles.Forsyth 338*37da2899SCharles.Forsythppop(pp: ref PPrint): string 339*37da2899SCharles.Forsyth{ 340*37da2899SCharles.Forsyth if(pp.sp == 0) 341*37da2899SCharles.Forsyth fatal(pp.ex, "popping too far off the pstack"); 342*37da2899SCharles.Forsyth return pp.stack[--pp.sp]; 343*37da2899SCharles.Forsyth} 344*37da2899SCharles.Forsyth 345*37da2899SCharles.Forsythunescmap := array[128] of 346*37da2899SCharles.Forsyth{ 347*37da2899SCharles.Forsyth '\'' => byte '\'', 348*37da2899SCharles.Forsyth '"' => byte '"', 349*37da2899SCharles.Forsyth '\\' => byte '\\', 350*37da2899SCharles.Forsyth '\b' => byte 'b', 351*37da2899SCharles.Forsyth '\u000c' => byte 'f', 352*37da2899SCharles.Forsyth '\n' => byte 'n', 353*37da2899SCharles.Forsyth '\r' => byte 'r', 354*37da2899SCharles.Forsyth '\t' => byte 't', 355*37da2899SCharles.Forsyth 356*37da2899SCharles.Forsyth * => byte 0 357*37da2899SCharles.Forsyth}; 358*37da2899SCharles.Forsyth 359*37da2899SCharles.Forsythescstr(s: string): string 360*37da2899SCharles.Forsyth{ 361*37da2899SCharles.Forsyth n := len s; 362*37da2899SCharles.Forsyth sb := ""; 363*37da2899SCharles.Forsyth for(i := 0; i < n; i++){ 364*37da2899SCharles.Forsyth c := s[i]; 365*37da2899SCharles.Forsyth if(c < 128 && (e := int unescmap[c])){ 366*37da2899SCharles.Forsyth sb[len sb] = '\\'; 367*37da2899SCharles.Forsyth sb[len sb] = e; 368*37da2899SCharles.Forsyth }else if(c > 128 || c < 32){ 369*37da2899SCharles.Forsyth sb += "\\u0000"; 370*37da2899SCharles.Forsyth for(j := 1; j <= 4; j++){ 371*37da2899SCharles.Forsyth sb[len sb - j] = "0123456789abcdef"[c & 16rf]; 372*37da2899SCharles.Forsyth c >>= 4; 373*37da2899SCharles.Forsyth } 374*37da2899SCharles.Forsyth }else 375*37da2899SCharles.Forsyth sb[len sb] = c; 376*37da2899SCharles.Forsyth } 377*37da2899SCharles.Forsyth return sb; 378*37da2899SCharles.Forsyth} 379