else if(IS_NIL(o)) ERR(ctx, "nil used in numeric context");
else if(!IS_STR(o)) ERR(ctx, "non-scalar in numeric context");
else if(naStr_tonum(o, &n)) return n;
- else ERR(ctx, "non-numeric string in numeric context");
+ else naRuntimeError( ctx,
+ "non-numeric string in numeric context: '%s'",
+ naStr_data(o) );
return 0;
}
globals->symbols = naNewHash(c);
globals->save = naNewVector(c);
+ globals->save_hash = naNewHash(c);
+ globals->next_gc_key = 0;
// Cache pre-calculated "me", "arg" and "parents" scalars
globals->meRef = naInternSymbol(naStr_fromdata(naNewString(c), "me", 2));
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:
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;
naVec_append(globals->save, obj);
}
+int naGCSave(naRef obj)
+{
+ int key = globals->next_gc_key++;
+ naHash_set(globals->save_hash, naNum(key), obj);
+ return key;
+}
+
+void naGCRelease(int key)
+{
+ naHash_delete(globals->save_hash, naNum(key));
+}
+
void naClearSaved()
{
naContext c;
c = naNewContext();
globals->save = naNewVector(c);
- naFreeContext(c);
+ globals->save_hash = naNewHash(c);
+ naFreeContext(c);
}
int naStackDepth(naContext ctx)
}
if(IS_CCODE(PTR(func).func->code)) {
- naCFunction fp = PTR(PTR(func).func->code).ccode->fptr;
- result = (*fp)(ctx, obj, argc, args);
+ struct naCCode *ccode = PTR(PTR(func).func->code).ccode;
+ result = ccode->fptru
+ ? (*ccode->fptru)(ctx, obj, argc, args, ccode->user_data)
+ : (*ccode->fptr) (ctx, obj, argc, args);
if(!ctx->callParent) naModUnlock();
return result;
}
if(!ctx->callParent) naModUnlock();
return result;
}
+
+static void logError(naContext ctx)
+{
+ int i, stack_depth = naStackDepth(ctx);
+ printf("Nasal runtime error: %s\n", naGetError(ctx));
+ if( stack_depth < 1 )
+ return;
+ printf(" at %s\n", naStr_data(naGetSourceFile(ctx, 0)));
+ printf(", line %d\n", naGetLine(ctx, 0));
+ for(i = 1; i < stack_depth; ++i )
+ printf( " called from: %s, line %d",
+ naStr_data(naGetSourceFile(ctx, i)),
+ naGetLine(ctx, i));
+}
+
+static naErrorHandler error_handler = &logError;
+naErrorHandler naSetErrorHandler(naErrorHandler cb)
+{
+ naErrorHandler old_handler = error_handler;
+ error_handler = cb;
+ return old_handler;
+}
+
+static int call_count = 0;
+naRef naCallMethodCtx( naContext ctx,
+ naRef code,
+ naRef self,
+ int argc,
+ naRef* args,
+ naRef locals )
+{
+ naRef result;
+ if(call_count) naModUnlock();
+ call_count++;
+ result = naCall(ctx, code, argc, args, self, locals);
+ if(naGetError(ctx) && error_handler)
+ error_handler(ctx);
+ call_count--;
+ if(call_count) naModLock();
+ return result;
+}
+
+naRef naCallMethod(naRef code, naRef self, int argc, naRef* args, naRef locals)
+{
+ naContext ctx = naNewContext();
+ naRef result = naCallMethodCtx(ctx, code, self, argc, args, locals);
+ naFreeContext(ctx);
+ return result;
+}