4 #include "jsvalue.h" /* for jsV_numbertostring */
6 #define cexp jsC_cexp /* collision with math.h */
8 #define JF js_State *J, js_Function *F
10 JS_NORETURN void jsC_error(js_State *J, js_Ast *node, const char *fmt, ...) JS_PRINTFLIKE(3,4);
12 static void cfunbody(JF, js_Ast *name, js_Ast *params, js_Ast *body);
13 static void cexp(JF, js_Ast *exp);
14 static void cstmlist(JF, js_Ast *list);
15 static void cstm(JF, js_Ast *stm);
17 void jsC_error(js_State *J, js_Ast *node, const char *fmt, ...)
24 vsnprintf(msgbuf, 256, fmt, ap);
27 snprintf(buf, 256, "%s:%d: ", J->filename, node->line);
30 js_newsyntaxerror(J, buf);
34 static js_Function *newfun(js_State *J, js_Ast *name, js_Ast *params, js_Ast *body, int script)
36 js_Function *F = js_malloc(J, sizeof *F);
37 memset(F, 0, sizeof *F);
43 F->filename = js_intern(J, J->filename);
44 F->line = name ? name->line : params ? params->line : body ? body->line : 1;
46 F->name = name ? name->string : "";
48 cfunbody(J, F, name, params, body);
53 /* Emit opcodes, constants and jumps */
55 static void emitraw(JF, int value)
57 if (value != (js_Instruction)value)
58 js_syntaxerror(J, "integer overflow in instruction coding");
59 if (F->codelen >= F->codecap) {
60 F->codecap = F->codecap ? F->codecap * 2 : 64;
61 F->code = js_realloc(J, F->code, F->codecap * sizeof *F->code);
63 F->code[F->codelen++] = value;
66 static void emit(JF, int value)
71 static void emitline(JF, js_Ast *node)
73 if (F->lastline != node->line) {
74 F->lastline = node->line;
76 emitraw(J, F, node->line);
80 static int addfunction(JF, js_Function *value)
82 if (F->funlen >= F->funcap) {
83 F->funcap = F->funcap ? F->funcap * 2 : 16;
84 F->funtab = js_realloc(J, F->funtab, F->funcap * sizeof *F->funtab);
86 F->funtab[F->funlen] = value;
90 static int addnumber(JF, double value)
93 for (i = 0; i < F->numlen; ++i)
94 if (F->numtab[i] == value)
96 if (F->numlen >= F->numcap) {
97 F->numcap = F->numcap ? F->numcap * 2 : 16;
98 F->numtab = js_realloc(J, F->numtab, F->numcap * sizeof *F->numtab);
100 F->numtab[F->numlen] = value;
104 static int addstring(JF, const char *value)
107 for (i = 0; i < F->strlen; ++i)
108 if (!strcmp(F->strtab[i], value))
110 if (F->strlen >= F->strcap) {
111 F->strcap = F->strcap ? F->strcap * 2 : 16;
112 F->strtab = js_realloc(J, F->strtab, F->strcap * sizeof *F->strtab);
114 F->strtab[F->strlen] = value;
118 static void addlocal(JF, js_Ast *ident, int reuse)
120 const char *name = ident->string;
122 if (!strcmp(name, "arguments"))
123 jsC_error(J, ident, "redefining 'arguments' is not allowed in strict mode");
124 if (!strcmp(name, "eval"))
125 jsC_error(J, ident, "redefining 'eval' is not allowed in strict mode");
127 if (reuse || J->strict) {
129 for (i = 0; i < F->varlen; ++i) {
130 if (!strcmp(F->vartab[i], name)) {
134 jsC_error(J, ident, "duplicate formal parameter '%s'", name);
138 if (F->varlen >= F->varcap) {
139 F->varcap = F->varcap ? F->varcap * 2 : 16;
140 F->vartab = js_realloc(J, F->vartab, F->varcap * sizeof *F->vartab);
142 F->vartab[F->varlen++] = name;
145 static int findlocal(JF, const char *name)
148 for (i = F->varlen; i > 0; --i)
149 if (!strcmp(F->vartab[i-1], name))
154 static void emitfunction(JF, js_Function *fun)
156 emit(J, F, OP_CLOSURE);
157 emitraw(J, F, addfunction(J, F, fun));
160 static void emitnumber(JF, double num)
163 emit(J, F, OP_NUMBER_0);
166 } else if (num == 1) {
167 emit(J, F, OP_NUMBER_1);
168 } else if (num == (js_Instruction)num) {
169 emit(J, F, OP_NUMBER_POS);
170 emitraw(J, F, (js_Instruction)num);
171 } else if (num < 0 && -num == (js_Instruction)(-num)) {
172 emit(J, F, OP_NUMBER_NEG);
173 emitraw(J, F, (js_Instruction)(-num));
175 emit(J, F, OP_NUMBER);
176 emitraw(J, F, addnumber(J, F, num));
180 static void emitstring(JF, int opcode, const char *str)
183 emitraw(J, F, addstring(J, F, str));
186 static void emitlocal(JF, int oploc, int opvar, js_Ast *ident)
189 if (J->strict && oploc == OP_SETLOCAL) {
190 if (!strcmp(ident->string, "arguments"))
191 jsC_error(J, ident, "'arguments' is read-only in strict mode");
192 if (!strcmp(ident->string, "eval"))
193 jsC_error(J, ident, "'eval' is read-only in strict mode");
195 if (F->lightweight) {
196 i = findlocal(J, F, ident->string);
203 emitstring(J, F, opvar, ident->string);
211 static int emitjump(JF, int opcode)
213 int inst = F->codelen + 1;
219 static void emitjumpto(JF, int opcode, int dest)
222 if (dest != (js_Instruction)dest)
223 js_syntaxerror(J, "jump address integer overflow");
227 static void labelto(JF, int inst, int addr)
229 if (addr != (js_Instruction)addr)
230 js_syntaxerror(J, "jump address integer overflow");
231 F->code[inst] = addr;
234 static void label(JF, int inst)
236 labelto(J, F, inst, F->codelen);
241 static void ctypeof(JF, js_Ast *exp)
243 if (exp->type == EXP_IDENTIFIER)
244 emitlocal(J, F, OP_GETLOCAL, OP_HASVAR, exp);
247 emit(J, F, OP_TYPEOF);
250 static void cunary(JF, js_Ast *exp, int opcode)
256 static void cbinary(JF, js_Ast *exp, int opcode)
263 static void carray(JF, js_Ast *list)
267 if (list->a->type != EXP_UNDEF) {
268 emitnumber(J, F, i++);
270 emit(J, F, OP_INITPROP);
278 static void checkdup(JF, js_Ast *list, js_Ast *end)
280 char nbuf[32], sbuf[32];
281 const char *needle, *straw;
283 if (end->a->type == EXP_NUMBER)
284 needle = jsV_numbertostring(J, nbuf, end->a->number);
286 needle = end->a->string;
288 while (list->a != end) {
289 if (list->a->type == end->type) {
290 js_Ast *prop = list->a->a;
291 if (prop->type == EXP_NUMBER)
292 straw = jsV_numbertostring(J, sbuf, prop->number);
294 straw = prop->string;
295 if (!strcmp(needle, straw))
296 jsC_error(J, list, "duplicate property '%s' in object literal", needle);
302 static void cobject(JF, js_Ast *list)
307 js_Ast *kv = list->a;
308 js_Ast *prop = kv->a;
310 if (prop->type == AST_IDENTIFIER || prop->type == EXP_STRING)
311 emitstring(J, F, OP_STRING, prop->string);
312 else if (prop->type == EXP_NUMBER)
313 emitnumber(J, F, prop->number);
315 jsC_error(J, prop, "invalid property name in object initializer");
318 checkdup(J, F, head, kv);
323 emit(J, F, OP_INITPROP);
326 emitfunction(J, F, newfun(J, NULL, kv->b, kv->c, 0));
327 emit(J, F, OP_INITGETTER);
330 emitfunction(J, F, newfun(J, NULL, kv->b, kv->c, 0));
331 emit(J, F, OP_INITSETTER);
339 static int cargs(JF, js_Ast *list)
350 static void cassign(JF, js_Ast *exp)
352 js_Ast *lhs = exp->a;
353 js_Ast *rhs = exp->b;
357 emitlocal(J, F, OP_SETLOCAL, OP_SETVAR, lhs);
363 emit(J, F, OP_SETPROP);
368 emitstring(J, F, OP_SETPROP_S, lhs->b->string);
371 jsC_error(J, lhs, "invalid l-value in assignment");
375 static void cassignforin(JF, js_Ast *stm)
377 js_Ast *lhs = stm->a;
379 if (stm->type == STM_FOR_IN_VAR) {
381 jsC_error(J, lhs->b, "more than one loop variable in for-in statement");
382 emitlocal(J, F, OP_SETLOCAL, OP_SETVAR, lhs->a->a); /* list(var-init(ident)) */
389 emitlocal(J, F, OP_SETLOCAL, OP_SETVAR, lhs);
396 emit(J, F, OP_SETPROP);
402 emitstring(J, F, OP_SETPROP_S, lhs->b->string);
406 jsC_error(J, lhs, "invalid l-value in for-in loop assignment");
410 static void cassignop1(JF, js_Ast *lhs)
414 emitlocal(J, F, OP_GETLOCAL, OP_GETVAR, lhs);
420 emit(J, F, OP_GETPROP);
425 emitstring(J, F, OP_GETPROP_S, lhs->b->string);
428 jsC_error(J, lhs, "invalid l-value in assignment");
432 static void cassignop2(JF, js_Ast *lhs, int postfix)
436 if (postfix) emit(J, F, OP_ROT2);
437 emitlocal(J, F, OP_SETLOCAL, OP_SETVAR, lhs);
440 if (postfix) emit(J, F, OP_ROT4);
441 emit(J, F, OP_SETPROP);
444 if (postfix) emit(J, F, OP_ROT3);
445 emitstring(J, F, OP_SETPROP_S, lhs->b->string);
448 jsC_error(J, lhs, "invalid l-value in assignment");
452 static void cassignop(JF, js_Ast *exp, int opcode)
454 js_Ast *lhs = exp->a;
455 js_Ast *rhs = exp->b;
456 cassignop1(J, F, lhs);
459 cassignop2(J, F, lhs, 0);
462 static void cdelete(JF, js_Ast *exp)
467 jsC_error(J, exp, "delete on an unqualified name is not allowed in strict mode");
468 emitlocal(J, F, OP_DELLOCAL, OP_DELVAR, exp);
473 emit(J, F, OP_DELPROP);
477 emitstring(J, F, OP_DELPROP_S, exp->b->string);
480 jsC_error(J, exp, "invalid l-value in delete expression");
484 static void ceval(JF, js_Ast *fun, js_Ast *args)
486 int n = cargs(J, F, args);
488 emit(J, F, OP_UNDEF);
494 static void ccall(JF, js_Ast *fun, js_Ast *args)
502 emit(J, F, OP_GETPROP);
508 emitstring(J, F, OP_GETPROP_S, fun->b->string);
512 if (!strcmp(fun->string, "eval")) {
513 ceval(J, F, fun, args);
519 emit(J, F, J->strict ? OP_UNDEF : OP_GLOBAL);
522 n = cargs(J, F, args);
527 static void cexp(JF, js_Ast *exp)
533 case EXP_STRING: emitstring(J, F, OP_STRING, exp->string); break;
534 case EXP_NUMBER: emitnumber(J, F, exp->number); break;
535 case EXP_UNDEF: emit(J, F, OP_UNDEF); break;
536 case EXP_NULL: emit(J, F, OP_NULL); break;
537 case EXP_TRUE: emit(J, F, OP_TRUE); break;
538 case EXP_FALSE: emit(J, F, OP_FALSE); break;
539 case EXP_THIS: emit(J, F, OP_THIS); break;
542 emit(J, F, OP_NEWREGEXP);
543 emitraw(J, F, addstring(J, F, exp->string));
544 emitraw(J, F, exp->number);
548 emit(J, F, OP_NEWOBJECT);
549 cobject(J, F, exp->a);
553 emit(J, F, OP_NEWARRAY);
554 carray(J, F, exp->a);
558 emitfunction(J, F, newfun(J, exp->a, exp->b, exp->c, 0));
562 emitlocal(J, F, OP_GETLOCAL, OP_GETVAR, exp);
568 emit(J, F, OP_GETPROP);
573 emitstring(J, F, OP_GETPROP_S, exp->b->string);
577 ccall(J, F, exp->a, exp->b);
582 n = cargs(J, F, exp->b);
588 cdelete(J, F, exp->a);
592 cassignop1(J, F, exp->a);
594 cassignop2(J, F, exp->a, 0);
598 cassignop1(J, F, exp->a);
600 cassignop2(J, F, exp->a, 0);
604 cassignop1(J, F, exp->a);
605 emit(J, F, OP_POSTINC);
606 cassignop2(J, F, exp->a, 1);
611 cassignop1(J, F, exp->a);
612 emit(J, F, OP_POSTDEC);
613 cassignop2(J, F, exp->a, 1);
620 emit(J, F, OP_UNDEF);
623 case EXP_TYPEOF: ctypeof(J, F, exp->a); break;
624 case EXP_POS: cunary(J, F, exp, OP_POS); break;
625 case EXP_NEG: cunary(J, F, exp, OP_NEG); break;
626 case EXP_BITNOT: cunary(J, F, exp, OP_BITNOT); break;
627 case EXP_LOGNOT: cunary(J, F, exp, OP_LOGNOT); break;
629 case EXP_BITOR: cbinary(J, F, exp, OP_BITOR); break;
630 case EXP_BITXOR: cbinary(J, F, exp, OP_BITXOR); break;
631 case EXP_BITAND: cbinary(J, F, exp, OP_BITAND); break;
632 case EXP_EQ: cbinary(J, F, exp, OP_EQ); break;
633 case EXP_NE: cbinary(J, F, exp, OP_NE); break;
634 case EXP_STRICTEQ: cbinary(J, F, exp, OP_STRICTEQ); break;
635 case EXP_STRICTNE: cbinary(J, F, exp, OP_STRICTNE); break;
636 case EXP_LT: cbinary(J, F, exp, OP_LT); break;
637 case EXP_GT: cbinary(J, F, exp, OP_GT); break;
638 case EXP_LE: cbinary(J, F, exp, OP_LE); break;
639 case EXP_GE: cbinary(J, F, exp, OP_GE); break;
640 case EXP_INSTANCEOF: cbinary(J, F, exp, OP_INSTANCEOF); break;
641 case EXP_IN: cbinary(J, F, exp, OP_IN); break;
642 case EXP_SHL: cbinary(J, F, exp, OP_SHL); break;
643 case EXP_SHR: cbinary(J, F, exp, OP_SHR); break;
644 case EXP_USHR: cbinary(J, F, exp, OP_USHR); break;
645 case EXP_ADD: cbinary(J, F, exp, OP_ADD); break;
646 case EXP_SUB: cbinary(J, F, exp, OP_SUB); break;
647 case EXP_MUL: cbinary(J, F, exp, OP_MUL); break;
648 case EXP_DIV: cbinary(J, F, exp, OP_DIV); break;
649 case EXP_MOD: cbinary(J, F, exp, OP_MOD); break;
651 case EXP_ASS: cassign(J, F, exp); break;
652 case EXP_ASS_MUL: cassignop(J, F, exp, OP_MUL); break;
653 case EXP_ASS_DIV: cassignop(J, F, exp, OP_DIV); break;
654 case EXP_ASS_MOD: cassignop(J, F, exp, OP_MOD); break;
655 case EXP_ASS_ADD: cassignop(J, F, exp, OP_ADD); break;
656 case EXP_ASS_SUB: cassignop(J, F, exp, OP_SUB); break;
657 case EXP_ASS_SHL: cassignop(J, F, exp, OP_SHL); break;
658 case EXP_ASS_SHR: cassignop(J, F, exp, OP_SHR); break;
659 case EXP_ASS_USHR: cassignop(J, F, exp, OP_USHR); break;
660 case EXP_ASS_BITAND: cassignop(J, F, exp, OP_BITAND); break;
661 case EXP_ASS_BITXOR: cassignop(J, F, exp, OP_BITXOR); break;
662 case EXP_ASS_BITOR: cassignop(J, F, exp, OP_BITOR); break;
673 end = emitjump(J, F, OP_JTRUE);
682 end = emitjump(J, F, OP_JFALSE);
690 then = emitjump(J, F, OP_JTRUE);
692 end = emitjump(J, F, OP_JUMP);
699 jsC_error(J, exp, "unknown expression: (%s)", jsP_aststring(exp->type));
703 /* Patch break and continue statements */
705 static void addjump(JF, enum js_AstType type, js_Ast *target, int inst)
707 js_JumpList *jump = js_malloc(J, sizeof *jump);
710 jump->next = target->jumps;
711 target->jumps = jump;
714 static void labeljumps(JF, js_JumpList *jump, int baddr, int caddr)
717 if (jump->type == STM_BREAK)
718 labelto(J, F, jump->inst, baddr);
719 if (jump->type == STM_CONTINUE)
720 labelto(J, F, jump->inst, caddr);
725 static int isloop(enum js_AstType T)
727 return T == STM_DO || T == STM_WHILE ||
728 T == STM_FOR || T == STM_FOR_VAR ||
729 T == STM_FOR_IN || T == STM_FOR_IN_VAR;
732 static int isfun(enum js_AstType T)
734 return T == AST_FUNDEC || T == EXP_FUN || T == EXP_PROP_GET || T == EXP_PROP_SET;
737 static int matchlabel(js_Ast *node, const char *label)
739 while (node && node->type == STM_LABEL) {
740 if (!strcmp(node->a->string, label))
747 static js_Ast *breaktarget(JF, js_Ast *node, const char *label)
750 if (isfun(node->type))
753 if (isloop(node->type) || node->type == STM_SWITCH)
756 if (matchlabel(node->parent, label))
764 static js_Ast *continuetarget(JF, js_Ast *node, const char *label)
767 if (isfun(node->type))
769 if (isloop(node->type)) {
772 else if (matchlabel(node->parent, label))
780 static js_Ast *returntarget(JF, js_Ast *node)
783 if (isfun(node->type))
790 /* Emit code to rebalance stack and scopes during an abrupt exit */
792 static void cexit(JF, enum js_AstType T, js_Ast *node, js_Ast *target)
796 prev = node, node = node->parent;
797 switch (node->type) {
799 emit(J, F, OP_ENDWITH);
803 /* pop the iterator if leaving the loop */
805 if (T == STM_RETURN || T == STM_BREAK || (T == STM_CONTINUE && target != node)) {
806 /* pop the iterator, save the return or exp value */
810 if (T == STM_CONTINUE)
811 emit(J, F, OP_ROT2); /* put the iterator back on top */
813 if (T == STM_RETURN) {
814 /* pop the iterator, save the return value */
818 if (T == STM_BREAK || (T == STM_CONTINUE && target != node))
819 emit(J, F, OP_POP); /* pop the iterator */
823 /* came from try block */
824 if (prev == node->a) {
825 emit(J, F, OP_ENDTRY);
826 if (node->d) cstm(J, F, node->d); /* finally */
828 /* came from catch block */
829 if (prev == node->c) {
830 /* ... with finally */
832 emit(J, F, OP_ENDCATCH);
833 emit(J, F, OP_ENDTRY);
834 cstm(J, F, node->d); /* finally */
836 emit(J, F, OP_ENDCATCH);
841 } while (node != target);
844 /* Try/catch/finally */
846 static void ctryfinally(JF, js_Ast *trystm, js_Ast *finallystm)
849 L1 = emitjump(J, F, OP_TRY);
851 /* if we get here, we have caught an exception in the try block */
852 cstm(J, F, finallystm); /* inline finally block */
853 emit(J, F, OP_THROW); /* rethrow exception */
857 emit(J, F, OP_ENDTRY);
858 cstm(J, F, finallystm);
861 static void ctrycatch(JF, js_Ast *trystm, js_Ast *catchvar, js_Ast *catchstm)
864 L1 = emitjump(J, F, OP_TRY);
866 /* if we get here, we have caught an exception in the try block */
868 if (!strcmp(catchvar->string, "arguments"))
869 jsC_error(J, catchvar, "redefining 'arguments' is not allowed in strict mode");
870 if (!strcmp(catchvar->string, "eval"))
871 jsC_error(J, catchvar, "redefining 'eval' is not allowed in strict mode");
873 emitstring(J, F, OP_CATCH, catchvar->string);
874 cstm(J, F, catchstm);
875 emit(J, F, OP_ENDCATCH);
876 L2 = emitjump(J, F, OP_JUMP); /* skip past the try block */
880 emit(J, F, OP_ENDTRY);
884 static void ctrycatchfinally(JF, js_Ast *trystm, js_Ast *catchvar, js_Ast *catchstm, js_Ast *finallystm)
887 L1 = emitjump(J, F, OP_TRY);
889 /* if we get here, we have caught an exception in the try block */
890 L2 = emitjump(J, F, OP_TRY);
892 /* if we get here, we have caught an exception in the catch block */
893 cstm(J, F, finallystm); /* inline finally block */
894 emit(J, F, OP_THROW); /* rethrow exception */
898 if (!strcmp(catchvar->string, "arguments"))
899 jsC_error(J, catchvar, "redefining 'arguments' is not allowed in strict mode");
900 if (!strcmp(catchvar->string, "eval"))
901 jsC_error(J, catchvar, "redefining 'eval' is not allowed in strict mode");
903 emitstring(J, F, OP_CATCH, catchvar->string);
904 cstm(J, F, catchstm);
905 emit(J, F, OP_ENDCATCH);
906 L3 = emitjump(J, F, OP_JUMP); /* skip past the try block to the finally block */
910 emit(J, F, OP_ENDTRY);
912 cstm(J, F, finallystm);
917 static void cswitch(JF, js_Ast *ref, js_Ast *head)
919 js_Ast *node, *clause, *def = NULL;
924 /* emit an if-else chain of tests for the case clause expressions */
925 for (node = head; node; node = node->b) {
927 if (clause->type == STM_DEFAULT) {
929 jsC_error(J, clause, "more than one default label in switch");
932 cexp(J, F, clause->a);
933 clause->casejump = emitjump(J, F, OP_JCASE);
938 def->casejump = emitjump(J, F, OP_JUMP);
941 end = emitjump(J, F, OP_JUMP);
944 /* emit the casue clause bodies */
945 for (node = head; node; node = node->b) {
947 label(J, F, clause->casejump);
948 if (clause->type == STM_DEFAULT)
949 cstmlist(J, F, clause->a);
951 cstmlist(J, F, clause->b);
960 static void cvarinit(JF, js_Ast *list)
963 js_Ast *var = list->a;
966 emitlocal(J, F, OP_SETLOCAL, OP_SETVAR, var->a);
973 static void cstm(JF, js_Ast *stm)
976 int loop, cont, then, end;
985 cstmlist(J, F, stm->a);
991 emit(J, F, OP_UNDEF);
996 cvarinit(J, F, stm->a);
1002 then = emitjump(J, F, OP_JTRUE);
1004 end = emitjump(J, F, OP_JUMP);
1010 end = emitjump(J, F, OP_JFALSE);
1021 emitjumpto(J, F, OP_JTRUE, loop);
1022 labeljumps(J, F, stm->jumps, here(J,F), cont);
1028 end = emitjump(J, F, OP_JFALSE);
1030 emitjumpto(J, F, OP_JUMP, loop);
1032 labeljumps(J, F, stm->jumps, here(J,F), loop);
1037 if (stm->type == STM_FOR_VAR) {
1038 cvarinit(J, F, stm->a);
1048 end = emitjump(J, F, OP_JFALSE);
1058 emitjumpto(J, F, OP_JUMP, loop);
1061 labeljumps(J, F, stm->jumps, here(J,F), cont);
1065 case STM_FOR_IN_VAR:
1067 emit(J, F, OP_ITERATOR);
1070 emit(J, F, OP_NEXTITER);
1071 end = emitjump(J, F, OP_JFALSE);
1072 cassignforin(J, F, stm);
1074 emit(J, F, OP_ROT2);
1076 emit(J, F, OP_ROT2);
1080 emitjumpto(J, F, OP_JUMP, loop);
1083 labeljumps(J, F, stm->jumps, here(J,F), loop);
1087 cswitch(J, F, stm->a, stm->b);
1088 labeljumps(J, F, stm->jumps, here(J,F), 0);
1093 /* skip consecutive labels */
1094 while (stm->type == STM_LABEL)
1096 /* loops and switches have already been labelled */
1097 if (!isloop(stm->type) && stm->type != STM_SWITCH)
1098 labeljumps(J, F, stm->jumps, here(J,F), 0);
1103 target = breaktarget(J, F, stm, stm->a->string);
1105 jsC_error(J, stm, "break label '%s' not found", stm->a->string);
1107 target = breaktarget(J, F, stm, NULL);
1109 jsC_error(J, stm, "unlabelled break must be inside loop or switch");
1111 cexit(J, F, STM_BREAK, stm, target);
1112 addjump(J, F, STM_BREAK, target, emitjump(J, F, OP_JUMP));
1117 target = continuetarget(J, F, stm, stm->a->string);
1119 jsC_error(J, stm, "continue label '%s' not found", stm->a->string);
1121 target = continuetarget(J, F, stm, NULL);
1123 jsC_error(J, stm, "continue must be inside loop");
1125 cexit(J, F, STM_CONTINUE, stm, target);
1126 addjump(J, F, STM_CONTINUE, target, emitjump(J, F, OP_JUMP));
1133 emit(J, F, OP_UNDEF);
1134 target = returntarget(J, F, stm);
1136 jsC_error(J, stm, "return not in function");
1137 cexit(J, F, STM_RETURN, stm, target);
1138 emit(J, F, OP_RETURN);
1143 emit(J, F, OP_THROW);
1148 emit(J, F, OP_WITH);
1150 emit(J, F, OP_ENDWITH);
1154 if (stm->b && stm->c) {
1156 ctrycatchfinally(J, F, stm->a, stm->b, stm->c, stm->d);
1158 ctrycatch(J, F, stm->a, stm->b, stm->c);
1160 ctryfinally(J, F, stm->a, stm->d);
1165 emit(J, F, OP_DEBUGGER);
1180 static void cstmlist(JF, js_Ast *list)
1183 cstm(J, F, list->a);
1190 static void analyze(JF, js_Ast *node)
1192 if (isfun(node->type)) {
1194 return; /* don't scan inner functions */
1197 if (node->type == STM_WITH) {
1201 if (node->type == STM_TRY && node->c) {
1205 if (node->type == EXP_IDENTIFIER) {
1206 if (!strcmp(node->string, "arguments")) {
1209 } else if (!strcmp(node->string, "eval")) {
1210 /* eval may only be used as a direct function call */
1211 if (!node->parent || node->parent->type != EXP_CALL || node->parent->a != node)
1212 js_evalerror(J, "%s:%d: invalid use of 'eval'", J->filename, node->line);
1217 if (node->a) analyze(J, F, node->a);
1218 if (node->b) analyze(J, F, node->b);
1219 if (node->c) analyze(J, F, node->c);
1220 if (node->d) analyze(J, F, node->d);
1223 /* Declarations and programs */
1225 static int listlength(js_Ast *list)
1228 while (list) ++n, list = list->b;
1232 static void cparams(JF, js_Ast *list)
1234 F->numparams = listlength(list);
1236 addlocal(J, F, list->a, 0);
1241 static void cvardecs(JF, js_Ast *node)
1243 if (isfun(node->type))
1244 return; /* stop at inner functions */
1246 if (node->type == EXP_VAR) {
1248 addlocal(J, F, node->a, 1);
1250 emitstring(J, F, OP_DEFVAR, node->a->string);
1253 if (node->a) cvardecs(J, F, node->a);
1254 if (node->b) cvardecs(J, F, node->b);
1255 if (node->c) cvardecs(J, F, node->c);
1256 if (node->d) cvardecs(J, F, node->d);
1259 static void cfundecs(JF, js_Ast *list)
1262 js_Ast *stm = list->a;
1263 if (stm->type == AST_FUNDEC) {
1264 emitfunction(J, F, newfun(J, stm->a, stm->b, stm->c, 0));
1265 emitstring(J, F, OP_INITVAR, stm->a->string);
1271 static void cfunbody(JF, js_Ast *name, js_Ast *params, js_Ast *body)
1280 analyze(J, F, body);
1282 cparams(J, F, params);
1285 emit(J, F, OP_CURRENT);
1286 if (F->lightweight) {
1287 addlocal(J, F, name, 0);
1288 emit(J, F, OP_INITLOCAL);
1289 emitraw(J, F, findlocal(J, F, name->string));
1291 emitstring(J, F, OP_INITVAR, name->string);
1296 cvardecs(J, F, body);
1297 cfundecs(J, F, body);
1301 emit(J, F, OP_UNDEF);
1302 cstmlist(J, F, body);
1303 emit(J, F, OP_RETURN);
1305 cstmlist(J, F, body);
1306 emit(J, F, OP_UNDEF);
1307 emit(J, F, OP_RETURN);
1311 js_Function *jsC_compilefunction(js_State *J, js_Ast *prog)
1313 return newfun(J, prog->a, prog->b, prog->c, 0);
1316 js_Function *jsC_compile(js_State *J, js_Ast *prog)
1318 return newfun(J, NULL, NULL, prog, 1);