Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include "jsi.h"
  2. #include "jsparse.h"
  3. #include "jscompile.h"
  4. #include "jsvalue.h"
  5.  
  6. #include "utf.h"
  7.  
  8. #include <assert.h>
  9.  
  10. static const char *astname[] = {
  11. #include "astnames.h"
  12. NULL
  13. };
  14.  
  15. static const char *opname[] = {
  16. #include "opnames.h"
  17. NULL
  18. };
  19.  
  20. static int minify = 0;
  21.  
  22. const char *jsP_aststring(enum js_AstType type)
  23. {
  24.         if (type < nelem(astname)-1)
  25.                 return astname[type];
  26.         return "<unknown>";
  27. }
  28.  
  29. const char *jsC_opcodestring(enum js_OpCode opcode)
  30. {
  31.         if (opcode < nelem(opname)-1)
  32.                 return opname[opcode];
  33.         return "<unknown>";
  34. }
  35.  
  36. static int prec(enum js_AstType type)
  37. {
  38.         switch (type) {
  39.         case AST_IDENTIFIER:
  40.         case EXP_IDENTIFIER:
  41.         case EXP_NUMBER:
  42.         case EXP_STRING:
  43.         case EXP_REGEXP:
  44.         case EXP_UNDEF:
  45.         case EXP_NULL:
  46.         case EXP_TRUE:
  47.         case EXP_FALSE:
  48.         case EXP_THIS:
  49.         case EXP_ARRAY:
  50.         case EXP_OBJECT:
  51.                 return 170;
  52.  
  53.         case EXP_FUN:
  54.         case EXP_INDEX:
  55.         case EXP_MEMBER:
  56.         case EXP_CALL:
  57.         case EXP_NEW:
  58.                 return 160;
  59.  
  60.         case EXP_POSTINC:
  61.         case EXP_POSTDEC:
  62.                 return 150;
  63.  
  64.         case EXP_DELETE:
  65.         case EXP_VOID:
  66.         case EXP_TYPEOF:
  67.         case EXP_PREINC:
  68.         case EXP_PREDEC:
  69.         case EXP_POS:
  70.         case EXP_NEG:
  71.         case EXP_BITNOT:
  72.         case EXP_LOGNOT:
  73.                 return 140;
  74.  
  75.         case EXP_MOD:
  76.         case EXP_DIV:
  77.         case EXP_MUL:
  78.                 return 130;
  79.  
  80.         case EXP_SUB:
  81.         case EXP_ADD:
  82.                 return 120;
  83.  
  84.         case EXP_USHR:
  85.         case EXP_SHR:
  86.         case EXP_SHL:
  87.                 return 110;
  88.  
  89.         case EXP_IN:
  90.         case EXP_INSTANCEOF:
  91.         case EXP_GE:
  92.         case EXP_LE:
  93.         case EXP_GT:
  94.         case EXP_LT:
  95.                 return 100;
  96.  
  97.         case EXP_STRICTNE:
  98.         case EXP_STRICTEQ:
  99.         case EXP_NE:
  100.         case EXP_EQ:
  101.                 return 90;
  102.  
  103.         case EXP_BITAND: return 80;
  104.         case EXP_BITXOR: return 70;
  105.         case EXP_BITOR: return 60;
  106.         case EXP_LOGAND: return 50;
  107.         case EXP_LOGOR: return 40;
  108.  
  109.         case EXP_COND:
  110.                 return 30;
  111.  
  112.         case EXP_ASS:
  113.         case EXP_ASS_MUL:
  114.         case EXP_ASS_DIV:
  115.         case EXP_ASS_MOD:
  116.         case EXP_ASS_ADD:
  117.         case EXP_ASS_SUB:
  118.         case EXP_ASS_SHL:
  119.         case EXP_ASS_SHR:
  120.         case EXP_ASS_USHR:
  121.         case EXP_ASS_BITAND:
  122.         case EXP_ASS_BITXOR:
  123.         case EXP_ASS_BITOR:
  124.                 return 20;
  125.  
  126. #define COMMA 15
  127.  
  128.         case EXP_COMMA:
  129.                 return 10;
  130.  
  131.         default:
  132.                 return 0;
  133.         }
  134. }
  135.  
  136. static void pc(int c)
  137. {
  138.         putchar(c);
  139. }
  140.  
  141. static void ps(const char *s)
  142. {
  143.         fputs(s, stdout);
  144. }
  145.  
  146. static void pn(int n)
  147. {
  148.         printf("%d", n);
  149. }
  150.  
  151. static void in(int d)
  152. {
  153.         if (minify < 1)
  154.                 while (d-- > 0)
  155.                         putchar('\t');
  156. }
  157.  
  158. static void nl(void)
  159. {
  160.         if (minify < 2)
  161.                 putchar('\n');
  162. }
  163.  
  164. static void sp(void)
  165. {
  166.         if (minify < 1)
  167.                 putchar(' ');
  168. }
  169.  
  170. static void comma(void)
  171. {
  172.         putchar(',');
  173.         sp();
  174. }
  175.  
  176. /* Pretty-printed Javascript syntax */
  177.  
  178. static void pstmlist(int d, js_Ast *list);
  179. static void pexpi(int d, int i, js_Ast *exp);
  180. static void pstm(int d, js_Ast *stm);
  181. static void slist(int d, js_Ast *list);
  182. static void sblock(int d, js_Ast *list);
  183.  
  184. static void pargs(int d, js_Ast *list)
  185. {
  186.         while (list) {
  187.                 assert(list->type == AST_LIST);
  188.                 pexpi(d, COMMA, list->a);
  189.                 list = list->b;
  190.                 if (list)
  191.                         comma();
  192.         }
  193. }
  194.  
  195. static void parray(int d, js_Ast *list)
  196. {
  197.         pc('[');
  198.         while (list) {
  199.                 assert(list->type == AST_LIST);
  200.                 pexpi(d, COMMA, list->a);
  201.                 list = list->b;
  202.                 if (list)
  203.                         comma();
  204.         }
  205.         pc(']');
  206. }
  207.  
  208. static void pobject(int d, js_Ast *list)
  209. {
  210.         pc('{');
  211.         if (list) {
  212.                 nl();
  213.                 in(d+1);
  214.         }
  215.         while (list) {
  216.                 js_Ast *kv = list->a;
  217.                 assert(list->type == AST_LIST);
  218.                 switch (kv->type) {
  219.                 default: break;
  220.                 case EXP_PROP_VAL:
  221.                         pexpi(d+1, COMMA, kv->a);
  222.                         pc(':'); sp();
  223.                         pexpi(d+1, COMMA, kv->b);
  224.                         break;
  225.                 case EXP_PROP_GET:
  226.                         ps("get ");
  227.                         pexpi(d+1, COMMA, kv->a);
  228.                         ps("()"); sp(); pc('{'); nl();
  229.                         pstmlist(d+1, kv->c);
  230.                         in(d+1); pc('}');
  231.                         break;
  232.                 case EXP_PROP_SET:
  233.                         ps("set ");
  234.                         pexpi(d+1, COMMA, kv->a);
  235.                         pc('(');
  236.                         pargs(d+1, kv->b);
  237.                         pc(')'); sp(); pc('{'); nl();
  238.                         pstmlist(d+1, kv->c);
  239.                         in(d+1); pc('}');
  240.                         break;
  241.                 }
  242.                 list = list->b;
  243.                 if (list) {
  244.                         pc(',');
  245.                         nl();
  246.                         in(d+1);
  247.                 } else {
  248.                         nl();
  249.                         in(d);
  250.                 }
  251.         }
  252.         pc('}');
  253. }
  254.  
  255. static void pstr(const char *s)
  256. {
  257.         static const char *HEX = "0123456789ABCDEF";
  258.         Rune c;
  259.         pc(minify ? '\'' : '"');
  260.         while (*s) {
  261.                 s += chartorune(&c, s);
  262.                 switch (c) {
  263.                 case '\'': ps("\\'"); break;
  264.                 case '"': ps("\\\""); break;
  265.                 case '\\': ps("\\\\"); break;
  266.                 case '\b': ps("\\b"); break;
  267.                 case '\f': ps("\\f"); break;
  268.                 case '\n': ps("\\n"); break;
  269.                 case '\r': ps("\\r"); break;
  270.                 case '\t': ps("\\t"); break;
  271.                 default:
  272.                         if (c < ' ' || c > 127) {
  273.                                 ps("\\u");
  274.                                 pc(HEX[(c>>12)&15]);
  275.                                 pc(HEX[(c>>8)&15]);
  276.                                 pc(HEX[(c>>4)&15]);
  277.                                 pc(HEX[c&15]);
  278.                         } else {
  279.                                 pc(c); break;
  280.                         }
  281.                 }
  282.         }
  283.         pc(minify ? '\'' : '"');
  284. }
  285.  
  286. static void pregexp(const char *prog, int flags)
  287. {
  288.         pc('/');
  289.         ps(prog);
  290.         pc('/');
  291.         if (flags & JS_REGEXP_G) pc('g');
  292.         if (flags & JS_REGEXP_I) pc('i');
  293.         if (flags & JS_REGEXP_M) pc('m');
  294. }
  295.  
  296. static void pbin(int d, int p, js_Ast *exp, const char *op)
  297. {
  298.         pexpi(d, p, exp->a);
  299.         sp();
  300.         ps(op);
  301.         sp();
  302.         pexpi(d, p, exp->b);
  303. }
  304.  
  305. static void puna(int d, int p, js_Ast *exp, const char *pre, const char *suf)
  306. {
  307.         ps(pre);
  308.         pexpi(d, p, exp->a);
  309.         ps(suf);
  310. }
  311.  
  312. static void pexpi(int d, int p, js_Ast *exp)
  313. {
  314.         int tp, paren;
  315.  
  316.         if (!exp) return;
  317.  
  318.         tp = prec(exp->type);
  319.         paren = 0;
  320.         if (tp < p) {
  321.                 pc('(');
  322.                 paren = 1;
  323.         }
  324.         p = tp;
  325.  
  326.         switch (exp->type) {
  327.         case AST_IDENTIFIER: ps(exp->string); break;
  328.         case EXP_IDENTIFIER: ps(exp->string); break;
  329.         case EXP_NUMBER: printf("%.9g", exp->number); break;
  330.         case EXP_STRING: pstr(exp->string); break;
  331.         case EXP_REGEXP: pregexp(exp->string, exp->number); break;
  332.  
  333.         case EXP_UNDEF: break;
  334.         case EXP_NULL: ps("null"); break;
  335.         case EXP_TRUE: ps("true"); break;
  336.         case EXP_FALSE: ps("false"); break;
  337.         case EXP_THIS: ps("this"); break;
  338.  
  339.         case EXP_OBJECT: pobject(d, exp->a); break;
  340.         case EXP_ARRAY: parray(d, exp->a); break;
  341.  
  342.         case EXP_DELETE: puna(d, p, exp, "delete ", ""); break;
  343.         case EXP_VOID: puna(d, p, exp, "void ", ""); break;
  344.         case EXP_TYPEOF: puna(d, p, exp, "typeof ", ""); break;
  345.         case EXP_PREINC: puna(d, p, exp, "++", ""); break;
  346.         case EXP_PREDEC: puna(d, p, exp, "--", ""); break;
  347.         case EXP_POSTINC: puna(d, p, exp, "", "++"); break;
  348.         case EXP_POSTDEC: puna(d, p, exp, "", "--"); break;
  349.         case EXP_POS: puna(d, p, exp, "+", ""); break;
  350.         case EXP_NEG: puna(d, p, exp, "-", ""); break;
  351.         case EXP_BITNOT: puna(d, p, exp, "~", ""); break;
  352.         case EXP_LOGNOT: puna(d, p, exp, "!", ""); break;
  353.  
  354.         case EXP_LOGOR: pbin(d, p, exp, "||"); break;
  355.         case EXP_LOGAND: pbin(d, p, exp, "&&"); break;
  356.         case EXP_BITOR: pbin(d, p, exp, "|"); break;
  357.         case EXP_BITXOR: pbin(d, p, exp, "^"); break;
  358.         case EXP_BITAND: pbin(d, p, exp, "&"); break;
  359.         case EXP_EQ: pbin(d, p, exp, "=="); break;
  360.         case EXP_NE: pbin(d, p, exp, "!="); break;
  361.         case EXP_STRICTEQ: pbin(d, p, exp, "==="); break;
  362.         case EXP_STRICTNE: pbin(d, p, exp, "!=="); break;
  363.         case EXP_LT: pbin(d, p, exp, "<"); break;
  364.         case EXP_GT: pbin(d, p, exp, ">"); break;
  365.         case EXP_LE: pbin(d, p, exp, "<="); break;
  366.         case EXP_GE: pbin(d, p, exp, ">="); break;
  367.         case EXP_IN: pbin(d, p, exp, "in"); break;
  368.         case EXP_SHL: pbin(d, p, exp, "<<"); break;
  369.         case EXP_SHR: pbin(d, p, exp, ">>"); break;
  370.         case EXP_USHR: pbin(d, p, exp, ">>>"); break;
  371.         case EXP_ADD: pbin(d, p, exp, "+"); break;
  372.         case EXP_SUB: pbin(d, p, exp, "-"); break;
  373.         case EXP_MUL: pbin(d, p, exp, "*"); break;
  374.         case EXP_DIV: pbin(d, p, exp, "/"); break;
  375.         case EXP_MOD: pbin(d, p, exp, "%"); break;
  376.         case EXP_ASS: pbin(d, p, exp, "="); break;
  377.         case EXP_ASS_MUL: pbin(d, p, exp, "*="); break;
  378.         case EXP_ASS_DIV: pbin(d, p, exp, "/="); break;
  379.         case EXP_ASS_MOD: pbin(d, p, exp, "%="); break;
  380.         case EXP_ASS_ADD: pbin(d, p, exp, "+="); break;
  381.         case EXP_ASS_SUB: pbin(d, p, exp, "-="); break;
  382.         case EXP_ASS_SHL: pbin(d, p, exp, "<<="); break;
  383.         case EXP_ASS_SHR: pbin(d, p, exp, ">>="); break;
  384.         case EXP_ASS_USHR: pbin(d, p, exp, ">>>="); break;
  385.         case EXP_ASS_BITAND: pbin(d, p, exp, "&="); break;
  386.         case EXP_ASS_BITXOR: pbin(d, p, exp, "^="); break;
  387.         case EXP_ASS_BITOR: pbin(d, p, exp, "|="); break;
  388.  
  389.         case EXP_INSTANCEOF:
  390.                 pexpi(d, p, exp->a);
  391.                 ps(" instanceof ");
  392.                 pexpi(d, p, exp->b);
  393.                 break;
  394.  
  395.         case EXP_COMMA:
  396.                 pexpi(d, p, exp->a);
  397.                 pc(','); sp();
  398.                 pexpi(d, p, exp->b);
  399.                 break;
  400.  
  401.         case EXP_COND:
  402.                 pexpi(d, p, exp->a);
  403.                 sp(); pc('?'); sp();
  404.                 pexpi(d, p, exp->b);
  405.                 sp(); pc(':'); sp();
  406.                 pexpi(d, p, exp->c);
  407.                 break;
  408.  
  409.         case EXP_INDEX:
  410.                 pexpi(d, p, exp->a);
  411.                 pc('[');
  412.                 pexpi(d, 0, exp->b);
  413.                 pc(']');
  414.                 break;
  415.  
  416.         case EXP_MEMBER:
  417.                 pexpi(d, p, exp->a);
  418.                 pc('.');
  419.                 pexpi(d, 0, exp->b);
  420.                 break;
  421.  
  422.         case EXP_CALL:
  423.                 pexpi(d, p, exp->a);
  424.                 pc('(');
  425.                 pargs(d, exp->b);
  426.                 pc(')');
  427.                 break;
  428.  
  429.         case EXP_NEW:
  430.                 ps("new ");
  431.                 pexpi(d, p, exp->a);
  432.                 pc('(');
  433.                 pargs(d, exp->b);
  434.                 pc(')');
  435.                 break;
  436.  
  437.         case EXP_FUN:
  438.                 if (p == 0) pc('(');
  439.                 ps("function ");
  440.                 pexpi(d, 0, exp->a);
  441.                 pc('(');
  442.                 pargs(d, exp->b);
  443.                 pc(')'); sp(); pc('{'); nl();
  444.                 pstmlist(d, exp->c);
  445.                 in(d); pc('}');
  446.                 if (p == 0) pc(')');
  447.                 break;
  448.  
  449.         default:
  450.                 ps("<UNKNOWN>");
  451.                 break;
  452.         }
  453.  
  454.         if (paren) pc(')');
  455. }
  456.  
  457. static void pexp(int d, js_Ast *exp)
  458. {
  459.         pexpi(d, 0, exp);
  460. }
  461.  
  462. static void pvar(int d, js_Ast *var)
  463. {
  464.         assert(var->type == EXP_VAR);
  465.         pexp(d, var->a);
  466.         if (var->b) {
  467.                 sp(); pc('='); sp();
  468.                 pexp(d, var->b);
  469.         }
  470. }
  471.  
  472. static void pvarlist(int d, js_Ast *list)
  473. {
  474.         while (list) {
  475.                 assert(list->type == AST_LIST);
  476.                 pvar(d, list->a);
  477.                 list = list->b;
  478.                 if (list)
  479.                         comma();
  480.         }
  481. }
  482.  
  483. static void pblock(int d, js_Ast *block)
  484. {
  485.         assert(block->type == STM_BLOCK);
  486.         pc('{'); nl();
  487.         pstmlist(d, block->a);
  488.         in(d); pc('}');
  489. }
  490.  
  491. static void pstmh(int d, js_Ast *stm)
  492. {
  493.         if (stm->type == STM_BLOCK) {
  494.                 sp();
  495.                 pblock(d, stm);
  496.         } else {
  497.                 nl();
  498.                 pstm(d+1, stm);
  499.         }
  500. }
  501.  
  502. static void pcaselist(int d, js_Ast *list)
  503. {
  504.         while (list) {
  505.                 js_Ast *stm = list->a;
  506.                 if (stm->type == STM_CASE) {
  507.                         in(d); ps("case "); pexp(d, stm->a); pc(':'); nl();
  508.                         pstmlist(d, stm->b);
  509.                 }
  510.                 if (stm->type == STM_DEFAULT) {
  511.                         in(d); ps("default:"); nl();
  512.                         pstmlist(d, stm->a);
  513.                 }
  514.                 list = list->b;
  515.         }
  516. }
  517.  
  518. static void pstm(int d, js_Ast *stm)
  519. {
  520.         if (stm->type == STM_BLOCK) {
  521.                 pblock(d, stm);
  522.                 return;
  523.         }
  524.  
  525.         in(d);
  526.  
  527.         switch (stm->type) {
  528.         case AST_FUNDEC:
  529.                 ps("function ");
  530.                 pexp(d, stm->a);
  531.                 pc('(');
  532.                 pargs(d, stm->b);
  533.                 pc(')'); sp(); pc('{'); nl();
  534.                 pstmlist(d, stm->c);
  535.                 in(d); pc('}');
  536.                 break;
  537.  
  538.         case STM_EMPTY:
  539.                 pc(';');
  540.                 break;
  541.  
  542.         case STM_VAR:
  543.                 ps("var ");
  544.                 pvarlist(d, stm->a);
  545.                 pc(';');
  546.                 break;
  547.  
  548.         case STM_IF:
  549.                 ps("if"); sp(); pc('('); pexp(d, stm->a); pc(')');
  550.                 pstmh(d, stm->b);
  551.                 if (stm->c) {
  552.                         nl(); in(d); ps("else");
  553.                         pstmh(d, stm->c);
  554.                 }
  555.                 break;
  556.  
  557.         case STM_DO:
  558.                 ps("do");
  559.                 pstmh(d, stm->a);
  560.                 nl();
  561.                 in(d); ps("while"); sp(); pc('('); pexp(d, stm->b); pc(')'); pc(';');
  562.                 break;
  563.  
  564.         case STM_WHILE:
  565.                 ps("while"); sp(); pc('('); pexp(d, stm->a); pc(')');
  566.                 pstmh(d, stm->b);
  567.                 break;
  568.  
  569.         case STM_FOR:
  570.                 ps("for"); sp(); pc('(');
  571.                 pexp(d, stm->a); pc(';'); sp();
  572.                 pexp(d, stm->b); pc(';'); sp();
  573.                 pexp(d, stm->c); pc(')');
  574.                 pstmh(d, stm->d);
  575.                 break;
  576.         case STM_FOR_VAR:
  577.                 ps("for"); sp(); ps("(var ");
  578.                 pvarlist(d, stm->a); pc(';'); sp();
  579.                 pexp(d, stm->b); pc(';'); sp();
  580.                 pexp(d, stm->c); pc(')');
  581.                 pstmh(d, stm->d);
  582.                 break;
  583.         case STM_FOR_IN:
  584.                 ps("for"); sp(); pc('(');
  585.                 pexp(d, stm->a); ps(" in ");
  586.                 pexp(d, stm->b); pc(')');
  587.                 pstmh(d, stm->c);
  588.                 break;
  589.         case STM_FOR_IN_VAR:
  590.                 ps("for"); sp(); ps("(var ");
  591.                 pvarlist(d, stm->a); ps(" in ");
  592.                 pexp(d, stm->b); pc(')');
  593.                 pstmh(d, stm->c);
  594.                 break;
  595.  
  596.         case STM_CONTINUE:
  597.                 ps("continue");
  598.                 if (stm->a) {
  599.                         pc(' '); pexp(d, stm->a);
  600.                 }
  601.                 pc(';');
  602.                 break;
  603.  
  604.         case STM_BREAK:
  605.                 ps("break");
  606.                 if (stm->a) {
  607.                         pc(' '); pexp(d, stm->a);
  608.                 }
  609.                 pc(';');
  610.                 break;
  611.  
  612.         case STM_RETURN:
  613.                 ps("return");
  614.                 if (stm->a) {
  615.                         pc(' '); pexp(d, stm->a);
  616.                 }
  617.                 pc(';');
  618.                 break;
  619.  
  620.         case STM_WITH:
  621.                 ps("with"); sp(); pc('('); pexp(d, stm->a); pc(')');
  622.                 pstmh(d, stm->b);
  623.                 break;
  624.  
  625.         case STM_SWITCH:
  626.                 ps("switch"); sp(); pc('(');
  627.                 pexp(d, stm->a);
  628.                 pc(')'); sp(); pc('{'); nl();
  629.                 pcaselist(d, stm->b);
  630.                 in(d); pc('}');
  631.                 break;
  632.  
  633.         case STM_THROW:
  634.                 ps("throw "); pexp(d, stm->a); pc(';');
  635.                 break;
  636.  
  637.         case STM_TRY:
  638.                 ps("try");
  639.                 if (minify && stm->a->type != STM_BLOCK)
  640.                         pc(' ');
  641.                 pstmh(d, stm->a);
  642.                 if (stm->b && stm->c) {
  643.                         nl(); in(d); ps("catch"); sp(); pc('('); pexp(d, stm->b); pc(')');
  644.                         pstmh(d, stm->c);
  645.                 }
  646.                 if (stm->d) {
  647.                         nl(); in(d); ps("finally");
  648.                         pstmh(d, stm->d);
  649.                 }
  650.                 break;
  651.  
  652.         case STM_LABEL:
  653.                 pexp(d, stm->a); pc(':'); sp(); pstm(d, stm->b);
  654.                 break;
  655.  
  656.         case STM_DEBUGGER:
  657.                 ps("debugger");
  658.                 pc(';');
  659.                 break;
  660.  
  661.         default:
  662.                 pexp(d, stm);
  663.                 pc(';');
  664.         }
  665. }
  666.  
  667. static void pstmlist(int d, js_Ast *list)
  668. {
  669.         while (list) {
  670.                 assert(list->type == AST_LIST);
  671.                 pstm(d+1, list->a);
  672.                 nl();
  673.                 list = list->b;
  674.         }
  675. }
  676.  
  677. void jsP_dumpsyntax(js_State *J, js_Ast *prog, int dominify)
  678. {
  679.         minify = dominify;
  680.         if (prog->type == AST_LIST)
  681.                 pstmlist(-1, prog);
  682.         else {
  683.                 pstm(0, prog);
  684.                 nl();
  685.         }
  686.         if (minify > 1)
  687.                 putchar('\n');
  688. }
  689.  
  690. /* S-expression list representation */
  691.  
  692. static void snode(int d, js_Ast *node)
  693. {
  694.         void (*afun)(int,js_Ast*) = snode;
  695.         void (*bfun)(int,js_Ast*) = snode;
  696.         void (*cfun)(int,js_Ast*) = snode;
  697.         void (*dfun)(int,js_Ast*) = snode;
  698.  
  699.         if (!node) {
  700.                 return;
  701.         }
  702.  
  703.         if (node->type == AST_LIST) {
  704.                 slist(d, node);
  705.                 return;
  706.         }
  707.  
  708.         pc('(');
  709.         ps(astname[node->type]);
  710.         pc(':');
  711.         pn(node->line);
  712.         switch (node->type) {
  713.         default: break;
  714.         case AST_IDENTIFIER: pc(' '); ps(node->string); break;
  715.         case EXP_IDENTIFIER: pc(' '); ps(node->string); break;
  716.         case EXP_STRING: pc(' '); pstr(node->string); break;
  717.         case EXP_REGEXP: pc(' '); pregexp(node->string, node->number); break;
  718.         case EXP_NUMBER: printf(" %.9g", node->number); break;
  719.         case STM_BLOCK: afun = sblock; break;
  720.         case AST_FUNDEC: case EXP_FUN: cfun = sblock; break;
  721.         case EXP_PROP_GET: cfun = sblock; break;
  722.         case EXP_PROP_SET: cfun = sblock; break;
  723.         case STM_SWITCH: bfun = sblock; break;
  724.         case STM_CASE: bfun = sblock; break;
  725.         case STM_DEFAULT: afun = sblock; break;
  726.         }
  727.         if (node->a) { pc(' '); afun(d, node->a); }
  728.         if (node->b) { pc(' '); bfun(d, node->b); }
  729.         if (node->c) { pc(' '); cfun(d, node->c); }
  730.         if (node->d) { pc(' '); dfun(d, node->d); }
  731.         pc(')');
  732. }
  733.  
  734. static void slist(int d, js_Ast *list)
  735. {
  736.         pc('[');
  737.         while (list) {
  738.                 assert(list->type == AST_LIST);
  739.                 snode(d, list->a);
  740.                 list = list->b;
  741.                 if (list)
  742.                         pc(' ');
  743.         }
  744.         pc(']');
  745. }
  746.  
  747. static void sblock(int d, js_Ast *list)
  748. {
  749.         ps("[\n");
  750.         in(d+1);
  751.         while (list) {
  752.                 assert(list->type == AST_LIST);
  753.                 snode(d+1, list->a);
  754.                 list = list->b;
  755.                 if (list) {
  756.                         nl();
  757.                         in(d+1);
  758.                 }
  759.         }
  760.         nl(); in(d); pc(']');
  761. }
  762.  
  763. void jsP_dumplist(js_State *J, js_Ast *prog)
  764. {
  765.         minify = 0;
  766.         if (prog->type == AST_LIST)
  767.                 sblock(0, prog);
  768.         else
  769.                 snode(0, prog);
  770.         nl();
  771. }
  772.  
  773. /* Compiled code */
  774.  
  775. void jsC_dumpfunction(js_State *J, js_Function *F)
  776. {
  777.         js_Instruction *p = F->code;
  778.         js_Instruction *end = F->code + F->codelen;
  779.         int i;
  780.  
  781.         minify = 0;
  782.  
  783.         printf("%s(%d)\n", F->name, F->numparams);
  784.         if (F->lightweight) printf("\tlightweight\n");
  785.         if (F->arguments) printf("\targuments\n");
  786.         printf("\tsource %s:%d\n", F->filename, F->line);
  787.         for (i = 0; i < F->funlen; ++i)
  788.                 printf("\tfunction %d %s\n", i, F->funtab[i]->name);
  789.         for (i = 0; i < F->varlen; ++i)
  790.                 printf("\tlocal %d %s\n", i + 1, F->vartab[i]);
  791.  
  792.         printf("{\n");
  793.         while (p < end) {
  794.                 int ln = *p++;
  795.                 int c = *p++;
  796.  
  797.                 printf("%5d(%3d): ", (int)(p - F->code) - 2, ln);
  798.                 ps(opname[c]);
  799.  
  800.                 switch (c) {
  801.                 case OP_INTEGER:
  802.                         printf(" %ld", (long)((*p++) - 32768));
  803.                         break;
  804.                 case OP_NUMBER:
  805.                         printf(" %.9g", F->numtab[*p++]);
  806.                         break;
  807.                 case OP_STRING:
  808.                         pc(' ');
  809.                         pstr(F->strtab[*p++]);
  810.                         break;
  811.                 case OP_NEWREGEXP:
  812.                         pc(' ');
  813.                         pregexp(F->strtab[p[0]], p[1]);
  814.                         p += 2;
  815.                         break;
  816.  
  817.                 case OP_GETVAR:
  818.                 case OP_HASVAR:
  819.                 case OP_SETVAR:
  820.                 case OP_DELVAR:
  821.                 case OP_GETPROP_S:
  822.                 case OP_SETPROP_S:
  823.                 case OP_DELPROP_S:
  824.                 case OP_CATCH:
  825.                         pc(' ');
  826.                         ps(F->strtab[*p++]);
  827.                         break;
  828.  
  829.                 case OP_GETLOCAL:
  830.                 case OP_SETLOCAL:
  831.                 case OP_DELLOCAL:
  832.                         printf(" %s", F->vartab[*p++ - 1]);
  833.                         break;
  834.  
  835.                 case OP_CLOSURE:
  836.                 case OP_CALL:
  837.                 case OP_NEW:
  838.                 case OP_JUMP:
  839.                 case OP_JTRUE:
  840.                 case OP_JFALSE:
  841.                 case OP_JCASE:
  842.                 case OP_TRY:
  843.                         printf(" %ld", (long)*p++);
  844.                         break;
  845.                 }
  846.  
  847.                 nl();
  848.         }
  849.         printf("}\n");
  850.  
  851.         for (i = 0; i < F->funlen; ++i) {
  852.                 if (F->funtab[i] != F) {
  853.                         printf("function %d ", i);
  854.                         jsC_dumpfunction(J, F->funtab[i]);
  855.                 }
  856.         }
  857. }
  858.  
  859. /* Runtime values */
  860.  
  861. void js_dumpvalue(js_State *J, js_Value v)
  862. {
  863.         minify = 0;
  864.         switch (v.type) {
  865.         case JS_TUNDEFINED: printf("undefined"); break;
  866.         case JS_TNULL: printf("null"); break;
  867.         case JS_TBOOLEAN: printf(v.u.boolean ? "true" : "false"); break;
  868.         case JS_TNUMBER: printf("%.9g", v.u.number); break;
  869.         case JS_TSHRSTR: printf("'%s'", v.u.shrstr); break;
  870.         case JS_TLITSTR: printf("'%s'", v.u.litstr); break;
  871.         case JS_TMEMSTR: printf("'%s'", v.u.memstr->p); break;
  872.         case JS_TOBJECT:
  873.                 if (v.u.object == J->G) {
  874.                         printf("[Global]");
  875.                         break;
  876.                 }
  877.                 switch (v.u.object->type) {
  878.                 case JS_COBJECT: printf("[Object %p]", (void*)v.u.object); break;
  879.                 case JS_CARRAY: printf("[Array %p]", (void*)v.u.object); break;
  880.                 case JS_CFUNCTION:
  881.                         printf("[Function %p, %s, %s:%d]",
  882.                                 (void*)v.u.object,
  883.                                 v.u.object->u.f.function->name,
  884.                                 v.u.object->u.f.function->filename,
  885.                                 v.u.object->u.f.function->line);
  886.                         break;
  887.                 case JS_CSCRIPT: printf("[Script %s]", v.u.object->u.f.function->filename); break;
  888.                 case JS_CEVAL: printf("[Eval %s]", v.u.object->u.f.function->filename); break;
  889.                 case JS_CCFUNCTION: printf("[CFunction %s]", v.u.object->u.c.name); break;
  890.                 case JS_CBOOLEAN: printf("[Boolean %d]", v.u.object->u.boolean); break;
  891.                 case JS_CNUMBER: printf("[Number %g]", v.u.object->u.number); break;
  892.                 case JS_CSTRING: printf("[String'%s']", v.u.object->u.s.string); break;
  893.                 case JS_CERROR: printf("[Error]"); break;
  894.                 case JS_CARGUMENTS: printf("[Arguments %p]", (void*)v.u.object); break;
  895.                 case JS_CITERATOR: printf("[Iterator %p]", (void*)v.u.object); break;
  896.                 case JS_CUSERDATA:
  897.                         printf("[Userdata %s %p]", v.u.object->u.user.tag, v.u.object->u.user.data);
  898.                         break;
  899.                 default: printf("[Object %p]", (void*)v.u.object); break;
  900.                 }
  901.                 break;
  902.         }
  903. }
  904.  
  905. static void js_dumpproperty(js_State *J, js_Property *node)
  906. {
  907.         minify = 0;
  908.         if (node->left->level)
  909.                 js_dumpproperty(J, node->left);
  910.         printf("\t%s: ", node->name);
  911.         js_dumpvalue(J, node->value);
  912.         printf(",\n");
  913.         if (node->right->level)
  914.                 js_dumpproperty(J, node->right);
  915. }
  916.  
  917. void js_dumpobject(js_State *J, js_Object *obj)
  918. {
  919.         minify = 0;
  920.         printf("{\n");
  921.         if (obj->properties->level)
  922.                 js_dumpproperty(J, obj->properties);
  923.         printf("}\n");
  924. }
  925.