]> git.mxchange.org Git - simgear.git/commitdiff
Nasal: support for standard bitwise operators.
authorThomas Geymayer <tomgey@gmail.com>
Tue, 17 Jun 2014 14:13:53 +0000 (16:13 +0200)
committerThomas Geymayer <tomgey@gmail.com>
Tue, 17 Jun 2014 14:59:04 +0000 (16:59 +0200)
This makes bitwise operations a lot easier^^

simgear/nasal/code.c
simgear/nasal/code.h
simgear/nasal/codegen.c
simgear/nasal/lex.c
simgear/nasal/parse.c
simgear/nasal/parse.h

index 5f94217f45d403c769a5f898294994587f3fc99b..2f75220e8a51bccab8e53f20ef7b7800101973d5 100644 (file)
@@ -592,6 +592,9 @@ static naRef run(naContext ctx)
         case OP_LTE:   BINOP(l <= r ? 1 : 0); break;
         case OP_GT:    BINOP(l >  r ? 1 : 0); break;
         case OP_GTE:   BINOP(l >= r ? 1 : 0); break;
+        case OP_BIT_AND: BINOP((int)l & (int)r); break;
+        case OP_BIT_OR:  BINOP((int)l | (int)r); break;
+        case OP_BIT_XOR: BINOP((int)l ^ (int)r); break;
 #undef BINOP
 
         case OP_EQ: case OP_NEQ:
@@ -605,6 +608,9 @@ static naRef run(naContext ctx)
         case OP_NEG:
             STK(1) = naNum(-numify(ctx, STK(1)));
             break;
+        case OP_BIT_NEG:
+            STK(1) = naNum(~(int)numify(ctx, STK(1)));
+            break;
         case OP_NOT:
             STK(1) = naNum(boolify(ctx, STK(1)) ? 0 : 1);
             break;
index 4ff27afc5885c2b85fa26c5ef9ba08e739f80068..e7cb3f39edc47f2331b0491a908271699c742443 100644 (file)
@@ -26,7 +26,8 @@ enum {
     OP_MEMBER, OP_SETMEMBER, OP_LOCAL, OP_SETLOCAL, OP_NEWVEC, OP_VAPPEND,
     OP_NEWHASH, OP_HAPPEND, OP_MARK, OP_UNMARK, OP_BREAK, OP_SETSYM, OP_DUP2,
     OP_INDEX, OP_BREAK2, OP_PUSHEND, OP_JIFTRUE, OP_JIFNOT, OP_FCALLH,
-    OP_MCALLH, OP_XCHG2, OP_UNPACK, OP_SLICE, OP_SLICE2
+    OP_MCALLH, OP_XCHG2, OP_UNPACK, OP_SLICE, OP_SLICE2, OP_BIT_AND, OP_BIT_OR,
+    OP_BIT_XOR, OP_BIT_NEG
 };
 
 struct Frame {
index bc36a8179b124d2701e4b9acc8ebdc4aa530f359..495456a6cf91b72a8901b52742027983dfe96e61 100644 (file)
@@ -166,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);
 }
 
@@ -678,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)
@@ -690,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;
@@ -705,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);
     };
