diff --git a/js-assembler/runtime-src/baselib-functions.js b/js-assembler/runtime-src/baselib-functions.js index ff98f23..0970d53 100644 --- a/js-assembler/runtime-src/baselib-functions.js +++ b/js-assembler/runtime-src/baselib-functions.js @@ -48,6 +48,12 @@ for (var i = 2; i < arguments.length; i++) { args.push(arguments[i]); } + + // Check arity usage. + if (! plt.baselib.arity.isArityMatching(v.arity, args.length)) { + throw new Error("arity mismatch"); + } + var result = v.apply(null, args); succ(result); } catch (e) { @@ -79,23 +85,29 @@ var oldErrorHandler = MACHINE.params['currentErrorHandler']; var afterGoodInvoke = function(MACHINE) { - MACHINE.params['currentErrorHandler'] = oldErrorHandler; - var returnValue = MACHINE.val; - MACHINE.val = oldVal; - MACHINE.argcount = oldArgcount; - MACHINE.proc = oldProc; - succ(returnValue); + plt.runtime.PAUSE( + function(restart) { + MACHINE.params['currentErrorHandler'] = oldErrorHandler; + var returnValue = MACHINE.val; + MACHINE.val = oldVal; + MACHINE.argcount = oldArgcount; + MACHINE.proc = oldProc; + succ(returnValue); + }); }; afterGoodInvoke.multipleValueReturn = function(MACHINE) { - MACHINE.params['currentErrorHandler'] = oldErrorHandler; - var returnValues = [MACHINE.val]; - for (var i = 0; i < MACHINE.argcount - 1; i++) { - returnValues.push(MACHINE.env.pop()); - } - MACHINE.val = oldVal; - MACHINE.argcount = oldArgcount; - MACHINE.proc = oldProc; - succ.apply(null, returnValues); + plt.runtime.PAUSE( + function(restart) { + MACHINE.params['currentErrorHandler'] = oldErrorHandler; + var returnValues = [MACHINE.val]; + for (var i = 0; i < MACHINE.argcount - 1; i++) { + returnValues.push(MACHINE.env.pop()); + } + MACHINE.val = oldVal; + MACHINE.argcount = oldArgcount; + MACHINE.proc = oldProc; + succ.apply(null, returnValues); + }); }; setTimeout( @@ -123,10 +135,13 @@ - // internallCall: call a Racket procedure and get its results. - // The use MUST be in the context of a closure call. This assumes that - // it is still in the context of the trampoline - var internalCall = function(MACHINE, proc, success, fail) { + // internallCallDuringPause: call a Racket procedure and get its results. + // The use assumes the machine is in a running-but-paused state. + var internalCallDuringPause = function(MACHINE, proc, success, fail) { + if (! plt.baselib.arity.isArityMatching(proc.arity, args.length)) { + return fail(plt.baselib.exceptions.makeExnFailContractArity("arity mismatch")); + } + if (isPrimitiveProcedure(proc)) { var args = []; for (var i = 4; i < arguments.length; i++) { @@ -135,13 +150,56 @@ var result = v.apply(null, args); succ(result); } else if (isClosure(v)) { - // FIXME + + var oldVal = MACHINE.val; + var oldArgcount = MACHINE.argcount; + var oldProc = MACHINE.proc; + + var oldErrorHandler = MACHINE.params['currentErrorHandler']; + var afterGoodInvoke = function(MACHINE) { + plt.runtime.PAUSE(function(restart) { + MACHINE.params['currentErrorHandler'] = oldErrorHandler; + var returnValue = MACHINE.val; + MACHINE.val = oldVal; + MACHINE.argcount = oldArgcount; + MACHINE.proc = oldProc; + succ(returnValue); + }); + }; + afterGoodInvoke.multipleValueReturn = function(MACHINE) { + plt.runtime.PAUSE(function(restart) { + MACHINE.params['currentErrorHandler'] = oldErrorHandler; + var returnValues = [MACHINE.val]; + for (var i = 0; i < MACHINE.argcount - 1; i++) { + returnValues.push(MACHINE.env.pop()); + } + MACHINE.val = oldVal; + MACHINE.argcount = oldArgcount; + MACHINE.proc = oldProc; + succ.apply(null, returnValues); + }); + }; + + MACHINE.control.push( + new plt.baselib.frames.CallFrame(afterGoodInvoke, null)); + MACHINE.argcount = args.length; + for (var i = 0; i < args.length; i++) { + MACHINE.env.push(args[i]); + } + MACHINE.proc = v; + MACHINE.params['currentErrorHandler'] = function(MACHINE, e) { + MACHINE.params['currentErrorHandler'] = oldErrorHandler; + MACHINE.val = oldVal; + MACHINE.argcount = oldArgcount; + MACHINE.proc = oldProc; + fail(e); + }; + plt.runtime.trampoline(MACHINE, v.label); } else { - plt.baselib.exceptions.raise(MACHINE, - plt.baselib.exceptions.makeExnFail( - plt.baselib.format.format( - "Not a procedure: ~e", - v))); + fail(plt.baselib.exceptions.makeExnFail( + plt.baselib.format.format( + "Not a procedure: ~e", + v))); } }; @@ -272,7 +330,7 @@ ////////////////////////////////////////////////////////////////////// exports.Closure = Closure; - exports.internalCall = internalCall; + exports.internalCallDuringPause = internalCallDuringPause; exports.finalizeClosureCall = finalizeClosureCall; exports.makePrimitiveProcedure = makePrimitiveProcedure; diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index 84d1268..41a7f40 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -404,7 +404,7 @@ if(this['plt'] === undefined) { this['plt'] = {}; } (new Date()).valueOf() - startTime); setTimeout( function() { trampoline(MACHINE, thunk); }, - 0); + 10); return; } else { continue; diff --git a/tests/coersing/Makefile b/tests/coersing/Makefile index a616d5b..17313e0 100644 --- a/tests/coersing/Makefile +++ b/tests/coersing/Makefile @@ -1,5 +1,5 @@ #!/bin/sh all: - ../../whalesong get-javascript --verbose --compress-javascript fact.rkt > fact.js - ../../whalesong get-runtime --verbose --compress-javascript > runtime.js + ../../whalesong get-javascript --verbose fact.rkt > fact.js + ../../whalesong get-runtime --verbose > runtime.js