4 // These are more sensical predicate names in most contexts in this file
5 #define LEFT(tok) ((tok)->children)
6 #define RIGHT(tok) ((tok)->lastChild)
7 #define BINARY(tok) (LEFT(tok) && RIGHT(tok) && LEFT(tok) != RIGHT(tok))
9 // Forward references for recursion
10 static void genExpr(struct Parser* p, struct Token* t);
11 static void genExprList(struct Parser* p, struct Token* t);
13 static void emit(struct Parser* p, int byte)
15 if(p->cg->nBytes >= p->cg->codeAlloced) {
16 int i, sz = p->cg->codeAlloced * 2;
17 unsigned char* buf = naParseAlloc(p, sz);
18 for(i=0; i<p->cg->codeAlloced; i++) buf[i] = p->cg->byteCode[i];
19 p->cg->byteCode = buf;
20 p->cg->codeAlloced = sz;
22 p->cg->byteCode[p->cg->nBytes++] = (unsigned char)byte;
25 static void emitImmediate(struct Parser* p, int byte, int arg)
32 static void genBinOp(int op, struct Parser* p, struct Token* t)
34 if(!LEFT(t) || !RIGHT(t))
35 naParseError(p, "empty subexpression", t->line);
41 static int newConstant(struct Parser* p, naRef c)
44 naVec_append(p->cg->consts, c);
45 i = naVec_size(p->cg->consts) - 1;
46 if(i > 0xffff) naParseError(p, "too many constants in code block", 0);
50 static naRef getConstant(struct Parser* p, int idx)
52 return naVec_get(p->cg->consts, idx);
55 // Interns a scalar (!) constant and returns its index
56 static int internConstant(struct Parser* p, naRef c)
58 int i, j, n = naVec_size(p->cg->consts);
60 naRef b = naVec_get(p->cg->consts, i);
61 if(IS_NUM(b) && IS_NUM(c) && b.num == c.num)
63 if(IS_STR(b) && IS_STR(c)) {
64 int len = naStr_len(c);
65 char* cs = naStr_data(c);
66 char* bs = naStr_data(b);
67 if(naStr_len(b) != len)
73 if(IS_REF(b) && IS_REF(c))
74 if(b.ref.ptr.obj->type == c.ref.ptr.obj->type)
78 return newConstant(p, c);
81 static void genScalarConstant(struct Parser* p, struct Token* t)
84 ? naStr_fromdata(naNewString(p->context), t->str, t->strlen)
86 int idx = internConstant(p, c);
87 emitImmediate(p, OP_PUSHCONST, idx);
90 static int genLValue(struct Parser* p, struct Token* t)
92 if(t->type == TOK_LPAR) {
93 return genLValue(p, LEFT(t)); // Handle stuff like "(a) = 1"
94 } else if(t->type == TOK_SYMBOL) {
95 genScalarConstant(p, t);
97 } else if(t->type == TOK_DOT && RIGHT(t) && RIGHT(t)->type == TOK_SYMBOL) {
99 genScalarConstant(p, RIGHT(t));
101 } else if(t->type == TOK_LBRA) {
103 genExpr(p, RIGHT(t));
106 naParseError(p, "bad lvalue", t->line);
111 static void genLambda(struct Parser* p, struct Token* t)
114 struct CodeGenerator* cgSave;
116 if(LEFT(t)->type != TOK_LCURL)
117 naParseError(p, "bad function definition", t->line);
119 // Save off the generator state while we do the new one
121 codeObj = naCodeGen(p, LEFT(LEFT(t)));
124 idx = newConstant(p, codeObj);
125 emitImmediate(p, OP_PUSHCONST, idx);
128 static void genList(struct Parser* p, struct Token* t)
130 if(t->type == TOK_COMMA) {
133 genList(p, RIGHT(t));
134 } else if(t->type == TOK_EMPTY) {
142 static void genHashElem(struct Parser* p, struct Token* t)
144 if(t->type == TOK_EMPTY)
146 if(t->type != TOK_COLON)
147 naParseError(p, "bad hash/object initializer", t->line);
148 if(LEFT(t)->type == TOK_SYMBOL) genScalarConstant(p, LEFT(t));
149 else if(LEFT(t)->type == TOK_LITERAL) genExpr(p, LEFT(t));
150 else naParseError(p, "bad hash/object initializer", t->line);
151 genExpr(p, RIGHT(t));
155 static void genHash(struct Parser* p, struct Token* t)
157 if(t->type == TOK_COMMA) {
158 genHashElem(p, LEFT(t));
159 genHash(p, RIGHT(t));
160 } else if(t->type != TOK_EMPTY) {
165 static void genFuncall(struct Parser* p, struct Token* t)
168 if(LEFT(t)->type == TOK_DOT) {
169 genExpr(p, LEFT(LEFT(t)));
171 genScalarConstant(p, RIGHT(LEFT(t)));
178 if(RIGHT(t)) genList(p, RIGHT(t));
182 static void pushLoop(struct Parser* p, struct Token* label)
184 int i = p->cg->loopTop;
185 p->cg->loops[i].breakIP = 0xffffff;
186 p->cg->loops[i].contIP = 0xffffff;
187 p->cg->loops[i].label = label;
192 static void popLoop(struct Parser* p)
195 if(p->cg->loopTop < 0) naParseError(p, "BUG: loop stack underflow", -1);
199 // Emit a jump operation, and return the location of the address in
200 // the bytecode for future fixup in fixJumpTarget
201 static int emitJump(struct Parser* p, int op)
206 emit(p, 0xff); // dummy address
211 // Points a previous jump instruction at the current "end-of-bytecode"
212 static void fixJumpTarget(struct Parser* p, int spot)
214 p->cg->byteCode[spot] = p->cg->nBytes >> 8;
215 p->cg->byteCode[spot+1] = p->cg->nBytes & 0xff;
218 static void genShortCircuit(struct Parser* p, struct Token* t)
220 int jumpNext, jumpEnd, isAnd = (t->type == TOK_AND);
222 if(isAnd) emit(p, OP_NOT);
223 jumpNext = emitJump(p, OP_JIFNOT);
224 emit(p, isAnd ? OP_PUSHNIL : OP_PUSHONE);
225 jumpEnd = emitJump(p, OP_JMP);
226 fixJumpTarget(p, jumpNext);
227 genExpr(p, RIGHT(t));
228 fixJumpTarget(p, jumpEnd);
232 static void genIf(struct Parser* p, struct Token* tif, struct Token* telse)
234 int jumpNext, jumpEnd;
235 genExpr(p, tif->children); // the test
236 jumpNext = emitJump(p, OP_JIFNOT);
237 genExprList(p, tif->children->next->children); // the body
238 jumpEnd = emitJump(p, OP_JMP);
239 fixJumpTarget(p, jumpNext);
241 if(telse->type == TOK_ELSIF) genIf(p, telse, telse->next);
242 else genExprList(p, telse->children->children);
246 fixJumpTarget(p, jumpEnd);
249 static void genIfElse(struct Parser* p, struct Token* t)
251 genIf(p, t, t->children->next->next);
254 static int countSemis(struct Token* t)
256 if(!t || t->type != TOK_SEMI) return 0;
257 return 1 + countSemis(RIGHT(t));
260 static void genLoop(struct Parser* p, struct Token* body,
261 struct Token* update, struct Token* label,
262 int loopTop, int jumpEnd)
264 int cont, jumpOverContinue;
266 p->cg->loops[p->cg->loopTop-1].breakIP = jumpEnd-1;
268 jumpOverContinue = emitJump(p, OP_JMP);
269 p->cg->loops[p->cg->loopTop-1].contIP = p->cg->nBytes;
270 cont = emitJump(p, OP_JMP);
271 fixJumpTarget(p, jumpOverContinue);
273 genExprList(p, body);
275 fixJumpTarget(p, cont);
276 if(update) { genExpr(p, update); emit(p, OP_POP); }
277 emitImmediate(p, OP_JMP, loopTop);
278 fixJumpTarget(p, jumpEnd);
280 emit(p, OP_PUSHNIL); // Leave something on the stack
283 static void genForWhile(struct Parser* p, struct Token* init,
284 struct Token* test, struct Token* update,
285 struct Token* body, struct Token* label)
287 int loopTop, jumpEnd;
288 if(init) { genExpr(p, init); emit(p, OP_POP); }
290 loopTop = p->cg->nBytes;
292 jumpEnd = emitJump(p, OP_JIFNOT);
293 genLoop(p, body, update, label, loopTop, jumpEnd);
296 static void genWhile(struct Parser* p, struct Token* t)
298 struct Token *test=LEFT(t)->children, *body, *label=0;
299 int semis = countSemis(test);
302 if(!label || label->type != TOK_SYMBOL)
303 naParseError(p, "bad loop label", t->line);
307 naParseError(p, "too many semicolons in while test", t->line);
308 body = LEFT(RIGHT(t));
309 genForWhile(p, 0, test, 0, body, label);
312 static void genFor(struct Parser* p, struct Token* t)
314 struct Token *init, *test, *body, *update, *label=0;
315 struct Token *h = LEFT(t)->children;
316 int semis = countSemis(h);
318 if(!LEFT(h) || LEFT(h)->type != TOK_SYMBOL)
319 naParseError(p, "bad loop label", h->line);
322 } else if(semis != 2) {
323 naParseError(p, "wrong number of terms in for header", t->line);
326 // Parse tree hell :)
328 test = LEFT(RIGHT(h));
329 update = RIGHT(RIGHT(h));
330 body = RIGHT(t)->children;
331 genForWhile(p, init, test, update, body, label);
334 static void genForEach(struct Parser* p, struct Token* t)
336 int loopTop, jumpEnd, assignOp;
337 struct Token *elem, *body, *vec, *label=0;
338 struct Token *h = LEFT(LEFT(t));
339 int semis = countSemis(h);
341 if(!LEFT(h) || LEFT(h)->type != TOK_SYMBOL)
342 naParseError(p, "bad loop label", h->line);
345 } else if (semis != 1) {
346 naParseError(p, "wrong number of terms in foreach header", t->line);
350 body = RIGHT(t)->children;
354 emit(p, OP_PUSHZERO);
355 loopTop = p->cg->nBytes;
357 jumpEnd = emitJump(p, OP_JIFNIL);
358 assignOp = genLValue(p, elem);
362 genLoop(p, body, 0, label, loopTop, jumpEnd);
365 static int tokMatch(struct Token* a, struct Token* b)
367 int i, l = a->strlen;
368 if(!a || !b) return 0;
369 if(l != b->strlen) return 0;
370 for(i=0; i<l; i++) if(a->str[i] != b->str[i]) return 0;
374 static void genBreakContinue(struct Parser* p, struct Token* t)
376 int levels = 1, loop = -1, bp, cp, i;
378 if(RIGHT(t)->type != TOK_SYMBOL)
379 naParseError(p, "bad break/continue label", t->line);
380 for(i=0; i<p->cg->loopTop; i++)
381 if(tokMatch(RIGHT(t), p->cg->loops[i].label))
384 naParseError(p, "no match for break/continue label", t->line);
385 levels = p->cg->loopTop - loop;
387 bp = p->cg->loops[p->cg->loopTop - levels].breakIP;
388 cp = p->cg->loops[p->cg->loopTop - levels].contIP;
389 for(i=0; i<levels; i++)
391 if(t->type == TOK_BREAK)
392 emit(p, OP_PUSHNIL); // breakIP is always a JIFNOT/JIFNIL!
393 emitImmediate(p, OP_JMP, t->type == TOK_BREAK ? bp : cp);
396 static void genExpr(struct Parser* p, struct Token* t)
400 naParseError(p, "BUG: null subexpression", -1);
401 if(t->line != p->cg->lastLine)
402 emitImmediate(p, OP_LINE, t->line);
403 p->cg->lastLine = t->line;
417 case TOK_BREAK: case TOK_CONTINUE:
418 genBreakContinue(p, t);
421 genExprList(p, LEFT(t));
427 if(BINARY(t) || !RIGHT(t)) genFuncall(p, t); // function invocation
428 else genExpr(p, LEFT(t)); // simple parenthesis
432 genBinOp(OP_EXTRACT, p, t); // a[i]
443 i = genLValue(p, LEFT(t));
444 genExpr(p, RIGHT(t));
445 emit(p, i); // use the op appropriate to the lvalue
448 if(RIGHT(t)) genExpr(p, RIGHT(t));
449 else emit(p, OP_PUSHNIL);
453 genExpr(p, RIGHT(t));
457 genScalarConstant(p, t);
461 genScalarConstant(p, t);
465 genBinOp(OP_MINUS, p, t); // binary subtraction
466 } else if(RIGHT(t)->type == TOK_LITERAL && !RIGHT(t)->str) {
467 RIGHT(t)->num *= -1; // Pre-negate constants
468 genScalarConstant(p, RIGHT(t));
470 genExpr(p, RIGHT(t)); // unary negation
475 genExpr(p, RIGHT(t)); // unary negation (see also TOK_MINUS!)
480 if(RIGHT(t)->type != TOK_SYMBOL)
481 naParseError(p, "object field not symbol", RIGHT(t)->line);
482 genScalarConstant(p, RIGHT(t));
485 case TOK_EMPTY: case TOK_NIL:
486 emit(p, OP_PUSHNIL); break; // *NOT* a noop!
487 case TOK_AND: case TOK_OR:
488 genShortCircuit(p, t);
490 case TOK_MUL: genBinOp(OP_MUL, p, t); break;
491 case TOK_PLUS: genBinOp(OP_PLUS, p, t); break;
492 case TOK_DIV: genBinOp(OP_DIV, p, t); break;
493 case TOK_CAT: genBinOp(OP_CAT, p, t); break;
494 case TOK_LT: genBinOp(OP_LT, p, t); break;
495 case TOK_LTE: genBinOp(OP_LTE, p, t); break;
496 case TOK_EQ: genBinOp(OP_EQ, p, t); break;
497 case TOK_NEQ: genBinOp(OP_NEQ, p, t); break;
498 case TOK_GT: genBinOp(OP_GT, p, t); break;
499 case TOK_GTE: genBinOp(OP_GTE, p, t); break;
501 naParseError(p, "parse error", t->line);
505 static void genExprList(struct Parser* p, struct Token* t)
507 if(t->type == TOK_SEMI) {
509 if(RIGHT(t) && RIGHT(t)->type != TOK_EMPTY) {
511 genExprList(p, RIGHT(t));
518 naRef naCodeGen(struct Parser* p, struct Token* t)
523 struct CodeGenerator cg;
526 cg.codeAlloced = 1024; // Start fairly big, this is a cheap allocation
527 cg.byteCode = naParseAlloc(p, cg.codeAlloced);
529 cg.consts = naNewVector(p->context);
535 // Now make a code object
536 codeObj = naNewCode(p->context);
537 code = codeObj.ref.ptr.code;
538 code->nBytes = cg.nBytes;
539 code->byteCode = naAlloc(cg.nBytes);
540 for(i=0; i < cg.nBytes; i++)
541 code->byteCode[i] = cg.byteCode[i];
542 code->nConstants = naVec_size(cg.consts);
543 code->constants = naAlloc(code->nConstants * sizeof(naRef));
544 code->srcFile = p->srcFile;
545 for(i=0; i<code->nConstants; i++)
546 code->constants[i] = getConstant(p, i);