Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. #include "jsi.h"
  2. #include "jslex.h"
  3. #include "jsparse.h"
  4. #include "jscompile.h"
  5. #include "jsvalue.h" /* for jsV_numbertostring */
  6.  
  7. #define cexp jsC_cexp /* collision with math.h */
  8.  
  9. #define JF js_State *J, js_Function *F
  10.  
  11. JS_NORETURN void jsC_error(js_State *J, js_Ast *node, const char *fmt, ...) JS_PRINTFLIKE(3,4);
  12.  
  13. static void cfunbody(JF, js_Ast *name, js_Ast *params, js_Ast *body);
  14. static void cexp(JF, js_Ast *exp);
  15. static void cstmlist(JF, js_Ast *list);
  16. static void cstm(JF, js_Ast *stm);
  17.  
  18. void jsC_error(js_State *J, js_Ast *node, const char *fmt, ...)
  19. {
  20.         va_list ap;
  21.         char buf[512];
  22.         char msgbuf[256];
  23.  
  24.         va_start(ap, fmt);
  25.         vsnprintf(msgbuf, 256, fmt, ap);
  26.         va_end(ap);
  27.  
  28.         snprintf(buf, 256, "%s:%d: ", J->filename, node->line);
  29.         strcat(buf, msgbuf);
  30.  
  31.         js_newsyntaxerror(J, buf);
  32.         js_throw(J);
  33. }
  34.  
  35. static const char *futurewords[] = {
  36.         "class", "const", "enum", "export", "extends", "import", "super",
  37. };
  38.  
  39. static const char *strictfuturewords[] = {
  40.         "implements", "interface", "let", "package", "private", "protected",
  41.         "public", "static", "yield",
  42. };
  43.  
  44. static void checkfutureword(JF, js_Ast *exp)
  45. {
  46.         if (jsY_findword(exp->string, futurewords, nelem(futurewords)) >= 0)
  47.                 jsC_error(J, exp, "'%s' is a future reserved word", exp->string);
  48.         if (F->strict) {
  49.                 if (jsY_findword(exp->string, strictfuturewords, nelem(strictfuturewords)) >= 0)
  50.                         jsC_error(J, exp, "'%s' is a strict mode future reserved word", exp->string);
  51.         }
  52. }
  53.  
  54. static js_Function *newfun(js_State *J, int line, js_Ast *name, js_Ast *params, js_Ast *body, int script, int default_strict)
  55. {
  56.         js_Function *F = js_malloc(J, sizeof *F);
  57.         memset(F, 0, sizeof *F);
  58.         F->gcmark = 0;
  59.         F->gcnext = J->gcfun;
  60.         J->gcfun = F;
  61.         ++J->gccounter;
  62.  
  63.         F->filename = js_intern(J, J->filename);
  64.         F->line = line;
  65.         F->script = script;
  66.         F->strict = default_strict;
  67.         F->name = name ? name->string : "";
  68.  
  69.         cfunbody(J, F, name, params, body);
  70.  
  71.         return F;
  72. }
  73.  
  74. /* Emit opcodes, constants and jumps */
  75.  
  76. static void emitraw(JF, int value)
  77. {
  78.         if (value != (js_Instruction)value)
  79.                 js_syntaxerror(J, "integer overflow in instruction coding");
  80.         if (F->codelen >= F->codecap) {
  81.                 F->codecap = F->codecap ? F->codecap * 2 : 64;
  82.                 F->code = js_realloc(J, F->code, F->codecap * sizeof *F->code);
  83.         }
  84.         F->code[F->codelen++] = value;
  85. }
  86.  
  87. static void emit(JF, int value)
  88. {
  89.         emitraw(J, F, F->lastline);
  90.         emitraw(J, F, value);
  91. }
  92.  
  93. static void emitarg(JF, int value)
  94. {
  95.         emitraw(J, F, value);
  96. }
  97.  
  98. static void emitline(JF, js_Ast *node)
  99. {
  100.         F->lastline = node->line;
  101. }
  102.  
  103. static int addfunction(JF, js_Function *value)
  104. {
  105.         if (F->funlen >= F->funcap) {
  106.                 F->funcap = F->funcap ? F->funcap * 2 : 16;
  107.                 F->funtab = js_realloc(J, F->funtab, F->funcap * sizeof *F->funtab);
  108.         }
  109.         F->funtab[F->funlen] = value;
  110.         return F->funlen++;
  111. }
  112.  
  113. static int addnumber(JF, double value)
  114. {
  115.         int i;
  116.         for (i = 0; i < F->numlen; ++i)
  117.                 if (F->numtab[i] == value)
  118.                         return i;
  119.         if (F->numlen >= F->numcap) {
  120.                 F->numcap = F->numcap ? F->numcap * 2 : 16;
  121.                 F->numtab = js_realloc(J, F->numtab, F->numcap * sizeof *F->numtab);
  122.         }
  123.         F->numtab[F->numlen] = value;
  124.         return F->numlen++;
  125. }
  126.  
  127. static int addstring(JF, const char *value)
  128. {
  129.         int i;
  130.         for (i = 0; i < F->strlen; ++i)
  131.                 if (!strcmp(F->strtab[i], value))
  132.                         return i;
  133.         if (F->strlen >= F->strcap) {
  134.                 F->strcap = F->strcap ? F->strcap * 2 : 16;
  135.                 F->strtab = js_realloc(J, F->strtab, F->strcap * sizeof *F->strtab);
  136.         }
  137.         F->strtab[F->strlen] = value;
  138.         return F->strlen++;
  139. }
  140.  
  141. static int addlocal(JF, js_Ast *ident, int reuse)
  142. {
  143.         const char *name = ident->string;
  144.         if (F->strict) {
  145.                 if (!strcmp(name, "arguments"))
  146.                         jsC_error(J, ident, "redefining 'arguments' is not allowed in strict mode");
  147.                 if (!strcmp(name, "eval"))
  148.                         jsC_error(J, ident, "redefining 'eval' is not allowed in strict mode");
  149.         } else {
  150.                 if (!strcmp(name, "eval"))
  151.                         js_evalerror(J, "%s:%d: invalid use of 'eval'", J->filename, ident->line);
  152.         }
  153.         if (reuse || F->strict) {
  154.                 int i;
  155.                 for (i = 0; i < F->varlen; ++i) {
  156.                         if (!strcmp(F->vartab[i], name)) {
  157.                                 if (reuse)
  158.                                         return i+1;
  159.                                 if (F->strict)
  160.                                         jsC_error(J, ident, "duplicate formal parameter '%s'", name);
  161.                         }
  162.                 }
  163.         }
  164.         if (F->varlen >= F->varcap) {
  165.                 F->varcap = F->varcap ? F->varcap * 2 : 16;
  166.                 F->vartab = js_realloc(J, F->vartab, F->varcap * sizeof *F->vartab);
  167.         }
  168.         F->vartab[F->varlen] = name;
  169.         return ++F->varlen;
  170. }
  171.  
  172. static int findlocal(JF, const char *name)
  173. {
  174.         int i;
  175.         for (i = F->varlen; i > 0; --i)
  176.                 if (!strcmp(F->vartab[i-1], name))
  177.                         return i;
  178.         return -1;
  179. }
  180.  
  181. static void emitfunction(JF, js_Function *fun)
  182. {
  183.         F->lightweight = 0;
  184.         emit(J, F, OP_CLOSURE);
  185.         emitarg(J, F, addfunction(J, F, fun));
  186. }
  187.  
  188. static void emitnumber(JF, double num)
  189. {
  190.         if (num == 0) {
  191.                 emit(J, F, OP_INTEGER);
  192.                 emitarg(J, F, 32768);
  193.                 if (signbit(num))
  194.                         emit(J, F, OP_NEG);
  195.         } else if (num >= SHRT_MIN && num <= SHRT_MAX && num == (int)num) {
  196.                 emit(J, F, OP_INTEGER);
  197.                 emitarg(J, F, num + 32768);
  198.         } else {
  199.                 emit(J, F, OP_NUMBER);
  200.                 emitarg(J, F, addnumber(J, F, num));
  201.         }
  202. }
  203.  
  204. static void emitstring(JF, int opcode, const char *str)
  205. {
  206.         emit(J, F, opcode);
  207.         emitarg(J, F, addstring(J, F, str));
  208. }
  209.  
  210. static void emitlocal(JF, int oploc, int opvar, js_Ast *ident)
  211. {
  212.         int is_arguments = !strcmp(ident->string, "arguments");
  213.         int is_eval = !strcmp(ident->string, "eval");
  214.         int i;
  215.  
  216.         if (is_arguments) {
  217.                 F->lightweight = 0;
  218.                 F->arguments = 1;
  219.         }
  220.  
  221.         checkfutureword(J, F, ident);
  222.         if (F->strict && oploc == OP_SETLOCAL) {
  223.                 if (is_arguments)
  224.                         jsC_error(J, ident, "'arguments' is read-only in strict mode");
  225.                 if (is_eval)
  226.                         jsC_error(J, ident, "'eval' is read-only in strict mode");
  227.         }
  228.         if (is_eval)
  229.                 js_evalerror(J, "%s:%d: invalid use of 'eval'", J->filename, ident->line);
  230.  
  231.         i = findlocal(J, F, ident->string);
  232.         if (i < 0) {
  233.                 emitstring(J, F, opvar, ident->string);
  234.         } else {
  235.                 emit(J, F, oploc);
  236.                 emitarg(J, F, i);
  237.         }
  238. }
  239.  
  240. static int here(JF)
  241. {
  242.         return F->codelen;
  243. }
  244.  
  245. static int emitjump(JF, int opcode)
  246. {
  247.         int inst;
  248.         emit(J, F, opcode);
  249.         inst = F->codelen;
  250.         emitarg(J, F, 0);
  251.         return inst;
  252. }
  253.  
  254. static void emitjumpto(JF, int opcode, int dest)
  255. {
  256.         emit(J, F, opcode);
  257.         if (dest != (js_Instruction)dest)
  258.                 js_syntaxerror(J, "jump address integer overflow");
  259.         emitarg(J, F, dest);
  260. }
  261.  
  262. static void labelto(JF, int inst, int addr)
  263. {
  264.         if (addr != (js_Instruction)addr)
  265.                 js_syntaxerror(J, "jump address integer overflow");
  266.         F->code[inst] = addr;
  267. }
  268.  
  269. static void label(JF, int inst)
  270. {
  271.         labelto(J, F, inst, F->codelen);
  272. }
  273.  
  274. /* Expressions */
  275.  
  276. static void ctypeof(JF, js_Ast *exp)
  277. {
  278.         if (exp->a->type == EXP_IDENTIFIER) {
  279.                 emitline(J, F, exp->a);
  280.                 emitlocal(J, F, OP_GETLOCAL, OP_HASVAR, exp->a);
  281.         } else {
  282.                 cexp(J, F, exp->a);
  283.         }
  284.         emitline(J, F, exp);
  285.         emit(J, F, OP_TYPEOF);
  286. }
  287.  
  288. static void cunary(JF, js_Ast *exp, int opcode)
  289. {
  290.         cexp(J, F, exp->a);
  291.         emitline(J, F, exp);
  292.         emit(J, F, opcode);
  293. }
  294.  
  295. static void cbinary(JF, js_Ast *exp, int opcode)
  296. {
  297.         cexp(J, F, exp->a);
  298.         cexp(J, F, exp->b);
  299.         emitline(J, F, exp);
  300.         emit(J, F, opcode);
  301. }
  302.  
  303. static void carray(JF, js_Ast *list)
  304. {
  305.         int i = 0;
  306.         while (list) {
  307.                 if (list->a->type != EXP_UNDEF) {
  308.                         emitline(J, F, list->a);
  309.                         emitnumber(J, F, i++);
  310.                         cexp(J, F, list->a);
  311.                         emitline(J, F, list->a);
  312.                         emit(J, F, OP_INITPROP);
  313.                 } else {
  314.                         ++i;
  315.                 }
  316.                 list = list->b;
  317.         }
  318. }
  319.  
  320. static void checkdup(JF, js_Ast *list, js_Ast *end)
  321. {
  322.         char nbuf[32], sbuf[32];
  323.         const char *needle, *straw;
  324.  
  325.         if (end->a->type == EXP_NUMBER)
  326.                 needle = jsV_numbertostring(J, nbuf, end->a->number);
  327.         else
  328.                 needle = end->a->string;
  329.  
  330.         while (list->a != end) {
  331.                 if (list->a->type == end->type) {
  332.                         js_Ast *prop = list->a->a;
  333.                         if (prop->type == EXP_NUMBER)
  334.                                 straw = jsV_numbertostring(J, sbuf, prop->number);
  335.                         else
  336.                                 straw =  prop->string;
  337.                         if (!strcmp(needle, straw))
  338.                                 jsC_error(J, list, "duplicate property '%s' in object literal", needle);
  339.                 }
  340.                 list = list->b;
  341.         }
  342. }
  343.  
  344. static void cobject(JF, js_Ast *list)
  345. {
  346.         js_Ast *head = list;
  347.  
  348.         while (list) {
  349.                 js_Ast *kv = list->a;
  350.                 js_Ast *prop = kv->a;
  351.  
  352.                 if (prop->type == AST_IDENTIFIER || prop->type == EXP_STRING) {
  353.                         emitline(J, F, prop);
  354.                         emitstring(J, F, OP_STRING, prop->string);
  355.                 } else if (prop->type == EXP_NUMBER) {
  356.                         emitline(J, F, prop);
  357.                         emitnumber(J, F, prop->number);
  358.                 } else {
  359.                         jsC_error(J, prop, "invalid property name in object initializer");
  360.                 }
  361.  
  362.                 if (F->strict)
  363.                         checkdup(J, F, head, kv);
  364.  
  365.                 switch (kv->type) {
  366.                 default: /* impossible */ break;
  367.                 case EXP_PROP_VAL:
  368.                         cexp(J, F, kv->b);
  369.                         emitline(J, F, kv);
  370.                         emit(J, F, OP_INITPROP);
  371.                         break;
  372.                 case EXP_PROP_GET:
  373.                         emitfunction(J, F, newfun(J, prop->line, NULL, NULL, kv->c, 0, F->strict));
  374.                         emitline(J, F, kv);
  375.                         emit(J, F, OP_INITGETTER);
  376.                         break;
  377.                 case EXP_PROP_SET:
  378.                         emitfunction(J, F, newfun(J, prop->line, NULL, kv->b, kv->c, 0, F->strict));
  379.                         emitline(J, F, kv);
  380.                         emit(J, F, OP_INITSETTER);
  381.                         break;
  382.                 }
  383.  
  384.                 list = list->b;
  385.         }
  386. }
  387.  
  388. static int cargs(JF, js_Ast *list)
  389. {
  390.         int n = 0;
  391.         while (list) {
  392.                 cexp(J, F, list->a);
  393.                 list = list->b;
  394.                 ++n;
  395.         }
  396.         return n;
  397. }
  398.  
  399. static void cassign(JF, js_Ast *exp)
  400. {
  401.         js_Ast *lhs = exp->a;
  402.         js_Ast *rhs = exp->b;
  403.         switch (lhs->type) {
  404.         case EXP_IDENTIFIER:
  405.                 cexp(J, F, rhs);
  406.                 emitline(J, F, exp);
  407.                 emitlocal(J, F, OP_SETLOCAL, OP_SETVAR, lhs);
  408.                 break;
  409.         case EXP_INDEX:
  410.                 cexp(J, F, lhs->a);
  411.                 cexp(J, F, lhs->b);
  412.                 cexp(J, F, rhs);
  413.                 emitline(J, F, exp);
  414.                 emit(J, F, OP_SETPROP);
  415.                 break;
  416.         case EXP_MEMBER:
  417.                 cexp(J, F, lhs->a);
  418.                 cexp(J, F, rhs);
  419.                 emitline(J, F, exp);
  420.                 emitstring(J, F, OP_SETPROP_S, lhs->b->string);
  421.                 break;
  422.         default:
  423.                 jsC_error(J, lhs, "invalid l-value in assignment");
  424.         }
  425. }
  426.  
  427. static void cassignforin(JF, js_Ast *stm)
  428. {
  429.         js_Ast *lhs = stm->a;
  430.  
  431.         if (stm->type == STM_FOR_IN_VAR) {
  432.                 if (lhs->b)
  433.                         jsC_error(J, lhs->b, "more than one loop variable in for-in statement");
  434.                 emitline(J, F, lhs->a);
  435.                 emitlocal(J, F, OP_SETLOCAL, OP_SETVAR, lhs->a->a); /* list(var-init(ident)) */
  436.                 emit(J, F, OP_POP);
  437.                 return;
  438.         }
  439.  
  440.         switch (lhs->type) {
  441.         case EXP_IDENTIFIER:
  442.                 emitline(J, F, lhs);
  443.                 emitlocal(J, F, OP_SETLOCAL, OP_SETVAR, lhs);
  444.                 emit(J, F, OP_POP);
  445.                 break;
  446.         case EXP_INDEX:
  447.                 cexp(J, F, lhs->a);
  448.                 cexp(J, F, lhs->b);
  449.                 emitline(J, F, lhs);
  450.                 emit(J, F, OP_ROT3);
  451.                 emit(J, F, OP_SETPROP);
  452.                 emit(J, F, OP_POP);
  453.                 break;
  454.         case EXP_MEMBER:
  455.                 cexp(J, F, lhs->a);
  456.                 emitline(J, F, lhs);
  457.                 emit(J, F, OP_ROT2);
  458.                 emitstring(J, F, OP_SETPROP_S, lhs->b->string);
  459.                 emit(J, F, OP_POP);
  460.                 break;
  461.         default:
  462.                 jsC_error(J, lhs, "invalid l-value in for-in loop assignment");
  463.         }
  464. }
  465.  
  466. static void cassignop1(JF, js_Ast *lhs)
  467. {
  468.         switch (lhs->type) {
  469.         case EXP_IDENTIFIER:
  470.                 emitline(J, F, lhs);
  471.                 emitlocal(J, F, OP_GETLOCAL, OP_GETVAR, lhs);
  472.                 break;
  473.         case EXP_INDEX:
  474.                 cexp(J, F, lhs->a);
  475.                 cexp(J, F, lhs->b);
  476.                 emitline(J, F, lhs);
  477.                 emit(J, F, OP_DUP2);
  478.                 emit(J, F, OP_GETPROP);
  479.                 break;
  480.         case EXP_MEMBER:
  481.                 cexp(J, F, lhs->a);
  482.                 emitline(J, F, lhs);
  483.                 emit(J, F, OP_DUP);
  484.                 emitstring(J, F, OP_GETPROP_S, lhs->b->string);
  485.                 break;
  486.         default:
  487.                 jsC_error(J, lhs, "invalid l-value in assignment");
  488.         }
  489. }
  490.  
  491. static void cassignop2(JF, js_Ast *lhs, int postfix)
  492. {
  493.         switch (lhs->type) {
  494.         case EXP_IDENTIFIER:
  495.                 emitline(J, F, lhs);
  496.                 if (postfix) emit(J, F, OP_ROT2);
  497.                 emitlocal(J, F, OP_SETLOCAL, OP_SETVAR, lhs);
  498.                 break;
  499.         case EXP_INDEX:
  500.                 emitline(J, F, lhs);
  501.                 if (postfix) emit(J, F, OP_ROT4);
  502.                 emit(J, F, OP_SETPROP);
  503.                 break;
  504.         case EXP_MEMBER:
  505.                 emitline(J, F, lhs);
  506.                 if (postfix) emit(J, F, OP_ROT3);
  507.                 emitstring(J, F, OP_SETPROP_S, lhs->b->string);
  508.                 break;
  509.         default:
  510.                 jsC_error(J, lhs, "invalid l-value in assignment");
  511.         }
  512. }
  513.  
  514. static void cassignop(JF, js_Ast *exp, int opcode)
  515. {
  516.         js_Ast *lhs = exp->a;
  517.         js_Ast *rhs = exp->b;
  518.         cassignop1(J, F, lhs);
  519.         cexp(J, F, rhs);
  520.         emitline(J, F, exp);
  521.         emit(J, F, opcode);
  522.         cassignop2(J, F, lhs, 0);
  523. }
  524.  
  525. static void cdelete(JF, js_Ast *exp)
  526. {
  527.         js_Ast *arg = exp->a;
  528.         switch (arg->type) {
  529.         case EXP_IDENTIFIER:
  530.                 if (F->strict)
  531.                         jsC_error(J, exp, "delete on an unqualified name is not allowed in strict mode");
  532.                 emitline(J, F, exp);
  533.                 emitlocal(J, F, OP_DELLOCAL, OP_DELVAR, arg);
  534.                 break;
  535.         case EXP_INDEX:
  536.                 cexp(J, F, arg->a);
  537.                 cexp(J, F, arg->b);
  538.                 emitline(J, F, exp);
  539.                 emit(J, F, OP_DELPROP);
  540.                 break;
  541.         case EXP_MEMBER:
  542.                 cexp(J, F, arg->a);
  543.                 emitline(J, F, exp);
  544.                 emitstring(J, F, OP_DELPROP_S, arg->b->string);
  545.                 break;
  546.         default:
  547.                 jsC_error(J, exp, "invalid l-value in delete expression");
  548.         }
  549. }
  550.  
  551. static void ceval(JF, js_Ast *fun, js_Ast *args)
  552. {
  553.         int n = cargs(J, F, args);
  554.         F->lightweight = 0;
  555.         F->arguments = 1;
  556.         if (n == 0)
  557.                 emit(J, F, OP_UNDEF);
  558.         else while (n-- > 1)
  559.                 emit(J, F, OP_POP);
  560.         emit(J, F, OP_EVAL);
  561. }
  562.  
  563. static void ccall(JF, js_Ast *fun, js_Ast *args)
  564. {
  565.         int n;
  566.         switch (fun->type) {
  567.         case EXP_INDEX:
  568.                 cexp(J, F, fun->a);
  569.                 emit(J, F, OP_DUP);
  570.                 cexp(J, F, fun->b);
  571.                 emit(J, F, OP_GETPROP);
  572.                 emit(J, F, OP_ROT2);
  573.                 break;
  574.         case EXP_MEMBER:
  575.                 cexp(J, F, fun->a);
  576.                 emit(J, F, OP_DUP);
  577.                 emitstring(J, F, OP_GETPROP_S, fun->b->string);
  578.                 emit(J, F, OP_ROT2);
  579.                 break;
  580.         case EXP_IDENTIFIER:
  581.                 if (!strcmp(fun->string, "eval")) {
  582.                         ceval(J, F, fun, args);
  583.                         return;
  584.                 }
  585.                 /* fallthrough */
  586.         default:
  587.                 cexp(J, F, fun);
  588.                 emit(J, F, OP_UNDEF);
  589.                 break;
  590.         }
  591.         n = cargs(J, F, args);
  592.         emit(J, F, OP_CALL);
  593.         emitarg(J, F, n);
  594. }
  595.  
  596. static void cexp(JF, js_Ast *exp)
  597. {
  598.         int then, end;
  599.         int n;
  600.  
  601.         switch (exp->type) {
  602.         case EXP_STRING:
  603.                 emitline(J, F, exp);
  604.                 emitstring(J, F, OP_STRING, exp->string);
  605.                 break;
  606.         case EXP_NUMBER:
  607.                 emitline(J, F, exp);
  608.                 emitnumber(J, F, exp->number);
  609.                 break;
  610.         case EXP_UNDEF:
  611.                 emitline(J, F, exp);
  612.                 emit(J, F, OP_UNDEF);
  613.                 break;
  614.         case EXP_NULL:
  615.                 emitline(J, F, exp);
  616.                 emit(J, F, OP_NULL);
  617.                 break;
  618.         case EXP_TRUE:
  619.                 emitline(J, F, exp);
  620.                 emit(J, F, OP_TRUE);
  621.                 break;
  622.         case EXP_FALSE:
  623.                 emitline(J, F, exp);
  624.                 emit(J, F, OP_FALSE);
  625.                 break;
  626.         case EXP_THIS:
  627.                 emitline(J, F, exp);
  628.                 emit(J, F, OP_THIS);
  629.                 break;
  630.  
  631.         case EXP_REGEXP:
  632.                 emitline(J, F, exp);
  633.                 emit(J, F, OP_NEWREGEXP);
  634.                 emitarg(J, F, addstring(J, F, exp->string));
  635.                 emitarg(J, F, exp->number);
  636.                 break;
  637.  
  638.         case EXP_OBJECT:
  639.                 emitline(J, F, exp);
  640.                 emit(J, F, OP_NEWOBJECT);
  641.                 cobject(J, F, exp->a);
  642.                 break;
  643.  
  644.         case EXP_ARRAY:
  645.                 emitline(J, F, exp);
  646.                 emit(J, F, OP_NEWARRAY);
  647.                 carray(J, F, exp->a);
  648.                 break;
  649.  
  650.         case EXP_FUN:
  651.                 emitline(J, F, exp);
  652.                 emitfunction(J, F, newfun(J, exp->line, exp->a, exp->b, exp->c, 0, F->strict));
  653.                 break;
  654.  
  655.         case EXP_IDENTIFIER:
  656.                 emitline(J, F, exp);
  657.                 emitlocal(J, F, OP_GETLOCAL, OP_GETVAR, exp);
  658.                 break;
  659.  
  660.         case EXP_INDEX:
  661.                 cexp(J, F, exp->a);
  662.                 cexp(J, F, exp->b);
  663.                 emitline(J, F, exp);
  664.                 emit(J, F, OP_GETPROP);
  665.                 break;
  666.  
  667.         case EXP_MEMBER:
  668.                 cexp(J, F, exp->a);
  669.                 emitline(J, F, exp);
  670.                 emitstring(J, F, OP_GETPROP_S, exp->b->string);
  671.                 break;
  672.  
  673.         case EXP_CALL:
  674.                 ccall(J, F, exp->a, exp->b);
  675.                 break;
  676.  
  677.         case EXP_NEW:
  678.                 cexp(J, F, exp->a);
  679.                 n = cargs(J, F, exp->b);
  680.                 emitline(J, F, exp);
  681.                 emit(J, F, OP_NEW);
  682.                 emitarg(J, F, n);
  683.                 break;
  684.  
  685.         case EXP_DELETE:
  686.                 cdelete(J, F, exp);
  687.                 break;
  688.  
  689.         case EXP_PREINC:
  690.                 cassignop1(J, F, exp->a);
  691.                 emitline(J, F, exp);
  692.                 emit(J, F, OP_INC);
  693.                 cassignop2(J, F, exp->a, 0);
  694.                 break;
  695.  
  696.         case EXP_PREDEC:
  697.                 cassignop1(J, F, exp->a);
  698.                 emitline(J, F, exp);
  699.                 emit(J, F, OP_DEC);
  700.                 cassignop2(J, F, exp->a, 0);
  701.                 break;
  702.  
  703.         case EXP_POSTINC:
  704.                 cassignop1(J, F, exp->a);
  705.                 emitline(J, F, exp);
  706.                 emit(J, F, OP_POSTINC);
  707.                 cassignop2(J, F, exp->a, 1);
  708.                 emit(J, F, OP_POP);
  709.                 break;
  710.  
  711.         case EXP_POSTDEC:
  712.                 cassignop1(J, F, exp->a);
  713.                 emitline(J, F, exp);
  714.                 emit(J, F, OP_POSTDEC);
  715.                 cassignop2(J, F, exp->a, 1);
  716.                 emit(J, F, OP_POP);
  717.                 break;
  718.  
  719.         case EXP_VOID:
  720.                 cexp(J, F, exp->a);
  721.                 emitline(J, F, exp);
  722.                 emit(J, F, OP_POP);
  723.                 emit(J, F, OP_UNDEF);
  724.                 break;
  725.  
  726.         case EXP_TYPEOF: ctypeof(J, F, exp); break;
  727.         case EXP_POS: cunary(J, F, exp, OP_POS); break;
  728.         case EXP_NEG: cunary(J, F, exp, OP_NEG); break;
  729.         case EXP_BITNOT: cunary(J, F, exp, OP_BITNOT); break;
  730.         case EXP_LOGNOT: cunary(J, F, exp, OP_LOGNOT); break;
  731.  
  732.         case EXP_BITOR: cbinary(J, F, exp, OP_BITOR); break;
  733.         case EXP_BITXOR: cbinary(J, F, exp, OP_BITXOR); break;
  734.         case EXP_BITAND: cbinary(J, F, exp, OP_BITAND); break;
  735.         case EXP_EQ: cbinary(J, F, exp, OP_EQ); break;
  736.         case EXP_NE: cbinary(J, F, exp, OP_NE); break;
  737.         case EXP_STRICTEQ: cbinary(J, F, exp, OP_STRICTEQ); break;
  738.         case EXP_STRICTNE: cbinary(J, F, exp, OP_STRICTNE); break;
  739.         case EXP_LT: cbinary(J, F, exp, OP_LT); break;
  740.         case EXP_GT: cbinary(J, F, exp, OP_GT); break;
  741.         case EXP_LE: cbinary(J, F, exp, OP_LE); break;
  742.         case EXP_GE: cbinary(J, F, exp, OP_GE); break;
  743.         case EXP_INSTANCEOF: cbinary(J, F, exp, OP_INSTANCEOF); break;
  744.         case EXP_IN: cbinary(J, F, exp, OP_IN); break;
  745.         case EXP_SHL: cbinary(J, F, exp, OP_SHL); break;
  746.         case EXP_SHR: cbinary(J, F, exp, OP_SHR); break;
  747.         case EXP_USHR: cbinary(J, F, exp, OP_USHR); break;
  748.         case EXP_ADD: cbinary(J, F, exp, OP_ADD); break;
  749.         case EXP_SUB: cbinary(J, F, exp, OP_SUB); break;
  750.         case EXP_MUL: cbinary(J, F, exp, OP_MUL); break;
  751.         case EXP_DIV: cbinary(J, F, exp, OP_DIV); break;
  752.         case EXP_MOD: cbinary(J, F, exp, OP_MOD); break;
  753.  
  754.         case EXP_ASS: cassign(J, F, exp); break;
  755.         case EXP_ASS_MUL: cassignop(J, F, exp, OP_MUL); break;
  756.         case EXP_ASS_DIV: cassignop(J, F, exp, OP_DIV); break;
  757.         case EXP_ASS_MOD: cassignop(J, F, exp, OP_MOD); break;
  758.         case EXP_ASS_ADD: cassignop(J, F, exp, OP_ADD); break;
  759.         case EXP_ASS_SUB: cassignop(J, F, exp, OP_SUB); break;
  760.         case EXP_ASS_SHL: cassignop(J, F, exp, OP_SHL); break;
  761.         case EXP_ASS_SHR: cassignop(J, F, exp, OP_SHR); break;
  762.         case EXP_ASS_USHR: cassignop(J, F, exp, OP_USHR); break;
  763.         case EXP_ASS_BITAND: cassignop(J, F, exp, OP_BITAND); break;
  764.         case EXP_ASS_BITXOR: cassignop(J, F, exp, OP_BITXOR); break;
  765.         case EXP_ASS_BITOR: cassignop(J, F, exp, OP_BITOR); break;
  766.  
  767.         case EXP_COMMA:
  768.                 cexp(J, F, exp->a);
  769.                 emitline(J, F, exp);
  770.                 emit(J, F, OP_POP);
  771.                 cexp(J, F, exp->b);
  772.                 break;
  773.  
  774.         case EXP_LOGOR:
  775.                 cexp(J, F, exp->a);
  776.                 emitline(J, F, exp);
  777.                 emit(J, F, OP_DUP);
  778.                 end = emitjump(J, F, OP_JTRUE);
  779.                 emit(J, F, OP_POP);
  780.                 cexp(J, F, exp->b);
  781.                 label(J, F, end);
  782.                 break;
  783.  
  784.         case EXP_LOGAND:
  785.                 cexp(J, F, exp->a);
  786.                 emitline(J, F, exp);
  787.                 emit(J, F, OP_DUP);
  788.                 end = emitjump(J, F, OP_JFALSE);
  789.                 emit(J, F, OP_POP);
  790.                 cexp(J, F, exp->b);
  791.                 label(J, F, end);
  792.                 break;
  793.  
  794.         case EXP_COND:
  795.                 cexp(J, F, exp->a);
  796.                 emitline(J, F, exp);
  797.                 then = emitjump(J, F, OP_JTRUE);
  798.                 cexp(J, F, exp->c);
  799.                 end = emitjump(J, F, OP_JUMP);
  800.                 label(J, F, then);
  801.                 cexp(J, F, exp->b);
  802.                 label(J, F, end);
  803.                 break;
  804.  
  805.         default:
  806.                 jsC_error(J, exp, "unknown expression: (%s)", jsP_aststring(exp->type));
  807.         }
  808. }
  809.  
  810. /* Patch break and continue statements */
  811.  
  812. static void addjump(JF, enum js_AstType type, js_Ast *target, int inst)
  813. {
  814.         js_JumpList *jump = js_malloc(J, sizeof *jump);
  815.         jump->type = type;
  816.         jump->inst = inst;
  817.         jump->next = target->jumps;
  818.         target->jumps = jump;
  819. }
  820.  
  821. static void labeljumps(JF, js_JumpList *jump, int baddr, int caddr)
  822. {
  823.         while (jump) {
  824.                 if (jump->type == STM_BREAK)
  825.                         labelto(J, F, jump->inst, baddr);
  826.                 if (jump->type == STM_CONTINUE)
  827.                         labelto(J, F, jump->inst, caddr);
  828.                 jump = jump->next;
  829.         }
  830. }
  831.  
  832. static int isloop(enum js_AstType T)
  833. {
  834.         return T == STM_DO || T == STM_WHILE ||
  835.                 T == STM_FOR || T == STM_FOR_VAR ||
  836.                 T == STM_FOR_IN || T == STM_FOR_IN_VAR;
  837. }
  838.  
  839. static int isfun(enum js_AstType T)
  840. {
  841.         return T == AST_FUNDEC || T == EXP_FUN || T == EXP_PROP_GET || T == EXP_PROP_SET;
  842. }
  843.  
  844. static int matchlabel(js_Ast *node, const char *label)
  845. {
  846.         while (node && node->type == STM_LABEL) {
  847.                 if (!strcmp(node->a->string, label))
  848.                         return 1;
  849.                 node = node->parent;
  850.         }
  851.         return 0;
  852. }
  853.  
  854. static js_Ast *breaktarget(JF, js_Ast *node, const char *label)
  855. {
  856.         while (node) {
  857.                 if (isfun(node->type))
  858.                         break;
  859.                 if (!label) {
  860.                         if (isloop(node->type) || node->type == STM_SWITCH)
  861.                                 return node;
  862.                 } else {
  863.                         if (matchlabel(node->parent, label))
  864.                                 return node;
  865.                 }
  866.                 node = node->parent;
  867.         }
  868.         return NULL;
  869. }
  870.  
  871. static js_Ast *continuetarget(JF, js_Ast *node, const char *label)
  872. {
  873.         while (node) {
  874.                 if (isfun(node->type))
  875.                         break;
  876.                 if (isloop(node->type)) {
  877.                         if (!label)
  878.                                 return node;
  879.                         else if (matchlabel(node->parent, label))
  880.                                 return node;
  881.                 }
  882.                 node = node->parent;
  883.         }
  884.         return NULL;
  885. }
  886.  
  887. static js_Ast *returntarget(JF, js_Ast *node)
  888. {
  889.         while (node) {
  890.                 if (isfun(node->type))
  891.                         return node;
  892.                 node = node->parent;
  893.         }
  894.         return NULL;
  895. }
  896.  
  897. /* Emit code to rebalance stack and scopes during an abrupt exit */
  898.  
  899. static void cexit(JF, enum js_AstType T, js_Ast *node, js_Ast *target)
  900. {
  901.         js_Ast *prev;
  902.         do {
  903.                 prev = node, node = node->parent;
  904.                 switch (node->type) {
  905.                 default:
  906.                         /* impossible */
  907.                         break;
  908.                 case STM_WITH:
  909.                         emitline(J, F, node);
  910.                         emit(J, F, OP_ENDWITH);
  911.                         break;
  912.                 case STM_FOR_IN:
  913.                 case STM_FOR_IN_VAR:
  914.                         emitline(J, F, node);
  915.                         /* pop the iterator if leaving the loop */
  916.                         if (F->script) {
  917.                                 if (T == STM_RETURN || T == STM_BREAK || (T == STM_CONTINUE && target != node)) {
  918.                                         /* pop the iterator, save the return or exp value */
  919.                                         emit(J, F, OP_ROT2);
  920.                                         emit(J, F, OP_POP);
  921.                                 }
  922.                                 if (T == STM_CONTINUE)
  923.                                         emit(J, F, OP_ROT2); /* put the iterator back on top */
  924.                         } else {
  925.                                 if (T == STM_RETURN) {
  926.                                         /* pop the iterator, save the return value */
  927.                                         emit(J, F, OP_ROT2);
  928.                                         emit(J, F, OP_POP);
  929.                                 }
  930.                                 if (T == STM_BREAK || (T == STM_CONTINUE && target != node))
  931.                                         emit(J, F, OP_POP); /* pop the iterator */
  932.                         }
  933.                         break;
  934.                 case STM_TRY:
  935.                         emitline(J, F, node);
  936.                         /* came from try block */
  937.                         if (prev == node->a) {
  938.                                 emit(J, F, OP_ENDTRY);
  939.                                 if (node->d) cstm(J, F, node->d); /* finally */
  940.                         }
  941.                         /* came from catch block */
  942.                         if (prev == node->c) {
  943.                                 /* ... with finally */
  944.                                 if (node->d) {
  945.                                         emit(J, F, OP_ENDCATCH);
  946.                                         emit(J, F, OP_ENDTRY);
  947.                                         cstm(J, F, node->d); /* finally */
  948.                                 } else {
  949.                                         emit(J, F, OP_ENDCATCH);
  950.                                 }
  951.                         }
  952.                         break;
  953.                 }
  954.         } while (node != target);
  955. }
  956.  
  957. /* Try/catch/finally */
  958.  
  959. static void ctryfinally(JF, js_Ast *trystm, js_Ast *finallystm)
  960. {
  961.         int L1;
  962.         L1 = emitjump(J, F, OP_TRY);
  963.         {
  964.                 /* if we get here, we have caught an exception in the try block */
  965.                 cstm(J, F, finallystm); /* inline finally block */
  966.                 emit(J, F, OP_THROW); /* rethrow exception */
  967.         }
  968.         label(J, F, L1);
  969.         cstm(J, F, trystm);
  970.         emit(J, F, OP_ENDTRY);
  971.         cstm(J, F, finallystm);
  972. }
  973.  
  974. static void ctrycatch(JF, js_Ast *trystm, js_Ast *catchvar, js_Ast *catchstm)
  975. {
  976.         int L1, L2;
  977.         L1 = emitjump(J, F, OP_TRY);
  978.         {
  979.                 /* if we get here, we have caught an exception in the try block */
  980.                 checkfutureword(J, F, catchvar);
  981.                 if (F->strict) {
  982.                         if (!strcmp(catchvar->string, "arguments"))
  983.                                 jsC_error(J, catchvar, "redefining 'arguments' is not allowed in strict mode");
  984.                         if (!strcmp(catchvar->string, "eval"))
  985.                                 jsC_error(J, catchvar, "redefining 'eval' is not allowed in strict mode");
  986.                 }
  987.                 emitline(J, F, catchvar);
  988.                 emitstring(J, F, OP_CATCH, catchvar->string);
  989.                 cstm(J, F, catchstm);
  990.                 emit(J, F, OP_ENDCATCH);
  991.                 L2 = emitjump(J, F, OP_JUMP); /* skip past the try block */
  992.         }
  993.         label(J, F, L1);
  994.         cstm(J, F, trystm);
  995.         emit(J, F, OP_ENDTRY);
  996.         label(J, F, L2);
  997. }
  998.  
  999. static void ctrycatchfinally(JF, js_Ast *trystm, js_Ast *catchvar, js_Ast *catchstm, js_Ast *finallystm)
  1000. {
  1001.         int L1, L2, L3;
  1002.         L1 = emitjump(J, F, OP_TRY);
  1003.         {
  1004.                 /* if we get here, we have caught an exception in the try block */
  1005.                 L2 = emitjump(J, F, OP_TRY);
  1006.                 {
  1007.                         /* if we get here, we have caught an exception in the catch block */
  1008.                         cstm(J, F, finallystm); /* inline finally block */
  1009.                         emit(J, F, OP_THROW); /* rethrow exception */
  1010.                 }
  1011.                 label(J, F, L2);
  1012.                 if (F->strict) {
  1013.                         checkfutureword(J, F, catchvar);
  1014.                         if (!strcmp(catchvar->string, "arguments"))
  1015.                                 jsC_error(J, catchvar, "redefining 'arguments' is not allowed in strict mode");
  1016.                         if (!strcmp(catchvar->string, "eval"))
  1017.                                 jsC_error(J, catchvar, "redefining 'eval' is not allowed in strict mode");
  1018.                 }
  1019.                 emitline(J, F, catchvar);
  1020.                 emitstring(J, F, OP_CATCH, catchvar->string);
  1021.                 cstm(J, F, catchstm);
  1022.                 emit(J, F, OP_ENDCATCH);
  1023.                 emit(J, F, OP_ENDTRY);
  1024.                 L3 = emitjump(J, F, OP_JUMP); /* skip past the try block to the finally block */
  1025.         }
  1026.         label(J, F, L1);
  1027.         cstm(J, F, trystm);
  1028.         emit(J, F, OP_ENDTRY);
  1029.         label(J, F, L3);
  1030.         cstm(J, F, finallystm);
  1031. }
  1032.  
  1033. /* Switch */
  1034.  
  1035. static void cswitch(JF, js_Ast *ref, js_Ast *head)
  1036. {
  1037.         js_Ast *node, *clause, *def = NULL;
  1038.         int end;
  1039.  
  1040.         cexp(J, F, ref);
  1041.  
  1042.         /* emit an if-else chain of tests for the case clause expressions */
  1043.         for (node = head; node; node = node->b) {
  1044.                 clause = node->a;
  1045.                 if (clause->type == STM_DEFAULT) {
  1046.                         if (def)
  1047.                                 jsC_error(J, clause, "more than one default label in switch");
  1048.                         def = clause;
  1049.                 } else {
  1050.                         cexp(J, F, clause->a);
  1051.                         emitline(J, F, clause);
  1052.                         clause->casejump = emitjump(J, F, OP_JCASE);
  1053.                 }
  1054.         }
  1055.         emit(J, F, OP_POP);
  1056.         if (def) {
  1057.                 emitline(J, F, def);
  1058.                 def->casejump = emitjump(J, F, OP_JUMP);
  1059.                 end = 0;
  1060.         } else {
  1061.                 end = emitjump(J, F, OP_JUMP);
  1062.         }
  1063.  
  1064.         /* emit the case clause bodies */
  1065.         for (node = head; node; node = node->b) {
  1066.                 clause = node->a;
  1067.                 label(J, F, clause->casejump);
  1068.                 if (clause->type == STM_DEFAULT)
  1069.                         cstmlist(J, F, clause->a);
  1070.                 else
  1071.                         cstmlist(J, F, clause->b);
  1072.         }
  1073.  
  1074.         if (end)
  1075.                 label(J, F, end);
  1076. }
  1077.  
  1078. /* Statements */
  1079.  
  1080. static void cvarinit(JF, js_Ast *list)
  1081. {
  1082.         while (list) {
  1083.                 js_Ast *var = list->a;
  1084.                 if (var->b) {
  1085.                         cexp(J, F, var->b);
  1086.                         emitline(J, F, var);
  1087.                         emitlocal(J, F, OP_SETLOCAL, OP_SETVAR, var->a);
  1088.                         emit(J, F, OP_POP);
  1089.                 }
  1090.                 list = list->b;
  1091.         }
  1092. }
  1093.  
  1094. static void cstm(JF, js_Ast *stm)
  1095. {
  1096.         js_Ast *target;
  1097.         int loop, cont, then, end;
  1098.  
  1099.         emitline(J, F, stm);
  1100.  
  1101.         switch (stm->type) {
  1102.         case AST_FUNDEC:
  1103.                 break;
  1104.  
  1105.         case STM_BLOCK:
  1106.                 cstmlist(J, F, stm->a);
  1107.                 break;
  1108.  
  1109.         case STM_EMPTY:
  1110.                 if (F->script) {
  1111.                         emitline(J, F, stm);
  1112.                         emit(J, F, OP_POP);
  1113.                         emit(J, F, OP_UNDEF);
  1114.                 }
  1115.                 break;
  1116.  
  1117.         case STM_VAR:
  1118.                 cvarinit(J, F, stm->a);
  1119.                 break;
  1120.  
  1121.         case STM_IF:
  1122.                 if (stm->c) {
  1123.                         cexp(J, F, stm->a);
  1124.                         emitline(J, F, stm);
  1125.                         then = emitjump(J, F, OP_JTRUE);
  1126.                         cstm(J, F, stm->c);
  1127.                         emitline(J, F, stm);
  1128.                         end = emitjump(J, F, OP_JUMP);
  1129.                         label(J, F, then);
  1130.                         cstm(J, F, stm->b);
  1131.                         label(J, F, end);
  1132.                 } else {
  1133.                         cexp(J, F, stm->a);
  1134.                         emitline(J, F, stm);
  1135.                         end = emitjump(J, F, OP_JFALSE);
  1136.                         cstm(J, F, stm->b);
  1137.                         label(J, F, end);
  1138.                 }
  1139.                 break;
  1140.  
  1141.         case STM_DO:
  1142.                 loop = here(J, F);
  1143.                 cstm(J, F, stm->a);
  1144.                 cont = here(J, F);
  1145.                 cexp(J, F, stm->b);
  1146.                 emitline(J, F, stm);
  1147.                 emitjumpto(J, F, OP_JTRUE, loop);
  1148.                 labeljumps(J, F, stm->jumps, here(J,F), cont);
  1149.                 break;
  1150.  
  1151.         case STM_WHILE:
  1152.                 loop = here(J, F);
  1153.                 cexp(J, F, stm->a);
  1154.                 emitline(J, F, stm);
  1155.                 end = emitjump(J, F, OP_JFALSE);
  1156.                 cstm(J, F, stm->b);
  1157.                 emitline(J, F, stm);
  1158.                 emitjumpto(J, F, OP_JUMP, loop);
  1159.                 label(J, F, end);
  1160.                 labeljumps(J, F, stm->jumps, here(J,F), loop);
  1161.                 break;
  1162.  
  1163.         case STM_FOR:
  1164.         case STM_FOR_VAR:
  1165.                 if (stm->type == STM_FOR_VAR) {
  1166.                         cvarinit(J, F, stm->a);
  1167.                 } else {
  1168.                         if (stm->a) {
  1169.                                 cexp(J, F, stm->a);
  1170.                                 emit(J, F, OP_POP);
  1171.                         }
  1172.                 }
  1173.                 loop = here(J, F);
  1174.                 if (stm->b) {
  1175.                         cexp(J, F, stm->b);
  1176.                         emitline(J, F, stm);
  1177.                         end = emitjump(J, F, OP_JFALSE);
  1178.                 } else {
  1179.                         end = 0;
  1180.                 }
  1181.                 cstm(J, F, stm->d);
  1182.                 cont = here(J, F);
  1183.                 if (stm->c) {
  1184.                         cexp(J, F, stm->c);
  1185.                         emit(J, F, OP_POP);
  1186.                 }
  1187.                 emitline(J, F, stm);
  1188.                 emitjumpto(J, F, OP_JUMP, loop);
  1189.                 if (end)
  1190.                         label(J, F, end);
  1191.                 labeljumps(J, F, stm->jumps, here(J,F), cont);
  1192.                 break;
  1193.  
  1194.         case STM_FOR_IN:
  1195.         case STM_FOR_IN_VAR:
  1196.                 cexp(J, F, stm->b);
  1197.                 emitline(J, F, stm);
  1198.                 emit(J, F, OP_ITERATOR);
  1199.                 loop = here(J, F);
  1200.                 {
  1201.                         emitline(J, F, stm);
  1202.                         emit(J, F, OP_NEXTITER);
  1203.                         end = emitjump(J, F, OP_JFALSE);
  1204.                         cassignforin(J, F, stm);
  1205.                         if (F->script) {
  1206.                                 emit(J, F, OP_ROT2);
  1207.                                 cstm(J, F, stm->c);
  1208.                                 emit(J, F, OP_ROT2);
  1209.                         } else {
  1210.                                 cstm(J, F, stm->c);
  1211.                         }
  1212.                         emitline(J, F, stm);
  1213.                         emitjumpto(J, F, OP_JUMP, loop);
  1214.                 }
  1215.                 label(J, F, end);
  1216.                 labeljumps(J, F, stm->jumps, here(J,F), loop);
  1217.                 break;
  1218.  
  1219.         case STM_SWITCH:
  1220.                 cswitch(J, F, stm->a, stm->b);
  1221.                 labeljumps(J, F, stm->jumps, here(J,F), 0);
  1222.                 break;
  1223.  
  1224.         case STM_LABEL:
  1225.                 cstm(J, F, stm->b);
  1226.                 /* skip consecutive labels */
  1227.                 while (stm->type == STM_LABEL)
  1228.                         stm = stm->b;
  1229.                 /* loops and switches have already been labelled */
  1230.                 if (!isloop(stm->type) && stm->type != STM_SWITCH)
  1231.                         labeljumps(J, F, stm->jumps, here(J,F), 0);
  1232.                 break;
  1233.  
  1234.         case STM_BREAK:
  1235.                 if (stm->a) {
  1236.                         checkfutureword(J, F, stm->a);
  1237.                         target = breaktarget(J, F, stm->parent, stm->a->string);
  1238.                         if (!target)
  1239.                                 jsC_error(J, stm, "break label '%s' not found", stm->a->string);
  1240.                 } else {
  1241.                         target = breaktarget(J, F, stm->parent, NULL);
  1242.                         if (!target)
  1243.                                 jsC_error(J, stm, "unlabelled break must be inside loop or switch");
  1244.                 }
  1245.                 cexit(J, F, STM_BREAK, stm, target);
  1246.                 emitline(J, F, stm);
  1247.                 addjump(J, F, STM_BREAK, target, emitjump(J, F, OP_JUMP));
  1248.                 break;
  1249.  
  1250.         case STM_CONTINUE:
  1251.                 if (stm->a) {
  1252.                         checkfutureword(J, F, stm->a);
  1253.                         target = continuetarget(J, F, stm->parent, stm->a->string);
  1254.                         if (!target)
  1255.                                 jsC_error(J, stm, "continue label '%s' not found", stm->a->string);
  1256.                 } else {
  1257.                         target = continuetarget(J, F, stm->parent, NULL);
  1258.                         if (!target)
  1259.                                 jsC_error(J, stm, "continue must be inside loop");
  1260.                 }
  1261.                 cexit(J, F, STM_CONTINUE, stm, target);
  1262.                 emitline(J, F, stm);
  1263.                 addjump(J, F, STM_CONTINUE, target, emitjump(J, F, OP_JUMP));
  1264.                 break;
  1265.  
  1266.         case STM_RETURN:
  1267.                 if (stm->a)
  1268.                         cexp(J, F, stm->a);
  1269.                 else
  1270.                         emit(J, F, OP_UNDEF);
  1271.                 target = returntarget(J, F, stm->parent);
  1272.                 if (!target)
  1273.                         jsC_error(J, stm, "return not in function");
  1274.                 cexit(J, F, STM_RETURN, stm, target);
  1275.                 emitline(J, F, stm);
  1276.                 emit(J, F, OP_RETURN);
  1277.                 break;
  1278.  
  1279.         case STM_THROW:
  1280.                 cexp(J, F, stm->a);
  1281.                 emitline(J, F, stm);
  1282.                 emit(J, F, OP_THROW);
  1283.                 break;
  1284.  
  1285.         case STM_WITH:
  1286.                 F->lightweight = 0;
  1287.                 if (F->strict)
  1288.                         jsC_error(J, stm->a, "'with' statements are not allowed in strict mode");
  1289.                 cexp(J, F, stm->a);
  1290.                 emitline(J, F, stm);
  1291.                 emit(J, F, OP_WITH);
  1292.                 cstm(J, F, stm->b);
  1293.                 emitline(J, F, stm);
  1294.                 emit(J, F, OP_ENDWITH);
  1295.                 break;
  1296.  
  1297.         case STM_TRY:
  1298.                 emitline(J, F, stm);
  1299.                 if (stm->b && stm->c) {
  1300.                         F->lightweight = 0;
  1301.                         if (stm->d)
  1302.                                 ctrycatchfinally(J, F, stm->a, stm->b, stm->c, stm->d);
  1303.                         else
  1304.                                 ctrycatch(J, F, stm->a, stm->b, stm->c);
  1305.                 } else {
  1306.                         ctryfinally(J, F, stm->a, stm->d);
  1307.                 }
  1308.                 break;
  1309.  
  1310.         case STM_DEBUGGER:
  1311.                 emitline(J, F, stm);
  1312.                 emit(J, F, OP_DEBUGGER);
  1313.                 break;
  1314.  
  1315.         default:
  1316.                 if (F->script) {
  1317.                         emitline(J, F, stm);
  1318.                         emit(J, F, OP_POP);
  1319.                         cexp(J, F, stm);
  1320.                 } else {
  1321.                         cexp(J, F, stm);
  1322.                         emitline(J, F, stm);
  1323.                         emit(J, F, OP_POP);
  1324.                 }
  1325.                 break;
  1326.         }
  1327. }
  1328.  
  1329. static void cstmlist(JF, js_Ast *list)
  1330. {
  1331.         while (list) {
  1332.                 cstm(J, F, list->a);
  1333.                 list = list->b;
  1334.         }
  1335. }
  1336.  
  1337. /* Declarations and programs */
  1338.  
  1339. static int listlength(js_Ast *list)
  1340. {
  1341.         int n = 0;
  1342.         while (list) ++n, list = list->b;
  1343.         return n;
  1344. }
  1345.  
  1346. static void cparams(JF, js_Ast *list, js_Ast *fname)
  1347. {
  1348.         F->numparams = listlength(list);
  1349.         while (list) {
  1350.                 checkfutureword(J, F, list->a);
  1351.                 addlocal(J, F, list->a, 0);
  1352.                 list = list->b;
  1353.         }
  1354. }
  1355.  
  1356. static void cvardecs(JF, js_Ast *node)
  1357. {
  1358.         if (node->type == AST_LIST) {
  1359.                 while (node) {
  1360.                         cvardecs(J, F, node->a);
  1361.                         node = node->b;
  1362.                 }
  1363.                 return;
  1364.         }
  1365.  
  1366.         if (isfun(node->type))
  1367.                 return; /* stop at inner functions */
  1368.  
  1369.         if (node->type == EXP_VAR) {
  1370.                 checkfutureword(J, F, node->a);
  1371.                 addlocal(J, F, node->a, 1);
  1372.         }
  1373.  
  1374.         if (node->a) cvardecs(J, F, node->a);
  1375.         if (node->b) cvardecs(J, F, node->b);
  1376.         if (node->c) cvardecs(J, F, node->c);
  1377.         if (node->d) cvardecs(J, F, node->d);
  1378. }
  1379.  
  1380. static void cfundecs(JF, js_Ast *list)
  1381. {
  1382.         while (list) {
  1383.                 js_Ast *stm = list->a;
  1384.                 if (stm->type == AST_FUNDEC) {
  1385.                         emitline(J, F, stm);
  1386.                         emitfunction(J, F, newfun(J, stm->line, stm->a, stm->b, stm->c, 0, F->strict));
  1387.                         emitline(J, F, stm);
  1388.                         emit(J, F, OP_SETLOCAL);
  1389.                         emitarg(J, F, addlocal(J, F, stm->a, 0));
  1390.                         emit(J, F, OP_POP);
  1391.                 }
  1392.                 list = list->b;
  1393.         }
  1394. }
  1395.  
  1396. static void cfunbody(JF, js_Ast *name, js_Ast *params, js_Ast *body)
  1397. {
  1398.         F->lightweight = 1;
  1399.         F->arguments = 0;
  1400.  
  1401.         if (F->script)
  1402.                 F->lightweight = 0;
  1403.  
  1404.         /* Check if first statement is 'use strict': */
  1405.         if (body && body->type == AST_LIST && body->a && body->a->type == EXP_STRING)
  1406.                 if (!strcmp(body->a->string, "use strict"))
  1407.                         F->strict = 1;
  1408.  
  1409.         F->lastline = F->line;
  1410.  
  1411.         cparams(J, F, params, name);
  1412.  
  1413.         if (body) {
  1414.                 cvardecs(J, F, body);
  1415.                 cfundecs(J, F, body);
  1416.         }
  1417.  
  1418.         if (name) {
  1419.                 checkfutureword(J, F, name);
  1420.                 if (findlocal(J, F, name->string) < 0) {
  1421.                         emit(J, F, OP_CURRENT);
  1422.                         emit(J, F, OP_SETLOCAL);
  1423.                         emitarg(J, F, addlocal(J, F, name, 0));
  1424.                         emit(J, F, OP_POP);
  1425.                 }
  1426.         }
  1427.  
  1428.         if (F->script) {
  1429.                 emit(J, F, OP_UNDEF);
  1430.                 cstmlist(J, F, body);
  1431.                 emit(J, F, OP_RETURN);
  1432.         } else {
  1433.                 cstmlist(J, F, body);
  1434.                 emit(J, F, OP_UNDEF);
  1435.                 emit(J, F, OP_RETURN);
  1436.         }
  1437. }
  1438.  
  1439. js_Function *jsC_compilefunction(js_State *J, js_Ast *prog)
  1440. {
  1441.         return newfun(J, prog->line, prog->a, prog->b, prog->c, 0, J->default_strict);
  1442. }
  1443.  
  1444. js_Function *jsC_compilescript(js_State *J, js_Ast *prog, int default_strict)
  1445. {
  1446.         return newfun(J, prog ? prog->line : 0, NULL, NULL, prog, 1, default_strict);
  1447. }
  1448.