Add Nasal Vs. 1.5

This commit is contained in:
ehofman 2003-12-01 14:33:45 +00:00
parent 5812571df4
commit 83b4dcb55c
8 changed files with 65 additions and 6 deletions

View 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();

View 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;

View 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

View 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) {

View 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);

View 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;
}

View 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);
}

View 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