// that it can be reset if we get a die()/naRethrowError() situation
// later. Right now, the IP on the stack trace is the line of the
// die() call, when it should be this one...
+//
+// FIXME: don't use naCall at all here, we don't need it. Fix up the
+// context stack to tail call the function directly. There's no need
+// for f_call() to live on the C stack at all.
static naRef f_call(naContext c, naRef me, int argc, naRef* args)
{
naContext subc;
callns = argc > 3 ? args[3] : naNil(); // ditto
if(!IS_HASH(callme)) callme = naNil();
if(!IS_HASH(callns)) callns = naNil();
- if(!IS_FUNC(args[0]) || (!IS_NIL(callargs) && !IS_VEC(callargs)))
+ if(argc==0 || !IS_FUNC(args[0]) || (!IS_NIL(callargs) && !IS_VEC(callargs)))
ARGERR();
- // Note that we don't free the subcontext, in case the user
- // re-throws the same error. That happens at the next OP_RETURN
- // or naSubContext().
subc = naSubContext(c);
vr = IS_NIL(callargs) ? 0 : PTR(callargs).vec->rec;
result = naCall(subc, args[0], vr ? vr->size : 0, vr ? vr->array : 0,
callme, callns);
- if(naGetError(subc)) {
- if(argc <= 2 || !IS_VEC(args[argc-1])) {
- naRethrowError(subc);
- } else {
- int i, sd;
- naRef errv = args[argc-1];
- if(!IS_NIL(subc->dieArg)) naVec_append(errv, subc->dieArg);
- else naVec_append(errv, NEWCSTR(subc, naGetError(subc)));
- sd = naStackDepth(subc);
- for(i=0; i<sd; i++) {
- naVec_append(errv, naGetSourceFile(subc, i));
- naVec_append(errv, naNum(naGetLine(subc, i)));
- }
+ if(!naGetError(subc)) {
+ naFreeContext(subc);
+ return result;
+ }
+
+ // Error handling. Note that we don't free the subcontext after an
+ // error, in case the user re-throws the same error or calls
+ // naContinue()
+ if(argc <= 2 || !IS_VEC(args[argc-1])) {
+ naRethrowError(subc);
+ } else {
+ int i, sd;
+ naRef errv = args[argc-1];
+ if(!IS_NIL(subc->dieArg)) naVec_append(errv, subc->dieArg);
+ else naVec_append(errv, NEWCSTR(subc, naGetError(subc)));
+ sd = naStackDepth(subc);
+ for(i=0; i<sd; i++) {
+ naVec_append(errv, naGetSourceFile(subc, i));
+ naVec_append(errv, naNum(naGetLine(subc, i)));
}
}
- return result;
+ return naNil();
}
static naRef f_die(naContext c, naRef me, int argc, naRef* args)
int start = 0;
if(argc < 2 || !IS_STR(args[0]) || !IS_STR(args[1])) ARGERR();
if(argc > 2) start = (int)(naNumValue(args[2]).num);
- return naNum(find(PTR(args[0]).str->data, PTR(args[0]).str->len,
- PTR(args[1]).str->data, PTR(args[1]).str->len,
+ return naNum(find((void*)naStr_data(args[0]), naStr_len(args[0]),
+ (void*)naStr_data(args[1]), naStr_len(args[1]),
start));
}
if(argc != 2 || !naIsVector(args[0]) || !naIsFunc(args[1]))
naRuntimeError(c, "bad/missing argument to sort()");
sd.subc = naSubContext(c);
+ if(!PTR(args[0]).vec->rec) return naNewVector(c);
sd.elems = PTR(args[0]).vec->rec->array;
sd.n = PTR(args[0]).vec->rec->size;
sd.fn = args[1];
return out;
}
+static naRef f_id(naContext c, naRef me, int argc, naRef* args)
+{
+ char *t = "unk", buf[64];
+ if(argc != 1 || !IS_REF(args[0]))
+ naRuntimeError(c, "bad/missing argument to id()");
+ if (IS_STR(args[0])) t = "str";
+ else if(IS_VEC(args[0])) t = "vec";
+ else if(IS_HASH(args[0])) t = "hash";
+ else if(IS_CODE(args[0])) t = "code";
+ else if(IS_FUNC(args[0])) t = "func";
+ else if(IS_CCODE(args[0])) t = "ccode";
+ else if(IS_GHOST(args[0])) {
+ naGhostType *gt = PTR(args[0]).ghost->gtype;
+ t = gt->name ? (char*)gt->name : "ghost";
+ }
+ sprintf(buf, "%s:%p", (char*)t, (void*)PTR(args[0]).obj);
+ return NEWCSTR(c, buf);
+}
+
static naCFuncItem funcs[] = {
{ "size", f_size },
{ "keys", f_keys },
{ "rand", f_rand },
{ "bind", f_bind },
{ "sort", f_sort },
+ { "id", f_id },
{ 0 }
};