diff --git a/examples/logo.rkt b/examples/logo.rkt new file mode 100644 index 0000000..3b150ca --- /dev/null +++ b/examples/logo.rkt @@ -0,0 +1,5 @@ +#lang planet dyoo/whalesong + +(require (planet dyoo/whalesong/image)) + +(image-url "http://racket-lang.org/logo.png") diff --git a/image/private/js-impl.js b/image/private/js-impl.js index 571c504..b3a65ae 100644 --- a/image/private/js-impl.js +++ b/image/private/js-impl.js @@ -1,10 +1,6 @@ -var checkString = plt.baselib.check.makeCheckArgumentType( - plt.baselib.strings.isString, - 'string'); - -var checkByte = plt.baselib.check.makeCheckArgumentType( - plt.baselib.numbers.isByte, - 'byte'); +var checkString = plt.baselib.check.checkString; +var checkByte = plt.baselib.check.checkByte; +var checkReal = plt.baselib.check.checkReal; var checkColor = plt.baselib.check.makeCheckArgumentType( isColorOrColorString, @@ -14,9 +10,9 @@ var checkImage = plt.baselib.check.makeCheckArgumentType( isImage, 'image'); -var checkReal = plt.baselib.check.makeCheckArgumentType( - plt.baselib.numbers.isReal, - 'real'); + +var Closure = plt.baselib.functions.Closure; +var PAUSE = plt.runtime.PAUSE; @@ -34,7 +30,6 @@ EXPORTS['image-color?'] = - EXPORTS['text'] = plt.baselib.functions.makePrimitiveProcedure( 'text', @@ -60,20 +55,44 @@ EXPORTS['text'] = // ... // }); -// FIXME -// EXPORTS['image-url'] = -// plt.baselib.functions.makePrimitiveProcedure( -// 'image-url', -// ???, -// function(MACHINE) { -// ... -// }); // FIXME +EXPORTS['image-url'] = + new Closure( + function(MACHINE) { + var url = checkString(MACHINE, 'image-url', 0); + PAUSE(function(restart) { + var rawImage = new Image(); + rawImage.onload = function() { + restart(function(MACHINE) { + finalizeClosureCall( + makeFileImage( + path.toString(), + rawImage)); + }) + }); + rawImage.onerror = + (function(e) { + restart(function(MACHINE) { + plt.baselib.exceptions.raise( + MACHINE, + new Error(plt.baselib.format.format( + "unable to load: ~a", + url))); + }); + }); + rawImage.src = path.toString(); + ); + }, + 1, + [], + 'image-url'); + +// // FIXME // EXPORTS['open-image-url'] = // plt.baselib.functions.makePrimitiveProcedure( // 'open-image-url', -// ???, +// 1, // function(MACHINE) { // ... // }); diff --git a/js-assembler/package.rkt b/js-assembler/package.rkt index afa6f94..b859b68 100644 --- a/js-assembler/package.rkt +++ b/js-assembler/package.rkt @@ -210,7 +210,7 @@ MACHINE.modules[~s] = (define (on-visit-src src ast stmts) (cond [(UninterpretedSource? src) - (fprintf op (UninterpretedSource-datum src))] + (fprintf op "~a" (UninterpretedSource-datum src))] [else (assemble/write-invoke stmts op) (fprintf op "(MACHINE, function() { ")])) diff --git a/js-assembler/runtime-src/baselib-check.js b/js-assembler/runtime-src/baselib-check.js index 7f52175..24249c8 100644 --- a/js-assembler/runtime-src/baselib-check.js +++ b/js-assembler/runtime-src/baselib-check.js @@ -113,6 +113,11 @@ 'inspector'); + var checkByte = makeCheckArgumentType( + plt.baselib.numbers.isByte, + 'byte'); + + @@ -138,7 +143,7 @@ exports.checkBox = checkBox; exports.checkMutableBox = checkMutableBox; exports.checkInspector = checkInspector; - + exports.checkByte = checkByte; })(this['plt'].baselib); \ No newline at end of file diff --git a/js-assembler/runtime-src/baselib-exceptions.js b/js-assembler/runtime-src/baselib-exceptions.js index 6c25bd5..fbd00f5 100644 --- a/js-assembler/runtime-src/baselib-exceptions.js +++ b/js-assembler/runtime-src/baselib-exceptions.js @@ -156,44 +156,45 @@ exceptions.IncompleteExn = IncompleteExn; - exceptions.incompleteExn = function(constructor, msg, args) { return new IncompleteExn(constructor, msg, args); }; + exceptions.makeIncompleteExn = function(constructor, msg, args) { return new IncompleteExn(constructor, msg, args); }; exceptions.isIncompleteExn = function(x) { return x instanceof IncompleteExn; }; exceptions.Exn = Exn; - exceptions.exn = Exn.constructor; + exceptions.makeExn = Exn.constructor; exceptions.isExn = Exn.predicate; exceptions.exnMessage = function(exn) { return Exn.accessor(exn, 0); }; exceptions.exnContMarks = function(exn) { return Exn.accessor(exn, 1); }; exceptions.exnSetContMarks = function(exn, v) { Exn.mutator(exn, 1, v); }; exceptions.ExnBreak = ExnBreak; - exceptions.exnBreak = ExnBreak.constructor; + exceptions.makeExnBreak = ExnBreak.constructor; exceptions.isExnBreak = ExnBreak.predicate; exceptions.exnBreakContinuation = function(exn) { return ExnBreak.accessor(exn, 0); }; exceptions.ExnFail = ExnFail; - exceptions.exnFail = ExnFail.constructor; + exceptions.makeExnFail = ExnFail.constructor; exceptions.isExnFail = ExnFail.predicate; exceptions.ExnFailContract = ExnFailContract; - exceptions.exnFailContract = ExnFailContract.constructor; + exceptions.makeExnFailContract = ExnFailContract.constructor; exceptions.isExnFailContract = ExnFailContract.predicate; exceptions.ExnFailContractArity = ExnFailContractArity; - exceptions.exnFailContractArity = ExnFailContractArity.constructor; + exceptions.makeExnFailContractArity = ExnFailContractArity.constructor; exceptions.isExnFailContractArity = ExnFailContractArity.predicate; exceptions.ExnFailContractVariable = ExnFailContractVariable; - exceptions.exnFailContractVariable = ExnFailContractVariable.constructor; + exceptions.makeExnFailContractVariable = ExnFailContractVariable.constructor; exceptions.isExnFailContractVariable = ExnFailContractVariable.predicate; exceptions.exnFailContractVariableId = function(exn) { return ExnFailContractVariable.accessor(exn, 0); }; exceptions.ExnFailContractDivisionByZero = ExnFailContractDivisionByZero; - exceptions.exnFailContractDivisionByZero = ExnFailContractDivisionByZero.constructor; + exceptions.makeExnFailContractDivisionByZero = + ExnFailContractDivisionByZero.constructor; exceptions.isExnFailContractDivisionByZero = ExnFailContractDivisionByZero.predicate; diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index e148446..46cd374 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -333,6 +333,18 @@ if(this['plt'] === undefined) { this['plt'] = {}; } }; + var Pause = function(onPause) { + // onPause: MACHINE -> void + this.onPause = onPause || function(MACHINE) {}; + }; + + var PAUSE = function(onPause) { + throw new Pause(onPause); + } + + + + ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// @@ -361,15 +373,23 @@ if(this['plt'] === undefined) { this['plt'] = {}; } // There are a few kinds of things that can get thrown // during racket evaluation: // - // functions: this gets thrown if the Racket code realizes - // that the number of bounces has grown too large. The thrown - // function represents a restarter function. + // functions: this gets thrown if the Racket code + // realizes that the number of bounces has grown too + // large. The thrown function represents a restarter + // function. The running flag remains true. // - // HaltError: causes evaluation to immediately halt. We schedule - // the onHalt function of the HaltError to call afterwards. + // Pause: causes the machine evaluation to pause, with + // the expectation that it will restart momentarily. + // The running flag on the machine will remain true. // - // everything else: otherwise, we send the exception value + // HaltError: causes evaluation to immediately halt. + // We schedule the onHalt function of the HaltError to + // call afterwards. The running flag on the machine + // is set to false. + // + // Everything else: otherwise, we send the exception value // to the current error handler and exit. + // The running flag is set to false. if (typeof(e) === 'function') { thunk = e; MACHINE.callsBeforeTrampoline = STACK_LIMIT_ESTIMATE; @@ -385,7 +405,19 @@ if(this['plt'] === undefined) { this['plt'] = {}; } } else { continue; } - } else if (e instanceof HaltError) { + } else if (e instanceof Pause) { + var restart = function(thunk) { + setTimeout( + function() { trampoline(MACHINE, thunk); }, + 0); + }; + setTimeout( + function() { + e.onPause(restart); + }, + 0); + return; + } else if (e instanceof HaltError) { MACHINE.running = false; setTimeout( function() { e.onHalt(MACHINE); }, @@ -1922,6 +1954,7 @@ if(this['plt'] === undefined) { this['plt'] = {}; } exports['heir'] = heir; exports['makeClassPredicate'] = makeClassPredicate; + exports['PAUSE'] = PAUSE; exports['HaltError'] = HaltError;