diff --git a/broken-fact.rkt b/broken-fact.rkt new file mode 100644 index 0000000..d2ca022 --- /dev/null +++ b/broken-fact.rkt @@ -0,0 +1,9 @@ +#lang planet dyoo/whalesong + +(define (f x) + (if (= x 0) + "one" + (* x (f (sub1 x))))) + +(list (f 3) + (f 4)) diff --git a/js-assembler/runtime-src/baselib-check.js b/js-assembler/runtime-src/baselib-check.js index 99b93a5..c867ce1 100644 --- a/js-assembler/runtime-src/baselib-check.js +++ b/js-assembler/runtime-src/baselib-check.js @@ -121,10 +121,12 @@ var testArity = function (MACHINE, callerName, observed, minimum, maximum) { if (observed < minimum || observed > maximum) { baselib.exceptions.raise( - MACHINE, new Error(callerName + ": expected at least " + minimum - + " arguments " - + " but received " + observed)); - + MACHINE, + baselib.exceptions.ExnFailContractArity.constructor( + callerName + ": expected at least " + minimum + + " arguments " + + " but received " + observed, + MACHINE.captureContinuationMarks())); } }; diff --git a/js-assembler/runtime-src/baselib-exceptions.js b/js-assembler/runtime-src/baselib-exceptions.js index 7b88615..ea22c6d 100644 --- a/js-assembler/runtime-src/baselib-exceptions.js +++ b/js-assembler/runtime-src/baselib-exceptions.js @@ -65,6 +65,8 @@ var raise = function(MACHINE, e) { if (isRacketError(e) && Exn.predicate(e.racketError)) { e.message = Exn.accessor(e.racketError, 0); + } else if (Exn.predicate(e)) { + e = new RacketError(Exn.accessor(e, 0), e); } if (typeof(window.console) !== 'undefined' && @@ -83,11 +85,9 @@ var message = baselib.format.format("Not bound: ~a", [name]); var contMarks = MACHINE.captureContinuationMarks(); raise(MACHINE, - new RacketError( - message, - ExnFailContractVariable.constructor(message, - contMarks, - baselib.symbols.makeSymbol(name)))); + ExnFailContractVariable.constructor(message, + contMarks, + baselib.symbols.makeSymbol(name))); }; @@ -105,16 +105,14 @@ expectedTypeName, (argumentOffset + 1), actualValue]); - raise(MACHINE, new RacketError(message, - ExnFailContract.constructor(message, contMarks))); + raise(MACHINE, ExnFailContract.constructor(message, contMarks)); } else { message = baselib.format.format( "~a: expected ~a but received ~e", [callerName, expectedTypeName, actualValue]); - raise(MACHINE, new RacketError(message, - ExnFailContract.constructor(message, contMarks))); + raise(MACHINE, ExnFailContract.constructor(message, contMarks)); } }; @@ -122,9 +120,7 @@ var message = baselib.format.format("expected ~e values, received ~e values", [expected, MACHINE.argcount]); var contMarks = MACHINE.captureContinuationMarks(); - raise(MACHINE, - new RacketError(message, - ExnFailContract.constructor(message, contMarks))); + raise(MACHINE, ExnFailContract.constructor(message, contMarks)); }; var raiseArityMismatchError = function(MACHINE, proc, expected, received) { @@ -133,8 +129,7 @@ expected, received]); raise(MACHINE, - new RacketError(message, - ExnFailContractArity.constructor(message, contMarks))); + ExnFailContractArity.constructor(message, contMarks)); }; var raiseOperatorApplicationError = function(MACHINE, operator) { @@ -142,8 +137,7 @@ [operator]); var contMarks = MACHINE.captureContinuationMarks(); raise(MACHINE, - new RacketError(message, - ExnFailContract.constructor(message, contMarks))); + ExnFailContract.constructor(message, contMarks)); }; var raiseOperatorIsNotClosure = function(MACHINE, operator) { @@ -151,8 +145,7 @@ [operator]); var contMarks = MACHINE.captureContinuationMarks(); raise(MACHINE, - new RacketError(message, - ExnFailContract.constructor(message, contMarks))); + ExnFailContract.constructor(message, contMarks)); }; var raiseOperatorIsNotPrimitiveProcedure = function(MACHINE, operator) { @@ -160,16 +153,15 @@ [operator]); var contMarks = MACHINE.captureContinuationMarks(); raise(MACHINE, - new RacketError(message, - ExnFailContract.constructor(message, contMarks))); + ExnFailContract.constructor(message, contMarks)); }; var raiseUnimplementedPrimitiveError = function(MACHINE, name) { var message = "unimplemented kernel procedure: " + name; var contMarks = MACHINE.captureContinuationMarks(); - raise(MACHINE, new RacketError(message, - ExnFailContract.constructor(message, contMarks))); + raise(MACHINE, + ExnFailContract.constructor(message, contMarks)); }; diff --git a/js-assembler/runtime-src/baselib-functions.js b/js-assembler/runtime-src/baselib-functions.js index 5b8dac9..e146006 100644 --- a/js-assembler/runtime-src/baselib-functions.js +++ b/js-assembler/runtime-src/baselib-functions.js @@ -212,10 +212,11 @@ return coerseClosureToJavaScript(v, MACHINE); } else { baselib.exceptions.raise(MACHINE, - baselib.exceptions.makeExnFail( - baselib.format.format( - "Not a procedure: ~e", - v))); + baselib.exceptions.makeExnFailContract( + baselib.format.format( + "Not a procedure: ~e", + v), + MACHINE.captureContinuationMarks())); } }; diff --git a/js-assembler/runtime-src/baselib-primitives.js b/js-assembler/runtime-src/baselib-primitives.js index 036649d..8251351 100644 --- a/js-assembler/runtime-src/baselib-primitives.js +++ b/js-assembler/runtime-src/baselib-primitives.js @@ -1465,8 +1465,8 @@ var i; if (MACHINE.argcount === 1) { var sym = checkSymbol(MACHINE, 'error', 1); - // FIXME: we should collect the current continuation marks here... - raise(MACHINE, baselib.exceptions.makeExnFail(String(sym), undefined)); + raise(MACHINE, baselib.exceptions.makeExnFail(String(sym), + MACHINE.captureContinuationMarks())); } if (isString(MACHINE.env[MACHINE.env.length - 1])) { @@ -1477,7 +1477,7 @@ raise(MACHINE, baselib.exceptions.makeExnFail(String(MACHINE.env[MACHINE.env.length - 1]) + ": " + vs.join(' '), - undefined)); + MACHINE.captureContinuationMarks())); } if (isSymbol(MACHINE.env[MACHINE.env.length - 1])) { @@ -1489,7 +1489,7 @@ raise(MACHINE, baselib.exceptions.makeExnFail( baselib.format.format('~s: ' + String(fmtString), args), - undefined)); + MACHINE.captureContinuationMarks())); } // Fall-through @@ -1509,7 +1509,7 @@ [name, message, val]), - undefined)); + MACHINE.captureContinuationMarks())); });