index b0dcf5f32f738fbec6089442fcccbd540fb889d6..92777ff9db5b5f0c604a99b097a332831e037674 100644 (file)
@@ -8,6 +8,9 @@ static const struct Lexeme {
     {"and", TOK_AND},
     {"or",  TOK_OR},
     {"!",   TOK_NOT},
+    {"&",   TOK_BIT_AND},
+    {"|",   TOK_BIT_OR},
+    {"^",   TOK_BIT_XOR},
     {"(", TOK_LPAR},
     {")", TOK_RPAR},
     {"[", TOK_LBRA},
@@ -49,6 +52,9 @@ static const struct Lexeme {
     {"*=", TOK_MULEQ},
     {"/=", TOK_DIVEQ},
     {"~=", TOK_CATEQ},
+    {"&=", TOK_BIT_ANDEQ},
+    {"|=", TOK_BIT_OREQ},
+    {"^=", TOK_BIT_XOREQ},
     {"forindex", TOK_FORINDEX},
 };
 
@@ -136,13 +142,14 @@ static void newToken(struct Parser* p, int pos, int type,
     tok->lastChild = 0;
     tok->rule = 0;
     
-    // Context sensitivity hack: a "-" following a binary operator of
+    // Context sensitivity hack: a "-" or "~" following a binary operator of
     // equal or higher precedence must be a unary negation.  Needed to
     // get precedence right in the parser for expressiong like "a * -2"
-    if(type == TOK_MINUS && tok->prev) {
+    if((type == TOK_MINUS || type == TOK_CAT) && tok->prev) {
         int pt = tok->prev->type;
-        if(pt==TOK_PLUS||pt==TOK_MINUS||pt==TOK_CAT||pt==TOK_MUL||pt==TOK_DIV)
-            tok->type = type = TOK_NEG;
+        if( pt==TOK_PLUS||pt==TOK_MINUS||pt==TOK_CAT||pt==TOK_MUL||pt==TOK_DIV
+         || pt==TOK_BIT_AND||pt==TOK_BIT_OR||pt==TOK_BIT_XOR )
+            tok->type = type = (type == TOK_MINUS ? TOK_NEG : TOK_BIT_NEG);
     }
 
     if(!p->tree.children) p->tree.children = tok;
index 2e66d8fe92de81f7b0b59cd8c6462683be685c7b..e5b012fa973c3b56cbccfa963a2ad84f6e6fd632 100644 (file)
@@ -5,7 +5,7 @@
 
 // Static precedence table, from low (loose binding, do first) to high
 // (tight binding, do last).
-#define MAX_PREC_TOKS 6
+#define MAX_PREC_TOKS 9
 static const struct precedence {
     int toks[MAX_PREC_TOKS];
     int rule;
@@ -14,16 +14,22 @@ static const struct precedence {
     { { TOK_ELLIPSIS },                        PREC_SUFFIX  },
     { { TOK_RETURN, TOK_BREAK, TOK_CONTINUE }, PREC_PREFIX  },
     { { TOK_ASSIGN, TOK_PLUSEQ, TOK_MINUSEQ,
-        TOK_MULEQ, TOK_DIVEQ, TOK_CATEQ     }, PREC_REVERSE },
+        TOK_MULEQ, TOK_DIVEQ, TOK_CATEQ,
+        TOK_BIT_ANDEQ, TOK_BIT_OREQ,
+        TOK_BIT_XOREQ },                       PREC_REVERSE },
     { { TOK_COLON, TOK_QUESTION },             PREC_REVERSE },
     { { TOK_VAR },                             PREC_PREFIX  },
+    { { TOK_BIT_OR },                          PREC_BINARY  },
+    { { TOK_BIT_XOR },                         PREC_BINARY  },
+    { { TOK_BIT_AND },                         PREC_BINARY  },
     { { TOK_OR },                              PREC_BINARY  },
     { { TOK_AND },                             PREC_BINARY  },
     { { TOK_EQ, TOK_NEQ },                     PREC_BINARY  },
     { { TOK_LT, TOK_LTE, TOK_GT, TOK_GTE },    PREC_BINARY  },
     { { TOK_PLUS, TOK_MINUS, TOK_CAT },        PREC_BINARY  },
     { { TOK_MUL, TOK_DIV },                    PREC_BINARY  },
-    { { TOK_MINUS, TOK_NEG, TOK_NOT },         PREC_PREFIX  },
+    { { TOK_MINUS, TOK_NEG, TOK_NOT,
+        TOK_CAT, TOK_BIT_NEG },                PREC_PREFIX  },
     { { TOK_LPAR, TOK_LBRA },                  PREC_SUFFIX  },
     { { TOK_DOT },                             PREC_BINARY  },
 };
index 1574ea305f3999f869355d4c066d58adf203e572..39bfbe05df4001c1ea607b525c59cef3d40dc1b2 100644 (file)
@@ -8,15 +8,16 @@
 #include "code.h"
 
 enum tok {
-    TOK_TOP=1, TOK_AND, TOK_OR, TOK_NOT, TOK_LPAR, TOK_RPAR, TOK_LBRA,
+    TOK_TOP=1, TOK_AND, TOK_OR, TOK_NOT, TOK_BIT_AND, TOK_BIT_OR, TOK_BIT_XOR,
+    TOK_BIT_NEG, TOK_LPAR, TOK_RPAR, TOK_LBRA,
     TOK_RBRA, TOK_LCURL, TOK_RCURL, TOK_MUL, TOK_PLUS, TOK_MINUS, TOK_NEG,
     TOK_DIV, TOK_CAT, TOK_COLON, TOK_DOT, TOK_COMMA, TOK_SEMI,
     TOK_ASSIGN, TOK_LT, TOK_LTE, TOK_EQ, TOK_NEQ, TOK_GT, TOK_GTE,
     TOK_IF, TOK_ELSIF, TOK_ELSE, TOK_FOR, TOK_FOREACH, TOK_WHILE,
     TOK_RETURN, TOK_BREAK, TOK_CONTINUE, TOK_FUNC, TOK_SYMBOL,
     TOK_LITERAL, TOK_EMPTY, TOK_NIL, TOK_ELLIPSIS, TOK_QUESTION, TOK_VAR,
-    TOK_PLUSEQ, TOK_MINUSEQ, TOK_MULEQ, TOK_DIVEQ, TOK_CATEQ,
-    TOK_FORINDEX
+    TOK_PLUSEQ, TOK_MINUSEQ, TOK_MULEQ, TOK_DIVEQ, TOK_CATEQ, TOK_BIT_ANDEQ,
+    TOK_BIT_OREQ, TOK_BIT_XOREQ, TOK_FORINDEX
 };
 
 // Precedence rules