Nasal: recursive method calling.
New functions naCallMethodCtx and naCallMethod to replace NasalSystem::callMethod from FlightGear. This has just added an unneeded level of indirection and fits better directly into Nasal. naSetErrorHandler can be used to register an error handler/logging function.
This commit is contained in:
@@ -936,3 +936,51 @@ naRef naContinue(naContext ctx)
|
||||
if(!ctx->callParent) naModUnlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
static void logError(naContext ctx)
|
||||
{
|
||||
int i;
|
||||
printf("logError\n");
|
||||
printf("Nasal runtime error: %s\n", naGetError(ctx));
|
||||
printf(" at %s\n", naStr_data(naGetSourceFile(ctx, 0)));
|
||||
printf(", line %d\n", naGetLine(ctx, 0));
|
||||
for(i = 1; i < naStackDepth(ctx); ++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;
|
||||
}
|
||||
|
||||
@@ -103,6 +103,28 @@ naRef naCall(naContext ctx, naRef func, int argc, naRef* args,
|
||||
// naModUnlock() first if the lock is already held.
|
||||
naRef naContinue(naContext ctx);
|
||||
|
||||
// Does a naCall() in a given context. Wrapped here to make lock
|
||||
// tracking easier. Extension functions are called with the lock, but
|
||||
// we have to release it before making a new naCall(). So rather than
|
||||
// drop the lock in every extension function that might call back into
|
||||
// Nasal, we keep a stack depth counter here and only unlock/lock
|
||||
// around the naCall if it isn't the first one.
|
||||
naRef naCallMethodCtx( naContext ctx,
|
||||
naRef code,
|
||||
naRef self,
|
||||
int argc,
|
||||
naRef* args,
|
||||
naRef locals );
|
||||
|
||||
// Same as naCallMethodCtx but creates (and afterwards destroyes) a new context
|
||||
naRef naCallMethod(naRef code, naRef self, int argc, naRef* args, naRef locals);
|
||||
|
||||
typedef void (*naErrorHandler)(naContext);
|
||||
|
||||
// Register a handler to be called if an error is raised during the execution of
|
||||
// naCallMethodCtx or naCallMethod.
|
||||
naErrorHandler naSetErrorHandler(naErrorHandler cb);
|
||||
|
||||
// Throw an error from the current call stack. This function makes a
|
||||
// longjmp call to a handler in naCall() and DOES NOT RETURN. It is
|
||||
// intended for use in library code that cannot otherwise report an
|
||||
|
||||
Reference in New Issue
Block a user