00001 #include "parse.h"
00002 #include "code.h"
00003
00004 #define MAX_FUNARGS 32
00005
00006
00007 #define LEFT(tok) ((tok)->children)
00008 #define RIGHT(tok) ((tok)->lastChild)
00009 #define BINARY(tok) (LEFT(tok) && RIGHT(tok) && LEFT(tok) != RIGHT(tok))
00010
00011
00012 static void genExpr(struct Parser* p, struct Token* t);
00013 static void genExprList(struct Parser* p, struct Token* t);
00014 static naRef newLambda(struct Parser* p, struct Token* t);
00015
00016 static void emit(struct Parser* p, int val)
00017 {
00018 if(p->cg->codesz >= p->cg->codeAlloced) {
00019 int i, sz = p->cg->codeAlloced * 2;
00020 unsigned short* buf = naParseAlloc(p, sz*sizeof(unsigned short));
00021 for(i=0; i<p->cg->codeAlloced; i++) buf[i] = p->cg->byteCode[i];
00022 p->cg->byteCode = buf;
00023 p->cg->codeAlloced = sz;
00024 }
00025 p->cg->byteCode[p->cg->codesz++] = (unsigned short)val;
00026 }
00027
00028 static void emitImmediate(struct Parser* p, int val, int arg)
00029 {
00030 emit(p, val);
00031 emit(p, arg);
00032 }
00033
00034 static void genBinOp(int op, struct Parser* p, struct Token* t)
00035 {
00036 if(!LEFT(t) || !RIGHT(t))
00037 naParseError(p, "empty subexpression", t->line);
00038 genExpr(p, LEFT(t));
00039 genExpr(p, RIGHT(t));
00040 emit(p, op);
00041 }
00042
00043 static int newConstant(struct Parser* p, naRef c)
00044 {
00045 int i;
00046 naVec_append(p->cg->consts, c);
00047 i = naVec_size(p->cg->consts) - 1;
00048 if(i > 0xffff) naParseError(p, "too many constants in code block", 0);
00049 return i;
00050 }
00051
00052 static naRef getConstant(struct Parser* p, int idx)
00053 {
00054 return naVec_get(p->cg->consts, idx);
00055 }
00056
00057
00058 static int internConstant(struct Parser* p, naRef c)
00059 {
00060 int i, n = naVec_size(p->cg->consts);
00061 if(IS_CODE(c)) return newConstant(p, c);
00062 for(i=0; i<n; i++) {
00063 naRef b = naVec_get(p->cg->consts, i);
00064 if(IS_NUM(b) && IS_NUM(c) && b.num == c.num) return i;
00065 else if(IS_NIL(b) && IS_NIL(c)) return i;
00066 else if(naStrEqual(b, c)) return i;
00067 }
00068 return newConstant(p, c);
00069 }
00070
00071 naRef naInternSymbol(naRef sym)
00072 {
00073 naRef result;
00074 if(naHash_get(globals->symbols, sym, &result))
00075 return result;
00076 naHash_set(globals->symbols, sym, sym);
00077 return sym;
00078 }
00079
00080 static int findConstantIndex(struct Parser* p, struct Token* t)
00081 {
00082 naRef c, dummy;
00083 if(t->type == TOK_NIL) c = naNil();
00084 else if(t->str) {
00085 c = naStr_fromdata(naNewString(p->context), t->str, t->strlen);
00086 naHash_get(globals->symbols, c, &dummy);
00087 if(t->type == TOK_SYMBOL) c = naInternSymbol(c);
00088 } else if(t->type == TOK_FUNC) c = newLambda(p, t);
00089 else if(t->type == TOK_LITERAL) c = naNum(t->num);
00090 else naParseError(p, "invalid/non-constant constant", t->line);
00091 return internConstant(p, c);
00092 }
00093
00094 static int genScalarConstant(struct Parser* p, struct Token* t)
00095 {
00096
00097
00098
00099 if(t->str == 0 && t->num == 1) {
00100 emit(p, OP_PUSHONE);
00101 } else if(t->str == 0 && t->num == 0) {
00102 emit(p, OP_PUSHZERO);
00103 } else {
00104 int idx = findConstantIndex(p, t);
00105 emitImmediate(p, OP_PUSHCONST, idx);
00106 return idx;
00107 }
00108 return 0;
00109 }
00110
00111 static int genLValue(struct Parser* p, struct Token* t, int* cidx)
00112 {
00113 if(!t) naParseError(p, "bad lvalue", -1);
00114 if(t->type == TOK_LPAR && t->rule != PREC_SUFFIX) {
00115 return genLValue(p, LEFT(t), cidx);
00116 } else if(t->type == TOK_SYMBOL) {
00117 *cidx = genScalarConstant(p, t);
00118 return OP_SETSYM;
00119 } else if(t->type == TOK_DOT && RIGHT(t) && RIGHT(t)->type == TOK_SYMBOL) {
00120 genExpr(p, LEFT(t));
00121 *cidx = genScalarConstant(p, RIGHT(t));
00122 return OP_SETMEMBER;
00123 } else if(t->type == TOK_LBRA) {
00124 genExpr(p, LEFT(t));
00125 genExpr(p, RIGHT(t));
00126 return OP_INSERT;
00127 } else if(t->type == TOK_VAR && RIGHT(t) && RIGHT(t)->type == TOK_SYMBOL) {
00128 *cidx = genScalarConstant(p, RIGHT(t));
00129 return OP_SETLOCAL;
00130 } else {
00131 naParseError(p, "bad lvalue", t->line);
00132 return -1;
00133 }
00134 }
00135
00136 static void genEqOp(int op, struct Parser* p, struct Token* t)
00137 {
00138 int cidx, setop = genLValue(p, LEFT(t), &cidx);
00139 if(setop == OP_SETMEMBER) {
00140 emit(p, OP_DUP2);
00141 emit(p, OP_POP);
00142 emitImmediate(p, OP_MEMBER, cidx);
00143 } else if(setop == OP_INSERT) {
00144 emit(p, OP_DUP2);
00145 emit(p, OP_EXTRACT);
00146 } else
00147 emitImmediate(p, OP_LOCAL, cidx);
00148 genExpr(p, RIGHT(t));
00149 emit(p, op);
00150 emit(p, setop);
00151 }
00152
00153 static int defArg(struct Parser* p, struct Token* t)
00154 {
00155 if(t->type == TOK_LPAR) return defArg(p, RIGHT(t));
00156 if(t->type == TOK_MINUS && RIGHT(t) &&
00157 RIGHT(t)->type == TOK_LITERAL && !RIGHT(t)->str)
00158 {
00159
00160
00161
00162 RIGHT(t)->num *= -1;
00163 return defArg(p, RIGHT(t));
00164 }
00165 return findConstantIndex(p, t);
00166 }
00167
00168 static void genArgList(struct Parser* p, struct naCode* c, struct Token* t)
00169 {
00170 naRef sym;
00171 if(t->type == TOK_EMPTY) return;
00172 if(!IDENTICAL(c->restArgSym, globals->argRef))
00173 naParseError(p, "remainder must be last", t->line);
00174 if(t->type == TOK_ELLIPSIS) {
00175 if(LEFT(t)->type != TOK_SYMBOL)
00176 naParseError(p, "bad function argument expression", t->line);
00177 sym = naStr_fromdata(naNewString(p->context),
00178 LEFT(t)->str, LEFT(t)->strlen);
00179 c->restArgSym = naInternSymbol(sym);
00180 c->needArgVector = 1;
00181 } else if(t->type == TOK_ASSIGN) {
00182 if(LEFT(t)->type != TOK_SYMBOL)
00183 naParseError(p, "bad function argument expression", t->line);
00184 c->optArgSyms[c->nOptArgs] = findConstantIndex(p, LEFT(t));
00185 c->optArgVals[c->nOptArgs++] = defArg(p, RIGHT(t));
00186 } else if(t->type == TOK_SYMBOL) {
00187 if(c->nOptArgs)
00188 naParseError(p, "optional arguments must be last", t->line);
00189 if(c->nArgs >= MAX_FUNARGS)
00190 naParseError(p, "too many named function arguments", t->line);
00191 c->argSyms[c->nArgs++] = findConstantIndex(p, t);
00192 } else if(t->type == TOK_COMMA) {
00193 genArgList(p, c, LEFT(t));
00194 genArgList(p, c, RIGHT(t));
00195 } else
00196 naParseError(p, "bad function argument expression", t->line);
00197 }
00198
00199 static naRef newLambda(struct Parser* p, struct Token* t)
00200 {
00201 struct CodeGenerator* cgSave;
00202 naRef codeObj;
00203 struct Token* arglist;
00204 if(RIGHT(t)->type != TOK_LCURL)
00205 naParseError(p, "bad function definition", t->line);
00206
00207
00208 cgSave = p->cg;
00209 arglist = LEFT(t)->type == TOK_LPAR ? LEFT(LEFT(t)) : 0;
00210 codeObj = naCodeGen(p, LEFT(RIGHT(t)), arglist);
00211 p->cg = cgSave;
00212 return codeObj;
00213 }
00214
00215 static void genLambda(struct Parser* p, struct Token* t)
00216 {
00217 emitImmediate(p, OP_PUSHCONST, newConstant(p, newLambda(p, t)));
00218 }
00219
00220 static int genList(struct Parser* p, struct Token* t, int doAppend)
00221 {
00222 if(t->type == TOK_COMMA) {
00223 genExpr(p, LEFT(t));
00224 if(doAppend) emit(p, OP_VAPPEND);
00225 return 1 + genList(p, RIGHT(t), doAppend);
00226 } else if(t->type == TOK_EMPTY) {
00227 return 0;
00228 } else {
00229 genExpr(p, t);
00230 if(doAppend) emit(p, OP_VAPPEND);
00231 return 1;
00232 }
00233 }
00234
00235 static void genHashElem(struct Parser* p, struct Token* t)
00236 {
00237 if(t->type == TOK_EMPTY)
00238 return;
00239 if(t->type != TOK_COLON)
00240 naParseError(p, "bad hash/object initializer", t->line);
00241 if(LEFT(t)->type == TOK_SYMBOL) genScalarConstant(p, LEFT(t));
00242 else if(LEFT(t)->type == TOK_LITERAL) genExpr(p, LEFT(t));
00243 else naParseError(p, "bad hash/object initializer", t->line);
00244 genExpr(p, RIGHT(t));
00245 emit(p, OP_HAPPEND);
00246 }
00247
00248 static void genHash(struct Parser* p, struct Token* t)
00249 {
00250 if(t->type == TOK_COMMA) {
00251 genHashElem(p, LEFT(t));
00252 genHash(p, RIGHT(t));
00253 } else if(t->type != TOK_EMPTY) {
00254 genHashElem(p, t);
00255 }
00256 }
00257
00258 static void genFuncall(struct Parser* p, struct Token* t)
00259 {
00260 int op = OP_FCALL;
00261 int nargs = 0;
00262 if(LEFT(t)->type == TOK_DOT) {
00263 genExpr(p, LEFT(LEFT(t)));
00264 emit(p, OP_DUP);
00265 emitImmediate(p, OP_MEMBER, findConstantIndex(p, RIGHT(LEFT(t))));
00266 op = OP_MCALL;
00267 } else {
00268 genExpr(p, LEFT(t));
00269 }
00270 if(RIGHT(t)) nargs = genList(p, RIGHT(t), 0);
00271 emitImmediate(p, op, nargs);
00272 }
00273
00274 static void pushLoop(struct Parser* p, struct Token* label)
00275 {
00276 int i = p->cg->loopTop;
00277 p->cg->loops[i].breakIP = 0xffffff;
00278 p->cg->loops[i].contIP = 0xffffff;
00279 p->cg->loops[i].label = label;
00280 p->cg->loopTop++;
00281 emit(p, OP_MARK);
00282 }
00283
00284 static void popLoop(struct Parser* p)
00285 {
00286 p->cg->loopTop--;
00287 if(p->cg->loopTop < 0) naParseError(p, "BUG: loop stack underflow", -1);
00288 emit(p, OP_UNMARK);
00289 }
00290
00291
00292
00293 static int emitJump(struct Parser* p, int op)
00294 {
00295 int ip;
00296 emit(p, op);
00297 ip = p->cg->codesz;
00298 emit(p, 0xffff);
00299 return ip;
00300 }
00301
00302
00303 static void fixJumpTarget(struct Parser* p, int spot)
00304 {
00305 p->cg->byteCode[spot] = p->cg->codesz;
00306 }
00307
00308 static void genShortCircuit(struct Parser* p, struct Token* t)
00309 {
00310 int end;
00311 genExpr(p, LEFT(t));
00312 end = emitJump(p, t->type == TOK_AND ? OP_JIFNOT : OP_JIFTRUE);
00313 emit(p, OP_POP);
00314 genExpr(p, RIGHT(t));
00315 fixJumpTarget(p, end);
00316 }
00317
00318
00319 static void genIf(struct Parser* p, struct Token* tif, struct Token* telse)
00320 {
00321 int jumpNext, jumpEnd;
00322 genExpr(p, tif->children);
00323 jumpNext = emitJump(p, OP_JIFNOTPOP);
00324 genExprList(p, tif->children->next->children);
00325 jumpEnd = emitJump(p, OP_JMP);
00326 fixJumpTarget(p, jumpNext);
00327 if(telse) {
00328 if(telse->type == TOK_ELSIF) genIf(p, telse, telse->next);
00329 else genExprList(p, telse->children->children);
00330 } else {
00331 emit(p, OP_PUSHNIL);
00332 }
00333 fixJumpTarget(p, jumpEnd);
00334 }
00335
00336 static void genIfElse(struct Parser* p, struct Token* t)
00337 {
00338 genIf(p, t, t->children->next->next);
00339 }
00340
00341 static void genQuestion(struct Parser* p, struct Token* t)
00342 {
00343 int jumpNext, jumpEnd;
00344 if(!RIGHT(t) || RIGHT(t)->type != TOK_COLON)
00345 naParseError(p, "invalid ?: expression", t->line);
00346 genExpr(p, LEFT(t));
00347 jumpNext = emitJump(p, OP_JIFNOTPOP);
00348 genExpr(p, LEFT(RIGHT(t)));
00349 jumpEnd = emitJump(p, OP_JMP);
00350 fixJumpTarget(p, jumpNext);
00351 genExpr(p, RIGHT(RIGHT(t)));
00352 fixJumpTarget(p, jumpEnd);
00353 }
00354
00355 static int countSemis(struct Token* t)
00356 {
00357 if(!t || t->type != TOK_SEMI) return 0;
00358 return 1 + countSemis(RIGHT(t));
00359 }
00360
00361 static void genLoop(struct Parser* p, struct Token* body,
00362 struct Token* update, struct Token* label,
00363 int loopTop, int jumpEnd)
00364 {
00365 int cont, jumpOverContinue;
00366
00367 p->cg->loops[p->cg->loopTop-1].breakIP = jumpEnd-1;
00368
00369 jumpOverContinue = emitJump(p, OP_JMP);
00370 p->cg->loops[p->cg->loopTop-1].contIP = p->cg->codesz;
00371 cont = emitJump(p, OP_JMP);
00372 fixJumpTarget(p, jumpOverContinue);
00373
00374 genExprList(p, body);
00375 emit(p, OP_POP);
00376 fixJumpTarget(p, cont);
00377 if(update) { genExpr(p, update); emit(p, OP_POP); }
00378 emitImmediate(p, OP_JMPLOOP, loopTop);
00379 fixJumpTarget(p, jumpEnd);
00380 popLoop(p);
00381 emit(p, OP_PUSHNIL);
00382 }
00383
00384 static void genForWhile(struct Parser* p, struct Token* init,
00385 struct Token* test, struct Token* update,
00386 struct Token* body, struct Token* label)
00387 {
00388 int loopTop, jumpEnd;
00389 if(init) { genExpr(p, init); emit(p, OP_POP); }
00390 pushLoop(p, label);
00391 loopTop = p->cg->codesz;
00392 genExpr(p, test);
00393 jumpEnd = emitJump(p, OP_JIFNOTPOP);
00394 genLoop(p, body, update, label, loopTop, jumpEnd);
00395 }
00396
00397 static void genWhile(struct Parser* p, struct Token* t)
00398 {
00399 struct Token *test=LEFT(t)->children, *body, *label=0;
00400 int semis = countSemis(test);
00401 if(semis == 1) {
00402 label = LEFT(test);
00403 if(!label || label->type != TOK_SYMBOL)
00404 naParseError(p, "bad loop label", t->line);
00405 test = RIGHT(test);
00406 }
00407 else if(semis != 0)
00408 naParseError(p, "too many semicolons in while test", t->line);
00409 body = LEFT(RIGHT(t));
00410 genForWhile(p, 0, test, 0, body, label);
00411 }
00412
00413 static void genFor(struct Parser* p, struct Token* t)
00414 {
00415 struct Token *init, *test, *body, *update, *label=0;
00416 struct Token *h = LEFT(t)->children;
00417 int semis = countSemis(h);
00418 if(semis == 3) {
00419 if(!LEFT(h) || LEFT(h)->type != TOK_SYMBOL)
00420 naParseError(p, "bad loop label", h->line);
00421 label = LEFT(h);
00422 h=RIGHT(h);
00423 } else if(semis != 2) {
00424 naParseError(p, "wrong number of terms in for header", t->line);
00425 }
00426
00427
00428 init = LEFT(h);
00429 test = LEFT(RIGHT(h));
00430 update = RIGHT(RIGHT(h));
00431 body = RIGHT(t)->children;
00432 genForWhile(p, init, test, update, body, label);
00433 }
00434
00435 static void genForEach(struct Parser* p, struct Token* t)
00436 {
00437 int loopTop, jumpEnd, assignOp, dummy;
00438 struct Token *elem, *body, *vec, *label=0;
00439 struct Token *h = LEFT(LEFT(t));
00440 int semis = countSemis(h);
00441 if(semis == 2) {
00442 if(!LEFT(h) || LEFT(h)->type != TOK_SYMBOL)
00443 naParseError(p, "bad loop label", h->line);
00444 label = LEFT(h);
00445 h = RIGHT(h);
00446 } else if (semis != 1) {
00447 naParseError(p, "wrong number of terms in foreach header", t->line);
00448 }
00449 elem = LEFT(h);
00450 vec = RIGHT(h);
00451 body = RIGHT(t)->children;
00452
00453 genExpr(p, vec);
00454 emit(p, OP_PUSHZERO);
00455 pushLoop(p, label);
00456 loopTop = p->cg->codesz;
00457 emit(p, t->type == TOK_FOREACH ? OP_EACH : OP_INDEX);
00458 jumpEnd = emitJump(p, OP_JIFEND);
00459 assignOp = genLValue(p, elem, &dummy);
00460 emit(p, OP_XCHG);
00461 emit(p, assignOp);
00462 emit(p, OP_POP);
00463 genLoop(p, body, 0, label, loopTop, jumpEnd);
00464 emit(p, OP_POP);
00465 emit(p, OP_POP);
00466 }
00467
00468 static int tokMatch(struct Token* a, struct Token* b)
00469 {
00470 int i, l = a->strlen;
00471 if(!a || !b) return 0;
00472 if(l != b->strlen) return 0;
00473 for(i=0; i<l; i++) if(a->str[i] != b->str[i]) return 0;
00474 return 1;
00475 }
00476
00477 static void genBreakContinue(struct Parser* p, struct Token* t)
00478 {
00479 int levels = 1, loop = -1, bp, cp, i;
00480 if(RIGHT(t)) {
00481 if(RIGHT(t)->type != TOK_SYMBOL)
00482 naParseError(p, "bad break/continue label", t->line);
00483 for(i=0; i<p->cg->loopTop; i++)
00484 if(tokMatch(RIGHT(t), p->cg->loops[i].label))
00485 loop = i;
00486 if(loop == -1)
00487 naParseError(p, "no match for break/continue label", t->line);
00488 levels = p->cg->loopTop - loop;
00489 }
00490 bp = p->cg->loops[p->cg->loopTop - levels].breakIP;
00491 cp = p->cg->loops[p->cg->loopTop - levels].contIP;
00492 for(i=0; i<levels; i++)
00493 emit(p, (i<levels-1) ? OP_BREAK2 : OP_BREAK);
00494 if(t->type == TOK_BREAK)
00495 emit(p, OP_PUSHEND);
00496 emitImmediate(p, OP_JMP, t->type == TOK_BREAK ? bp : cp);
00497 }
00498
00499 static void newLineEntry(struct Parser* p, int line)
00500 {
00501 int i;
00502 if(p->cg->nextLineIp >= p->cg->nLineIps) {
00503 int nsz = p->cg->nLineIps*2 + 1;
00504 unsigned short* n = naParseAlloc(p, sizeof(unsigned short)*2*nsz);
00505 for(i=0; i<(p->cg->nextLineIp*2); i++)
00506 n[i] = p->cg->lineIps[i];
00507 p->cg->lineIps = n;
00508 p->cg->nLineIps = nsz;
00509 }
00510 p->cg->lineIps[p->cg->nextLineIp++] = (unsigned short) p->cg->codesz;
00511 p->cg->lineIps[p->cg->nextLineIp++] = (unsigned short) line;
00512 }
00513
00514 static void genExpr(struct Parser* p, struct Token* t)
00515 {
00516 int i, dummy;
00517 if(!t) naParseError(p, "parse error", -1);
00518 p->errLine = t->line;
00519 if(t->line != p->cg->lastLine)
00520 newLineEntry(p, t->line);
00521 p->cg->lastLine = t->line;
00522 switch(t->type) {
00523 case TOK_IF:
00524 genIfElse(p, t);
00525 break;
00526 case TOK_QUESTION:
00527 genQuestion(p, t);
00528 break;
00529 case TOK_WHILE:
00530 genWhile(p, t);
00531 break;
00532 case TOK_FOR:
00533 genFor(p, t);
00534 break;
00535 case TOK_FOREACH:
00536 case TOK_FORINDEX:
00537 genForEach(p, t);
00538 break;
00539 case TOK_BREAK: case TOK_CONTINUE:
00540 genBreakContinue(p, t);
00541 break;
00542 case TOK_TOP:
00543 genExprList(p, LEFT(t));
00544 break;
00545 case TOK_FUNC:
00546 genLambda(p, t);
00547 break;
00548 case TOK_LPAR:
00549 if(BINARY(t) || !RIGHT(t)) genFuncall(p, t);
00550 else genExpr(p, LEFT(t));
00551 break;
00552 case TOK_LBRA:
00553 if(BINARY(t)) {
00554 genBinOp(OP_EXTRACT, p, t);
00555 } else {
00556 emit(p, OP_NEWVEC);
00557 genList(p, LEFT(t), 1);
00558 }
00559 break;
00560 case TOK_LCURL:
00561 emit(p, OP_NEWHASH);
00562 genHash(p, LEFT(t));
00563 break;
00564 case TOK_ASSIGN:
00565 i = genLValue(p, LEFT(t), &dummy);
00566 genExpr(p, RIGHT(t));
00567 emit(p, i);
00568 break;
00569 case TOK_RETURN:
00570 if(RIGHT(t)) genExpr(p, RIGHT(t));
00571 else emit(p, OP_PUSHNIL);
00572 for(i=0; i<p->cg->loopTop; i++) emit(p, OP_UNMARK);
00573 emit(p, OP_RETURN);
00574 break;
00575 case TOK_NOT:
00576 genExpr(p, RIGHT(t));
00577 emit(p, OP_NOT);
00578 break;
00579 case TOK_SYMBOL:
00580 emitImmediate(p, OP_LOCAL, findConstantIndex(p, t));
00581 break;
00582 case TOK_LITERAL:
00583 genScalarConstant(p, t);
00584 break;
00585 case TOK_MINUS:
00586 if(BINARY(t)) {
00587 genBinOp(OP_MINUS, p, t);
00588 } else if(RIGHT(t) && RIGHT(t)->type == TOK_LITERAL && !RIGHT(t)->str) {
00589 RIGHT(t)->num *= -1;
00590 genScalarConstant(p, RIGHT(t));
00591 } else {
00592 genExpr(p, RIGHT(t));
00593 emit(p, OP_NEG);
00594 }
00595 break;
00596 case TOK_NEG:
00597 genExpr(p, RIGHT(t));
00598 emit(p, OP_NEG);
00599 break;
00600 case TOK_DOT:
00601 genExpr(p, LEFT(t));
00602 if(!RIGHT(t) || RIGHT(t)->type != TOK_SYMBOL)
00603 naParseError(p, "object field not symbol", RIGHT(t)->line);
00604 emitImmediate(p, OP_MEMBER, findConstantIndex(p, RIGHT(t)));
00605 break;
00606 case TOK_EMPTY: case TOK_NIL:
00607 emit(p, OP_PUSHNIL); break;
00608 case TOK_AND: case TOK_OR:
00609 genShortCircuit(p, t);
00610 break;
00611 case TOK_MUL: genBinOp(OP_MUL, p, t); break;
00612 case TOK_PLUS: genBinOp(OP_PLUS, p, t); break;
00613 case TOK_DIV: genBinOp(OP_DIV, p, t); break;
00614 case TOK_CAT: genBinOp(OP_CAT, p, t); break;
00615 case TOK_LT: genBinOp(OP_LT, p, t); break;
00616 case TOK_LTE: genBinOp(OP_LTE, p, t); break;
00617 case TOK_EQ: genBinOp(OP_EQ, p, t); break;
00618 case TOK_NEQ: genBinOp(OP_NEQ, p, t); break;
00619 case TOK_GT: genBinOp(OP_GT, p, t); break;
00620 case TOK_GTE: genBinOp(OP_GTE, p, t); break;
00621 case TOK_PLUSEQ: genEqOp(OP_PLUS, p, t); break;
00622 case TOK_MINUSEQ: genEqOp(OP_MINUS, p, t); break;
00623 case TOK_MULEQ: genEqOp(OP_MUL, p, t); break;
00624 case TOK_DIVEQ: genEqOp(OP_DIV, p, t); break;
00625 case TOK_CATEQ: genEqOp(OP_CAT, p, t); break;
00626 default:
00627 naParseError(p, "parse error", t->line);
00628 };
00629 }
00630
00631 static void genExprList(struct Parser* p, struct Token* t)
00632 {
00633 if(t && t->type == TOK_SEMI) {
00634 genExpr(p, LEFT(t));
00635 if(RIGHT(t) && RIGHT(t)->type != TOK_EMPTY) {
00636 emit(p, OP_POP);
00637 genExprList(p, RIGHT(t));
00638 }
00639 } else {
00640 genExpr(p, t);
00641 }
00642 }
00643
00644 naRef naCodeGen(struct Parser* p, struct Token* block, struct Token* arglist)
00645 {
00646 int i;
00647 naRef codeObj;
00648 struct naCode* code;
00649 struct CodeGenerator cg;
00650
00651 cg.lastLine = 0;
00652 cg.codeAlloced = 1024;
00653 cg.byteCode = naParseAlloc(p, cg.codeAlloced *sizeof(unsigned short));
00654 cg.codesz = 0;
00655 cg.consts = naNewVector(p->context);
00656 cg.loopTop = 0;
00657 cg.lineIps = 0;
00658 cg.nLineIps = 0;
00659 cg.nextLineIp = 0;
00660 p->cg = &cg;
00661
00662 genExprList(p, block);
00663 emit(p, OP_RETURN);
00664
00665
00666 codeObj = naNewCode(p->context);
00667 code = PTR(codeObj).code;
00668
00669
00670 code->restArgSym = globals->argRef;
00671 code->nArgs = code->nOptArgs = 0;
00672 code->argSyms = code->optArgSyms = code->optArgVals = 0;
00673 code->needArgVector = 1;
00674 if(arglist) {
00675 code->argSyms = naParseAlloc(p, sizeof(int) * MAX_FUNARGS);
00676 code->optArgSyms = naParseAlloc(p, sizeof(int) * MAX_FUNARGS);
00677 code->optArgVals = naParseAlloc(p, sizeof(int) * MAX_FUNARGS);
00678 code->needArgVector = 0;
00679 genArgList(p, code, arglist);
00680 if(code->nArgs) {
00681 int i, *nsyms;
00682 nsyms = naAlloc(sizeof(int) * code->nArgs);
00683 for(i=0; i<code->nArgs; i++) nsyms[i] = code->argSyms[i];
00684 code->argSyms = nsyms;
00685 } else code->argSyms = 0;
00686 if(code->nOptArgs) {
00687 int i, *nsyms, *nvals;
00688 nsyms = naAlloc(sizeof(int) * code->nOptArgs);
00689 nvals = naAlloc(sizeof(int) * code->nOptArgs);
00690 for(i=0; i<code->nOptArgs; i++) nsyms[i] = code->optArgSyms[i];
00691 for(i=0; i<code->nOptArgs; i++) nvals[i] = code->optArgVals[i];
00692 code->optArgSyms = nsyms;
00693 code->optArgVals = nvals;
00694 } else code->optArgSyms = code->optArgVals = 0;
00695 }
00696
00697 code->codesz = cg.codesz;
00698 code->byteCode = naAlloc(cg.codesz * sizeof(unsigned short));
00699 for(i=0; i < cg.codesz; i++)
00700 code->byteCode[i] = cg.byteCode[i];
00701 code->nConstants = naVec_size(cg.consts);
00702 code->constants = naAlloc(code->nConstants * sizeof(naRef));
00703 code->srcFile = p->srcFile;
00704 for(i=0; i<code->nConstants; i++)
00705 code->constants[i] = getConstant(p, i);
00706 code->nLines = p->cg->nextLineIp;
00707 code->lineIps = naAlloc(sizeof(unsigned short)*p->cg->nLineIps*2);
00708 for(i=0; i<p->cg->nLineIps*2; i++)
00709 code->lineIps[i] = p->cg->lineIps[i];
00710 return codeObj;
00711 }