From 5798e28801b4cb117f8c589f4cfff1faff44c107 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Thu, 15 Mar 2012 16:28:16 -0400 Subject: [PATCH] avoiding the internal error by explicitly checking the arity --- .../runtime-src/baselib-exceptions.js | 8 ++++- js-assembler/runtime-src/runtime.js | 18 ++++++++-- js/world/test-geo.rkt | 4 +-- web-world/js-impl.js | 33 ++++++++++++------- 4 files changed, 46 insertions(+), 17 deletions(-) diff --git a/js-assembler/runtime-src/baselib-exceptions.js b/js-assembler/runtime-src/baselib-exceptions.js index 29706d7..609e14b 100644 --- a/js-assembler/runtime-src/baselib-exceptions.js +++ b/js-assembler/runtime-src/baselib-exceptions.js @@ -134,14 +134,19 @@ }; var raiseArityMismatchError = function(MACHINE, proc, received) { + raise(MACHINE, makeArityMismatchError(MACHINE, proc, received)); + }; + + var makeArityMismatchError = function(MACHINE, proc, received) { var message = baselib.format.format("~a: expected ~e value(s), received ~e value(s)", [proc.displayName, proc.racketArity, received]); var contMarks = MACHINE.captureContinuationMarks(); - raise(MACHINE, ExnFailContractArity.constructor([message, contMarks])); + return ExnFailContractArity.constructor([message, contMarks]); }; + var raiseOperatorApplicationError = function(MACHINE, operator) { var message = baselib.format.format("not a procedure: ~e", [operator]); @@ -233,6 +238,7 @@ exceptions.raiseArgumentTypeError = raiseArgumentTypeError; exceptions.raiseContextExpectedValuesError = raiseContextExpectedValuesError; exceptions.raiseArityMismatchError = raiseArityMismatchError; + exceptions.makeArityMismatchError = makeArityMismatchError; exceptions.raiseOperatorApplicationError = raiseOperatorApplicationError; exceptions.raiseOperatorIsNotPrimitiveProcedure = raiseOperatorIsNotPrimitiveProcedure; exceptions.raiseUnimplementedPrimitiveError = raiseUnimplementedPrimitiveError; diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index 374fa0f..60c2246 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -171,6 +171,7 @@ // with two computations, with use of setTimeout. var ExclusiveLock = function() { this.locked = false; // (U false string) + this.alreadyReleased = false; this.waiters = []; }; @@ -193,16 +194,17 @@ id = ExclusiveLock.makeRandomNonce(); } - var alreadyReleased = false; + this.alreadyReleased = false; if (this.locked === false) { + console.log("lock is clear. Grabbing..."); this.locked = id; onAcquire.call( that, // releaseLock function() { var waiter; - if (alreadyReleased) { + if (that.alreadyReleased) { throw new Error( "Internal error: trying to release the lock, but already released"); } @@ -211,17 +213,19 @@ "Internal error: trying to unlock the lock, but already unlocked"); } that.locked = false; - alreadyReleased = true; + that.alreadyReleased = true; if (that.waiters.length > 0) { waiter = that.waiters.shift(); setTimeout( function() { + console.log("trying to re-acquire lock..."); that.acquire(waiter.id, waiter.onAcquire); }, 0); } }); } else { + console.log("lock is currently in play. Need to wait."); this.waiters.push({ id: id, onAcquire: onAcquire } ); } @@ -580,6 +584,7 @@ }); }; var internalCall = function(proc, success, fail) { + console.log("internalCall"); var i; if (restarted) { return; @@ -588,15 +593,20 @@ for (i = 3; i < arguments.length; i++) { args.push(arguments[i]); } + console.log("acquiring lock..."); pauseLock.acquire( void(0), function(release) { var newSuccess = function() { + console.log('newSuccess', arguments, proc, success); success.apply(null, arguments); + console.log("releasing lock..."); release(); }; var newFail = function() { + console.log('newFail', arguments, proc, fail); fail.apply(null, arguments); + console.log("releasing lock..."); release(); }; baselib.functions.internalCallDuringPause.apply( @@ -614,7 +624,9 @@ // General error condition: just exit out // of the trampoline and call the current error handler. that.running = false; + console.log("calling current error handler", that.params.currentErrorHandler); that.params.currentErrorHandler(that, e); + console.log("releasing"); release(); return; } diff --git a/js/world/test-geo.rkt b/js/world/test-geo.rkt index ac593fa..d5605dc 100644 --- a/js/world/test-geo.rkt +++ b/js/world/test-geo.rkt @@ -5,5 +5,5 @@ (big-bang (list 'undefined 'undefined) - (on-geo (lambda (w v lat lng) - (list lat lng)))) \ No newline at end of file + (on-geo (lambda (w v lat #;lng) + (list lat #;lng)))) \ No newline at end of file diff --git a/web-world/js-impl.js b/web-world/js-impl.js index 098e31e..82b875f 100644 --- a/web-world/js-impl.js +++ b/web-world/js-impl.js @@ -17,6 +17,7 @@ var makePair = plt.baselib.lists.makePair; var makeSymbol = plt.baselib.symbols.makeSymbol; var isArityMatching = plt.baselib.arity.isArityMatching; + var makeArityMismatchError = plt.baselib.exceptions.makeArityMismatchError; // EventHandler and the other classes here will be defined below. @@ -1197,6 +1198,7 @@ dispatchEventsInQueue, refreshView; onCleanRestart = function() { + console.log('on clean restart'); running = false; stopEventHandlers( function() { @@ -1209,12 +1211,16 @@ }; onMessyRestart = function(exn) { + console.log('on messy restart'); running = false; + console.log('stopping the event handlers'); stopEventHandlers( function() { + console.log('event handlers stopped'); restart(function(MACHINE) { currentBigBangRecord = oldCurrentBigBangRecord; MACHINE.params.currentOutputPort = oldOutputPort; + console.log('about to raise'); plt.baselib.exceptions.raise(MACHINE, exn); }); }); @@ -1235,15 +1241,11 @@ eventQueue.queue(new EventQueueElement(who, handler, args)); if (! dispatchingEvents) { dispatchingEvents = true; - setTimeout( - function() { - dispatchEventsInQueue( - function() { - refreshView(function() {}, onMessyRestart); - }, - onMessyRestart); - }, - 0); + dispatchEventsInQueue( + function() { + refreshView(function() {}, onMessyRestart); + }, + onMessyRestart); } }; handler.eventSource.onStart(fireEvent, internalCall, k); @@ -1255,6 +1257,7 @@ dispatchEventsInQueue = function(success, fail) { + console.log("dispatchEventsInQueue"); // Apply all the events on the queue, call toDraw, and then stop. // If the world ever satisfies stopWhen, stop immediately and quit. var nextEvent; @@ -1274,7 +1277,8 @@ racketWorldCallback = nextEvent.handler.racketWorldCallback; args = nextEvent.data.slice(0); var onGoodWorldUpdate = - function(newWorld) { + function (newWorld) { + console.log("good world update"); world = newWorld; stopWhen(internalCall, world, @@ -1290,23 +1294,29 @@ fail); }; if (isArityMatching(racketWorldCallback.racketArity, 1)) { + console.log("arity match 1"); racketWorldCallback(internalCall, world, onGoodWorldUpdate, fail); } else if (isArityMatching(racketWorldCallback.racketArity, 2)) { + console.log("arity match 2"); racketWorldCallback(internalCall, world, mockView, onGoodWorldUpdate, fail); - } else { + } else if (isArityMatching(racketWorldCallback.racketArity, 2 + args.length)){ + console.log("arity match 3"); args = ([internalCall, world, mockView] .concat(args) .concat([onGoodWorldUpdate, fail])); racketWorldCallback.apply(null, args); + } else { + fail(makeArityMismatchError(MACHINE, racketWorldCallback, 2+args.length)); } } else { + console.log("dispatched all events"); dispatchingEvents = false; success(); } @@ -1369,6 +1379,7 @@ success, fail].concat(args)); }; + f.displayName = proc.displayName; f.racketArity = proc.racketArity; return f; };