]> git.mxchange.org Git - simgear.git/commitdiff
Add Nasal Vs. 1.5
authorehofman <ehofman>
Mon, 1 Dec 2003 14:33:45 +0000 (14:33 +0000)
committerehofman <ehofman>
Mon, 1 Dec 2003 14:33:45 +0000 (14:33 +0000)
simgear/nasal/code.c
simgear/nasal/data.h
simgear/nasal/gc.c
simgear/nasal/hash.c
simgear/nasal/lex.c
simgear/nasal/lib.c
simgear/nasal/misc.c
simgear/nasal/nasal.h

index d24dcc47ddce5927a33da176479a4bf6b6d79502..9333c88f2dc4e1ebb013139f640f23c2f7a20c19 100644 (file)
@@ -358,8 +358,12 @@ static void run1(struct Context* ctx, struct Frame* f, naRef code)
         PUSH(ctx, evalAndOr(ctx, op, a, b));
         break;
     case OP_CAT:
-        a = stringify(ctx, POP(ctx)); b = stringify(ctx, POP(ctx));
+        // stringify can call the GC, so don't take stuff of the stack!
+        if(ctx->opTop <= 1) ERR(ctx, "BUG: stack underflow");
+        a = stringify(ctx, ctx->opStack[ctx->opTop-1]);
+        b = stringify(ctx, ctx->opStack[ctx->opTop-2]);
         c = naStr_concat(naNewString(ctx), b, a);
+        ctx->opTop -= 2;
         PUSH(ctx, c);
         break;
     case OP_NEG:
