X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fnasal%2Fcodegen.c;h=15276e8c96ec4f59c68278c49eb1a45749371e76;hb=04c1e95f087b9f9885db1cf8fd61a488c253d742;hp=757f703d8fd40a1e66838ff93d761f1faaacc2c6;hpb=65056bfa72c5fc391c89a829bcd7bb2759284ce5;p=simgear.git diff --git a/simgear/nasal/codegen.c b/simgear/nasal/codegen.c index 757f703d..15276e8c 100644 --- a/simgear/nasal/codegen.c +++ b/simgear/nasal/codegen.c @@ -79,10 +79,11 @@ naRef naInternSymbol(naRef sym) static int findConstantIndex(struct Parser* p, struct Token* t) { - naRef c; + naRef c, dummy; if(t->type == TOK_NIL) c = naNil(); else if(t->str) { c = naStr_fromdata(naNewString(p->context), t->str, t->strlen); + naHash_get(globals->symbols, c, &dummy); // noop, make c immutable if(t->type == TOK_SYMBOL) c = naInternSymbol(c); } else if(t->type == TOK_FUNC) c = newLambda(p, t); else if(t->type == TOK_LITERAL) c = naNum(t->num); @@ -90,41 +91,6 @@ static int findConstantIndex(struct Parser* p, struct Token* t) return internConstant(p, c); } -static int lastExprInBlock(struct Token* t) -{ - if(!t->parent) return 1; - if(t->parent->type == TOK_TOP || t->parent->type == TOK_LCURL) return 1; - if(t->parent->type == TOK_SEMI) - if(!t->next || t->next->type == TOK_EMPTY) - return 1; - return 0; -} - -// Returns true if the node is in "tail context" -- either a child of -// a return, the last child of a func block, or else the -// last child of an if/elsif/if that is itself in tail context. -static int tailContext(struct Token* t) -{ - if(t->parent && t->parent->type == TOK_RETURN) - return 1; - else if(!lastExprInBlock(t)) - return 0; - - // Walk up the tree. It is ok to see semicolons, else's, elsifs - // and curlies. If we reach the top or a func, then we are in - // tail context. If we hit an if, then we are in tail context - // only if the "if" node is. - while((t = t->parent) != 0) - switch(t->type) { - case TOK_SEMI: case TOK_LCURL: break; - case TOK_ELSE: case TOK_ELSIF: break; - case TOK_TOP: case TOK_FUNC: return 1; - case TOK_IF: return tailContext(t); - default: return 0; - } - return 0; -} - static int genScalarConstant(struct Parser* p, struct Token* t) { // These opcodes are for special-case use in other constructs, but @@ -144,7 +110,8 @@ static int genScalarConstant(struct Parser* p, struct Token* t) static int genLValue(struct Parser* p, struct Token* t, int* cidx) { - if(t->type == TOK_LPAR) { + if(!t) naParseError(p, "bad lvalue", -1); + if(t->type == TOK_LPAR && t->rule != PREC_SUFFIX) { return genLValue(p, LEFT(t), cidx); // Handle stuff like "(a) = 1" } else if(t->type == TOK_SYMBOL) { *cidx = genScalarConstant(p, t); @@ -186,6 +153,15 @@ static void genEqOp(int op, struct Parser* p, struct Token* t) static int defArg(struct Parser* p, struct Token* t) { if(t->type == TOK_LPAR) return defArg(p, RIGHT(t)); + if(t->type == TOK_MINUS && RIGHT(t) && + RIGHT(t)->type == TOK_LITERAL && !RIGHT(t)->str) + { + /* default arguments are constants, but "-1" parses as two + * tokens, so we have to subset the expression generator for that + * case */ + RIGHT(t)->num *= -1; + return defArg(p, RIGHT(t)); + } return findConstantIndex(p, t); } @@ -292,8 +268,6 @@ static void genFuncall(struct Parser* p, struct Token* t) genExpr(p, LEFT(t)); } if(RIGHT(t)) nargs = genList(p, RIGHT(t), 0); - if(tailContext(t)) - op = op == OP_FCALL ? OP_FTAIL : OP_MTAIL; emitImmediate(p, op, nargs); } @@ -333,15 +307,12 @@ static void fixJumpTarget(struct Parser* p, int spot) static void genShortCircuit(struct Parser* p, struct Token* t) { - int jumpNext, jumpEnd, isAnd = (t->type == TOK_AND); + int end; genExpr(p, LEFT(t)); - if(isAnd) emit(p, OP_NOT); - jumpNext = emitJump(p, OP_JIFNOT); - emit(p, isAnd ? OP_PUSHNIL : OP_PUSHONE); - jumpEnd = emitJump(p, OP_JMP); - fixJumpTarget(p, jumpNext); + end = emitJump(p, t->type == TOK_AND ? OP_JIFNOT : OP_JIFTRUE); + emit(p, OP_POP); genExpr(p, RIGHT(t)); - fixJumpTarget(p, jumpEnd); + fixJumpTarget(p, end); } @@ -349,7 +320,7 @@ static void genIf(struct Parser* p, struct Token* tif, struct Token* telse) { int jumpNext, jumpEnd; genExpr(p, tif->children); // the test - jumpNext = emitJump(p, OP_JIFNOT); + jumpNext = emitJump(p, OP_JIFNOTPOP); genExprList(p, tif->children->next->children); // the body jumpEnd = emitJump(p, OP_JMP); fixJumpTarget(p, jumpNext); @@ -373,7 +344,7 @@ static void genQuestion(struct Parser* p, struct Token* t) if(!RIGHT(t) || RIGHT(t)->type != TOK_COLON) naParseError(p, "invalid ?: expression", t->line); genExpr(p, LEFT(t)); // the test - jumpNext = emitJump(p, OP_JIFNOT); + jumpNext = emitJump(p, OP_JIFNOTPOP); genExpr(p, LEFT(RIGHT(t))); // the "if true" expr jumpEnd = emitJump(p, OP_JMP); fixJumpTarget(p, jumpNext); @@ -419,7 +390,7 @@ static void genForWhile(struct Parser* p, struct Token* init, pushLoop(p, label); loopTop = p->cg->codesz; genExpr(p, test); - jumpEnd = emitJump(p, OP_JIFNOT); + jumpEnd = emitJump(p, OP_JIFNOTPOP); genLoop(p, body, update, label, loopTop, jumpEnd); } @@ -479,17 +450,19 @@ static void genForEach(struct Parser* p, struct Token* t) vec = RIGHT(h); body = RIGHT(t)->children; - pushLoop(p, label); genExpr(p, vec); emit(p, OP_PUSHZERO); + pushLoop(p, label); loopTop = p->cg->codesz; emit(p, t->type == TOK_FOREACH ? OP_EACH : OP_INDEX); - jumpEnd = emitJump(p, OP_JIFNIL); + jumpEnd = emitJump(p, OP_JIFEND); assignOp = genLValue(p, elem, &dummy); emit(p, OP_XCHG); emit(p, assignOp); emit(p, OP_POP); genLoop(p, body, 0, label, loopTop, jumpEnd); + emit(p, OP_POP); // Pull off the vector and index + emit(p, OP_POP); } static int tokMatch(struct Token* a, struct Token* b) @@ -517,9 +490,9 @@ static void genBreakContinue(struct Parser* p, struct Token* t) bp = p->cg->loops[p->cg->loopTop - levels].breakIP; cp = p->cg->loops[p->cg->loopTop - levels].contIP; for(i=0; itype == TOK_BREAK) - emit(p, OP_PUSHNIL); // breakIP is always a JIFNOT/JIFNIL! + emit(p, OP_PUSHEND); // breakIP is always a JIFNOTPOP/JIFEND! emitImmediate(p, OP_JMP, t->type == TOK_BREAK ? bp : cp); } @@ -541,6 +514,8 @@ static void newLineEntry(struct Parser* p, int line) static void genExpr(struct Parser* p, struct Token* t) { int i, dummy; + if(!t) naParseError(p, "parse error", -1); // throw line -1... + p->errLine = t->line; // ...to use this one instead if(t->line != p->cg->lastLine) newLineEntry(p, t->line); p->cg->lastLine = t->line; @@ -610,7 +585,7 @@ static void genExpr(struct Parser* p, struct Token* t) case TOK_MINUS: if(BINARY(t)) { genBinOp(OP_MINUS, p, t); // binary subtraction - } else if(RIGHT(t)->type == TOK_LITERAL && !RIGHT(t)->str) { + } else if(RIGHT(t) && RIGHT(t)->type == TOK_LITERAL && !RIGHT(t)->str) { RIGHT(t)->num *= -1; // Pre-negate constants genScalarConstant(p, RIGHT(t)); } else { @@ -624,7 +599,7 @@ static void genExpr(struct Parser* p, struct Token* t) break; case TOK_DOT: genExpr(p, LEFT(t)); - if(RIGHT(t)->type != TOK_SYMBOL) + if(!RIGHT(t) || RIGHT(t)->type != TOK_SYMBOL) naParseError(p, "object field not symbol", RIGHT(t)->line); emitImmediate(p, OP_MEMBER, findConstantIndex(p, RIGHT(t))); break; @@ -655,7 +630,7 @@ static void genExpr(struct Parser* p, struct Token* t) static void genExprList(struct Parser* p, struct Token* t) { - if(t->type == TOK_SEMI) { + if(t && t->type == TOK_SEMI) { genExpr(p, LEFT(t)); if(RIGHT(t) && RIGHT(t)->type != TOK_EMPTY) { emit(p, OP_POP); @@ -689,7 +664,7 @@ naRef naCodeGen(struct Parser* p, struct Token* block, struct Token* arglist) // Now make a code object codeObj = naNewCode(p->context); - code = codeObj.ref.ptr.code; + code = PTR(codeObj).code; // Parse the argument list, if any code->restArgSym = globals->argRef;