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, 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_REF(b) && IS_REF(c) && b.ref.ptr.obj->type != c.ref.ptr.obj->type)
68 return newConstant(p, c);
71 static void genScalarConstant(struct Parser* p, struct Token* t)
74 ? naStr_fromdata(naNewString(p->context), t->str, t->strlen)
76 int idx = internConstant(p, c);
77 emitImmediate(p, OP_PUSHCONST, idx);
80 static int genLValue(struct Parser* p, struct Token* t)
82 if(t->type == TOK_LPAR) {
83 return genLValue(p, LEFT(t)); // Handle stuff like "(a) = 1"
84 } else if(t->type == TOK_SYMBOL) {
85 genScalarConstant(p, t);
87 } else if(t->type == TOK_DOT && RIGHT(t) && RIGHT(t)->type == TOK_SYMBOL) {
89 genScalarConstant(p, RIGHT(t));
91 } else if(t->type == TOK_LBRA) {
96 naParseError(p, "bad lvalue", t->line);
101 static void genLambda(struct Parser* p, struct Token* t)
104 struct CodeGenerator* cgSave;
106 if(LEFT(t)->type != TOK_LCURL)
107 naParseError(p, "bad function definition", t->line);
109 // Save off the generator state while we do the new one
111 codeObj = naCodeGen(p, LEFT(LEFT(t)));
114 idx = newConstant(p, codeObj);
115 emitImmediate(p, OP_PUSHCONST, idx);
118 static void genList(struct Parser* p, struct Token* t)
120 if(t->type == TOK_COMMA) {
123 genList(p, RIGHT(t));
124 } else if(t->type == TOK_EMPTY) {
132 static void genHashElem(struct Parser* p, struct Token* t)
134 if(t->type == TOK_EMPTY)
136 if(t->type != TOK_COLON)
137 naParseError(p, "bad hash/object initializer", t->line);
138 if(LEFT(t)->type == TOK_SYMBOL) genScalarConstant(p, LEFT(t));
139 else if(LEFT(t)->type == TOK_LITERAL) genExpr(p, LEFT(t));
140 else naParseError(p, "bad hash/object initializer", t->line);
141 genExpr(p, RIGHT(t));
145 static void genHash(struct Parser* p, struct Token* t)
147 if(t->type == TOK_COMMA) {
148 genHashElem(p, LEFT(t));
149 genHash(p, RIGHT(t));
150 } else if(t->type != TOK_EMPTY) {
155 static void genFuncall(struct Parser* p, struct Token* t)
158 if(LEFT(t)->type == TOK_DOT) {
159 genExpr(p, LEFT(LEFT(t)));
161 genScalarConstant(p, RIGHT(LEFT(t)));
168 if(RIGHT(t)) genList(p, RIGHT(t));
172 static void pushLoop(struct Parser* p, struct Token* label)
174 int i = p->cg->loopTop;
175 p->cg->loops[i].breakIP = 0xffffff;
176 p->cg->loops[i].contIP = 0xffffff;
177 p->cg->loops[i].label = label;
182 static void popLoop(struct Parser* p)
185 if(p->cg->loopTop < 0) naParseError(p, "BUG: loop stack underflow", -1);
189 // Emit a jump operation, and return the location of the address in
190 // the bytecode for future fixup in fixJumpTarget
191 static int emitJump(struct Parser* p, int op)
196 emit(p, 0xff); // dummy address
201 // Points a previous jump instruction at the current "end-of-bytecode"
202 static void fixJumpTarget(struct Parser* p, int spot)
204 p->cg->byteCode[spot] = p->cg->nBytes >> 8;
205 p->cg->byteCode[spot+1] = p->cg->nBytes & 0xff;
208 static void genShortCircuit(struct Parser* p, struct Token* t)
210 int jumpNext, jumpEnd, isAnd = (t->type == TOK_AND);
212 if(isAnd) emit(p, OP_NOT);
213 jumpNext = emitJump(p, OP_JIFNOT);
214 emit(p, isAnd ? OP_PUSHNIL : OP_PUSHONE);
215 jumpEnd = emitJump(p, OP_JMP);
216 fixJumpTarget(p, jumpNext);
217 genExpr(p, RIGHT(t));
218 fixJumpTarget(p, jumpEnd);
222 static void genIf(struct Parser* p, struct Token* tif, struct Token* telse)
224 int jumpNext, jumpEnd;
225 genExpr(p, tif->children); // the test
226 jumpNext = emitJump(p, OP_JIFNOT);
227 genExprList(p, tif->children->next->children); // the body
228 jumpEnd = emitJump(p, OP_JMP);
229 fixJumpTarget(p, jumpNext);
231 if(telse->type == TOK_ELSIF) genIf(p, telse, telse->next);
232 else genExprList(p, telse->children->children);
236 fixJumpTarget(p, jumpEnd);
239 static void genIfElse(struct Parser* p, struct Token* t)
241 genIf(p, t, t->children->next->next);
244 static int countSemis(struct Token* t)
246 if(!t || t->type != TOK_SEMI) return 0;
247 return 1 + countSemis(RIGHT(t));
250 static void genLoop(struct Parser* p, struct Token* body,
251 struct Token* update, struct Token* label,
252 int loopTop, int jumpEnd)
254 int cont, jumpOverContinue;
256 p->cg->loops[p->cg->loopTop-1].breakIP = jumpEnd-1;
258 jumpOverContinue = emitJump(p, OP_JMP);
259 p->cg->loops[p->cg->loopTop-1].contIP = p->cg->nBytes;
260 cont = emitJump(p, OP_JMP);
261 fixJumpTarget(p, jumpOverContinue);
263 genExprList(p, body);
265 fixJumpTarget(p, cont);
266 if(update) { genExpr(p, update); emit(p, OP_POP); }
267 emitImmediate(p, OP_JMP, loopTop);
268 fixJumpTarget(p, jumpEnd);
270 emit(p, OP_PUSHNIL); // Leave something on the stack
273 static void genForWhile(struct Parser* p, struct Token* init,
274 struct Token* test, struct Token* update,
275 struct Token* body, struct Token* label)
277 int loopTop, jumpEnd;
278 if(init) { genExpr(p, init); emit(p, OP_POP); }
280 loopTop = p->cg->nBytes;
282 jumpEnd = emitJump(p, OP_JIFNOT);
283 genLoop(p, body, update, label, loopTop, jumpEnd);
286 static void genWhile(struct Parser* p, struct Token* t)
288 struct Token *test=LEFT(t)->children, *body, *label=0;
289 int semis = countSemis(test);
292 if(!label || label->type != TOK_SYMBOL)
293 naParseError(p, "bad loop label", t->line);
297 naParseError(p, "too many semicolons in while test", t->line);
298 body = LEFT(RIGHT(t));
299 genForWhile(p, 0, test, 0, body, label);
302 static void genFor(struct Parser* p, struct Token* t)
304 struct Token *init, *test, *body, *update, *label=0;
305 struct Token *h = LEFT(t)->children;
306 int semis = countSemis(h);
308 if(!LEFT(h) || LEFT(h)->type != TOK_SYMBOL)
309 naParseError(p, "bad loop label", h->line);
312 } else if(semis != 2) {
313 naParseError(p, "wrong number of terms in for header", t->line);
316 // Parse tree hell :)
318 test = LEFT(RIGHT(h));
319 update = RIGHT(RIGHT(h));
320 body = RIGHT(t)->children;
321 genForWhile(p, init, test, update, body, label);
324 static void genForEach(struct Parser* p, struct Token* t)
326 int loopTop, jumpEnd, assignOp;
327 struct Token *elem, *body, *vec, *label=0;
328 struct Token *h = LEFT(LEFT(t));
329 int semis = countSemis(h);
331 if(!LEFT(h) || LEFT(h)->type != TOK_SYMBOL)
332 naParseError(p, "bad loop label", h->line);
335 } else if (semis != 1) {
336 naParseError(p, "wrong number of terms in foreach header", t->line);
340 body = RIGHT(t)->children;
344 emit(p, OP_PUSHZERO);
345 loopTop = p->cg->nBytes;
347 jumpEnd = emitJump(p, OP_JIFNIL);
348 assignOp = genLValue(p, elem);
352 genLoop(p, body, 0, label, loopTop, jumpEnd);
355 static int tokMatch(struct Token* a, struct Token* b)
357 int i, l = a->strlen;
358 if(!a || !b) return 0;
359 if(l != b->strlen) return 0;
360 for(i=0; i<l; i++) if(a->str[i] != b->str[i]) return 0;
364 static void genBreakContinue(struct Parser* p, struct Token* t)
366 int levels = 1, loop = -1, bp, cp, i;
368 if(RIGHT(t)->type != TOK_SYMBOL)
369 naParseError(p, "bad break/continue label", t->line);
370 for(i=0; i<p->cg->loopTop; i++)
371 if(tokMatch(RIGHT(t), p->cg->loops[i].label))
374 naParseError(p, "no match for break/continue label", t->line);
375 levels = p->cg->loopTop - loop;
377 bp = p->cg->loops[p->cg->loopTop - levels].breakIP;
378 cp = p->cg->loops[p->cg->loopTop - levels].contIP;
379 for(i=0; i<levels; i++)
381 if(t->type == TOK_BREAK)
382 emit(p, OP_PUSHNIL); // breakIP is always a JIFNOT/JIFNIL!
383 emitImmediate(p, OP_JMP, t->type == TOK_BREAK ? bp : cp);
386 static void genExpr(struct Parser* p, struct Token* t)
390 naParseError(p, "BUG: null subexpression", -1);
391 if(t->line != p->cg->lastLine)
392 emitImmediate(p, OP_LINE, t->line);
393 p->cg->lastLine = t->line;
407 case TOK_BREAK: case TOK_CONTINUE:
408 genBreakContinue(p, t);
411 genExprList(p, LEFT(t));
417 if(BINARY(t) || !RIGHT(t)) genFuncall(p, t); // function invocation
418 else genExpr(p, LEFT(t)); // simple parenthesis
422 genBinOp(OP_EXTRACT, p, t); // a[i]
433 i = genLValue(p, LEFT(t));
434 genExpr(p, RIGHT(t));
435 emit(p, i); // use the op appropriate to the lvalue
438 if(RIGHT(t)) genExpr(p, RIGHT(t));
439 else emit(p, OP_PUSHNIL);
443 genExpr(p, RIGHT(t));
447 genScalarConstant(p, t);
451 genScalarConstant(p, t);
455 genBinOp(OP_MINUS, p, t); // binary subtraction
456 } else if(RIGHT(t)->type == TOK_LITERAL && !RIGHT(t)->str) {
457 RIGHT(t)->num *= -1; // Pre-negate constants
458 genScalarConstant(p, RIGHT(t));
460 genExpr(p, RIGHT(t)); // unary negation
465 genExpr(p, RIGHT(t)); // unary negation (see also TOK_MINUS!)
470 if(RIGHT(t)->type != TOK_SYMBOL)
471 naParseError(p, "object field not symbol", RIGHT(t)->line);
472 genScalarConstant(p, RIGHT(t));
475 case TOK_EMPTY: case TOK_NIL:
476 emit(p, OP_PUSHNIL); break; // *NOT* a noop!
477 case TOK_AND: case TOK_OR:
478 genShortCircuit(p, t);
480 case TOK_MUL: genBinOp(OP_MUL, p, t); break;
481 case TOK_PLUS: genBinOp(OP_PLUS, p, t); break;
482 case TOK_DIV: genBinOp(OP_DIV, p, t); break;
483 case TOK_CAT: genBinOp(OP_CAT, p, t); break;
484 case TOK_LT: genBinOp(OP_LT, p, t); break;
485 case TOK_LTE: genBinOp(OP_LTE, p, t); break;
486 case TOK_EQ: genBinOp(OP_EQ, p, t); break;
487 case TOK_NEQ: genBinOp(OP_NEQ, p, t); break;
488 case TOK_GT: genBinOp(OP_GT, p, t); break;
489 case TOK_GTE: genBinOp(OP_GTE, p, t); break;
491 naParseError(p, "parse error", t->line);
495 static void genExprList(struct Parser* p, struct Token* t)
497 if(t->type == TOK_SEMI) {
499 if(RIGHT(t) && RIGHT(t)->type != TOK_EMPTY) {
501 genExprList(p, RIGHT(t));
508 naRef naCodeGen(struct Parser* p, struct Token* t)
513 struct CodeGenerator cg;
516 cg.codeAlloced = 1024; // Start fairly big, this is a cheap allocation
517 cg.byteCode = naParseAlloc(p, cg.codeAlloced);
519 cg.consts = naNewVector(p->context);
525 // Now make a code object
526 codeObj = naNewCode(p->context);
527 code = codeObj.ref.ptr.code;
528 code->nBytes = cg.nBytes;
529 code->byteCode = naAlloc(cg.nBytes);
530 for(i=0; i < cg.nBytes; i++)
531 code->byteCode[i] = cg.byteCode[i];
532 code->nConstants = naVec_size(cg.consts);
533 code->constants = naAlloc(code->nConstants * sizeof(naRef));
534 code->srcFile = p->srcFile;
535 for(i=0; i<code->nConstants; i++)
536 code->constants[i] = getConstant(p, i);