@@ -531,6 +535,7 @@ static naRef run(naContext ctx)
 {
     // Return early if an error occurred.  It will be visible to the
     // caller via naGetError().
+    ctx->error = 0;
     if(setjmp(ctx->jumpHandle))
         return naNil();
     
index c350b6574e1191cbc86897f93fb7c884a7b17406..4ed0f07c38c13e23dc66e21456cb5822e90feda2 100644 (file)
@@ -7,7 +7,7 @@
 // What actually gets executed at runtime is a bound FUNC object,
 // which combines the raw code with a pointer to a CLOSURE chain of
 // namespaces.
-enum { T_STR, T_VEC, T_HASH, T_CODE, T_CLOSURE, T_FUNC, T_CCODE,
+enum { T_STR, T_VEC, T_HASH, T_CODE, T_CLOSURE, T_FUNC, T_CCODE, T_GHOST,
        NUM_NASAL_TYPES }; // V. important that this come last!
 
 #define IS_REF(r) ((r).ref.reftag == NASAL_REFTAG)
@@ -21,6 +21,7 @@ enum { T_STR, T_VEC, T_HASH, T_CODE, T_CLOSURE, T_FUNC, T_CCODE,
 #define IS_FUNC(r) (IS_OBJ((r)) && (r).ref.ptr.obj->type == T_FUNC)
 #define IS_CLOSURE(r) (IS_OBJ((r)) && (r).ref.ptr.obj->type == T_CLOSURE)
 #define IS_CCODE(r) (IS_OBJ((r)) && (r).ref.ptr.obj->type == T_CCODE)
+#define IS_GHOST(r) (IS_OBJ((r)) && (r).ref.ptr.obj->type == T_GHOST)
 #define IS_CONTAINER(r) (IS_VEC(r)||IS_HASH(r))
 #define IS_SCALAR(r) (IS_NUM((r)) || IS_STR((r)))
 
@@ -90,6 +91,12 @@ struct naCCode {
     naCFunction fptr;
 };
 
+struct naGhost {
+    GC_HEADER;
+    naGhostType* gtype;
+    void* ptr;
+};
+
 struct naPool {
     int           type;
     int           elemsz;
index 8fa2b9c5326b96312f9f70a9b06305540eec0b83..60f6c4223785c1f476bed9733f5acfb6d0993fbe 100644 (file)
@@ -41,6 +41,12 @@ static void naCode_gcclean(struct naCode* o)
     naFree(o->constants); o->constants = 0;
 }
 
+static void naGhost_gcclean(struct naGhost* g)
+{
+    if(g->ptr) g->gtype->destroy(g->ptr);
+    g->ptr = 0;
+}
+
 static void freeelem(struct naPool* p, struct naObj* o)
 {
     // Mark the object as "freed" for debugging purposes
@@ -61,6 +67,9 @@ static void freeelem(struct naPool* p, struct naObj* o)
     case T_CODE:
         naCode_gcclean((struct naCode*)o);
         break;
+    case T_GHOST:
+        naGhost_gcclean((struct naGhost*)o);
+        break;
     }
 
     // And add it to the free list
index 966cd95785e7e0b7d3ace0ceda5a0378ce1f6450..8c8e537d1bd653982481c570f503909751f67c52 100644 (file)
@@ -196,7 +196,7 @@ void naHash_keys(naRef dst, naRef hash)
 {
     struct naHash* h = hash.ref.ptr.hash;
     int i;
-    if(!IS_HASH(hash)) return;
+    if(!IS_HASH(hash) || !h->table) return;
     for(i=0; i<(1<<h->lgalloced); i++) {
         struct HashNode* hn = h->table[i];
         while(hn) {
index 86f1442eb5c2ce79514f0b918845ff7ab9cd340a..adc08e176e56de5014f0cec8675152808486b426 100644 (file)
@@ -132,7 +132,7 @@ static void newToken(struct Parser* p, int pos, int type,
 static int hexc(char c, struct Parser* p, int index)
 {
     if(c >= '0' && c <= '9') return c - '0';
-    if(c >= 'A' && c <= 'F') return c - 'a' + 10;
+    if(c >= 'A' && c <= 'F') return c - 'A' + 10;
     if(c >= 'a' && c <= 'f') return c - 'a' + 10;
     error(p, "bad hex constant", index);
     return 0;
@@ -170,6 +170,7 @@ static void dqEscape(char* buf, int len, int index, struct Parser* p,
         if(len < 4) error(p, "unterminated string", index);
         *cOut = (char)((hexc(buf[2], p, index)<<4) | hexc(buf[3], p, index));
         *eatenOut = 4;
+        break;
     default:
         // Unhandled, put the backslash back
         *cOut = '\\';
@@ -235,7 +236,8 @@ static int trySymbol(struct Parser* p, int start)
 {
     int i = start;
     while((i < p->len) &&
-          ((p->buf[i] >= 'A' && p->buf[i] <= 'Z') ||
+          ((p->buf[i] == '_') ||
+           (p->buf[i] >= 'A' && p->buf[i] <= 'Z') ||
            (p->buf[i] >= 'a' && p->buf[i] <= 'z') ||
            (p->buf[i] >= '0' && p->buf[i] <= '9')))
     { i++; }
@@ -316,7 +318,7 @@ void naLex(struct Parser* p)
         if(!handled) {
             int symlen=0, lexlen=0, lexeme;
             lexlen = tryLexemes(p, i, &lexeme);
-            if((c>='A' && c<='Z') || (c>='a' && c<='z'))
+            if((c>='A' && c<='Z') || (c>='a' && c<='z') || (c=='_'))
                 symlen = trySymbol(p, i);
             if(lexlen && lexlen >= symlen) {
                 newToken(p, i, LEXEMES[lexeme].tok, 0, 0, 0);
index 1ed3837bd6549fbd400d361c87f7177e48218576..b050aa708499fab98dad4429a30b7d76ff75104f 100644 (file)
@@ -118,6 +118,7 @@ static naRef typeOf(naContext c, naRef args)
     else if(naIsVector(r)) t = "vector";
     else if(naIsHash(r)) t = "hash";
     else if(naIsFunc(r)) t = "func";
+    else if(naIsGhost(r)) t = "ghost";
     r = naStr_fromdata(naNewString(c), t, strlen(t));
     return r;
 }
index 541900329a362b2a42e200dc9479c15f9bf63e54..73bd19d2b01129c8afa9d074bbdecbd6d80d6ab2 100644 (file)
@@ -104,6 +104,26 @@ naRef naNewClosure(struct Context* c, naRef namespace, naRef next)
     return closure;
 }
 
+naRef naNewGhost(naContext c, naGhostType* type, void* ptr)
+{
+    naRef ghost = naNew(c, T_GHOST);
+    ghost.ref.ptr.ghost->gtype = type;
+    ghost.ref.ptr.ghost->ptr = ptr;
+    return ghost;
+}
+
+naGhostType* naGhost_type(naRef ghost)
+{
+    if(!IS_GHOST(ghost)) return 0;
+    return ghost.ref.ptr.ghost->gtype;
+}
+
+void* naGhost_ptr(naRef ghost)
+{
+    if(!IS_GHOST(ghost)) return 0;
+    return ghost.ref.ptr.ghost->ptr;
+}
+
 naRef naNil()
 {
     naRef r;
@@ -151,6 +171,7 @@ int naTypeSize(int type)
     case T_FUNC: return sizeof(struct naFunc);
     case T_CLOSURE: return sizeof(struct naClosure);
     case T_CCODE: return sizeof(struct naCCode);
+    case T_GHOST: return sizeof(struct naGhost);
     };
     return 0x7fffffff; // Make sure the answer is nonsense :)
 }
@@ -200,3 +221,7 @@ int naIsCCode(naRef r)
     return IS_CCODE(r);
 }
 
+int naIsGhost(naRef r)
+{
+    return IS_GHOST(r);
+}
index 417ca67d3438959a775e89c164b8bfe45f7eebf9..57b0372de295c78fa401df1ac1360f7a8eba6551 100644 (file)
@@ -31,6 +31,7 @@ typedef union {
             struct naFunc* func;
             struct naClosure* closure;
             struct naCCode* ccode;
+            struct naGhost* ghost;
         } ptr;
 #ifndef NASAL_BIG_ENDIAN_32_BIT
         int reftag; // Little-endian and 64 bit systems need this here!
@@ -139,6 +140,15 @@ void naHash_cset(naRef hash, char* key, naRef val);
 void naHash_delete(naRef hash, naRef key);
 void naHash_keys(naRef dst, naRef hash);
 
+// Ghost utilities:
+typedef struct naGhostType {
+    void (*destroy)(void* ghost);
+} naGhostType;
+naRef        naNewGhost(naContext c, naGhostType* t, void* ghost);
+naGhostType* naGhost_type(naRef ghost);
+void*        naGhost_ptr(naRef ghost);
+int          naIsGhost(naRef r);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif