X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fnasal%2Fcodegen.c;h=495456a6cf91b72a8901b52742027983dfe96e61;hb=9aa5c3b2ae9442a9f777088cae982aef9034183c;hp=d1c05ef6254808bc7abf6c20b9e4d5f7f6d44afd;hpb=818359bfd09e493c8d74b7ace8b91f4d229eab67;p=simgear.git diff --git a/simgear/nasal/codegen.c b/simgear/nasal/codegen.c index d1c05ef6..495456a6 100644 --- a/simgear/nasal/codegen.c +++ b/simgear/nasal/codegen.c @@ -7,6 +7,7 @@ // These are more sensical predicate names in most contexts in this file #define LEFT(tok) ((tok)->children) #define RIGHT(tok) ((tok)->lastChild) +#define UNARY(tok) (LEFT(tok) && LEFT(tok) == RIGHT(tok)) #define BINARY(tok) (LEFT(tok) && RIGHT(tok) && LEFT(tok)->next == RIGHT(tok)) // Forward references for recursion @@ -147,7 +148,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_LPAR) { + // http://code.google.com/p/flightgear-bugs/issues/detail?id=737 + // TOK_LPAR can mean multi-value assignment or function call, + // disambigaute by checking the rule of the token + if (t->rule == PREC_SUFFIX) + naParseError(p, "default arguments cannot be function calls", t->line); + return defArg(p, RIGHT(t)); + } + if(t->type == TOK_MINUS && RIGHT(t) && RIGHT(t)->type == TOK_LITERAL && !RIGHT(t)->str) { @@ -157,6 +166,15 @@ static int defArg(struct Parser* p, struct Token* t) RIGHT(t)->num *= -1; return defArg(p, RIGHT(t)); } + if(t->type == TOK_CAT && 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 = ~(int)RIGHT(t)->num; + return defArg(p, RIGHT(t)); + } return findConstantIndex(p, t); } @@ -477,6 +495,11 @@ static int tokMatch(struct Token* a, struct Token* b) static void genBreakContinue(struct Parser* p, struct Token* t) { int levels = 1, loop = -1, bp, cp, i; + // http://code.google.com/p/flightgear-bugs/issues/detail?id=587 + // Make sure we are inside of a loop + if(p->cg->loopTop <= 0) + naParseError(p, "break/continue outside of a valid loop", t->line); + if(RIGHT(t)) { if(RIGHT(t)->type != TOK_SYMBOL) naParseError(p, "bad break/continue label", t->line); @@ -536,10 +559,16 @@ static void genAssign(struct Parser* p, struct Token* t) { struct Token *lv = LEFT(t), *rv = RIGHT(t); int len, dummy, var=0; + if (!lv) + naParseError(p, "bad assignment, missing variable", t->line); + else if(parListLen(lv) || (lv->type == TOK_VAR && parListLen(RIGHT(lv)))) { if(lv->type == TOK_VAR) { lv = RIGHT(lv); var = 1; } len = parListLen(lv); - if(rv->type == TOK_LPAR) { + // http://code.google.com/p/flightgear-bugs/issues/detail?id=585 + // TOK_LPAR can mean multi-value assignment or function call, + // disambigaute by checking the rule of the token + if(rv->type == TOK_LPAR && rv->rule != PREC_SUFFIX) { if(len != parListLen(rv)) naParseError(p, "bad assignment count", rv->line); genCommaList(p, LEFT(rv)); @@ -615,12 +644,16 @@ static void genExpr(struct Parser* p, struct Token* t) else genExpr(p, LEFT(t)); break; case TOK_LBRA: - if(BINARY(t)) { - genExtract(p, t); - } else { + if(UNARY(t)) { emit(p, OP_NEWVEC); genList(p, LEFT(t), 1); } + else if(BINARY(t)) { + genExtract(p, t); + } else { + // forbid usage as 'vec[]' + naParseError(p, "missing index or slice expression(s)", t->line); + } break; case TOK_LCURL: emit(p, OP_NEWHASH); @@ -654,6 +687,21 @@ static void genExpr(struct Parser* p, struct Token* t) genExpr(p, RIGHT(t)); // unary negation (see also TOK_MINUS!) emit(p, OP_NEG); break; + case TOK_CAT: + if(BINARY(t)) { + genBinOp(OP_CAT, p, t); // string concatenation + } else if(RIGHT(t) && RIGHT(t)->type == TOK_LITERAL && !RIGHT(t)->str) { + RIGHT(t)->num = ~(int)RIGHT(t)->num; // Pre-negate constants + genScalarConstant(p, RIGHT(t)); + } else { + genExpr(p, RIGHT(t)); // unary, bitwise negation + emit(p, OP_BIT_NEG); + } + break; + case TOK_BIT_NEG: + genExpr(p, RIGHT(t)); // unary, bitwise negation (see also TOK_CAT!) + emit(p, OP_BIT_NEG); + break; case TOK_DOT: genExpr(p, LEFT(t)); if(!RIGHT(t) || RIGHT(t)->type != TOK_SYMBOL) @@ -666,10 +714,12 @@ static void genExpr(struct Parser* p, struct Token* t) case TOK_AND: case TOK_OR: genShortCircuit(p, t); break; + case TOK_BIT_AND:genBinOp(OP_BIT_AND, p, t); break; + case TOK_BIT_OR: genBinOp(OP_BIT_OR, p, t); break; + case TOK_BIT_XOR:genBinOp(OP_BIT_XOR, p, t); break; case TOK_MUL: genBinOp(OP_MUL, p, t); break; case TOK_PLUS: genBinOp(OP_PLUS, p, t); break; case TOK_DIV: genBinOp(OP_DIV, p, t); break; - case TOK_CAT: genBinOp(OP_CAT, p, t); break; case TOK_LT: genBinOp(OP_LT, p, t); break; case TOK_LTE: genBinOp(OP_LTE, p, t); break; case TOK_EQ: genBinOp(OP_EQ, p, t); break; @@ -681,6 +731,9 @@ static void genExpr(struct Parser* p, struct Token* t) case TOK_MULEQ: genEqOp(OP_MUL, p, t); break; case TOK_DIVEQ: genEqOp(OP_DIV, p, t); break; case TOK_CATEQ: genEqOp(OP_CAT, p, t); break; + case TOK_BIT_ANDEQ: genEqOp(OP_BIT_AND, p, t); break; + case TOK_BIT_OREQ: genEqOp(OP_BIT_OR, p, t); break; + case TOK_BIT_XOREQ: genEqOp(OP_BIT_XOR, p, t); break; default: naParseError(p, "parse error", t->line); };