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:
Thomas Geymayer
2013-10-15 12:05:09 +02:00
parent 42c39b6be3
commit d68b1144b8
2 changed files with 70 additions and 0 deletions

View File

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

View File

@@ -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