Add Nasal Vs. 1.5
This commit is contained in:
parent
5812571df4
commit
83b4dcb55c
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user