zig-pug 0.2.0

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