7 // These are more sensical predicate names in most contexts in this file
8 #define LEFT(tok) ((tok)->children)
9 #define RIGHT(tok) ((tok)->lastChild)
10 #define UNARY(tok) (LEFT(tok) && LEFT(tok) == RIGHT(tok))
11 #define BINARY(tok) (LEFT(tok) && RIGHT(tok) && LEFT(tok)->next == RIGHT(tok))
13 // Forward references for recursion
14 static void genExpr(struct Parser* p, struct Token* t);
15 static void genExprList(struct Parser* p, struct Token* t);
16 static naRef newLambda(struct Parser* p, struct Token* t);
18 static void emit(struct Parser* p, int val)
20 if(p->cg->codesz >= p->cg->codeAlloced) {
21 int i, sz = p->cg->codeAlloced * 2;
22 unsigned short* buf = naParseAlloc(p, sz*sizeof(unsigned short));
23 for(i=0; i<p->cg->codeAlloced; i++) buf[i] = p->cg->byteCode[i];
24 p->cg->byteCode = buf;
25 p->cg->codeAlloced = sz;
27 p->cg->byteCode[p->cg->codesz++] = (unsigned short)val;
30 static void emitImmediate(struct Parser* p, int val, int arg)
36 static void genBinOp(int op, struct Parser* p, struct Token* t)
38 if(!LEFT(t) || !RIGHT(t))
39 naParseError(p, "empty subexpression", t->line);
45 static int newConstant(struct Parser* p, naRef c)
48 naVec_append(p->cg->consts, c);
49 i = naVec_size(p->cg->consts) - 1;
50 if(i > 0xffff) naParseError(p, "too many constants in code block", 0);
54 // Interns a scalar (!) constant and returns its index
55 static int internConstant(struct Parser* p, naRef c)
57 int i, n = naVec_size(p->cg->consts);
58 if(IS_CODE(c)) return newConstant(p, c);
60 naRef b = naVec_get(p->cg->consts, i);
61 if(IS_NUM(b) && IS_NUM(c) && b.num == c.num) return i;
62 else if(IS_NIL(b) && IS_NIL(c)) return i;
63 else if(naStrEqual(b, c)) return i;
65 return newConstant(p, c);
68 /* FIXME: this API is fundamentally a resource leak, because symbols
69 * can't be deregistered. The "proper" way to do this would be to
70 * keep a reference count for each symbol, and decrement it when a
71 * code object referencing it is deleted. */
72 naRef naInternSymbol(naRef sym)
75 if(naHash_get(globals->symbols, sym, &result))
77 naHash_set(globals->symbols, sym, sym);
81 static int findConstantIndex(struct Parser* p, struct Token* t)
84 if(t->type == TOK_NIL) c = naNil();
86 c = naStr_fromdata(naNewString(p->context), t->str, t->strlen);
87 naHash_get(globals->symbols, c, &dummy); // noop, make c immutable
88 if(t->type == TOK_SYMBOL) c = naInternSymbol(c);
89 } else if(t->type == TOK_FUNC) c = newLambda(p, t);
90 else if(t->type == TOK_LITERAL) c = naNum(t->num);
91 else naParseError(p, "invalid/non-constant constant", t->line);
92 return internConstant(p, c);
95 static int genScalarConstant(struct Parser* p, struct Token* t)
98 if(t->str == 0 && t->num == 1) { emit(p, OP_PUSHONE); return 0; }
99 if(t->str == 0 && t->num == 0) { emit(p, OP_PUSHZERO); return 0; }
100 emitImmediate(p, OP_PUSHCONST, idx = findConstantIndex(p, t));
104 static int genLValue(struct Parser* p, struct Token* t, int* cidx)
106 if(!t) naParseError(p, "bad lvalue", -1);
107 if(t->type == TOK_LPAR && t->rule != PREC_SUFFIX) {
108 return genLValue(p, LEFT(t), cidx); // Handle stuff like "(a) = 1"
109 } else if(t->type == TOK_SYMBOL) {
110 *cidx = genScalarConstant(p, t);
112 } else if(t->type == TOK_DOT && RIGHT(t) && RIGHT(t)->type == TOK_SYMBOL) {
114 *cidx = genScalarConstant(p, RIGHT(t));
116 } else if(t->type == TOK_LBRA) {
118 genExpr(p, RIGHT(t));
120 } else if(t->type == TOK_VAR && RIGHT(t) && RIGHT(t)->type == TOK_SYMBOL) {
121 *cidx = genScalarConstant(p, RIGHT(t));
124 naParseError(p, "bad lvalue", t->line);
129 static void genEqOp(int op, struct Parser* p, struct Token* t)
131 int cidx, n = 2, setop = genLValue(p, LEFT(t), &cidx);
132 if(setop == OP_SETMEMBER) {
135 emitImmediate(p, OP_MEMBER, cidx);
136 } else if(setop == OP_INSERT) {
140 emitImmediate(p, OP_LOCAL, cidx);
143 genExpr(p, RIGHT(t));
145 emit(p, n == 1 ? OP_XCHG : OP_XCHG2);
149 static int defArg(struct Parser* p, struct Token* t)
151 if(t->type == TOK_LPAR) {
152 // http://code.google.com/p/flightgear-bugs/issues/detail?id=737
153 // TOK_LPAR can mean multi-value assignment or function call,
154 // disambigaute by checking the rule of the token
155 if (t->rule == PREC_SUFFIX)
156 naParseError(p, "default arguments cannot be function calls", t->line);
157 return defArg(p, RIGHT(t));
160 if(t->type == TOK_MINUS && RIGHT(t) &&
161 RIGHT(t)->type == TOK_LITERAL && !RIGHT(t)->str)
163 /* default arguments are constants, but "-1" parses as two
164 * tokens, so we have to subset the expression generator for that
167 return defArg(p, RIGHT(t));
169 return findConstantIndex(p, t);
172 static void genArgList(struct Parser* p, struct naCode* c, struct Token* t)
175 if(t->type == TOK_EMPTY) return;
176 if(!IDENTICAL(p->cg->restArgSym, globals->argRef))
177 naParseError(p, "remainder must be last", t->line);
178 if(t->type == TOK_ELLIPSIS) {
179 if(LEFT(t)->type != TOK_SYMBOL)
180 naParseError(p, "bad function argument expression", t->line);
181 sym = naStr_fromdata(naNewString(p->context),
182 LEFT(t)->str, LEFT(t)->strlen);
183 p->cg->restArgSym = naInternSymbol(sym);
184 c->needArgVector = 1;
185 } else if(t->type == TOK_ASSIGN) {
186 if(LEFT(t)->type != TOK_SYMBOL)
187 naParseError(p, "bad function argument expression", t->line);
188 p->cg->optArgSyms[c->nOptArgs] = findConstantIndex(p, LEFT(t));
189 p->cg->optArgVals[c->nOptArgs++] = defArg(p, RIGHT(t));
190 } else if(t->type == TOK_SYMBOL) {
192 naParseError(p, "optional arguments must be last", t->line);
193 if(c->nArgs >= MAX_FUNARGS)
194 naParseError(p, "too many named function arguments", t->line);
195 p->cg->argSyms[c->nArgs++] = findConstantIndex(p, t);
196 } else if(t->type == TOK_COMMA) {
197 if(!LEFT(t) || !RIGHT(t))
198 naParseError(p, "empty function argument", t->line);
199 genArgList(p, c, LEFT(t));
200 genArgList(p, c, RIGHT(t));
202 naParseError(p, "bad function argument expression", t->line);
205 static naRef newLambda(struct Parser* p, struct Token* t)
207 struct CodeGenerator* cgSave;
209 struct Token* arglist;
210 if(RIGHT(t)->type != TOK_LCURL)
211 naParseError(p, "bad function definition", t->line);
213 // Save off the generator state while we do the new one
215 arglist = LEFT(t)->type == TOK_LPAR ? LEFT(LEFT(t)) : 0;
216 codeObj = naCodeGen(p, LEFT(RIGHT(t)), arglist);
221 static void genLambda(struct Parser* p, struct Token* t)
223 emitImmediate(p, OP_PUSHCONST, newConstant(p, newLambda(p, t)));
226 static int genList(struct Parser* p, struct Token* t, int doAppend)
228 if(!t || t->type == TOK_EMPTY) {
230 } else if(t->type == TOK_COMMA) {
232 if(doAppend) emit(p, OP_VAPPEND);
233 return 1 + genList(p, RIGHT(t), doAppend);
236 if(doAppend) emit(p, OP_VAPPEND);
241 static void genHashElem(struct Parser* p, struct Token* t)
243 if(!t || t->type == TOK_EMPTY)
245 if(t->type != TOK_COLON || !LEFT(t))
246 naParseError(p, "bad hash/object initializer", t->line);
247 if(LEFT(t)->type == TOK_SYMBOL) genScalarConstant(p, LEFT(t));
248 else if(LEFT(t)->type == TOK_LITERAL) genExpr(p, LEFT(t));
249 else naParseError(p, "bad hash/object initializer", t->line);
250 genExpr(p, RIGHT(t));
254 static void genHash(struct Parser* p, struct Token* t)
256 if(t && t->type == TOK_COMMA) {
257 genHashElem(p, LEFT(t));
258 genHash(p, RIGHT(t));
259 } else if(t && t->type != TOK_EMPTY) {
264 static int isHashcall(struct Parser* p, struct Token* t)
267 int sep = LEFT(t) && t->type == TOK_COMMA ? t->children->type : t->type;
268 return sep == TOK_COLON;
273 static void genFuncall(struct Parser* p, struct Token* t)
276 if(LEFT(t)->type == TOK_DOT) {
278 genExpr(p, LEFT(LEFT(t)));
280 emitImmediate(p, OP_MEMBER, findConstantIndex(p, RIGHT(LEFT(t))));
284 if(isHashcall(p, RIGHT(t))) {
286 genHash(p, RIGHT(t));
287 emit(p, method ? OP_MCALLH : OP_FCALLH);
289 int nargs = genList(p, RIGHT(t), 0);
290 emitImmediate(p, method ? OP_MCALL : OP_FCALL, nargs);
294 static int startLoop(struct Parser* p, struct Token* label)
296 int i = p->cg->loopTop;
297 p->cg->loops[i].breakIP = 0xffffff;
298 p->cg->loops[i].contIP = 0xffffff;
299 p->cg->loops[i].label = label;
302 return p->cg->codesz;
305 // Emit a jump operation, and return the location of the address in
306 // the bytecode for future fixup in fixJumpTarget
307 static int emitJump(struct Parser* p, int op)
312 emit(p, 0xffff); // dummy address
316 // Points a previous jump instruction at the current "end-of-bytecode"
317 static void fixJumpTarget(struct Parser* p, int spot)
319 p->cg->byteCode[spot] = p->cg->codesz;
322 static void genShortCircuit(struct Parser* p, struct Token* t)
326 end = emitJump(p, t->type == TOK_AND ? OP_JIFNOT : OP_JIFTRUE);
328 genExpr(p, RIGHT(t));
329 fixJumpTarget(p, end);
333 static void genIf(struct Parser* p, struct Token* tif, struct Token* telse)
335 int jumpNext, jumpEnd;
336 genExpr(p, tif->children); // the test
337 jumpNext = emitJump(p, OP_JIFNOTPOP);
338 genExprList(p, tif->children->next->children); // the body
339 jumpEnd = emitJump(p, OP_JMP);
340 fixJumpTarget(p, jumpNext);
342 if(telse->type == TOK_ELSIF) genIf(p, telse, telse->next);
343 else genExprList(p, telse->children->children);
347 fixJumpTarget(p, jumpEnd);
350 static void genIfElse(struct Parser* p, struct Token* t)
352 genIf(p, t, t->children->next->next);
355 static void genQuestion(struct Parser* p, struct Token* t)
357 int jumpNext, jumpEnd;
358 if(!RIGHT(t) || RIGHT(t)->type != TOK_COLON)
359 naParseError(p, "invalid ?: expression", t->line);
360 genExpr(p, LEFT(t)); // the test
361 jumpNext = emitJump(p, OP_JIFNOTPOP);
362 genExpr(p, LEFT(RIGHT(t))); // the "if true" expr
363 jumpEnd = emitJump(p, OP_JMP);
364 fixJumpTarget(p, jumpNext);
365 genExpr(p, RIGHT(RIGHT(t))); // the "else" expr
366 fixJumpTarget(p, jumpEnd);
369 static int countList(struct Token* t, int type)
372 for(n = 1; t && t->type == type; t = RIGHT(t)) n++;
376 static void genLoop(struct Parser* p, struct Token* body,
377 struct Token* update, struct Token* label,
378 int loopTop, int jumpEnd)
380 int cont, jumpOverContinue;
382 p->cg->loops[p->cg->loopTop-1].breakIP = jumpEnd-1;
384 jumpOverContinue = emitJump(p, OP_JMP);
385 p->cg->loops[p->cg->loopTop-1].contIP = p->cg->codesz;
386 cont = emitJump(p, OP_JMP);
387 fixJumpTarget(p, jumpOverContinue);
389 genExprList(p, body);
391 fixJumpTarget(p, cont);
392 if(update) { genExpr(p, update); emit(p, OP_POP); }
393 emitImmediate(p, OP_JMPLOOP, loopTop);
394 fixJumpTarget(p, jumpEnd);
397 emit(p, OP_PUSHNIL); // Leave something on the stack
400 static void genForWhile(struct Parser* p, struct Token* init,
401 struct Token* test, struct Token* update,
402 struct Token* body, struct Token* label)
404 int loopTop, jumpEnd;
405 if(init) { genExpr(p, init); emit(p, OP_POP); }
406 loopTop = startLoop(p, label);
408 jumpEnd = emitJump(p, OP_JIFNOTPOP);
409 genLoop(p, body, update, label, loopTop, jumpEnd);
412 static void genWhile(struct Parser* p, struct Token* t)
414 struct Token *test=LEFT(t)->children, *body, *label=0;
415 int len = countList(test, TOK_SEMI);
418 if(!label || label->type != TOK_SYMBOL)
419 naParseError(p, "bad loop label", t->line);
422 naParseError(p, "too many semicolons in while test", t->line);
423 body = LEFT(RIGHT(t));
424 genForWhile(p, 0, test, 0, body, label);
427 static void genFor(struct Parser* p, struct Token* t)
429 struct Token *init, *test, *body, *update, *label=0;
430 struct Token *h = LEFT(t)->children;
431 int len = countList(h, TOK_SEMI);
433 if(!LEFT(h) || LEFT(h)->type != TOK_SYMBOL)
434 naParseError(p, "bad loop label", h->line);
438 naParseError(p, "wrong number of terms in for header", t->line);
440 test = LEFT(RIGHT(h));
441 update = RIGHT(RIGHT(h));
442 body = RIGHT(t)->children;
443 genForWhile(p, init, test, update, body, label);
446 static void genForEach(struct Parser* p, struct Token* t)
448 int loopTop, jumpEnd, assignOp, dummy;
449 struct Token *elem, *body, *vec, *label=0;
450 struct Token *h = LEFT(LEFT(t));
451 int len = countList(h, TOK_SEMI);
453 if(!LEFT(h) || LEFT(h)->type != TOK_SYMBOL)
454 naParseError(p, "bad loop label", h->line);
457 } else if (len != 2) {
458 naParseError(p, "wrong number of terms in foreach header", t->line);
462 body = RIGHT(t)->children;
465 emit(p, OP_PUSHZERO);
466 loopTop = startLoop(p, label);
467 emit(p, t->type == TOK_FOREACH ? OP_EACH : OP_INDEX);
468 jumpEnd = emitJump(p, OP_JIFEND);
469 assignOp = genLValue(p, elem, &dummy);
472 genLoop(p, body, 0, label, loopTop, jumpEnd);
473 emit(p, OP_POP); // Pull off the vector and index
477 static int tokMatch(struct Token* a, struct Token* b)
479 int i, l = a->strlen;
480 if(!a || !b) return 0;
481 if(l != b->strlen) return 0;
482 for(i=0; i<l; i++) if(a->str[i] != b->str[i]) return 0;
486 static void genBreakContinue(struct Parser* p, struct Token* t)
488 int levels = 1, loop = -1, bp, cp, i;
489 // http://code.google.com/p/flightgear-bugs/issues/detail?id=587
490 // Make sure we are inside of a loop
491 if(p->cg->loopTop <= 0)
492 naParseError(p, "break/continue outside of a valid loop", t->line);
495 if(RIGHT(t)->type != TOK_SYMBOL)
496 naParseError(p, "bad break/continue label", t->line);
497 for(i=0; i<p->cg->loopTop; i++)
498 if(tokMatch(RIGHT(t), p->cg->loops[i].label))
501 naParseError(p, "no match for break/continue label", t->line);
502 levels = p->cg->loopTop - loop;
504 bp = p->cg->loops[p->cg->loopTop - levels].breakIP;
505 cp = p->cg->loops[p->cg->loopTop - levels].contIP;
506 for(i=0; i<levels; i++)
507 emit(p, (i<levels-1) ? OP_BREAK2 : OP_BREAK);
508 if(t->type == TOK_BREAK)
509 emit(p, OP_PUSHEND); // breakIP is always a JIFNOTPOP/JIFEND!
510 emitImmediate(p, OP_JMP, t->type == TOK_BREAK ? bp : cp);
513 static void newLineEntry(struct Parser* p, int line)
516 if(p->cg->nextLineIp >= p->cg->nLineIps) {
517 int nsz = p->cg->nLineIps*2 + 1;
518 unsigned short* n = naParseAlloc(p, sizeof(unsigned short)*2*nsz);
519 for(i=0; i<(p->cg->nextLineIp*2); i++)
520 n[i] = p->cg->lineIps[i];
522 p->cg->nLineIps = nsz;
524 p->cg->lineIps[p->cg->nextLineIp++] = (unsigned short) p->cg->codesz;
525 p->cg->lineIps[p->cg->nextLineIp++] = (unsigned short) line;
528 static int parListLen(struct Token* t)
530 if(t->type != TOK_LPAR || !LEFT(t) || LEFT(t)->type != TOK_COMMA) return 0;
531 return countList(LEFT(t), TOK_COMMA);
534 static void genCommaList(struct Parser* p, struct Token* t)
536 if(t->type != TOK_COMMA) { genExpr(p, t); return; }
537 genCommaList(p, RIGHT(t));
541 static void genMultiLV(struct Parser* p, struct Token* t, int var)
543 if(!var) { emit(p, genLValue(p, t, &var)); return; }
544 if(t->type != TOK_SYMBOL) naParseError(p, "bad lvalue", t->line);
545 genScalarConstant(p, t);
546 emit(p, OP_SETLOCAL);
549 static void genAssign(struct Parser* p, struct Token* t)
551 struct Token *lv = LEFT(t), *rv = RIGHT(t);
552 int len, dummy, var=0;
554 naParseError(p, "bad assignment, missing variable", t->line);
556 if(parListLen(lv) || (lv->type == TOK_VAR && parListLen(RIGHT(lv)))) {
557 if(lv->type == TOK_VAR) { lv = RIGHT(lv); var = 1; }
558 len = parListLen(lv);
559 // http://code.google.com/p/flightgear-bugs/issues/detail?id=585
560 // TOK_LPAR can mean multi-value assignment or function call,
561 // disambigaute by checking the rule of the token
562 if(rv->type == TOK_LPAR && rv->rule != PREC_SUFFIX) {
563 if(len != parListLen(rv))
564 naParseError(p, "bad assignment count", rv->line);
565 genCommaList(p, LEFT(rv));
568 emitImmediate(p, OP_UNPACK, len);
570 for(t = LEFT(lv); t && t->type == TOK_COMMA; t = RIGHT(t)) {
571 genMultiLV(p, LEFT(t), var);
574 genMultiLV(p, t, var);
577 emit(p, genLValue(p, lv, &dummy));
581 static void genSlice(struct Parser* p, struct Token* t)
583 if(!t || t->type==TOK_EMPTY) naParseError(p, "empty slice expression", -1);
584 if(t->type == TOK_COLON) {
585 if(LEFT(t)) genExpr(p, LEFT(t)); else emit(p, OP_PUSHNIL);
586 if(RIGHT(t)) genExpr(p, RIGHT(t)); else emit(p, OP_PUSHNIL);
594 static void genExtract(struct Parser* p, struct Token* t)
597 if(countList(RIGHT(t), TOK_COMMA) == 1 && RIGHT(t)->type != TOK_COLON) {
598 genExpr(p, RIGHT(t));
602 for(t = RIGHT(t); t->type == TOK_COMMA; t = RIGHT(t))
603 genSlice(p, LEFT(t));
610 static void genExpr(struct Parser* p, struct Token* t)
613 if(!t) naParseError(p, "parse error", -1); // throw line -1...
614 p->errLine = t->line; // ...to use this one instead
615 if(t->line != p->cg->lastLine)
616 newLineEntry(p, t->line);
617 p->cg->lastLine = t->line;
619 case TOK_TOP: genExprList(p, LEFT(t)); break;
620 case TOK_IF: genIfElse(p, t); break;
621 case TOK_QUESTION: genQuestion(p, t); break;
622 case TOK_WHILE: genWhile(p, t); break;
623 case TOK_FOR: genFor(p, t); break;
624 case TOK_FUNC: genLambda(p, t); break;
625 case TOK_ASSIGN: genAssign(p, t); break;
626 case TOK_LITERAL: genScalarConstant(p, t); break;
627 case TOK_FOREACH: case TOK_FORINDEX:
630 case TOK_BREAK: case TOK_CONTINUE:
631 genBreakContinue(p, t);
634 if(BINARY(t) || !RIGHT(t)) genFuncall(p, t);
635 else genExpr(p, LEFT(t));
640 genList(p, LEFT(t), 1);
645 // forbid usage as 'vec[]'
646 naParseError(p, "missing index or slice expression(s)", t->line);
654 if(RIGHT(t)) genExpr(p, RIGHT(t));
655 else emit(p, OP_PUSHNIL);
656 for(i=0; i<p->cg->loopTop; i++) emit(p, OP_UNMARK);
660 genExpr(p, RIGHT(t));
664 emitImmediate(p, OP_LOCAL, findConstantIndex(p, t));
668 genBinOp(OP_MINUS, p, t); // binary subtraction
669 } else if(RIGHT(t) && RIGHT(t)->type == TOK_LITERAL && !RIGHT(t)->str) {
670 RIGHT(t)->num *= -1; // Pre-negate constants
671 genScalarConstant(p, RIGHT(t));
673 genExpr(p, RIGHT(t)); // unary negation
678 genExpr(p, RIGHT(t)); // unary negation (see also TOK_MINUS!)
683 if(!RIGHT(t) || RIGHT(t)->type != TOK_SYMBOL)
684 naParseError(p, "object field not symbol", RIGHT(t)->line);
685 emitImmediate(p, OP_MEMBER, findConstantIndex(p, RIGHT(t)));
687 case TOK_EMPTY: case TOK_NIL:
690 case TOK_AND: case TOK_OR:
691 genShortCircuit(p, t);
693 case TOK_MUL: genBinOp(OP_MUL, p, t); break;
694 case TOK_PLUS: genBinOp(OP_PLUS, p, t); break;
695 case TOK_DIV: genBinOp(OP_DIV, p, t); break;
696 case TOK_CAT: genBinOp(OP_CAT, p, t); break;
697 case TOK_LT: genBinOp(OP_LT, p, t); break;
698 case TOK_LTE: genBinOp(OP_LTE, p, t); break;
699 case TOK_EQ: genBinOp(OP_EQ, p, t); break;
700 case TOK_NEQ: genBinOp(OP_NEQ, p, t); break;
701 case TOK_GT: genBinOp(OP_GT, p, t); break;
702 case TOK_GTE: genBinOp(OP_GTE, p, t); break;
703 case TOK_PLUSEQ: genEqOp(OP_PLUS, p, t); break;
704 case TOK_MINUSEQ: genEqOp(OP_MINUS, p, t); break;
705 case TOK_MULEQ: genEqOp(OP_MUL, p, t); break;
706 case TOK_DIVEQ: genEqOp(OP_DIV, p, t); break;
707 case TOK_CATEQ: genEqOp(OP_CAT, p, t); break;
709 naParseError(p, "parse error", t->line);
713 static void genExprList(struct Parser* p, struct Token* t)
715 if(t && t->type == TOK_SEMI) {
717 if(RIGHT(t) && RIGHT(t)->type != TOK_EMPTY) {
719 genExprList(p, RIGHT(t));
726 naRef naCodeGen(struct Parser* p, struct Token* block, struct Token* arglist)
731 struct CodeGenerator cg;
734 cg.codeAlloced = 1024; // Start fairly big, this is a cheap allocation
735 cg.byteCode = naParseAlloc(p, cg.codeAlloced *sizeof(unsigned short));
737 cg.consts = naNewVector(p->context);
744 genExprList(p, block);
747 // Now make a code object
748 codeObj = naNewCode(p->context);
749 code = PTR(codeObj).code;
751 // Parse the argument list, if any
752 p->cg->restArgSym = globals->argRef;
753 code->nArgs = code->nOptArgs = 0;
754 p->cg->argSyms = p->cg->optArgSyms = p->cg->optArgVals = 0;
755 code->needArgVector = 1;
757 p->cg->argSyms = naParseAlloc(p, sizeof(int) * MAX_FUNARGS);
758 p->cg->optArgSyms = naParseAlloc(p, sizeof(int) * MAX_FUNARGS);
759 p->cg->optArgVals = naParseAlloc(p, sizeof(int) * MAX_FUNARGS);
760 code->needArgVector = 0;
761 genArgList(p, code, arglist);
764 code->restArgSym = internConstant(p, p->cg->restArgSym);
766 /* Set the size fields and allocate the combined array buffer.
767 * Note cute trick with null pointer to get the array size. */
768 code->nConstants = naVec_size(cg.consts);
769 code->codesz = cg.codesz;
770 code->nLines = cg.nextLineIp;
771 code->srcFile = p->srcFile;
773 code->constants = naAlloc((int)(size_t)(LINEIPS(code)+code->nLines));
774 for(i=0; i<code->nConstants; i++)
775 code->constants[i] = naVec_get(p->cg->consts, i);
777 for(i=0; i<code->nArgs; i++) ARGSYMS(code)[i] = cg.argSyms[i];
778 for(i=0; i<code->nOptArgs; i++) OPTARGSYMS(code)[i] = cg.optArgSyms[i];
779 for(i=0; i<code->nOptArgs; i++) OPTARGVALS(code)[i] = cg.optArgVals[i];
780 for(i=0; i<code->codesz; i++) BYTECODE(code)[i] = cg.byteCode[i];
781 for(i=0; i<code->nLines; i++) LINEIPS(code)[i] = cg.lineIps[i];