]> git.mxchange.org Git - simgear.git/commitdiff
Nasal: recursive method calling.
authorThomas Geymayer <tomgey@gmail.com>
Tue, 15 Oct 2013 10:05:09 +0000 (12:05 +0200)
committerThomas Geymayer <tomgey@gmail.com>
Tue, 15 Oct 2013 10:08:42 +0000 (12:08 +0200)
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.

simgear/nasal/code.c
simgear/nasal/nasal.h

index bac8b92bd900c9ea7fcd4da99d3f9b0351416601..395a3cdd99ddd9e96153b6556a2d6ff70055006b 100644 (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;
+}
index 0464c94cee864c0dc3fc0864fd604623d0ac030b..ba7947fc7986a1058747df911651ae523e7418e2 100644 (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