]> git.mxchange.org Git - simgear.git/blobdiff - simgear/nasal/codegen.c
Cygwin fixes.
[simgear.git] / simgear / nasal / codegen.c
index c909c92888996436a37e48228799791029265b08..6593c268ae2ccbf8aa1fc674ac53a82b22ef69a3 100644 (file)
@@ -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);
@@ -125,7 +126,7 @@ static int tailContext(struct Token* t)
     return 0;
 }
 
-static void genScalarConstant(struct Parser* p, struct Token* t)
+static int genScalarConstant(struct Parser* p, struct Token* t)
 {
     // These opcodes are for special-case use in other constructs, but
     // we might as well use them here to save a few bytes in the
@@ -137,26 +138,28 @@ static void genScalarConstant(struct Parser* p, struct Token* t)
     } else {
         int idx = findConstantIndex(p, t);
         emitImmediate(p, OP_PUSHCONST, idx);
+        return idx;
     }
+    return 0;
 }
 
-static int genLValue(struct Parser* p, struct Token* t)
+static int genLValue(struct Parser* p, struct Token* t, int* cidx)
 {
     if(t->type == TOK_LPAR) {
-        return genLValue(p, LEFT(t)); // Handle stuff like "(a) = 1"
+        return genLValue(p, LEFT(t), cidx); // Handle stuff like "(a) = 1"
     } else if(t->type == TOK_SYMBOL) {
-        genScalarConstant(p, t);
+        *cidx = genScalarConstant(p, t);
         return OP_SETSYM;
     } else if(t->type == TOK_DOT && RIGHT(t) && RIGHT(t)->type == TOK_SYMBOL) {
         genExpr(p, LEFT(t));
-        genScalarConstant(p, RIGHT(t));
+        *cidx = genScalarConstant(p, RIGHT(t));
         return OP_SETMEMBER;
     } else if(t->type == TOK_LBRA) {
         genExpr(p, LEFT(t));
         genExpr(p, RIGHT(t));
         return OP_INSERT;
-    } else if(t->type == TOK_VAR && RIGHT(t)->type == TOK_SYMBOL) {
-        genScalarConstant(p, RIGHT(t));
+    } else if(t->type == TOK_VAR && RIGHT(t) && RIGHT(t)->type == TOK_SYMBOL) {
+        *cidx = genScalarConstant(p, RIGHT(t));
         return OP_SETLOCAL;
     } else {
         naParseError(p, "bad lvalue", t->line);
@@ -164,6 +167,23 @@ static int genLValue(struct Parser* p, struct Token* t)
     }
 }
 
+static void genEqOp(int op, struct Parser* p, struct Token* t)
+{
+    int cidx, setop = genLValue(p, LEFT(t), &cidx);
+    if(setop == OP_SETMEMBER) {
+        emit(p, OP_DUP2);
+        emit(p, OP_POP);
+        emitImmediate(p, OP_MEMBER, cidx);
+    } else if(setop == OP_INSERT) {
+        emit(p, OP_DUP2);
+        emit(p, OP_EXTRACT);
+    } else // OP_SETSYM, OP_SETLOCAL
+        emitImmediate(p, OP_LOCAL, cidx);
+    genExpr(p, RIGHT(t));
+    emit(p, op);
+    emit(p, setop);
+}
+
 static int defArg(struct Parser* p, struct Token* t)
 {
     if(t->type == TOK_LPAR) return defArg(p, RIGHT(t));
@@ -444,7 +464,7 @@ static void genFor(struct Parser* p, struct Token* t)
 
 static void genForEach(struct Parser* p, struct Token* t)
 {
-    int loopTop, jumpEnd, assignOp;
+    int loopTop, jumpEnd, assignOp, dummy;
     struct Token *elem, *body, *vec, *label=0;
     struct Token *h = LEFT(LEFT(t));
     int semis = countSemis(h);
@@ -464,9 +484,9 @@ static void genForEach(struct Parser* p, struct Token* t)
     genExpr(p, vec);
     emit(p, OP_PUSHZERO);
     loopTop = p->cg->codesz;
-    emit(p, OP_EACH);
+    emit(p, t->type == TOK_FOREACH ? OP_EACH : OP_INDEX);
     jumpEnd = emitJump(p, OP_JIFNIL);
-    assignOp = genLValue(p, elem);
+    assignOp = genLValue(p, elem, &dummy);
     emit(p, OP_XCHG);
     emit(p, assignOp);
     emit(p, OP_POP);
@@ -521,7 +541,7 @@ static void newLineEntry(struct Parser* p, int line)
 
 static void genExpr(struct Parser* p, struct Token* t)
 {
-    int i;
+    int i, dummy;
     if(t->line != p->cg->lastLine)
         newLineEntry(p, t->line);
     p->cg->lastLine = t->line;
@@ -539,6 +559,7 @@ static void genExpr(struct Parser* p, struct Token* t)
         genFor(p, t);
         break;
     case TOK_FOREACH:
+    case TOK_FORINDEX:
         genForEach(p, t);
         break;
     case TOK_BREAK: case TOK_CONTINUE:
@@ -567,7 +588,7 @@ static void genExpr(struct Parser* p, struct Token* t)
         genHash(p, LEFT(t));
         break;
     case TOK_ASSIGN:
-        i = genLValue(p, LEFT(t));
+        i = genLValue(p, LEFT(t), &dummy);
         genExpr(p, RIGHT(t));
         emit(p, i); // use the op appropriate to the lvalue
         break;
@@ -623,6 +644,11 @@ static void genExpr(struct Parser* p, struct Token* t)
     case TOK_NEQ:   genBinOp(OP_NEQ,    p, t); break;
     case TOK_GT:    genBinOp(OP_GT,     p, t); break;
     case TOK_GTE:   genBinOp(OP_GTE,    p, t); break;
+    case TOK_PLUSEQ:  genEqOp(OP_PLUS, p, t);  break;
+    case TOK_MINUSEQ: genEqOp(OP_MINUS, p, t); break;
+    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;
     default:
         naParseError(p, "parse error", t->line);
     };