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