From e0f2502b18e2371cacf5f84be80b8bc74f65c4b4 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Wed, 14 Sep 2011 23:42:24 -0400 Subject: [PATCH 01/22] renaming control to c --- js-assembler/assemble-helpers.rkt | 6 ++--- js-assembler/assemble-perform-statement.rkt | 4 ++-- js-assembler/assemble.rkt | 8 +++---- js-assembler/package.rkt | 2 +- js-assembler/runtime-src/baselib-functions.js | 12 +++++----- js-assembler/runtime-src/baselib-modules.js | 2 +- js-assembler/runtime-src/runtime.js | 22 +++++++++---------- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/js-assembler/assemble-helpers.rkt b/js-assembler/assemble-helpers.rkt index e0cb282..504a735 100644 --- a/js-assembler/assemble-helpers.rkt +++ b/js-assembler/assemble-helpers.rkt @@ -103,7 +103,7 @@ (: assemble-control-frame-temporary (ControlFrameTemporary -> String)) (define (assemble-control-frame-temporary t) - (format "M.control[M.control.length-1].~a" + (format "M.c[M.c.length-1].~a" (ControlFrameTemporary-name t))) ;; fixme: use js->string @@ -313,12 +313,12 @@ (: assemble-control-stack-label (ControlStackLabel -> String)) (define (assemble-control-stack-label a-csl) - "M.control[M.control.length-1].label") + "M.c[M.c.length-1].label") (: assemble-control-stack-label/multiple-value-return (ControlStackLabel/MultipleValueReturn -> String)) (define (assemble-control-stack-label/multiple-value-return a-csl) - "M.control[M.control.length-1].label.mvr") + "M.c[M.c.length-1].label.mvr") diff --git a/js-assembler/assemble-perform-statement.rkt b/js-assembler/assemble-perform-statement.rkt index af19019..f7fa8ec 100644 --- a/js-assembler/assemble-perform-statement.rkt +++ b/js-assembler/assemble-perform-statement.rkt @@ -98,7 +98,7 @@ ","))] [(SetFrameCallee!? op) - (format "M.control[M.control.length-1].proc=~a;" + (format "M.c[M.c.length-1].proc=~a;" (assemble-oparg (SetFrameCallee!-proc op)))] [(SpliceListIntoStack!? op) @@ -112,7 +112,7 @@ [(InstallContinuationMarkEntry!? op) (string-append "M.installContinuationMarkEntry(" - "M.control[M.control.length-1].pendingContinuationMarkKey," + "M.c[M.c.length-1].pendingContinuationMarkKey," "M.val);")] [(RaiseContextExpectedValuesError!? op) diff --git a/js-assembler/assemble.rkt b/js-assembler/assemble.rkt index c4b510b..58d4c35 100644 --- a/js-assembler/assemble.rkt +++ b/js-assembler/assemble.rkt @@ -483,10 +483,10 @@ EOF (assemble-jump (GotoStatement-target stmt))] [(PushControlFrame/Generic? stmt) - "M.control.push(new RT.Frame());"] + "M.c.push(new RT.Frame());"] [(PushControlFrame/Call? stmt) - (format "M.control.push(new RT.CallFrame(~a,M.proc));" + (format "M.c.push(new RT.CallFrame(~a,M.proc));" (let: ([label : (U Symbol LinkedLabel) (PushControlFrame/Call-label stmt)]) (cond [(symbol? label) @@ -496,7 +496,7 @@ EOF [(PushControlFrame/Prompt? stmt) ;; fixme: use a different frame structure - (format "M.control.push(new RT.PromptFrame(~a,~a));" + (format "M.c.push(new RT.PromptFrame(~a,~a));" (let: ([label : (U Symbol LinkedLabel) (PushControlFrame/Prompt-label stmt)]) (cond [(symbol? label) @@ -513,7 +513,7 @@ EOF (assemble-oparg tag)])))] [(PopControlFrame? stmt) - "M.control.pop();"] + "M.c.pop();"] [(PushEnvironment? stmt) (cond [(= (PushEnvironment-n stmt) 0) diff --git a/js-assembler/package.rkt b/js-assembler/package.rkt index 68b8d99..211ca0e 100644 --- a/js-assembler/package.rkt +++ b/js-assembler/package.rkt @@ -164,7 +164,7 @@ (function(MACHINE, EXPORTS){~a})(M, exports); ~a modrec.privateExports = exports; - return M.control.pop().label(M);" + return M.c.pop().label(M);" (symbol->string name) text (get-provided-name-code bytecode))]) diff --git a/js-assembler/runtime-src/baselib-functions.js b/js-assembler/runtime-src/baselib-functions.js index 9ff0eee..e58732d 100644 --- a/js-assembler/runtime-src/baselib-functions.js +++ b/js-assembler/runtime-src/baselib-functions.js @@ -69,15 +69,15 @@ if (returnArgs.length === 1) { MACHINE.val = returnArgs[0]; - return MACHINE.control.pop().label(MACHINE); + return MACHINE.c.pop().label(MACHINE); } else if (returnArgs.length === 0) { MACHINE.a = 0; - return MACHINE.control.pop().label.mvr(MACHINE); + return MACHINE.c.pop().label.mvr(MACHINE); } else { MACHINE.a = returnArgs.length; MACHINE.val = returnArgs.shift(); MACHINE.e.push.apply(MACHINE.e, returnArgs.reverse()); - return MACHINE.control.pop().label.mvr(MACHINE); + return MACHINE.c.pop().label.mvr(MACHINE); } }; @@ -179,7 +179,7 @@ }); }; - MACHINE.control.push( + MACHINE.c.push( new baselib.frames.CallFrame(afterGoodInvoke, v)); MACHINE.a = arguments.length - 2; var i; @@ -276,7 +276,7 @@ }); }; - MACHINE.control.push( + MACHINE.c.push( new baselib.frames.CallFrame(afterGoodInvoke, proc)); MACHINE.a = arguments.length - 4; for (i = 0; i < arguments.length - 4; i++) { @@ -326,7 +326,7 @@ --M.cbt; M.val = f(M); M.e.length -= M.a; - return M.control.pop().label(M); + return M.c.pop().label(M); }, []); }; diff --git a/js-assembler/runtime-src/baselib-modules.js b/js-assembler/runtime-src/baselib-modules.js index ee98f15..15aa6af 100644 --- a/js-assembler/runtime-src/baselib-modules.js +++ b/js-assembler/runtime-src/baselib-modules.js @@ -66,7 +66,7 @@ MACHINE.params['currentErrorHandler'] = oldErrorHandler; fail(MACHINE, anError); }; - MACHINE.control.push(new plt.baselib.frames.CallFrame(afterGoodInvoke, null)); + MACHINE.c.push(new plt.baselib.frames.CallFrame(afterGoodInvoke, null)); if (isInternal) { throw that.label; } else { diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index 674a8d1..1a200cd 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -216,7 +216,7 @@ this.proc = undefined; // procedure register this.a = undefined; // argument count this.e = []; // environment - this.control = []; // control: Arrayof (U Frame CallFrame PromptFrame) + this.c = []; // control: Arrayof (U Frame CallFrame PromptFrame) this.running = false; this.modules = {}; // String -> ModuleRecord this.mainModules = []; // Arrayof String @@ -293,10 +293,10 @@ Machine.prototype.captureControl = function(skip, tag) { var MACHINE = this; var i; - for (i = MACHINE.control.length - 1 - skip; i >= 0; i--) { - if (MACHINE.control[i].tag === tag) { - return MACHINE.control.slice(i + 1, - MACHINE.control.length - skip); + for (i = MACHINE.c.length - 1 - skip; i >= 0; i--) { + if (MACHINE.c[i].tag === tag) { + return MACHINE.c.slice(i + 1, + MACHINE.c.length - skip); } } raise(MACHINE, new Error("captureControl: unable to find tag " + tag)); @@ -311,10 +311,10 @@ Machine.prototype.restoreControl = function(tag) { var MACHINE = this; var i; - for (i = MACHINE.control.length - 1; i >= 0; i--) { - if (MACHINE.control[i].tag === tag) { - MACHINE.control = - MACHINE.control.slice(0, i+1).concat( + for (i = MACHINE.c.length - 1; i >= 0; i--) { + if (MACHINE.c[i].tag === tag) { + MACHINE.c = + MACHINE.c.slice(0, i+1).concat( MACHINE.e[MACHINE.e.length - 1]); return; } @@ -359,7 +359,7 @@ // Save the continuation mark on the top control frame. Machine.prototype.installContinuationMarkEntry = function(key, value) { - var frame = this.control[this.control.length - 1]; + var frame = this.c[this.c.length - 1]; var marks = frame.marks; var i; for (i = 0; i < marks.length; i++) { @@ -375,7 +375,7 @@ Machine.prototype.captureContinuationMarks = function() { var kvLists = []; var i; - var control = this.control; + var control = this.c; var tracedCalleeKey = getTracedCalleeKey(this); for (i = control.length-1; i >= 0; i--) { if (control[i].marks.length !== 0) { From a107d83827c24f49e603fa4a61dcee558286587b Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Wed, 14 Sep 2011 23:50:02 -0400 Subject: [PATCH 02/22] renamed proc to p --- js-assembler/assemble-expression.rkt | 2 +- js-assembler/assemble-helpers.rkt | 4 ++-- js-assembler/assemble-perform-statement.rkt | 4 ++-- js-assembler/assemble.rkt | 2 +- js-assembler/runtime-src/baselib-frames.js | 2 +- js-assembler/runtime-src/baselib-functions.js | 20 +++++++++---------- .../runtime-src/baselib-primitives.js | 2 +- js-assembler/runtime-src/runtime.js | 14 ++++++------- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/js-assembler/assemble-expression.rkt b/js-assembler/assemble-expression.rkt index 86233be..7d44e89 100644 --- a/js-assembler/assemble-expression.rkt +++ b/js-assembler/assemble-expression.rkt @@ -14,7 +14,7 @@ (define (assemble-op-expression op) (cond [(GetCompiledProcedureEntry? op) - "M.proc.label"] + "M.p.label"] [(MakeCompiledProcedure? op) (format "new RT.Closure(~a,~a,[~a],~a)" diff --git a/js-assembler/assemble-helpers.rkt b/js-assembler/assemble-helpers.rkt index 504a735..5fb7ae8 100644 --- a/js-assembler/assemble-helpers.rkt +++ b/js-assembler/assemble-helpers.rkt @@ -83,7 +83,7 @@ (format "~a=~a;" (cond [(eq? target 'proc) - "M.proc"] + "M.p"] [(eq? target 'val) "M.val"] [(eq? target 'argcount) @@ -279,7 +279,7 @@ (let ([name (Reg-name a-reg)]) (cond [(eq? name 'proc) - "M.proc"] + "M.p"] [(eq? name 'val) "M.val"] [(eq? name 'argcount) diff --git a/js-assembler/assemble-perform-statement.rkt b/js-assembler/assemble-perform-statement.rkt index f7fa8ec..ca35653 100644 --- a/js-assembler/assemble-perform-statement.rkt +++ b/js-assembler/assemble-perform-statement.rkt @@ -70,7 +70,7 @@ ",")))] [(InstallClosureValues!? op) - "M.e.push.apply(M.e,M.proc.closedVals);"] + "M.e.push.apply(M.e,M.p.closedVals);"] [(RestoreEnvironment!? op) "M.e=M.e[M.e.length-2].slice(0);"] @@ -98,7 +98,7 @@ ","))] [(SetFrameCallee!? op) - (format "M.c[M.c.length-1].proc=~a;" + (format "M.c[M.c.length-1].p=~a;" (assemble-oparg (SetFrameCallee!-proc op)))] [(SpliceListIntoStack!? op) diff --git a/js-assembler/assemble.rkt b/js-assembler/assemble.rkt index 58d4c35..8490551 100644 --- a/js-assembler/assemble.rkt +++ b/js-assembler/assemble.rkt @@ -486,7 +486,7 @@ EOF "M.c.push(new RT.Frame());"] [(PushControlFrame/Call? stmt) - (format "M.c.push(new RT.CallFrame(~a,M.proc));" + (format "M.c.push(new RT.CallFrame(~a,M.p));" (let: ([label : (U Symbol LinkedLabel) (PushControlFrame/Call-label stmt)]) (cond [(symbol? label) diff --git a/js-assembler/runtime-src/baselib-frames.js b/js-assembler/runtime-src/baselib-frames.js index eb5e7ac..f2f0848 100644 --- a/js-assembler/runtime-src/baselib-frames.js +++ b/js-assembler/runtime-src/baselib-frames.js @@ -31,7 +31,7 @@ // as well as the function being called. var CallFrame = function(label, proc) { this.label = label; - this.proc = proc; + this.p = proc; // The set of continuation marks. this.marks = []; diff --git a/js-assembler/runtime-src/baselib-functions.js b/js-assembler/runtime-src/baselib-functions.js index e58732d..4403eee 100644 --- a/js-assembler/runtime-src/baselib-functions.js +++ b/js-assembler/runtime-src/baselib-functions.js @@ -150,7 +150,7 @@ var oldVal = MACHINE.val; var oldArgcount = MACHINE.a; - var oldProc = MACHINE.proc; + var oldProc = MACHINE.p; var oldErrorHandler = MACHINE.params['currentErrorHandler']; var afterGoodInvoke = function (MACHINE) { @@ -160,7 +160,7 @@ var returnValue = MACHINE.val; MACHINE.val = oldVal; MACHINE.a = oldArgcount; - MACHINE.proc = oldProc; + MACHINE.p = oldProc; succ(returnValue); }); }; @@ -174,7 +174,7 @@ } MACHINE.val = oldVal; MACHINE.a = oldArgcount; - MACHINE.proc = oldProc; + MACHINE.p = oldProc; succ.apply(null, returnValues); }); }; @@ -186,12 +186,12 @@ for (i = 0; i < arguments.length - 2; i++) { MACHINE.e.push(arguments[arguments.length - 1 - i]); } - MACHINE.proc = v; + MACHINE.p = v; MACHINE.params['currentErrorHandler'] = function (MACHINE, e) { MACHINE.params['currentErrorHandler'] = oldErrorHandler; MACHINE.val = oldVal; MACHINE.a = oldArgcount; - MACHINE.proc = oldProc; + MACHINE.p = oldProc; fail(e); }; MACHINE.trampoline(v.label); @@ -248,7 +248,7 @@ } else if (isClosure(proc)) { oldVal = MACHINE.val; oldArgcount = MACHINE.a; - oldProc = MACHINE.proc; + oldProc = MACHINE.p; oldErrorHandler = MACHINE.params['currentErrorHandler']; var afterGoodInvoke = function (MACHINE) { @@ -257,7 +257,7 @@ var returnValue = MACHINE.val; MACHINE.val = oldVal; MACHINE.a = oldArgcount; - MACHINE.proc = oldProc; + MACHINE.p = oldProc; success(returnValue); }); }; @@ -271,7 +271,7 @@ } MACHINE.val = oldVal; MACHINE.a = oldArgcount; - MACHINE.proc = oldProc; + MACHINE.p = oldProc; success.apply(null, returnValues); }); }; @@ -282,12 +282,12 @@ for (i = 0; i < arguments.length - 4; i++) { MACHINE.e.push(arguments[arguments.length - 1 - i]); } - MACHINE.proc = proc; + MACHINE.p = proc; MACHINE.params['currentErrorHandler'] = function (MACHINE, e) { MACHINE.params['currentErrorHandler'] = oldErrorHandler; MACHINE.val = oldVal; MACHINE.a = oldArgcount; - MACHINE.proc = oldProc; + MACHINE.p = oldProc; fail(e); }; MACHINE.trampoline(proc.label); diff --git a/js-assembler/runtime-src/baselib-primitives.js b/js-assembler/runtime-src/baselib-primitives.js index 7ebe65f..23b12e3 100644 --- a/js-assembler/runtime-src/baselib-primitives.js +++ b/js-assembler/runtime-src/baselib-primitives.js @@ -1150,7 +1150,7 @@ checkList(M, 'apply', M.a - 1); M.spliceListIntoStack(M.a - 1); if (baselib.arity.isArityMatching(proc.racketArity, M.a)) { - M.proc = proc; + M.p = proc; if (baselib.functions.isPrimitiveProcedure(proc)) { return finalizeClosureCall(M, proc(M)); } else { diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index 1a200cd..b1a1135 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -213,7 +213,7 @@ var Machine = function() { this.cbt = STACK_LIMIT_ESTIMATE; // calls before trampoline this.val = undefined; // value register - this.proc = undefined; // procedure register + this.p = undefined; // procedure register this.a = undefined; // argument count this.e = []; // environment this.c = []; // control: Arrayof (U Frame CallFrame PromptFrame) @@ -384,8 +384,8 @@ if (tracedCalleeKey !== null && control[i] instanceof CallFrame && - control[i].proc !== null) { - kvLists.push([[tracedCalleeKey, control[i].proc]]); + control[i].p !== null) { + kvLists.push([[tracedCalleeKey, control[i].p]]); } } return new baselib.contmarks.ContinuationMarkSet(kvLists); @@ -656,11 +656,11 @@ var checkClosureAndArity = function(M) { - if(!(M.proc instanceof Closure)){ - raiseOperatorIsNotClosure(M,M.proc); + if(!(M.p instanceof Closure)){ + raiseOperatorIsNotClosure(M,M.p); } - if(!isArityMatching(M.proc.racketArity,M.a)) { - raiseArityMismatchError(M, M.proc,M.a); + if(!isArityMatching(M.p.racketArity,M.a)) { + raiseArityMismatchError(M,M.p,M.a); } }; From 7de6e18d3fdc04c5ee9ec329439c1d07b412834c Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Thu, 15 Sep 2011 00:03:24 -0400 Subject: [PATCH 03/22] renamed val to v --- js-assembler/assemble-helpers.rkt | 4 +-- js-assembler/assemble-perform-statement.rkt | 2 +- js-assembler/runtime-src/baselib-functions.js | 30 +++++++++---------- js-assembler/runtime-src/runtime.js | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/js-assembler/assemble-helpers.rkt b/js-assembler/assemble-helpers.rkt index 5fb7ae8..6b0f6fc 100644 --- a/js-assembler/assemble-helpers.rkt +++ b/js-assembler/assemble-helpers.rkt @@ -85,7 +85,7 @@ [(eq? target 'proc) "M.p"] [(eq? target 'val) - "M.val"] + "M.v"] [(eq? target 'argcount) "M.a"] [(EnvLexicalReference? target) @@ -281,7 +281,7 @@ [(eq? name 'proc) "M.p"] [(eq? name 'val) - "M.val"] + "M.v"] [(eq? name 'argcount) "M.a"]))) diff --git a/js-assembler/assemble-perform-statement.rkt b/js-assembler/assemble-perform-statement.rkt index ca35653..10ea4ea 100644 --- a/js-assembler/assemble-perform-statement.rkt +++ b/js-assembler/assemble-perform-statement.rkt @@ -113,7 +113,7 @@ [(InstallContinuationMarkEntry!? op) (string-append "M.installContinuationMarkEntry(" "M.c[M.c.length-1].pendingContinuationMarkKey," - "M.val);")] + "M.v);")] [(RaiseContextExpectedValuesError!? op) (format "RT.raiseContextExpectedValuesError(M,~a);" diff --git a/js-assembler/runtime-src/baselib-functions.js b/js-assembler/runtime-src/baselib-functions.js index 4403eee..3cdb988 100644 --- a/js-assembler/runtime-src/baselib-functions.js +++ b/js-assembler/runtime-src/baselib-functions.js @@ -68,14 +68,14 @@ MACHINE.e.length -= MACHINE.a; if (returnArgs.length === 1) { - MACHINE.val = returnArgs[0]; + MACHINE.v = returnArgs[0]; return MACHINE.c.pop().label(MACHINE); } else if (returnArgs.length === 0) { MACHINE.a = 0; return MACHINE.c.pop().label.mvr(MACHINE); } else { MACHINE.a = returnArgs.length; - MACHINE.val = returnArgs.shift(); + MACHINE.v = returnArgs.shift(); MACHINE.e.push.apply(MACHINE.e, returnArgs.reverse()); return MACHINE.c.pop().label.mvr(MACHINE); } @@ -148,7 +148,7 @@ MACHINE.captureContinuationMarks()))); } - var oldVal = MACHINE.val; + var oldVal = MACHINE.v; var oldArgcount = MACHINE.a; var oldProc = MACHINE.p; @@ -157,8 +157,8 @@ plt.runtime.PAUSE( function (restart) { MACHINE.params['currentErrorHandler'] = oldErrorHandler; - var returnValue = MACHINE.val; - MACHINE.val = oldVal; + var returnValue = MACHINE.v; + MACHINE.v = oldVal; MACHINE.a = oldArgcount; MACHINE.p = oldProc; succ(returnValue); @@ -168,11 +168,11 @@ plt.runtime.PAUSE( function (restart) { MACHINE.params['currentErrorHandler'] = oldErrorHandler; - var returnValues = [MACHINE.val], i; + var returnValues = [MACHINE.v], i; for (i = 0; i < MACHINE.a - 1; i++) { returnValues.push(MACHINE.e.pop()); } - MACHINE.val = oldVal; + MACHINE.v = oldVal; MACHINE.a = oldArgcount; MACHINE.p = oldProc; succ.apply(null, returnValues); @@ -189,7 +189,7 @@ MACHINE.p = v; MACHINE.params['currentErrorHandler'] = function (MACHINE, e) { MACHINE.params['currentErrorHandler'] = oldErrorHandler; - MACHINE.val = oldVal; + MACHINE.v = oldVal; MACHINE.a = oldArgcount; MACHINE.p = oldProc; fail(e); @@ -246,7 +246,7 @@ } success(result); } else if (isClosure(proc)) { - oldVal = MACHINE.val; + oldVal = MACHINE.v; oldArgcount = MACHINE.a; oldProc = MACHINE.p; @@ -254,8 +254,8 @@ var afterGoodInvoke = function (MACHINE) { plt.runtime.PAUSE(function (restart) { MACHINE.params['currentErrorHandler'] = oldErrorHandler; - var returnValue = MACHINE.val; - MACHINE.val = oldVal; + var returnValue = MACHINE.v; + MACHINE.v = oldVal; MACHINE.a = oldArgcount; MACHINE.p = oldProc; success(returnValue); @@ -264,12 +264,12 @@ afterGoodInvoke.mvr = function (MACHINE) { plt.runtime.PAUSE(function (restart) { MACHINE.params['currentErrorHandler'] = oldErrorHandler; - var returnValues = [MACHINE.val]; + var returnValues = [MACHINE.v]; var i; for (i = 0; i < MACHINE.a - 1; i++) { returnValues.push(MACHINE.e.pop()); } - MACHINE.val = oldVal; + MACHINE.v = oldVal; MACHINE.a = oldArgcount; MACHINE.p = oldProc; success.apply(null, returnValues); @@ -285,7 +285,7 @@ MACHINE.p = proc; MACHINE.params['currentErrorHandler'] = function (MACHINE, e) { MACHINE.params['currentErrorHandler'] = oldErrorHandler; - MACHINE.val = oldVal; + MACHINE.v = oldVal; MACHINE.a = oldArgcount; MACHINE.p = oldProc; fail(e); @@ -324,7 +324,7 @@ arity, function(M) { --M.cbt; - M.val = f(M); + M.v = f(M); M.e.length -= M.a; return M.c.pop().label(M); }, diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index b1a1135..4c74476 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -212,7 +212,7 @@ var Machine = function() { this.cbt = STACK_LIMIT_ESTIMATE; // calls before trampoline - this.val = undefined; // value register + this.v = undefined; // value register this.p = undefined; // procedure register this.a = undefined; // argument count this.e = []; // environment From 605bcbc76aa72ab5dfa52ca337f135f4291b8cfe Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Fri, 16 Sep 2011 12:29:29 -0400 Subject: [PATCH 04/22] get-module-bytecode hacks off the syntax portion of the bytecode, because we're seeing some weirdness. Thanks to Matthew Flatt for bringing the error report. --- expand-out-images.rkt | 12 +++++++---- get-module-bytecode.rkt | 18 +++++++++++----- tests/more-tests/nqueens.rkt | 40 ++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 tests/more-tests/nqueens.rkt diff --git a/expand-out-images.rkt b/expand-out-images.rkt index 3a68ffe..45bddd6 100644 --- a/expand-out-images.rkt +++ b/expand-out-images.rkt @@ -202,12 +202,16 @@ (define-values ids #,(on-expr #'expr)))] [(define-syntaxes ids expr) - (quasisyntax/loc stx - (define-syntaxes ids #,(on-expr #'expr)))] + #'(void) + ;(quasisyntax/loc stx + ; (define-syntaxes ids #,(on-expr #'expr))) + ] [(define-values-for-syntax ids expr) - (quasisyntax/loc stx - (define-values-for-syntax ids #,(on-expr #'expr)))] + #'(void) + ;(quasisyntax/loc stx + ; (define-values-for-syntax ids #,(on-expr #'expr))) + ] [else (on-expr stx)])) \ No newline at end of file diff --git a/get-module-bytecode.rkt b/get-module-bytecode.rkt index 14f42c9..fef4cae 100644 --- a/get-module-bytecode.rkt +++ b/get-module-bytecode.rkt @@ -46,8 +46,12 @@ (error 'get-module-bytecode)])) (with-handlers ([exn? (lambda (exn) + ;(printf "error? ~s\n" (exn-message exn)) (define op (open-output-bytes)) - (write (alternative-f) op) + ;(printf "trying alternative to get bytecode\n") + (define bytecode (alternative-f)) + ;(printf "got the bytecode\n") + (write bytecode op) (get-output-bytes op))]) (define op (open-output-bytes)) (write compiled-code op) @@ -57,10 +61,11 @@ (define base-namespace - (lookup-language-namespace - #;'racket/base - `(file ,(path->string kernel-language-path))) - #;(make-base-namespace)) + (make-base-namespace)) + ;(lookup-language-namespace + ;;'racket/base + ;;`(file ,(path->string kernel-language-path))) + ;(make-base-namespace))) @@ -82,8 +87,11 @@ ;; get-compiled-code-from-port: input-port -> compiled-code ;; Compiles the source from scratch. (define (get-compiled-code-from-port ip) + ;(printf "get-compiled-code-from-port\n") (parameterize ([read-accept-reader #t] [current-namespace base-namespace]) (define stx (read-syntax (object-name ip) ip)) + ;(printf "got stx; now expanding out the images\n") (define expanded-stx (expand-out-images stx)) + ;(printf "now trying to compile the expanded syntax\n") (compile expanded-stx))) \ No newline at end of file diff --git a/tests/more-tests/nqueens.rkt b/tests/more-tests/nqueens.rkt new file mode 100644 index 0000000..e03f76f --- /dev/null +++ b/tests/more-tests/nqueens.rkt @@ -0,0 +1,40 @@ +#lang planet dyoo/whalesong/base +;;; NQUEENS -- Compute number of solutions to 8-queens problem. +;; 2006/08 -- renamed `try' to `try-it' to avoid Bigloo collision (mflatt) +;; 2010/04 -- got rid of the one-armed id (stamourv) + +(define trace? #f) + +(define (nqueens n) + + (define (one-to n) + (let loop ((i n) (l '())) + (if (= i 0) l (loop (- i 1) (cons i l))))) + + (define (try-it x y z) + (if (null? x) + (if (null? y) + (begin (if trace? (begin (write z) (newline)) #t) 1) + 0) + (+ (if (ok? (car x) 1 z) + (try-it (append (cdr x) y) '() (cons (car x) z)) + 0) + (try-it (cdr x) (cons (car x) y) z)))) + + (define (ok? row dist placed) + (if (null? placed) + #t + (and (not (= (car placed) (+ row dist))) + (not (= (car placed) (- row dist))) + (ok? row (+ dist 1) (cdr placed))))) + + (try-it (one-to n) '() '())) + +(let loop ((n 1000 ;10000 + ) + (v 0)) + (if (zero? n) + v + (loop (- n 1) (nqueens 8 + ; (if input 8 0) + )))) From 2542f2b1e6409f1dd9cae9338006bc9000dc333a Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Fri, 16 Sep 2011 13:01:26 -0400 Subject: [PATCH 05/22] mouse events in progress --- examples/mouse.rkt | 27 ++++++++++++++++++++++++ world/js-impl.js | 17 +++++++++++++++ world/kernel.js | 21 +++++++++++++++++++ world/main.rkt | 1 + world/racket-impl.rkt | 21 ++++++++++++------- world/raw-jsworld.js | 49 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 examples/mouse.rkt diff --git a/examples/mouse.rkt b/examples/mouse.rkt new file mode 100644 index 0000000..f6ff704 --- /dev/null +++ b/examples/mouse.rkt @@ -0,0 +1,27 @@ +#lang planet dyoo/whalesong + +(require (planet dyoo/whalesong/world) + (planet dyoo/whalesong/image)) + +(define width 640) +(define height 480) + +(define-struct posn (x y)) + +(define (mouse world x y type) + (cond + [(string=? type "click") + (make-posn x y)] + [else + world])) + +(define (draw w) + (place-image (circle 20 'solid 'red) + (posn-x w) + (posn-y w) + (empty-scene width height))) + + +(big-bang (make-posn 0 0) + (on-mouse mouse) + (to-draw draw)) \ No newline at end of file diff --git a/world/js-impl.js b/world/js-impl.js index 8e06b24..0831f62 100644 --- a/world/js-impl.js +++ b/world/js-impl.js @@ -21,6 +21,12 @@ var checkProcedureWithKey = plt.baselib.check.makeCheckArgumentType( plt.baselib.arity.isArityMatching(x.racketArity, 2)); }, 'procedure that consumes a world argument and a key'); +var checkProcedureWithMouse = plt.baselib.check.makeCheckArgumentType( + function(x) { return (plt.baselib.functions.isProcedure(x) && + plt.baselib.arity.isArityMatching(x.racketArity, 4)); }, + 'procedure that consumes a world argument, an x and y coordinate, and a mouse event'); + + var checkHandler = plt.baselib.check.makeCheckArgumentType( isWorldConfigOption, @@ -97,6 +103,17 @@ EXPORTS['on-key'] = return new OnKey(f); }); +EXPORTS['on-mouse'] = + makePrimitiveProcedure( + 'on-mouse', + 1, + function(MACHINE) { + var f = checkProcedureWithMouse(MACHINE, "on-key", 0); + return new OnMouse(f); + }); + + + EXPORTS['key=?'] = makePrimitiveProcedure( 'on-key', diff --git a/world/kernel.js b/world/kernel.js index d327e3e..83b4c44 100644 --- a/world/kernel.js +++ b/world/kernel.js @@ -233,6 +233,27 @@ var getKeyCodeName = function(e) { +var OnMouse = function(handler) { + WorldConfigOption.call(this, 'on-mouse'); + this.handler = handler; +} + +OnMouse.prototype = plt.baselib.heir(WorldConfigOption.prototype); + +OnMouse.prototype.toRawHandler = function(MACHINE, toplevelNode) { + var that = this; + var worldFunction = adaptWorldFunction(that.handler); + return rawJsworld.on_mouse( + function(w, x, y, type, success) { + worldFunction(w, x, y, type, success); + }); +}; + + + + + + var OutputConfig = function() {} diff --git a/world/main.rkt b/world/main.rkt index 0238a74..7d9845d 100644 --- a/world/main.rkt +++ b/world/main.rkt @@ -16,6 +16,7 @@ #:provided-values (big-bang on-tick on-key + on-mouse key=? to-draw stop-when)) diff --git a/world/racket-impl.rkt b/world/racket-impl.rkt index 38d50ca..bac4fab 100644 --- a/world/racket-impl.rkt +++ b/world/racket-impl.rkt @@ -1,8 +1,9 @@ #lang s-exp "../lang/base.rkt" (provide big-bang - on-tick to-draw + on-tick + on-mouse on-key key=? stop-when) @@ -13,23 +14,27 @@ (define (big-bang initial-world . args) - (error 'big-bang "not done yet")) + (error 'big-bang "must be run in JavaScript context")) (define on-tick (case-lambda [(handler) - (error 'on-tick "not done yet")] + (error 'on-tick "must be run in JavaScript context")] [(handler interval) - (error 'on-tick "not done yet")])) + (error 'on-tick "must be run in JavaScript context")])) + + +(define (on-mouse handle) + (error 'on-mouse "must be run in JavaScript context")) (define (to-draw handler) - (error 'to-draw "not done yet")) + (error 'to-draw "must be run in JavaScript context")) (define (on-key handler) - (error 'on-key "not done yet")) + (error 'on-key "must be run in JavaScript context")) (define (key=? key-1 key-2) - (error 'key=? "not done yet")) + (error 'key=? "must be run in JavaScript context")) (define (stop-when handler) - (error 'stop-when "not done yet")) + (error 'stop-when "must be run in JavaScript context")) diff --git a/world/raw-jsworld.js b/world/raw-jsworld.js index bb8246e..1a67b47 100644 --- a/world/raw-jsworld.js +++ b/world/raw-jsworld.js @@ -917,6 +917,55 @@ var rawJsworld = {}; Jsworld.on_key = on_key; + + + // http://www.quirksmode.org/js/events_mouse.html + // http://stackoverflow.com/questions/55677/how-do-i-get-the-coordinates-of-a-mouse-click-on-a-canvas-element + function on_mouse(mouse) { + return function() { + var makeWrapped = function(type) { + return function(e) { + var x = e.pageX, y = e.pageY; + x -= e.target.offsetLeft; + y -= e.target.offsetLeft; + preventDefault(e); + stopPropagation(e); + change_world(function(w, k) { + mouse(w, x, y, type, k); + }, doNothing); + }; + }; + var wrappedDown = makeWrapped('button-down'); + var wrappedUp = makeWrapped('button-up'); + // How do we do drag? + var wrappedMove = makeWrapped('move'); + var wrappedEnter = makeWrapped('enter'); + var wrappedLeave = makeWrapped('leave'); + return { + onRegister: function(top) { + attachEvent(top, 'mousedown', wrappedDown); + attachEvent(top, 'mouseup', wrappedUp); + attachEvent(top, 'mousemove', wrappedMove); + attachEvent(top, 'mouseenter', wrappedEnter); + attachEvent(top, 'mouseleave', wrappedLeave); + }, + onUnregister: function(top) { + detachEvent(top, 'mousedown', wrappedDown); + detachEvent(top, 'mouseup', wrappedUp); + detachEvent(top, 'mousemove', wrappedMove); + detachEvent(top, 'mouseenter', wrappedEnter); + detachEvent(top, 'mouseleave', wrappedLeave); + } + }; + } + } + Jsworld.on_mouse = on_mouse; + + + + + + // on_draw: CPS(world -> (sexpof node)) CPS(world -> (sexpof css-style)) -> handler function on_draw(redraw, redraw_css) { From 5ccaf1ca461fdcf995b4801dcc988c91ff8f20e6 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Fri, 16 Sep 2011 13:11:49 -0400 Subject: [PATCH 06/22] correcting coordinate calculations --- examples/mouse.rkt | 6 ++++-- world/raw-jsworld.js | 7 +++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/examples/mouse.rkt b/examples/mouse.rkt index f6ff704..1431111 100644 --- a/examples/mouse.rkt +++ b/examples/mouse.rkt @@ -10,8 +10,10 @@ (define (mouse world x y type) (cond - [(string=? type "click") + + [(string=? type "move") (make-posn x y)] + [else world])) @@ -21,7 +23,7 @@ (posn-y w) (empty-scene width height))) - +(printf "let's see how this works.\n\n") (big-bang (make-posn 0 0) (on-mouse mouse) (to-draw draw)) \ No newline at end of file diff --git a/world/raw-jsworld.js b/world/raw-jsworld.js index 1a67b47..eeae8cc 100644 --- a/world/raw-jsworld.js +++ b/world/raw-jsworld.js @@ -926,8 +926,11 @@ var rawJsworld = {}; var makeWrapped = function(type) { return function(e) { var x = e.pageX, y = e.pageY; - x -= e.target.offsetLeft; - y -= e.target.offsetLeft; + var currentElement = e.target; + do { + x -= currentElement.offsetLeft; + y -= currentElement.offsetTop; + } while(currentElement = currentElement.offsetParent); preventDefault(e); stopPropagation(e); change_world(function(w, k) { From b7bcc97e788292c72a367751dff300cebf41b1e9 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Fri, 16 Sep 2011 13:17:52 -0400 Subject: [PATCH 07/22] drag --- world/raw-jsworld.js | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/world/raw-jsworld.js b/world/raw-jsworld.js index eeae8cc..97aa7a0 100644 --- a/world/raw-jsworld.js +++ b/world/raw-jsworld.js @@ -923,19 +923,32 @@ var rawJsworld = {}; // http://stackoverflow.com/questions/55677/how-do-i-get-the-coordinates-of-a-mouse-click-on-a-canvas-element function on_mouse(mouse) { return function() { + var isButtonDown = false; var makeWrapped = function(type) { return function(e) { + preventDefault(e); + stopPropagation(e); var x = e.pageX, y = e.pageY; var currentElement = e.target; do { x -= currentElement.offsetLeft; y -= currentElement.offsetTop; } while(currentElement = currentElement.offsetParent); - preventDefault(e); - stopPropagation(e); - change_world(function(w, k) { - mouse(w, x, y, type, k); - }, doNothing); + + if (type === 'button-down') { + isButtonDown = true; + } else if (type === 'button-up') { + isButtonDown = false; + } + if (type === 'move' && isButtonDown) { + change_world(function(w, k) { + mouse(w, x, y, 'drag', k); + }, doNothing); + } else { + change_world(function(w, k) { + mouse(w, x, y, type, k); + }, doNothing); + } }; }; var wrappedDown = makeWrapped('button-down'); From 69d24fe4067c133f1b281beb78d58d4c3f845963 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Fri, 16 Sep 2011 13:29:36 -0400 Subject: [PATCH 08/22] doc --- scribblings/manual.scrbl | 1 + 1 file changed, 1 insertion(+) diff --git a/scribblings/manual.scrbl b/scribblings/manual.scrbl index 8ef7f02..95db961 100644 --- a/scribblings/manual.scrbl +++ b/scribblings/manual.scrbl @@ -1856,5 +1856,6 @@ and suggesting improvements. "Robby Findler" "Gregor Kiczales" "Cristina Teodoropol" + "Matthew Flatt" ) string Date: Fri, 16 Sep 2011 15:33:48 -0400 Subject: [PATCH 09/22] dead code --- js-assembler/assemble.rkt | 1 - js-assembler/optimize-basic-blocks.rkt | 75 -------------------------- 2 files changed, 76 deletions(-) delete mode 100644 js-assembler/optimize-basic-blocks.rkt diff --git a/js-assembler/assemble.rkt b/js-assembler/assemble.rkt index cac9a61..22f2af5 100644 --- a/js-assembler/assemble.rkt +++ b/js-assembler/assemble.rkt @@ -8,7 +8,6 @@ "assemble-helpers.rkt" "assemble-expression.rkt" "assemble-perform-statement.rkt" - "optimize-basic-blocks.rkt" "fracture.rkt" "../compiler/il-structs.rkt" "../sets.rkt" diff --git a/js-assembler/optimize-basic-blocks.rkt b/js-assembler/optimize-basic-blocks.rkt deleted file mode 100644 index a9fd476..0000000 --- a/js-assembler/optimize-basic-blocks.rkt +++ /dev/null @@ -1,75 +0,0 @@ -#lang typed/racket/base - -;; Does some basic optimizations at the level of basic blocks. - - -(require "assemble-structs.rkt" - "../compiler/il-structs.rkt" - racket/list) - - -(require/typed "../logger.rkt" [log-debug (String -> Void)]) - - -(provide optimize-basic-blocks) - - -(define-type Blockht (HashTable Symbol BasicBlock)) - -;; We want maps from unlabeled statements to their respective blocks. -(define-type Bodyht (HashTable (Listof UnlabeledStatement) (Listof Symbol))) - - -(: optimize-basic-blocks ((Listof BasicBlock) -> (Listof BasicBlock))) -(define (optimize-basic-blocks blocks) - - (: blockht : Blockht) - (define blockht (make-hasheq)) - - (: bodyht : Bodyht) - (define bodyht (make-hasheq)) - - ;; First, scan through the blocks, and pick up their names and bodies. - (for ([b blocks]) - (hash-set! blockht (BasicBlock-name b) b) - - (when (hash-has-key? bodyht (BasicBlock-stmts b)) - (log-debug (format "block ~a has the same content as another block" (BasicBlock-name b)))) - (hash-set! bodyht (BasicBlock-stmts b) - (cons (BasicBlock-name b) - (hash-ref bodyht (BasicBlock-stmts b) (lambda () '()))))) - - blocks - #;(define inlined-blocks - (map (lambda: ([b : BasicBlock]) - (optimize-block b blockht)) - blocks)) - #;inlined-blocks) - - - - -(: optimize-block (BasicBlock Blockht -> BasicBlock)) -;; Simple optimization: optimize away single-statement goto blocks with their -;; immediate contents. -(define (optimize-block b blocks) - (define stmts (BasicBlock-stmts b)) - (cond - [(= (length stmts) 1) - (define first-stmt (first stmts)) - (cond - [(GotoStatement? first-stmt) - (define target (GotoStatement-target first-stmt)) - (cond - [(Label? target) - (log-debug (format "inlining basic block ~a" (BasicBlock-name b))) - (optimize-block (make-BasicBlock (BasicBlock-name b) - (BasicBlock-stmts - (hash-ref blocks (Label-name target)))) - blocks)] - [else - b])] - [else - b])] - [else - b])) From f2c3dc3fe1a62fd2f4e37d199144a118db3e21e4 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Fri, 16 Sep 2011 16:09:46 -0400 Subject: [PATCH 10/22] threading state about all the basic blocks throughout assembly, so we can do some tricks. --- js-assembler/assemble-expression.rkt | 14 +- js-assembler/assemble-helpers.rkt | 93 +++++++---- js-assembler/assemble-open-coded.rkt | 9 +- js-assembler/assemble-perform-statement.rkt | 26 ++-- js-assembler/assemble-structs.rkt | 5 + js-assembler/assemble.rkt | 162 +++++++++++--------- 6 files changed, 192 insertions(+), 117 deletions(-) diff --git a/js-assembler/assemble-expression.rkt b/js-assembler/assemble-expression.rkt index 7d44e89..9c15358 100644 --- a/js-assembler/assemble-expression.rkt +++ b/js-assembler/assemble-expression.rkt @@ -10,15 +10,16 @@ -(: assemble-op-expression (PrimitiveOperator -> String)) -(define (assemble-op-expression op) +(: assemble-op-expression (PrimitiveOperator Blockht -> String)) +(define (assemble-op-expression op blockht) (cond [(GetCompiledProcedureEntry? op) "M.p.label"] [(MakeCompiledProcedure? op) (format "new RT.Closure(~a,~a,[~a],~a)" - (assemble-label (make-Label (MakeCompiledProcedure-label op))) + (assemble-label (make-Label (MakeCompiledProcedure-label op)) + blockht) (assemble-arity (MakeCompiledProcedure-arity op)) (string-join (map assemble-env-reference/closure-capture @@ -32,7 +33,8 @@ [(MakeCompiledProcedureShell? op) (format "new RT.Closure(~a,~a,undefined,~a)" - (assemble-label (make-Label (MakeCompiledProcedureShell-label op))) + (assemble-label (make-Label (MakeCompiledProcedureShell-label op)) + blockht) (assemble-arity (MakeCompiledProcedureShell-arity op)) (assemble-display-name (MakeCompiledProcedureShell-display-name op)))] @@ -48,7 +50,7 @@ (cond [(DefaultContinuationPromptTag? tag) (assemble-default-continuation-prompt-tag)] [(OpArg? tag) - (assemble-oparg tag)])))] + (assemble-oparg tag blockht)])))] [(MakeBoxedEnvironmentValue? op) @@ -56,4 +58,4 @@ (add1 (MakeBoxedEnvironmentValue-depth op)))] [(CallKernelPrimitiveProcedure? op) - (open-code-kernel-primitive-procedure op)])) \ No newline at end of file + (open-code-kernel-primitive-procedure op blockht)])) \ No newline at end of file diff --git a/js-assembler/assemble-helpers.rkt b/js-assembler/assemble-helpers.rkt index 6b0f6fc..5ed24e8 100644 --- a/js-assembler/assemble-helpers.rkt +++ b/js-assembler/assemble-helpers.rkt @@ -4,8 +4,13 @@ "../compiler/expression-structs.rkt" "../compiler/lexical-structs.rkt" "../compiler/arity-structs.rkt" + "assemble-structs.rkt" racket/list - racket/string) + racket/string + racket/match) + + + (provide assemble-oparg assemble-target @@ -22,19 +27,21 @@ assemble-jump assemble-display-name assemble-location - assemble-numeric-constant) + assemble-numeric-constant + + block-looks-like-context-expected-values?) (require/typed typed/racket/base [regexp-split (Regexp String -> (Listof String))]) -(: assemble-oparg (OpArg -> String)) -(define (assemble-oparg v) +(: assemble-oparg (OpArg Blockht -> String)) +(define (assemble-oparg v blockht) (cond [(Reg? v) (assemble-reg v)] [(Label? v) - (assemble-label v)] + (assemble-label v blockht)] [(Const? v) (assemble-const v)] [(EnvLexicalReference? v) @@ -44,7 +51,7 @@ [(EnvWholePrefixReference? v) (assemble-whole-prefix-reference v)] [(SubtractArg? v) - (assemble-subtractarg v)] + (assemble-subtractarg v blockht)] [(ControlStackLabel? v) (assemble-control-stack-label v)] [(ControlStackLabel/MultipleValueReturn? v) @@ -52,9 +59,9 @@ [(ControlFrameTemporary? v) (assemble-control-frame-temporary v)] [(CompiledProcedureEntry? v) - (assemble-compiled-procedure-entry v)] + (assemble-compiled-procedure-entry v blockht)] [(CompiledProcedureClosureReference? v) - (assemble-compiled-procedure-closure-reference v)] + (assemble-compiled-procedure-closure-reference v blockht)] [(PrimitiveKernelValue? v) (assemble-primitive-kernel-value v)] [(ModuleEntry? v) @@ -69,6 +76,8 @@ + + (: assemble-target (Target -> (String -> String))) (define (assemble-target target) (cond @@ -287,8 +296,8 @@ -(: assemble-label (Label -> String)) -(define (assemble-label a-label) +(: assemble-label (Label Blockht -> String)) +(define (assemble-label a-label Blockht) (let ([chunks (regexp-split #rx"[^a-zA-Z0-9]+" (symbol->string (Label-name a-label)))]) @@ -304,11 +313,11 @@ -(: assemble-subtractarg (SubtractArg -> String)) -(define (assemble-subtractarg s) +(: assemble-subtractarg (SubtractArg Blockht -> String)) +(define (assemble-subtractarg s blockht) (format "(~a-~a)" - (assemble-oparg (SubtractArg-lhs s)) - (assemble-oparg (SubtractArg-rhs s)))) + (assemble-oparg (SubtractArg-lhs s) blockht) + (assemble-oparg (SubtractArg-rhs s) blockht))) (: assemble-control-stack-label (ControlStackLabel -> String)) @@ -322,17 +331,18 @@ -(: assemble-compiled-procedure-entry (CompiledProcedureEntry -> String)) -(define (assemble-compiled-procedure-entry a-compiled-procedure-entry) +(: assemble-compiled-procedure-entry (CompiledProcedureEntry Blockht -> String)) +(define (assemble-compiled-procedure-entry a-compiled-procedure-entry blockht) (format "(~a).label" - (assemble-oparg (CompiledProcedureEntry-proc a-compiled-procedure-entry)))) + (assemble-oparg (CompiledProcedureEntry-proc a-compiled-procedure-entry) + blockht))) -(: assemble-compiled-procedure-closure-reference (CompiledProcedureClosureReference -> String)) -(define (assemble-compiled-procedure-closure-reference a-ref) +(: assemble-compiled-procedure-closure-reference (CompiledProcedureClosureReference Blockht -> String)) +(define (assemble-compiled-procedure-closure-reference a-ref blockht) (format "(~a).closedVals[(~a).closedVals.length - ~a]" - (assemble-oparg (CompiledProcedureClosureReference-proc a-ref)) - (assemble-oparg (CompiledProcedureClosureReference-proc a-ref)) + (assemble-oparg (CompiledProcedureClosureReference-proc a-ref) blockht) + (assemble-oparg (CompiledProcedureClosureReference-proc a-ref) blockht) (add1 (CompiledProcedureClosureReference-n a-ref)))) @@ -379,9 +389,38 @@ -(: assemble-jump (OpArg -> String)) -(define (assemble-jump target) - (format "return(~a)(M);" (assemble-oparg target))) + +(: assemble-jump (OpArg Blockht -> String)) +(define (assemble-jump target blockht) + + (define (default) + (format "return(~a)(M);" (assemble-oparg target blockht))) + + ;; Optimization: if the target of the jump goes to a block whose + ;; only body is a si-context-expected_1, then jump directly to that code. + (cond + [(Label? target) + (define target-block (hash-ref blockht (Label-name target))) + (cond + [(block-looks-like-context-expected-values? target-block) + => + (lambda (expected) + (format "RT.si_context_expected(~a)(M);\n" expected))] + [else + (default)])] + [else + (default)])) + + + +(: block-looks-like-context-expected-values? (BasicBlock -> (U Natural False))) +(define (block-looks-like-context-expected-values? a-block) + (match (BasicBlock-stmts a-block) + [(list (struct PerformStatement ((struct RaiseContextExpectedValuesError! (expected)))) + stmts ...) + expected] + [else + #f])) @@ -399,13 +438,13 @@ -(: assemble-location ((U Reg Label) -> String)) -(define (assemble-location a-location) +(: assemble-location ((U Reg Label) Blockht -> String)) +(define (assemble-location a-location blockht) (cond [(Reg? a-location) (assemble-reg a-location)] [(Label? a-location) - (assemble-label a-location)])) + (assemble-label a-location blockht)])) (: assemble-primitive-kernel-value (PrimitiveKernelValue -> String)) diff --git a/js-assembler/assemble-open-coded.rkt b/js-assembler/assemble-open-coded.rkt index b788941..86ac5d4 100644 --- a/js-assembler/assemble-open-coded.rkt +++ b/js-assembler/assemble-open-coded.rkt @@ -4,6 +4,7 @@ "../compiler/il-structs.rkt" "../compiler/lexical-structs.rkt" "../compiler/kernel-primitives.rkt" + "assemble-structs.rkt" racket/string racket/list typed/rackunit) @@ -12,10 +13,12 @@ -(: open-code-kernel-primitive-procedure (CallKernelPrimitiveProcedure -> String)) -(define (open-code-kernel-primitive-procedure op) +(: open-code-kernel-primitive-procedure (CallKernelPrimitiveProcedure Blockht -> String)) +(define (open-code-kernel-primitive-procedure op blockht) (let*: ([operator : KernelPrimitiveName/Inline (CallKernelPrimitiveProcedure-operator op)] - [operands : (Listof String) (map assemble-oparg (CallKernelPrimitiveProcedure-operands op))] + [operands : (Listof String) (map (lambda: ([op : OpArg]) + (assemble-oparg op blockht)) + (CallKernelPrimitiveProcedure-operands op))] [checked-operands : (Listof String) (map (lambda: ([dom : OperandDomain] [pos : Natural] diff --git a/js-assembler/assemble-perform-statement.rkt b/js-assembler/assemble-perform-statement.rkt index 10ea4ea..1b1eda0 100644 --- a/js-assembler/assemble-perform-statement.rkt +++ b/js-assembler/assemble-perform-statement.rkt @@ -3,14 +3,15 @@ "../compiler/il-structs.rkt" "../compiler/lexical-structs.rkt" "../parameters.rkt" + "assemble-structs.rkt" racket/string) (provide assemble-op-statement) -(: assemble-op-statement (PrimitiveCommand -> String)) -(define (assemble-op-statement op) +(: assemble-op-statement (PrimitiveCommand Blockht -> String)) +(define (assemble-op-statement op blockht) (cond [(CheckToplevelBound!? op) @@ -83,7 +84,7 @@ [(DefaultContinuationPromptTag? tag) (assemble-default-continuation-prompt-tag)] [(OpArg? tag) - (assemble-oparg tag)])))] + (assemble-oparg tag blockht)])))] [(FixClosureShellMap!? op) (format "M.e[M.e.length-~a].closedVals=[~a];" @@ -99,16 +100,18 @@ [(SetFrameCallee!? op) (format "M.c[M.c.length-1].p=~a;" - (assemble-oparg (SetFrameCallee!-proc op)))] + (assemble-oparg (SetFrameCallee!-proc op) + blockht))] [(SpliceListIntoStack!? op) (format "M.spliceListIntoStack(~a);" - (assemble-oparg (SpliceListIntoStack!-depth op)))] + (assemble-oparg (SpliceListIntoStack!-depth op) + blockht))] [(UnspliceRestFromStack!? op) (format "M.unspliceRestFromStack(~a,~a);" - (assemble-oparg (UnspliceRestFromStack!-depth op)) - (assemble-oparg (UnspliceRestFromStack!-length op)))] + (assemble-oparg (UnspliceRestFromStack!-depth op) blockht) + (assemble-oparg (UnspliceRestFromStack!-length op) blockht))] [(InstallContinuationMarkEntry!? op) (string-append "M.installContinuationMarkEntry(" @@ -122,13 +125,13 @@ [(RaiseArityMismatchError!? op) (format "RT.raiseArityMismatchError(M,~a,~a);" - (assemble-oparg (RaiseArityMismatchError!-proc op)) - (assemble-oparg (RaiseArityMismatchError!-received op)))] + (assemble-oparg (RaiseArityMismatchError!-proc op) blockht) + (assemble-oparg (RaiseArityMismatchError!-received op) blockht))] [(RaiseOperatorApplicationError!? op) (format "RT.raiseOperatorApplicationError(M,~a);" - (assemble-oparg (RaiseOperatorApplicationError!-operator op)))] + (assemble-oparg (RaiseOperatorApplicationError!-operator op) blockht))] [(RaiseUnimplementedPrimitiveError!? op) @@ -140,7 +143,8 @@ (format "M.modules[~s]=new RT.ModuleRecord(~s,~a);" (symbol->string (ModuleLocator-name (InstallModuleEntry!-path op))) (symbol->string (InstallModuleEntry!-name op)) - (assemble-label (make-Label (InstallModuleEntry!-entry-point op))))] + (assemble-label (make-Label (InstallModuleEntry!-entry-point op)) + blockht))] [(MarkModuleInvoked!? op) (format "M.modules[~s].isInvoked=true;" diff --git a/js-assembler/assemble-structs.rkt b/js-assembler/assemble-structs.rkt index 5704cfc..730c59b 100644 --- a/js-assembler/assemble-structs.rkt +++ b/js-assembler/assemble-structs.rkt @@ -13,3 +13,8 @@ (define-struct: BasicBlock ([name : Symbol] [stmts : (Listof UnlabeledStatement)]) #:transparent) + + + +;; Represents a hashtable from symbols to basic blocks +(define-type Blockht (HashTable Symbol BasicBlock)) diff --git a/js-assembler/assemble.rkt b/js-assembler/assemble.rkt index 22f2af5..1d7f071 100644 --- a/js-assembler/assemble.rkt +++ b/js-assembler/assemble.rkt @@ -29,8 +29,6 @@ (define current-emit-debug-trace? (make-parameter #f)) -;; Represents a hashtable from symbols to basic blocks -(define-type Blockht (HashTable Symbol BasicBlock)) @@ -48,12 +46,19 @@ (define function-entry-and-exit-names (list->set (get-function-entry-and-exit-names stmts))) + (: blockht : Blockht) + (define blockht (make-hash)) + + (for ([b basic-blocks]) + (hash-set! blockht (BasicBlock-name b) b)) + (write-blocks basic-blocks + blockht (list->set entry-points) function-entry-and-exit-names op) - (write-linked-label-attributes stmts op) + (write-linked-label-attributes stmts blockht op) (display "M.params.currentErrorHandler = fail;\n" op) (display "M.params.currentSuccessHandler = success;\n" op) @@ -66,18 +71,14 @@ for (param in params) { EOF op) (fprintf op "M.trampoline(~a, true); })" - (assemble-label (make-Label (BasicBlock-name (first basic-blocks)))))) + (assemble-label (make-Label (BasicBlock-name (first basic-blocks))) + blockht))) -(: write-blocks ((Listof BasicBlock) (Setof Symbol) (Setof Symbol) Output-Port -> Void)) +(: write-blocks ((Listof BasicBlock) Blockht (Setof Symbol) (Setof Symbol) Output-Port -> Void)) ;; Write out all the basic blocks associated to an entry point. -(define (write-blocks blocks entry-points function-entry-and-exit-names op) - (: blockht : Blockht) - (define blockht (make-hash)) - - (for ([b blocks]) - (hash-set! blockht (BasicBlock-name b) b)) +(define (write-blocks blocks blockht entry-points function-entry-and-exit-names op) ;; Since there may be cycles between the blocks, we cut the cycles by ;; making them entry points as well. @@ -124,15 +125,15 @@ EOF -(: write-linked-label-attributes ((Listof Statement) Output-Port -> 'ok)) -(define (write-linked-label-attributes stmts op) +(: write-linked-label-attributes ((Listof Statement) Blockht Output-Port -> 'ok)) +(define (write-linked-label-attributes stmts blockht op) (cond [(empty? stmts) 'ok] [else (let: ([stmt : Statement (first stmts)]) - (define (next) (write-linked-label-attributes (rest stmts) op)) + (define (next) (write-linked-label-attributes (rest stmts) blockht op)) (cond [(symbol? stmt) @@ -140,8 +141,8 @@ EOF [(LinkedLabel? stmt) ;; Setting up multiple-value-return (fprintf op "~a.mvr=~a;\n" - (assemble-label (make-Label (LinkedLabel-label stmt))) - (assemble-label (make-Label (LinkedLabel-linked-to stmt)))) + (assemble-label (make-Label (LinkedLabel-label stmt)) blockht) + (assemble-label (make-Label (LinkedLabel-linked-to stmt)) blockht)) (next)] [(DebugPrint? stmt) (next)] @@ -179,15 +180,17 @@ EOF (: assemble-basic-block (BasicBlock Blockht (Setof Symbol) (Setof Symbol) Output-Port -> 'ok)) (define (assemble-basic-block a-basic-block blockht entry-points function-entry-and-exit-names op) - (match (BasicBlock-stmts a-basic-block) - [(list (struct PerformStatement ((struct RaiseContextExpectedValuesError! (expected)))) - stmts ...) - (fprintf op "~a=RT.si_context_expected(~a);\n" - (assemble-label (make-Label (BasicBlock-name a-basic-block))) - expected) - 'ok] - [else - (default-assemble-basic-block a-basic-block blockht entry-points function-entry-and-exit-names op)])) + (cond + [(block-looks-like-context-expected-values? a-basic-block) + => + (lambda (expected) + (fprintf op "~a=RT.si_context_expected(~a);\n" + (assemble-label (make-Label (BasicBlock-name a-basic-block)) + blockht) + expected) + 'ok)] + [else + (default-assemble-basic-block a-basic-block blockht entry-points function-entry-and-exit-names op)])) @@ -196,11 +199,11 @@ EOF (cond [(set-contains? function-entry-and-exit-names (BasicBlock-name a-basic-block)) (fprintf op "var ~a=function(M){if(--M.cbt<0){throw ~a;}\n" - (assemble-label (make-Label (BasicBlock-name a-basic-block))) - (assemble-label (make-Label (BasicBlock-name a-basic-block))))] + (assemble-label (make-Label (BasicBlock-name a-basic-block)) blockht) + (assemble-label (make-Label (BasicBlock-name a-basic-block)) blockht))] [else (fprintf op "var ~a=function(M){--M.cbt<0;\n" - (assemble-label (make-Label (BasicBlock-name a-basic-block))))]) + (assemble-label (make-Label (BasicBlock-name a-basic-block)) blockht))]) (assemble-block-statements (BasicBlock-name a-basic-block) (BasicBlock-stmts a-basic-block) blockht @@ -221,7 +224,7 @@ EOF (not (GotoStatement? stmt))) (log-debug (format "Last statement of the block ~a is not a goto" name))) - (display (assemble-statement stmt) op) + (display (assemble-statement stmt blockht) op) (newline op) (assemble-block-statements name (rest stmts) @@ -253,30 +256,33 @@ EOF (define test-code (cond [(TestFalse? test) (format "if(~a===false)" - (assemble-oparg (TestFalse-operand test)))] + (assemble-oparg (TestFalse-operand test) + blockht))] [(TestTrue? test) (format "if(~a!==false)" - (assemble-oparg (TestTrue-operand test)))] + (assemble-oparg (TestTrue-operand test) + blockht))] [(TestOne? test) (format "if(~a===1)" - (assemble-oparg (TestOne-operand test)))] + (assemble-oparg (TestOne-operand test) + blockht))] [(TestZero? test) (format "if(~a===0)" - (assemble-oparg (TestZero-operand test)))] - - ;; [(TestPrimitiveProcedure? test) - ;; (format "if(typeof(~a)==='function')" - ;; (assemble-oparg (TestPrimitiveProcedure-operand test)))] - + (assemble-oparg (TestZero-operand test) + blockht))] + [(TestClosureArityMismatch? test) (format "if(!RT.isArityMatching((~a).racketArity,~a))" - (assemble-oparg (TestClosureArityMismatch-closure test)) - (assemble-oparg (TestClosureArityMismatch-n test)))])) + (assemble-oparg (TestClosureArityMismatch-closure test) + blockht) + (assemble-oparg (TestClosureArityMismatch-n test) + blockht))])) (display test-code op) (display "{" op) (cond [(set-contains? entry-points (TestAndJumpStatement-label stmt)) - (display (assemble-jump (make-Label (TestAndJumpStatement-label stmt))) op)] + (display (assemble-jump (make-Label (TestAndJumpStatement-label stmt)) + blockht) op)] [else (assemble-block-statements (BasicBlock-name (hash-ref blockht (TestAndJumpStatement-label stmt))) @@ -306,7 +312,7 @@ EOF (GotoStatement? (first target-statements))) (loop (first target-statements))] [(set-contains? entry-points (Label-name target)) - (display (assemble-statement stmt) op) + (display (assemble-statement stmt blockht) op) 'ok] [else (log-debug (format "Assembling inlined jump into ~a" (Label-name target)) ) @@ -316,13 +322,13 @@ EOF entry-points op)])] [(Reg? target) - (display (assemble-statement stmt) op) + (display (assemble-statement stmt blockht) op) 'ok] [(ModuleEntry? target) - (display (assemble-statement stmt) op) + (display (assemble-statement stmt blockht) op) 'ok] [(CompiledProcedureEntry? target) - (display (assemble-statement stmt) op) + (display (assemble-statement stmt blockht) op) 'ok]))] @@ -429,57 +435,67 @@ EOF -(: assemble-statement (UnlabeledStatement -> String)) +(: assemble-statement (UnlabeledStatement Blockht -> String)) ;; Generates the code to assemble a statement. -(define (assemble-statement stmt) +(define (assemble-statement stmt blockht) (define assembled (cond [(DebugPrint? stmt) (format "M.params.currentOutputPort.writeDomNode(M, $('').text(~a));" - (assemble-oparg (DebugPrint-value stmt)))] + (assemble-oparg (DebugPrint-value stmt) + blockht))] [(AssignImmediateStatement? stmt) (let: ([t : (String -> String) (assemble-target (AssignImmediateStatement-target stmt))] [v : OpArg (AssignImmediateStatement-value stmt)]) - (t (assemble-oparg v)))] + (t (assemble-oparg v blockht)))] [(AssignPrimOpStatement? stmt) ((assemble-target (AssignPrimOpStatement-target stmt)) - (assemble-op-expression (AssignPrimOpStatement-op stmt)))] + (assemble-op-expression (AssignPrimOpStatement-op stmt) + blockht))] [(PerformStatement? stmt) - (assemble-op-statement (PerformStatement-op stmt))] + (assemble-op-statement (PerformStatement-op stmt) blockht)] [(TestAndJumpStatement? stmt) (let*: ([test : PrimitiveTest (TestAndJumpStatement-op stmt)] [jump : String (assemble-jump - (make-Label (TestAndJumpStatement-label stmt)))]) + (make-Label (TestAndJumpStatement-label stmt)) + blockht)]) ;; to help localize type checks, we add a type annotation here. (ann (cond [(TestFalse? test) (format "if(~a===false){~a}" - (assemble-oparg (TestFalse-operand test)) + (assemble-oparg (TestFalse-operand test) + blockht) jump)] [(TestTrue? test) (format "if(~a!==false){~a}" - (assemble-oparg (TestTrue-operand test)) + (assemble-oparg (TestTrue-operand test) + blockht) jump)] [(TestOne? test) (format "if(~a===1){~a}" - (assemble-oparg (TestOne-operand test)) + (assemble-oparg (TestOne-operand test) + blockht) jump)] [(TestZero? test) (format "if(~a===0){~a}" - (assemble-oparg (TestZero-operand test)) + (assemble-oparg (TestZero-operand test) + blockht) jump)] [(TestClosureArityMismatch? test) (format "if(!RT.isArityMatching((~a).racketArity,~a)){~a}" - (assemble-oparg (TestClosureArityMismatch-closure test)) - (assemble-oparg (TestClosureArityMismatch-n test)) + (assemble-oparg (TestClosureArityMismatch-closure test) + blockht) + (assemble-oparg (TestClosureArityMismatch-n test) + blockht) jump)]) String))] [(GotoStatement? stmt) - (assemble-jump (GotoStatement-target stmt))] + (assemble-jump (GotoStatement-target stmt) + blockht)] [(PushControlFrame/Generic? stmt) "M.c.push(new RT.Frame());"] @@ -489,9 +505,11 @@ EOF (let: ([label : (U Symbol LinkedLabel) (PushControlFrame/Call-label stmt)]) (cond [(symbol? label) - (assemble-label (make-Label label))] + (assemble-label (make-Label label) + blockht)] [(LinkedLabel? label) - (assemble-label (make-Label (LinkedLabel-label label)))])))] + (assemble-label (make-Label (LinkedLabel-label label)) + blockht)])))] [(PushControlFrame/Prompt? stmt) ;; fixme: use a different frame structure @@ -499,9 +517,11 @@ EOF (let: ([label : (U Symbol LinkedLabel) (PushControlFrame/Prompt-label stmt)]) (cond [(symbol? label) - (assemble-label (make-Label label))] + (assemble-label (make-Label label) + blockht)] [(LinkedLabel? label) - (assemble-label (make-Label (LinkedLabel-label label)))])) + (assemble-label (make-Label (LinkedLabel-label label)) + blockht)])) (let: ([tag : (U DefaultContinuationPromptTag OpArg) (PushControlFrame/Prompt-tag stmt)]) @@ -509,7 +529,7 @@ EOF [(DefaultContinuationPromptTag? tag) (assemble-default-continuation-prompt-tag)] [(OpArg? tag) - (assemble-oparg tag)])))] + (assemble-oparg tag blockht)])))] [(PopControlFrame? stmt) "M.c.pop();"] @@ -530,20 +550,22 @@ EOF (cond [(and (Const? skip) (= (ensure-natural (Const-const skip)) 0)) (format "M.e.length-=~a;" - (assemble-oparg (PopEnvironment-n stmt)))] + (assemble-oparg (PopEnvironment-n stmt) blockht))] [else (format "M.e.splice(M.e.length-(~a+~a),~a);" - (assemble-oparg (PopEnvironment-skip stmt)) - (assemble-oparg (PopEnvironment-n stmt)) - (assemble-oparg (PopEnvironment-n stmt)))]))] + (assemble-oparg (PopEnvironment-skip stmt) blockht) + (assemble-oparg (PopEnvironment-n stmt) blockht) + (assemble-oparg (PopEnvironment-n stmt) blockht))]))] [(PushImmediateOntoEnvironment? stmt) (format "M.e.push(~a);" (let: ([val-string : String (cond [(PushImmediateOntoEnvironment-box? stmt) - (format "[~a]" (assemble-oparg (PushImmediateOntoEnvironment-value stmt)))] + (format "[~a]" (assemble-oparg (PushImmediateOntoEnvironment-value stmt) + blockht))] [else - (assemble-oparg (PushImmediateOntoEnvironment-value stmt))])]) + (assemble-oparg (PushImmediateOntoEnvironment-value stmt) + blockht)])]) val-string))] [(Comment? stmt) ;; TODO: maybe comments should be emitted as JavaScript comments. From 0991a0d74b105e9492937f66db08dd865d98c049 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Fri, 16 Sep 2011 16:22:26 -0400 Subject: [PATCH 11/22] mvr initialization should now optimize away the common case --- js-assembler/assemble-helpers.rkt | 28 +++++++++++-------- js-assembler/assemble.rkt | 21 +++++++++++--- js-assembler/runtime-src/baselib-functions.js | 4 +-- js-assembler/runtime-src/runtime.js | 1 + 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/js-assembler/assemble-helpers.rkt b/js-assembler/assemble-helpers.rkt index 5ed24e8..a501723 100644 --- a/js-assembler/assemble-helpers.rkt +++ b/js-assembler/assemble-helpers.rkt @@ -298,18 +298,24 @@ (: assemble-label (Label Blockht -> String)) (define (assemble-label a-label Blockht) - (let ([chunks - (regexp-split #rx"[^a-zA-Z0-9]+" - (symbol->string (Label-name a-label)))]) + (define a-block (hash-ref Blockht (Label-name a-label))) + (cond + [(block-looks-like-context-expected-values? a-block) + => (lambda (expected) + (format "RT.si_context_expected(~a)" expected))] + [else + (define chunks + (regexp-split #rx"[^a-zA-Z0-9]+" + (symbol->string (Label-name a-label)))) (cond - [(empty? chunks) - (error "impossible: empty label ~s" a-label)] - [(empty? (rest chunks)) - (string-append "_" (first chunks))] - [else - (string-append "_" - (first chunks) - (apply string-append (map string-titlecase (rest chunks))))]))) + [(empty? chunks) + (error "impossible: empty label ~s" a-label)] + [(empty? (rest chunks)) + (string-append "_" (first chunks))] + [else + (string-append "_" + (first chunks) + (apply string-append (map string-titlecase (rest chunks))))])])) diff --git a/js-assembler/assemble.rkt b/js-assembler/assemble.rkt index 1d7f071..a96bc19 100644 --- a/js-assembler/assemble.rkt +++ b/js-assembler/assemble.rkt @@ -139,10 +139,23 @@ EOF [(symbol? stmt) (next)] [(LinkedLabel? stmt) - ;; Setting up multiple-value-return - (fprintf op "~a.mvr=~a;\n" - (assemble-label (make-Label (LinkedLabel-label stmt)) blockht) - (assemble-label (make-Label (LinkedLabel-linked-to stmt)) blockht)) + ;; Setting up multiple-value-return. + ;; Optimization: in the most common case (expecting only one), we optimize away + ;; the assignment, because there's a distinguished instruction, and it's implied + ;; that if .mvr is missing, that the block only expects one. + (define linked-to-block (hash-ref blockht (LinkedLabel-linked-to stmt))) + (cond + [(block-looks-like-context-expected-values? linked-to-block) + => (lambda (expected) + (cond + [(= expected 1) + (void)] + [else + (fprintf op "~a.mvr=RT.si_context_expected(~a);\n" expected)]))] + [else + (fprintf op "~a.mvr=~a;\n" + (assemble-label (make-Label (LinkedLabel-label stmt)) blockht) + (assemble-label (make-Label (LinkedLabel-linked-to stmt)) blockht))]) (next)] [(DebugPrint? stmt) (next)] diff --git a/js-assembler/runtime-src/baselib-functions.js b/js-assembler/runtime-src/baselib-functions.js index 3cdb988..f77d278 100644 --- a/js-assembler/runtime-src/baselib-functions.js +++ b/js-assembler/runtime-src/baselib-functions.js @@ -72,12 +72,12 @@ return MACHINE.c.pop().label(MACHINE); } else if (returnArgs.length === 0) { MACHINE.a = 0; - return MACHINE.c.pop().label.mvr(MACHINE); + return (MACHINE.c.pop().label.mvr || plt.runtime.si_context_expected_1)(MACHINE); } else { MACHINE.a = returnArgs.length; MACHINE.v = returnArgs.shift(); MACHINE.e.push.apply(MACHINE.e, returnArgs.reverse()); - return MACHINE.c.pop().label.mvr(MACHINE); + return (MACHINE.c.pop().label.mvr || plt.runtime.si_context_expected_1)(MACHINE); } }; diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index 9cbce07..1a3e8e8 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -817,6 +817,7 @@ exports['getTracedCalleeKey'] = getTracedCalleeKey; exports['si_context_expected'] = si_context_expected; + exports['si_context_expected_1'] = si_context_expected_1; exports['checkClosureAndArity'] = checkClosureAndArity; From b8cfd43a50091eb6d6ecc0bf3574d40a1e54013c Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Fri, 16 Sep 2011 17:04:15 -0400 Subject: [PATCH 12/22] multiple value return optimizations --- js-assembler/assemble-helpers.rkt | 38 ++++++++++++++--------------- js-assembler/assemble.rkt | 19 +++++++++------ js-assembler/runtime-src/runtime.js | 4 +-- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/js-assembler/assemble-helpers.rkt b/js-assembler/assemble-helpers.rkt index a501723..b99db97 100644 --- a/js-assembler/assemble-helpers.rkt +++ b/js-assembler/assemble-helpers.rkt @@ -19,6 +19,7 @@ assemble-prefix-reference assemble-whole-prefix-reference assemble-reg + munge-label-name assemble-label assemble-listof-assembled-values assemble-default-continuation-prompt-tag @@ -295,27 +296,26 @@ "M.a"]))) +(: munge-label-name (Label -> String)) +(define (munge-label-name a-label) + (define chunks + (regexp-split #rx"[^a-zA-Z0-9]+" + (symbol->string (Label-name a-label)))) + (cond + [(empty? chunks) + (error "impossible: empty label ~s" a-label)] + [(empty? (rest chunks)) + (string-append "_" (first chunks))] + [else + (string-append "_" + (first chunks) + (apply string-append (map string-titlecase (rest chunks))))])) + + (: assemble-label (Label Blockht -> String)) (define (assemble-label a-label Blockht) - (define a-block (hash-ref Blockht (Label-name a-label))) - (cond - [(block-looks-like-context-expected-values? a-block) - => (lambda (expected) - (format "RT.si_context_expected(~a)" expected))] - [else - (define chunks - (regexp-split #rx"[^a-zA-Z0-9]+" - (symbol->string (Label-name a-label)))) - (cond - [(empty? chunks) - (error "impossible: empty label ~s" a-label)] - [(empty? (rest chunks)) - (string-append "_" (first chunks))] - [else - (string-append "_" - (first chunks) - (apply string-append (map string-titlecase (rest chunks))))])])) + (munge-label-name a-label)) @@ -333,7 +333,7 @@ (: assemble-control-stack-label/multiple-value-return (ControlStackLabel/MultipleValueReturn -> String)) (define (assemble-control-stack-label/multiple-value-return a-csl) - "M.c[M.c.length-1].label.mvr") + "(M.c[M.c.length-1].label.mvr||RT.si_context_expected_1)") diff --git a/js-assembler/assemble.rkt b/js-assembler/assemble.rkt index a96bc19..888cc46 100644 --- a/js-assembler/assemble.rkt +++ b/js-assembler/assemble.rkt @@ -151,10 +151,12 @@ EOF [(= expected 1) (void)] [else - (fprintf op "~a.mvr=RT.si_context_expected(~a);\n" expected)]))] + (fprintf op "~a.mvr=RT.si_context_expected(~a);\n" + (munge-label-name (make-Label (LinkedLabel-label stmt))) + expected)]))] [else (fprintf op "~a.mvr=~a;\n" - (assemble-label (make-Label (LinkedLabel-label stmt)) blockht) + (munge-label-name (make-Label (LinkedLabel-label stmt))) (assemble-label (make-Label (LinkedLabel-linked-to stmt)) blockht))]) (next)] [(DebugPrint? stmt) @@ -197,11 +199,14 @@ EOF [(block-looks-like-context-expected-values? a-basic-block) => (lambda (expected) - (fprintf op "~a=RT.si_context_expected(~a);\n" - (assemble-label (make-Label (BasicBlock-name a-basic-block)) - blockht) - expected) - 'ok)] + (cond + [(= expected 1) + 'ok] + [else + (fprintf op "~a=RT.si_context_expected(~a);\n" + (munge-label-name (make-Label (BasicBlock-name a-basic-block))) + expected) + 'ok]))] [else (default-assemble-basic-block a-basic-block blockht entry-points function-entry-and-exit-names op)])) diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index 1a3e8e8..2466d16 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -675,7 +675,8 @@ // Superinstructions to try to reduce code size. var si_context_expected = function(n) { if (n === 1) { return si_context_expected_1; } - return function(M) { raiseContextExpectedValuesError(M, n); } + var f = function(M) { raiseContextExpectedValuesError(M, n); }; + return f; }; var si_context_expected_1 = function(M) { raiseContextExpectedValuesError(M, 1); } @@ -686,7 +687,6 @@ - ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// From 22eb5fc187f16d79704720d08cc3a7fee811f74e Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Fri, 16 Sep 2011 18:00:05 -0400 Subject: [PATCH 13/22] flagging some things as no-ops --- compiler/optimize-il.rkt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/compiler/optimize-il.rkt b/compiler/optimize-il.rkt index 4c8f921..379b915 100644 --- a/compiler/optimize-il.rkt +++ b/compiler/optimize-il.rkt @@ -180,10 +180,14 @@ (loop (rest stmts)))] [(DebugPrint? a-stmt) - (cons a-stmt (loop (rest stmts)))] + ;(cons a-stmt (loop (rest stmts))) + (loop (rest stmts)) + ] [(Comment? a-stmt) - (cons a-stmt (loop (rest stmts)))] + (loop (rest stmts)) + ;(cons a-stmt (loop (rest stmts))) + ] [(AssignImmediateStatement? a-stmt) (cons (make-AssignImmediateStatement (rewrite-target (AssignImmediateStatement-target a-stmt)) @@ -332,7 +336,8 @@ #f] [(DebugPrint? stmt) - #f] + ;#f + #t] [(AssignImmediateStatement? stmt) (equal? (AssignImmediateStatement-target stmt) From b6fa8a97425b6635ba95c3ed55552d21e990d3e7 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Sat, 17 Sep 2011 21:44:15 -0400 Subject: [PATCH 14/22] jslinting, and removing use of indexOf --- world/raw-jsworld.js | 1525 ++++++------- world/scratch/jsworld/define-effect.rkt | 82 - world/scratch/jsworld/jsworld.js | 1396 ------------ world/scratch/jsworld/jsworld.rkt | 50 - world/scratch/jsworld/private/jsworld.js | 777 ------- .../jsworld/private/jsworld/jsworld.js | 1488 ------------- world/scratch/world/kernel.js | 1938 ----------------- world/scratch/world/kernel.rkt | 3 - 8 files changed, 773 insertions(+), 6486 deletions(-) delete mode 100644 world/scratch/jsworld/define-effect.rkt delete mode 100644 world/scratch/jsworld/jsworld.js delete mode 100644 world/scratch/jsworld/jsworld.rkt delete mode 100644 world/scratch/jsworld/private/jsworld.js delete mode 100644 world/scratch/jsworld/private/jsworld/jsworld.js delete mode 100644 world/scratch/world/kernel.js delete mode 100644 world/scratch/world/kernel.rkt diff --git a/world/raw-jsworld.js b/world/raw-jsworld.js index 97aa7a0..3c6ffc7 100644 --- a/world/raw-jsworld.js +++ b/world/raw-jsworld.js @@ -8,6 +8,8 @@ var rawJsworld = {}; (function() { + 'use strict'; + /* Type signature notation * CPS(a b ... -> c) is used to denote * a b ... (c -> void) -> void @@ -27,22 +29,22 @@ var rawJsworld = {}; // Iterates through an array and applies f to each element using CPS // If an error is thrown, it catches the error and calls f_error on it var forEachK = function(a, f, f_error, k) { - var forEachHelp = function(i) { - if( i >= a.length ) { - if (k) { - return k(); - } else { - return; - } - } + var forEachHelp = function(i) { + if( i >= a.length ) { + if (k) { + return k(); + } else { + return; + } + } - try { - return f(a[i], function() { return forEachHelp(i+1); }); - } catch (e) { - f_error(e); - } - }; - return forEachHelp(0); + try { + return f(a[i], function() { return forEachHelp(i+1); }); + } catch (e) { + f_error(e); + } + }; + return forEachHelp(0); }; @@ -66,38 +68,47 @@ var rawJsworld = {}; + function clear_running_state() { + var i; + world = new InitialWorld(); + worldListeners = []; + + for (i = 0; i < eventDetachers.length; i++) { + eventDetachers[i](); + } + eventDetachers = []; + changingWorld = false; + } + + + // Close all world computations. Jsworld.shutdown = function() { - while(runningBigBangs.length > 0) { - var currentRecord = runningBigBangs.pop(); - if (currentRecord) { currentRecord.pause(); } - } - clear_running_state(); - } + while(runningBigBangs.length > 0) { + var currentRecord = runningBigBangs.pop(); + if (currentRecord) { currentRecord.pause(); } + } + clear_running_state(); + }; function add_world_listener(listener) { - worldListeners.push(listener); + worldListeners.push(listener); } function remove_world_listener(listener) { - var index = worldListeners.indexOf(listener); - if (index != -1) { - worldListeners.splice(index, 1); - } - } - - function clear_running_state() { - world = new InitialWorld(); - worldListeners = []; - - for (var i = 0; i < eventDetachers.length; i++) { - eventDetachers[i](); - } - eventDetachers = []; - changingWorld = false; + var i, index = -1; + for (i = 0; i < worldListeners.length; i++) { + if (worldListeners[i] === listener) { + index = i; + break; + } + } + if (index !== -1) { + worldListeners.splice(index, 1); + } } @@ -105,75 +116,79 @@ var rawJsworld = {}; var DELAY_BEFORE_RETRY = 10; + var WrappedWorldWithEffects; + // change_world: CPS( CPS(world -> world) -> void ) // Adjust the world, and notify all listeners. var change_world = function(updater, k) { - // Check to see if we're in the middle of changing - // the world already. If so, put on the queue - // and exit quickly. - if (changingWorld) { - setTimeout( - function() { - change_world(updater, k)}, - DELAY_BEFORE_RETRY); - return; - } + // Check to see if we're in the middle of changing + // the world already. If so, put on the queue + // and exit quickly. + if (changingWorld) { + setTimeout( + function() { + change_world(updater, k); + }, + DELAY_BEFORE_RETRY); + return; + } - changingWorld = true; - var originalWorld = world; + changingWorld = true; + var originalWorld = world; - var changeWorldHelp = function() { - if (world instanceof WrappedWorldWithEffects) { - var effects = world.getEffects(); - forEachK(effects, - function(anEffect, k2) { - anEffect.invokeEffect(change_world, k2); - }, - function (e) { - changingWorld = false; - throw e; - }, - function() { - world = world.getWorld(); - changeWorldHelp2(); - }); - } else { - changeWorldHelp2(); - } - }; - - var changeWorldHelp2 = function() { - forEachK(worldListeners, - function(listener, k2) { - listener(world, originalWorld, k2); - }, - function(e) { - changingWorld = false; - world = originalWorld; - throw e; }, - function() { - changingWorld = false; - k(); - }); - }; + var changeWorldHelp, changeWorldHelp2; + changeWorldHelp = function() { + if (world instanceof WrappedWorldWithEffects) { + var effects = world.getEffects(); + forEachK(effects, + function(anEffect, k2) { + anEffect.invokeEffect(change_world, k2); + }, + function (e) { + changingWorld = false; + throw e; + }, + function() { + world = world.getWorld(); + changeWorldHelp2(); + }); + } else { + changeWorldHelp2(); + } + }; - try { - updater(world, function(newWorld) { - world = newWorld; - changeWorldHelp(); - }); - } catch(e) { - changingWorld = false; - world = originalWorld; + changeWorldHelp2 = function() { + forEachK(worldListeners, + function(listener, k2) { + listener(world, originalWorld, k2); + }, + function(e) { + changingWorld = false; + world = originalWorld; + throw e; }, + function() { + changingWorld = false; + k(); + }); + }; - if (typeof(console) !== 'undefined' && console.log && e.stack) { - console.log(e.stack); - } - throw e; - } - } + try { + updater(world, function(newWorld) { + world = newWorld; + changeWorldHelp(); + }); + } catch(e) { + changingWorld = false; + world = originalWorld; + + if (typeof(window.console) !== 'undefined' && window.console.log && e.stack) { + window.console.log(e.stack); + } + throw e; + } + }; Jsworld.change_world = change_world; @@ -182,18 +197,18 @@ var rawJsworld = {}; // // STUFF THAT SHOULD REALLY BE IN ECMASCRIPT // - Number.prototype.NaN0=function(){return isNaN(this)?0:this;} + Number.prototype.NaN0=function(){return isNaN(this)?0:this;}; function getPosition(e){ - var left = 0; - var top = 0; - while (e.offsetParent){ - left += e.offsetLeft + (e.currentStyle?(parseInt(e.currentStyle.borderLeftWidth)).NaN0():0); - top += e.offsetTop + (e.currentStyle?(parseInt(e.currentStyle.borderTopWidth)).NaN0():0); - e = e.offsetParent; - } - left += e.offsetLeft + (e.currentStyle?(parseInt(e.currentStyle.borderLeftWidth)).NaN0():0); - top += e.offsetTop + (e.currentStyle?(parseInt(e.currentStyle.borderTopWidth)).NaN0():0); - return {x:left, y:top}; + var left = 0; + var top = 0; + while (e.offsetParent){ + left += e.offsetLeft + (e.currentStyle?(Number(e.currentStyle.borderLeftWidth)).NaN0():0); + top += e.offsetTop + (e.currentStyle?(Number(e.currentStyle.borderTopWidth)).NaN0():0); + e = e.offsetParent; + } + left += e.offsetLeft + (e.currentStyle?(Number(e.currentStyle.borderLeftWidth)).NaN0():0); + top += e.offsetTop + (e.currentStyle?(Number(e.currentStyle.borderTopWidth)).NaN0():0); + return {x:left, y:top}; } Jsworld.getPosition = getPosition; @@ -204,151 +219,158 @@ var rawJsworld = {}; var map = function(a1, f) { - var b = new Array(a1.length); - for (var i = 0; i < a1.length; i++) { - b[i] = f(a1[i]); - } - return b; - } + var b = new Array(a1.length), i; + for (i = 0; i < a1.length; i++) { + b[i] = f(a1[i]); + } + return b; + }; Jsworld.map = map; var concat_map = function(a, f) { - var b = []; - for (var i = 0; i < a.length; i++) { - b = b.concat(f(a[i])); - } - return b; - } + var b = [], i; + for (i = 0; i < a.length; i++) { + b = b.concat(f(a[i])); + } + return b; + }; var mapi = function(a, f) { - var b = new Array(a.length); - for (var i = 0; i < a.length; i++) { - b[i] = f(a[i], i); - } - return b; - } + var b = new Array(a.length), i; + for (i = 0; i < a.length; i++) { + b[i] = f(a[i], i); + } + return b; + }; Jsworld.mapi = mapi; var fold = function(a, x, f) { - for (var i = 0; i < a.length; i++) { - x = f(a[i], x); - } - return x; - } + var i; + for (i = 0; i < a.length; i++) { + x = f(a[i], x); + } + return x; + }; Jsworld.fold = fold; function augment(o, a) { - var oo = {}; - for (var e in o) - oo[e] = o[e]; - for (var e in a) - oo[e] = a[e]; - return oo; - } + var oo = {}; + for (var e in o) { + if (o.hasOwnProperty(e)) { + oo[e] = o[e]; + } + } + for (var e in a) { + if (a.hasOwnProperty(e)) { + oo[e] = a[e]; + } + } + return oo; + }; Jsworld.augment = augment; function assoc_cons(o, k, v) { - var oo = {}; - for (var e in o) - oo[e] = o[e]; - oo[k] = v; - return oo; + var oo = {}; + for (var e in o) + oo[e] = o[e]; + oo[k] = v; + return oo; } Jsworld.assoc_cons = assoc_cons; function cons(value, array) { - return [value].concat(array); + return [value].concat(array); } Jsworld.cons = cons; function append(array1, array2){ - return array1.concat(array2); + return array1.concat(array2); } Jsworld.append = append; function array_join(array1, array2){ - var joined = []; - for (var i = 0; i < array1.length; i++) - joined.push([array1[i], array2[i]]); - return joined; + var joined = []; + for (var i = 0; i < array1.length; i++) + joined.push([array1[i], array2[i]]); + return joined; } Jsworld.array_join = array_join; function removeq(a, value) { - for (var i = 0; i < a.length; i++) - if (a[i] === value){ - return a.slice(0, i).concat(a.slice(i+1)); - } - return a; + for (var i = 0; i < a.length; i++) + if (a[i] === value){ + return a.slice(0, i).concat(a.slice(i+1)); + } + return a; } Jsworld.removeq = removeq; function removef(a, value) { - for (var i = 0; i < a.length; i++) - if ( f(a[i]) ){ - return a.slice(0, i).concat(a.slice(i+1)); - } - return a; + for (var i = 0; i < a.length; i++) + if ( f(a[i]) ){ + return a.slice(0, i).concat(a.slice(i+1)); + } + return a; } Jsworld.removef = removef; function filter(a, f) { - var b = []; - for (var i = 0; i < a.length; i++) { - if ( f(a[i]) ) { - b.push(a[i]); - } - } - return b; + var b = []; + for (var i = 0; i < a.length; i++) { + if ( f(a[i]) ) { + b.push(a[i]); + } + } + return b; } Jsworld.filter = filter; function without(obj, attrib) { - var o = {}; - for (var a in obj) - if (a != attrib) - o[a] = obj[a]; - return o; + var o = {}; + for (var a in obj) + if (a != attrib) + o[a] = obj[a]; + return o; } Jsworld.without = without; function memberq(a, x) { - for (var i = 0; i < a.length; i++) - if (a[i] === x) return true; - return false; + for (var i = 0; i < a.length; i++) + if (a[i] === x) return true; + return false; } Jsworld.memberq = memberq; function member(a, x) { - for (var i = 0; i < a.length; i++) - if (a[i] == x) return true; - return false; + for (var i = 0; i < a.length; i++) + if (a[i] == x) return true; + return false; } Jsworld.member = member; function head(a){ - return a[0]; + return a[0]; } Jsworld.head = head; function tail(a){ - return a.slice(1, a.length); + return a.slice(1, a.length); } Jsworld.tail = tail; @@ -414,11 +436,11 @@ var rawJsworld = {}; // node_to_tree: dom -> dom-tree // Given a native dom node, produces the appropriate tree. function node_to_tree(domNode) { - var result = [domNode]; - for (var c = domNode.firstChild; c != null; c = c.nextSibling) { - result.push(node_to_tree(c)); - } - return result; + var result = [domNode]; + for (var c = domNode.firstChild; c != null; c = c.nextSibling) { + result.push(node_to_tree(c)); + } + return result; } Jsworld.node_to_tree = node_to_tree; @@ -426,329 +448,329 @@ var rawJsworld = {}; // nodes(tree(N)) = nodes(N) function nodes(tree) { - var ret; - - if (tree.node.jsworldOpaque == true) { - return [tree.node]; - } + var ret; + + if (tree.node.jsworldOpaque == true) { + return [tree.node]; + } - ret = [tree.node]; - for (var i = 0; i < tree.children.length; i++) - ret = ret.concat(nodes(tree.children[i])); - - return ret; + ret = [tree.node]; + for (var i = 0; i < tree.children.length; i++) + ret = ret.concat(nodes(tree.children[i])); + + return ret; } // relations(tree(N)) = relations(N) function relations(tree) { - var ret = []; + var ret = []; - for (var i = 0; i < tree.children.length; i++) - ret.push({ relation: 'parent', - parent: tree.node, - child: tree.children[i].node }); - - for (var i = 0; i < tree.children.length - 1; i++) - ret.push({ relation: 'neighbor', - left: tree.children[i].node, - right: tree.children[i + 1].node }); - - if (! tree.node.jsworldOpaque) { - for (var i = 0; i < tree.children.length; i++) { - ret = ret.concat(relations(tree.children[i])); - } - } - - return ret; + for (var i = 0; i < tree.children.length; i++) + ret.push({ relation: 'parent', + parent: tree.node, + child: tree.children[i].node }); + + for (var i = 0; i < tree.children.length - 1; i++) + ret.push({ relation: 'neighbor', + left: tree.children[i].node, + right: tree.children[i + 1].node }); + + if (! tree.node.jsworldOpaque) { + for (var i = 0; i < tree.children.length; i++) { + ret = ret.concat(relations(tree.children[i])); + } + } + + return ret; } var removeAllChildren = function(n) { - while (n.firstChild) { - n.removeChild(n.firstChild); - } + while (n.firstChild) { + n.removeChild(n.firstChild); + } } // Preorder traversal. var preorder = function(node, f) { - f(node, function() { - var child = node.firstChild; - var nextSibling; - while (child) { - var nextSibling = child.nextSibling; - preorder(child, f); - child = nextSibling; - } - }); + f(node, function() { + var child = node.firstChild; + var nextSibling; + while (child) { + var nextSibling = child.nextSibling; + preorder(child, f); + child = nextSibling; + } + }); }; // update_dom(nodes(Node), relations(Node)) = void function update_dom(toplevelNode, nodes, relations) { - // TODO: rewrite this to move stuff all in one go... possible? necessary? - - // move all children to their proper parents - for (var i = 0; i < relations.length; i++) { - if (relations[i].relation == 'parent') { - var parent = relations[i].parent, child = relations[i].child; - if (child.parentNode !== parent) { - parent.appendChild(child); - } - } - } - - // arrange siblings in proper order - // truly terrible... BUBBLE SORT - var unsorted = true; - while (unsorted) { - unsorted = false; - for (var i = 0; i < relations.length; i++) { - if (relations[i].relation == 'neighbor') { - var left = relations[i].left, right = relations[i].right; - - if (! nodeEq(left.nextSibling, right)) { - left.parentNode.insertBefore(left, right) - unsorted = true; - } - } - } - } + // TODO: rewrite this to move stuff all in one go... possible? necessary? + + // move all children to their proper parents + for (var i = 0; i < relations.length; i++) { + if (relations[i].relation == 'parent') { + var parent = relations[i].parent, child = relations[i].child; + if (child.parentNode !== parent) { + parent.appendChild(child); + } + } + } + + // arrange siblings in proper order + // truly terrible... BUBBLE SORT + var unsorted = true; + while (unsorted) { + unsorted = false; + for (var i = 0; i < relations.length; i++) { + if (relations[i].relation == 'neighbor') { + var left = relations[i].left, right = relations[i].right; + + if (! nodeEq(left.nextSibling, right)) { + left.parentNode.insertBefore(left, right) + unsorted = true; + } + } + } + } - // Finally, remove nodes that shouldn't be attached anymore. - var nodesPlus = nodes.concat([toplevelNode]); - preorder(toplevelNode, function(aNode, continueTraversalDown) { - if (aNode.jsworldOpaque) { - if (! isMemq(aNode, nodesPlus)) { - aNode.parentNode.removeChild(aNode); - } - } else { - if (! isMemq(aNode, nodesPlus)) { - aNode.parentNode.removeChild(aNode); - } else { - continueTraversalDown(); - } - } - }); + // Finally, remove nodes that shouldn't be attached anymore. + var nodesPlus = nodes.concat([toplevelNode]); + preorder(toplevelNode, function(aNode, continueTraversalDown) { + if (aNode.jsworldOpaque) { + if (! isMemq(aNode, nodesPlus)) { + aNode.parentNode.removeChild(aNode); + } + } else { + if (! isMemq(aNode, nodesPlus)) { + aNode.parentNode.removeChild(aNode); + } else { + continueTraversalDown(); + } + } + }); - refresh_node_values(nodes); + refresh_node_values(nodes); } // isMemq: X (arrayof X) -> boolean // Produces true if any of the elements of L are nodeEq to x. var isMemq = function(x, L) { - var i; - for (i = 0 ; i < L.length; i++) { - if (nodeEq(x, L[i])) { - return true; - } - } - return false; + var i; + for (i = 0 ; i < L.length; i++) { + if (nodeEq(x, L[i])) { + return true; + } + } + return false; }; // nodeEq: node node -> boolean // Returns true if the two nodes should be the same. var nodeEq = function(node1, node2) { - return (node1 && node2 && node1 === node2); + return (node1 && node2 && node1 === node2); } // camelCase: string -> string function camelCase(name) { - return name.replace(/\-(.)/g, function(m, l){return l.toUpperCase()}); + return name.replace(/\-(.)/g, function(m, l){return l.toUpperCase()}); } function set_css_attribs(node, attribs) { - for (var j = 0; j < attribs.length; j++){ - node.style[camelCase(attribs[j].attrib)] = attribs[j].values.join(" "); - } + for (var j = 0; j < attribs.length; j++){ + node.style[camelCase(attribs[j].attrib)] = attribs[j].values.join(" "); + } } // isMatchingCssSelector: node css -> boolean // Returns true if the CSS selector matches. function isMatchingCssSelector(node, css) { - if (css.id.match(/^\./)) { - // Check to see if we match the class - return ('className' in node && member(node['className'].split(/\s+/), - css.id.substring(1))); - } else { - return ('id' in node && node.id == css.id); - } + if (css.id.match(/^\./)) { + // Check to see if we match the class + return ('className' in node && member(node['className'].split(/\s+/), + css.id.substring(1))); + } else { + return ('id' in node && node.id == css.id); + } } function update_css(nodes, css) { - // clear CSS - for (var i = 0; i < nodes.length; i++) { - if ( !nodes[i].jsworldOpaque ) { - clearCss(nodes[i]); - } - } - - // set CSS - for (var i = 0; i < css.length; i++) - if ('id' in css[i]) { - for (var j = 0; j < nodes.length; j++) - if (isMatchingCssSelector(nodes[j], css[i])) { - set_css_attribs(nodes[j], css[i].attribs); - } - } - else set_css_attribs(css[i].node, css[i].attribs); + // clear CSS + for (var i = 0; i < nodes.length; i++) { + if ( !nodes[i].jsworldOpaque ) { + clearCss(nodes[i]); + } + } + + // set CSS + for (var i = 0; i < css.length; i++) + if ('id' in css[i]) { + for (var j = 0; j < nodes.length; j++) + if (isMatchingCssSelector(nodes[j], css[i])) { + set_css_attribs(nodes[j], css[i].attribs); + } + } + else set_css_attribs(css[i].node, css[i].attribs); } var clearCss = function(node) { - // FIXME: we should not be clearing the css -// if ('style' in node) -// node.style.cssText = ""; + // FIXME: we should not be clearing the css +// if ('style' in node) +// node.style.cssText = ""; } // If any node cares about the world, send it in. function refresh_node_values(nodes) { - for (var i = 0; i < nodes.length; i++) { - if (nodes[i].onWorldChange) { - nodes[i].onWorldChange(world); - } - } + for (var i = 0; i < nodes.length; i++) { + if (nodes[i].onWorldChange) { + nodes[i].onWorldChange(world); + } + } } function do_redraw(world, oldWorld, toplevelNode, redraw_func, redraw_css_func, k) { - if (oldWorld instanceof InitialWorld) { - // Simple path - redraw_func(world, - function(drawn) { - var t = sexp2tree(drawn); - var ns = nodes(t); - // HACK: css before dom, due to excanvas hack. - redraw_css_func(world, - function(css) { - update_css(ns, sexp2css(css)); - update_dom(toplevelNode, ns, relations(t)); - k(); - }); - }); - } else { - maintainingSelection( - function(k2) { - // For legibility, here is the non-CPS version of the same function: - /* - var oldRedraw = redraw_func(oldWorld); - var newRedraw = redraw_func(world); - var oldRedrawCss = redraw_css_func(oldWorld); - var newRedrawCss = redraw_css_func(world); - var t = sexp2tree(newRedraw); - var ns = nodes(t); + if (oldWorld instanceof InitialWorld) { + // Simple path + redraw_func(world, + function(drawn) { + var t = sexp2tree(drawn); + var ns = nodes(t); + // HACK: css before dom, due to excanvas hack. + redraw_css_func(world, + function(css) { + update_css(ns, sexp2css(css)); + update_dom(toplevelNode, ns, relations(t)); + k(); + }); + }); + } else { + maintainingSelection( + function(k2) { + // For legibility, here is the non-CPS version of the same function: + /* + var oldRedraw = redraw_func(oldWorld); + var newRedraw = redraw_func(world); + var oldRedrawCss = redraw_css_func(oldWorld); + var newRedrawCss = redraw_css_func(world); + var t = sexp2tree(newRedraw); + var ns = nodes(t); - // Try to save the current selection and preserve it across - // dom updates. + // Try to save the current selection and preserve it across + // dom updates. - if(oldRedraw !== newRedraw) { - // Kludge: update the CSS styles first. - // This is a workaround an issue with excanvas: any style change - // clears the content of the canvas, so we do this first before - // attaching the dom element. - update_css(ns, sexp2css(newRedrawCss)); - update_dom(toplevelNode, ns, relations(t)); - } else { - if(oldRedrawCss !== newRedrawCss) { - update_css(ns, sexp2css(newRedrawCss)); - } - } - */ + if(oldRedraw !== newRedraw) { + // Kludge: update the CSS styles first. + // This is a workaround an issue with excanvas: any style change + // clears the content of the canvas, so we do this first before + // attaching the dom element. + update_css(ns, sexp2css(newRedrawCss)); + update_dom(toplevelNode, ns, relations(t)); + } else { + if(oldRedrawCss !== newRedrawCss) { + update_css(ns, sexp2css(newRedrawCss)); + } + } + */ - redraw_func( + redraw_func( world, - function(newRedraw) { + function(newRedraw) { - redraw_css_func( + redraw_css_func( world, - function(newRedrawCss) { - var t = sexp2tree(newRedraw); - var ns = nodes(t); + function(newRedrawCss) { + var t = sexp2tree(newRedraw); + var ns = nodes(t); - // Try to save the current selection and preserve it across - // dom updates. + // Try to save the current selection and preserve it across + // dom updates. - // Kludge: update the CSS styles first. - // This is a workaround an issue with excanvas: any style change - // clears the content of the canvas, so we do this first before - // attaching the dom element. - update_css(ns, sexp2css(newRedrawCss)); - update_dom(toplevelNode, ns, relations(t)); + // Kludge: update the CSS styles first. + // This is a workaround an issue with excanvas: any style change + // clears the content of the canvas, so we do this first before + // attaching the dom element. + update_css(ns, sexp2css(newRedrawCss)); + update_dom(toplevelNode, ns, relations(t)); - k2(); - }) - }) + k2(); + }) + }) - }, k); - } + }, k); + } } // maintainingSelection: (-> void) -> void // Calls the thunk f while trying to maintain the current focused selection. function maintainingSelection(f, k) { - var currentFocusedSelection; - if (hasCurrentFocusedSelection()) { - currentFocusedSelection = getCurrentFocusedSelection(); - f(function() { - currentFocusedSelection.restore(); - k(); - }); - } else { - f(function() { k(); }); - } + var currentFocusedSelection; + if (hasCurrentFocusedSelection()) { + currentFocusedSelection = getCurrentFocusedSelection(); + f(function() { + currentFocusedSelection.restore(); + k(); + }); + } else { + f(function() { k(); }); + } } function FocusedSelection() { - this.focused = currentFocusedNode; - this.selectionStart = currentFocusedNode.selectionStart; - this.selectionEnd = currentFocusedNode.selectionEnd; + this.focused = currentFocusedNode; + this.selectionStart = currentFocusedNode.selectionStart; + this.selectionEnd = currentFocusedNode.selectionEnd; } // Try to restore the focus. FocusedSelection.prototype.restore = function() { - // FIXME: if we're scrolling through, what's visible - // isn't restored yet. - if (this.focused.parentNode) { - this.focused.selectionStart = this.selectionStart; - this.focused.selectionEnd = this.selectionEnd; - this.focused.focus(); - } else if (this.focused.id) { - var matching = document.getElementById(this.focused.id); - if (matching) { - matching.selectionStart = this.selectionStart; - matching.selectionEnd = this.selectionEnd; - matching.focus(); - } - } + // FIXME: if we're scrolling through, what's visible + // isn't restored yet. + if (this.focused.parentNode) { + this.focused.selectionStart = this.selectionStart; + this.focused.selectionEnd = this.selectionEnd; + this.focused.focus(); + } else if (this.focused.id) { + var matching = document.getElementById(this.focused.id); + if (matching) { + matching.selectionStart = this.selectionStart; + matching.selectionEnd = this.selectionEnd; + matching.focus(); + } + } }; function hasCurrentFocusedSelection() { - return currentFocusedNode != undefined; + return currentFocusedNode != undefined; } function getCurrentFocusedSelection() { - return new FocusedSelection(); + return new FocusedSelection(); } @@ -756,25 +778,25 @@ var rawJsworld = {}; ////////////////////////////////////////////////////////////////////// function BigBangRecord(top, world, handlerCreators, handlers, attribs) { - this.top = top; - this.world = world; - this.handlers = handlers; - this.handlerCreators = handlerCreators; - this.attribs = attribs; + this.top = top; + this.world = world; + this.handlers = handlers; + this.handlerCreators = handlerCreators; + this.attribs = attribs; } BigBangRecord.prototype.restart = function() { - bigBang(this.top, this.world, this.handlerCreators, this.attribs); + bigBang(this.top, this.world, this.handlerCreators, this.attribs); } BigBangRecord.prototype.pause = function() { - for(var i = 0 ; i < this.handlers.length; i++) { - if (this.handlers[i] instanceof StopWhenHandler) { - // Do nothing for now. - } else { - this.handlers[i].onUnregister(top); - } - } + for(var i = 0 ; i < this.handlers.length; i++) { + if (this.handlers[i] instanceof StopWhenHandler) { + // Do nothing for now. + } else { + this.handlers[i].onUnregister(top); + } + } }; ////////////////////////////////////////////////////////////////////// @@ -787,64 +809,64 @@ var rawJsworld = {}; // handlerCreators: (Arrayof (-> handler)) // k: any -> void function bigBang(top, init_world, handlerCreators, attribs, succ) { - // clear_running_state(); + // clear_running_state(); - // Construct a fresh set of the handlers. - var handlers = map(handlerCreators, function(x) { return x();} ); - if (runningBigBangs.length > 0) { - runningBigBangs[runningBigBangs.length - 1].pause(); - } + // Construct a fresh set of the handlers. + var handlers = map(handlerCreators, function(x) { return x();} ); + if (runningBigBangs.length > 0) { + runningBigBangs[runningBigBangs.length - 1].pause(); + } - // Create an activation record for this big-bang. - var activationRecord = - new BigBangRecord(top, init_world, handlerCreators, handlers, attribs); - runningBigBangs.push(activationRecord); - function keepRecordUpToDate(w, oldW, k2) { - activationRecord.world = w; - k2(); - } - add_world_listener(keepRecordUpToDate); + // Create an activation record for this big-bang. + var activationRecord = + new BigBangRecord(top, init_world, handlerCreators, handlers, attribs); + runningBigBangs.push(activationRecord); + function keepRecordUpToDate(w, oldW, k2) { + activationRecord.world = w; + k2(); + } + add_world_listener(keepRecordUpToDate); - // Monitor for termination and register the other handlers. - var stopWhen = new StopWhenHandler(function(w, k2) { k2(false); }, - function(w, k2) { k2(w); }); - for(var i = 0 ; i < handlers.length; i++) { - if (handlers[i] instanceof StopWhenHandler) { - stopWhen = handlers[i]; - } else { - handlers[i].onRegister(top); - } - } - var watchForTermination = function(w, oldW, k2) { - stopWhen.test(w, - function(stop) { - if (stop) { - Jsworld.shutdown(); - succ(w); - /* - stopWhen.receiver(world, - function() { - var currentRecord = runningBigBangs.pop(); - if (currentRecord) { currentRecord.pause(); } - if (runningBigBangs.length > 0) { - var restartingBigBang = runningBigBangs.pop(); - restartingBigBang.restart(); - } - k(); - }); - */ - } - else { k2(); } - }); - }; - add_world_listener(watchForTermination); + // Monitor for termination and register the other handlers. + var stopWhen = new StopWhenHandler(function(w, k2) { k2(false); }, + function(w, k2) { k2(w); }); + for(var i = 0 ; i < handlers.length; i++) { + if (handlers[i] instanceof StopWhenHandler) { + stopWhen = handlers[i]; + } else { + handlers[i].onRegister(top); + } + } + var watchForTermination = function(w, oldW, k2) { + stopWhen.test(w, + function(stop) { + if (stop) { + Jsworld.shutdown(); + succ(w); + /* + stopWhen.receiver(world, + function() { + var currentRecord = runningBigBangs.pop(); + if (currentRecord) { currentRecord.pause(); } + if (runningBigBangs.length > 0) { + var restartingBigBang = runningBigBangs.pop(); + restartingBigBang.restart(); + } + k(); + }); + */ + } + else { k2(); } + }); + }; + add_world_listener(watchForTermination); - // Finally, begin the big-bang. - copy_attribs(top, attribs); - change_world(function(w, k2) { k2(init_world); }, doNothing); + // Finally, begin the big-bang. + copy_attribs(top, attribs); + change_world(function(w, k2) { k2(init_world); }, doNothing); } @@ -856,63 +878,63 @@ var rawJsworld = {}; // on_tick: number CPS(world -> world) -> handler var on_tick = function(delay, tick) { - return function() { - var scheduleTick, ticker; + return function() { + var scheduleTick, ticker; - (new Date()).valueOf() + (new Date()).valueOf() - scheduleTick = function(t) { - ticker.watchId = setTimeout( - function() { - ticker.watchId = undefined; - var startTime = (new Date()).valueOf(); - change_world(tick, - function() { - var endTime = (new Date()).valueOf(); - scheduleTick(Math.max(delay - (endTime - startTime), - 0)); - }); - }, - t); - }; - - ticker = { - watchId: -1, - onRegister: function (top) { - scheduleTick(delay); - }, + scheduleTick = function(t) { + ticker.watchId = setTimeout( + function() { + ticker.watchId = undefined; + var startTime = (new Date()).valueOf(); + change_world(tick, + function() { + var endTime = (new Date()).valueOf(); + scheduleTick(Math.max(delay - (endTime - startTime), + 0)); + }); + }, + t); + }; + + ticker = { + watchId: -1, + onRegister: function (top) { + scheduleTick(delay); + }, - onUnregister: function (top) { - if (ticker.watchId) - clearTimeout(ticker.watchId); - } - }; - return ticker; - }; + onUnregister: function (top) { + if (ticker.watchId) + clearTimeout(ticker.watchId); + } + }; + return ticker; + }; } Jsworld.on_tick = on_tick; function on_key(press) { - return function() { - var wrappedPress = function(e) { - preventDefault(e); - stopPropagation(e); - change_world(function(w, k) { press(w, e, k); }, doNothing); - }; - return { - onRegister: function(top) { + return function() { + var wrappedPress = function(e) { + preventDefault(e); + stopPropagation(e); + change_world(function(w, k) { press(w, e, k); }, doNothing); + }; + return { + onRegister: function(top) { //http://www.w3.org/TR/html5/editing.html#sequential-focus-navigation-and-the-tabindex-attribue $(top).attr('tabindex', 1); $(top).focus(); attachEvent(top, 'keydown', wrappedPress); }, - onUnregister: function(top) { + onUnregister: function(top) { detachEvent(top, 'keydown', wrappedPress); } - }; - } + }; + } } Jsworld.on_key = on_key; @@ -922,12 +944,12 @@ var rawJsworld = {}; // http://www.quirksmode.org/js/events_mouse.html // http://stackoverflow.com/questions/55677/how-do-i-get-the-coordinates-of-a-mouse-click-on-a-canvas-element function on_mouse(mouse) { - return function() { + return function() { var isButtonDown = false; - var makeWrapped = function(type) { + var makeWrapped = function(type) { return function(e) { - preventDefault(e); - stopPropagation(e); + preventDefault(e); + stopPropagation(e); var x = e.pageX, y = e.pageY; var currentElement = e.target; do { @@ -941,15 +963,15 @@ var rawJsworld = {}; isButtonDown = false; } if (type === 'move' && isButtonDown) { - change_world(function(w, k) { + change_world(function(w, k) { mouse(w, x, y, 'drag', k); }, doNothing); } else { - change_world(function(w, k) { + change_world(function(w, k) { mouse(w, x, y, type, k); }, doNothing); } - }; + }; }; var wrappedDown = makeWrapped('button-down'); var wrappedUp = makeWrapped('button-up'); @@ -957,23 +979,23 @@ var rawJsworld = {}; var wrappedMove = makeWrapped('move'); var wrappedEnter = makeWrapped('enter'); var wrappedLeave = makeWrapped('leave'); - return { - onRegister: function(top) { + return { + onRegister: function(top) { attachEvent(top, 'mousedown', wrappedDown); attachEvent(top, 'mouseup', wrappedUp); attachEvent(top, 'mousemove', wrappedMove); attachEvent(top, 'mouseenter', wrappedEnter); attachEvent(top, 'mouseleave', wrappedLeave); }, - onUnregister: function(top) { + onUnregister: function(top) { detachEvent(top, 'mousedown', wrappedDown); detachEvent(top, 'mouseup', wrappedUp); detachEvent(top, 'mousemove', wrappedMove); detachEvent(top, 'mouseenter', wrappedEnter); detachEvent(top, 'mouseleave', wrappedLeave); } - }; - } + }; + } } Jsworld.on_mouse = on_mouse; @@ -985,62 +1007,62 @@ var rawJsworld = {}; // on_draw: CPS(world -> (sexpof node)) CPS(world -> (sexpof css-style)) -> handler function on_draw(redraw, redraw_css) { - var wrappedRedraw = function(w, k) { - redraw(w, function(newDomTree) { - checkDomSexp(newDomTree, newDomTree); - k(newDomTree); - }); - } + var wrappedRedraw = function(w, k) { + redraw(w, function(newDomTree) { + checkDomSexp(newDomTree, newDomTree); + k(newDomTree); + }); + } - return function() { - var drawer = { - _top: null, - _listener: function(w, oldW, k2) { - do_redraw(w, oldW, drawer._top, wrappedRedraw, redraw_css, k2); - }, - onRegister: function (top) { - drawer._top = top; - add_world_listener(drawer._listener); - }, + return function() { + var drawer = { + _top: null, + _listener: function(w, oldW, k2) { + do_redraw(w, oldW, drawer._top, wrappedRedraw, redraw_css, k2); + }, + onRegister: function (top) { + drawer._top = top; + add_world_listener(drawer._listener); + }, - onUnregister: function (top) { - remove_world_listener(drawer._listener); - } - }; - return drawer; - }; + onUnregister: function (top) { + remove_world_listener(drawer._listener); + } + }; + return drawer; + }; } Jsworld.on_draw = on_draw; function StopWhenHandler(test, receiver) { - this.test = test; - this.receiver = receiver; + this.test = test; + this.receiver = receiver; } // stop_when: CPS(world -> boolean) CPS(world -> boolean) -> handler function stop_when(test, receiver) { - return function() { - if (receiver == undefined) { - receiver = function(w, k) { k(w); }; - } - return new StopWhenHandler(test, receiver); - }; + return function() { + if (receiver == undefined) { + receiver = function(w, k) { k(w); }; + } + return new StopWhenHandler(test, receiver); + }; } Jsworld.stop_when = stop_when; function on_world_change(f) { - var listener = function(world, oldW, k) { f(world, k); }; - return function() { - return { - onRegister: function (top) { - add_world_listener(listener); }, - onUnregister: function (top) { - remove_world_listener(listener)} - }; - }; + var listener = function(world, oldW, k) { f(world, k); }; + return function() { + return { + onRegister: function (top) { + add_world_listener(listener); }, + onUnregister: function (top) { + remove_world_listener(listener)} + }; + }; } Jsworld.on_world_change = on_world_change; @@ -1050,23 +1072,23 @@ var rawJsworld = {}; // Compatibility for attaching events to nodes. function attachEvent(node, eventName, fn) { - if (node.addEventListener) { - // Mozilla - node.addEventListener(eventName, fn, false); - } else { - // IE - node.attachEvent('on' + eventName, fn, false); - } + if (node.addEventListener) { + // Mozilla + node.addEventListener(eventName, fn, false); + } else { + // IE + node.attachEvent('on' + eventName, fn, false); + } } var detachEvent = function(node, eventName, fn) { - if (node.addEventListener) { - // Mozilla - node.removeEventListener(eventName, fn, false); - } else { - // IE - node.detachEvent('on' + eventName, fn, false); - } + if (node.addEventListener) { + // Mozilla + node.removeEventListener(eventName, fn, false); + } else { + // IE + node.detachEvent('on' + eventName, fn, false); + } } // @@ -1076,34 +1098,34 @@ var rawJsworld = {}; // add_ev: node string CPS(world event -> world) -> void // Attaches a world-updating handler when the world is changed. function add_ev(node, event, f) { - var eventHandler = function(e) { change_world(function(w, k) { f(w, e, k); }, - doNothing); }; - attachEvent(node, event, eventHandler); - eventDetachers.push(function() { detachEvent(node, event, eventHandler); }); + var eventHandler = function(e) { change_world(function(w, k) { f(w, e, k); }, + doNothing); }; + attachEvent(node, event, eventHandler); + eventDetachers.push(function() { detachEvent(node, event, eventHandler); }); } // add_ev_after: node string CPS(world event -> world) -> void // Attaches a world-updating handler when the world is changed, but only // after the fired event has finished. function add_ev_after(node, event, f) { - var eventHandler = function(e) { - setTimeout(function() { change_world(function(w, k) { f(w, e, k); }, - doNothing); }, - 0); - }; + var eventHandler = function(e) { + setTimeout(function() { change_world(function(w, k) { f(w, e, k); }, + doNothing); }, + 0); + }; - attachEvent(node, event, eventHandler); - eventDetachers.push(function() { detachEvent(node, event, eventHandler); }); + attachEvent(node, event, eventHandler); + eventDetachers.push(function() { detachEvent(node, event, eventHandler); }); } function addFocusTracking(node) { - attachEvent(node, "focus", function(e) { - currentFocusedNode = node; }); - attachEvent(node, "blur", function(e) { - currentFocusedNode = undefined; - }); - return node; + attachEvent(node, "focus", function(e) { + currentFocusedNode = node; }); + attachEvent(node, "blur", function(e) { + currentFocusedNode = undefined; + }); + return node; } @@ -1116,89 +1138,89 @@ var rawJsworld = {}; function sexp2tree(sexp) { - if(sexp.length == undefined) return { node: sexp, children: [] }; - else return { node: sexp[0], children: map(sexp.slice(1), sexp2tree) }; + if(sexp.length == undefined) return { node: sexp, children: [] }; + else return { node: sexp[0], children: map(sexp.slice(1), sexp2tree) }; } function sexp2attrib(sexp) { - return { attrib: sexp[0], values: sexp.slice(1) }; + return { attrib: sexp[0], values: sexp.slice(1) }; } function sexp2css_node(sexp) { - var attribs = map(sexp.slice(1), sexp2attrib); - if (typeof sexp[0] == 'string'){ - return [{ id: sexp[0], attribs: attribs }]; - } else if ('length' in sexp[0]){ - return map(sexp[0], function (id) { return { id: id, attribs: attribs } }); - } else { - return [{ node: sexp[0], attribs: attribs }]; - } + var attribs = map(sexp.slice(1), sexp2attrib); + if (typeof sexp[0] == 'string'){ + return [{ id: sexp[0], attribs: attribs }]; + } else if ('length' in sexp[0]){ + return map(sexp[0], function (id) { return { id: id, attribs: attribs } }); + } else { + return [{ node: sexp[0], attribs: attribs }]; + } } function sexp2css(sexp) { - return concat_map(sexp, sexp2css_node); + return concat_map(sexp, sexp2css_node); } function isTextNode(n) { - return (n.nodeType == Node.TEXT_NODE); + return (n.nodeType == Node.TEXT_NODE); }; function isElementNode(n) { - return (n.nodeType == Node.ELEMENT_NODE); + return (n.nodeType == Node.ELEMENT_NODE); }; var throwDomError = function(thing, topThing) { - throw new JsworldDomError( - plt.baselib.format.format( - "Expected a non-empty array, received ~s within ~s", - [thing, topThing]), - thing); + throw new JsworldDomError( + plt.baselib.format.format( + "Expected a non-empty array, received ~s within ~s", + [thing, topThing]), + thing); }; // checkDomSexp: X X -> boolean // Checks to see if thing is a DOM-sexp. If not, // throws an object that explains why not. function checkDomSexp(thing, topThing) { - if (! thing instanceof Array) { - throwDomError(thing, topThing); - } - if (thing.length == 0) { - throwDomError(thing, topThing); - } + if (! thing instanceof Array) { + throwDomError(thing, topThing); + } + if (thing.length == 0) { + throwDomError(thing, topThing); + } - // Check that the first element is a Text or an element. - if (isTextNode(thing[0])) { - if (thing.length > 1) { - throw new JsworldDomError(plt.baselib.format.format("Text node ~s can not have children", - [thing]), - thing); - } - } else if (isElementNode(thing[0])) { - for (var i = 1; i < thing.length; i++) { - checkDomSexp(thing[i], thing); - } - } else { + // Check that the first element is a Text or an element. + if (isTextNode(thing[0])) { + if (thing.length > 1) { + throw new JsworldDomError(plt.baselib.format.format("Text node ~s can not have children", + [thing]), + thing); + } + } else if (isElementNode(thing[0])) { + for (var i = 1; i < thing.length; i++) { + checkDomSexp(thing[i], thing); + } + } else { console.log(thing[0]); - throw new JsworldDomError( - plt.baselib.format.format( - "expected a Text or an Element, received ~s within ~s", - [thing, topThing]), - thing[0]); - } + throw new JsworldDomError( + plt.baselib.format.format( + "expected a Text or an Element, received ~s within ~s", + [thing, topThing]), + thing[0]); + } } function JsworldDomError(msg, elt) { - this.msg = msg; - this.elt = elt; + this.msg = msg; + this.elt = elt; } JsworldDomError.prototype.toString = function() { - return "JsworldDomError: " + this.msg; + return "JsworldDomError: " + this.msg; } @@ -1211,17 +1233,17 @@ var rawJsworld = {}; function copy_attribs(node, attribs) { - if (attribs) - for (a in attribs) { - if (attribs.hasOwnProperty(a)) { - if (typeof attribs[a] == 'function') - add_ev(node, a, attribs[a]); - else{ - node[a] = attribs[a];//eval("node."+a+"='"+attribs[a]+"'"); - } - } - } - return node; + if (attribs) + for (a in attribs) { + if (attribs.hasOwnProperty(a)) { + if (typeof attribs[a] == 'function') + add_ev(node, a, attribs[a]); + else{ + node[a] = attribs[a];//eval("node."+a+"='"+attribs[a]+"'"); + } + } + } + return node; } @@ -1230,22 +1252,22 @@ var rawJsworld = {}; // function p(attribs) { - return addFocusTracking(copy_attribs(document.createElement('p'), attribs)); + return addFocusTracking(copy_attribs(document.createElement('p'), attribs)); } Jsworld.p = p; function div(attribs) { - return addFocusTracking(copy_attribs(document.createElement('div'), attribs)); + return addFocusTracking(copy_attribs(document.createElement('div'), attribs)); } Jsworld.div = div; // Used To Be: (world event -> world) (hashof X Y) -> domElement // Now: CPS(world event -> world) (hashof X Y) -> domElement function button(f, attribs) { - var n = document.createElement('button'); - n.onclick = function(e) {return false;}; - add_ev(n, 'click', f); - return addFocusTracking(copy_attribs(n, attribs)); + var n = document.createElement('button'); + n.onclick = function(e) {return false;}; + add_ev(n, 'click', f); + return addFocusTracking(copy_attribs(n, attribs)); } Jsworld.button = button; @@ -1253,47 +1275,47 @@ var rawJsworld = {}; var preventDefault = function(event) { - if (event.preventDefault) { - event.preventDefault(); - } else { - event.returnValue = false; - } + if (event.preventDefault) { + event.preventDefault(); + } else { + event.returnValue = false; + } } var stopPropagation = function(event) { - if (event.stopPropagation) { - event.stopPropagation(); - } else { - event.cancelBubble = true; - } + if (event.stopPropagation) { + event.stopPropagation(); + } else { + event.cancelBubble = true; + } } var stopClickPropagation = function(node) { - attachEvent(node, "click", - function(e) { - stopPropagation(e); - }); - return node; + attachEvent(node, "click", + function(e) { + stopPropagation(e); + }); + return node; } // input: string CPS(world -> world) function input(aType, updateF, attribs) { - aType = aType.toLowerCase(); - var dispatchTable = { text : text_input, - password: text_input, - checkbox: checkbox_input - //button: button_input, - //radio: radio_input - }; + aType = aType.toLowerCase(); + var dispatchTable = { text : text_input, + password: text_input, + checkbox: checkbox_input + //button: button_input, + //radio: radio_input + }; - if (dispatchTable[aType]) { - return (dispatchTable[aType])(aType, updateF, attribs); - } - else { - throw new Error("js-input: does not currently support type " + aType); - } + if (dispatchTable[aType]) { + return (dispatchTable[aType])(aType, updateF, attribs); + } + else { + throw new Error("js-input: does not currently support type " + aType); + } } Jsworld.input = input; @@ -1301,58 +1323,58 @@ var rawJsworld = {}; var text_input = function(type, updateF, attribs) { - var n = document.createElement('input'); - n.type = type; + var n = document.createElement('input'); + n.type = type; - var lastVal = n.value; - var onEvent = function() { - if (! n.parentNode) { return; } - setTimeout( - function() { - if (lastVal != n.value) { - lastVal = n.value; - change_world(function (w, k) { - updateF(w, n.value, k); - }, doNothing); - } - }, - 0); - } + var lastVal = n.value; + var onEvent = function() { + if (! n.parentNode) { return; } + setTimeout( + function() { + if (lastVal != n.value) { + lastVal = n.value; + change_world(function (w, k) { + updateF(w, n.value, k); + }, doNothing); + } + }, + 0); + } - attachEvent(n, "keydown", onEvent); - eventDetachers.push(function() { - detachEvent(n, "keydown", onEvent); }); + attachEvent(n, "keydown", onEvent); + eventDetachers.push(function() { + detachEvent(n, "keydown", onEvent); }); - attachEvent(n, "change", onEvent); - eventDetachers.push(function() { - detachEvent(n, "change", onEvent); }); + attachEvent(n, "change", onEvent); + eventDetachers.push(function() { + detachEvent(n, "change", onEvent); }); - return stopClickPropagation( - addFocusTracking(copy_attribs(n, attribs))); + return stopClickPropagation( + addFocusTracking(copy_attribs(n, attribs))); }; var checkbox_input = function(type, updateF, attribs) { - var n = document.createElement('input'); - n.type = type; - var onCheck = function(w, e, k) { - updateF(w, n.checked, k); - }; - // This established the widget->world direction - add_ev_after(n, 'change', onCheck); - - attachEvent(n, 'click', function(e) { - stopPropagation(e); - }); + var n = document.createElement('input'); + n.type = type; + var onCheck = function(w, e, k) { + updateF(w, n.checked, k); + }; + // This established the widget->world direction + add_ev_after(n, 'change', onCheck); + + attachEvent(n, 'click', function(e) { + stopPropagation(e); + }); - return copy_attribs(n, attribs); + return copy_attribs(n, attribs); }; var button_input = function(type, updateF, attribs) { - var n = document.createElement('button'); - add_ev(n, 'click', function(w, e, k) { updateF(w, n.value, k); }); - return addFocusTracking(copy_attribs(n, attribs)); + var n = document.createElement('button'); + add_ev(n, 'click', function(w, e, k) { updateF(w, n.value, k); }); + return addFocusTracking(copy_attribs(n, attribs)); }; @@ -1360,61 +1382,61 @@ var rawJsworld = {}; function text(s, attribs) { - var result = document.createElement("div"); - result.appendChild(document.createTextNode(String(s))); - result.jsworldOpaque = true; - return result; + var result = document.createElement("div"); + result.appendChild(document.createTextNode(String(s))); + result.jsworldOpaque = true; + return result; } Jsworld.text = text; function select(attribs, opts, f){ - var n = document.createElement('select'); - for(var i = 0; i < opts.length; i++) { - n.add(option({value: opts[i]}), null); - } - n.jsworldOpaque = true; - add_ev(n, 'change', f); - var result = addFocusTracking(copy_attribs(n, attribs)); - return result; + var n = document.createElement('select'); + for(var i = 0; i < opts.length; i++) { + n.add(option({value: opts[i]}), null); + } + n.jsworldOpaque = true; + add_ev(n, 'change', f); + var result = addFocusTracking(copy_attribs(n, attribs)); + return result; } Jsworld.select = select; function option(attribs){ - var node = document.createElement("option"); + var node = document.createElement("option"); node.text = attribs.value; - node.value = attribs.value; - return node; + node.value = attribs.value; + return node; } function textarea(attribs){ - return addFocusTracking(copy_attribs(document.createElement('textarea'), attribs)); + return addFocusTracking(copy_attribs(document.createElement('textarea'), attribs)); } Jsworld.textarea = textarea; function h1(attribs){ - return addFocusTracking(copy_attribs(document.createElement('h1'), attribs)); + return addFocusTracking(copy_attribs(document.createElement('h1'), attribs)); } Jsworld.h1 = h1; function canvas(attribs){ - return addFocusTracking(copy_attribs(document.createElement('canvas'), attribs)); + return addFocusTracking(copy_attribs(document.createElement('canvas'), attribs)); } Jsworld.canvas = canvas; function img(src, attribs) { - var n = document.createElement('img'); - n.src = src; - return addFocusTracking(copy_attribs(n, attribs)); + var n = document.createElement('img'); + n.src = src; + return addFocusTracking(copy_attribs(n, attribs)); } Jsworld.img = img; function raw_node(node, attribs) { - return addFocusTracking(copy_attribs(node, attribs)); + return addFocusTracking(copy_attribs(node, attribs)); } Jsworld.raw_node = raw_node; @@ -1427,38 +1449,37 @@ var rawJsworld = {}; // Effects // An effect is an object with an invokeEffect() method. - - var WrappedWorldWithEffects = function(w, effects) { - if (w instanceof WrappedWorldWithEffects) { - this.w = w.w; - this.e = w.e.concat(effects); - } else { - this.w = w; - this.e = effects; - } + WrappedWorldWithEffects = function(w, effects) { + if (w instanceof WrappedWorldWithEffects) { + this.w = w.w; + this.e = w.e.concat(effects); + } else { + this.w = w; + this.e = effects; + } }; WrappedWorldWithEffects.prototype.getWorld = function() { - return this.w; + return this.w; }; WrappedWorldWithEffects.prototype.getEffects = function() { - return this.e; + return this.e; }; ////////////////////////////////////////////////////////////////////// Jsworld.with_effect = function(w, e) { - return new WrappedWorldWithEffects(w, [e]); + return new WrappedWorldWithEffects(w, [e]); }; Jsworld.with_multiple_effects = function(w, effects) { - return new WrappedWorldWithEffects(w, effects); + return new WrappedWorldWithEffects(w, effects); }; Jsworld.has_effects = function(w) { - return w instanceof WrappedWorldWithEffects; + return w instanceof WrappedWorldWithEffects; }; diff --git a/world/scratch/jsworld/define-effect.rkt b/world/scratch/jsworld/define-effect.rkt deleted file mode 100644 index 0b4e8f9..0000000 --- a/world/scratch/jsworld/define-effect.rkt +++ /dev/null @@ -1,82 +0,0 @@ -#lang s-exp "../lang/base.rkt" - -(require "jsworld.rkt") - -(require (for-syntax racket/base)) - -(provide define-effect) - -(define-syntax (define-effect stx) - (syntax-case stx () - - [(_ name (field ...) #:impl impl) - (identifier? #'name) - (syntax/loc stx - (define-effect (name #f) (field ...) #:impl impl))] - - [(_ (name supertype) (field ...) #:impl impl) - (with-syntax ([field-count - (length (syntax->list #'(field ...)))] - [struct:name - (datum->syntax #'name - (string->symbol - (format "struct:~a" - (syntax-e #'name))))] - [make-name - (datum->syntax #'name - (string->symbol - (format "make-~a" - (syntax-e #'name))))] - [name? - (datum->syntax #'name - (string->symbol - (format "~a?" - (syntax-e #'name))))] - [(field-index ...) - (build-list (length (syntax->list - #'(field ...))) - (lambda (i) i))] - [(accessor ...) - (map (lambda (field) - (datum->syntax - field - (string->symbol - (format "~a-~a" - (syntax-e #'name) - (syntax-e field))))) - (syntax->list #'(field ...)))] - - [(mutator ...) - (map (lambda (field) - (datum->syntax - field - (string->symbol - (format "set-~a-~a!" - (syntax-e #'name) - (syntax-e field))))) - (syntax->list #'(field ...)))]) - - (syntax/loc stx - (begin (define-values (struct:name - make-name - name? - name-accessor - name-mutator) - (make-effect-type 'name - supertype - field-count - impl)) - (begin - (define accessor - (make-struct-field-accessor - name-accessor field-index 'field)) - ...) - - (begin - (define mutator - (make-struct-field-mutator - name-mutator field-index 'field)) - ...) - - )))])) - \ No newline at end of file diff --git a/world/scratch/jsworld/jsworld.js b/world/scratch/jsworld/jsworld.js deleted file mode 100644 index 748ee1e..0000000 --- a/world/scratch/jsworld/jsworld.js +++ /dev/null @@ -1,1396 +0,0 @@ - -/************************ - *** World Primitives *** - ************************/ - -var PrimProc = types.PrimProc; -var CasePrimitive = types.CasePrimitive; -var makeOptionPrimitive = types.makeOptionPrimitive; -var checkListOf = helpers.checkListOf; -var procArityContains = helpers.procArityContains; -var raise = helpers.raise; - - -var makeCaller = function(aState) { - return function(operator, operands, k, callSite) { - interpret.call(aState, operator, operands, k, aState.onFail, callSite); - }; -}; - - - - -// Every world configuration function (on-tick, stop-when, ...) -// produces a WorldConfigOption instance. -var WorldConfigOption = function(name) { - this.name = name; -}; - -WorldConfigOption.prototype.configure = function(config) { - raise(types.incompleteExn( - types.exnFailContract, - 'unimplemented WorldConfigOption', - [])); -}; - -WorldConfigOption.prototype.toDomNode = function(cache) { - var div = document.createElement('div'); - div.appendChild(document.createTextNode("(" + this.name + " ...)")); - return div; -}; - -WorldConfigOption.prototype.toWrittenString = function(cache) { - return "(" + this.name + " ...)"; -}; - -WorldConfigOption.prototype.toDisplayedString = function(cache) { - return "(" + this.name + " ...)"; -}; - - - -var isWorldConfigOption = function(x) { return x instanceof WorldConfigOption; }; - - - - - -// convertAttribList: (listof (list string (or string boolean))) -> (hashof string string) -var convertAttribList = function(attribList) { - var newList = types.EMPTY; - var nextElt; - var key, val; - while (!types.isEmpty(attribList)) { - nextElt = attribList.first(); - - key = nextElt.first(); - val = nextElt.rest().first(); - - key = String(key); - - if (types.isString(val)) { - val = String(val); - } else if (types.isBoolean(val)) { - // do nothing: the representation is the same. - } else if (types.isSymbol(val)) { - if (String(val) === 'true') { - val = true; - } else if (String(val) === 'false') { - val = false; - } else { - val = String(val); - } - } else { - // raise error: neither string nor boolean - raise(types.incompleteExn( - types.exnFailContract, - helpers.format( - "attribute value ~s neither a string nor a boolean", - [val]), - [])); - } - // ensure each element in the hash are primitive strings - newList = types.cons(types.list([key, val]), - newList); - attribList = attribList.rest(); - } - return helpers.assocListToHash(newList); -} - - - - -////////////////////////////////////////////////////////////////////// - - - - -EXPORTS['key=?'] = - new PrimProc('key=?', - 2, - false, false, - function(key1, key2) { - return (String(key1).toLowerCase() === - String(key2).toLowerCase()); - }); - - - - - -var OnTickBang = function(handler, effectHandler, aDelay) { - WorldConfigOption.call(this, 'on-tick'); - this.handler = handler; - this.effectHandler = effectHandler; - this.aDelay = aDelay; -}; - -OnTickBang.prototype = helpers.heir(WorldConfigOption.prototype); - -OnTickBang.prototype.configure = function(config) { - var newVals = { - onTick: this.handler, - onTickEffect: this.effectHandler, - tickDelay: jsnums.toFixnum(jsnums.multiply(1000, this.aDelay)) - }; - return config.updateAll(newVals); -}; - - - - -// The default tick delay is 28 times a second. -var DEFAULT_TICK_DELAY = types.rational(1, 28); - -EXPORTS['on-tick'] = - new CasePrimitive( - 'on-tick', - [new PrimProc('on-tick', - 1, - false, false, - function(f) { - check(f, isFunction, "on-tick", "procedure", 1); - return new OnTickBang(f, - new PrimProc('', 1, false, false, - function(w) { return types.effectDoNothing(); }), - DEFAULT_TICK_DELAY); - }), - new PrimProc('on-tick', - 2, - false, false, - function(f, aDelay) { - check(f, isFunction, "on-tick", "procedure", 1, arguments); - check(aDelay, isNumber, "on-tick", "number", 2, arguments); - return new OnTickBang(f, - new PrimProc('', 1, false, false, - function(w) { return types.effectDoNothing(); }), - aDelay); - }) ]); - - - -EXPORTS['on-tick!'] = - new CasePrimitive('on-tick!', - [new PrimProc('on-tick!', - 2, - false, false, - function(handler, effectHandler) { - check(handler, isFunction, "on-tick!", "procedure", 1, arguments); - check(effectHandler, isFunction, "on-tick!","procedure", 2, arguments); - return new OnTickBang(handler, effectHandler, DEFAULT_TICK_DELAY); - }), - new PrimProc('on-tick!', - 3, - false, false, - function(handler, effectHandler, aDelay) { - check(handler, isFunction, "on-tick!", "procedure", 1, arguments); - check(effectHandler, isFunction, "on-tick!","procedure", 2, arguments); - check(aDelay, isNumber, "on-tick!", "number", 3, arguments); - return new OnTickBang(handler, effectHandler, aDelay); - }) ]); - - - -var onEvent = function(funName, inConfigName, numArgs) { - return function(handler) { - return onEventBang(funName, inConfigName)(handler, - new PrimProc('', numArgs, false, false, function() { return types.EMPTY; })); - }; -}; - - -var onEventBang = function(funName, inConfigName) { - - var CustomConfigOption = function(handler, effectHandler) { - WorldConfigOption.call(this, funName); - this.handler = handler; - this.effectHandler = effectHandler; - }; - CustomConfigOption.prototype = helpers.heir(WorldConfigOption.prototype); - - CustomConfigOption.prototype.configure =function(config) { - var newHash = {}; - newHash[inConfigName] = this.handler; - newHash[inConfigName+'Effect'] = this.effectHandler; - return config.updateAll(newHash); - } - - return function(handler, effectHandler) { - check(handler, isFunction, funName, 'procedure', 1, arguments); - check(effectHandler, isFunction, funName, 'procedure', 2, arguments); - return new CustomConfigOption(handler, effectHandler); - }; -}; - - -EXPORTS['on-key'] = new PrimProc('on-key', 1, false, false, onEvent('on-key', 'onKey', 2)); -EXPORTS['on-key!'] = new PrimProc('on-key!', 2, false, false, onEventBang('on-key!', 'onKey')); - - -EXPORTS['stop-when'] = new PrimProc('stop-when', 1, false, false, - onEvent('stop-when', 'stopWhen', 1)); -EXPORTS['stop-when!'] = new PrimProc('stop-when!', 2, false, false, - onEventBang('stop-when!', 'stopWhen')); - - - - - -var DrawConfigOption = function(f) { - WorldConfigOption.call(this, 'to-draw'); - this.f = f; -}; - -DrawConfigOption.prototype = helpers.heir(WorldConfigOption.prototype); - -DrawConfigOption.prototype.configure = function(config) { - return config.updateAll({'onRedraw': this.f}); -}; - - -EXPORTS['to-draw'] = - new PrimProc('to-draw', - 1, - false, false, - function(f) { - check(f, isFunction, 'to-draw', 'procedure', 1); - return new DrawConfigOption(f); - }); - - -var DrawPageOption = function(domHandler) { - WorldConfigOption.call(this, 'to-draw-page'); - this.domHandler = domHandler; -}; -DrawPageOption.prototype = helpers.heir(WorldConfigOption.prototype); -DrawPageOption.prototype.configure = function(config) { - return config.updateAll({'onDraw': this.domHandler}); -}; - - -var DrawPageAndCssOption = function(domHandler, styleHandler) { - WorldConfigOption.call(this, 'to-draw-page'); - this.domHandler = domHandler; - this.styleHandler = styleHandler; -}; -DrawPageAndCssOption.prototype = helpers.heir(WorldConfigOption.prototype); -DrawPageAndCssOption.prototype.configure = function(config) { - return config.updateAll({'onDraw': this.domHandler, - 'onDrawCss' : this.styleHandler}); -}; - - - - -EXPORTS['to-draw-page'] = - new CasePrimitive('to-draw-page', - [new PrimProc('to-draw-page', - 1, - false, false, - function(domHandler) { - check(domHandler, isFunction, 'to-draw-page', 'procedure', 1); - return new DrawPageOption(domHandler); - }), - new PrimProc('to-draw-page', - 2, - false, false, - function(domHandler, styleHandler) { - check(domHandler, isFunction, 'to-draw-page', 'procedure', 1, arguments); - check(styleHandler, isFunction, 'to-draw-page', 'procedure', 2, arguments); - return new DrawPageAndCssOption(domHandler, styleHandler); }) ]); - - -var InitialEffectOption = function(effect) { - WorldConfigOption.call(this, 'initial-effect'); - this.effect = effect; -}; -InitialEffectOption.prototype = helpers.heir(WorldConfigOption.prototype); -InitialEffectOption.prototype.configure = function(config) { - return config.updateAll({'initialEffect': this.effect}); -}; - - -EXPORTS['initial-effect'] = - new PrimProc('initial-effect', - 1, - false, false, - function(effect) { - return new InitialEffectOption(effect); - }); - - - -/************************** - *** Jsworld Primitives *** - **************************/ - - -var jsp = function(attribList) { - checkListOf(attribList, function(x) { return isList(x) && length(x) == 2; }, - 'js-p', 'list of (list of X Y)', 1); - var attribs = convertAttribList(attribList); - var node = jsworld.MobyJsworld.p(attribs); - node.toWrittenString = function(cache) { return "(js-p)"; }; - node.toDisplayedString = node.toWrittenString; - node.toDomNode = function(cache) { return node; }; - return helpers.wrapJsValue(node); -}; -EXPORTS['js-p'] = - new CasePrimitive('js-p', - [new PrimProc('js-p', 0, false, false, function() { return jsp(types.EMPTY); }), - new PrimProc('js-p', 1, false, false, jsp)]); - - -var jsdiv = function(attribList) { - checkListOf(attribList, isAssocList, 'js-div', '(listof X Y)', 1); - - var attribs = convertAttribList(attribList); - var node = jsworld.MobyJsworld.div(attribs); - - node.toWrittenString = function(cache) { return "(js-div)"; }; - node.toDisplayedString = node.toWrittenString; - node.toDomNode = function(cache) { return node; }; - return helpers.wrapJsValue(node); -}; - -EXPORTS['js-div'] = - new CasePrimitive('js-div', - [new PrimProc('js-div', 0, false, false, function() { - return jsdiv(types.EMPTY); - }), - new PrimProc('js-div', 1, false, false, jsdiv) - ]); - - -var jsButtonBang = function(funName) { - return function(worldUpdateF, effectF, attribList) { - check(worldUpdateF, isFunction, funName, 'procedure', 1); - check(effectF, isFunction, funName, 'procedure', 2); - checkListOf(attribList, isAssocList, funName, '(listof X Y)', 3); - - var attribs = attribList ? convertAttribList(attribList) : {}; - var node = jsworld.MobyJsworld.buttonBang(worldUpdateF, effectF, attribs); - - node.toWrittenString = function(cache) { return '(' + funName + ' ...)'; }; - node.toDisplayedString = node.toWrittenString; - node.toDomNode = function(cache) { return node; }; - return helpers.wrapJsValue(node); - } -}; -var jsButton = function(updateWorldF, attribList) { - var noneF = new types.PrimProc('', 1, false, false, function(w) { return types.EMPTY; }); - return jsButtonBang('js-button')(updateWorldF, noneF, attribList); -}; -EXPORTS['js-button'] = - new CasePrimitive('js-button', - [new PrimProc('js-button', 1, false, false, - function(updateWorldF) { - return jsButton(updateWorldF, types.EMPTY)}), - new PrimProc('js-button', 2, false, false, jsButton)]); - - -EXPORTS['js-button!'] = - new CasePrimitive('js-button!', - [new PrimProc('js-button!', 2, false, false, - function(worldUpdateF, effectF) { - return jsButtonBang('js-button!')(worldUpdateF, effectF, types.EMPTY); - }), - new PrimProc('js-button!', 3, false, false, - jsButtonBang('js-button!'))]); - - - -var jsInput = function(type, updateF, attribList) { - check(type, isString, 'js-input', 'string', 1); - check(updateF, isFunction, 'js-input', 'procedure', 2); - checkListOf(attribList, isAssocList, 'js-input', '(listof X Y)', 3); - - var attribs = attribList ? convertAttribList(attribList) : {}; - var node = jsworld.MobyJsworld.input(String(type), - updateF, attribs); - - node.toWrittenString = function(cache) { return "(js-input ...)"; } - node.toDisplayedString = node.toWrittenString; - node.toDomNode = function(cache) { return node; } - return helpers.wrapJsValue(node); -}; - -EXPORTS['js-input'] = - new CasePrimitive('js-input', - [new PrimProc('js-input', 2, false, false, - function(type, updateF) { - return jsInput(type, updateF, types.EMPTY)}), - new PrimProc('js-input', 3, false, false, jsInput)]); - - - -var jsImg = function(src, attribList) { - check(src, isString, "js-img", "string", 1); - checkListOf(attribList, isAssocList, 'js-img', '(listof X Y)', 2); - - var attribs = convertAttribList(attribList); - var node = jsworld.MobyJsworld.img(String(src), attribs); - - node.toWrittenString = function(cache) { return "(js-img ...)"; } - node.toDisplayedString = node.toWrittenString; - node.toDomNode = function(cache) { return node; } - return helpers.wrapJsValue(node); -}; - - - -EXPORTS['js-img'] = - new CasePrimitive('js-img', - [new PrimProc('js-img', 1, false, false, - function(src) { return jsImg(src, types.EMPTY); }), - new PrimProc('js-img', 2, false, false, jsImg)]); - - - -EXPORTS['js-text'] = - new PrimProc('js-text', - 1, - false, false, - function(s) { - check(s, isString, 'js-text', 'string', 1); - - var node = jsworld.MobyJsworld.text(String(s), []); - node.toWrittenString = function(cache) { return "(js-text ...)"; } - node.toDisplayedString = node.toWrittenString; - node.toDomNode = function(cache) { return node; } - return helpers.wrapJsValue(node); - }); - - -var jsSelect = function(optionList, updateF, attribList) { - checkListOf(optionList, isString, 'js-select', 'listof string', 1); - check(updateF, isFunction, 'js-select', 'procedure', 2); - checkListOf(attribList, isAssocList, 'js-select', '(listof X Y)', 3); - - var attribs = attribList ? convertAttribList(attribList) : {}; - var options = helpers.deepListToArray(optionList); - for (var i = 0 ; i < options.length; i++) { - options[i] = String(options[i]); - } - var node = jsworld.MobyJsworld.select(options, updateF, attribs); - - node.toWrittenString = function(cache) { return '(js-select ...)'; }; - node.toDisplayedString = node.toWrittenString; - node.toDomNode = function(cache) { return node; }; - return helpers.wrapJsValue(node); -}; - - -EXPORTS['js-select'] = - new CasePrimitive( - 'js-select', - [new PrimProc('js-select', 2, false, false, - function(optionList, updateF) { - return jsSelect(optionList, updateF, - types.EMPTY) - }), - new PrimProc('js-select', 3, false, false, - jsSelect)]); - - - - -EXPORTS['big-bang'] = - new PrimProc('big-bang', - 1, - true, true, - function(state, initW, handlers) { - arrayEach(handlers, - function(x, i) { - check(x, function(y) { return isWorldConfigOption(y) || isList(y) || types.isWorldConfig(y); }, - 'js-big-bang', 'handler or attribute list', i+2); - }); - var unwrappedConfigs = - helpers.map(function(x) { - if ( isWorldConfigOption(x) ) { - return function(config) { return x.configure(config); }; - } - else { - return x; - } - }, - handlers); - return types.internalPause(function(caller, restarter, onFail) { - var bigBangController; - var onBreak = function() { - bigBangController.breaker(); - } - state.addBreakRequestedListener(onBreak); - bigBangController = jsworld.MobyJsworld.bigBang( - initW, - state.getToplevelNodeHook()(), - unwrappedConfigs, - caller, - function(v) { - state.removeBreakRequestedListener(onBreak); - restarter(v); - }, - onFail); - }) - }); - - -////////////////////////////////////////////////////////////////////// - - -var emptyPage = function(attribList) { - checkListOf(attribList, isAssocList, 'empty-page', '(listof X Y)', 1); - - var attribs = convertAttribList(attribList); - var node = jsworld.MobyJsworld.emptyPage(attribs); - - // node.toWrittenString = function(cache) { return "(js-div)"; }; - // node.toDisplayedString = node.toWrittenString; - // node.toDomNode = function(cache) { return node; }; - // return helpers.wrapJsValue(node); - return node; -}; - -EXPORTS['empty-page'] = - new CasePrimitive('empty-page', - [new PrimProc('empty-page', 0, false, false, - function() { return emptyPage(types.EMPTY); }), - new PrimProc('empty-page', 1, false, false, emptyPage)]); - - -EXPORTS['place-on-page'] = - new PrimProc('empty-page', - 4, - false, false, - function(elt, left, top, page) { - // FIXME: add type checking - check(left, isReal, 'place-on-page', 'real', 2); - check(top, isReal, 'place-on-page', 'real', 3); - return jsworld.MobyJsworld.placeOnPage( - elt, jsnums.toFixnum(left), jsnums.toFixnum(top), page); - }); - - - - - -////////////////////////////////////////////////////////////////////// - - - - - -EXPORTS['make-world-config'] = - new PrimProc('make-world-config', - 2, - true, false, - function(startup, shutdown, startupArgs) { - var allArgs = [startup, shutdown].concat(startupArgs); - check(startup, isFunction, 'make-world-config', 'procedure', 1, allArgs); - check(shutdown, procArityContains(1), 'make-world-config', 'procedure (arity 1)', 2, allArgs); - arrayEach(startupArgs, function(x, i) { check(x, isFunction, 'make-world-config', 'handler', i+3, allArgs); }); - - if ( !procArityContains(startupArgs.length)(startup) ) { - raise( types.incompleteExn( - types.exnFailContract, - 'make-world-config: 1st argument must have arity equal to ' - + 'the number of arguments after the second', - []) ); - } - - return types.worldConfig(startup, shutdown, startupArgs); - }); - - -EXPORTS['make-effect-type'] = - makeOptionPrimitive( - 'make-effect-type', - 4, - [false], - true, - function(userArgs, aState, name, superType, fieldCnt, impl, guard) { - check(name, isSymbol, 'make-effect-type', 'string', 1, userArgs); - check(superType, function(x) { return x === false || types.isEffectType(x) }, - 'make-effect-type', 'effect type or #f', 2, userArgs); - check(fieldCnt, isNatural, 'make-effect-type', 'exact non-negative integer', 3, userArgs); - check(impl, isFunction, 'make-effect-type', 'procedure', 4, userArgs); -// checkListOf(handlerIndices, isNatural, 'make-effect-type', 'exact non-negative integer', 5); - check(guard, function(x) { return x === false || isFunction(x); }, 'make-effect-type', 'procedure or #f', 6, userArgs); - // Check the number of arguments on the guard - var numberOfGuardArgs = fieldCnt + 1 + (superType ? superType.numberOfArgs : 0); - if ( guard && !procArityContains(numberOfGuardArgs)(guard) ) { - raise(types.incompleteExn( - types.exnFailContract, - helpers.format( - 'make-effect-type: guard procedure does not accept ~a arguments ' - + '(one more than the number constructor arguments): ~s', - [numberOfGuardArgs, guard]), - [])); - } - -// var jsImpl = schemeProcToJs(aState, impl); - var jsGuard = (guard ? schemeProcToJs(aState, guard) : false); -// var handlerIndices_js = helpers.map(jsnums.toFixnum, helpers.schemeListToArray(handlerIndices)); - -// var caller = makeCaller(aState); -// var wrapHandler = function(handler, changeWorld) { -// return types.jsObject('function', function() { -// var externalArgs = arguments; -// changeWorld(function(w, k) { -// var args = [w]; -// for (var i = 0; i < externalArgs.length; i++) { -// args.push( helpers.wrapJsValue(externalArgs[i]) ); -// } -// caller(handler, args, k); -// }); -// }); -// } - - var anEffectType = types.makeEffectType(String(name), - superType, - fieldCnt, - impl, -// handlerIndices_js, - jsGuard, - makeCaller(aState)); - aState.v = getMakeStructTypeReturns(anEffectType); - }); - - -EXPORTS['effect-type?'] = new PrimProc('effect-type?', 1, false, false, types.isEffectType); -EXPORTS['effect?'] = new PrimProc('effect?', 1, false, false, types.isEffect); - -//EXPORTS['make-effect:do-nothing'] = new PrimProc('make-effect:do-nothing', 0, false, false, types.EffectDoNothing.constructor); -//EXPORTS['effect:do-nothing?'] = new PrimProc('effect:do-nothing?', 1, false, false, types.EffectDoNothing.predicate); - - -EXPORTS['make-render-effect-type'] = - makeOptionPrimitive( - 'make-render-effect-type', - 4, - [false], - true, - function(userArgs, aState, name, superType, fieldCnt, impl, guard) { - check(name, isSymbol, 'make-render-effect-type', 'string', 1, userArgs); - check(superType, function(x) { return x === false || types.isEffectType(x) }, - 'make-render-effect-type', 'effect type or #f', 2, userArgs); - check(fieldCnt, isNatural, 'make-render-effect-type', 'exact non-negative integer', 3, userArgs); - check(impl, isFunction, 'make-render-effect-type', 'procedure', 4, userArgs); - check(guard, function(x) { return x === false || isFunction(x); }, 'make-render-effect-type', 'procedure or #f', 6, userArgs); - // Check the number of arguments on the guard - var numberOfGuardArgs = fieldCnt + 1 + (superType ? superType.numberOfArgs : 0); - if ( guard && !procArityContains(numberOfGuardArgs)(guard) ) { - raise(types.incompleteExn( - types.exnFailContract, - helpers.format( - 'make-effect-type: guard procedure does not accept ~a arguments ' - + '(one more than the number constructor arguments): ~s', - [numberOfGuardArgs, guard]), - [])); - } - var jsGuard = (guard ? schemeProcToJs(aState, guard) : false); - - var aRenderEffectType = types.makeRenderEffectType(String(name), - superType, - fieldCnt, - impl, - jsGuard); - aState.v = getMakeStructTypeReturns(aRenderEffectType); - }); - - -EXPORTS['render-effect-type?'] = new PrimProc('render-effect-type?', 1, false, false, types.isRenderEffectType); -EXPORTS['render-effect?'] = new PrimProc('render-effect?', 1, false, false, types.isRenderEffect); - - -EXPORTS['world-with-effects'] = - new PrimProc('world-with-effects', - 2, - false, false, - function(effects, w) { - check(effects, isCompoundEffect, 'world-with-effects', 'compound effect', 1, arguments); - - return jsworld.Jsworld.with_multiple_effects(w, helpers.flattenSchemeListToArray(effects)); - }); - - - -EXPORTS['make-render-effect'] = new PrimProc('make-render-effect', 2, false, false, types.makeRenderEffect); - -EXPORTS['render-effect?'] = new PrimProc('render-effect?', 1, false, false, types.isRenderEffect); - -EXPORTS['render-effect-dom-node'] = - new PrimProc('render-effect-dom-node', - 1, - false, false, - function(effect) { - check(effect, types.isRenderEffect, 'render-effect-dom-node', 'render-effect', 1); - return types.renderEffectDomNode(effect); - }); - -EXPORTS['render-effect-effects'] = - new PrimProc('render-effect-effects', - 1, - false, false, - function(effect) { - check(effect, types.isRenderEffect, 'render-effect-effects', 'render-effect', 1); - return types.renderEffectEffects(effect); - }); - - - - - - - - - - - - - - - - - - -////////////////////////////////////////////////////////////////////// - -// Helper Functions - - - - - - - - -var checkList = function(x, functionName, position, args) { - if ( !isList(x) ) { - helpers.throwCheckError([functionName, - 'list', - helpers.ordinalize(position), - x], - position, - args); - } -} - - -var length = function(lst) { - checkList(lst, 'length', 1, [lst]); - var ret = 0; - for (; !isEmpty(lst); lst = lst.rest()) { - ret = ret+1; - } - return ret; -} - - - - - - - - - - - - - - - - - -var getMakeStructTypeReturns = function(aStructType) { - var name = aStructType.name; - return new types.ValuesWrapper( - [aStructType, - (new types.StructConstructorProc(name, - 'make-'+name, - aStructType.numberOfArgs, - false, - false, - aStructType.constructor)), - (new types.StructPredicateProc(name, name+'?', 1, false, false, aStructType.predicate)), - (new types.StructAccessorProc(name, - name+'-ref', - 2, - false, - false, - function(x, i) { - check(x, aStructType.predicate, name+'-ref', 'struct:'+name, 1, arguments); - check(i, isNatural, name+'-ref', 'non-negative exact integer', 2, arguments); - - var numFields = aStructType.numberOfFields; - if ( jsnums.greaterThanOrEqual(i, numFields) ) { - var msg = (name+'-ref: slot index for not in ' + - '[0, ' + (numFields-1) + ']: ' + i); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - return aStructType.accessor(x, jsnums.toFixnum(i)); - })), - (new types.StructMutatorProc(name, - name+'-set!', - 3, - false, - false, - function(x, i, v) { - check(x, aStructType.predicate, name+'-set!', 'struct:'+name, 1, arguments); - check(i, isNatural, name+'-set!', 'non-negative exact integer', 2, arguments); - - var numFields = aStructType.numberOfFields; - if ( jsnums.greaterThanOrEqual(i, numFields) ) { - var msg = (name+'-set!: slot index for not in ' + - '[0, ' + (numFields-1) + ']: ' + i); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - aStructType.mutator(x, jsnums.toFixnum(i), v) - })) ]); -}; - - - - -////////////////////////////////////////////////////////////////////// - - -var isNumber = jsnums.isSchemeNumber; -var isReal = jsnums.isReal; -var isRational = jsnums.isRational; -var isComplex = isNumber; -var isInteger = jsnums.isInteger; - -var isNatural = function(x) { - return jsnums.isExact(x) && isInteger(x) && jsnums.greaterThanOrEqual(x, 0); -}; - -var isNonNegativeReal = function(x) { - return isReal(x) && jsnums.greaterThanOrEqual(x, 0); -}; - -var isSymbol = types.isSymbol; -var isChar = types.isChar; -var isString = types.isString; -var isPair = types.isPair; -var isEmpty = function(x) { return x === types.EMPTY; }; -var isList = helpers.isList; -var isListOf = helpers.isListOf; - -var isVector = types.isVector; -var isBox = types.isBox; -var isHash = types.isHash; -var isByteString = types.isByteString; - -var isByte = function(x) { - return (isNatural(x) && - jsnums.lessThanOrEqual(x, 255)); -} - -var isBoolean = function(x) { - return (x === true || x === false); -} - -var isFunction = types.isFunction; - -var isEqual = function(x, y) { - return types.isEqual(x, y, new types.UnionFind()); -} - -var isEq = function(x, y) { - return x === y; -} - -var isEqv = function(x, y) { - if (isNumber(x) && isNumber(y)) { - return jsnums.eqv(x, y); - } - else if (isChar(x) && isChar(y)) { - return x.val === y.val; - } - return x === y; -} - - - - - - -var isStyle = function(x) { - return ((isString(x) || isSymbol(x)) && - (String(x).toLowerCase() == "solid" || - String(x).toLowerCase() == "outline")); -}; - - -var isAssocList = function(x) { - return isPair(x) && isPair(x.rest()) && isEmpty(x.rest().rest()); -}; - - -var isCompoundEffect = function(x) { - return ( types.isEffect(x) || isListOf(x, isCompoundEffect) ); -}; - -var isJsValue = types.isJsValue; -var isJsFunction = function(x) { - return isJsValue(x) && typeof(x.unbox()) == 'function'; -}; - - - -var arrayEach = function(arr, f) { - for (var i = 0; i < arr.length; i++) { - f.call(null, arr[i], i); - } -} - -//var throwCheckError = helpers.throwCheckError; -var check = helpers.check; - - - - - - - - - - - - - - -////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////// - - - - - -/* - - - -PRIMITIVES['js-p'] = - makeOptionPrimitive('js-p', - 0, - [types.EMPTY], - false, - function(userArgs, attribList) { - checkListOf(attribList, function(x) { return isList(x) && length(x) == 2; }, - 'js-p', 'list of (list of X Y)', 1, userArgs); - - var attribs = assocListToHash(attribList); - var node = helpers.wrapJsValue( jsworld.Jsworld.p(attribs) ); - - node.toWrittenString = function(cache) { return "(js-p)"; }; - node.toDisplayedString = node.toWrittenString; - // node.toDomNode = function(cache) { return node; }; - return node; - }); - - -PRIMITIVES['js-div'] = - makeOptionPrimitive('js-div', - 0, - [types.EMPTY], - false, - function(userArgs, attribList) { - checkListOf(attribList, isAssocList, 'js-div', '(listof X Y)', 1, userArgs); - - var attribs = assocListToHash(attribList); - var node = helpers.wrapJsValue( jsworld.Jsworld.div(attribs) ); - - node.toWrittenString = function(cache) { return "(js-div)"; }; - node.toDisplayedString = node.toWrittenString; - // node.toDomNode = function(cache) { return node; }; - return node; - }); - - -var jsButtonBang = function(funName, worldUpdateF, effectF, attribList) { - var attribs = assocListToHash(attribList); - var node = helpers.wrapJsValue( jsworld.Jsworld.buttonBang(worldUpdateF, effectF, attribs) ); - - node.toWrittenString = function(cache) { return '(' + funName + ' ...)'; }; - node.toDisplayedString = node.toWrittenString; -// node.toDomNode = function(cache) { return node; }; - return node; -}; -PRIMITIVES['js-button'] = - makeOptionPrimitive('js-button', - 1, - [types.EMPTY], - false, - function(userArgs, updateWorldF, attribList) { - check(updateWorldF, isFunction, 'js-button', 'procedure', 1, userArgs); - checkListOf(attribList, isAssocList, 'js-button', '(listof X Y)', 2, userArgs); - - var noneF = new types.PrimProc('', 1, false, false, function(w) { return types.EMPTY; }); - return jsButtonBang('js-button', updateWorldF, noneF, attribList); - }); - -PRIMITIVES['js-button!'] = - makeOptionPrimitive('js-button!', - 2, - [types.EMPTY], - false, - function(userArgs, updateWorldF, effectF, attribList) { - check(worldUpdateF, isFunction, funName, 'procedure', 1, userArgs); - check(effectF, isFunction, funName, 'procedure', 2, userArgs); - checkListOf(attribList, isAssocList, funName, '(listof X Y)', 3, userArgs); - - return jsButtonBang('js-button!', updateWorldF, effectF, attribList); - }); - - -PRIMITIVES['js-input'] = - makeOptionPrimitive('js-input', - 2, - [types.EMPTY], - false, - function(userArgs, type, updateF, attribList) { - check(type, isString, 'js-input', 'string', 1, userArgs); - check(updateF, isFunction, 'js-input', 'procedure', 2, userArgs); - checkListOf(attribList, isAssocList, 'js-input', '(listof X Y)', 3, userArgs); - - var attribs = assocListToHash(attribList); - var node = helpers.wrapJsValue( jsworld.Jsworld.input(type.toString(), updateF, attribs) ); - - node.toWrittenString = function(cache) { return "(js-input ...)"; } - node.toDisplayedString = node.toWrittenString; - // node.toDomNode = function(cache) { return node; } - return node; - }); - - -PRIMITIVES['js-img'] = - makeOptionPrimitive('js-img', - 1, - [types.EMPTY], - false, - function(userArgs, src, attribList) { - check(src, isString, "js-img", "string", 1, userArgs); - checkListOf(attribList, isAssocList, 'js-img', '(listof X Y)', 2, userArgs); - - var attribs = assocListToHash(attribList); - var node = helpers.wrapJsValue( jsworld.Jsworld.img(src.toString(), attribs) ); - - node.toWrittenString = function(cache) { return "(js-img ...)"; } - node.toDisplayedString = node.toWrittenString; - // node.toDomNode = function(cache) { return node; } - return node; - }); - - -PRIMITIVES['js-text'] = - new PrimProc('js-text', - 1, - false, false, - function(s) { - check(s, isString, 'js-text', 'string', 1); - - var node = helpers.wrapJsValue( jsworld.Jsworld.text(s.toString(), []) ); - node.toWrittenString = function(cache) { return "(js-text ...)"; } - node.toDisplayedString = node.toWrittenString; -// node.toDomNode = function(cache) { return node; } - return node; - }); - - -PRIMITIVES['js-select'] = - makeOptionPrimitive('js-select', - 2, - [types.EMPTY], - false, - function(userArgs, optionList, updateF, attribList) { - checkListOf(optionList, isString, 'js-select', 'listof string', 1, userArgs); - check(updateF, isFunction, 'js-select', 'procedure', 2, userArgs); - checkListOf(attribList, isAssocList, 'js-select', '(listof X Y)', 3, userArgs); - - var attribs = assocListToHash(attribList); - var options = helpers.deepListToArray(optionList); - for (var i = 0; i < options.length; i++) { - options[i] = options[i].toString(); - } - var node = helpers.wrapJsValue( jsworld.Jsworld.select(options, updateF, attribs) ); - - node.toWrittenString = function(cache) { return '(js-select ...)'; }; - node.toDisplayedString = node.toWrittenString; - // node.toDomNode = function(cache) { return node; }; - return node; - }); - - - -PRIMITIVES['js-big-bang'] = - new PrimProc('js-big-bang', - 1, - true, true, - function(aState, initW, configs) { - arrayEach(configs, - function(x, i) { - check(x, function(y) { return (types.isWorldConfig(y) || - jsworld.Jsworld.isBuiltInConfig(y)); }, - 'js-big-bang', 'world configuration', i+2); - }); - - return PAUSE(function(caller, onSuccess, onFail) { - var bigBangController = {}; - var onBreak = function() { - bigBangController.breaker(aState); - } - aState.addBreakRequestedListener(onBreak); - aState.onSuccess = function(v) { - aState.removeBreakRequestedListener(onBreak); - onSuccess(v); - }; - jsworld.Jsworld.bigBang(initW, -// aState.getToplevelNodeHook()(), - configs, - aState, - caller, - bigBangController); -// caller, -// function(v) { -// aState.removeBreakRequestedListener(onBreak); -// onSuccess(v); -// }, -// onFail, -// bigBangController); - }); - }); - - -////////////////////////////////////////////////////////////////////// - - - var emptyPage = function(attribList) { - checkListOf(attribList, isAssocList, 'empty-page', '(listof X Y)', 1); - - var attribs = assocListToHash(attribList); - var node = jsworld.MobyJsworld.emptyPage(attribs); - -// node.toWrittenString = function(cache) { return "(js-div)"; }; -// node.toDisplayedString = node.toWrittenString; -// node.toDomNode = function(cache) { return node; }; -// return helpers.wrapJsValue(node); - return node; - }; - - PRIMITIVES['empty-page'] = - new CasePrimitive('empty-page', - [new PrimProc('empty-page', 0, false, false, - function() { return emptyPage(types.EMPTY); }), - new PrimProc('empty-page', 1, false, false, emptyPage)]); - - - PRIMITIVES['place-on-page'] = - new PrimProc('empty-page', - 4, - false, false, - function(elt, left, top, page) { - // FIXME: add type checking - return jsworld.MobyJsworld.placeOnPage( - elt, left, top, page); - }); - - - - - -////////////////////////////////////////////////////////////////////// - - - - - -PRIMITIVES['make-world-config'] = - makeOptionPrimitive('make-world-config', - 2, - [false, false], - false, - function(userArgs, startup, shutdown, pause, restart) { - check(startup, procArityContains(1), 'make-world-config', 'procedure', 1, userArgs); - check(shutdown, procArityContains(1), 'make-world-config', 'procedure (arity 1)', 2, userArgs); - check(pause, function(x) { return (x === false || procArityContains(1)(x)); }, - 'make-world-config', 'procedure (arity 1) or #f', 3, userArgs); - check(restart, function(x) { return (x === false || procArityContains(2)(x)); }, - 'make-world-config', 'procedure (arity 2) or #f', 4, userArgs); - - return types.worldConfig(startup, shutdown, pause, restart); - }); - -PRIMITIVES['bb-info'] = types.BigBangInfo; -PRIMITIVES['make-bb-info'] = new PrimProc('make-bb-info', 2, false, false, types.makeBigBangInfo); -PRIMITIVES['bb-info?'] = new PrimProc('bb-info?', 1, false, false, types.isBigBangInfo); - -PRIMITIVES['bb-info-change-world'] = - new PrimProc('bb-info-change-world', - 1, - false, false, - function(bbInfo) { - check(bbInfo, types.isBigBangInfo, 'bb-info-change-world', 'bb-info', 1); - return types.bbInfoChangeWorld(bbInfo); - }); - -PRIMITIVES['bb-info-toplevel-node'] = - new PrimProc('bb-info-toplevel-node', - 1, - false, false, - function(bbInfo) { - check(bbInfo, types.isBigBangInfo, 'bb-info-toplevel-node', 'bb-info', 1); - return types.bbInfoToplevelNode(bbInfo); - }); - - -PRIMITIVES['make-effect-type'] = - makeOptionPrimitive( - 'make-effect-type', - 4, - [false], - true, - function(userArgs, aState, name, superType, fieldCnt, impl, guard) { - check(name, isSymbol, 'make-effect-type', 'string', 1, userArgs); - check(superType, function(x) { return x === false || types.isEffectType(x) }, - 'make-effect-type', 'effect type or #f', 2, userArgs); - check(fieldCnt, isNatural, 'make-effect-type', 'exact non-negative integer', 3, userArgs); - check(impl, isFunction, 'make-effect-type', 'procedure', 4, userArgs); - check(guard, function(x) { return x === false || isFunction(x); }, 'make-effect-type', 'procedure or #f', 6, userArgs); - - var numberOfGuardArgs = fieldCnt + 1 + (superType ? superType.numberOfArgs : 0); - var anEffectType = types.makeEffectType(name.toString(), - superType, - fieldCnt, - impl, - checkAndGetGuard('make-effect-type', - guard, - numberOfGuardArgs)); - aState.v = getMakeStructTypeReturns(anEffectType); - }); - - -PRIMITIVES['effect-type?'] = new PrimProc('effect-type?', 1, false, false, types.isEffectType); -PRIMITIVES['effect?'] = new PrimProc('effect?', 1, false, false, types.isEffect); - -//PRIMITIVES['make-effect:do-nothing'] = new PrimProc('make-effect:do-nothing', 0, false, false, types.EffectDoNothing.constructor); -//PRIMITIVES['effect:do-nothing?'] = new PrimProc('effect:do-nothing?', 1, false, false, types.EffectDoNothing.predicate); - - -PRIMITIVES['make-render-effect-type'] = - makeOptionPrimitive( - 'make-render-effect-type', - 4, - [false], - true, - function(userArgs, aState, name, superType, fieldCnt, impl, guard) { - check(name, isSymbol, 'make-render-effect-type', 'string', 1, userArgs); - check(superType, function(x) { return x === false || types.isEffectType(x) }, - 'make-render-effect-type', 'effect type or #f', 2, userArgs); - check(fieldCnt, isNatural, 'make-render-effect-type', 'exact non-negative integer', 3, userArgs); - check(impl, isFunction, 'make-render-effect-type', 'procedure', 4, userArgs); - check(guard, function(x) { return x === false || isFunction(x); }, 'make-render-effect-type', 'procedure or #f', 6, userArgs); - - var numberOfGuardArgs = fieldCnt + 1 + (superType ? superType.numberOfArgs : 0); - var aRenderEffectType = - types.makeRenderEffectType(name.toString(), - superType, - fieldCnt, - impl, - checkAndGetGuard('make-render-effect-type', - guard, - numberOfGuardArgs)); - aState.v = getMakeStructTypeReturns(aRenderEffectType); - }); - - -PRIMITIVES['render-effect-type?'] = new PrimProc('render-effect-type?', 1, false, false, types.isRenderEffectType); -PRIMITIVES['render-effect?'] = new PrimProc('render-effect?', 1, false, false, types.isRenderEffect); - - -PRIMITIVES['world-with-effects'] = - new PrimProc('world-with-effects', - 2, - false, false, - function(effects, w) { - check(effects, isCompoundEffect, 'world-with-effects', 'compound effect', 1, arguments); - - return jsworld.Jsworld.worldWithEffects(helpers.flattenSchemeListToArray(effects), w); - }); - - - -PRIMITIVES['make-render-effect'] = new PrimProc('make-render-effect', 2, false, false, types.makeRenderEffect); - -PRIMITIVES['render-effect?'] = new PrimProc('render-effect?', 1, false, false, types.isRenderEffect); - -PRIMITIVES['render-effect-dom-node'] = - new PrimProc('render-effect-dom-node', - 1, - false, false, - function(effect) { - check(effect, types.isRenderEffect, 'render-effect-dom-node', 'render-effect', 1); - return types.renderEffectDomNode(effect); - }); - -PRIMITIVES['render-effect-effects'] = - new PrimProc('render-effect-effects', - 1, - false, false, - function(effect) { - check(effect, types.isRenderEffect, 'render-effect-effects', 'render-effect', 1); - return types.renderEffectEffects(effect); - }); - - - - - - - - -PRIMITIVES['stop-when'] = - new PrimProc('stop-when', 1, false, false, - function(test) { - check(test, isFunction, 'stop-when', 'procedure', 1); - return jsworld.Jsworld.stopWhenConfig(test); - }); -//PRIMITIVES['stop-when!'] = new PrimProc('stop-when!', 2, false, false, -// onEventBang('stop-when!', 'stopWhen')); - - -PRIMITIVES['to-draw'] = - new PrimProc('to-draw', - 1, - false, false, - function(f) { - check(f, isFunction, 'to-draw', 'procedure', 1); - return jsworld.Jsworld.onDrawSceneConfig(f); - - }); - - -PRIMITIVES['to-draw-page'] = - new CasePrimitive('to-draw-page', - [new PrimProc('to-draw-page', - 1, - false, false, - function(domHandler) { - check(domHandler, isFunction, 'to-draw-page', 'procedure', 1); - return jsworld.Jsworld.onDrawPageConfig(domHandler); - }), - new PrimProc('to-draw-page', - 2, - false, false, - function(domHandler, styleHandler) { - check(domHandler, isFunction, 'to-draw-page', 'procedure', 1, arguments); - check(styleHandler, isFunction, 'to-draw-page', 'procedure', 2, arguments); - return jsworld.Jsworld.onDrawPageConfig(domHandler, styleHandler); - }) ]); - - - -*/ \ No newline at end of file diff --git a/world/scratch/jsworld/jsworld.rkt b/world/scratch/jsworld/jsworld.rkt deleted file mode 100644 index e706821..0000000 --- a/world/scratch/jsworld/jsworld.rkt +++ /dev/null @@ -1,50 +0,0 @@ -#lang s-exp "../lang/js-impl/js-impl.rkt" - -;; Loaded so we have access to image library stuff, as well as the world kernel -(require "../world/kernel.rkt" - "../image/image.rkt") - - -(require-js "private/jsworld/jsworld.js" - "private/jsworld.js" - "jsworld.js") - - -(provide big-bang - to-draw - to-draw-page - - key=? - on-tick on-tick! - on-key on-key! - stop-when stop-when! - - initial-effect - - js-p - js-div - js-button - js-button! - js-input - js-img - js-text - js-select - - - empty-page - place-on-page - - make-world-config - make-effect-type - effect-type? - effect? - - #;make-render-effect-type - #;render-effect-type? - - world-with-effects - - #;make-render-effect - #;render-effect? - #;render-effect-dom-node - #;render-effect-effects) diff --git a/world/scratch/jsworld/private/jsworld.js b/world/scratch/jsworld/private/jsworld.js deleted file mode 100644 index 17a0cc8..0000000 --- a/world/scratch/jsworld/private/jsworld.js +++ /dev/null @@ -1,777 +0,0 @@ -// Depends on world.js, world-config.js - -(function() { - - var world = {}; - world.Kernel = STATE.invokedModules["mzscheme-vm/world/kernel"].lookup("kernel"); - - - - var Jsworld = jsworld.MobyJsworld = {}; - - // The real low-level jsworld module: - var _js = jsworld.Jsworld; - - - var caller; - var setCaller = function(c) { - caller = function(op, args, k) { - c(op, args, k, handleError); - }; - }; - var unsetCaller = function() { - caller = function(op, args, k) { - throw new Error('caller not defined!'); - }; - }; - unsetCaller(); - - // The restarted and things to set it - // Note that we never want to restart the same computation - // more than once, so we throw an error if someone tries to do that - var restarter; - var setRestarter = function(r) { - var hasRestarted = false; - restarter = function(v) { - if (hasRestarted) { - throw new Error('Cannot restart twice!'); - } - hasRestarted = true; - r(v); - }; - }; - var unsetRestarter = function() { - restarter = function() { - throw new Error('restarter not defined!'); - }; - }; - unsetRestarter(); - - - var errorReporter = function(e) { - // default: do nothing. - }; - - - - var terminator; - var setTerminator = function(t) { - terminator = t; - }; - var unsetTerminator = function() { - terminator = function() { - throw new Error('terminator not defined!'); - }; - }; - unsetTerminator(); - - - - // mutateStringsInDeepArray: array -> array - // walks and in-place mutates Scheme strings to primitive strings. - var mutateStringsInDeepArray = function(thing) { - var i, length; - if (typeof(thing) === 'object' && - thing.constructor === Array) { - length = thing.length; - for (i = 0; i < length; i++) { - thing[i] = mutateStringsInDeepArray(thing[i]); - } - } else if (types.isString(thing)) { - return thing.toString(); - } - return thing; - }; - - - - - var userConfigs = []; - - var startUserConfigs = function(k) { - helpers.forEachK(userConfigs, - function(aConfig, k2) { - caller(aConfig.startup, aConfig.startupArgs, - function(res) { - aConfig.isRunning = true; - aConfig.shutdownArg = res; - k2() - }); - }, - handleError, - k); - } - - var shutdownUserConfigs = function(k) { -// console.log('shutting down user configs'); - var theConfigs = userConfigs; - userConfigs = [] - helpers.forEachK(theConfigs, - function(aConfig, k2) { -// console.log(' shutting down a config'); - if (aConfig.isRunning) { - aConfig.isRunning = false; - caller(aConfig.shutdown, [aConfig.shutdownArg], k2); - } else { - k2(); - } - }, - handleError, - k); - } - - var expandHandler = function(handler) { - return types.jsValue('function', function() { - var wrappedStimulusArgs = []; - for (var i = 0; i < arguments.length; i++) { - wrappedStimulusArgs.push( helpers.wrapJsValue(arguments[i]) ); - } - - Jsworld.updateWorld( - function(w, k) { - var args = [w].concat(wrappedStimulusArgs); - caller(handler, args, k); - }, - function() {}); - }); - }; - - -// var unwrapWorldEffects = function(w) { -// if ( _js.has_effects(w) ) { -// var unwrappedEffects = -// helpers.map(function(e) { -// if ( types.isEffect(e) ) { -// return types.makeJsworldEffect(function(k) { -// caller(types.effectThunk(e), [], k); -// }); -// } -// else { -// return e; -// } -// }, -// w.getEffects()); -// var returnVal = _js.with_multiple_effects(w.getWorld(), unwrappedEffects); -// return returnVal; -// } -// else { -// return w; -// } -// }; - - - var deepUnwrapJsValues = function(x, k) { - if ( types.isJsValue(x) ) { - k(x.unbox()); - } - else if ( types.isRenderEffect(x) ) { - x.callImplementation(caller, function(y) { deepUnwrapJsValues(y, k); }); - } -// var effects = helpers.schemeListToArray( types.renderEffectEffects(x) ).reverse(); -// types.setRenderEffectEffects(x, types.EMPTY); -// -// helpers.forEachK(effects, -// function(ef, k2) { caller(ef, [], k2); }, -// handleError, -// function() { deepUnwrapJsValues(types.renderEffectDomNode(x), k); }); -// } - else if ( types.isPair(x) ) { - deepUnwrapJsValues(x.first(), function(first) { - deepUnwrapJsValues(x.rest(), function(rest) { - k( types.cons(first, rest) ); - }); - }); - } - else { - k(x); - } - }; - - - - - - - - - // isHandler: X -> boolean - // Right now, a handler is a function that consumes and produces - // configs. We should tighten up the type check eventually. - var isHandler = function(x) { - return typeof(x) == 'function'; - } - - - - - ////////////////////////////////////////////////////////////////////// - //From this point forward, we define wrappers to integrate jsworld - //with Moby. - - - // getBigBangWindow: -> window - var getBigBangWindow = function() { - if (window.document.getElementById("jsworld-div") !== undefined) { - return window; - } else { - var newDiv = window.document.createElement("div"); - newDiv.id = 'jsworld-div'; - window.document.appendChild(newDiv); - return window; - } - } - - - // types are - // sexp: (cons node (listof sexp)) - // css-style: (node (listof (list string string))) - - // Exports: - - - - - var isPair = types.isPair; - var isEmpty = function(x) { return x === types.EMPTY; }; - var isList = function(x) { return (isPair(x) || isEmpty(x)); }; - - - - // The default printWorldHook will write the written content of the node. - // We probably want to invoke the pretty printer here instead! - Jsworld.printWorldHook = function(world, node) { - var newNode; - if(node.lastChild == null) { - newNode = types.toDomNode(world); - node.appendChild(newNode); - helpers.maybeCallAfterAttach(newNode); - } else { - newNode = types.toDomNode(world); - node.replaceChild(newNode, node.lastChild); - helpers.maybeCallAfterAttach(newNode); - } - }; - - - - // Figure out the target of an event. - // http://www.quirksmode.org/js/events_properties.html#target - var findEventTarget = function(e) { - var targ; - if (e.target) - targ = e.target; - else if (e.srcElement) - targ = e.srcElement; - if (targ.nodeType == 3) // defeat Safari bug - targ = targ.parentNode; - return targ; - } - - // isNode: any -> boolean - // Returns true if the thing has a nodeType. - var isNode = function(thing) { - return thing && typeof(thing.nodeType) != 'undefined'; - } - - - - // checkWellFormedDomTree: X X (or number undefined) -> void - // Check to see if the tree is well formed. If it isn't, - // we need to raise a meaningful error so the user can repair - // the structure. - // - // Invariants: - // The dom tree must be a pair. - // The first element must be a node. - // Each of the rest of the elements must be dom trees. - // If the first element is a text node, it must NOT have children. - var checkWellFormedDomTree = function(x, top, index) { - var fail = function(formatStr, formatArgs) { - throw types.schemeError( - types.incompleteExn(types.exnFailContract, - helpers.format(formatStr, formatArgs), - [])); - } - - if (_js.isPage(x)) { - return; - } - - if (types.isPair(x)) { - var firstElt = x.first(); - var restElts = x.rest(); - - if (! isNode(firstElt)) { - fail("on-draw: expected a dom-element, but received ~s instead, the first element within ~s", [firstElt, top]); - } - - if (firstElt.nodeType == Node.TEXT_NODE && !restElts.isEmpty() ) { - fail("on-draw: the text node ~s must not have children. It has ~s", [firstElt, restElts]); - } - - var i = 2; - while( !restElts.isEmpty() ) { - checkWellFormedDomTree(restElts.first(), x, i); - restElts = restElts.rest(); - i++; - } - } else { - var formatStr = "on-draw: expected a dom-s-expression, but received ~s instead"; - var formatArgs = [x]; - if (index != undefined) { - formatStr += ", the ~a element within ~s"; - formatArgs.push( helpers.ordinalize(index) ); - formatArgs.push(top); - } - formatStr += "."; - - fail(formatStr, formatArgs); - } - }; - - - // Compatibility for attaching events to nodes. - var attachEvent = function(node, eventName, fn) { - if (node.addEventListener) { - // Mozilla - node.addEventListener(eventName, fn, false); - } else { - // IE - node.attachEvent('on' + eventName, fn, false); - } - return function() { - detachEvent(node, eventName, fn); - } - }; - - var detachEvent = function(node, eventName, fn) { - if (node.addEventListener) { - // Mozilla - node.removeEventListener(eventName, fn, false); - } else { - // IE - node.detachEvent('on' + eventName, fn, false); - } - } - - - var preventDefault = function(event) { - if (event.preventDefault) { - event.preventDefault(); - } else { - event.returnValue = false; - } - } - - var stopPropagation = function(event) { - if (event.stopPropagation) { - event.stopPropagation(); - } else { - event.cancelBubble = true; - } - } - - - // bigBang: world dom (listof (list string string)) (arrayof handler) -> world - Jsworld.bigBang = function(initWorld, toplevelNode, handlers, theCaller, theRestarter, onFail) { - // shutdownListeners: arrayof (-> void) - // We maintain a list of thunks that need to be called as soon as we come out of - // bigBang, to do cleanup. - var shutdownListeners = []; - - var onTermination = function(w) { - for (var i = 0; i < shutdownListeners.length; i++) { - try { - shutdownListeners[i](); - } catch (e) { } - } - shutdownUserConfigs(function() { - unsetCaller(); - theRestarter(w); - }); - } - - - //console.log('in high level big-bang'); - errorReporter = onFail; - - setCaller(theCaller); - setRestarter(theRestarter); - setTerminator(function(w) { - detachEvent(toplevelNode, 'click', absorber); - shutdownUserConfigs(function() { - unsetCaller(); - unsetTerminator(); - restarter(w); - }); - }); - - var attribs = types.EMPTY; - - // Ensure that the toplevelNode can be focused by mouse or keyboard - toplevelNode.tabIndex = 0; - - // Absorb all click events so they don't bubble up. - var absorber = function(e) { - preventDefault(e); - stopPropagation(e); - return false; - } - - attachEvent(toplevelNode, 'click', absorber); - shutdownListeners.push(function() { detachEvent(toplevelNode, 'click', absorber)}); - - - - var config = new world.Kernel.config.WorldConfig(); - for(var i = 0; i < handlers.length; i++) { - if (isList(handlers[i])) { - attribs = handlers[i]; - } - else if (isHandler(handlers[i])) { - config = handlers[i](config); - } - else if ( types.isWorldConfig(handlers[i]) ) { - handlers[i].startupArgs = helpers.map(expandHandler, handlers[i].startupArgs); - userConfigs.push(handlers[i]); - } - } - config = config.updateAll({'changeWorld': Jsworld.updateWorld, - 'shutdownWorld': Jsworld.shutdownWorld}); - var stimuli = new world.Kernel.stimuli.StimuliHandler(config, caller, restarter); - - var wrappedHandlers = []; - var wrappedRedraw; - var wrappedRedrawCss; - - - if (config.lookup('onDraw')) { - wrappedRedraw = function(w, k) { - try { - caller(config.lookup('onDraw'), [w], - function(newDomTree) { - deepUnwrapJsValues(newDomTree, function(unwrappedTree) { - checkWellFormedDomTree(unwrappedTree, unwrappedTree, undefined); - var result = [toplevelNode, - helpers.deepListToArray(unwrappedTree)]; - k(result); - }); - }); - } catch (e) { - handleError(e); -// throw e; - } - } - - if (config.lookup('onDrawCss')) { - wrappedRedrawCss = function(w, k) { - try { - caller(config.lookup('onDrawCss'), [w], - function(res) { - var result = helpers.deepListToArray(res); - result = mutateStringsInDeepArray(result); - // plt.Kernel.setLastLoc(undefined); - k(result); - }); - } catch (e) { - handleError(e); - // throw e; - } - } - } - else { - wrappedRedrawCss = function(w, k) { k([]); }; - } - wrappedHandlers.push(_js.on_draw(wrappedRedraw, wrappedRedrawCss)); - } else if (config.lookup('onRedraw')) { - var reusableCanvas = undefined; - var reusableCanvasNode = undefined; - - wrappedRedraw = function(w, k) { - try { - //console.log('in onRedraw handler'); - caller(config.lookup('onRedraw'), [w], - function(aScene) { - // Performance hack: if we're using onRedraw, we know - // we've got a scene, so we optimize away the repeated - // construction of a canvas object. - if ( world.Kernel.isImage(aScene) ) { - var width = aScene.getWidth(); - var height = aScene.getHeight(); - - if (! reusableCanvas) { - reusableCanvas = world.Kernel.makeCanvas(width, height); - // Note: the canvas object may itself manage objects, - // as in the case of an excanvas. In that case, we must make - // sure jsworld doesn't try to disrupt its contents! - reusableCanvas.jsworldOpaque = true; - reusableCanvasNode = _js.node_to_tree(reusableCanvas); - } - - reusableCanvas.width = width; - reusableCanvas.height = height; - var ctx = reusableCanvas.getContext("2d"); - aScene.render(ctx, 0, 0); - - k([toplevelNode, reusableCanvasNode]); - } else { - k([toplevelNode, _js.node_to_tree(types.toDomNode(aScene))]); - } - }); - } catch (e) { - handleError(e); -// throw e; - } - } - - wrappedRedrawCss = function(w, k) { - //console.log('in RedrawCss handler'); - k([[reusableCanvas, - ["width", reusableCanvas.width + "px"], - ["height", reusableCanvas.height + "px"]]]); - } - wrappedHandlers.push(_js.on_draw(wrappedRedraw, wrappedRedrawCss)); - } else { - wrappedHandlers.push(_js.on_world_change - (function(w, k) { - Jsworld.printWorldHook(w, toplevelNode); - k(); - })); - } - - if (config.lookup('tickDelay')) { - var wrappedTick = function(w, k) { - caller(config.lookup('onTick'), - [w], - k); - } - var wrappedDelay = jsnums.toFixnum( config.lookup('tickDelay') ); - wrappedHandlers.push(_js.on_tick(wrappedDelay, wrappedTick)); - } - - if (config.lookup('stopWhen')) { - wrappedHandlers.push(_js.stop_when( - function(w, k) { - caller(config.lookup('stopWhen'), [w], - function(res) { k(res); }); - })); - } - - - if (config.lookup('onKey')) { - var wrappedKey = function(w, e, k) { - caller(config.lookup('onKey'), [w, helpers.getKeyCodeName(e)], k); - } - wrappedHandlers.push(_js.on_key(wrappedKey)); - toplevelNode.focus(); - } - - - if (config.lookup('initialEffect')) { - var updaters = - world.Kernel.applyEffect(config.lookup('initialEffect')); - for (var i = 0 ; i < updaters.length; i++) { - if (config.lookup('stopWhen') && - config.lookup('stopWhen')([initWorld])) { - break; - } else { - initWorld = updaters[i](initWorld); - } - } - } - - - _js.big_bang(toplevelNode, - initWorld, - wrappedHandlers, - helpers.assocListToHash(attribs), - terminator); - - startUserConfigs(function() {}); - - return { - breaker: function() { - handleError(types.schemeError( - types.incompleteExn(types.exnBreak, 'user break', []))); - } - }; - - } - - - - var handleError = function(e) { -// helpers.reportError(e); - // When something bad happens, shut down - // the world computation. -// helpers.reportError("Shutting down jsworld computations"); -// world.Kernel.stimuli.onShutdown(); - world.Kernel.stimuli.massShutdown(); - shutdownUserConfigs(function() { - errorReporter(e); -// console.log('Got an error, the error was:'); -// console.log(e); - if (typeof(console) !== 'undefined' && console.log) { - if (e.stack) { - console.log(e.stack); - } - else { - console.log(e); - } - } - if ( types.isSchemeError(e) ) { - terminator(e); - } - else if ( types.isInternalError(e) ) { - terminator(e); - } - else if (typeof(e) == 'string') { - terminator( types.schemeError(types.incompleteExn(types.exnFail, e, [])) ); - } - else if (e instanceof Error) { - terminator( types.schemeError(types.incompleteExn(types.exnFail, e.message, [])) ); - } - else { - terminator( types.schemeError(e) ); - } - }); - } - - - - // updateWorld: CPS( CPS(world -> world) -> void ) - Jsworld.updateWorld = function(updater, k) { - var wrappedUpdater = function(w, k2) { - try { - updater(w, k2); - } catch (e) { - if (typeof(console) !== 'undefined' && console.log && e.stack) { - console.log(e.stack); - } - handleError(e); -// k2(w); - } - } - - _js.change_world(wrappedUpdater, k); - } - - - - // shutdownWorld: -> void - // Shut down all world computations. - Jsworld.shutdownWorld = function() { - _js.shutdown(); - }; - - -// var getAttribs = function(args) { -// if (args.length == 0) { -// return [] -// } -// if (args.length == 1) { -// return helpers.assocListToHash(args[0]); -// } else { -// throw new Error("getAttribs recevied unexpected value for args: " -// + args); -// } -// } - - - Jsworld.p = _js.p; - - Jsworld.div = _js.div; - - Jsworld.buttonBang = function(updateWorldF, effectF, attribs) { - var wrappedF = function(w, evt, k) { - try { -// FIXME: Get effects back online! -// caller(effectF, [world], -// function(effect) { - caller(updateWorldF, [w], - function(newWorld) { -// world.Kernel.applyEffect(effect); - k(newWorld); - }); -// }); - } catch (e) { - if (typeof(console) !== 'undefined' && console.log && e.stack) { - console.log(e.stack); - } - handleError(e); -// k(w); - } - } - return _js.button(wrappedF, attribs); - }; - - - Jsworld.input = function(type, updateF, attribs) { - var wrappedUpdater = function(w, evt, k) { - caller(updateF, [w, evt], k); - } - return _js.input(type, wrappedUpdater, attribs); - }; - - - Jsworld.get_dash_input_dash_value = function(node) { -// plt.Kernel.check(node, -// function(x) { return (plt.Kernel.isString(node) || -// node.nodeType == -// Node.ELEMENT_NODE) }, -// "get-input-value", -// "dom-node", -// 1); - if (types.isString(node)) { - return (document.getElementById(node).value || ""); - } else { - return (node.value || ""); - } - - }; - - - - // Images. - Jsworld.img = _js.img; - - // text: string -> node - Jsworld.text = _js.text; - - Jsworld.select = function(options, updateF, attribs) { - var wrappedUpdater = function(w, e, k) { -// console.log(e); - caller(updateF, [w, e.target.value], k); - } - return _js.select(attribs, options, wrappedUpdater); - }; - - - - - ////////////////////////////////////////////////////////////////////// - Jsworld.emptyPage = _js.emptyPage; - - Jsworld.placeOnPage = function(elt, left, top, page) { - deepUnwrapJsValues(elt, function(newElt) { - elt = types.toDomNode(newElt);}); - return _js.placeOnPage(elt, left, top, page); - }; - - - // fixme: add support for textarea, h1, canvas - - -// // raw_node: scheme-value assoc -> node -// Jsworld.rawNode = function(x, args) { -// var attribs = getAttribs(args); -// var node = _js.raw_node(types.toDomNode(x), attribs); -// node.toWrittenString = function(cache) { return "(js-raw-node ...)"; } -// node.toDisplayedString = node.toWrittenString; -// node.toDomNode = function(cache) { return node; } -// return node; -// }; - - - -})(); diff --git a/world/scratch/jsworld/private/jsworld/jsworld.js b/world/scratch/jsworld/private/jsworld/jsworld.js deleted file mode 100644 index f4d315d..0000000 --- a/world/scratch/jsworld/private/jsworld/jsworld.js +++ /dev/null @@ -1,1488 +0,0 @@ -var jsworld = {}; - -// Stuff here is copy-and-pasted from Chris's JSWorld. We -// namespace-protect it, and add the Javascript <-> Moby wrapper -// functions here. - -(function() { - - /* Type signature notation - * CPS(a b ... -> c) is used to denote - * a b ... (c -> void) -> void - */ - - jsworld.Jsworld = {}; - var Jsworld = jsworld.Jsworld; - - - var currentFocusedNode = false; - - var doNothing = function() {}; - - - - // - // WORLD STUFFS - // - - function InitialWorld() {} - - var world = new InitialWorld(); - var worldListeners = []; - var eventDetachers = []; - var runningBigBangs = []; - - var changingWorld = false; - - - - // Close all world computations. - Jsworld.shutdown = function() { - while(runningBigBangs.length > 0) { - var currentRecord = runningBigBangs.pop(); - if (currentRecord) { currentRecord.pause(); } - } - clear_running_state(); - } - - - - function add_world_listener(listener) { - worldListeners.push(listener); - } - - - function remove_world_listener(listener) { - var index = worldListeners.indexOf(listener); - if (index != -1) { - worldListeners.splice(index, 1); - } - } - - function clear_running_state() { - world = new InitialWorld(); - worldListeners = []; - - for (var i = 0; i < eventDetachers.length; i++) { - eventDetachers[i](); - } - eventDetachers = []; - changingWorld = false; - } - - - // If we're in the middle of a change_world, delay. - var DELAY_BEFORE_RETRY = 10; - - - // change_world: CPS( CPS(world -> world) -> void ) - // Adjust the world, and notify all listeners. - var change_world = function(updater, k) { - - // Check to see if we're in the middle of changing - // the world already. If so, put on the queue - // and exit quickly. - if (changingWorld) { - setTimeout( - function() { - change_world(updater, k)}, - DELAY_BEFORE_RETRY); - return; - } - - - changingWorld = true; - var originalWorld = world; - - var changeWorldHelp = function() { - if (world instanceof WrappedWorldWithEffects) { - var effects = world.getEffects(); - helpers.forEachK(effects, - function(anEffect, k2) { - anEffect.invokeEffect(change_world, k2); - }, - function (e) { - changingWorld = false; - throw e; - }, - function() { - world = world.getWorld(); - changeWorldHelp2(); - }); - } else { - changeWorldHelp2(); - } - }; - - var changeWorldHelp2 = function() { - helpers.forEachK(worldListeners, - function(listener, k2) { - listener(world, originalWorld, k2); - }, - function(e) { - changingWorld = false; - world = originalWorld; - throw e; }, - function() { - changingWorld = false; - k(); - }); - }; - - try { - updater(world, function(newWorld) { - world = newWorld; - changeWorldHelp(); - }); - } catch(e) { - changingWorld = false; - world = originalWorld; - - if (typeof(console) !== 'undefined' && console.log && e.stack) { - console.log(e.stack); - } - throw e; - } - } - Jsworld.change_world = change_world; - - - - - // - // STUFF THAT SHOULD REALLY BE IN ECMASCRIPT - // - Number.prototype.NaN0=function(){return isNaN(this)?0:this;} - function getPosition(e){ - var left = 0; - var top = 0; - while (e.offsetParent){ - left += e.offsetLeft + (e.currentStyle?(parseInt(e.currentStyle.borderLeftWidth)).NaN0():0); - top += e.offsetTop + (e.currentStyle?(parseInt(e.currentStyle.borderTopWidth)).NaN0():0); - e = e.offsetParent; - } - left += e.offsetLeft + (e.currentStyle?(parseInt(e.currentStyle.borderLeftWidth)).NaN0():0); - top += e.offsetTop + (e.currentStyle?(parseInt(e.currentStyle.borderTopWidth)).NaN0():0); - return {x:left, y:top}; - } - Jsworld.getPosition = getPosition; - - - var gensym_counter = 0; - function gensym(){ return gensym_counter++;} - Jsworld.gensym = gensym; - - - function map(a1, f) { - var b = new Array(a1.length); - for (var i = 0; i < a1.length; i++) { - b[i] = f(a1[i]); - } - return b; - } - Jsworld.map = map; - - - - function concat_map(a, f) { - var b = []; - for (var i = 0; i < a.length; i++) { - b = b.concat(f(a[i])); - } - return b; - } - - - function mapi(a, f) { - var b = new Array(a.length); - for (var i = 0; i < a.length; i++) { - b[i] = f(a[i], i); - } - return b; - } - Jsworld.mapi = mapi; - - - function fold(a, x, f) { - for (var i = 0; i < a.length; i++) { - x = f(a[i], x); - } - return x; - } - Jsworld.fold = fold; - - - function augment(o, a) { - var oo = {}; - for (var e in o) - oo[e] = o[e]; - for (var e in a) - oo[e] = a[e]; - return oo; - } - Jsworld.augment = augment; - - - function assoc_cons(o, k, v) { - var oo = {}; - for (var e in o) - oo[e] = o[e]; - oo[k] = v; - return oo; - } - Jsworld.assoc_cons = assoc_cons; - - - function cons(value, array) { - return [value].concat(array); - } - Jsworld.cons = cons; - - - function append(array1, array2){ - return array1.concat(array2); - } - Jsworld.append = append; - - function array_join(array1, array2){ - var joined = []; - for (var i = 0; i < array1.length; i++) - joined.push([array1[i], array2[i]]); - return joined; - } - Jsworld.array_join = array_join; - - - function removeq(a, value) { - for (var i = 0; i < a.length; i++) - if (a[i] === value){ - return a.slice(0, i).concat(a.slice(i+1)); - } - return a; - } - Jsworld.removeq = removeq; - - function removef(a, value) { - for (var i = 0; i < a.length; i++) - if ( f(a[i]) ){ - return a.slice(0, i).concat(a.slice(i+1)); - } - return a; - } - Jsworld.removef = removef; - - - function filter(a, f) { - var b = []; - for (var i = 0; i < a.length; i++) { - if ( f(a[i]) ) { - b.push(a[i]); - } - } - return b; - } - Jsworld.filter = filter; - - - function without(obj, attrib) { - var o = {}; - for (var a in obj) - if (a != attrib) - o[a] = obj[a]; - return o; - } - Jsworld.without = without; - - - function memberq(a, x) { - for (var i = 0; i < a.length; i++) - if (a[i] === x) return true; - return false; - } - Jsworld.memberq = memberq; - - - function member(a, x) { - for (var i = 0; i < a.length; i++) - if (a[i] == x) return true; - return false; - } - Jsworld.member = member; - - - - function head(a){ - return a[0]; - } - Jsworld.head = head; - - - function tail(a){ - return a.slice(1, a.length); - } - Jsworld.tail = tail; - - // - // DOM UPDATING STUFFS - // - - // tree(N): { node: N, children: [tree(N)] } - // relation(N): { relation: 'parent', parent: N, child: N } | { relation: 'neighbor', left: N, right: N } - // relations(N): [relation(N)] - // nodes(N): [N] - // css(N): [css_node(N)] - // css_node(N): { node: N, attribs: attribs } | { className: string, attribs: attribs } - // attrib: { attrib: string, values: [string] } - // attribs: [attrib] - - // treeable(nodes(N), relations(N)) = bool - /*function treeable(nodes, relations) { - // for all neighbor relations between x and y - for (var i = 0; i < relations.length; i++) - if (relations[i].relation == 'neighbor') { - var x = relations[i].left, y = relations[i].right; - - // there does not exist a neighbor relation between x and z!=y or z!=x and y - for (var j = 0; j < relations.length; j++) - if (relations[j].relation === 'neighbor') - if (relations[j].left === x && relations[j].right !== y || - relations[j].left !== x && relations[j].right === y) - return false; - } - - // for all parent relations between x and y - for (var i = 0; i < relations.length; i++) - if (relations[i].relation == 'parent') { - var x = relations[i].parent, y = relations[i].child; - - // there does not exist a parent relation between z!=x and y - for (var j = 0; j < relations.length; j++) - if (relations[j].relation == 'parent') - if (relations[j].parent !== x && relations[j].child === y) - return false; - } - - // for all neighbor relations between x and y - for (var i = 0; i < relations.length; i++) - if (relations[i].relation == 'neighbor') { - var x = relations[i].left, y = relations[i].right; - - // all parent relations between z and x or y share the same z - for (var j = 0; j < relations.length; j++) - if (relations[j].relation == 'parent') - for (var k = 0; k < relations.length; k++) - if (relations[k].relation == 'parent') - if (relations[j].child === x && relations[k].child === y && - relations[j].parent !== relations[k].parent) - return false; - } - - return true; - }*/ - - - // node_to_tree: dom -> dom-tree - // Given a native dom node, produces the appropriate tree. - function node_to_tree(domNode) { - var result = [domNode]; - for (var c = domNode.firstChild; c != null; c = c.nextSibling) { - result.push(node_to_tree(c)); - } - return result; - } - Jsworld.node_to_tree = node_to_tree; - - - - // nodes(tree(N)) = nodes(N) - function nodes(tree) { - var ret; - - if (tree.node.jsworldOpaque == true) { - return [tree.node]; - } - - ret = [tree.node]; - for (var i = 0; i < tree.children.length; i++) - ret = ret.concat(nodes(tree.children[i])); - - return ret; - } - - - // relations(tree(N)) = relations(N) - function relations(tree) { - var ret = []; - - for (var i = 0; i < tree.children.length; i++) - ret.push({ relation: 'parent', - parent: tree.node, - child: tree.children[i].node }); - - for (var i = 0; i < tree.children.length - 1; i++) - ret.push({ relation: 'neighbor', - left: tree.children[i].node, - right: tree.children[i + 1].node }); - - if (! tree.node.jsworldOpaque) { - for (var i = 0; i < tree.children.length; i++) { - ret = ret.concat(relations(tree.children[i])); - } - } - - return ret; - } - - - - var removeAllChildren = function(n) { - while (n.firstChild) { - n.removeChild(n.firstChild); - } - } - - - // Preorder traversal. - var preorder = function(node, f) { - f(node, function() { - var child = node.firstChild; - var nextSibling; - while (child) { - var nextSibling = child.nextSibling; - preorder(child, f); - child = nextSibling; - } - }); - }; - - - // update_dom(nodes(Node), relations(Node)) = void - function update_dom(toplevelNode, nodes, relations) { - - // TODO: rewrite this to move stuff all in one go... possible? necessary? - - // move all children to their proper parents - for (var i = 0; i < relations.length; i++) { - if (relations[i].relation == 'parent') { - var parent = relations[i].parent, child = relations[i].child; - if (child.parentNode !== parent) { - parent.appendChild(child); - } - } - } - - // arrange siblings in proper order - // truly terrible... BUBBLE SORT - var unsorted = true; - while (unsorted) { - unsorted = false; - for (var i = 0; i < relations.length; i++) { - if (relations[i].relation == 'neighbor') { - var left = relations[i].left, right = relations[i].right; - - if (! nodeEq(left.nextSibling, right)) { - left.parentNode.insertBefore(left, right) - unsorted = true; - } - } - } - } - - // Finally, remove nodes that shouldn't be attached anymore. - var nodesPlus = nodes.concat([toplevelNode]); - preorder(toplevelNode, function(aNode, continueTraversalDown) { - if (aNode.jsworldOpaque) { - if (! isMemq(aNode, nodesPlus)) { - aNode.parentNode.removeChild(aNode); - } - } else { - if (! isMemq(aNode, nodesPlus)) { - aNode.parentNode.removeChild(aNode); - } else { - continueTraversalDown(); - } - } - }); - - refresh_node_values(nodes); - } - - - // isMemq: X (arrayof X) -> boolean - // Produces true if any of the elements of L are nodeEq to x. - var isMemq = function(x, L) { - var i; - for (i = 0 ; i < L.length; i++) { - if (nodeEq(x, L[i])) { - return true; - } - } - return false; - }; - - - // nodeEq: node node -> boolean - // Returns true if the two nodes should be the same. - var nodeEq = function(node1, node2) { - return (node1 && node2 && node1 === node2); - } - - - - // camelCase: string -> string - function camelCase(name) { - return name.replace(/\-(.)/g, function(m, l){return l.toUpperCase()}); - } - - - function set_css_attribs(node, attribs) { - for (var j = 0; j < attribs.length; j++){ - node.style[camelCase(attribs[j].attrib)] = attribs[j].values.join(" "); - } - } - - - // isMatchingCssSelector: node css -> boolean - // Returns true if the CSS selector matches. - function isMatchingCssSelector(node, css) { - if (css.id.match(/^\./)) { - // Check to see if we match the class - return ('className' in node && member(node['className'].split(/\s+/), - css.id.substring(1))); - } else { - return ('id' in node && node.id == css.id); - } - } - - - function update_css(nodes, css) { - // clear CSS - for (var i = 0; i < nodes.length; i++) { - if ( !nodes[i].jsworldOpaque ) { - clearCss(nodes[i]); - } - } - - // set CSS - for (var i = 0; i < css.length; i++) - if ('id' in css[i]) { - for (var j = 0; j < nodes.length; j++) - if (isMatchingCssSelector(nodes[j], css[i])) { - set_css_attribs(nodes[j], css[i].attribs); - } - } - else set_css_attribs(css[i].node, css[i].attribs); - } - - - var clearCss = function(node) { - // FIXME: we should not be clearing the css -// if ('style' in node) -// node.style.cssText = ""; - } - - - - // If any node cares about the world, send it in. - function refresh_node_values(nodes) { - for (var i = 0; i < nodes.length; i++) { - if (nodes[i].onWorldChange) { - nodes[i].onWorldChange(world); - } - } - } - - - - function do_redraw(world, oldWorld, toplevelNode, redraw_func, redraw_css_func, k) { - if (oldWorld instanceof InitialWorld) { - // Simple path - redraw_func(world, - function(drawn) { - var t = sexp2tree(drawn); - var ns = nodes(t); - // HACK: css before dom, due to excanvas hack. - redraw_css_func(world, - function(css) { - update_css(ns, sexp2css(css)); - update_dom(toplevelNode, ns, relations(t)); - k(); - }); - }); - } else { - maintainingSelection( - function(k2) { - // For legibility, here is the non-CPS version of the same function: - /* - var oldRedraw = redraw_func(oldWorld); - var newRedraw = redraw_func(world); - var oldRedrawCss = redraw_css_func(oldWorld); - var newRedrawCss = redraw_css_func(world); - var t = sexp2tree(newRedraw); - var ns = nodes(t); - - // Try to save the current selection and preserve it across - // dom updates. - - if(oldRedraw !== newRedraw) { - // Kludge: update the CSS styles first. - // This is a workaround an issue with excanvas: any style change - // clears the content of the canvas, so we do this first before - // attaching the dom element. - update_css(ns, sexp2css(newRedrawCss)); - update_dom(toplevelNode, ns, relations(t)); - } else { - if(oldRedrawCss !== newRedrawCss) { - update_css(ns, sexp2css(newRedrawCss)); - } - } - */ - - // We try to avoid updating the dom if the value - // hasn't changed. - redraw_func(oldWorld, - function(oldRedraw) { - redraw_func(world, - function(newRedraw) { - redraw_css_func(oldWorld, - function(oldRedrawCss) { - redraw_css_func(world, - function(newRedrawCss) { - var t = sexp2tree(newRedraw); - var ns = nodes(t); - - // Try to save the current selection and preserve it across - // dom updates. - - if(oldRedraw !== newRedraw) { - // Kludge: update the CSS styles first. - // This is a workaround an issue with excanvas: any style change - // clears the content of the canvas, so we do this first before - // attaching the dom element. - update_css(ns, sexp2css(newRedrawCss)); - update_dom(toplevelNode, ns, relations(t)); - } else { - if (oldRedrawCss !== newRedrawCss) { - update_css(ns, sexp2css(newRedrawCss)); - } - } - k2(); - }) - }) - }) - }); - }, k); - } - } - - - // maintainingSelection: (-> void) -> void - // Calls the thunk f while trying to maintain the current focused selection. - function maintainingSelection(f, k) { - var currentFocusedSelection; - if (hasCurrentFocusedSelection()) { - currentFocusedSelection = getCurrentFocusedSelection(); - f(function() { - currentFocusedSelection.restore(); - k(); - }); - } else { - f(function() { k(); }); - } - } - - - - function FocusedSelection() { - this.focused = currentFocusedNode; - this.selectionStart = currentFocusedNode.selectionStart; - this.selectionEnd = currentFocusedNode.selectionEnd; - } - - // Try to restore the focus. - FocusedSelection.prototype.restore = function() { - // FIXME: if we're scrolling through, what's visible - // isn't restored yet. - if (this.focused.parentNode) { - this.focused.selectionStart = this.selectionStart; - this.focused.selectionEnd = this.selectionEnd; - this.focused.focus(); - } else if (this.focused.id) { - var matching = document.getElementById(this.focused.id); - if (matching) { - matching.selectionStart = this.selectionStart; - matching.selectionEnd = this.selectionEnd; - matching.focus(); - } - } - }; - - function hasCurrentFocusedSelection() { - return currentFocusedNode != undefined; - } - - function getCurrentFocusedSelection() { - return new FocusedSelection(); - } - - - - ////////////////////////////////////////////////////////////////////// - - function BigBangRecord(top, world, handlerCreators, handlers, attribs) { - this.top = top; - this.world = world; - this.handlers = handlers; - this.handlerCreators = handlerCreators; - this.attribs = attribs; - } - - BigBangRecord.prototype.restart = function() { - big_bang(this.top, this.world, this.handlerCreators, this.attribs); - } - - BigBangRecord.prototype.pause = function() { - for(var i = 0 ; i < this.handlers.length; i++) { - if (this.handlers[i] instanceof StopWhenHandler) { - // Do nothing for now. - } else { - this.handlers[i].onUnregister(top); - } - } - }; - ////////////////////////////////////////////////////////////////////// - - // Notes: big_bang maintains a stack of activation records; it should be possible - // to call big_bang re-entrantly. - function big_bang(top, init_world, handlerCreators, attribs, k) { - // clear_running_state(); - - // Construct a fresh set of the handlers. - var handlers = map(handlerCreators, function(x) { return x();} ); - if (runningBigBangs.length > 0) { - runningBigBangs[runningBigBangs.length - 1].pause(); - } - - // Create an activation record for this big-bang. - var activationRecord = - new BigBangRecord(top, init_world, handlerCreators, handlers, attribs); - runningBigBangs.push(activationRecord); - function keepRecordUpToDate(w, oldW, k2) { - activationRecord.world = w; - k2(); - } - add_world_listener(keepRecordUpToDate); - - - - // Monitor for termination and register the other handlers. - var stopWhen = new StopWhenHandler(function(w, k2) { k2(false); }, - function(w, k2) { k2(w); }); - for(var i = 0 ; i < handlers.length; i++) { - if (handlers[i] instanceof StopWhenHandler) { - stopWhen = handlers[i]; - } else { - handlers[i].onRegister(top); - } - } - function watchForTermination(w, oldW, k2) { - stopWhen.test(w, - function(stop) { - if (stop) { - Jsworld.shutdown(); - k(w); - /* - stopWhen.receiver(world, - function() { - var currentRecord = runningBigBangs.pop(); - if (currentRecord) { currentRecord.pause(); } - if (runningBigBangs.length > 0) { - var restartingBigBang = runningBigBangs.pop(); - restartingBigBang.restart(); - } - k(); - }); - */ - } - else { k2(); } - }); - }; - add_world_listener(watchForTermination); - - - // Finally, begin the big-bang. - copy_attribs(top, attribs); - change_world(function(w, k2) { k2(init_world); }, doNothing); - - - } - Jsworld.big_bang = big_bang; - - - - - - // on_tick: number CPS(world -> world) -> handler - function on_tick(delay, tick) { - return function() { - var scheduleTick, ticker; - - - (new Date()).valueOf() - - scheduleTick = function(t) { - ticker.watchId = setTimeout( - function() { - ticker.watchId = undefined; - var startTime = (new Date()).valueOf(); - change_world(tick, - function() { - var endTime = (new Date()).valueOf(); - scheduleTick(Math.max(delay - (endTime - startTime), - 0)); - }); - }, - t); - }; - - ticker = { - watchId: -1, - onRegister: function (top) { - scheduleTick(delay); - }, - - onUnregister: function (top) { - if (ticker.watchId) - clearTimeout(ticker.watchId); - } - }; - return ticker; - }; - } - Jsworld.on_tick = on_tick; - - - function on_key(press) { - return function() { - var wrappedPress = function(e) { - preventDefault(e); - stopPropagation(e); - change_world(function(w, k) { press(w, e, k); }, doNothing); - }; - return { - onRegister: function(top) { attachEvent(top, 'keydown', wrappedPress); }, - onUnregister: function(top) { detachEvent(top, 'keydown', wrappedPress); } - }; - } - } - Jsworld.on_key = on_key; - - - - // on_draw: CPS(world -> (sexpof node)) CPS(world -> (sexpof css-style)) -> handler - function on_draw(redraw, redraw_css) { - var wrappedRedraw = function(w, k) { - redraw(w, function(newDomTree) { - checkDomSexp(newDomTree, newDomTree); - k(newDomTree); - }); - } - - return function() { - var drawer = { - _top: null, - _listener: function(w, oldW, k2) { - do_redraw(w, oldW, drawer._top, wrappedRedraw, redraw_css, k2); - }, - onRegister: function (top) { - drawer._top = top; - add_world_listener(drawer._listener); - }, - - onUnregister: function (top) { - remove_world_listener(drawer._listener); - } - }; - return drawer; - }; - } - Jsworld.on_draw = on_draw; - - - - function StopWhenHandler(test, receiver) { - this.test = test; - this.receiver = receiver; - } - // stop_when: CPS(world -> boolean) CPS(world -> boolean) -> handler - function stop_when(test, receiver) { - return function() { - if (receiver == undefined) { - receiver = function(w, k) { k(w); }; - } - return new StopWhenHandler(test, receiver); - }; - } - Jsworld.stop_when = stop_when; - - - - function on_world_change(f) { - var listener = function(world, oldW, k) { f(world, k); }; - return function() { - return { - onRegister: function (top) { - add_world_listener(listener); }, - onUnregister: function (top) { - remove_world_listener(listener)} - }; - }; - } - Jsworld.on_world_change = on_world_change; - - - - - - // Compatibility for attaching events to nodes. - function attachEvent(node, eventName, fn) { - if (node.addEventListener) { - // Mozilla - node.addEventListener(eventName, fn, false); - } else { - // IE - node.attachEvent('on' + eventName, fn, false); - } - } - - var detachEvent = function(node, eventName, fn) { - if (node.addEventListener) { - // Mozilla - node.removeEventListener(eventName, fn, false); - } else { - // IE - node.detachEvent('on' + eventName, fn, false); - } - } - - // - // DOM CREATION STUFFS - // - - // add_ev: node string CPS(world event -> world) -> void - // Attaches a world-updating handler when the world is changed. - function add_ev(node, event, f) { - var eventHandler = function(e) { change_world(function(w, k) { f(w, e, k); }, - doNothing); }; - attachEvent(node, event, eventHandler); - eventDetachers.push(function() { detachEvent(node, event, eventHandler); }); - } - - // add_ev_after: node string CPS(world event -> world) -> void - // Attaches a world-updating handler when the world is changed, but only - // after the fired event has finished. - function add_ev_after(node, event, f) { - var eventHandler = function(e) { - setTimeout(function() { change_world(function(w, k) { f(w, e, k); }, - doNothing); }, - 0); - }; - - attachEvent(node, event, eventHandler); - eventDetachers.push(function() { detachEvent(node, event, eventHandler); }); - } - - - function addFocusTracking(node) { - attachEvent(node, "focus", function(e) { - currentFocusedNode = node; }); - attachEvent(node, "blur", function(e) { - currentFocusedNode = undefined; - }); - return node; - } - - - - - - // - // WORLD STUFFS - // - - - function sexp2tree(sexp) { - if (isPage(sexp)) { - return sexp2tree(node_to_tree(sexp.toDomNode())); - } else { - if(sexp.length == undefined) return { node: sexp, children: [] }; - else return { node: sexp[0], children: map(sexp.slice(1), sexp2tree) }; - } - } - - function sexp2attrib(sexp) { - return { attrib: sexp[0], values: sexp.slice(1) }; - } - - function sexp2css_node(sexp) { - var attribs = map(sexp.slice(1), sexp2attrib); - if (typeof sexp[0] == 'string'){ - return [{ id: sexp[0], attribs: attribs }]; - } else if ('length' in sexp[0]){ - return map(sexp[0], function (id) { return { id: id, attribs: attribs } }); - } else { - return [{ node: sexp[0], attribs: attribs }]; - } - } - - function sexp2css(sexp) { - return concat_map(sexp, sexp2css_node); - } - - - - function isTextNode(n) { - return (n.nodeType == Node.TEXT_NODE); - } - - - function isElementNode(n) { - return (n.nodeType == Node.ELEMENT_NODE); - } - - - var throwDomError = function(thing, topThing) { - throw new JsworldDomError( - helpers.format( - "Expected a non-empty array, received ~s within ~s", - [thing, topThing]), - thing); - }; - - // checkDomSexp: X X -> boolean - // Checks to see if thing is a DOM-sexp. If not, - // throws an object that explains why not. - function checkDomSexp(thing, topThing) { - if (isPage(thing)) { - return; - } - - if (! thing instanceof Array) { - throwDomError(thing, topThing); - } - if (thing.length == 0) { - throwDomError(thing, topThing); - } - - // Check that the first element is a Text or an element. - if (isTextNode(thing[0])) { - if (thing.length > 1) { - throw new JsworldDomError(helpers.format("Text node ~s can not have children", - [thing]), - thing); - } - } else if (isElementNode(thing[0])) { - for (var i = 1; i < thing.length; i++) { - checkDomSexp(thing[i], thing); - } - } else { - throw new JsworldDomError( - helpers.format( - "expected a Text or an Element, received ~s within ~s", - [thing, topThing]), - thing[0]); - } - } - - function JsworldDomError(msg, elt) { - this.msg = msg; - this.elt = elt; - } - JsworldDomError.prototype.toString = function() { - return "on-draw: " + this.msg; - } - - - - - - // - // DOM CREATION STUFFS - // - - - function copy_attribs(node, attribs) { - if (attribs) - for (a in attribs) { - if (attribs.hasOwnProperty(a)) { - if (typeof attribs[a] == 'function') - add_ev(node, a, attribs[a]); - else{ - node[a] = attribs[a];//eval("node."+a+"='"+attribs[a]+"'"); - } - } - } - return node; - } - - - // - // NODE TYPES - // - - function p(attribs) { - return addFocusTracking(copy_attribs(document.createElement('p'), attribs)); - } - Jsworld.p = p; - - function div(attribs) { - return addFocusTracking(copy_attribs(document.createElement('div'), attribs)); - } - Jsworld.div = div; - - // Used To Be: (world event -> world) (hashof X Y) -> domElement - // Now: CPS(world event -> world) (hashof X Y) -> domElement - function button(f, attribs) { - var n = document.createElement('button'); - n.onclick = function(e) {return false;}; - add_ev(n, 'click', f); - return addFocusTracking(copy_attribs(n, attribs)); - } - Jsworld.button = button; - - - - - var preventDefault = function(event) { - if (event.preventDefault) { - event.preventDefault(); - } else { - event.returnValue = false; - } - } - - var stopPropagation = function(event) { - if (event.stopPropagation) { - event.stopPropagation(); - } else { - event.cancelBubble = true; - } - } - - - var stopClickPropagation = function(node) { - attachEvent(node, "click", - function(e) { - stopPropagation(e); - }); - return node; - } - - - // input: string CPS(world -> world) - function input(aType, updateF, attribs) { - aType = aType.toLowerCase(); - var dispatchTable = { text : text_input, - password: text_input, - checkbox: checkbox_input - //button: button_input, - //radio: radio_input - }; - - if (dispatchTable[aType]) { - return (dispatchTable[aType])(aType, updateF, attribs); - } - else { - throw new Error("js-input: does not currently support type " + aType); - } - } - Jsworld.input = input; - - - - - var text_input = function(type, updateF, attribs) { - var n = document.createElement('input'); - n.type = type; - - var lastVal = n.value; - var onEvent = function() { - if (! n.parentNode) { return; } - setTimeout( - function() { - if (lastVal != n.value) { - lastVal = n.value; - change_world(function (w, k) { - updateF(w, n.value, k); - }, doNothing); - } - }, - 0); - } - - -// attachEvent(n, "keypress", onEvent); -// eventDetachers.push(function() { -// detachEvent(n, "keypress", onEvent); }); - - attachEvent(n, "keydown", onEvent); - eventDetachers.push(function() { - detachEvent(n, "keydown", onEvent); }); - - attachEvent(n, "change", onEvent); - eventDetachers.push(function() { - detachEvent(n, "change", onEvent); }); - -// function onKey(w, e, k) { -// updateF(w, n.value, k); -// } -// // This established the widget->world direction -// add_ev_after(n, 'keypress', onKey); - - // Every second, do a manual polling of the object, just in case. -// var delay = 1000; -// var intervalId = setInterval(function() { -// if (! n.parentNode) { -// clearInterval(intervalId); -// return; -// } -// if (lastVal != n.value) { -// lastVal = n.value; -// change_world(function (w, k) { -// updateF(w, n.value, k); -// }, doNothing); -// } -// }, -// delay); - return stopClickPropagation( - addFocusTracking(copy_attribs(n, attribs))); - }; - - - var checkbox_input = function(type, updateF, attribs) { - var n = document.createElement('input'); - n.type = type; - var onCheck = function(w, e, k) { - updateF(w, n.checked, k); - }; - // This established the widget->world direction - add_ev_after(n, 'change', onCheck); - - attachEvent(n, 'click', function(e) { - stopPropagation(e); - }); - - return copy_attribs(n, attribs); - }; - - - var button_input = function(type, updateF, attribs) { - var n = document.createElement('button'); - add_ev(n, 'click', function(w, e, k) { updateF(w, n.value, k); }); - return addFocusTracking(copy_attribs(n, attribs)); - }; - - - - - - function text(s, attribs) { - var result = document.createElement("div"); - result.appendChild(document.createTextNode(String(s))); - result.jsworldOpaque = true; - return result; - } - Jsworld.text = text; - - function select(attribs, opts, f){ - var n = document.createElement('select'); - for(var i = 0; i < opts.length; i++) { - n.add(option({value: opts[i]}), null); - } - n.jsworldOpaque = true; - add_ev(n, 'change', f); - var result = addFocusTracking(copy_attribs(n, attribs)); - return result; - } - Jsworld.select = select; - - function option(attribs){ - var node = document.createElement("option"); - node.text = attribs.value; - node.value = attribs.value; - return node; - } - - - - function textarea(attribs){ - return addFocusTracking(copy_attribs(document.createElement('textarea'), attribs)); - } - Jsworld.textarea = textarea; - - function h1(attribs){ - return addFocusTracking(copy_attribs(document.createElement('h1'), attribs)); - } - Jsworld.h1 = h1; - - function canvas(attribs){ - return addFocusTracking(copy_attribs(document.createElement('canvas'), attribs)); - } - Jsworld.canvas = canvas; - - - function img(src, attribs) { - var n = document.createElement('img'); - n.src = src; - return addFocusTracking(copy_attribs(n, attribs)); - } - Jsworld.img = img; - - - - function raw_node(node, attribs) { - return addFocusTracking(copy_attribs(node, attribs)); - } - Jsworld.raw_node = raw_node; - - - - - - ////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////// - // Effects - - // An effect is an object with an invokeEffect() method. - - var WrappedWorldWithEffects = function(w, effects) { - if (w instanceof WrappedWorldWithEffects) { - this.w = w.w; - this.e = w.e.concat(effects); - } else { - this.w = w; - this.e = effects; - } - }; - - WrappedWorldWithEffects.prototype.getWorld = function() { - return this.w; - }; - - WrappedWorldWithEffects.prototype.getEffects = function() { - return this.e; - }; - - - ////////////////////////////////////////////////////////////////////// - - Jsworld.with_effect = function(w, e) { - return new WrappedWorldWithEffects(w, [e]); - }; - - Jsworld.with_multiple_effects = function(w, effects) { - return new WrappedWorldWithEffects(w, effects); - }; - - Jsworld.has_effects = function(w) { - return w instanceof WrappedWorldWithEffects; - }; - - - - - ////////////////////////////////////////////////////////////////////// - // Example effect: raise an alert. - Jsworld.alert_effect = function(msg) { - return new AlertEffect(msg); - }; - - var AlertEffect = function(msg) { - this.msg = msg; - }; - - AlertEffect.prototype.invokeEffect = function(k) { - alert(this.msg); - k(); - }; - - - ////////////////////////////////////////////////////////////////////// - - - // Example effect: play a song, given its url - Jsworld.music_effect = function(musicUrl) { - return new MusicEffect(musicUrl); - }; - - var MusicEffect = function(musicUrl) { - this.musicUrl = musicUrl; - }; - - MusicEffect.prototype.invokeEffect = function(k) { - new Audio(url).play(); - k(); - }; - - - - - - ////////////////////////////////////////////////////////////////////// - // Pages - - - var Page = function(elts, attribs) { - if (typeof(elts) === 'undefined') { - elts = []; - } - this.elts = elts; - this.attribs = attribs; - }; - - Page.prototype.add = function(elt, positionLeft, positionTop) { - return new Page(this.elts.concat([{elt: elt, - positionTop: positionTop, - positionLeft: positionLeft}]), - this.attribs); - }; - - Page.prototype.toDomNode = function() { - var aDiv = div(); - for (var i = 0 ; i < this.elts.length; i++) { - var elt = this.elts[i].elt; - if (! elt.style) { - elt.style = ''; - } - - elt.style.position = 'absolute'; - elt.style.left = this.elts[i].positionLeft + "px"; - elt.style.top = this.elts[i].positionTop + "px"; - aDiv.appendChild(elt); - }; - copy_attribs(aDiv, this.attribs) - return aDiv; - }; - - - isPage = function(x) { - return x instanceof Page; - }; - - Jsworld.isPage = isPage; - - Jsworld.emptyPage = function(attribs) { - var result = new Page([], attribs); - return result; - }; - - Jsworld.placeOnPage = function(elt, positionLeft, positionTop, page) { - if (typeof(elt) === 'string') { - elt = text(elt); - } - return page.add(elt, positionLeft, positionTop); - }; - - - -})(); diff --git a/world/scratch/world/kernel.js b/world/scratch/world/kernel.js deleted file mode 100644 index c0b51f9..0000000 --- a/world/scratch/world/kernel.js +++ /dev/null @@ -1,1938 +0,0 @@ -var world = {}; -world.Kernel = {}; - -EXPORTS['kernel'] = world.Kernel; - - - - - -var worldListeners = []; -var stopped; -var timerInterval = false; - - -// Inheritance from pg 168: Javascript, the Definitive Guide. -var heir = function(p) { - var f = function() {} - f.prototype = p; - return new f(); -} - - -// clone: object -> object -// Copies an object. The new object should respond like the old -// object, including to things like instanceof -var clone = function(obj) { - var C = function() {} - C.prototype = obj; - var c = new C(); - for (property in obj) { - if (obj.hasOwnProperty(property)) { - c[property] = obj[property]; - } - } - return c; -}; - - - - -var announceListeners = []; -world.Kernel.addAnnounceListener = function(listener) { - announceListeners.push(listener); -}; -world.Kernel.removeAnnounceListener = function(listener) { - var idx = announceListeners.indexOf(listener); - if (idx != -1) { - announceListeners.splice(idx, 1); - } -}; -world.Kernel.announce = function(eventName, vals) { - for (var i = 0; i < announceListeners.length; i++) { - try { - announceListeners[i](eventName, vals); - } catch (e) {} - } -}; - - - - - - - - - - -// changeWorld: world -> void -// Changes the current world to newWorld. -var changeWorld = function(newWorld) { - world = newWorld; - notifyWorldListeners(); -} - - -// updateWorld: (world -> world) -> void -// Public function: update the world, given the old state of the -// world. -world.Kernel.updateWorld = function(updater) { - var newWorld = updater(world); - changeWorld(newWorld); -} - - -world.Kernel.shutdownWorld = function() { - stopped = true; -}; - - -// notifyWorldListeners: -> void -// Tells all of the world listeners that the world has changed. -var notifyWorldListeners = function() { - var i; - for (i = 0; i < worldListeners.length; i++) { - worldListeners[i](world); - } -} - -// addWorldListener: (world -> void) -> void -// Adds a new world listener: whenever the world is changed, the aListener -// will be called with that new world. -var addWorldListener = function(aListener) { - worldListeners.push(aListener); -} - - -// getKeyCodeName: keyEvent -> String -// Given an event, try to get the name of the key. -var getKeyCodeName = function(e) { - var code = e.charCode || e.keyCode; - var keyname; - if (code == 37) { - keyname = "left"; - } else if (code == 38) { - keyname = "up"; - } else if (code == 39) { - keyname = "right"; - } else if (code == 40) { - keyname = "down"; - } else { - keyname = String.fromCharCode(code); - } - return keyname; -} - - -// resetWorld: -> void -// Resets all of the world global values. -var resetWorld = function() { - if (timerInterval) { - clearInterval(timerInterval); - timerInterval = false; - } - stopped = false; - worldListeners = []; -} - - -var getBigBangWindow = function(width, height) { - if (window.document.getElementById("canvas") != undefined) { - return window; - } - - var newWindow = window.open( - "big-bang.html", - "big-bang"); - //"toolbar=false,location=false,directories=false,status=false,menubar=false,width="+width+",height="+height); - if (newWindow == null) { - throw new Error("Error: Not allowed to create a new window."); } - - return newWindow; -} - - - -// scheduleTimerTick: -> void -// Repeatedly schedules an evaluation of the onTick until the program has stopped. -var scheduleTimerTick = function(window, config) { - timerInterval = window.setInterval( - function() { - if (stopped) { - window.clearTimeout(timerInterval); - timerInterval = false; - } - else { - world.Kernel.stimuli.onTick(); - } - }, - config.lookup('tickDelay')); -} - - - - -// Base class for all images. -var BaseImage = function(pinholeX, pinholeY) { - this.pinholeX = pinholeX; - this.pinholeY = pinholeY; -} -world.Kernel.BaseImage = BaseImage; - - -var isImage = function(thing) { - return (thing !== null && - thing !== undefined && - thing instanceof BaseImage); -} - - - -BaseImage.prototype.updatePinhole = function(x, y) { - var aCopy = clone(this); - aCopy.pinholeX = x; - aCopy.pinholeY = y; - return aCopy; -}; - - - -// render: context fixnum fixnum: -> void -// Render the image, where the upper-left corner of the image is drawn at -// (x, y). -// NOTE: the rendering should be oblivous to the pinhole. -BaseImage.prototype.render = function(ctx, x, y) { - throw new Error('BaseImage.render unimplemented!'); - // plt.Kernel.throwMobyError( - // false, - // "make-moby-error-type:generic-runtime-error", - // "Unimplemented method render"); -}; - - -// makeCanvas: number number -> canvas -// Constructs a canvas object of a particular width and height. -world.Kernel.makeCanvas = function(width, height) { - var canvas = document.createElement("canvas"); - canvas.width = width; - canvas.height = height; - - canvas.style.width = canvas.width + "px"; - canvas.style.height = canvas.height + "px"; - - // KLUDGE: IE compatibility uses /js/excanvas.js, and dynamic - // elements must be marked this way. - if (window && typeof window.G_vmlCanvasManager != 'undefined') { - canvas = window.G_vmlCanvasManager.initElement(canvas); - } - return canvas; -}; - - - -var withIeHack = function(canvas, f) { - // canvas.style.display = 'none'; - // document.body.appendChild(canvas); - // try { - var result = f(canvas); - // } catch(e) { - // document.body.removeChild(canvas); - // canvas.style.display = ''; - // throw e; - // } - // document.body.removeChild(canvas); - // canvas.style.display = ''; - return result; -}; - - -BaseImage.prototype.toDomNode = function(cache) { - var that = this; - var width = that.getWidth(); - var height = that.getHeight(); - var canvas = world.Kernel.makeCanvas(width, height); - - // KLUDGE: on IE, the canvas rendering functions depend on a - // context where the canvas is attached to the DOM tree. - - // We initialize an afterAttach hook; the client's responsible - // for calling this after the dom node is attached to the - // document. - canvas.afterAttach = function() { - var ctx = canvas.getContext("2d"); - that.render(ctx, 0, 0); - }; - - return canvas; -}; - - - - -BaseImage.prototype.toWrittenString = function(cache) { return ""; } -BaseImage.prototype.toDisplayedString = function(cache) { return ""; } - -BaseImage.prototype.isEqual = function(other, aUnionFind) { - return (this.pinholeX == other.pinholeX && - this.pinholeY == other.pinholeY); -}; - - - - -// isScene: any -> boolean -// Produces true when x is a scene. -var isScene = function(x) { - return ((x != undefined) && (x != null) && (x instanceof SceneImage)); -}; - -// SceneImage: primitive-number primitive-number (listof image) -> Scene -var SceneImage = function(width, height, children, withBorder) { - BaseImage.call(this, 0, 0); - this.width = width; - this.height = height; - this.children = children; // arrayof [image, number, number] - this.withBorder = withBorder; -} -SceneImage.prototype = heir(BaseImage.prototype); - - -// add: image primitive-number primitive-number -> Scene -SceneImage.prototype.add = function(anImage, x, y) { - return new SceneImage(this.width, - this.height, - this.children.concat([[anImage, - x - anImage.pinholeX, - y - anImage.pinholeY]]), - this.withBorder); -}; - -// render: 2d-context primitive-number primitive-number -> void -SceneImage.prototype.render = function(ctx, x, y) { - var i; - var childImage, childX, childY; - // Clear the scene. - ctx.clearRect(x, y, this.width, this.height); - // Then ask every object to render itself. - for(i = 0; i < this.children.length; i++) { - childImage = this.children[i][0]; - childX = this.children[i][1]; - childY = this.children[i][2]; - ctx.save(); - childImage.render(ctx, childX + x, childY + y); - ctx.restore(); - - - } - // Finally, draw the black border if withBorder is true - if (this.withBorder) { - ctx.strokeStyle = 'black'; - ctx.strokeRect(x, y, this.width, this.height); - } -}; - -SceneImage.prototype.getWidth = function() { - return this.width; -}; - -SceneImage.prototype.getHeight = function() { - return this.height; -}; - -SceneImage.prototype.isEqual = function(other, aUnionFind) { - if (!(other instanceof SceneImage)) { - return false; - } - - if (this.pinholeX != other.pinholeX || - this.pinholeY != other.pinholeY || - this.width != other.width || - this.height != other.height || - this.children.length != other.children.length) { - return false; - } - - for (var i = 0; i < this.children.length; i++) { - var rec1 = this.children[i]; - var rec2 = other.children[i]; - if (rec1[1] !== rec2[1] || - rec1[2] !== rec2[2] || - !types.isEqual(rec1[0], - rec2[0], - aUnionFind)) { - return false; - } - } - return true; -}; - - -////////////////////////////////////////////////////////////////////// - - -var FileImage = function(src, rawImage) { - BaseImage.call(this, 0, 0); - var self = this; - this.src = src; - this.isLoaded = false; - if (rawImage && rawImage.complete) { - this.img = rawImage; - this.isLoaded = true; - this.pinholeX = self.img.width / 2; - this.pinholeY = self.img.height / 2; - } else { - // fixme: we may want to do something blocking here for - // onload, since we don't know at this time what the file size - // should be, nor will drawImage do the right thing until the - // file is loaded. - this.img = new Image(); - this.img.onload = function() { - self.isLoaded = true; - self.pinholeX = self.img.width / 2; - self.pinholeY = self.img.height / 2; - }; - this.img.onerror = function(e) { - self.img.onerror = ""; - self.img.src = "http://www.wescheme.org/images/broken.png"; - } - this.img.src = src; - } -} -FileImage.prototype = heir(BaseImage.prototype); -// world.Kernel.FileImage = FileImage; - - -var imageCache = {}; -FileImage.makeInstance = function(path, rawImage) { - if (! (path in imageCache)) { - imageCache[path] = new FileImage(path, rawImage); - } - return imageCache[path]; -}; - -FileImage.installInstance = function(path, rawImage) { - imageCache[path] = new FileImage(path, rawImage); -}; - -FileImage.installBrokenImage = function(path) { - imageCache[path] = new TextImage("Unable to load " + path, 10, - colorDb.get("red")); -}; - - - -FileImage.prototype.render = function(ctx, x, y) { - ctx.drawImage(this.img, x, y); -}; - - -FileImage.prototype.getWidth = function() { - return this.img.width; -}; - - -FileImage.prototype.getHeight = function() { - return this.img.height; -}; - -// Override toDomNode: we don't need a full-fledged canvas here. -FileImage.prototype.toDomNode = function(cache) { - return this.img.cloneNode(true); -}; - -FileImage.prototype.isEqual = function(other, aUnionFind) { - return (other instanceof FileImage && - this.pinholeX == other.pinholeX && - this.pinholeY == other.pinholeY && - this.src == other.src); - // types.isEqual(this.img, other.img, aUnionFind)); -}; - - -////////////////////////////////////////////////////////////////////// - - -// OverlayImage: image image -> image -// Creates an image that overlays img1 on top of the -// other image. shiftX and shiftY are deltas off the first -// image's pinhole. -var OverlayImage = function(img1, img2, shiftX, shiftY) { - var deltaX = img1.pinholeX - img2.pinholeX + shiftX; - var deltaY = img1.pinholeY - img2.pinholeY + shiftY; - var left = Math.min(0, deltaX); - var top = Math.min(0, deltaY); - var right = Math.max(deltaX + img2.getWidth(), - img1.getWidth()); - var bottom = Math.max(deltaY + img2.getHeight(), - img1.getHeight()); - - BaseImage.call(this, - Math.floor((right-left) / 2), - Math.floor((bottom-top) / 2)); - this.img1 = img1; - this.img2 = img2; - this.width = right - left; - this.height = bottom - top; - - this.img1Dx = -left; - this.img1Dy = -top; - this.img2Dx = deltaX - left; - this.img2Dy = deltaY - top; -}; - -OverlayImage.prototype = heir(BaseImage.prototype); - - -OverlayImage.prototype.render = function(ctx, x, y) { - this.img2.render(ctx, x + this.img2Dx, y + this.img2Dy); - this.img1.render(ctx, x + this.img1Dx, y + this.img1Dy); -}; - - -OverlayImage.prototype.getWidth = function() { - return this.width; -}; - -OverlayImage.prototype.getHeight = function() { - return this.height; -}; - -OverlayImage.prototype.isEqual = function(other, aUnionFind) { - return ( other instanceof OverlayImage && - this.pinholeX == other.pinholeX && - this.pinholeY == other.pinholeY && - this.width == other.width && - this.height == other.height && - this.img1Dx == other.img1Dx && - this.img1Dy == other.img1Dy && - this.img2Dx == other.img2Dx && - this.img2Dy == other.img2Dy && - types.isEqual(this.img1, other.img1, aUnionFind) && - types.isEqual(this.img2, other.img2, aUnionFind) ); -}; - - -////////////////////////////////////////////////////////////////////// - - -// rotate: angle image -> image -// Rotates image by angle degrees in a counter-clockwise direction. -// based on http://stackoverflow.com/questions/3276467/adjusting-div-width-and-height-after-rotated -var RotateImage = function(angle, img) { - var sin = Math.sin(angle * Math.PI / 180), - cos = Math.cos(angle * Math.PI / 180); - - // (w,0) rotation - var x1 = Math.floor(cos * img.getWidth()), - y1 = Math.floor(sin * img.getWidth()); - - // (0,h) rotation - var x2 = Math.floor(-sin * img.getHeight()), - y2 = Math.floor( cos * img.getHeight()); - - // (w,h) rotation - var x3 = Math.floor(cos * img.getWidth() - sin * img.getHeight()), - y3 = Math.floor(sin * img.getWidth() + cos * img.getHeight()); - - var minX = Math.min(0, x1, x2, x3), - maxX = Math.max(0, x1, x2, x3), - minY = Math.min(0, y1, y2, y3), - maxY = Math.max(0, y1, y2, y3); - - var rotatedWidth = maxX - minX, - rotatedHeight = maxY - minY; - - // resize the image - BaseImage.call(this, - Math.floor(rotatedWidth / 2), - Math.floor(rotatedHeight / 2)); - - this.img = img; - this.width = rotatedWidth; - this.height = rotatedHeight; - this.angle = angle; - this.translateX = -minX; - this.translateY = -minY; -}; - -RotateImage.prototype = heir(BaseImage.prototype); - - -// translate drawing point, so that this.img appears in the UL corner. Then rotate and render this.img. -RotateImage.prototype.render = function(ctx, x, y) { - ctx.translate(this.translateX, this.translateY); - ctx.rotate(this.angle * Math.PI / 180); - this.img.render(ctx, x, y); - ctx.restore(); -}; - - -RotateImage.prototype.getWidth = function() { - return this.width; -}; - -RotateImage.prototype.getHeight = function() { - return this.height; -}; - -RotateImage.prototype.isEqual = function(other, aUnionFind) { - return ( other instanceof RotateImage && - this.pinholeX == other.pinholeX && - this.pinholeY == other.pinholeY && - this.width == other.width && - this.height == other.height && - this.angle == other.angle && - this.translateX == other.translateX && - this.translateY == other.translateY && - types.isEqual(this.img, other.img, aUnionFind) ); -}; - -////////////////////////////////////////////////////////////////////// - - -// ScaleImage: factor factor image -> image -// Scale an image -var ScaleImage = function(xFactor, yFactor, img) { - - // resize the image - BaseImage.call(this, - Math.floor((img.getWidth() * xFactor) / 2), - Math.floor((img.getHeight() * yFactor) / 2)); - - this.img = img; - this.width = img.getWidth() * xFactor; - this.height = img.getHeight() * yFactor; - this.xFactor = xFactor; - this.yFactor = yFactor; -}; - -ScaleImage.prototype = heir(BaseImage.prototype); - - -// scale the context, and pass it to the image's render function -ScaleImage.prototype.render = function(ctx, x, y) { - ctx.save(); - ctx.scale(this.xFactor, this.yFactor); - this.img.render(ctx, x, y); - ctx.restore(); -}; - - -ScaleImage.prototype.getWidth = function() { - return this.width; -}; - -ScaleImage.prototype.getHeight = function() { - return this.height; -}; - -ScaleImage.prototype.isEqual = function(other, aUnionFind) { - return ( other instanceof ScaleImage && - this.pinholeX == other.pinholeX && - this.pinholeY == other.pinholeY && - this.width == other.width && - this.height == other.height && - this.xFactor == other.xFactor && - this.yFactor == other.yFactor && - types.isEqual(this.img, other.img, aUnionFind) ); -}; - -////////////////////////////////////////////////////////////////////// - - - -var colorString = function(aColor) { - return ("rgb(" + - types.colorRed(aColor) + "," + - types.colorGreen(aColor) + ", " + - types.colorBlue(aColor) + ")"); -}; - - - -var RectangleImage = function(width, height, style, color) { - BaseImage.call(this, width/2, height/2); - this.width = width; - this.height = height; - this.style = style; - this.color = color; -}; -RectangleImage.prototype = heir(BaseImage.prototype); - - -RectangleImage.prototype.render = function(ctx, x, y) { - if (this.style.toString().toLowerCase() == "outline") { - ctx.save(); - ctx.beginPath(); - ctx.strokeStyle = colorString(this.color); - ctx.strokeRect(x, y, this.width, this.height); - ctx.closePath(); - ctx.restore(); - } else { - ctx.save(); - ctx.beginPath(); - - ctx.fillStyle = colorString(this.color); - ctx.fillRect(x, y, this.width, this.height); - - ctx.closePath(); - ctx.restore(); - } -}; - -RectangleImage.prototype.getWidth = function() { - return this.width; -}; - - -RectangleImage.prototype.getHeight = function() { - return this.height; -}; - -RectangleImage.prototype.isEqual = function(other, aUnionFind) { - return (other instanceof RectangleImage && - this.pinholeX == other.pinholeX && - this.pinholeY == other.pinholeY && - this.width == other.width && - this.height == other.height && - this.style == other.style && - types.isEqual(this.color, other.color, aUnionFind)); -}; - - -////////////////////////////////////////////////////////////////////// - -var TextImage = function(msg, size, color) { - BaseImage.call(this, 0, 0); - this.msg = msg; - this.size = size; - this.color = color; - this.font = this.size + "px Optimer"; - - - var canvas = world.Kernel.makeCanvas(0, 0); - var ctx = canvas.getContext("2d"); - ctx.font = this.font; - var metrics = ctx.measureText(msg); - - this.width = metrics.width; - // KLUDGE: I don't know how to get at the height. - this.height = ctx.measureText("m").width + 20; - -} - -TextImage.prototype = heir(BaseImage.prototype); - -TextImage.prototype.render = function(ctx, x, y) { - ctx.save(); - ctx.font = this.font; - ctx.textAlign = 'left'; - ctx.textBaseline = 'top'; - ctx.fillStyle = colorString(this.color); - ctx.fillText(this.msg, x, y); - ctx.restore(); -}; - -TextImage.prototype.getWidth = function() { - return this.width; -}; - - -TextImage.prototype.getHeight = function() { - return this.height; -}; - -TextImage.prototype.isEqual = function(other, aUnionFind) { - return (other instanceof TextImage && - this.pinholeX == other.pinholeX && - this.pinholeY == other.pinholeY && - this.msg == other.msg && - this.size == other.size && - types.isEqual(this.color, other.color, aUnionFind) && - this.font == other.font); -}; - - -////////////////////////////////////////////////////////////////////// - -var CircleImage = function(radius, style, color) { - BaseImage.call(this, radius, radius); - this.radius = radius; - this.style = style; - this.color = color; -} -CircleImage.prototype = heir(BaseImage.prototype); - -CircleImage.prototype.render = function(ctx, x, y) { - ctx.save(); - ctx.beginPath(); - ctx.arc(x + this.radius, - y + this.radius, - this.radius, 0, 2*Math.PI, false); - ctx.closePath(); - if (this.style.toString().toLowerCase() == "outline") { - ctx.strokeStyle = colorString(this.color); - ctx.stroke(); - } else { - ctx.fillStyle = colorString(this.color); - ctx.fill(); - } - - ctx.restore(); -}; - -CircleImage.prototype.getWidth = function() { - return this.radius * 2; -}; - -CircleImage.prototype.getHeight = function() { - return this.radius * 2; -}; - -CircleImage.prototype.isEqual = function(other, aUnionFind) { - return (other instanceof CircleImage && - this.pinholeX == other.pinholeX && - this.pinholeY == other.pinholeY && - this.radius == other.radius && - this.style == other.style && - types.isEqual(this.color, other.color, aUnionFind)); -}; - - - -////////////////////////////////////////////////////////////////////// - - -// StarImage: fixnum fixnum fixnum color -> image -var StarImage = function(points, outer, inner, style, color) { - BaseImage.call(this, - Math.max(outer, inner), - Math.max(outer, inner)); - this.points = points; - this.outer = outer; - this.inner = inner; - this.style = style; - this.color = color; - - this.radius = Math.max(this.inner, this.outer); -}; - -StarImage.prototype = heir(BaseImage.prototype); - -var oneDegreeAsRadian = Math.PI / 180; - -// render: context fixnum fixnum -> void -// Draws a star on the given context. -// Most of this code here adapted from the Canvas tutorial at: -// http://developer.apple.com/safari/articles/makinggraphicswithcanvas.html -StarImage.prototype.render = function(ctx, x, y) { - ctx.save(); - ctx.beginPath(); - for( var pt = 0; pt < (this.points * 2) + 1; pt++ ) { - var rads = ( ( 360 / (2 * this.points) ) * pt ) * oneDegreeAsRadian - 0.5; - var radius = ( pt % 2 == 1 ) ? this.outer : this.inner; - ctx.lineTo(x + this.radius + ( Math.sin( rads ) * radius ), - y + this.radius + ( Math.cos( rads ) * radius ) ); - } - ctx.closePath(); - if (this.style.toString().toLowerCase() == "outline") { - ctx.strokeStyle = colorString(this.color); - ctx.stroke(); - } else { - ctx.fillStyle = colorString(this.color); - ctx.fill(); - } - - ctx.restore(); -}; - -// getWidth: -> fixnum -StarImage.prototype.getWidth = function() { - return this.radius * 2; -}; - - -// getHeight: -> fixnum -StarImage.prototype.getHeight = function() { - return this.radius * 2; -}; - -StarImage.prototype.isEqual = function(other, aUnionFind) { - return (other instanceof StarImage && - this.pinholeX == other.pinholeX && - this.pinholeY == other.pinholeY && - this.points == other.points && - this.outer == other.outer && - this.inner == other.inner && - this.style == other.style && - types.isEqual(this.color, other.color, aUnionFind)); -}; - - - - -////////////////////////////////////////////////////////////////////// -//Triangle -/////// -var TriangleImage = function(side, style, color) { - this.width = side; - this.height = Math.ceil(side * Math.sqrt(3) / 2); - - BaseImage.call(this, Math.floor(this.width/2), Math.floor(this.height/2)); - this.side = side; - this.style = style; - this.color = color; -} -TriangleImage.prototype = heir(BaseImage.prototype); - - -TriangleImage.prototype.render = function(ctx, x, y) { - var width = this.getWidth(); - var height = this.getHeight(); - ctx.save(); - ctx.beginPath(); - ctx.moveTo(x + this.side/2, y); - ctx.lineTo(x + width, y + height); - ctx.lineTo(x, y + height); - ctx.closePath(); - - if (this.style.toString().toLowerCase() == "outline") { - ctx.strokeStyle = colorString(this.color); - ctx.stroke(); - } - else { - ctx.fillStyle = colorString(this.color); - ctx.fill(); - } - ctx.restore(); -}; - - - -TriangleImage.prototype.getWidth = function() { - return this.width; -}; - -TriangleImage.prototype.getHeight = function() { - return this.height; -}; - -TriangleImage.prototype.isEqual = function(other, aUnionFind) { - return (other instanceof TriangleImage && - this.pinholeX == other.pinholeX && - this.pinholeY == other.pinholeY && - this.side == other.side && - this.style == other.style && - types.isEqual(this.color, other.color, aUnionFind)); -}; - - - -////////////////////////////////////////////////////////////////////// -//Ellipse -var EllipseImage = function(width, height, style, color) { - BaseImage.call(this, Math.floor(width/2), Math.floor(height/2)); - this.width = width; - this.height = height; - this.style = style; - this.color = color; -}; - -EllipseImage.prototype = heir(BaseImage.prototype); - - -EllipseImage.prototype.render = function(ctx, aX, aY) { - ctx.save(); - ctx.beginPath(); - - // Most of this code is taken from: - // http://webreflection.blogspot.com/2009/01/ellipse-and-circle-for-canvas-2d.html - var hB = (this.width / 2) * .5522848, - vB = (this.height / 2) * .5522848, - eX = aX + this.width, - eY = aY + this.height, - mX = aX + this.width / 2, - mY = aY + this.height / 2; - ctx.moveTo(aX, mY); - ctx.bezierCurveTo(aX, mY - vB, mX - hB, aY, mX, aY); - ctx.bezierCurveTo(mX + hB, aY, eX, mY - vB, eX, mY); - ctx.bezierCurveTo(eX, mY + vB, mX + hB, eY, mX, eY); - ctx.bezierCurveTo(mX - hB, eY, aX, mY + vB, aX, mY); - ctx.closePath(); - if (this.style.toString().toLowerCase() == "outline") { - ctx.strokeStyle = colorString(this.color); - ctx.stroke(); - } - else { - ctx.fillStyle = colorString(this.color); - ctx.fill(); - } - - - ctx.restore(); -}; - -EllipseImage.prototype.getWidth = function() { - return this.width; -}; - -EllipseImage.prototype.getHeight = function() { - return this.height; -}; - -EllipseImage.prototype.isEqual = function(other, aUnionFind) { - return (other instanceof EllipseImage && - this.pinholeX == other.pinholeX && - this.pinholeY == other.pinholeY && - this.width == other.width && - this.height == other.height && - this.style == other.style && - types.isEqual(this.color, other.color, aUnionFind)); -}; - - -////////////////////////////////////////////////////////////////////// -//Line -var LineImage = function(x, y, color) { - if (x >= 0) { - if (y >= 0) { - BaseImage.call(this, 0, 0); - } else { - BaseImage.call(this, 0, -y); - } - } else { - if (y >= 0) { - BaseImage.call(this, -x, 0); - } else { - BaseImage.call(this, -x, -y); - } - } - - - this.x = x; - this.y = y; - this.color = color; - this.width = Math.abs(x) + 1; - this.height = Math.abs(y) + 1; -} - -LineImage.prototype = heir(BaseImage.prototype); - - -LineImage.prototype.render = function(ctx, xstart, ystart) { - ctx.save(); - - if (this.x >= 0) { - if (this.y >= 0) { - ctx.moveTo(xstart, ystart); - ctx.lineTo((xstart + this.x), - (ystart + this.y)); - } else { - ctx.moveTo(xstart, ystart + (-this.y)); - ctx.lineTo(xstart + this.x, ystart); - } - } else { - if (this.y >= 0) { - ctx.moveTo(xstart + (-this.x), ystart); - ctx.lineTo(xstart, - (ystart + this.y)); - } else { - ctx.moveTo(xstart + (-this.x), ystart + (-this.y)); - ctx.lineTo(xstart, ystart); - } - } - ctx.strokeStyle = colorString(this.color); - ctx.stroke(); - ctx.restore(); -}; - - -LineImage.prototype.getWidth = function() { - return this.width; -}; - - -LineImage.prototype.getHeight = function() { - return this.height; -}; - -LineImage.prototype.isEqual = function(other, aUnionFind) { - return (other instanceof LineImage && - this.pinholeX == other.pinholeX && - this.pinholeY == other.pinholeY && - this.x == other.x && - this.y == other.y && - types.isEqual(this.color, other.color, aUnionFind)); -}; - - - - - -////////////////////////////////////////////////////////////////////// -// Effects - -/** - * applyEffect: compound-effect -> (arrayof (world -> world)) - - applyEffect applies all of the effects - - @param aCompEffect a compound effect is either a scheme list of - compound effects or a single primitive effect */ -world.Kernel.applyEffect = function(aCompEffect) { - if ( types.isEmpty(aCompEffect) ) { - // Do Nothing - } else if ( types.isPair(aCompEffect) ) { - var results = world.Kernel.applyEffect(aCompEffect.first()); - return results.concat(world.Kernel.applyEffect(aCompEffect.rest())); - } else { - var newResult = aCompEffect.run(); - if (newResult) { - return newResult; - } - } - return []; -} - -////////////////////////////////////////////////////////////////////////// - - - - -// Color database -var ColorDb = function() { - this.colors = {}; -} -ColorDb.prototype.put = function(name, color) { - this.colors[name] = color; -}; - -ColorDb.prototype.get = function(name) { - return this.colors[name.toString().toUpperCase()]; -}; - - -// FIXME: update toString to handle the primitive field values. - -var colorDb = new ColorDb(); -colorDb.put("ORANGE", types.color(255, 165, 0)); -colorDb.put("RED", types.color(255, 0, 0)); -colorDb.put("ORANGERED", types.color(255, 69, 0)); -colorDb.put("TOMATO", types.color(255, 99, 71)); -colorDb.put("DARKRED", types.color(139, 0, 0)); -colorDb.put("RED", types.color(255, 0, 0)); -colorDb.put("FIREBRICK", types.color(178, 34, 34)); -colorDb.put("CRIMSON", types.color(220, 20, 60)); -colorDb.put("DEEPPINK", types.color(255, 20, 147)); -colorDb.put("MAROON", types.color(176, 48, 96)); -colorDb.put("INDIAN RED", types.color(205, 92, 92)); -colorDb.put("INDIANRED", types.color(205, 92, 92)); -colorDb.put("MEDIUM VIOLET RED", types.color(199, 21, 133)); -colorDb.put("MEDIUMVIOLETRED", types.color(199, 21, 133)); -colorDb.put("VIOLET RED", types.color(208, 32, 144)); -colorDb.put("VIOLETRED", types.color(208, 32, 144)); -colorDb.put("LIGHTCORAL", types.color(240, 128, 128)); -colorDb.put("HOTPINK", types.color(255, 105, 180)); -colorDb.put("PALEVIOLETRED", types.color(219, 112, 147)); -colorDb.put("LIGHTPINK", types.color(255, 182, 193)); -colorDb.put("ROSYBROWN", types.color(188, 143, 143)); -colorDb.put("PINK", types.color(255, 192, 203)); -colorDb.put("ORCHID", types.color(218, 112, 214)); -colorDb.put("LAVENDERBLUSH", types.color(255, 240, 245)); -colorDb.put("SNOW", types.color(255, 250, 250)); -colorDb.put("CHOCOLATE", types.color(210, 105, 30)); -colorDb.put("SADDLEBROWN", types.color(139, 69, 19)); -colorDb.put("BROWN", types.color(132, 60, 36)); -colorDb.put("DARKORANGE", types.color(255, 140, 0)); -colorDb.put("CORAL", types.color(255, 127, 80)); -colorDb.put("SIENNA", types.color(160, 82, 45)); -colorDb.put("ORANGE", types.color(255, 165, 0)); -colorDb.put("SALMON", types.color(250, 128, 114)); -colorDb.put("PERU", types.color(205, 133, 63)); -colorDb.put("DARKGOLDENROD", types.color(184, 134, 11)); -colorDb.put("GOLDENROD", types.color(218, 165, 32)); -colorDb.put("SANDYBROWN", types.color(244, 164, 96)); -colorDb.put("LIGHTSALMON", types.color(255, 160, 122)); -colorDb.put("DARKSALMON", types.color(233, 150, 122)); -colorDb.put("GOLD", types.color(255, 215, 0)); -colorDb.put("YELLOW", types.color(255, 255, 0)); -colorDb.put("OLIVE", types.color(128, 128, 0)); -colorDb.put("BURLYWOOD", types.color(222, 184, 135)); -colorDb.put("TAN", types.color(210, 180, 140)); -colorDb.put("NAVAJOWHITE", types.color(255, 222, 173)); -colorDb.put("PEACHPUFF", types.color(255, 218, 185)); -colorDb.put("KHAKI", types.color(240, 230, 140)); -colorDb.put("DARKKHAKI", types.color(189, 183, 107)); -colorDb.put("MOCCASIN", types.color(255, 228, 181)); -colorDb.put("WHEAT", types.color(245, 222, 179)); -colorDb.put("BISQUE", types.color(255, 228, 196)); -colorDb.put("PALEGOLDENROD", types.color(238, 232, 170)); -colorDb.put("BLANCHEDALMOND", types.color(255, 235, 205)); -colorDb.put("MEDIUM GOLDENROD", types.color(234, 234, 173)); -colorDb.put("MEDIUMGOLDENROD", types.color(234, 234, 173)); -colorDb.put("PAPAYAWHIP", types.color(255, 239, 213)); -colorDb.put("MISTYROSE", types.color(255, 228, 225)); -colorDb.put("LEMONCHIFFON", types.color(255, 250, 205)); -colorDb.put("ANTIQUEWHITE", types.color(250, 235, 215)); -colorDb.put("CORNSILK", types.color(255, 248, 220)); -colorDb.put("LIGHTGOLDENRODYELLOW", types.color(250, 250, 210)); -colorDb.put("OLDLACE", types.color(253, 245, 230)); -colorDb.put("LINEN", types.color(250, 240, 230)); -colorDb.put("LIGHTYELLOW", types.color(255, 255, 224)); -colorDb.put("SEASHELL", types.color(255, 245, 238)); -colorDb.put("BEIGE", types.color(245, 245, 220)); -colorDb.put("FLORALWHITE", types.color(255, 250, 240)); -colorDb.put("IVORY", types.color(255, 255, 240)); -colorDb.put("GREEN", types.color(0, 255, 0)); -colorDb.put("LAWNGREEN", types.color(124, 252, 0)); -colorDb.put("CHARTREUSE", types.color(127, 255, 0)); -colorDb.put("GREEN YELLOW", types.color(173, 255, 47)); -colorDb.put("GREENYELLOW", types.color(173, 255, 47)); -colorDb.put("YELLOW GREEN", types.color(154, 205, 50)); -colorDb.put("YELLOWGREEN", types.color(154, 205, 50)); -colorDb.put("MEDIUM FOREST GREEN", types.color(107, 142, 35)); -colorDb.put("OLIVEDRAB", types.color(107, 142, 35)); -colorDb.put("MEDIUMFORESTGREEN", types.color(107, 142, 35)); -colorDb.put("DARK OLIVE GREEN", types.color(85, 107, 47)); -colorDb.put("DARKOLIVEGREEN", types.color(85, 107, 47)); -colorDb.put("DARKSEAGREEN", types.color(143, 188, 139)); -colorDb.put("LIME", types.color(0, 255, 0)); -colorDb.put("DARK GREEN", types.color(0, 100, 0)); -colorDb.put("DARKGREEN", types.color(0, 100, 0)); -colorDb.put("LIME GREEN", types.color(50, 205, 50)); -colorDb.put("LIMEGREEN", types.color(50, 205, 50)); -colorDb.put("FOREST GREEN", types.color(34, 139, 34)); -colorDb.put("FORESTGREEN", types.color(34, 139, 34)); -colorDb.put("SPRING GREEN", types.color(0, 255, 127)); -colorDb.put("SPRINGGREEN", types.color(0, 255, 127)); -colorDb.put("MEDIUM SPRING GREEN", types.color(0, 250, 154)); -colorDb.put("MEDIUMSPRINGGREEN", types.color(0, 250, 154)); -colorDb.put("SEA GREEN", types.color(46, 139, 87)); -colorDb.put("SEAGREEN", types.color(46, 139, 87)); -colorDb.put("MEDIUM SEA GREEN", types.color(60, 179, 113)); -colorDb.put("MEDIUMSEAGREEN", types.color(60, 179, 113)); -colorDb.put("AQUAMARINE", types.color(112, 216, 144)); -colorDb.put("LIGHTGREEN", types.color(144, 238, 144)); -colorDb.put("PALE GREEN", types.color(152, 251, 152)); -colorDb.put("PALEGREEN", types.color(152, 251, 152)); -colorDb.put("MEDIUM AQUAMARINE", types.color(102, 205, 170)); -colorDb.put("MEDIUMAQUAMARINE", types.color(102, 205, 170)); -colorDb.put("TURQUOISE", types.color(64, 224, 208)); -colorDb.put("LIGHTSEAGREEN", types.color(32, 178, 170)); -colorDb.put("MEDIUM TURQUOISE", types.color(72, 209, 204)); -colorDb.put("MEDIUMTURQUOISE", types.color(72, 209, 204)); -colorDb.put("HONEYDEW", types.color(240, 255, 240)); -colorDb.put("MINTCREAM", types.color(245, 255, 250)); -colorDb.put("ROYALBLUE", types.color(65, 105, 225)); -colorDb.put("DODGERBLUE", types.color(30, 144, 255)); -colorDb.put("DEEPSKYBLUE", types.color(0, 191, 255)); -colorDb.put("CORNFLOWERBLUE", types.color(100, 149, 237)); -colorDb.put("STEEL BLUE", types.color(70, 130, 180)); -colorDb.put("STEELBLUE", types.color(70, 130, 180)); -colorDb.put("LIGHTSKYBLUE", types.color(135, 206, 250)); -colorDb.put("DARK TURQUOISE", types.color(0, 206, 209)); -colorDb.put("DARKTURQUOISE", types.color(0, 206, 209)); -colorDb.put("CYAN", types.color(0, 255, 255)); -colorDb.put("AQUA", types.color(0, 255, 255)); -colorDb.put("DARKCYAN", types.color(0, 139, 139)); -colorDb.put("TEAL", types.color(0, 128, 128)); -colorDb.put("SKY BLUE", types.color(135, 206, 235)); -colorDb.put("SKYBLUE", types.color(135, 206, 235)); -colorDb.put("CADET BLUE", types.color(96, 160, 160)); -colorDb.put("CADETBLUE", types.color(95, 158, 160)); -colorDb.put("DARK SLATE GRAY", types.color(47, 79, 79)); -colorDb.put("DARKSLATEGRAY", types.color(47, 79, 79)); -colorDb.put("LIGHTSLATEGRAY", types.color(119, 136, 153)); -colorDb.put("SLATEGRAY", types.color(112, 128, 144)); -colorDb.put("LIGHT STEEL BLUE", types.color(176, 196, 222)); -colorDb.put("LIGHTSTEELBLUE", types.color(176, 196, 222)); -colorDb.put("LIGHT BLUE", types.color(173, 216, 230)); -colorDb.put("LIGHTBLUE", types.color(173, 216, 230)); -colorDb.put("POWDERBLUE", types.color(176, 224, 230)); -colorDb.put("PALETURQUOISE", types.color(175, 238, 238)); -colorDb.put("LIGHTCYAN", types.color(224, 255, 255)); -colorDb.put("ALICEBLUE", types.color(240, 248, 255)); -colorDb.put("AZURE", types.color(240, 255, 255)); -colorDb.put("MEDIUM BLUE", types.color(0, 0, 205)); -colorDb.put("MEDIUMBLUE", types.color(0, 0, 205)); -colorDb.put("DARKBLUE", types.color(0, 0, 139)); -colorDb.put("MIDNIGHT BLUE", types.color(25, 25, 112)); -colorDb.put("MIDNIGHTBLUE", types.color(25, 25, 112)); -colorDb.put("NAVY", types.color(36, 36, 140)); -colorDb.put("BLUE", types.color(0, 0, 255)); -colorDb.put("INDIGO", types.color(75, 0, 130)); -colorDb.put("BLUE VIOLET", types.color(138, 43, 226)); -colorDb.put("BLUEVIOLET", types.color(138, 43, 226)); -colorDb.put("MEDIUM SLATE BLUE", types.color(123, 104, 238)); -colorDb.put("MEDIUMSLATEBLUE", types.color(123, 104, 238)); -colorDb.put("SLATE BLUE", types.color(106, 90, 205)); -colorDb.put("SLATEBLUE", types.color(106, 90, 205)); -colorDb.put("PURPLE", types.color(160, 32, 240)); -colorDb.put("DARK SLATE BLUE", types.color(72, 61, 139)); -colorDb.put("DARKSLATEBLUE", types.color(72, 61, 139)); -colorDb.put("DARKVIOLET", types.color(148, 0, 211)); -colorDb.put("DARK ORCHID", types.color(153, 50, 204)); -colorDb.put("DARKORCHID", types.color(153, 50, 204)); -colorDb.put("MEDIUMPURPLE", types.color(147, 112, 219)); -colorDb.put("CORNFLOWER BLUE", types.color(68, 64, 108)); -colorDb.put("MEDIUM ORCHID", types.color(186, 85, 211)); -colorDb.put("MEDIUMORCHID", types.color(186, 85, 211)); -colorDb.put("MAGENTA", types.color(255, 0, 255)); -colorDb.put("FUCHSIA", types.color(255, 0, 255)); -colorDb.put("DARKMAGENTA", types.color(139, 0, 139)); -colorDb.put("VIOLET", types.color(238, 130, 238)); -colorDb.put("PLUM", types.color(221, 160, 221)); -colorDb.put("LAVENDER", types.color(230, 230, 250)); -colorDb.put("THISTLE", types.color(216, 191, 216)); -colorDb.put("GHOSTWHITE", types.color(248, 248, 255)); -colorDb.put("WHITE", types.color(255, 255, 255)); -colorDb.put("WHITESMOKE", types.color(245, 245, 245)); -colorDb.put("GAINSBORO", types.color(220, 220, 220)); -colorDb.put("LIGHT GRAY", types.color(211, 211, 211)); -colorDb.put("LIGHTGRAY", types.color(211, 211, 211)); -colorDb.put("SILVER", types.color(192, 192, 192)); -colorDb.put("GRAY", types.color(190, 190, 190)); -colorDb.put("DARK GRAY", types.color(169, 169, 169)); -colorDb.put("DARKGRAY", types.color(169, 169, 169)); -colorDb.put("DIM GRAY", types.color(105, 105, 105)); -colorDb.put("DIMGRAY", types.color(105, 105, 105)); -colorDb.put("BLACK", types.color(0, 0, 0)); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/////////////////////////////////////////////////////////////// -// Exports - -world.Kernel.isImage = isImage; -world.Kernel.isScene = isScene; -world.Kernel.isColor = function(thing) { - return (types.isColor(thing) || - ((types.isString(thing) || types.isSymbol(thing)) && - typeof(colorDb.get(thing)) != 'undefined')); -}; -world.Kernel.colorDb = colorDb; - -world.Kernel.sceneImage = function(width, height, children, withBorder) { - return new SceneImage(width, height, children, withBorder); -}; -world.Kernel.circleImage = function(radius, style, color) { - return new CircleImage(radius, style, color); -}; -world.Kernel.starImage = function(points, outer, inner, style, color) { - return new StarImage(points, outer, inner, style, color); -}; -world.Kernel.rectangleImage = function(width, height, style, color) { - return new RectangleImage(width, height, style, color); -}; -world.Kernel.triangleImage = function(side, style, color) { - return new TriangleImage(side, style, color); -}; -world.Kernel.ellipseImage = function(width, height, style, color) { - return new EllipseImage(width, height, style, color); -}; -world.Kernel.lineImage = function(x, y, color) { - return new LineImage(x, y, color); -}; -world.Kernel.overlayImage = function(img1, img2, shiftX, shiftY) { - return new OverlayImage(img1, img2, shiftX, shiftY); -}; -world.Kernel.rotateImage = function(angle, img) { - return new RotateImage(angle, img); -}; -world.Kernel.scaleImage = function(xFactor, yFactor, img) { - return new ScaleImage(xFactor, yFactor, img); -}; -world.Kernel.textImage = function(msg, size, color) { - return new TextImage(msg, size, color); -}; -world.Kernel.fileImage = function(path, rawImage) { - return FileImage.makeInstance(path, rawImage); -}; - - -world.Kernel.isSceneImage = function(x) { return x instanceof SceneImage; }; -world.Kernel.isCircleImage = function(x) { return x instanceof CircleImage; }; -world.Kernel.isStarImage = function(x) { return x instanceof StarImage; }; -world.Kernel.isRectangleImage = function(x) { return x instanceof RectangleImage; }; -world.Kernel.isTriangleImage = function(x) { return x instanceof TriangleImage; }; -world.Kernel.isEllipseImage = function(x) { return x instanceof EllipseImage; }; -world.Kernel.isLineImage = function(x) { return x instanceof LineImage; }; -world.Kernel.isOverlayImage = function(x) { return x instanceof OverlayImage; }; -world.Kernel.isRotateImage = function(x) { return x instanceof RotateImage; }; -world.Kernel.isTextImage = function(x) { return x instanceof TextImage; }; -world.Kernel.isFileImage = function(x) { return x instanceof FileImage; }; - - - - - - - -////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////// - - -// Feeds stimuli inputs into the world. The functions here -// are responsible for converting to Scheme values. -// -// NOTE and WARNING: make sure to really do the coersions, even for -// strings. Bad things happen otherwise, as in the sms stuff, where -// we're getting string-like values that aren't actually strings. - - - -world.stimuli = {}; -world.Kernel.stimuli = world.stimuli; - - -(function() { - var handlers = []; - - var doNothing = function() {}; - - - var StimuliHandler = function(config, caller, restarter) { - this.config = config; - this.caller = caller; - this.restarter = restarter; - handlers.push(this); - }; - - // StimuliHandler.prototype.failHandler = function(e) { - // this.onShutdown(); - // this.restarter(e); - // }; - - // doStimuli: CPS( (world -> effect) (world -> world) -> void ) - // - // Processes a stimuli by compute the effect and applying it, and - // computing a new world to replace the old. - StimuliHandler.prototype.doStimuli = function(computeEffectF, computeWorldF, restArgs, k) { - var effectUpdaters = []; - var that = this; - try { - that.change(function(w, k2) { - var args = [w].concat(restArgs); - var doStimuliHelper = function() { - if (computeWorldF) { - that.caller(computeWorldF, args, k2); - } else { - k2(w); - } - }; - doStimuliHelper(); - }, k); - // if (computeEffectF) { - // that.caller(computeEffectF, [args], - // function(effect) { - // effectUpdaters = applyEffect(effect); - // doStimuliHelper(); - // }, - // this.failHandler); - // } - // else { doStimuliHelper(); } - // }, - // function() { - // helpers.forEachK(effectUpdaters, - // function(effect, k2) { that.change(effect, k2); }, - // function(e) { throw e; }, - // k); - // }); - } catch (e) { - // if (console && console.log && e.stack) { - // console.log(e.stack); - // } - this.onShutdown(); - } - } - - - // Orientation change - // args: [azimuth, pitch, roll] - StimuliHandler.prototype.onTilt = function(args, k) { - var onTilt = this.lookup("onTilt"); - var onTiltEffect = this.lookup("onTiltEffect"); - this.doStimuli(onTiltEffect, onTilt, helpers.map(flt, args), k); - }; - - - // Accelerations - // args: [x, y, z] - StimuliHandler.prototype.onAcceleration = function(args, k) { - var onAcceleration = this.lookup('onAcceleration'); - var onAccelerationEffect = this.lookup('onAccelerationEffect'); - this.doStimuli(onAccelerationEffect, onAcceleration, helpers.map(flt, args), k); - }; - - - // Shakes - // args: [] - StimuliHandler.prototype.onShake = function(args, k) { - var onShake = this.lookup('onShake'); - var onShakeEffect = this.lookup('onShakeEffect'); - this.doStimuli(onShakeEffect, onShake, [], k); - }; - - - // Sms receiving - // args: [sender, message] - StimuliHandler.prototype.onSmsReceive = function(args, k) { - var onSmsReceive = this.lookup('onSmsReceive'); - var onSmsReceiveEffect = this.lookup('onSmsReceiveEffect'); - // IMPORTANT: must coerse to string by using x+"". Do not use - // toString(): it's not safe. - this.doStimuli(onSmsReceiveEffect, onSmsReceive, [args[0]+"", args[1]+""], k); - }; - - - // Locations - // args: [lat, lng] - StimuliHandler.prototype.onLocation = function(args, k) { - var onLocationChange = this.lookup('onLocationChange'); - var onLocationChangeEffect = this.lookup('onLocationChangeEffect'); - this.doStimuli(onLocationChangeEffect, onLocationChange, helpers.map(flt, args), k); - }; - - - - // Keystrokes - // args: [e] - StimuliHandler.prototype.onKey = function(args, k) { - // getKeyCodeName: keyEvent -> String - // Given an event, try to get the name of the key. - var getKeyCodeName = function(e) { - var code = e.charCode || e.keyCode; - var keyname; - switch(code) { - case 16: keyname = "shift"; break; - case 17: keyname = "control"; break; - case 19: keyname = "pause"; break; - case 27: keyname = "escape"; break; - case 33: keyname = "prior"; break; - case 34: keyname = "next"; break; - case 35: keyname = "end"; break; - case 36: keyname = "home"; break; - case 37: keyname = "left"; break; - case 38: keyname = "up"; break; - case 39: keyname = "right"; break; - case 40: keyname = "down"; break; - case 42: keyname = "print"; break; - case 45: keyname = "insert"; break; - case 46: keyname = String.fromCharCode(127); break; - case 106: keyname = "*"; break; - case 107: keyname = "+"; break; - case 109: keyname = "-"; break; - case 110: keyname = "."; break; - case 111: keyname = "/"; break; - case 144: keyname = "numlock"; break; - case 145: keyname = "scroll"; break; - case 186: keyname = ";"; break; - case 187: keyname = "="; break; - case 188: keyname = ","; break; - case 189: keyname = "-"; break; - case 190: keyname = "."; break; - case 191: keyname = "/"; break; - case 192: keyname = "`"; break; - case 219: keyname = "["; break; - case 220: keyname = "\\"; break; - case 221: keyname = "]"; break; - case 222: keyname = "'"; break; - default: if (code >= 96 && code <= 105) { - keyname = (code - 96).toString(); - } - else if (code >= 112 && code <= 123) { - keyname = "f" + (code - 111); - } - else { - keyname = String.fromCharCode(code).toLowerCase(); - } - break; - } - return keyname; - } - var keyname = getKeyCodeName(args[0]); - var onKey = this.lookup('onKey'); - var onKeyEffect = this.lookup('onKeyEffect'); - this.doStimuli(onKeyEffect, onKey, [keyname], k); - }; - - - - // // Time ticks - // // args: [] - // StimuliHandler.prototype.onTick = function(args, k) { - // var onTick = this.lookup('onTick'); - // var onTickEffect = this.lookup('onTickEffect'); - // this.doStimuli(onTickEffect, onTick, [], k); - // }; - - - - // Announcements - // args: [eventName, vals] - StimuliHandler.prototype.onAnnounce = function(args, k) { - var vals = args[1]; - var valsList = types.EMPTY; - for (var i = 0; i < vals.length; i++) { - valsList = types.cons(vals[vals.length - i - 1], valsList); - } - - var onAnnounce = this.lookup('onAnnounce'); - var onAnnounceEffect = this.lookup('onAnnounceEffect'); - this.doStimuli(onAnnounce, onAnnounceEffect, [args[0], valsList], k); - }; - - - - // The shutdown stimuli: special case that forces a world computation to quit. - // Also removes this instance from the list of handlers - StimuliHandler.prototype.onShutdown = function() { - var index = handlers.indexOf(this); - if (index != -1) { - handlers.splice(index, 1); - } - - var shutdownWorld = this.lookup('shutdownWorld'); - if (shutdownWorld) { - shutdownWorld(); - } - }; - - - ////////////////////////////////////////////////////////////////////// - // Helpers - var flt = types.float; - - StimuliHandler.prototype.lookup = function(s) { - return this.config.lookup(s); - }; - - StimuliHandler.prototype.change = function(f, k) { - if (this.lookup('changeWorld')) { - this.lookup('changeWorld')(f, k); - } - else { k(); } - }; - - // applyEffect: compound-effect: (arrayof (world -> world)) - var applyEffect = function(e) { - return world.Kernel.applyEffect(e); - }; - - var makeStimulusHandler = function(funName) { - return function() { - var args = arguments; - for (var i = 0; i < handlers.length; i++) { - (handlers[i])[funName](args, doNothing); - } - // helpers.forEachK(handlers, - // function(h, k) { h[funName](args, k); }, - // function(e) { throw e; }, - // doNothing); - } - }; - - ////////////////////////////////////////////////////////////////////// - // Exports - - world.stimuli.StimuliHandler = StimuliHandler; - - world.stimuli.onTilt = makeStimulusHandler('onTilt'); - world.stimuli.onAcceleration = makeStimulusHandler('onAcceleration'); - world.stimuli.onShake = makeStimulusHandler('onShake'); - world.stimuli.onSmsReceive = makeStimulusHandler('onSmsReceive'); - world.stimuli.onLocation = makeStimulusHandler('onLocation'); - world.stimuli.onKey = makeStimulusHandler('onKey'); - // world.stimuli.onTick = makeStimulusHandler('onTick'); - world.stimuli.onAnnounce = makeStimulusHandler('onAnnounce'); - - world.stimuli.massShutdown = function() { - for (var i = 0; i < handlers.length; i++) { - var shutdownWorld = handlers[i].lookup('shutdownWorld'); - if (shutdownWorld) { - shutdownWorld(); - } - } - handlers = []; - }; - - -})(); - -////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////// - - - - - - - -(function() { - -// var make_dash_effect_colon_none = -// (plt.Kernel.invokeModule("moby/runtime/effect-struct") -// .EXPORTS['make-effect:none']); - - world.config = {}; - world.Kernel.config = world.config; - - - // augment: hash hash -> hash - // Functionally extend a hashtable with another one. - var augment = function(o, a) { - var oo = {}; - for (var e in o) { - if (o.hasOwnProperty(e)) { - oo[e] = o[e]; - } - } - for (var e in a) { - if (a.hasOwnProperty(e)) { - oo[e] = a[e]; - } - } - return oo; - } - - - - var WorldConfig = function() { - // The following handler values are initially false until they're updated - // by configuration. - - // A handler is a function: - // handler: world X Y ... -> Z - - - this.vals = { - // changeWorld: (world -> world) -> void - // When called, this will update the world based on the - // updater passed to it. - changeWorld: false, - - // shutdownWorld: -> void - // When called, this will shut down the world computation. - shutdownWorld: false, - - // initialEffect: effect - // The initial effect to invoke when the world computation - // begins. - initialEffect: false, - - - // onRedraw: world -> scene - onRedraw: false, - - // onDraw: world -> (sexpof dom) - onDraw: false, - - // onDrawCss: world -> (sexpof css-style) - onDrawCss: false, - - - // tickDelay: number - tickDelay: false, - // onTick: world -> world - onTick: false, - // onTickEffect: world -> effect - onTickEffect: false, - - // onKey: world key -> world - onKey: false, - // onKeyEffect: world key -> effect - onKeyEffect : false, - - // onTilt: world number number number -> world - onTilt: false, - // onTiltEffect: world number number number -> effect - onTiltEffect: false, - - // onAcceleration: world number number number -> world - onAcceleration: false, - // onAccelerationEffect: world number number number -> effect - onAccelerationEffect: false, - - // onShake: world -> world - onShake: false, - // onShakeEffect: world -> effect - onShakeEffect: false, - - // onSmsReceive: world -> world - onSmsReceive: false, - // onSmsReceiveEffect: world -> effect - onSmsReceiveEffect: false, - - // onLocationChange: world number number -> world - onLocationChange : false, - // onLocationChangeEffect: world number number -> effect - onLocationChangeEffect: false, - - - // onAnnounce: world string X ... -> world - onAnnounce: false, - // onAnnounce: world string X ... -> effect - onAnnounceEffect: false, - - // stopWhen: world -> boolean - stopWhen: false, - // stopWhenEffect: world -> effect - stopWhenEffect: false, - - - - ////////////////////////////////////////////////////////////////////// - // For universe game playing - - // connectToGame: string - // Registers with some universe, given an identifier - // which is a URL to a Universe server. - connectToGame: false, - onGameStart: false, - onOpponentTurn: false, - onMyTurn: false, - afterMyTurn: false, - onGameFinish: false - }; - } - - - // WorldConfig.lookup: string -> handler - // Looks up a value in the configuration. - WorldConfig.prototype.lookup = function(key) { -// plt.Kernel.check(key, plt.Kernel.isString, "WorldConfig.lookup", "string", 1); - if (key in this.vals) { - return this.vals[key]; - } else { - throw Error("Can't find " + key + " in the configuration"); - } - } - - - - // WorldConfig.updateAll: (hashof string handler) -> WorldConfig - WorldConfig.prototype.updateAll = function(aHash) { - var result = new WorldConfig(); - result.vals = augment(this.vals, aHash); - return result; - } - - - world.config.WorldConfig = WorldConfig; - - // The following global variable CONFIG is mutated by either - // big-bang from the regular world or the one in jsworld. - world.config.CONFIG = new WorldConfig(); - - - // A handler is a function that consumes a config and produces a - // config. - - - ////////////////////////////////////////////////////////////////////// - - var getNoneEffect = function() { - throw new Error("getNoneEffect: We should not be calling effects!"); - // return make_dash_effect_colon_none(); - } - - - - ////////////////////////////////////////////////////////////////////// - - world.config.Kernel = world.config.Kernel || {}; - world.config.Kernel.getNoneEffect = getNoneEffect; - - -/* - // makeSimplePropertyUpdater: (string (X -> boolean) string string) -> (X -> handler) - var makeSimplePropertyUpdater = function(propertyName, - propertyPredicate, - propertyTypeName, - updaterName) { - return function(val) { - plt.Kernel.check(val, propertyPredicate, updaterName, propertyTypeName, 1); - return addStringMethods( - function(config) { - return config.updateAll({propertyName: val }); - }, updaterName); - } - }; - - // connects to the game - world.config.Kernel.connect_dash_to_dash_game = - makeSimplePropertyUpdater('connectToGame', - plt.Kernel.isString, - "string", - "connect-to-game"); - - - // Registers a handler for game-start events. - world.config.Kernel.on_dash_game_dash_start = - makeSimplePropertyUpdater('onGameStart', - plt.Kernel.isFunction, - "function", - "on-game-start"); - - - // Registers a handler for opponent-turn events. - world.config.Kernel.on_dash_opponent_dash_turn = - makeSimplePropertyUpdater('onOpponentTurn', - plt.Kernel.isFunction, - "function", - "on-opponent-turn"); - - - // Registers a handler for my turn. - world.config.Kernel.on_dash_my_dash_turn = - makeSimplePropertyUpdater('onMyTurn', - plt.Kernel.isFunction, - "function", - "on-my-turn"); - - // Register a handler after I make a move. - world.config.Kernel.after_dash_my_dash_turn = - makeSimplePropertyUpdater('afterMyTurn', - plt.Kernel.isFunction, - "function", - "after-my-turn"); - - world.config.Kernel.on_dash_game_dash_finish = - makeSimplePropertyUpdater('onGameFinish', - plt.Kernel.isFunction, - "function", - "on-game-finish"); -*/ - - - -})(); diff --git a/world/scratch/world/kernel.rkt b/world/scratch/world/kernel.rkt deleted file mode 100644 index f315428..0000000 --- a/world/scratch/world/kernel.rkt +++ /dev/null @@ -1,3 +0,0 @@ -#lang s-exp "../lang/js-impl/js-impl.rkt" - -(require-js "kernel.js") From b20d3d5ad94346bfb582b9e27559f56a479ef022 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Sat, 17 Sep 2011 22:12:43 -0400 Subject: [PATCH 15/22] continuing to jslint --- world/raw-jsworld.js | 301 +++++++++++++++++++++++-------------------- 1 file changed, 163 insertions(+), 138 deletions(-) diff --git a/world/raw-jsworld.js b/world/raw-jsworld.js index 3c6ffc7..2d5657c 100644 --- a/world/raw-jsworld.js +++ b/world/raw-jsworld.js @@ -259,26 +259,29 @@ var rawJsworld = {}; function augment(o, a) { - var oo = {}; - for (var e in o) { + var oo = {}, e; + for (e in o) { if (o.hasOwnProperty(e)) { oo[e] = o[e]; } } - for (var e in a) { + for (e in a) { if (a.hasOwnProperty(e)) { oo[e] = a[e]; } } return oo; - }; + } Jsworld.augment = augment; function assoc_cons(o, k, v) { - var oo = {}; - for (var e in o) - oo[e] = o[e]; + var oo = {}, e; + for (e in o) { + if (o.hasOwnProperty(e)) { + oo[e] = o[e]; + } + } oo[k] = v; return oo; } @@ -297,36 +300,30 @@ var rawJsworld = {}; Jsworld.append = append; function array_join(array1, array2){ - var joined = []; - for (var i = 0; i < array1.length; i++) + var joined = [], i; + for (i = 0; i < array1.length; i++) { joined.push([array1[i], array2[i]]); + } return joined; } Jsworld.array_join = array_join; function removeq(a, value) { - for (var i = 0; i < a.length; i++) + var i; + for (i = 0; i < a.length; i++) { if (a[i] === value){ return a.slice(0, i).concat(a.slice(i+1)); - } + } + } return a; } Jsworld.removeq = removeq; - function removef(a, value) { - for (var i = 0; i < a.length; i++) - if ( f(a[i]) ){ - return a.slice(0, i).concat(a.slice(i+1)); - } - return a; - } - Jsworld.removef = removef; - function filter(a, f) { - var b = []; - for (var i = 0; i < a.length; i++) { + var b = [], i; + for (i = 0; i < a.length; i++) { if ( f(a[i]) ) { b.push(a[i]); } @@ -337,26 +334,38 @@ var rawJsworld = {}; function without(obj, attrib) { - var o = {}; - for (var a in obj) - if (a != attrib) - o[a] = obj[a]; + var o = {}, a; + for (a in obj) { + if (obj.hasOwnProperty(a)) { + if (a !== attrib) { + o[a] = obj[a]; + } + } + } return o; } Jsworld.without = without; function memberq(a, x) { - for (var i = 0; i < a.length; i++) - if (a[i] === x) return true; + var i; + for (i = 0; i < a.length; i++) { + if (a[i] === x) { + return true; + } + } return false; } Jsworld.memberq = memberq; function member(a, x) { - for (var i = 0; i < a.length; i++) - if (a[i] == x) return true; + var i; + for (i = 0; i < a.length; i++) { + if (a[i] === x) { + return true; + } + } return false; } Jsworld.member = member; @@ -436,8 +445,8 @@ var rawJsworld = {}; // node_to_tree: dom -> dom-tree // Given a native dom node, produces the appropriate tree. function node_to_tree(domNode) { - var result = [domNode]; - for (var c = domNode.firstChild; c != null; c = c.nextSibling) { + var result = [domNode], c; + for (c = domNode.firstChild; c !== null; c = c.nextSibling) { result.push(node_to_tree(c)); } return result; @@ -448,40 +457,41 @@ var rawJsworld = {}; // nodes(tree(N)) = nodes(N) function nodes(tree) { - var ret; - - if (tree.node.jsworldOpaque == true) { + var ret, i; + if (tree.node.jsworldOpaque === true) { return [tree.node]; } ret = [tree.node]; - for (var i = 0; i < tree.children.length; i++) + for (i = 0; i < tree.children.length; i++) { ret = ret.concat(nodes(tree.children[i])); - + } return ret; } // relations(tree(N)) = relations(N) function relations(tree) { - var ret = []; - - for (var i = 0; i < tree.children.length; i++) - ret.push({ relation: 'parent', - parent: tree.node, + var ret = []; + var i; + for (i = 0; i < tree.children.length; i++) { + ret.push({ relation: 'parent', + parent: tree.node, child: tree.children[i].node }); - - for (var i = 0; i < tree.children.length - 1; i++) - ret.push({ relation: 'neighbor', + } + + for (i = 0; i < tree.children.length - 1; i++) { + ret.push({ relation: 'neighbor', left: tree.children[i].node, right: tree.children[i + 1].node }); - + } + if (! tree.node.jsworldOpaque) { - for (var i = 0; i < tree.children.length; i++) { + for (i = 0; i < tree.children.length; i++) { ret = ret.concat(relations(tree.children[i])); } } - + return ret; } @@ -491,7 +501,7 @@ var rawJsworld = {}; while (n.firstChild) { n.removeChild(n.firstChild); } - } + }; // Preorder traversal. @@ -500,7 +510,7 @@ var rawJsworld = {}; var child = node.firstChild; var nextSibling; while (child) { - var nextSibling = child.nextSibling; + nextSibling = child.nextSibling; preorder(child, f); child = nextSibling; } @@ -508,32 +518,66 @@ var rawJsworld = {}; }; + // nodeEq: node node -> boolean + // Returns true if the two nodes should be the same. + var nodeEq = function(node1, node2) { + return (node1 && node2 && node1 === node2); + }; + + + // isMemq: X (arrayof X) -> boolean + // Produces true if any of the elements of L are nodeEq to x. + var isMemq = function(x, L) { + var i; + for (i = 0 ; i < L.length; i++) { + if (nodeEq(x, L[i])) { + return true; + } + } + return false; + }; + + + + // If any node cares about the world, send it in. + function refresh_node_values(nodes) { + var i; + for (i = 0; i < nodes.length; i++) { + if (nodes[i].onWorldChange) { + nodes[i].onWorldChange(world); + } + } + } + + + // update_dom(nodes(Node), relations(Node)) = void function update_dom(toplevelNode, nodes, relations) { - + var i, parent, child; // TODO: rewrite this to move stuff all in one go... possible? necessary? - + // move all children to their proper parents - for (var i = 0; i < relations.length; i++) { - if (relations[i].relation == 'parent') { - var parent = relations[i].parent, child = relations[i].child; + for (i = 0; i < relations.length; i++) { + if (relations[i].relation === 'parent') { + parent = relations[i].parent; + child = relations[i].child; if (child.parentNode !== parent) { parent.appendChild(child); } } } - + // arrange siblings in proper order // truly terrible... BUBBLE SORT var unsorted = true; while (unsorted) { unsorted = false; - for (var i = 0; i < relations.length; i++) { - if (relations[i].relation == 'neighbor') { + for (i = 0; i < relations.length; i++) { + if (relations[i].relation === 'neighbor') { var left = relations[i].left, right = relations[i].right; - + if (! nodeEq(left.nextSibling, right)) { - left.parentNode.insertBefore(left, right) + left.parentNode.insertBefore(left, right); unsorted = true; } } @@ -558,37 +602,18 @@ var rawJsworld = {}; refresh_node_values(nodes); } - - - // isMemq: X (arrayof X) -> boolean - // Produces true if any of the elements of L are nodeEq to x. - var isMemq = function(x, L) { - var i; - for (i = 0 ; i < L.length; i++) { - if (nodeEq(x, L[i])) { - return true; - } - } - return false; - }; - - - // nodeEq: node node -> boolean - // Returns true if the two nodes should be the same. - var nodeEq = function(node1, node2) { - return (node1 && node2 && node1 === node2); - } // camelCase: string -> string function camelCase(name) { - return name.replace(/\-(.)/g, function(m, l){return l.toUpperCase()}); + return name.replace(/\-(.)/g, function(m, l){return l.toUpperCase();}); } function set_css_attribs(node, attribs) { - for (var j = 0; j < attribs.length; j++){ + var j; + for (j = 0; j < attribs.length; j++){ node.style[camelCase(attribs[j].attrib)] = attribs[j].values.join(" "); } } @@ -599,53 +624,53 @@ var rawJsworld = {}; function isMatchingCssSelector(node, css) { if (css.id.match(/^\./)) { // Check to see if we match the class - return ('className' in node && member(node['className'].split(/\s+/), - css.id.substring(1))); + return (node.className && member(node.className.split(/\s+/), + css.id.substring(1))); } else { - return ('id' in node && node.id == css.id); + return (node.id && node.id === css.id); } } - function update_css(nodes, css) { - // clear CSS - for (var i = 0; i < nodes.length; i++) { - if ( !nodes[i].jsworldOpaque ) { - clearCss(nodes[i]); - } - } - - // set CSS - for (var i = 0; i < css.length; i++) - if ('id' in css[i]) { - for (var j = 0; j < nodes.length; j++) - if (isMatchingCssSelector(nodes[j], css[i])) { - set_css_attribs(nodes[j], css[i].attribs); - } - } - else set_css_attribs(css[i].node, css[i].attribs); - } - - var clearCss = function(node) { // FIXME: we should not be clearing the css // if ('style' in node) // node.style.cssText = ""; - } + }; - // If any node cares about the world, send it in. - function refresh_node_values(nodes) { - for (var i = 0; i < nodes.length; i++) { - if (nodes[i].onWorldChange) { - nodes[i].onWorldChange(world); + function update_css(nodes, css) { + // clear CSS + var i, j; + for (i = 0; i < nodes.length; i++) { + if ( !nodes[i].jsworldOpaque ) { + clearCss(nodes[i]); + } + } + + // set CSS + for (i = 0; i < css.length; i++) { + if (css[i].id) { + for (j = 0; j < nodes.length; j++) { + if (isMatchingCssSelector(nodes[j], css[i])) { + set_css_attribs(nodes[j], css[i].attribs); + } + } + } else { + set_css_attribs(css[i].node, css[i].attribs); } } } + var sexp2tree; + var sexp2css; + var maintainingSelection; + + + function do_redraw(world, oldWorld, toplevelNode, redraw_func, redraw_css_func, k) { if (oldWorld instanceof InitialWorld) { // Simple path @@ -700,7 +725,6 @@ var rawJsworld = {}; function(newRedrawCss) { var t = sexp2tree(newRedraw); var ns = nodes(t); - // Try to save the current selection and preserve it across // dom updates. @@ -712,21 +736,28 @@ var rawJsworld = {}; update_dom(toplevelNode, ns, relations(t)); k2(); - }) - }) - - - - - + }); + }); }, k); } } + + var FocusedSelection; + + function hasCurrentFocusedSelection() { + return currentFocusedNode !== undefined; + } + + function getCurrentFocusedSelection() { + return new FocusedSelection(); + } + + // maintainingSelection: (-> void) -> void // Calls the thunk f while trying to maintain the current focused selection. - function maintainingSelection(f, k) { + maintainingSelection = function(f, k) { var currentFocusedSelection; if (hasCurrentFocusedSelection()) { currentFocusedSelection = getCurrentFocusedSelection(); @@ -737,15 +768,15 @@ var rawJsworld = {}; } else { f(function() { k(); }); } - } + }; - function FocusedSelection() { + FocusedSelection = function() { this.focused = currentFocusedNode; this.selectionStart = currentFocusedNode.selectionStart; this.selectionEnd = currentFocusedNode.selectionEnd; - } + }; // Try to restore the focus. FocusedSelection.prototype.restore = function() { @@ -765,19 +796,15 @@ var rawJsworld = {}; } }; - function hasCurrentFocusedSelection() { - return currentFocusedNode != undefined; - } - function getCurrentFocusedSelection() { - return new FocusedSelection(); - } ////////////////////////////////////////////////////////////////////// - function BigBangRecord(top, world, handlerCreators, handlers, attribs) { + var bigBang; + + function BigBangRecord(top, world, handlerCreators, handlers, attribs) { this.top = top; this.world = world; this.handlers = handlers; @@ -808,7 +835,7 @@ var rawJsworld = {}; // init_world: any // handlerCreators: (Arrayof (-> handler)) // k: any -> void - function bigBang(top, init_world, handlerCreators, attribs, succ) { + bigBang = function(top, init_world, handlerCreators, attribs, succ) { // clear_running_state(); // Construct a fresh set of the handlers. @@ -867,9 +894,7 @@ var rawJsworld = {}; // Finally, begin the big-bang. copy_attribs(top, attribs); change_world(function(w, k2) { k2(init_world); }, doNothing); - - - } + }; Jsworld.bigBang = bigBang; @@ -1137,10 +1162,10 @@ var rawJsworld = {}; // - function sexp2tree(sexp) { + sexp2tree = function(sexp) { if(sexp.length == undefined) return { node: sexp, children: [] }; else return { node: sexp[0], children: map(sexp.slice(1), sexp2tree) }; - } + }; function sexp2attrib(sexp) { return { attrib: sexp[0], values: sexp.slice(1) }; @@ -1157,9 +1182,9 @@ var rawJsworld = {}; } } - function sexp2css(sexp) { + sexp2css = function(sexp) { return concat_map(sexp, sexp2css_node); - } + }; From 45204fcb3fed2c177c362ab1421ed9cd7c7d6643 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Sat, 17 Sep 2011 22:28:19 -0400 Subject: [PATCH 16/22] continuing to jslint --- world/raw-jsworld.js | 181 +++++++++++++++++++++++-------------------- 1 file changed, 95 insertions(+), 86 deletions(-) diff --git a/world/raw-jsworld.js b/world/raw-jsworld.js index 2d5657c..6b2840d 100644 --- a/world/raw-jsworld.js +++ b/world/raw-jsworld.js @@ -1,3 +1,4 @@ +/*global $,plt*/ var rawJsworld = {}; // Stuff here is copy-and-pasted from Chris King's JSWorld. @@ -802,7 +803,7 @@ var rawJsworld = {}; ////////////////////////////////////////////////////////////////////// - var bigBang; + var bigBang, StopWhenHandler; function BigBangRecord(top, world, handlerCreators, handlers, attribs) { this.top = top; @@ -814,20 +815,21 @@ var rawJsworld = {}; BigBangRecord.prototype.restart = function() { bigBang(this.top, this.world, this.handlerCreators, this.attribs); - } - + }; + BigBangRecord.prototype.pause = function() { - for(var i = 0 ; i < this.handlers.length; i++) { - if (this.handlers[i] instanceof StopWhenHandler) { - // Do nothing for now. - } else { - this.handlers[i].onUnregister(top); + var i; + for(i = 0 ; i < this.handlers.length; i++) { + if (! (this.handlers[i] instanceof StopWhenHandler)) { + this.handlers[i].onUnregister(this.top); } } }; ////////////////////////////////////////////////////////////////////// + var copy_attribs; + // Notes: bigBang maintains a stack of activation records; it should be possible // to call bigBang re-entrantly. @@ -836,16 +838,17 @@ var rawJsworld = {}; // handlerCreators: (Arrayof (-> handler)) // k: any -> void bigBang = function(top, init_world, handlerCreators, attribs, succ) { + var i; // clear_running_state(); // Construct a fresh set of the handlers. var handlers = map(handlerCreators, function(x) { return x();} ); - if (runningBigBangs.length > 0) { + if (runningBigBangs.length > 0) { runningBigBangs[runningBigBangs.length - 1].pause(); } // Create an activation record for this big-bang. - var activationRecord = + var activationRecord = new BigBangRecord(top, init_world, handlerCreators, handlers, attribs); runningBigBangs.push(activationRecord); function keepRecordUpToDate(w, oldW, k2) { @@ -859,7 +862,7 @@ var rawJsworld = {}; // Monitor for termination and register the other handlers. var stopWhen = new StopWhenHandler(function(w, k2) { k2(false); }, function(w, k2) { k2(w); }); - for(var i = 0 ; i < handlers.length; i++) { + for(i = 0 ; i < handlers.length; i++) { if (handlers[i] instanceof StopWhenHandler) { stopWhen = handlers[i]; } else { @@ -905,41 +908,41 @@ var rawJsworld = {}; var on_tick = function(delay, tick) { return function() { var scheduleTick, ticker; - - - (new Date()).valueOf() - scheduleTick = function(t) { ticker.watchId = setTimeout( - function() { + function() { ticker.watchId = undefined; var startTime = (new Date()).valueOf(); - change_world(tick, - function() { + change_world(tick, + function() { var endTime = (new Date()).valueOf(); scheduleTick(Math.max(delay - (endTime - startTime), - 0)); - }); + 0)); + }); }, t); }; - + ticker = { watchId: -1, - onRegister: function (top) { + onRegister: function (top) { scheduleTick(delay); }, onUnregister: function (top) { - if (ticker.watchId) + if (ticker.watchId) { clearTimeout(ticker.watchId); + } } }; return ticker; }; - } + }; Jsworld.on_tick = on_tick; + var preventDefault, stopPropagation; + var attachEvent, detachEvent; + function on_key(press) { return function() { @@ -949,17 +952,17 @@ var rawJsworld = {}; change_world(function(w, k) { press(w, e, k); }, doNothing); }; return { - onRegister: function(top) { + onRegister: function(top) { //http://www.w3.org/TR/html5/editing.html#sequential-focus-navigation-and-the-tabindex-attribue $(top).attr('tabindex', 1); $(top).focus(); - attachEvent(top, 'keydown', wrappedPress); + attachEvent(top, 'keydown', wrappedPress); }, - onUnregister: function(top) { - detachEvent(top, 'keydown', wrappedPress); + onUnregister: function(top) { + detachEvent(top, 'keydown', wrappedPress); } }; - } + }; } Jsworld.on_key = on_key; @@ -980,9 +983,10 @@ var rawJsworld = {}; do { x -= currentElement.offsetLeft; y -= currentElement.offsetTop; - } while(currentElement = currentElement.offsetParent); + currentElement = currentElement.offsetParent; + } while(currentElement); - if (type === 'button-down') { + if (type === 'button-down') { isButtonDown = true; } else if (type === 'button-up') { isButtonDown = false; @@ -1005,22 +1009,22 @@ var rawJsworld = {}; var wrappedEnter = makeWrapped('enter'); var wrappedLeave = makeWrapped('leave'); return { - onRegister: function(top) { - attachEvent(top, 'mousedown', wrappedDown); - attachEvent(top, 'mouseup', wrappedUp); - attachEvent(top, 'mousemove', wrappedMove); - attachEvent(top, 'mouseenter', wrappedEnter); - attachEvent(top, 'mouseleave', wrappedLeave); + onRegister: function(top) { + attachEvent(top, 'mousedown', wrappedDown); + attachEvent(top, 'mouseup', wrappedUp); + attachEvent(top, 'mousemove', wrappedMove); + attachEvent(top, 'mouseenter', wrappedEnter); + attachEvent(top, 'mouseleave', wrappedLeave); }, - onUnregister: function(top) { - detachEvent(top, 'mousedown', wrappedDown); - detachEvent(top, 'mouseup', wrappedUp); - detachEvent(top, 'mousemove', wrappedMove); - detachEvent(top, 'mouseenter', wrappedEnter); - detachEvent(top, 'mouseleave', wrappedLeave); + onUnregister: function(top) { + detachEvent(top, 'mousedown', wrappedDown); + detachEvent(top, 'mouseup', wrappedUp); + detachEvent(top, 'mousemove', wrappedMove); + detachEvent(top, 'mouseenter', wrappedEnter); + detachEvent(top, 'mouseleave', wrappedLeave); } }; - } + }; } Jsworld.on_mouse = on_mouse; @@ -1028,8 +1032,9 @@ var rawJsworld = {}; + var checkDomSexp; + - // on_draw: CPS(world -> (sexpof node)) CPS(world -> (sexpof css-style)) -> handler function on_draw(redraw, redraw_css) { var wrappedRedraw = function(w, k) { @@ -1037,15 +1042,15 @@ var rawJsworld = {}; checkDomSexp(newDomTree, newDomTree); k(newDomTree); }); - } + }; return function() { var drawer = { _top: null, - _listener: function(w, oldW, k2) { - do_redraw(w, oldW, drawer._top, wrappedRedraw, redraw_css, k2); + _listener: function(w, oldW, k2) { + do_redraw(w, oldW, drawer._top, wrappedRedraw, redraw_css, k2); }, - onRegister: function (top) { + onRegister: function (top) { drawer._top = top; add_world_listener(drawer._listener); }, @@ -1061,14 +1066,14 @@ var rawJsworld = {}; - function StopWhenHandler(test, receiver) { + StopWhenHandler = function(test, receiver) { this.test = test; this.receiver = receiver; - } + }; // stop_when: CPS(world -> boolean) CPS(world -> boolean) -> handler function stop_when(test, receiver) { return function() { - if (receiver == undefined) { + if (receiver === undefined) { receiver = function(w, k) { k(w); }; } return new StopWhenHandler(test, receiver); @@ -1081,11 +1086,11 @@ var rawJsworld = {}; function on_world_change(f) { var listener = function(world, oldW, k) { f(world, k); }; return function() { - return { - onRegister: function (top) { + return { + onRegister: function (top) { add_world_listener(listener); }, onUnregister: function (top) { - remove_world_listener(listener)} + remove_world_listener(listener); } }; }; } @@ -1096,7 +1101,7 @@ var rawJsworld = {}; // Compatibility for attaching events to nodes. - function attachEvent(node, eventName, fn) { + attachEvent = function(node, eventName, fn) { if (node.addEventListener) { // Mozilla node.addEventListener(eventName, fn, false); @@ -1104,9 +1109,9 @@ var rawJsworld = {}; // IE node.attachEvent('on' + eventName, fn, false); } - } + }; - var detachEvent = function(node, eventName, fn) { + detachEvent = function(node, eventName, fn) { if (node.addEventListener) { // Mozilla node.removeEventListener(eventName, fn, false); @@ -1114,7 +1119,7 @@ var rawJsworld = {}; // IE node.detachEvent('on' + eventName, fn, false); } - } + }; // // DOM CREATION STUFFS @@ -1163,8 +1168,8 @@ var rawJsworld = {}; sexp2tree = function(sexp) { - if(sexp.length == undefined) return { node: sexp, children: [] }; - else return { node: sexp[0], children: map(sexp.slice(1), sexp2tree) }; + if(sexp.length === undefined) { return { node: sexp, children: [] }; } + else { return { node: sexp[0], children: map(sexp.slice(1), sexp2tree) }; } }; function sexp2attrib(sexp) { @@ -1173,10 +1178,10 @@ var rawJsworld = {}; function sexp2css_node(sexp) { var attribs = map(sexp.slice(1), sexp2attrib); - if (typeof sexp[0] == 'string'){ + if (typeof sexp[0] === 'string'){ return [{ id: sexp[0], attribs: attribs }]; - } else if ('length' in sexp[0]){ - return map(sexp[0], function (id) { return { id: id, attribs: attribs } }); + } else if (sexp[0].length !== undefined){ + return map(sexp[0], function (id) { return { id: id, attribs: attribs }; }); } else { return [{ node: sexp[0], attribs: attribs }]; } @@ -1189,14 +1194,15 @@ var rawJsworld = {}; function isTextNode(n) { - return (n.nodeType == Node.TEXT_NODE); - }; + return (n.nodeType === 3); + } function isElementNode(n) { - return (n.nodeType == Node.ELEMENT_NODE); - }; + return (n.nodeType === 1); + } + var JsworldDomError; var throwDomError = function(thing, topThing) { throw new JsworldDomError( @@ -1209,11 +1215,12 @@ var rawJsworld = {}; // checkDomSexp: X X -> boolean // Checks to see if thing is a DOM-sexp. If not, // throws an object that explains why not. - function checkDomSexp(thing, topThing) { + checkDomSexp = function(thing, topThing) { + var i; if (! thing instanceof Array) { throwDomError(thing, topThing); } - if (thing.length == 0) { + if (thing.length === 0) { throwDomError(thing, topThing); } @@ -1226,11 +1233,11 @@ var rawJsworld = {}; thing); } } else if (isElementNode(thing[0])) { - for (var i = 1; i < thing.length; i++) { + for (i = 1; i < thing.length; i++) { checkDomSexp(thing[i], thing); } } else { - console.log(thing[0]); + if (window.console && window.console.log) { window.console.log(thing[0]); } throw new JsworldDomError( plt.baselib.format.format( @@ -1238,15 +1245,15 @@ var rawJsworld = {}; [thing, topThing]), thing[0]); } - } + }; - function JsworldDomError(msg, elt) { + JsworldDomError = function(msg, elt) { this.msg = msg; this.elt = elt; - } + }; JsworldDomError.prototype.toString = function() { return "JsworldDomError: " + this.msg; - } + }; @@ -1257,19 +1264,21 @@ var rawJsworld = {}; // - function copy_attribs(node, attribs) { - if (attribs) + copy_attribs = function(node, attribs) { + var a; + if (attribs) { for (a in attribs) { if (attribs.hasOwnProperty(a)) { - if (typeof attribs[a] == 'function') + if (typeof attribs[a] === 'function') { add_ev(node, a, attribs[a]); - else{ - node[a] = attribs[a];//eval("node."+a+"='"+attribs[a]+"'"); + } else { + node[a] = attribs[a]; } } } + } return node; - } + }; // @@ -1299,21 +1308,21 @@ var rawJsworld = {}; - var preventDefault = function(event) { + preventDefault = function(event) { if (event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; } - } + }; - var stopPropagation = function(event) { + stopPropagation = function(event) { if (event.stopPropagation) { event.stopPropagation(); } else { event.cancelBubble = true; } - } + }; var stopClickPropagation = function(node) { From ae415aa09b6ae8bf3d5ad97beb41be2398e66da9 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Sat, 17 Sep 2011 22:31:56 -0400 Subject: [PATCH 17/22] jslinting complete --- world/raw-jsworld.js | 46 +++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/world/raw-jsworld.js b/world/raw-jsworld.js index 6b2840d..a1d6448 100644 --- a/world/raw-jsworld.js +++ b/world/raw-jsworld.js @@ -498,11 +498,6 @@ var rawJsworld = {}; - var removeAllChildren = function(n) { - while (n.firstChild) { - n.removeChild(n.firstChild); - } - }; // Preorder traversal. @@ -1331,8 +1326,10 @@ var rawJsworld = {}; stopPropagation(e); }); return node; - } - + }; + + + var text_input, checkbox_input; // input: string CPS(world -> world) function input(aType, updateF, attribs) { @@ -1356,7 +1353,7 @@ var rawJsworld = {}; - var text_input = function(type, updateF, attribs) { + text_input = function(type, updateF, attribs) { var n = document.createElement('input'); n.type = type; @@ -1365,7 +1362,7 @@ var rawJsworld = {}; if (! n.parentNode) { return; } setTimeout( function() { - if (lastVal != n.value) { + if (lastVal !== n.value) { lastVal = n.value; change_world(function (w, k) { updateF(w, n.value, k); @@ -1373,7 +1370,7 @@ var rawJsworld = {}; } }, 0); - } + }; attachEvent(n, "keydown", onEvent); eventDetachers.push(function() { @@ -1388,7 +1385,7 @@ var rawJsworld = {}; }; - var checkbox_input = function(type, updateF, attribs) { + checkbox_input = function(type, updateF, attribs) { var n = document.createElement('input'); n.type = type; var onCheck = function(w, e, k) { @@ -1396,7 +1393,7 @@ var rawJsworld = {}; }; // This established the widget->world direction add_ev_after(n, 'change', onCheck); - + attachEvent(n, 'click', function(e) { stopPropagation(e); }); @@ -1405,15 +1402,14 @@ var rawJsworld = {}; }; - var button_input = function(type, updateF, attribs) { - var n = document.createElement('button'); - add_ev(n, 'click', function(w, e, k) { updateF(w, n.value, k); }); - return addFocusTracking(copy_attribs(n, attribs)); - }; + // var button_input = function(type, updateF, attribs) { + // var n = document.createElement('button'); + // add_ev(n, 'click', function(w, e, k) { updateF(w, n.value, k); }); + // return addFocusTracking(copy_attribs(n, attribs)); + // }; - function text(s, attribs) { var result = document.createElement("div"); @@ -1423,9 +1419,11 @@ var rawJsworld = {}; } Jsworld.text = text; + var option; + function select(attribs, opts, f){ - var n = document.createElement('select'); - for(var i = 0; i < opts.length; i++) { + var n = document.createElement('select'), i; + for(i = 0; i < opts.length; i++) { n.add(option({value: opts[i]}), null); } n.jsworldOpaque = true; @@ -1435,12 +1433,12 @@ var rawJsworld = {}; } Jsworld.select = select; - function option(attribs){ + option = function(attribs){ var node = document.createElement("option"); node.text = attribs.value; node.value = attribs.value; return node; - } + }; @@ -1455,7 +1453,7 @@ var rawJsworld = {}; Jsworld.h1 = h1; function canvas(attribs){ - return addFocusTracking(copy_attribs(document.createElement('canvas'), attribs)); + return addFocusTracking(copy_attribs(document.createElement('canvas'), attribs)); } Jsworld.canvas = canvas; @@ -1517,4 +1515,4 @@ var rawJsworld = {}; }; -})(); +}()); From 2ae1b70c173239b16ecb84f145f83148c492ccf9 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Sat, 17 Sep 2011 22:40:02 -0400 Subject: [PATCH 18/22] removing dead files --- js-assembler/runtime-src/helpers.js | 513 -- js-assembler/runtime-src/js-vm-primitives.js | 4701 ------------------ js-assembler/runtime-src/types.js | 573 --- 3 files changed, 5787 deletions(-) delete mode 100644 js-assembler/runtime-src/helpers.js delete mode 100644 js-assembler/runtime-src/js-vm-primitives.js delete mode 100644 js-assembler/runtime-src/types.js diff --git a/js-assembler/runtime-src/helpers.js b/js-assembler/runtime-src/helpers.js deleted file mode 100644 index 43064f6..0000000 --- a/js-assembler/runtime-src/helpers.js +++ /dev/null @@ -1,513 +0,0 @@ -// Helper functions for whalesong. -// -// Note: this originally came from js-vm, and may have cruft that -// doesn't belong in whalesong. I need to clean this up. - - - -if (! this['plt']) { this['plt'] = {}; } - -// Helpers library: includes a bunch of helper functions that will be used -// -// -// FIXME: there's a circularity between this module and types, and that circularly -// should not be there! - - -////////////////////////////////////////////////////////////// - -// File of helper functions for primitives and world. - - -(function(scope) { - var helpers = {}; - scope.helpers = helpers; - - - // types refers to plt.types, and will be initialized later. - var types = scope['types']; - scope.link.ready('types', - function() { - types = scope['types']; - }); - - - - - - - // forEachK: CPS( array CPS(array -> void) (error -> void) -> void ) - // Iterates through an array and applies f to each element using CPS - // If an error is thrown, it catches the error and calls f_error on it - var forEachK = function(a, f, f_error, k) { - var forEachHelp = function(i) { - if( i >= a.length ) { - if (k) { - return k(); - } else { - return; - } - } - - try { - return f(a[i], function() { return forEachHelp(i+1); }); - } catch (e) { - f_error(e); - } - }; - return forEachHelp(0); - }; - - - // reportError: (or exception string) -> void - // Reports an error to the user, either at the console - // if the console exists, or as alerts otherwise. - var reportError = function(e) { - var reporter; - if (typeof(console) != 'undefined' && - typeof(console.log) != 'undefined') { - reporter = (function(x) { console.log(x); }); - } else { - reporter = (function(x) { alert(x); }); - } - if (typeof e == 'string') { - reporter(e); - } else if ( types.isSchemeError(e) ) { - if ( types.isExn(e.val) ) { - reporter( types.exnMessage(e.val) ); - } - else { - reporter(e.val); - } - } else if ( types.isInternalError(e) ) { - reporter(e.val); - } else if (e.message) { - reporter(e.message); - } else { - reporter(e.toString()); - } - // if (plt.Kernel.lastLoc) { - // var loc = plt.Kernel.lastLoc; - // if (typeof(loc) === 'string') { - // reporter("Error was raised around " + loc); - // } else if (typeof(loc) !== 'undefined' && - // typeof(loc.line) !== 'undefined') { - // reporter("Error was raised around: " - // + plt.Kernel.locToString(loc)); - // } - // } - }; - - - var raise = function(v) { - throw types.schemeError(v); - }; - - - -// var throwCheckError = function(details, pos, args) { -// var errorFormatStr; -// if (args && args.length > 1) { -// var errorFormatStrBuffer = ['~a: expects type <~a> as ~a arguments, given: ~s; other arguments were:']; -// for (var i = 0; i < args.length; i++) { -// if ( i != pos-1 ) { -// errorFormatStrBuffer.push(toWrittenString(args[i])); -// } -// } -// errorFormatStr = errorFormatStrBuffer.join(' '); -// } -// else { -// errorFormatStr = "~a: expects argument of type <~a>, given: ~s"; -// details.splice(2, 1); -// } - -// raise( types.incompleteExn(types.exnFailContract, -// helpers.format(errorFormatStr, details), -// []) ); -// }; - - - -// var check = function(x, f, functionName, typeName, position, args) { -// if ( !f(x) ) { -// throwCheckError([functionName, -// typeName, -// helpers.ordinalize(position), -// x], -// position, -// args); -// } -// }; - - var isList = function(x) { - var seenPairs = plt.baselib.hash.makeLowLevelEqHash(); - while (true) { - if (seenPairs.containsKey(x)) { - return true; - } else if (x === types.EMPTY) { - return true; - } else if (types.isPair(x)) { - seenPairs.put(x, true); - x = x.rest(); - } else { - return false; - } - } - }; - - var isListOf = function(x, f) { - var seenPairs = plt.baselib.hash.makeLowLevelEqHash(); - while (true) { - if (seenPairs.containsKey(x)) { - return true; - } else if (x === types.EMPTY) { - return true; - } else if (types.isPair(x)) { - seenPairs.put(x, true); - if (f(x.first())) { - x = x.rest(); - } else { - return false; - } - } else { - return false; - } - } - }; - -// var checkListOf = function(lst, f, functionName, typeName, position, args) { -// if ( !isListOf(lst, f) ) { -// helpers.throwCheckError([functionName, -// 'list of ' + typeName, -// helpers.ordinalize(position), -// lst], -// position, -// args); -// } -// }; - - - // // remove: array any -> array - // // removes the first instance of v in a - // // or returns a copy of a if v does not exist - // var remove = function(a, v) { - // for (var i = 0; i < a.length; i++) { - // if (a[i] === v) { - // return a.slice(0, i).concat( a.slice(i+1, a.length) ); - // } - // } - // return a.slice(0); - // }; - - // map: array (any -> any) -> array - // applies f to each element of a and returns the result - // as a new array - var map = function(f, a) { - var b = new Array(a.length); - for (var i = 0; i < a.length; i++) { - b[i] = f(a[i]); - } - return b; - }; - - - var concatMap = function(f, a) { - var b = []; - for (var i = 0; i < a.length; i++) { - b = b.concat( f(a[i]) ); - } - return b; - }; - - - var schemeListToArray = function(lst) { - var result = []; - while ( !lst.isEmpty() ) { - result.push(lst.first()); - lst = lst.rest(); - } - return result; - } - - // deepListToArray: any -> any - // Converts list structure to array structure. - var deepListToArray = function(x) { - var thing = x; - if (thing === types.EMPTY) { - return []; - } else if (types.isPair(thing)) { - var result = []; - while (!thing.isEmpty()) { - result.push(deepListToArray(thing.first())); - thing = thing.rest(); - } - return result; - } else { - return x; - } - } - - - var flattenSchemeListToArray = function(x) { - if ( !isList(x) ) { - return [x]; - } - - var ret = []; - while ( !x.isEmpty() ) { - ret = ret.concat( flattenSchemeListToArray(x.first()) ); - x = x.rest(); - } - return ret; - }; - - - - var ordinalize = function(n) { - // special case for 11th: - if ( n % 100 == 11 ) { - return n + 'th'; - } - var res = n; - switch( n % 10 ) { - case 1: res += 'st'; break; - case 2: res += 'nd'; break; - case 3: res += 'rd'; break; - default: res += 'th'; break; - } - return res; - } - - -// var wrapJsValue = function(x) { -// if (x === undefined) { -// return types.jsValue('undefined', x); -// } -// else if (x === null) { -// return types.jsValue('null', x); -// } -// else if (typeof(x) == 'function') { -// return types.jsValue('function', x); -// } -// else if ( x instanceof Array ) { -// return types.jsValue('array', x); -// } -// else if ( typeof(x) == 'string' ) { -// return types.jsValue("'" + x.toString() + "'", x); -// } -// else { -// return types.jsValue(x.toString(), x); -// } -// }; - - - var getKeyCodeName = function(e) { - var code = e.charCode || e.keyCode; - var keyname; - switch(code) { - case 16: keyname = "shift"; break; - case 17: keyname = "control"; break; - case 19: keyname = "pause"; break; - case 27: keyname = "escape"; break; - case 33: keyname = "prior"; break; - case 34: keyname = "next"; break; - case 35: keyname = "end"; break; - case 36: keyname = "home"; break; - case 37: keyname = "left"; break; - case 38: keyname = "up"; break; - case 39: keyname = "right"; break; - case 40: keyname = "down"; break; - case 42: keyname = "print"; break; - case 45: keyname = "insert"; break; - case 46: keyname = String.fromCharCode(127); break; - case 106: keyname = "*"; break; - case 107: keyname = "+"; break; - case 109: keyname = "-"; break; - case 110: keyname = "."; break; - case 111: keyname = "/"; break; - case 144: keyname = "numlock"; break; - case 145: keyname = "scroll"; break; - case 186: keyname = ";"; break; - case 187: keyname = "="; break; - case 188: keyname = ","; break; - case 189: keyname = "-"; break; - case 190: keyname = "."; break; - case 191: keyname = "/"; break; - case 192: keyname = "`"; break; - case 219: keyname = "["; break; - case 220: keyname = "\\"; break; - case 221: keyname = "]"; break; - case 222: keyname = "'"; break; - default: if (code >= 96 && code <= 105) { - keyname = (code - 96).toString(); - } - else if (code >= 112 && code <= 123) { - keyname = "f" + (code - 111); - } - else { - keyname = String.fromCharCode(code).toLowerCase(); - } - break; - } - return keyname; - }; - - - - - - // maybeCallAfterAttach: dom-node -> void - // walk the tree rooted at aNode, and call afterAttach if the element has - // such a method. - var maybeCallAfterAttach = function(aNode) { - var stack = [aNode]; - while (stack.length !== 0) { - var nextNode = stack.pop(); - if (nextNode.afterAttach) { - nextNode.afterAttach(nextNode); - } - if (nextNode.hasChildNodes && nextNode.hasChildNodes()) { - var children = nextNode.childNodes; - for (var i = 0; i < children.length; i++) { - stack.push(children[i]); - } - } - } - }; - - - - - - - - - // makeLocationDom: location -> dom - // Dom type that has special support in the editor through the print hook. - // The print hook is expected to look at the printing of dom values with - // this particular structure. In the context of WeScheme, the environment - // will rewrite these to be clickable links. - var makeLocationDom = function(aLocation) { - var locationSpan = document.createElement("span"); - var idSpan = document.createElement("span"); - var offsetSpan = document.createElement("span"); - var lineSpan = document.createElement("span"); - var columnSpan = document.createElement("span"); - var spanSpan = document.createElement("span"); - - locationSpan['className'] = 'location-reference'; - idSpan['className'] = 'location-id'; - offsetSpan['className'] = 'location-offset'; - lineSpan['className'] = 'location-line'; - columnSpan['className'] = 'location-column'; - spanSpan['className'] = 'location-span'; - - idSpan.appendChild(document.createTextNode(String(aLocation.id))); - offsetSpan.appendChild(document.createTextNode(String(aLocation.offset))); - lineSpan.appendChild(document.createTextNode(String(aLocation.line))); - columnSpan.appendChild(document.createTextNode(String(aLocation.column))); - spanSpan.appendChild(document.createTextNode(String(aLocation.span))); - - locationSpan.appendChild(idSpan); - locationSpan.appendChild(offsetSpan); - locationSpan.appendChild(lineSpan); - locationSpan.appendChild(columnSpan); - locationSpan.appendChild(spanSpan); - - return locationSpan; - }; - - - var isLocationDom = function(thing) { - return (thing - && - (thing.nodeType === Node.TEXT_NODE || - thing.nodeType === Node.ELEMENT_NODE) - && - thing['className'] === 'location-reference'); - }; - - - - - - - - - - // Inheritance. - var heir = function(parentPrototype) { - var f = function() {} - f.prototype = parentPrototype; - return new f(); - }; - - - - - - - - - - // clone: object -> object - // Copies an object. The new object should respond like the old - // object, including to things like instanceof - var clone = function(obj) { - var C = function() {} - C.prototype = obj; - var c = new C(); - for (property in obj) { - if (obj.hasOwnProperty(property)) { - c[property] = obj[property]; - } - } - return c; - }; - - - - - - - //////////////////////////////////////////////// - - helpers.forEachK = forEachK; - helpers.reportError = reportError; - helpers.raise = raise; - -// helpers.throwCheckError = throwCheckError; - helpers.isList = isList; - helpers.isListOf = isListOf; -// helpers.check = check; -// helpers.checkListOf = checkListOf; - - // helpers.remove = remove; - helpers.map = map; - helpers.concatMap = concatMap; - helpers.schemeListToArray = schemeListToArray; - helpers.deepListToArray = deepListToArray; - helpers.flattenSchemeListToArray = flattenSchemeListToArray; - - helpers.ordinalize = ordinalize; -// helpers.wrapJsValue = wrapJsValue; - - helpers.getKeyCodeName = getKeyCodeName; - - helpers.maybeCallAfterAttach = maybeCallAfterAttach; - - helpers.makeLocationDom = makeLocationDom; - helpers.isLocationDom = isLocationDom; - - - helpers.heir = heir; - - - - helpers.clone = clone; - - - scope.link.announceReady('helpers'); -})(this['plt']); - -///////////////////////////////////////////////////////////////// diff --git a/js-assembler/runtime-src/js-vm-primitives.js b/js-assembler/runtime-src/js-vm-primitives.js deleted file mode 100644 index 0315de2..0000000 --- a/js-assembler/runtime-src/js-vm-primitives.js +++ /dev/null @@ -1,4701 +0,0 @@ -if (! this['plt']) { this['plt'] = {}; } - - -/** - -Note: all primitives in this file should be written so that it's easy -to syntactically pull out all of the implemented primitives. Make -sure that any new primitive is written as: - - PRIMITIVES[name-of-primitive] = ... - -That way, we can do a simple grep. - -*/ - - -(function(scope) { - var primitives = {}; - scope.primitives = primitives; - var PRIMITIVES = {}; - - - var types = scope.types; - var helpers = scope.helpers; - - var CALL, PAUSE, PrimProc, CasePrimitive, makeOptionPrimitive, procArityContains; - var assocListToHash, raise; - var isList, isListOf; - var check; - var checkListOf; - - CALL = types.internalCall; - PAUSE = types.internalPause; - PrimProc = types.PrimProc; - CasePrimitive = types.CasePrimitive; - makeOptionPrimitive = types.makeOptionPrimitive; - - procArityContains = helpers.procArityContains; - assocListToHash = helpers.assocListToHash; - raise = helpers.raise; - isList = helpers.isList; - isListOf = helpers.isListOf; - check = helpers.check; - checkListOf = helpers.checkListOf; - - scope.link.ready('types', - function() { - types = scope.types; - CALL = types.internalCall; - PAUSE = types.internalPause; - PrimProc = types.PrimProc; - CasePrimitive = types.CasePrimitive; - makeOptionPrimitive = types.makeOptionPrimitive; - }); - scope.link.ready('helpers', - function() { - helpers = scope.helpers; - procArityContains = helpers.procArityContains; - assocListToHash = helpers.assocListToHash; - raise = helpers.raise; - isList = helpers.isList; - isListOf = helpers.isListOf; - check = helpers.check; - checkListOf = helpers.checkListOf; - }); - - - - - - ////////////////////////////////////////////////////////////////////// - - // Helper Functions - - var id = function(x) { return x; }; - - var sub1 = function(x) { - check(x, isNumber, 'sub1', 'number', 1, [x]); - return jsnums.subtract(x, 1); - } - - var add1 = function(x) { - check(x, isNumber, 'add1', 'number', 1, [x]); - return jsnums.add(x, 1); - } - - var callWithValues = function(f, vals) { - if (vals instanceof types.ValuesWrapper) { - return CALL(f, vals.elts, id); - } - else { - return CALL(f, [vals], id); - } - }; - - - // onSingleResult: x (x -> y) -> y - // Applies f on x, but first checks that x is a single value. - // If it isn't, raises an arity error. - var onSingleResult = function(x, f) { - if (x instanceof types.ValuesWrapper) { - if (x.elts.length === 1) { - return f(x.elts[0]); - } else { - var argsStr = helpers.map(function(x) { return "~s"; }, x.elts).join(' '); - raise(types.incompleteExn( - types.exnFailContractArity, - helpers.format( - 'context expected 1 value, received ~s values: ' + argsStr, - [x.elts.length].concat(x.elts)))); - } - } else { - return f(x); - } - }; - - - var procedureArity = function(proc) { - check(proc, isFunction, 'procedure-arity', 'procedure', 1, [proc]); - - var singleCaseArity = function(aCase) { - if (aCase instanceof types.ContinuationClosureValue) { - return types.arityAtLeast(0); - } - else if (aCase.isRest) { - return types.arityAtLeast(aCase.numParams); - } - else { - return aCase.numParams; - } - } - - if ( proc instanceof PrimProc || - proc instanceof types.ClosureValue || - proc instanceof types.ContinuationClosureValue ) { - return singleCaseArity(proc); - } - else { - var cases; - if ( proc instanceof CasePrimitive ) { - cases = proc.cases; - } - else if ( proc instanceof types.CaseLambdaValue ) { - cases = proc.closures; - } - else { - throw types.internalError('procedure-arity given wrong type that passed isFunction!', false); - } - - var ret = []; - for (var i = 0; i < cases.length; i++) { - ret.push( singleCaseArity(cases[i]) ); - } - ret = normalizeArity(ret); - return ret.length == 1 ? ret[0] : types.list(ret); - } - }; - - var normalizeArity = function(arity) { - var newArity = arity.slice(0); - var sortFunc = function(x, y) { - if ( types.isArityAtLeast(x) ) { - if ( types.isArityAtLeast(y) ) { - return types.arityAtLeastValue(x) - types.arityAtLeastValue(y); - } - else { - return types.arityAtLeastValue(x) - y - 0.5; - } - } - else { - if ( types.isArityAtLeast(y) ) { - return x - types.arityAtLeastValue(y) + 0.5; - } - else { - return x - y; - } - } - }; - newArity.sort(sortFunc); - - for (var i = 0; i < newArity.length-1; i++) { - if ( types.isArityAtLeast(newArity[i]) ) { - return newArity.slice(0, i+1); - } - } - return newArity; - }; - - - - - - - - var length = function(lst) { - checkList(lst, 'length', 1, [lst]); - var ret = 0; - for (; !lst.isEmpty(); lst = lst.rest) { - ret = ret+1; - } - return ret; - } - - var append = function(initArgs) { - if (initArgs.length == 0) { - return types.EMPTY; - } - var args = initArgs.slice(0, initArgs.length-1); - var lastArg = initArgs[initArgs.length - 1]; - arrayEach(args, function(x, i) {checkList(x, 'append', i+1, initArgs);}); - - var ret = lastArg; - for (var i = args.length-1; i >= 0; i--) { - ret = args[i].append(ret); - } - return ret; - } - - var foldHelp = function(f, acc, args) { - if ( args[0].isEmpty() ) { - return acc; - } - - var fArgs = []; - var argsRest = []; - for (var i = 0; i < args.length; i++) { - fArgs.push(args[i].first); - argsRest.push(args[i].rest); - } - fArgs.push(acc); - return CALL(f, fArgs, - function(result) { - return foldHelp(f, result, argsRest); - }); - } - - var quicksort = function(functionName) { - return function(initList, comp) { - checkList(initList, functionName, 1, arguments); - check(comp, procArityContains(2), functionName, 'procedure (arity 2)', 2, arguments); - - var quicksortHelp = function(k) { - return function(lst) { - if ( lst.isEmpty() ) { - return k(types.EMPTY); - } - - var compYes = new PrimProc('compYes', 1, false, false, - function(x) { return CALL(comp, [x, lst.first], id); }); - var compNo = new PrimProc('compNo', 1, false, false, - function(x) { return CALL(comp, [x, lst.first], - function(res) { return !res; }); - }); - - return CALL(PRIMITIVES['filter'], - [compYes, lst.rest], - quicksortHelp(function(sorted1) { - return CALL(PRIMITIVES['filter'], - [compNo, lst.rest], - quicksortHelp(function(sorted2) { - return k( append([sorted1, - types.list([lst.first]), - sorted2]) ); - })); - })); - }; - } - return quicksortHelp(id)(initList); - }; - } - - var compare = function(args, comp) { - var curArg = args[0]; - for (var i = 1; i < args.length; i++) { - if ( !comp(curArg, args[i]) ) { - return false; - } - curArg = args[i]; - } - return true; - } - - // isAlphabeticString: string -> boolean - var isAlphabeticString = function(s) { - for(var i = 0; i < s.length; i++) { - if (! ((s.charAt(i) >= "a" && s.charAt(i) <= "z") || - (s.charAt(i) >= "A" && s.charAt(i) <= "Z"))) { - return false; - } - } - return true; - }; - - - var isMutableString = function(s) { - return isString(s) && typeof s != 'string'; - }; - - - var isNumericString = function(s) { - for (var i = 0; i < s.length; i++) { - if ( ! (s.charAt(i) >= '0' && s.charAt(i) <= '9') ) { - return false; - } - } - return true; - } - - // isWhitespaceString: string -> boolean - var isWhitespaceString = (function() { - var pat = new RegExp("^\\s*$"); - return function(s) { - return (s.match(pat) ? true : false); - } - }()); - - - - - var isImmutable = function(x) { - return ((isString(x) || - isByteString(x) || - isVector(x) || - isHash(x) || - isBox(x)) && - !x.mutable); - }; - - - - - - - // On any numeric error, throw a contract error. - jsnums.onThrowRuntimeError = function(msg, x, y) { - raise(types.incompleteExn( - types.exnFailContract, - helpers.format("~a: ~s ~s", [msg, x, y]), - [])); - }; - - - - - var checkAndGetGuard = function(funName, guard, numberOfGuardArgs) { - if ( !guard ) { - return false; - } - - // Check the number of arguments on the guard - if ( !procArityContains(numberOfGuardArgs)(guard) ) { - raise(types.incompleteExn( - types.exnFailContract, - helpers.format( - '~a: guard procedure does not accept ~a arguments ' - + '(one more than the number constructor arguments): ~s', - [funName, numberOfGuardArgs, guard]), - [])); - } - - // if the guard has the right number of arguments, - // then construct a javascript function to call it - return function(args, name, k) { - args = args.concat([name]); - return CALL(guard, args, - function(res) { - if ( res instanceof types.ValuesWrapper ) { - return k(res.elts); - } - else { - return k([res]); - } - }); - }; - }; - - - - - - var getMakeStructTypeReturns = function(aStructType) { - var name = aStructType.name; - return new types.ValuesWrapper( - [aStructType, - (new types.StructConstructorProc(aStructType, - 'make-'+name, - aStructType.numberOfArgs, - false, - false, - aStructType.constructor)), - (new types.StructPredicateProc(aStructType, name+'?', 1, false, false, aStructType.predicate)), - (new types.StructAccessorProc(aStructType, - name+'-ref', - 2, - false, - false, - function(x, i) { - check(x, aStructType.predicate, name+'-ref', 'struct:'+name, 1, arguments); - check(i, isNatural, name+'-ref', 'non-negative exact integer', 2, arguments); - - var numFields = aStructType.numberOfFields; - if ( jsnums.greaterThanOrEqual(i, numFields) ) { - var msg = (name+'-ref: slot index for not in ' + - '[0, ' + (numFields-1) + ']: ' + i); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - return aStructType.accessor(x, jsnums.toFixnum(i)); - })), - (new types.StructMutatorProc(aStructType, - name+'-set!', - 3, - false, - false, - function(x, i, v) { - check(x, aStructType.predicate, name+'-set!', 'struct:'+name, 1, arguments); - check(i, isNatural, name+'-set!', 'non-negative exact integer', 2, arguments); - - var numFields = aStructType.numberOfFields; - if ( jsnums.greaterThanOrEqual(i, numFields) ) { - var msg = (name+'-set!: slot index for not in ' + - '[0, ' + (numFields-1) + ']: ' + i); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - aStructType.mutator(x, jsnums.toFixnum(i), v) - })) ]); - }; - - - - - ////////////////////////////////////////////////////////////////////// - - - var isNumber = jsnums.isSchemeNumber; - var isReal = jsnums.isReal; - var isRational = jsnums.isRational; - var isComplex = isNumber; - var isInteger = jsnums.isInteger; - - var isNatural = function(x) { - return jsnums.isExact(x) && isInteger(x) && jsnums.greaterThanOrEqual(x, 0); - }; - - var isNonNegativeReal = function(x) { - return isReal(x) && jsnums.greaterThanOrEqual(x, 0); - }; - - var isSymbol = types.isSymbol; - var isChar = types.isChar; - var isString = types.isString; - var isPair = types.isPair; - var isEmpty = function(x) { return x === types.EMPTY; }; - var isVector = types.isVector; - var isBox = types.isBox; - var isHash = types.isHash; - var isByteString = types.isByteString; - - var isByte = function(x) { - return (isNatural(x) && - jsnums.lessThanOrEqual(x, 255)); - } - - var isBoolean = function(x) { - return (x === true || x === false); - } - - var isFunction = types.isFunction; - - var isEqual = function(x, y) { - return types.isEqual(x, y, new types.UnionFind()); - } - - var isEq = function(x, y) { - return x === y; - } - - var isEqv = function(x, y) { - if (isNumber(x) && isNumber(y)) { - return jsnums.eqv(x, y); - } - else if (isChar(x) && isChar(y)) { - return x.val === y.val; - } - return x === y; - } - - - - var isAssocList = function(x) { - return isPair(x) && isPair(x.rest) && isEmpty(x.rest.rest); - }; - - - var isCompoundEffect = function(x) { - return ( types.isEffect(x) || isListOf(x, isCompoundEffect) ); - }; - - var isJsValue = types.isJsValue; - - var isJsObject = function(x) { - return isJsValue(x) && typeof(x.val) == 'object'; - }; - - var isJsFunction = function(x) { - return isJsValue(x) && typeof(x.val) == 'function'; - }; - - - - var arrayEach = function(arr, f) { - for (var i = 0; i < arr.length; i++) { - f.call(null, arr[i], i); - } - } - - - var checkList = function(x, functionName, position, args) { - if ( !isList(x) ) { - helpers.throwCheckError([functionName, - 'list', - helpers.ordinalize(position), - x], - position, - args); - } - } - - var checkListOfLength = function(lst, n, functionName, position, args) { - if ( !isList(lst) || (length(lst) < n) ) { - helpers.throwCheckError([functionName, - 'list with ' + n + ' or more elements', - helpers.ordinalize(position), - lst], - position, - args); - } - } - - var checkAllSameLength = function(lists, functionName, args) { - if (lists.length == 0) - return; - - var len = length(lists[0]); - arrayEach(lists, - function(lst, i) { - if (length(lst) != len) { - var argsStr = helpers.map(function(x) { return " ~s"; }, args).join(''); - var msg = helpers.format(functionName + ': all lists must have the same size; arguments were:' + argsStr, - args); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - }); - } - - - ////////////////////////////////////////////////////////////////////// - - - // Special moby-specific primitives - - PRIMITIVES['verify-boolean-branch-value'] = - new PrimProc('verify-boolean-branch-value', - 2, - false, - false, - function(x, aLoc) { - if (x !== true && x !== false) { - // FIXME: should throw structure - // make-moby-error-type:branch-value-not-boolean - // instead. - throw new Error("the value " + sys.inspect(x) + " is not boolean type at " + aLoc); - } - return x; - }) - - PRIMITIVES['throw-cond-exhausted-error'] = - new PrimProc('throw-cond-exhausted-error', - 1, - false, - false, - function(aLoc) { - // FIXME: should throw structure - // make-moby-error-type:conditional-exhausted - // instead. - throw types.schemeError(types.incompleteExn(types.exnFail, "cond: all question results were false", [])); - }); - - - PRIMITIVES['print-values'] = - new PrimProc('print-values', - 0, - true, - true, - function(state, values) { - var printed = false; - for (var i = 0; i < values.length; i++) { - if (values[i] !== types.VOID) { - if (printed) { - state.getDisplayHook()("\n"); - } - state.getPrintHook()(values[i]); - printed = true; - } - } - if (printed) { - state.getDisplayHook()("\n"); - } - state.v = types.VOID; - }); - - - - - - ////////////////////////////////////////////////////////////////////// - - var defaultPrint = - new PrimProc('print', - 1, - false, - true, - function(state, x) { - state.getPrintHook()(helpers.toDisplayedString(x)); - state.v = types.VOID; - }); - - - PRIMITIVES['write'] = - new CasePrimitive('write', - [new PrimProc('write', 1, false, true, function(aState, x) { - aState.getPrintHook()(x); - aState.v = types.VOID; - }), - new PrimProc('write', 2, false, true, function(aState, x, port) { - throw types.internalError('write to a port not implemented yet.', false); - }) ]); - - - - PRIMITIVES['display'] = - new CasePrimitive('display', - [new PrimProc('display', 1, false, true, function(state, x) { - state.getDisplayHook()(x); - state.v = types.VOID; - }), - new PrimProc('display', 2, false, true, function(state, x, port) { - // FIXME - throw types.internalError("display to a port not implemented yet.", false); - } )]); - - - - PRIMITIVES['newline'] = - new CasePrimitive('newline', - [new PrimProc('newline', 0, false, true, function(state) { - state.getDisplayHook()('\n'); - state.v = types.VOID; - }), - new PrimProc('newline', 1, false, false, function(port) { - // FIXME - throw types.internalError("newline to a port not implemented yet.", false); - } )]); - - - - PRIMITIVES['current-print'] = - new PrimProc('current-print', - 0, - false, false, - function() { - return defaultPrint; - }); - - - PRIMITIVES['current-continuation-marks'] = - // FIXME: should be CasePrimitive taking either 0 or 1 arguments - new PrimProc('current-continuation-marks', - 0, - false, true, - function(aState) { - aState.v = state.captureCurrentContinuationMarks(aState); - }); - - PRIMITIVES['continuation-mark-set?'] = - new PrimProc('continuation-mark-set?', - 1, - false, - false, - types.isContinuationMarkSet); - - PRIMITIVES['continuation-mark-set->list'] = - new PrimProc('continuation-mark-set->list', - 2, - false, - true, - function(state, markSet, keyV) { - check(markSet, - types.isContinuationMarkSet, - 'continuation-mark-set->list', - 'continuation-mark-set', - 1, - [markSet, keyV]); - state.v = types.list(markSet.ref(keyV)); - }); - - - - PRIMITIVES['for-each'] = - new PrimProc('for-each', - 2, - true, false, - function(f, firstArg, arglists) { - var allArgs = [f, firstArg].concat(arglists); - arglists.unshift(firstArg); - check(f, isFunction, 'for-each', 'procedure', 1, allArgs); - arrayEach(arglists, function(lst, i) {checkList(lst, 'for-each', i+2, allArgs);}); - checkAllSameLength(arglists, 'for-each', allArgs); - check(f, procArityContains(arglists.length), 'for-each', 'procedure (arity ' + arglists.length + ')', 1, allArgs); - - var forEachHelp = function(args) { - if (args[0].isEmpty()) { - return types.VOID; - } - - var argsFirst = []; - var argsRest = []; - for (var i = 0; i < args.length; i++) { - argsFirst.push(args[i].first); - argsRest.push(args[i].rest); - } - - return CALL(f, argsFirst, - function(result) { return forEachHelp(argsRest); }); - } - - return forEachHelp(arglists); - }); - - - PRIMITIVES['make-thread-cell'] = - new CasePrimitive('make-thread-cell', [ - new PrimProc("make-thread-cell", - 1, false, false, - function(x) { - return new types.ThreadCell(x, false); - } - ), - new PrimProc("make-thread-cell", - 2, false, false, - function(x, y) { - return new types.ThreadCell(x, y); - } - )]); - - - - PRIMITIVES['make-continuation-prompt-tag'] = - new CasePrimitive('make-continuation-prompt-tag', - [ - new PrimProc("make-continuation-prompt-tag", - 0, false, false, - function() { - return new types.ContinuationPromptTag(); - } - ), - new PrimProc("make-continuation-prompt-tag", - 1, false, false, - function(x) { - check(x, isSymbol, 'make-continuation-prompt-tag', - 'symbol', 1, arguments); - return new types.ContinuationPromptTag(x); - } - )]); - - - - PRIMITIVES['call-with-continuation-prompt'] = - new PrimProc('call-with-continuation-prompt', - 1, - true, true, - function(aState, proc, args) { - - // First check that proc is a procedure. - var allArgs = [proc].concat(args); - check(proc, isFunction, 'call-with-continuation-prompt', 'procedure', 1, allArgs); - - // Do other argument parsing stuff... - var promptTag; - var handler; - var procArgs; - if (args.length === 0) { - promptTag = types.defaultContinuationPromptTag; - handler = types.defaultContinuationPromptTagHandler; - procArgs = args.slice(0); - } else if (args.length === 1) { - promptTag = args[0]; - handler = types.defaultContinuationPromptTagHandler; - procArgs = args.slice(1); - - } else if (args.length >= 2) { - promptTag = args[0]; - handler = args[1]; - procArgs = args.slice(2); - } - - // If the handler is false, default to () - if (handler === false) { - handler = defaultCallWithContinuationPromptHandler; - } - - // Add the prompt. - aState.pushControl(new control.PromptControl(aState.vstack.length, - promptTag, - handler)); - // Within the context of the prompt, do the procedure application. - aState.pushControl( - new control.ApplicationControl( - new control.ConstantControl(proc), - helpers.map(function(op) { - return new control.ConstantControl(op)}, - procArgs))); - }); - - PRIMITIVES['default-continuation-prompt-tag'] = - new PrimProc('default-continuation-prompt-tag', - 0, - false, false, - function() { - return types.defaultContinuationPromptTag; - }); - - - PRIMITIVES['continuation-prompt-tag?'] = - new PrimProc('continuation-prompt-tag?', - 1, - false, false, - types.isContinuationPromptTag); - - - - - - // Implements the default handler for a continuation prompt, if one isn't provided - // by call-with-continuation-prompt. - var defaultCallWithContinuationPromptHandler = - new PrimProc('default-call-with-continuation-prompt-handler', - 1, - false, - true, - function(aState, abortThunk) { - // The default handler accepts a single abort thunk - // argument, and then re-installs the prompt and continues - // with the abort thunk. - // (call-with-continuation-prompt abort-thunk prompt-tag #f) - aState.pushControl( - new control.ApplicationControl( - new control.ConstantControl(PRIMITIVES['call-with-continuation-prompt']), - helpers.map(function(op) { - return new control.ConstantControl(op)}, - [abortThunk, promptTag, false]))); - }); - - - PRIMITIVES['abort-current-continuation'] = - new PrimProc('abort-current-continuation', - 1, - true, true, - function(aState, promptTag, args) { - control.setupAbortToPrompt(aState, promptTag, args); - }); - - - - - - - - - - - - - PRIMITIVES['make-struct-type'] = - makeOptionPrimitive( - 'make-struct-type', - 4, - [false, - types.EMPTY, - false, - false, - types.EMPTY, - false, - false], - true, - function(userArgs, - aState, - name, - superType, - initFieldCnt, - autoFieldCnt, - autoV, - props, // FIXME: currently ignored - inspector, // FIXME: currently ignored - procSpec, // FIXME: currently ignored - immutables, // FIXME: currently ignored - guard, - constructorName // FIXME: currently ignored - ) { - check(name, isSymbol, 'make-struct-type', 'symbol', 1, userArgs); - check(superType, function(x) { return x === false || types.isStructType(x); }, - 'make-struct-type', 'struct-type or #f', 2, userArgs); - check(initFieldCnt, isNatural, 'make-struct-type', 'exact non-negative integer', 3, userArgs); - check(autoFieldCnt, isNatural, 'make-struct-type', 'exact non-negative integer', 4, userArgs); - // TODO: check props - // TODO: check inspector - // TODO: check procSpect - checkListOf(immutables, isNatural, 'make-struct-type', 'exact non-negative integer', 9, userArgs); - check(guard, function(x) { return x === false || isFunction(x); }, - 'make-struct-type', 'procedure or #f', 10, userArgs); - - var numberOfGuardArgs = initFieldCnt + 1 + (superType ? superType.numberOfArgs : 0); - var aStructType = - types.makeStructureType(name.toString(), - superType, - jsnums.toFixnum(initFieldCnt), - jsnums.toFixnum(autoFieldCnt), - autoV, - checkAndGetGuard('make-struct-type', guard, numberOfGuardArgs)); - - aState.v = getMakeStructTypeReturns(aStructType); - }); - - - PRIMITIVES['make-struct-field-accessor'] = - makeOptionPrimitive( - 'make-struct-field-accessor', - 2, - [false], - false, - function(userArgs, accessor, fieldPos, fieldName) { - check(accessor, function(x) { return x instanceof types.StructAccessorProc && x.numParams > 1; }, - 'make-struct-field-accessor', 'accessor procedure that requires a field index', 1, userArgs); - check(fieldPos, isNatural, 'make-struct-field-accessor', 'exact non-negative integer', 2, userArgs); - check(fieldName, function(x) { return x === false || isSymbol(x); }, - 'make-struct-field-accessor', 'symbol or #f', 3, userArgs); - - var procName = accessor.type.name + '-' - + (fieldName ? fieldName.toString() : 'field' + fieldPos.toString()); - - return new types.StructAccessorProc(accessor.type, procName, 1, false, false, - function(x) { - check(x, accessor.type.predicate, procName, 'struct:'+accessor.type.name, 1); - return accessor.impl(x, fieldPos); - }); - }); - - - - PRIMITIVES['make-struct-field-mutator'] = - makeOptionPrimitive( - 'make-struct-field-mutator', - 2, - [false], - false, - function(userArgs, mutator, fieldPos, fieldName) { - check(mutator, function(x) { return x instanceof types.StructMutatorProc && x.numParams > 1; }, - 'make-struct-field-mutator', 'mutator procedure that requires a field index', 1, userArgs); - check(fieldPos, isNatural, 'make-struct-field-mutator', 'exact non-negative integer', 2, userArgs); - check(fieldName, function(x) { return x === false || isSymbol(x); }, - 'make-struct-field-mutator', 'symbol or #f', 3, userArgs); - - var procName = mutator.type.name + '-' - + (fieldName ? fieldName.toString() : 'field' + fieldPos.toString()); - - return new types.StructMutatorProc(mutator.type, procName, 2, false, false, - function(x, v) { - check(x, mutator.type.predicate, procName, 'struct:'+mutator.type.name, 1, arguments); - return mutator.impl(x, fieldPos, v); - }); - }); - - - PRIMITIVES['struct-type?'] = - new PrimProc('struct-type?', 1, false, false, types.isStructType); - - PRIMITIVES['struct-constructor-procedure?'] = - new PrimProc('struct-constructor-procedure?', 1, false, false, - function(x) { - return x instanceof types.StructConstructorProc; }); - - PRIMITIVES['struct-predicate-procedure?'] = - new PrimProc('struct-predicate-procedure?', 1, false, false, - function(x) { - return x instanceof types.StructPredicateProc; }); - - PRIMITIVES['struct-accessor-procedure?'] = - new PrimProc('struct-accessor-procedure?', 1, false, false, - function(x) { - return x instanceof types.StructAccessorProc; }); - - PRIMITIVES['struct-mutator-procedure?'] = - new PrimProc('struct-mutator-procedure?', 1, false, false, - function(x) { - return (x instanceof types.StructMutatorProc); }); - - - - PRIMITIVES['procedure-arity'] = new PrimProc('procedure-arity', 1, false, false, procedureArity); - - - PRIMITIVES['procedure-arity-includes?'] = - new PrimProc('procedure-arity-includes?', - 2, - false, - false, - function(proc, k) { - check(proc, isFunction, 'procedure-arity-includes?', 'procedure', 1, [proc, k]); - check(k, isNatural, 'procedure-arity-includes?', 'exact non-negative integer', 2, [proc, k]); - return helpers.procArityContains(k)(proc); - }); - - - PRIMITIVES['make-arity-at-least'] = - new PrimProc('make-arity-at-least', - 1, - false, - false, - types.arityAtLeast); - - PRIMITIVES['arity-at-least?'] = - new PrimProc('arity-at-least?', - 1, - false, false, - function(x) { - return types.isArityAtLeast(x); - }); - - PRIMITIVES['arity-at-least-value'] = - new PrimProc('arity-at-least-value', - 1, - false, false, - function(x) { - check(x, types.isArityAtLeast, 'arity-at-least-value', - 'arity-at-least', 1, [x]); - return types.arityAtLeastValue(x); - }); - - - PRIMITIVES['apply'] = - new PrimProc('apply', - 2, - true, false, - function(f, firstArg, args) { - var allArgs = [f, firstArg].concat(args); - check(f, isFunction, 'apply', 'procedure', 1, allArgs); - args.unshift(firstArg); - - var lastArg = args.pop(); - checkList(lastArg, 'apply', args.length+2, allArgs); - var args = args.concat(helpers.schemeListToArray(lastArg)); - - return CALL(f, args, id); - }); - - - PRIMITIVES['values'] = - new PrimProc('values', - 0, - true, false, - function(args) { - if (args.length === 1) { - return args[0]; - } - return new types.ValuesWrapper(args); - }); - - - PRIMITIVES['call-with-values'] = - new PrimProc('call-with-values', - 2, - false, false, - function(g, r) { - check(g, procArityContains(0), 'call-with-values', 'procedure (arity 0)', 1, arguments); - check(r, isFunction, 'call-with-values', 'procedure', 2, arguments); - - return CALL(g, [], - function(res) { - return callWithValues(r, res); - }); - }); - - - PRIMITIVES['compose'] = - new PrimProc('compose', - 0, - true, false, - function(procs) { - arrayEach(procs, function(p, i) {check(p, isFunction, 'compose', 'procedure', i+1, procs);}); - - if (procs.length == 0) { - return PRIMITIVES['values']; - } - var funList = types.list(procs).reverse(); - - var composeHelp = function(x, fList) { - if ( fList.isEmpty() ) { - return x; - } - - return CALL(new PrimProc('', 1, false, false, - function(args) { - return callWithValues(fList.first, args); - }), - [x], - function(result) { - return composeHelp(result, fList.rest); - }); - } - return new PrimProc('', 0, true, false, - function(args) { - if (args.length === 1) { - return composeHelp(args[0], funList); - } - return composeHelp(new types.ValuesWrapper(args), funList); - }); - }); - - - PRIMITIVES['current-inexact-milliseconds'] = - new PrimProc('current-inexact-milliseconds', - 0, - false, false, - function() { - return jsnums.makeFloat((new Date()).valueOf()); - }); - - - PRIMITIVES['current-seconds'] = - new PrimProc('current-seconds', - 0, - false, false, - function() { - return Math.floor( (new Date()).getTime() / 1000 ); - }); - - - PRIMITIVES['current-inspector'] = - new PrimProc('current-inspector', - 0, - false, false, - function() { - return false; - }); - - - - PRIMITIVES['not'] = - new PrimProc('not', - 1, - false, false, - function(x) { - return x === false; - }); - - - PRIMITIVES['void'] = - new PrimProc('void', 0, true, false, - function(args) { - return types.VOID; - }); - - - PRIMITIVES['random'] = - new CasePrimitive('random', - [new PrimProc('random', 0, false, false, - function() {return types.floatpoint(Math.random());}), - new PrimProc('random', 1, false, false, - function(n) { - check(n, isNatural, 'random', 'non-negative exact integer', 1, arguments); - return Math.floor(Math.random() * jsnums.toFixnum(n)); - }) ]); - - - PRIMITIVES['sleep'] = - new CasePrimitive('sleep', - [new PrimProc('sleep', 0, false, false, function() { return types.VOID; }), - new PrimProc('sleep', - 1, - false, false, - function(secs) { - check(secs, isNonNegativeReal, 'sleep', 'non-negative real number', 1); - - var millisecs = jsnums.toFixnum( jsnums.multiply(secs, 1000) ); - return PAUSE(function(caller, success, fail) { - setTimeout(function() { success(types.VOID); }, - millisecs); - }); - }) ]); - - - PRIMITIVES['identity'] = new PrimProc('identity', 1, false, false, id); - - - PRIMITIVES['raise'] = - new PrimProc('raise', - 1, - false, - false, - raise); - - PRIMITIVES['error'] = - new PrimProc('error', - 1, - true, false, - function(arg1, args) { - var allArgs = [arg1].concat(args); - check(arg1, function(x) {return isSymbol(x) || isString(x);}, - 'error', 'symbol or string', 1, allArgs); - - if ( isSymbol(arg1) ) { - if ( args.length === 0 ) { - raise( types.incompleteExn(types.exnFail, "error: " + arg1.val, []) ); - } - var formatStr = args.shift(); - check(formatStr, isString, 'error', 'string', 2, allArgs); - - args.unshift(arg1); - raise( types.incompleteExn(types.exnFail, helpers.format('~s: '+formatStr.toString(), args), []) ); - } - else { - var msgBuffer = [arg1.toString()]; - for (var i = 0; i < args.length; i++) { - msgBuffer.push( helpers.toDisplayedString(args[i]) ); - } - raise( types.incompleteExn(types.exnFail, msgBuffer.join(''), []) ); - } - }); - - - - PRIMITIVES['make-exn'] = new PrimProc('make-exn', 2, false, false, types.exn); - - PRIMITIVES['exn-message'] = - new PrimProc('exn-message', - 1, - false, false, - function(exn) { - check(exn, types.isExn, 'exn-message', 'exn', 1, [exn]); - return types.exnMessage(exn); - }); - - - PRIMITIVES['exn-continuation-marks'] = - new PrimProc('exn-continuation-marks', - 1, - false, false, - function(exn) { - check(exn, types.isExn, 'exn-continuation-marks', 'exn', 1, [exn]); - return types.exnContMarks(exn); - }); - - - PRIMITIVES['make-exn:fail'] = new PrimProc('make-exn:fail', 2, false, false, types.exnFail); - - - PRIMITIVES['make-exn:fail:contract'] = new PrimProc('make-exn:fail:contract', 2, false, false, types.exnFailContract); - - PRIMITIVES['make-exn:fail:contract:arity'] = - new PrimProc('make-exn:fail:contract:arity', - 2, - false, - false, - types.exnFailContractArity); - - - PRIMITIVES['make-exn:fail:contract:variable'] = - new PrimProc('make-exn:fail:contract:variable', - 3, - false, - false, - types.exnFailContractVariable); - - - - PRIMITIVES['make-exn:fail:contract:divide-by-zero'] = - new PrimProc('make-exn:fail:contract:divide-by-zero', - 2, - false, - false, - types.exnFailContractDivisionByZero); - - - PRIMITIVES['exn?'] = - new PrimProc('exn?', - 1, - false, - false, - types.isExn); - - - PRIMITIVES['exn:fail?'] = - new PrimProc('exn:fail?', - 1, - false, - false, - types.isExnFail); - - - PRIMITIVES['exn:fail:contract?'] = - new PrimProc('exn:fail:contract?', - 1, - false, - false, - types.isExnFailContract); - - - PRIMITIVES['exn:fail:contract:arity?'] = - new PrimProc('exn:fail:contract:arity?', - 1, - false, - false, - types.isExnFailContractArity); - - - PRIMITIVES['exn:fail:contract:variable?'] = - new PrimProc('exn:fail:contract:variable?', - 1, - false, - false, - types.isExnFailContractVariable); - - - PRIMITIVES['exn:fail:contract:divide-by-zero?'] = - new PrimProc('exn:fail:contract:divide-by-zero?', - 1, - false, - false, - types.isExnFailContractDivisionByZero); - - - - - /*********************** - *** Math Primitives *** - ***********************/ - - - PRIMITIVES['*'] = - new PrimProc('*', - 0, - true, false, - function(args) { - arrayEach(args, function(x, i) {check(x, isNumber, '*', 'number', i+1, args);}); - - var result = types.rational(1); - for(var i = 0; i < args.length; i++) { - result = jsnums.multiply(args[i], result); - } - return result; - }); - - - - PRIMITIVES['-'] = - new PrimProc("-", - 1, - true, false, - function(x, args) { - var allArgs = [x].concat(args); - check(x, isNumber, '-', 'number', 1, allArgs); - arrayEach(args, function(y, i) {check(y, isNumber, '-', 'number', i+2, allArgs);}); - - if (args.length == 0) { - return jsnums.subtract(0, x); - } - var result = x; - for (var i = 0; i < args.length; i++) { - result = jsnums.subtract(result, args[i]); - } - return result; - }); - - - PRIMITIVES['+'] = - new PrimProc("+", - 0, - true, false, - function(args) { - arrayEach(args, function(x, i) {check(x, isNumber, '+', 'number', i+1, args);}); - - if (args.length == 0) { - return 0; - } - var result = args[0]; - for (var i = 1; i < args.length; i++) { - result = jsnums.add(result, args[i]); - } - return result; - }); - - - PRIMITIVES['='] = - new PrimProc("=", - 2, - true, false, - function(x, y, args) { - args.unshift(y); - args.unshift(x); - arrayEach(args, function(z, i) {check(z, isNumber, '=', 'number', i+1, args);}); - - return compare(args, jsnums.equals); - }); - - - PRIMITIVES['=~'] = - new PrimProc('=~', - 3, - false, false, - function(x, y, range) { - check(x, isReal, '=~', 'real', 1, arguments); - check(y, isReal, '=~', 'real', 2, arguments); - check(range, isNonNegativeReal, '=~', 'non-negative-real', 3, arguments); - - return jsnums.lessThanOrEqual(jsnums.abs(jsnums.subtract(x, y)), range); - }); - - - PRIMITIVES['/'] = - new PrimProc('/', - 1, - true, false, - function(x, args) { - var allArgs = [x].concat(args); - check(x, isNumber, '/', 'number', 1, allArgs); - arrayEach(args, function(y, i) {check(y, isNumber, '/', 'number', i+2, allArgs);}); - - if (args.length == 0) { - if ( jsnums.eqv(x, 0) ) { - raise( types.incompleteExn(types.exnFailContractDivisionByZero, '/: division by zero', []) ); - } - return jsnums.divide(1, x); - } - - var res = x; - for (var i = 0; i < args.length; i++) { - if ( jsnums.eqv(args[i], 0) ) { - raise( types.incompleteExn(types.exnFailContractDivisionByZero, '/: division by zero', []) ); - } - res = jsnums.divide(res, args[i]); - } - return res; - }); - - - - PRIMITIVES['sub1'] = - new PrimProc("sub1", - 1, - false, false, - sub1); - - PRIMITIVES['add1'] = - new PrimProc("add1", - 1, - false, false, - add1); - - - PRIMITIVES['<'] = - new PrimProc('<', - 2, - true, false, - function(x, y, args) { - args.unshift(y); - args.unshift(x); - arrayEach(args, function(z, i) {check(z, isNumber, '<', 'number', i+1, args);}); - - return compare(args, jsnums.lessThan); - }); - - - PRIMITIVES['>'] = - new PrimProc('>', - 2, - true, false, - function(x, y, args) { - args.unshift(y); - args.unshift(x); - arrayEach(args, function(z, i) {check(z, isNumber, '>', 'number', i+1, args);}); - - return compare(args, jsnums.greaterThan); - }); - - - PRIMITIVES['<='] = - new PrimProc('<=', - 2, - true, false, - function(x, y, args) { - args.unshift(y); - args.unshift(x); - arrayEach(args, function(z, i) {check(z, isNumber, '<=', 'number', i+1, args);}); - - return compare(args, jsnums.lessThanOrEqual); - }); - - - PRIMITIVES['>='] = - new PrimProc('>=', - 2, - true, false, - function(x, y, args) { - args.unshift(y); - args.unshift(x); - arrayEach(args, function(z, i) {check(z, isNumber, '>=', 'number', i+1, args);}); - - return compare(args, jsnums.greaterThanOrEqual); - }); - - - - - PRIMITIVES['abs'] = - new PrimProc('abs', - 1, - false, false, - function(x) { - check(x, isReal, 'abs', 'real', 1); - return jsnums.abs(x); - }); - - - PRIMITIVES['quotient'] = - new PrimProc('quotient', - 2, - false, false, - function(x, y) { - check(x, isInteger, 'quotient', 'integer', 1, arguments); - check(y, isInteger, 'quotient', 'integer', 2, arguments); - - return jsnums.quotient(x, y); - }); - - - PRIMITIVES['remainder'] = - new PrimProc('remainder', - 2, - false, false, - function(x, y) { - check(x, isInteger, 'remainder', 'integer', 1, arguments); - check(y, isInteger, 'remainder', 'integer', 2, arguments); - - return jsnums.remainder(x, y); - }); - - - PRIMITIVES['modulo'] = - new PrimProc('modulo', - 2, - false, false, - function(x, y) { - check(x, isInteger, 'modulo', 'integer', 1, arguments); - check(y, isInteger, 'modulo', 'integer', 2, arguments); - - return jsnums.modulo(x, y); - }); - - - PRIMITIVES['max'] = - new PrimProc('max', - 1, - true, false, - function(x, args) { - args.unshift(x); - // check(x, isReal, 'max', 'real', 1, allArgs); - arrayEach(args, function(y, i) {check(y, isReal, 'max', 'real', i+1, args);}); - - var curMax = x; - for (var i = 1; i < args.length; i++) { - if ( jsnums.greaterThan(args[i], curMax) ) { - curMax = args[i]; - } - } - return curMax; - }); - - - PRIMITIVES['min'] = - new PrimProc('min', - 1, - true, false, - function(x, args) { - args.unshift(x); - // check(x, isReal, 'min', 'real', 1); - arrayEach(args, function(y, i) {check(y, isReal, 'min', 'real', i+1, args);}); - - var curMin = x; - for (var i = 1; i < args.length; i++) { - if ( jsnums.lessThan(args[i], curMin) ) { - curMin = args[i]; - } - } - return curMin; - }); - - - PRIMITIVES['gcd'] = - new PrimProc('gcd', - 1, - true, false, - function(x, args) { - var allArgs = [x].concat(args); - check(x, isInteger, 'gcd', 'integer', 1, allArgs); - arrayEach(args, function(y, i) {check(y, isInteger, 'gcd', 'integer', i+2, allArgs);}); - - return jsnums.gcd(x, args); - }); - - PRIMITIVES['lcm'] = - new PrimProc('lcm', - 1, - true, false, - function(x, args) { - var allArgs = [x].concat(args); - check(x, isInteger, 'lcm', 'integer', 1, allArgs); - arrayEach(args, function(y, i) {check(y, isInteger, 'lcm', 'integer', i+2, allArgs);}); - - return jsnums.lcm(x, args); - }); - - - PRIMITIVES['floor'] = - new PrimProc('floor', - 1, - false, false, - function(x) { - check(x, isReal, 'floor', 'real', 1); - return jsnums.floor(x); - }); - - - PRIMITIVES['ceiling'] = - new PrimProc('ceiling', - 1, - false, false, - function(x) { - check(x, isReal, 'ceiling', 'real', 1); - return jsnums.ceiling(x); - }); - - - PRIMITIVES['round'] = - new PrimProc('round', - 1, - false, false, - function(x) { - check(x, isReal, 'round', 'real', 1); - return jsnums.round(x); - }); - - PRIMITIVES['truncate'] = - new PrimProc('truncate', - 1, - false, false, - function(x) { - check(x, isReal, 'truncate', 'real', 1); - if (jsnums.lessThan(x, 0)) { - return jsnums.ceiling(x); - } else { - return jsnums.floor(x); - } - }); - - - - PRIMITIVES['numerator'] = - new PrimProc('numerator', - 1, - false, false, - function(x) { - check(x, isRational, 'numerator', 'rational number', 1); - return jsnums.numerator(x); - }); - - - PRIMITIVES['denominator'] = - new PrimProc('denominator', - 1, - false, false, - function(x) { - check(x, isRational, 'denominator', 'rational number', 1); - return jsnums.denominator(x); - }); - - - PRIMITIVES['expt'] = - new PrimProc("expt", - 2, - false, false, - function(x, y) { - check(x, isNumber, 'expt', 'number', 1, arguments); - check(y, isNumber, 'expt', 'number', 2, arguments); - return jsnums.expt(x, y); - }); - - - PRIMITIVES['exp'] = - new PrimProc('exp', - 1, - false, false, - function(x) { - check(x, isNumber, 'exp', 'number', 1); - return jsnums.exp(x); - }); - - - PRIMITIVES['log'] = - new PrimProc('log', - 1, - false, false, - function(x) { - check(x, isNumber, 'log', 'number', 1); - return jsnums.log(x); - }); - - - PRIMITIVES['sin'] = - new PrimProc('sin', - 1, - false, false, - function(x) { - check(x, isNumber, 'sin', 'number', 1); - return jsnums.sin(x); - }); - - - PRIMITIVES['cos'] = - new PrimProc('cos', - 1, - false, false, - function(x) { - check(x, isNumber, 'cos', 'number', 1); - return jsnums.cos(x); - }); - - - PRIMITIVES['tan'] = - new PrimProc('tan', - 1, - false, false, - function(x) { - check(x, isNumber, 'tan', 'number', 1); - return jsnums.tan(x); - }); - - - PRIMITIVES['asin'] = - new PrimProc('asin', - 1, - false, false, - function(x) { - check(x, isNumber, 'asin', 'number', 1); - return jsnums.asin(x); - }); - - - PRIMITIVES['acos'] = - new PrimProc('acos', - 1, - false, false, - function(x) { - check(x, isNumber, 'acos', 'number', 1); - return jsnums.acos(x); - }); - - - PRIMITIVES['atan'] = - new CasePrimitive('atan', - [new PrimProc('atan', - 1, - false, false, - function(x) { - check(x, isNumber, 'atan', 'number', 1); - return jsnums.atan(x); - }), - new PrimProc('atan', - 2, - false, false, - function(x, y) { - check(x, isReal, 'atan', 'number', 1); - check(y, isReal, 'atan', 'number', 1); - return jsnums.makeFloat( - Math.atan2(jsnums.toFixnum(x), - jsnums.toFixnum(y))); - })]); - - - PRIMITIVES['sinh'] = - new PrimProc('sinh', - 1, - false, false, - function(x) { - check(x, isNumber, 'sinh', 'number', 1); - return jsnums.sinh(x); - }); - - - PRIMITIVES['cosh'] = - new PrimProc('cosh', - 1, - false, false, - function(x) { - check(x, isNumber, 'cosh', 'number', 1); - return jsnums.cosh(x); - }); - - - PRIMITIVES['sqr'] = - new PrimProc('sqr', - 1, - false, false, - function(x) { - check(x, isNumber, 'sqr', 'number', 1); - return jsnums.sqr(x); - }); - - - PRIMITIVES['sqrt'] = - new PrimProc('sqrt', - 1, - false, false, - function(x) { - check(x, isNumber, 'sqrt', 'number', 1); - return jsnums.sqrt(x); - }); - - - PRIMITIVES['integer-sqrt'] = - new PrimProc('integer-sqrt', - 1, - false, false, - function(x) { - check(x, isInteger, 'integer-sqrt', 'integer', 1); - return jsnums.integerSqrt(x); - }); - - - PRIMITIVES['make-rectangular'] = - new PrimProc('make-rectangular', - 2, - false, false, - function(x, y) { - check(x, isReal, 'make-rectangular', 'real', 1, arguments); - check(y, isReal, 'make-rectangular', 'real', 2, arguments); - return types.complex(x, y); - }); - - PRIMITIVES['make-polar'] = - new PrimProc('make-polar', - 2, - false, false, - function(x, y) { - check(x, isReal, 'make-polar', 'real', 1, arguments); - check(x, isReal, 'make-polar', 'real', 2, arguments); - return jsnums.makeComplexPolar(x, y); - }); - - - PRIMITIVES['real-part'] = - new PrimProc('real-part', - 1, - false, false, - function(x) { - check(x, isNumber, 'real-part', 'number', 1); - return jsnums.realPart(x); - }); - - - PRIMITIVES['imag-part'] = - new PrimProc('imag-part', - 1, - false, false, - function(x) { - check(x, isNumber, 'imag-part', 'number', 1); - return jsnums.imaginaryPart(x); - }); - - - PRIMITIVES['angle'] = - new PrimProc('angle', - 1, - false, false, - function(x) { - check(x, isNumber, 'angle', 'number', 1); - return jsnums.angle(x); - }); - - - PRIMITIVES['magnitude'] = - new PrimProc('magnitude', - 1, - false, false, - function(x) { - check(x, isNumber, 'magnitude', 'number', 1); - return jsnums.magnitude(x); - }); - - - PRIMITIVES['conjugate'] = - new PrimProc('conjugate', - 1, - false, false, - function(x) { - check(x, isNumber, 'conjugate', 'number', 1); - return jsnums.conjugate(x); - }); - - - PRIMITIVES['sgn'] = - new PrimProc('sgn', - 1, - false, false, - function(x) { - check(x, isReal, 'sgn', 'real number', 1); - if (jsnums.isInexact(x)) { - if ( jsnums.greaterThan(x, 0) ) { - return jsnums.makeFloat(1); - } else if ( jsnums.lessThan(x, 0) ) { - return jsnums.makeFloat(-1); - } else { - return jsnums.makeFloat(0); - } - } else { - if ( jsnums.greaterThan(x, 0) ) { - return 1; - } else if ( jsnums.lessThan(x, 0) ) { - return -1; - } else { - return 0; - } - } - }); - - - PRIMITIVES['inexact->exact'] = - new PrimProc('inexact->exact', - 1, - false, false, - function (x) { - check(x, isNumber, 'inexact->exact', 'number', 1); - try { - return jsnums.toExact(x); - } catch(e) { - raise( types.exnFailContract('inexact->exact: no exact representation for ' - + helpers.toDisplayedString(x), - false) ); - } - }); - - - PRIMITIVES['exact->inexact'] = - new PrimProc('exact->inexact', - 1, - false, false, - function (x) { - check(x, isNumber, 'exact->inexact', 'number', 1); - return jsnums.toInexact(x); - }); - - - PRIMITIVES['number->string'] = - new PrimProc('number->string', - 1, - false, false, - function(x) { - check(x, isNumber, 'number->string', 'number', 1); - return types.string(x.toString()); - }); - - - PRIMITIVES['string->number'] = - new PrimProc('string->number', - 1, - false, false, - function(str) { - check(str, isString, 'string->number', 'string', 1); - return jsnums.fromString(str.toString()); - }); - - - PRIMITIVES['xml->s-exp'] = - new PrimProc('xml->s-exp', - 1, - false, false, - function(str) { - check(str, isString, 'xml->s-exp', 'string', 1); - str = str.toString(); - if (str.length == 0) { - return types.string(''); - } - - var xmlDoc; - try { - //Internet Explorer - xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); - xmlDoc.async = "false"; - xmlDoc.loadXML(s); - // FIXME: check parse errors - } - catch(e) { - var parser = new DOMParser(); - xmlDoc = parser.parseFromString(s, "text/xml"); - // FIXME: check parse errors - } - - var parseAttributes = function(attrs) { - var result = types.EMPTY; - for (var i = 0; i < attrs.length; i++) { - var keyValue = types.cons(types.symbol(attrs.item(i).nodeName), - types.cons(attrs.item(i).nodeValue, - types.EMPTY)); - result = types.cons(keyValue, result); - } - return types.cons(types.symbol("@"), result).reverse(); - }; - - var parse = function(node) { - if (node.nodeType == Node.ELEMENT_NODE) { - var result = types.EMPTY; - var child = node.firstChild; - while (child != null) { - var nextResult = parse(child); - if (isString(nextResult) && - !result.isEmpty() && - isString(result.first)) { - result = types.cons(result.first + nextResult, - result.rest); - } else { - result = types.cons(nextResult, result); - } - child = child.nextSibling; - } - result = result.reverse(); - result = types.cons(parseAttributes(node.attributes), - result); - result = types.cons( - types.symbol(node.nodeName), - result); - return result; - } else if (node.nodeType == Node.TEXT_NODE) { - return node.textContent; - } else if (node.nodeType == Node.CDATA_SECTION_NODE) { - return node.data; - } else { - return types.EMPTY; - } - }; - var result = parse(xmlDoc.firstChild); - return result; - }); - - - - - /****************** - *** Predicates *** - ******************/ - - PRIMITIVES['procedure?'] = new PrimProc('procedure?', 1, false, false, isFunction); - - PRIMITIVES['pair?'] = new PrimProc('pair?', 1, false, false, isPair); - PRIMITIVES['cons?'] = new PrimProc('cons?', 1, false, false, isPair); - PRIMITIVES['empty?'] = new PrimProc('empty?', 1, false, false, isEmpty); - PRIMITIVES['null?'] = new PrimProc('null?', 1, false, false, isEmpty); - - PRIMITIVES['undefined?'] = new PrimProc('undefined?', 1, false, false, function(x) { return x === types.UNDEFINED; }); - PRIMITIVES['void?'] = new PrimProc('void?', 1, false, false, function(x) { return x === types.VOID; }); - - - PRIMITIVES['immutable?'] = new PrimProc('immutable?', 1, false, false, isImmutable); - - PRIMITIVES['symbol?'] = new PrimProc('symbol?', 1, false, false, isSymbol); - PRIMITIVES['string?'] = new PrimProc('string?', 1, false, false, isString); - PRIMITIVES['char?'] = new PrimProc('char?', 1, false, false, isChar); - PRIMITIVES['boolean?'] = new PrimProc('boolean?', 1, false, false, isBoolean); - PRIMITIVES['vector?'] = new PrimProc('vector?', 1, false, false, isVector); - PRIMITIVES['struct?'] = new PrimProc('struct?', 1, false, false, types.isStruct); - PRIMITIVES['eof-object?'] = new PrimProc('eof-object?', 1, false, false, function(x) { return x === types.EOF; }); - PRIMITIVES['posn?'] = new PrimProc('posn?', 1, false, false, types.isPosn); - PRIMITIVES['bytes?'] = new PrimProc('bytes?', 1, false, false, isByteString); - PRIMITIVES['byte?'] = new PrimProc('byte?', 1, false, false, isByte); - - PRIMITIVES['number?'] = new PrimProc('number?', 1, false, false, isNumber); - PRIMITIVES['complex?'] = new PrimProc('complex?', 1, false, false, isComplex); - PRIMITIVES['real?'] = new PrimProc('real?', 1, false, false, isReal); - PRIMITIVES['rational?'] = new PrimProc('rational?', 1, false, false, isRational); - PRIMITIVES['integer?'] = new PrimProc('integer?', 1, false, false, isInteger); - - PRIMITIVES['exact?'] = - new PrimProc('exact?', 1, false, false, - function(x) { - check(x, isNumber, 'exact?', 'number', 1); - return jsnums.isExact(x); - }); - PRIMITIVES['inexact?'] = - new PrimProc('inexact?', 1, false, false, - function(x) { - check(x, isNumber, 'inexact?', 'number', 1); - return jsnums.isInexact(x); - }); - - PRIMITIVES['odd?'] = - new PrimProc('odd?', - 1, - false, false, - function(x) { - check(x, isInteger, 'odd?', 'integer', 1); - return jsnums.equals(jsnums.modulo(x, 2), 1); - }); - PRIMITIVES['even?'] = - new PrimProc('even?', - 1, - false, false, - function(x) { - check(x, isInteger, 'even?', 'integer', 1); - return jsnums.equals(jsnums.modulo(x, 2), 0); - }); - - PRIMITIVES['zero?'] = - new PrimProc("zero?", - 1, - false, false, - function(x) { - return jsnums.equals(0, x) - }); - - PRIMITIVES['positive?'] = - new PrimProc('positive?', - 1, - false, false, - function(x) { - check(x, isReal, 'positive?', 'real', 1); - return jsnums.greaterThan(x, 0); - }); - PRIMITIVES['negative?'] = - new PrimProc('negative?', - 1, - false, false, - function(x) { - check(x, isReal, 'negative?', 'real', 1); - return jsnums.lessThan(x, 0); - }); - - PRIMITIVES['box?'] = new PrimProc('box?', 1, false, false, isBox); - - PRIMITIVES['hash?'] = new PrimProc('hash?', 1, false, false, isHash); - - - PRIMITIVES['eq?'] = new PrimProc('eq?', 2, false, false, isEq); - PRIMITIVES['eqv?'] = new PrimProc('eqv?', 2, false, false, isEqv); - PRIMITIVES['equal?'] = new PrimProc('equal?', 2, false, false, isEqual); - PRIMITIVES['equal~?'] = - new PrimProc('equal~?', - 3, - false, false, - function(x, y, range) { - check(range, isNonNegativeReal, 'equal~?', 'non-negative-real', 3, arguments); - - return (isEqual(x, y) || - (isReal(x) && isReal(y) && - jsnums.lessThanOrEqual(jsnums.abs(jsnums.subtract(x, y)), range))); - }); - - - PRIMITIVES['false?'] = new PrimProc('false?', 1, false, false, function(x) { return x === false; }); - PRIMITIVES['boolean=?'] = - new PrimProc('boolean=?', - 2, - false, false, - function(x, y) { - check(x, isBoolean, 'boolean=?', 'boolean', 1, arguments); - check(y, isBoolean, 'boolean=?', 'boolean', 2, arguments); - return x === y; - }); - - PRIMITIVES['symbol=?'] = - new PrimProc('symbol=?', - 2, - false, false, - function(x, y) { - check(x, isSymbol, 'symbol=?', 'symbol', 1, arguments); - check(y, isSymbol, 'symbol=?', 'symbol', 2, arguments); - return isEqual(x, y); - }); - - - PRIMITIVES['js-value?'] = new PrimProc('js-value?', 1, false, false, isJsValue); - PRIMITIVES['js-object?'] = new PrimProc('js-object?', 1, false, false, isJsObject); - PRIMITIVES['js-function?'] = new PrimProc('js-function?', 1, false, false, isJsFunction); - - - /*********************** - *** List Primitives *** - ***********************/ - - PRIMITIVES['cons'] = - new PrimProc('cons', - 2, - false, false, - function(f, r) { - // checkList(r, "cons", 2); - return types.cons(f, r); - }); - - - PRIMITIVES['car'] = - new PrimProc('car', - 1, - false, false, - function(lst) { - check(lst, isPair, 'car', 'pair', 1); - return lst.first; - }); - - PRIMITIVES['cdr'] = - new PrimProc('cdr', - 1, - false, false, - function (lst) { - check(lst, isPair, 'cdr', 'pair', 1); - return lst.rest; - }); - - PRIMITIVES['caar'] = - new PrimProc('caar', - 1, - false, false, - function(lst) { - check(lst, function(x) { return (isPair(x) && isPair(x.first)); }, - 'caar', 'caarable value', 1); - return lst.first.first; - }); - - PRIMITIVES['cadr'] = - new PrimProc('cadr', - 1, - false, false, - function(lst) { - check(lst, function(x) { return isPair(x) && isPair(x.rest); }, - 'cadr', 'cadrable value', 1); - return lst.rest.first; - }); - - PRIMITIVES['cdar'] = - new PrimProc('cdar', - 1, - false, false, - function(lst) { - check(lst, function(x) { return isPair(x) && isPair(x.first); }, - 'cdar', 'cdarable value', 1); - return lst.first.rest; - }); - - PRIMITIVES['cddr'] = - new PrimProc('cddr', - 1, - false, false, - function(lst) { - check(lst, function(x) { return isPair(x) && isPair(x.rest); }, - 'cddr', 'cddrable value', 1); - return lst.rest.rest; - }); - - PRIMITIVES['caaar'] = - new PrimProc('caaar', - 1, - false, false, - function(lst) { - check(lst, function(x) { return ( isPair(x) && - isPair(x.first) && - isPair(x.first.first) ); }, - 'caaar', 'caaarable value', 1); - return lst.first.first.first; - }); - - PRIMITIVES['caadr'] = - new PrimProc('caadr', - 1, - false, false, - function(lst) { - check(lst, function(x) { return ( isPair(x) && - isPair(x.rest) && - isPair(x.rest.first) ); }, - 'caadr', 'caadrable value', 1); - return lst.rest.first.first; - }); - - PRIMITIVES['cadar'] = - new PrimProc('cadar', - 1, - false, false, - function(lst) { - check(lst, function(x) { return ( isPair(x) && - isPair(x.first) && - isPair(x.first.rest) ); }, - 'cadar', 'cadarable value', 1); - return lst.first.rest.first; - }); - - PRIMITIVES['cdaar'] = - new PrimProc('cdaar', - 1, - false, false, - function(lst) { - check(lst, function(x) { return ( isPair(x) && - isPair(x.first) && - isPair(x.first.first) ); }, - 'cdaar', 'cdaarable value', 1); - return lst.first.first.rest; - }); - - PRIMITIVES['cdadr'] = - new PrimProc('cdadr', - 1, - false, false, - function(lst) { - check(lst, function(x) { return ( isPair(x) && - isPair(x.rest) && - isPair(x.rest.first) ); }, - 'cdadr', 'cdadrable value', 1); - return lst.rest.first.rest; - }); - - PRIMITIVES['cddar'] = - new PrimProc('cddar', - 1, - false, false, - function(lst) { - check(lst, function(x) { return ( isPair(x) && - isPair(x.first) && - isPair(x.first.rest) ); }, - 'cddar', 'cddarable value', 1); - return lst.first.rest.rest; - }); - - PRIMITIVES['caddr'] = - new PrimProc('caddr', - 1, - false, false, - function(lst) { - check(lst, function(x) { return ( isPair(x) && - isPair(x.rest) && - isPair(x.rest.rest) ); }, - 'caddr', 'caddrable value', 1); - return lst.rest.rest.first; - }); - - PRIMITIVES['cdddr'] = - new PrimProc('cdddr', - 1, - false, false, - function(lst) { - check(lst, function(x) { return ( isPair(x) && - isPair(x.rest) && - isPair(x.rest.rest) ); }, - 'cdddr', 'cdddrable value', 1); - return lst.rest.rest.rest; - }); - - PRIMITIVES['cadddr'] = - new PrimProc('cadddr', - 1, - false, false, - function(lst) { - check(lst, function(x) { return ( isPair(x) && - isPair(x.rest) && - isPair(x.rest.rest) && - isPair(x.rest.rest.rest) ); }, - 'cadddr', 'cadddrable value', 1); - return lst.rest.rest.rest.first; - }); - - - PRIMITIVES['rest'] = - new PrimProc('rest', - 1, - false, false, - function(lst) { - check(lst, function(x) { return isList(x) && !isEmpty(x); }, - 'rest', 'non-empty list', 1); - return lst.rest; - }); - - PRIMITIVES['first'] = - new PrimProc('first', - 1, - false, false, - function(lst) { - check(lst, function(x) { return isList(x) && !isEmpty(x); }, - 'first', 'non-empty list', 1); - return lst.first; - }); - - PRIMITIVES['second'] = - new PrimProc('second', - 1, - false, false, - function(lst) { - checkListOfLength(lst, 2, 'second', 1); - return lst.rest.first; - }); - - PRIMITIVES['third'] = - new PrimProc('third', - 1, - false, false, - function(lst) { - checkListOfLength(lst, 3, 'third', 1); - return lst.rest.rest.first; - }); - - PRIMITIVES['fourth'] = - new PrimProc('fourth', - 1, - false, false, - function(lst) { - checkListOfLength(lst, 4, 'fourth', 1); - return lst.rest.rest.rest.first; - }); - - PRIMITIVES['fifth'] = - new PrimProc('fifth', - 1, - false, false, - function(lst) { - checkListOfLength(lst, 5, 'fifth', 1); - return lst.rest.rest.rest.rest.first; - }); - - PRIMITIVES['sixth'] = - new PrimProc('sixth', - 1, - false, false, - function(lst) { - checkListOfLength(lst, 6, 'sixth', 1); - return lst.rest.rest.rest.rest.rest.first; - }); - - PRIMITIVES['seventh'] = - new PrimProc( - 'seventh', - 1, - false, false, - function(lst) { - checkListOfLength(lst, 7, 'seventh', 1); - return lst.rest.rest.rest.rest.rest.rest.first; - }); - - PRIMITIVES['eighth'] = - new PrimProc('eighth', - 1, - false, false, - function(lst) { - checkListOfLength(lst, 8, 'eighth', 1); - return lst.rest.rest.rest.rest.rest.rest.rest.first; - }); - - - PRIMITIVES['length'] = - new PrimProc('length', - 1, - false, false, - function(lst) { - return jsnums.makeRational(length(lst)); - }); - - - PRIMITIVES['list?'] = new PrimProc('list?', 1, false, false, isList); - - - PRIMITIVES['list'] = - new PrimProc('list', - 0, - true, false, - types.list); - - - PRIMITIVES['list*'] = - new PrimProc('list*', - 1, - true, false, - function(anItem, otherItems) { - if (otherItems.length == 0) { - return anItem; - } - var allArgs = [anItem].concat(otherItems); - - var result = allArgs[allArgs.length - 1]; - for (var i = allArgs.length - 2 ; i >= 0; i--) { - result = types.cons(allArgs[i], result); - } - return result; - - // var lastListItem = otherItems.pop(); - // checkList(lastListItem, 'list*', otherItems.length+2, allArgs); - - // otherItems.unshift(anItem); - // return append([types.list(otherItems), lastListItem]); - }); - - - PRIMITIVES['list-ref'] = - new PrimProc('list-ref', - 2, - false, false, - function(origList, num) { - check(num, isNatural, 'list-ref', 'non-negative exact integer', 2, arguments); - - var lst = origList; - var n = jsnums.toFixnum(num); - for (var i = 0; i < n; i++) { - // According to the documentation of list-ref, we don't actually - // check the whole thing as a list. We rather do it as we walk - // along the cons chain. - if (! isPair(lst) && lst !== types.EMPTY) { - var msg = ('list-ref: index ' + n + - ' is too large for list (not a proper list): ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - if (lst.isEmpty()) { - var msg = ('list-ref: index ' + n + - ' is too large for list: ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - lst = lst.rest; - } - - - if (! isPair(lst) && lst !== types.EMPTY) { - var msg = ('list-ref: index ' + n + - ' is too large for list (not a proper list): ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - return lst.first; - }); - - PRIMITIVES['list-tail'] = - new PrimProc('list-tail', - 2, - false, false, - function(origList, num) { - check(num, isNatural, 'list-tail', 'non-negative exact integer', 2, arguments); - - var lst = origList; - var n = jsnums.toFixnum(num); - for (var i = 0; i < n; i++) { - // According to the documentation of list-tail, we don't actually - // check the whole thing as a list. We rather do it as we walk - // along the cons chain. - if (! isPair(lst) && lst !== types.EMPTY) { - var msg = ('list-tail: index ' + n + - ' is too large for list (not a proper list): ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - if (lst.isEmpty()) { - var msg = ('list-tail: index ' + n + - ' is too large for list: ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - lst = lst.rest; - } - return lst; - }); - - - PRIMITIVES['append'] = - new PrimProc('append', - 0, - true, false, - append); - - - PRIMITIVES['reverse'] = - new PrimProc('reverse', - 1, - false, false, - function(lst) { - checkList(lst, 'reverse', 1); - return lst.reverse(); - }); - - - PRIMITIVES['map'] = - new PrimProc('map', - 2, - true, false, - function(f, lst, arglists) { - var allArgs = [f, lst].concat(arglists); - arglists.unshift(lst); - check(f, isFunction, 'map', 'procedure', 1, allArgs); - arrayEach(arglists, function(x, i) {checkList(x, 'map', i+2, allArgs);}); - checkAllSameLength(arglists, 'map', allArgs); - - check(f, procArityContains(arglists.length), 'map', 'procedure (arity ' + arglists.length + ')', 1, allArgs); - - var mapHelp = function(f, args, acc) { - if (args[0].isEmpty()) { - return acc.reverse(); - } - - var argsFirst = []; - var argsRest = []; - for (var i = 0; i < args.length; i++) { - argsFirst.push(args[i].first); - argsRest.push(args[i].rest); - } - var result = CALL(f, argsFirst, - function(result) { - return onSingleResult(result, - function(result) { - return mapHelp(f, argsRest, types.cons(result, acc)); - }); - }); - return result; - } - return mapHelp(f, arglists, types.EMPTY); - }); - - - PRIMITIVES['andmap'] = - new PrimProc('andmap', - 2, - true, false, - function(f, lst, arglists) { - var allArgs = [f, lst].concat(arglists); - arglists.unshift(lst); - check(f, isFunction, 'andmap', 'procedure', 1, allArgs); - arrayEach(arglists, function(x, i) {checkList(x, 'andmap', i+2, allArgs);}); - checkAllSameLength(arglists, 'andmap', allArgs); - check(f, procArityContains(arglists.length), 'andmap', 'procedure (arity ' + arglists.length + ')', 1, allArgs); - - var andmapHelp = function(f, args) { - if ( args[0].isEmpty() ) { - return true; - } - - var argsFirst = []; - var argsRest = []; - for (var i = 0; i < args.length; i++) { - argsFirst.push(args[i].first); - argsRest.push(args[i].rest); - } - - return CALL(f, argsFirst, - function(result) { - if (argsRest[0].isEmpty()) { - return result; - } - return onSingleResult(result, - function(result) { - - return result && andmapHelp(f, argsRest); - }); - }); - } - return andmapHelp(f, arglists); - }); - - - PRIMITIVES['ormap'] = - new PrimProc('ormap', - 2, - true, false, - function(f, lst, arglists) { - var allArgs = [f, lst].concat(arglists); - arglists.unshift(lst); - check(f, isFunction, 'ormap', 'procedure', 1, allArgs); - arrayEach(arglists, function(x, i) {checkList(x, 'ormap', i+2, allArgs);}); - checkAllSameLength(arglists, 'ormap', allArgs); - - check(f, procArityContains(arglists.length), 'ormap', 'procedure (arity ' + arglists.length + ')', 1, allArgs); - - var ormapHelp = function(f, args) { - if ( args[0].isEmpty() ) { - return false; - } - - var argsFirst = []; - var argsRest = []; - for (var i = 0; i < args.length; i++) { - argsFirst.push(args[i].first); - argsRest.push(args[i].rest); - } - - return CALL(f, argsFirst, - function(result) { - if (argsRest[0].isEmpty()) { - return result; - } - return onSingleResult( - result, - function(result) { - return result || ormapHelp(f, argsRest); - }); - }); - } - return ormapHelp(f, arglists); - }); - - - PRIMITIVES['memq'] = - new PrimProc('memq', - 2, - false, false, - function(item, origList) { - var lst = origList; - if (! isPair(lst) && lst !== types.EMPTY) { - var msg = ('memq: not a proper list: ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - while ( !lst.isEmpty() ) { - - if ( isEq(item, lst.first) ) { - return lst; - } - lst = lst.rest; - if (! isPair(lst) && lst !== types.EMPTY) { - var msg = ('memq: not a proper list: ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - } - return false; - }); - - - PRIMITIVES['memv'] = - new PrimProc('memv', - 2, - false, false, - function(item, origList) { - var lst = origList; - if (! isPair(lst) && lst !== types.EMPTY) { - var msg = ('memv: not a proper list: ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - while ( !lst.isEmpty() ) { - if ( isEqv(item, lst.first) ) { - return lst; - } - lst = lst.rest; - if (! isPair(lst) && lst !== types.EMPTY) { - var msg = ('memv: not a proper list: ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - } - return false; - }); - - - PRIMITIVES['member'] = - new PrimProc('member', - 2, - false, false, - function(item, origList) { - var lst = origList; - //checkList(lst, 'member', 2, arguments); - if (! isPair(lst) && lst !== types.EMPTY) { - var msg = ('member: not a proper list: ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - while ( !lst.isEmpty() ) { - if ( isEqual(item, lst.first) ) { - return lst; - } - lst = lst.rest; - - if (! isPair(lst) && lst !== types.EMPTY) { - var msg = ('member: not a proper list: ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - } - return false; - }); - - - PRIMITIVES['memf'] = - new PrimProc('memf', - 2, - false, false, - function(f, initList) { - check(f, isFunction, 'memf', 'procedure', 1, arguments); - checkList(initList, 'memf', 2, arguments); - - var memfHelp = function(lst) { - if ( lst.isEmpty() ) { - return false; - } - - return CALL(f, [lst.first], - function(result) { - if (result) { - return lst; - } - return memfHelp(lst.rest); - }); - } - return memfHelp(initList); - }); - - - PRIMITIVES['assq'] = - new PrimProc('assq', - 2, - false, false, - function(item, origList) { - var lst = origList; - // checkListOf(lst, isPair, 'assq', 'pair', 2, arguments); - if (! isPair(lst) && lst !== types.EMPTY) { - var msg = ('assq: not a proper list: ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - while ( !lst.isEmpty() ) { - if (! isPair(lst.first)) { - var msg = ('assq: non-pair found in list: ' + - helpers.toDisplayedString(lst.first) +' in ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - if ( isEq(item, lst.first.first) ) { - return lst.first; - } - lst = lst.rest; - - if (! isPair(lst) && lst !== types.EMPTY) { - var msg = ('assq: not a proper list: ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - } - return false; - }); - - - PRIMITIVES['assv'] = - new PrimProc('assv', - 2, - false, false, - function(item, origList) { - //checkListOf(lst, isPair, 'assv', 'pair', 2, arguments); - var lst = origList; - if (! isPair(lst) && lst !== types.EMPTY) { - var msg = ('assv: not a proper list: ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - while ( !lst.isEmpty() ) { - if (! isPair(lst.first)) { - var msg = ('assv: non-pair found in list: ' + - helpers.toDisplayedString(lst.first) +' in ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - if ( isEqv(item, lst.first.first) ) { - return lst.first; - } - lst = lst.rest; - if (! isPair(lst) && lst !== types.EMPTY) { - var msg = ('assv: not a proper list: ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - } - return false; - }); - - - PRIMITIVES['assoc'] = - new PrimProc('assoc', - 2, - false, false, - function(item, origList) { - var lst = origList; - //checkListOf(lst, isPair, 'assoc', 'pair', 2, arguments); - if (! isPair(lst) && lst !== types.EMPTY) { - var msg = ('assoc: not a proper list: ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - while ( !lst.isEmpty() ) { - if (! isPair(lst.first)) { - var msg = ('assoc: non-pair found in list: ' + - helpers.toDisplayedString(lst.first) +' in ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - if ( isEqual(item, lst.first.first) ) { - return lst.first; - } - lst = lst.rest; - - if (! isPair(lst) && lst !== types.EMPTY) { - var msg = ('assoc: not a proper list: ' + - helpers.toDisplayedString(origList)); - raise( types.incompleteExn(types.exnFailContract, - msg, - []) ); - } - } - return false; - }); - - - PRIMITIVES['remove'] = - new PrimProc('remove', - 2, - false, false, - function(item, lst) { - checkList(lst, 'remove', 2, arguments); - var originalLst = lst; - var result = types.EMPTY; - while ( !lst.isEmpty() ) { - if ( isEqual(item, lst.first) ) { - return append([result.reverse(), lst.rest]); - } else { - result = types.cons(lst.first, result); - lst = lst.rest; - } - } - return originalLst; - }); - - - PRIMITIVES['filter'] = - new PrimProc('filter', - 2, - false, false, - function(f, lst) { - check(f, procArityContains(1), 'filter', 'procedure (arity 1)', 1, arguments); - checkList(lst, 'filter', 2); - - var filterHelp = function(f, lst, acc) { - if ( lst.isEmpty() ) { - return acc.reverse(); - } - - return CALL(f, [lst.first], - function(result) { - if (result) { - return filterHelp(f, lst.rest, - types.cons(lst.first, acc)); - } - else { - return filterHelp(f, lst.rest, acc); - } - }); - } - return filterHelp(f, lst, types.EMPTY); - }); - - PRIMITIVES['foldl'] = - new PrimProc('foldl', - 3, - true, false, - function(f, initAcc, lst, arglists) { - arglists.unshift(lst); - var allArgs = [f, initAcc].concat(arglists); - check(f, isFunction, 'foldl', 'procedure', 1, allArgs); - arrayEach(arglists, function(x, i) {checkList(x, 'foldl', i+3, allArgs);}); - checkAllSameLength(arglists, 'foldl', allArgs); - - return foldHelp(f, initAcc, arglists); - }); - - PRIMITIVES['foldr'] = - new PrimProc('foldr', - 3, - true, false, - function(f, initAcc, lst, arglists) { - arglists.unshift(lst); - var allArgs = [f, initAcc].concat(arglists); - check(f, isFunction, 'foldr', 'procedure', 1, allArgs); - arrayEach(arglists, function(x, i) {checkList(x, 'foldr', i+3, allArgs);}); - checkAllSameLength(arglists, 'foldr', allArgs); - - for (var i = 0; i < arglists.length; i++) { - arglists[i] = arglists[i].reverse(); - } - - return foldHelp(f, initAcc, arglists); - }); - - - PRIMITIVES['quicksort'] = new PrimProc('quicksort', 2, false, false, quicksort('quicksort')); - PRIMITIVES['sort'] = new PrimProc('sort', 2, false, false, quicksort('sort')); - - - - PRIMITIVES['argmax'] = - new PrimProc('argmax', - 2, - false, false, - function(f, initList) { - var args = arguments - check(f, isFunction, 'argmax', 'procedure', 1, args); - check(initList, isPair, 'argmax', 'non-empty list', 2, args); - - var argmaxHelp = function(lst, curMaxVal, curMaxElt) { - if ( lst.isEmpty() ) { - return curMaxElt; - } - - return CALL(f, [lst.first], - function(result) { - check(result, isReal, 'argmax', - 'procedure that returns real numbers', 1, args); - if (jsnums.greaterThan(result, curMaxVal)) { - return argmaxHelp(lst.rest, result, lst.first); - } - else { - return argmaxHelp(lst.rest, curMaxVal, curMaxElt); - } - }); - } - return CALL(f, [initList.first], - function(result) { - check(result, isReal, 'argmax', 'procedure that returns real numbers', 1, args); - return argmaxHelp(initList.rest, result, initList.first); - }); - }); - - - PRIMITIVES['argmin'] = - new PrimProc('argmin', - 2, - false, false, - function(f, initList) { - var args = arguments; - check(f, isFunction, 'argmin', 'procedure', 1, args); - check(initList, isPair, 'argmin', 'non-empty list', 2, args); - - var argminHelp = function(lst, curMaxVal, curMaxElt) { - if ( lst.isEmpty() ) { - return curMaxElt; - } - - return CALL(f, [lst.first], - function(result) { - check(result, isReal, 'argmin', - 'procedure that returns real numbers', 1, args); - if (jsnums.lessThan(result, curMaxVal)) { - return argminHelp(lst.rest, result, lst.first); - } - else { - return argminHelp(lst.rest, curMaxVal, curMaxElt); - } - }); - } - return CALL(f, [initList.first], - function(result) { - check(result, isReal, 'argmin', 'procedure that returns real numbers', 1, args); - return argminHelp(initList.rest, result, initList.first); - }); - }); - - - PRIMITIVES['build-list'] = - new PrimProc('build-list', - 2, - false, false, - function(num, f) { - check(num, isNatural, 'build-list', 'non-negative exact integer', 1, arguments); - check(f, isFunction, 'build-list', 'procedure', 2, arguments); - - var buildListHelp = function(n, acc) { - if ( jsnums.greaterThanOrEqual(n, num) ) { - return acc.reverse(); - } - - return CALL(f, [n], - function (result) { - return buildListHelp(n+1, types.cons(result, acc)); - }); - } - return buildListHelp(0, types.EMPTY); - }); - - - /********************** - *** Box Primitives *** - **********************/ - - - PRIMITIVES['box'] = new PrimProc('box', 1, false, false, types.box); - - PRIMITIVES['box-immutable'] = new PrimProc('box-immutable', 1, false, false, types.boxImmutable); - - PRIMITIVES['unbox'] = - new PrimProc('unbox', - 1, - false, false, - function(box) { - check(box, isBox, 'unbox', 'box', 1); - return box.ref(); - }); - - - PRIMITIVES['set-box!'] = - new PrimProc('set-box!', - 2, - false, false, - function(box, newVal) { - check(box, function(x) { return isBox(x) && x.mutable; }, 'set-box!', 'mutable box', 1, arguments); - box.set(newVal); - return types.VOID; - }); - - - - /**************************** - *** Hashtable Primitives *** - ****************************/ - - - PRIMITIVES['make-hash'] = - new CasePrimitive('make-hash', - [new PrimProc('make-hash', 0, false, false, function() { return types.hash(types.EMPTY); }), - new PrimProc('make-hash', - 1, - false, false, - function(lst) { - checkListOf(lst, isPair, 'make-hash', 'list of pairs', 1); - return types.hash(lst); - }) ]); - - PRIMITIVES['make-hasheq'] = - new CasePrimitive('make-hasheq', - [new PrimProc('make-hasheq', 0, false, false, function() { return types.hashEq(types.EMPTY); }), - new PrimProc('make-hasheq', - 1, - false, false, - function(lst) { - checkListOf(lst, isPair, 'make-hasheq', 'list of pairs', 1); - return types.hashEq(lst); - }) ]); - - PRIMITIVES['hash-set!'] = - new PrimProc('hash-set!', - 3, - false, false, - function(obj, key, val) { - check(obj, isHash, 'hash-set!', 'hash', 1, arguments); - obj.hash.put(key, val); - return types.VOID; - }); - - PRIMITIVES['hash-ref'] = - new CasePrimitive('hash-ref', - [new PrimProc('hash-ref', - 2, - false, false, - function(obj, key) { - check(obj, isHash, 'hash-ref', 'hash', 1, arguments); - - if ( !obj.hash.containsKey(key) ) { - var msg = 'hash-ref: no value found for key: ' + helpers.toDisplayedString(key); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - return obj.hash.get(key); - }), - new PrimProc('hash-ref', - 3, - false, false, - function(obj, key, defaultVal) { - check(obj, isHash, 'hash-ref', 'hash', 1, arguments); - - if (obj.hash.containsKey(key)) { - return obj.hash.get(key); - } - else { - if (isFunction(defaultVal)) { - return CALL(defaultVal, [], id); - } - return defaultVal; - } - }) ]); - - PRIMITIVES['hash-remove!'] = - new PrimProc('hash-remove', - 2, - false, false, - function(obj, key) { - check(obj, isHash, 'hash-remove!', 'hash', 1, arguments); - obj.hash.remove(key); - return types.VOID; - }); - - PRIMITIVES['hash-map'] = - new PrimProc('hash-map', - 2, - false, false, - function(ht, f) { - check(ht, isHash, 'hash-map', 'hash', 1, arguments); - check(f, isFunction, 'hash-map', 'procedure', 2, arguments); - - var keys = ht.hash.keys(); - var hashMapHelp = function(i, acc) { - if (i >= keys.length) { - return acc; - } - - var val = ht.hash.get(keys[i]); - return CALL(f, [keys[i], val], - function(result) { - return hashMapHelp(i+1, types.cons(result, acc)); - }); - } - return hashMapHelp(0, types.EMPTY); - }); - - - PRIMITIVES['hash-for-each'] = - new PrimProc('hash-for-each', - 2, - false, false, - function(ht, f) { - check(ht, isHash, 'hash-for-each', 'hash', 1, arguments); - check(f, isFunction, 'hash-for-each', 'procedure', 2, arguments); - - var keys = ht.hash.keys(); - var hashForEachHelp = function(i) { - if (i >= keys.length) { - return types.VOID; - } - - var val = ht.hash.get(keys[i]); - return CALL(f, [keys[i], val], - function(result) { - return hashForEachHelp(i+1); - }); - } - return hashForEachHelp(0); - }); - - - - /************************* - *** String Primitives *** - *************************/ - - - var makeStringImpl = function(n, c) { - check(n, isNatural, 'make-string', 'non-negative exact integer', 1, arguments); - check(c, isChar, 'make-string', 'char', 2, arguments); - var ret = []; - for (var i = 0; jsnums.lessThan(i, n); i++) { - ret.push(c.val); - } - return types.string(ret); - }; - - PRIMITIVES['make-string'] = - new CasePrimitive( - 'make-string', - [new PrimProc('make-string', - 2, - false, false, - makeStringImpl), - new PrimProc('make-string', - 1, - false, false, - function(n) { - return makeStringImpl(n, types.character(String.fromCharCode(0))); - })]); - - - - PRIMITIVES['replicate'] = - new PrimProc('replicate', - 2, - false, false, - function(n, str) { - check(n, isNatural, 'replicate', 'non-negative exact integer', 1, arguments); - check(str, isString, 'replicate', 'string', 2, arguments); - - var ret = ""; - var primStr = str.toString(); - for (var i = 0; jsnums.lessThan(i, n); i++) { - ret += primStr; - } - return types.string(ret); - }); - - - PRIMITIVES['string'] = - new PrimProc('string', - 0, - true, false, - function(chars) { - arrayEach(chars, function(c, i) {check(c, isChar, 'string', 'char', i+1, chars);}); - - var ret = []; - for (var i = 0; i < chars.length; i++) { - ret.push(chars[i].val); - } - return types.string(ret); - }); - - - PRIMITIVES['string-length'] = - new PrimProc('string-length', 1, false, false, - function(str) { - check(str, isString, 'string-length', 'string', 1); - return str.toString().length; - }); - - - PRIMITIVES['string-ref'] = - new PrimProc('string-ref', - 2, - false, false, - function(str, num) { - check(str, isString, 'string-ref', 'string', 1, arguments); - check(num, isNatural, 'string-ref', 'non-negative exact integer', 2, arguments); - - str = str.toString(); - var n = jsnums.toFixnum(num); - if (n >= str.length) { - var msg = ('string-ref: index ' + n + ' out of range ' + - '[0, ' + (str.length-1) + '] for string: ' + - helpers.toDisplayedString(str)); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - return types.character(str.charAt(n)); - }); - - - PRIMITIVES['string=?'] = - new PrimProc('string=?', - 2, - true, false, - function(str1, str2, strs) { - strs.unshift(str2); - strs.unshift(str1); - arrayEach(strs, function(str, i) {check(str, isString, 'string=?', 'string', i+1, strs);}); - - return compare(strs, function(strA, strB) {return strA.toString() === strB.toString();}); - }); - - - PRIMITIVES['string-ci=?'] = - new PrimProc('string-ci=?', - 2, - true, false, - function(str1, str2, strs) { - strs.unshift(str2); - strs.unshift(str1); - - for(var i = 0; i < strs.length; i++) { - check(strs[i], isString, 'string-ci=?', 'string', i+1, strs); - strs[i] = strs[i].toString().toLowerCase(); - } - - return compare(strs, function(strA, strB) {return strA === strB;}); - }); - - - PRIMITIVES['string?'] = - new PrimProc('string>?', - 2, - true, false, - function(str1, str2, strs) { - strs.unshift(str2); - strs.unshift(str1); - arrayEach(strs, function(str, i) {check(str, isString, 'string>?', 'string', i+1, strs);}); - - return compare(strs, function(strA, strB) {return strA.toString() > strB.toString();}); - }); - - - PRIMITIVES['string<=?'] = - new PrimProc('string<=?', - 2, - true, false, - function(str1, str2, strs) { - strs.unshift(str2); - strs.unshift(str1); - arrayEach(strs, function(str, i) {check(str, isString, 'string<=?', 'string', i+1, strs);}); - - return compare(strs, function(strA, strB) {return strA.toString() <= strB.toString();}); - }); - - - PRIMITIVES['string>=?'] = - new PrimProc('string>=?', - 2, - true, false, - function(str1, str2, strs) { - strs.unshift(str2); - strs.unshift(str1); - arrayEach(strs, function(str, i) {check(str, isString, 'string>=?', 'string', i+1, strs);}); - - return compare(strs, function(strA, strB) {return strA.toString() >= strB.toString();}); - }); - - - PRIMITIVES['string-ci?'] = - new PrimProc('string-ci>?', - 2, - true, false, - function(str1, str2, strs) { - strs.unshift(str2); - strs.unshift(str1); - - for (var i = 0; i < strs.length; i++) { - check(strs[i], isString, 'string-ci>?', 'string', i+1, strs); - strs[i] = strs[i].toString().toLowerCase(); - } - - return compare(strs, function(strA, strB) {return strA > strB;}); - }); - - - PRIMITIVES['string-ci<=?'] = - new PrimProc('string-ci<=?', - 2, - true, false, - function(str1, str2, strs) { - strs.unshift(str2); - strs.unshift(str1); - - for (var i = 0; i < strs.length; i++) { - check(strs[i], isString, 'string-ci<=?', 'string', i+1, strs); - strs[i] = strs[i].toString().toLowerCase(); - } - - return compare(strs, function(strA, strB) {return strA <= strB;}); - }); - - - PRIMITIVES['string-ci>=?'] = - new PrimProc('string-ci>=?', - 2, - true, false, - function(str1, str2, strs) { - strs.unshift(str2); - strs.unshift(str1); - - for (var i = 0; i < strs.length; i++) { - check(strs[i], isString, 'string-ci>=?', 'string', i+1, strs); - strs[i] = strs[i].toString().toLowerCase(); - } - - return compare(strs, function(strA, strB) {return strA >= strB;}); - }); - - - PRIMITIVES['substring'] = - new CasePrimitive('substring', - [new PrimProc('substring', - 2, - false, false, - function(str, theStart) { - check(str, isString, 'substring', 'string', 1, arguments); - check(theStart, isNatural, 'substring', 'non-negative exact integer', 2, arguments); - str = str.toString(); - var start = jsnums.toFixnum(theStart); - if (start > str.length) { - var msg = ('substring: starting index ' + start + ' out of range ' + - '[0, ' + str.length + '] for string: ' + helpers.toDisplayedString(str)); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - else { - return types.string( str.substring(jsnums.toFixnum(start)) ); - } - }), - new PrimProc('substring', - 3, - false, false, - function(str, theStart, theEnd) { - check(str, isString, 'substring', 'string', 1, arguments); - check(theStart, isNatural, 'substring', 'non-negative exact integer', 2, arguments); - check(theEnd, isNatural, 'substring', 'non-negative exact integer', 3, arguments); - str = str.toString(); - var start = jsnums.toFixnum(theStart); - var end = jsnums.toFixnum(theEnd); - if (start > str.length) { - var msg = ('substring: starting index ' + start + ' out of range ' + - '[0, ' + str.length + '] for string: ' + helpers.toDisplayedString(str)); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - if (end < start || end > str.length) { - var msg = ('substring: ending index ' + end + ' out of range ' + '[' + start + - ', ' + str.length + '] for string: ' + helpers.toDisplayedString(str)); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - return types.string( str.substring(start, end) ); - }) ]); - - - PRIMITIVES['string-append'] = - new PrimProc("string-append", - 0, - true, false, - function(args) { - arrayEach(args, - function(str, i) { - check(str, isString, 'string-append', 'string', i+1, args); - }); - - for (var i = 0; i < args.length; i++) { - args[i] = args[i].toString(); - } - return types.string(args.join("")); - }); - - - PRIMITIVES['string->list'] = - new PrimProc('string->list', - 1, - false, false, - function(str) { - check(str, isString, 'string->list', 'string', 1); - str = str.toString(); - var lst = types.EMPTY; - for (var i = str.length-1; i >= 0; i--) { - lst = types.cons(types.character(str.charAt(i)), lst); - } - return lst; - }); - - - PRIMITIVES['list->string'] = - new PrimProc('list->string', - 1, - false, false, - function(lst) { - checkListOf(lst, isChar, 'list->string', 'char', 1); - - var ret = []; - while( !lst.isEmpty() ) { - ret.push(lst.first.val); - lst = lst.rest; - } - return types.string(ret); - }); - - - PRIMITIVES['string-copy'] = - new PrimProc('string-copy', - 1, - false, false, - function(str) { - check(str, isString, 'string-copy', 'string', 1); - return types.string(str.toString()); - }); - - - - PRIMITIVES['string->symbol'] = - new PrimProc('string->symbol', - 1, - false, false, - function(str) { - check(str, isString, 'string->symbol', 'string', 1); - return types.symbol(str.toString()); - }); - - - PRIMITIVES['symbol->string'] = - new PrimProc('symbol->string', - 1, - false, false, - function(symb) { - check(symb, isSymbol, 'symbol->string', 'symbol', 1); - return types.string(symb.toString()); - }); - - - PRIMITIVES['format'] = - new PrimProc('format', 1, true, false, - function(formatStr, args) { - check(formatStr, isString, 'format', 'string', 1, [formatStr].concat(args)); - formatStr = formatStr.toString(); - return types.string( helpers.format(formatStr, args, 'format') ); - }); - - - PRIMITIVES['printf'] = - new PrimProc('printf', 1, true, true, - function(state, formatStr, args) { - check(formatStr, isString, 'printf', 'string', 1, [formatStr].concat(args)); - formatStr = formatStr.toString(); - var msg = helpers.format(formatStr, args, 'printf'); - state.getDisplayHook()(msg); - state.v = types.VOID; - }); - - - PRIMITIVES['string->int'] = - new PrimProc('string->int', - 1, - false, false, - function(str) { - check(str, function(s) {return isString(s) && s.length == 1;}, - 'string->int', '1-letter string', 1); - str = str.toString(); - return str.charCodeAt(0); - }); - - - PRIMITIVES['int->string'] = - new PrimProc('int->string', - 1, - false, false, - function(num) { - check(num, function(x) { - if ( !isInteger(x) ) { - return false; - } - var n = jsnums.toFixnum(x); - return ((n >= 0 && n < 55296) || - (n > 57343 && n <= 1114111)); - }, - 'int->string', - 'exact integer in [0,55295] or [57344,1114111]', - 1); - - return types.string( String.fromCharCode(jsnums.toFixnum(num)) ); - }); - - - PRIMITIVES['explode'] = - new PrimProc('explode', - 1, - false, false, - function(str) { - check(str, isString, 'explode', 'string', 1); - str = str.toString(); - var ret = types.EMPTY; - for (var i = str.length-1; i >= 0; i--) { - ret = types.cons( types.string(str.charAt(i)), ret ); - } - return ret; - }); - - PRIMITIVES['implode'] = - new PrimProc('implode', - 1, - false, false, - function(lst) { - checkListOf(lst, function(x) { return isString(x) && x.length == 1; }, - 'implode', 'list of 1-letter strings', 1); - var ret = []; - while ( !lst.isEmpty() ) { - ret.push( lst.first.toString() ); - lst = lst.rest; - } - return types.string(ret); - }); - - - PRIMITIVES['string-alphabetic?'] = - new PrimProc('string-alphabetic?', - 1, - false, false, - function(str) { - check(str, isString, 'string-alphabetic?', 'string', 1); - str = str.toString(); - return isAlphabeticString(str); - }); - - - PRIMITIVES['string-ith'] = - new PrimProc('string-ith', - 2, - false, false, - function(str, num) { - check(str, isString, 'string-ith', 'string', 1, arguments); - check(num, function(x) { return isNatural(x) && jsnums.lessThan(x, str.length); }, 'string-ith', - 'exact integer in [0, length of the given string minus 1 (' + (str.length-1) + ')]', 2, arguments); - str = str.toString(); - return types.string( str.charAt(jsnums.toFixnum(num)) ); - }); - - - PRIMITIVES['string-lower-case?'] = - new PrimProc('string-lower-case?', - 1, - false, false, - function(str) { - check(str, isString, 'string-lower-case?', 'string', 1); - var primStr = str.toString(); - return isAlphabeticString(str) && primStr.toLowerCase() === primStr; - }); - - - PRIMITIVES['string-numeric?'] = - new PrimProc('string-numeric?', - 1, - false, false, - function(str) { - check(str, isString, 'string-numeric?', 'string', 1); - str = str.toString(); - return isNumericString(str); - }); - - - PRIMITIVES['string-upper-case?'] = - new PrimProc('string-upper-case?', - 1, - false, false, - function(str) { - check(str, isString, 'string-upper-case?', 'string', 1); - var primStr = str.toString(); - return isAlphabeticString(str) && primStr.toUpperCase() === primStr; - }); - - - PRIMITIVES['string-whitespace?'] = - new PrimProc('string-whitespace?', - 1, - false, false, - function(str) { - check(str, isString, 'string-whitespace?', 'string', 1); - str = str.toString(); - return isWhitespaceString(str); - }); - - - PRIMITIVES['build-string'] = - new PrimProc('build-string', - 2, - false, false, - function(num, f) { - check(num, isNatural, 'build-string', 'non-negative exact integer', 1, arguments); - check(f, isFunction, 'build-string', 'procedure', 2, arguments); - - var buildStringHelp = function(n, acc) { - if ( jsnums.greaterThanOrEqual(n, num) ) { - return types.string(acc); - } - - return CALL(f, [n], - function(res) { - check(res, isChar, 'build-string', - 'procedure that returns a char', 2); - acc.push(res.val) - return buildStringHelp(n+1, acc); - }); - } - return buildStringHelp(0, []); - }); - - - PRIMITIVES['string->immutable-string'] = - new PrimProc('string->immutable-string', - 1, - false, false, - function(str) { - check(str, isString, 'string->immutable-string', 'string', 1); - return str.toString(); - }); - - - PRIMITIVES['string-set!'] = - new PrimProc('string-set!', - 3, - false, false, - function(str, k, c) { - check(str, function(x) { return isMutableString(x); }, - 'string-set!', 'mutable string', 1, arguments); - check(k, isNatural, 'string-set!', 'non-negative exact integer', 2, arguments); - check(c, isChar, 'string-set!', 'char', 3, arguments); - - if ( jsnums.greaterThanOrEqual(k, str.length) ) { - var msg = ('string-set!: index ' + k + ' out of range ' + - '[0, ' + (str.length-1) + '] for string: ' + - helpers.toDisplayedString(str)); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - str.set(jsnums.toFixnum(k), c.val); - return types.VOID; - }); - - - PRIMITIVES['string-fill!'] = - new PrimProc('string-fill!', - 2, - false, false, - function(str, c) { - check(str, function(x) { return isMutableString(x); }, - 'string-fill!', 'mutable string', 1, arguments); - check(c, isChar, 'string-fill!', 'char', 2, arguments); - - for (var i = 0; i < str.length; i++) { - str.set(i, c.val); - } - return types.VOID; - }); - - - - ////////////////////////////////////////////////////////////////////// - // Immutable cyclic data - PRIMITIVES['make-reader-graph'] = - new PrimProc('make-reader-graph', 1, false, false, - function(x) { - var result = types.readerGraph(x, types.makeLowLevelEqHash(), 0); - return result; - }); - - - PRIMITIVES['make-placeholder'] = - new PrimProc('make-placeholder', 1, false, false, - function(x) { return types.placeholder(x); }); - - - PRIMITIVES['placeholder-set!'] = - new PrimProc('placeholder-set!', 2, false, false, - function(pl, x) { - check(pl, types.isPlaceholder, - "placeholder-set!", "placeholder", 1); - pl.set(x); - return types.VOID; - }); - - PRIMITIVES['placeholder-get'] = - new PrimProc('placeholder-get', 1, false, false, - function(pl) { - check(pl, types.isPlaceholder, - "placeholder-get", "placeholder", 1); - return pl.get(); - }); - - - - - ////////////////////////////////////////////////////////////////////// - - - - - /****************************** - *** Byte String Primitives *** - ******************************/ - - - PRIMITIVES['make-bytes'] = - new CasePrimitive('make-bytes', - [new PrimProc('make-bytes', - 1, - false, false, - function(k) { - check(k, isNatural, 'make-bytes', 'non-negative exact integer', 1); - - var ret = []; - for (var i = 0; i < jsnums.toFixnum(k); i++) { - ret.push(0); - } - return types.bytes(ret, true); - }), - new PrimProc('make-bytes', - 2, - false, false, - function(k, b) { - check(k, isNatural, 'make-bytes', 'non-negative exact integer', 1, arguments); - check(b, isByte, 'make-bytes', 'byte', 2, arguments); - - var ret = []; - for (var i = 0; i < jsnums.toFixnum(k); i++) { - ret.push(b); - } - return types.bytes(ret, true); - }) ]); - - - PRIMITIVES['bytes'] = - new PrimProc('bytes', - 0, - true, false, - function(args) { - arrayEach(args, function(b, i) {check(b, isByte, 'bytes', 'byte', i+1, args);}); - return types.bytes(args, true); - }); - - - PRIMITIVES['bytes->immutable-bytes'] = - new PrimProc('bytes->immutable-bytes', - 1, - false, false, - function(bstr) { - check(bstr, isByteString, 'bytes->immutable-bytes', 'byte string', 1); - if ( bstr.mutable ) { - return bstr.copy(false); - } - else { - return bstr; - } - }); - - - PRIMITIVES['bytes-length'] = - new PrimProc('bytes-length', - 1, - false, false, - function(bstr) { - check(bstr, isByteString, 'bytes-length', 'byte string', 1); - return bstr.length(); - }); - - - PRIMITIVES['bytes-ref'] = - new PrimProc('bytes-ref', - 2, - false, false, - function(bstr, num) { - check(bstr, isByteString, 'bytes-ref', 'byte string', 1, arguments); - check(num, isNatural, 'bytes-ref', 'non-negative exact integer', 2, arguments); - - var n = jsnums.toFixnum(num); - if ( n >= bstr.length() ) { - var msg = ('bytes-ref: index ' + n + ' out of range ' + - '[0, ' + (bstr.length-1) + '] for byte-string: ' + - helpers.toDisplayedString(bstr)); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - return bstr.get(n); - }); - - - PRIMITIVES['bytes-set!'] = - new PrimProc('bytes-set!', - 3, - false, false, - function(bstr, num, b) { - check(bstr, function(x) { return isByteString(x) && x.mutable; }, - 'bytes-set!', 'mutable byte string', 1, arguments); - check(num, isNatural, 'bytes-set!', 'non-negative exact integer', 2, arguments); - check(b, isByte, 'bytes-set!', 'byte', 3, arguments); - - var n = jsnums.toFixnum(num); - if ( n >= bstr.length() ) { - var msg = ('bytes-set!: index ' + n + ' out of range ' + - '[0, ' + (bstr.length-1) + '] for byte-string: ' + - helpers.toDisplayedString(bstr)); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - bstr.set(n, b); - return types.VOID; - }); - - - PRIMITIVES['subbytes'] = - new CasePrimitive('subbytes', - [new PrimProc('subbytes', - 2, - false, false, - function(bstr, theStart) { - check(bstr, isByteString, 'subbytes', 'bytes string', 1, arguments); - check(theStart, isNatural, 'subbytes', 'non-negative exact integer', 2, arguments); - - var start = jsnums.toFixnum(theStart); - if (start > bstr.length()) { - var msg = ('subbytes: starting index ' + start + ' out of range ' + - '[0, ' + bstr.length + '] for byte-string: ' + - helpers.toDisplayedString(bstr)); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - else { - return bstr.subbytes(jsnums.toFixnum(start)); - } - }), - new PrimProc('subbytes', - 3, - false, false, - function(bstr, theStart, theEnd) { - check(bstr, isByteString, 'subbytes', 'byte string', 1, arguments); - check(theStart, isNatural, 'subbytes', 'non-negative exact integer', 2, arguments); - check(theEnd, isNatural, 'subbytes', 'non-negative exact integer', 3, arguments); - - var start = jsnums.toFixnum(theStart); - var end = jsnums.toFixnum(theEnd); - if (start > bstr.length()) { - var msg = ('subbytes: starting index ' + start + ' out of range ' + - '[0, ' + bstr.length() + '] for byte-string: ' + - helpers.toDisplayedString(bstr)); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - if (end < start || end > bstr.length()) { - var msg = ('subbytes: ending index ' + end + ' out of range ' + '[' + start + - ', ' + bstr.length() + '] for byte-string: ' + - helpers.toDisplayedString(bstr)); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - else { - return bstr.subbytes(start, end); - } - }) ]); - - - PRIMITIVES['bytes-copy'] = - new PrimProc('bytes-copy', - 1, - false, false, - function(bstr) { - check(bstr, isByteString, 'bytes-copy', 'byte string', 1); - return bstr.copy(true); - }); - - - PRIMITIVES['bytes-fill!'] = - new PrimProc('bytes-fill!', - 2, - false, false, - function(bstr, b) { - check(bstr, function(x) { return isByteString(x) && x.mutable; }, - 'bytes-fill!', 'mutable byte string', 1, arguments); - check(b, isByte, 'bytes-fill!', 'byte', 2, arguments); - - for (var i = 0; i < bstr.length(); i++) { - bstr.set(i, b); - } - return types.VOID; - }); - - - PRIMITIVES['bytes-append'] = - new PrimProc('bytes-append', - 0, - true, false, - function(args) { - arrayEach(args, function(x, i) { check(x, isByteString, 'bytes-append', 'byte string', i+1, args); }); - - var ret = []; - for (var i = 0; i < args.length; i++) { - ret = ret.concat(args[i].bytes); - } - return types.bytes(ret, true); - }); - - - PRIMITIVES['bytes->list'] = - new PrimProc('bytes->list', - 1, - false, false, - function(bstr) { - check(bstr, isByteString, 'bytes->list', 'byte string', 1); - - var ret = types.EMPTY; - for (var i = bstr.length()-1; i >= 0; i--) { - ret = types.cons(bstr.get(i), ret); - } - return ret; - }); - - - PRIMITIVES['list->bytes'] = - new PrimProc('list->bytes', - 1, - false, false, - function(lst) { - checkListOf(lst, isByte, 'list->bytes', 'byte', 1); - - var ret = []; - while ( !lst.isEmpty() ) { - ret.push(lst.first); - lst = lst.rest; - } - return types.bytes(ret, true); - }); - - - PRIMITIVES['bytes=?'] = - new PrimProc('bytes=?', - 2, - true, false, - function(bstr1, bstr2, bstrs) { - bstrs.unshift(bstr2); - bstrs.unshift(bstr1); - arrayEach(bstrs, function(x, i) { check(x, isByteString, 'bytes=?', 'byte string', i+1, bstrs); }); - - return compare(bstrs, function(bstrA, bstrB) { return bstrA.toString() === bstrB.toString(); }); - }); - - - PRIMITIVES['bytes?'] = - new PrimProc('bytes>?', - 2, - true, false, - function(bstr1, bstr2, bstrs) { - bstrs.unshift(bstr2); - bstrs.unshift(bstr1); - arrayEach(bstrs, function(x, i) { check(x, isByteString, 'bytes>?', 'byte string', i+1, bstrs); }); - - return compare(bstrs, function(bstrA, bstrB) { return bstrA.toString() > bstrB.toString(); }); - }); - - - - - /************************* - *** Vector Primitives *** - *************************/ - - var makeVectorImpl = function(size, content) { - check(size, isNatural, 'make-vector', 'non-negative exact integer', 1, arguments); - var s = jsnums.toFixnum(size); - var ret = []; - for (var i = 0; i < s; i++) { - ret.push(content); - } - return types.vector(ret); - }; - - PRIMITIVES['make-vector'] = new CasePrimitive - ("make-vector", - [new PrimProc('make-vector', - 2, - false, false, - makeVectorImpl), - new PrimProc('make-vector', - 1, - false, false, - function(size) { return makeVectorImpl(size, jsnums.fromFixnum(0)); })]); - - - PRIMITIVES['vector'] = - new PrimProc('vector', - 0, - true, false, - function(args) { - return types.vector(args); - }); - - - PRIMITIVES['vector-length'] = - new PrimProc('vector-length', - 1, - false, false, - function(vec) { - check(vec, isVector, 'vector-length', 'vector', 1); - return vec.length(); - }); - - - PRIMITIVES['vector-ref'] = - new PrimProc('vector-ref', - 2, - false, false, - function(vec, index) { - check(vec, isVector, 'vector-ref', 'vector', 1, arguments); - check(index, isNatural, 'vector-ref', 'non-negative exact integer', 2, arguments); - - var i = jsnums.toFixnum(index); - if (i >= vec.length()) { - var msg = ('vector-ref: index ' + i + ' out of range ' + - '[0, ' + (vec.length()-1) + '] for vector: ' + - helpers.toDisplayedString(vec)); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - return vec.ref(i); - }); - - - PRIMITIVES['vector-set!'] = - new PrimProc('vector-set!', - 3, - false, false, - function(vec, index, val) { - check(vec, isVector, 'vector-set!', 'vector', 1, arguments); - check(index, isNatural, 'vector-set!', 'non-negative exact integer', 2, arguments); - - var i = jsnums.toFixnum(index); - if (i >= vec.length()) { - var msg = ('vector-set!: index ' + i + ' out of range ' + - '[0, ' + (vec.length()-1) + '] for vector: ' + - helpers.toDisplayedString(vec)); - raise( types.incompleteExn(types.exnFailContract, msg, []) ); - } - vec.set(i, val); - return types.VOID; - }); - - - PRIMITIVES['vector->list'] = - new PrimProc('vector->list', - 1, - false, false, - function(vec) { - check(vec, isVector, 'vector->list', 'vector', 1); - return vec.toList(); - }); - - - PRIMITIVES['list->vector'] = - new PrimProc('list->vector', - 1, - false, false, - function(lst) { - checkList(lst, 'list->vector', 1); - return types.vector( helpers.schemeListToArray(lst) ); - }); - - - PRIMITIVES['build-vector'] = - new PrimProc('build-vector', - 2, - false, false, - function(num, f) { - check(num, isNatural, 'build-vector', 'non-negative exact integer', 1, arguments); - check(f, isFunction, 'build-vector', 'procedure', 2, arguments); - - var buildVectorHelp = function(n, acc) { - if ( jsnums.greaterThanOrEqual(n, num) ) { - return types.vector(acc); - } - - return CALL(f, [n], - function (result) { - acc.push(result) - return buildVectorHelp(n+1, acc); - }); - } - return buildVectorHelp(0, []); - }); - - - - /*********************** - *** Char Primitives *** - ***********************/ - - - PRIMITIVES['char=?'] = - new PrimProc('char=?', - 2, - true, false, - function(char1, char2, chars) { - chars.unshift(char2); - chars.unshift(char1); - arrayEach(chars, function(c, i) {check(c, isChar, 'char=?', 'char', i+1, chars);}); - - return compare(chars, function(c1, c2) {return c1.val === c2.val;}); - }); - - - PRIMITIVES['char?'] = - new PrimProc('char>?', - 2, - true, false, - function(char1, char2, chars) { - chars.unshift(char2); - chars.unshift(char1); - arrayEach(chars, function(c, i) {check(c, isChar, 'char>?', 'char', i+1, chars);}); - - return compare(chars, function(c1, c2) {return c1.val > c2.val;}); - }); - - - PRIMITIVES['char<=?'] = - new PrimProc('char<=?', - 2, - true, false, - function(char1, char2, chars) { - chars.unshift(char2); - chars.unshift(char1); - arrayEach(chars, function(c, i) {check(c, isChar, 'char<=?', 'char', i+1, chars);}); - - return compare(chars, function(c1, c2) {return c1.val <= c2.val;}); - }); - - - PRIMITIVES['char>=?'] = - new PrimProc('char>=?', - 2, - true, false, - function(char1, char2, chars) { - chars.unshift(char2); - chars.unshift(char1); - arrayEach(chars, function(c, i) {check(c, isChar, 'char>=?', 'char', i+1, chars);}); - - return compare(chars, function(c1, c2) {return c1.val >= c2.val;}); - }); - - - PRIMITIVES['char-ci=?'] = - new PrimProc('char-ci=?', - 2, - true, false, - function(char1, char2, chars) { - chars.unshift(char2); - chars.unshift(char1); - arrayEach(chars, function(c, i) {check(c, isChar, 'char-ci=?', 'char', i+1, chars);}); - - return compare(chars, - function(c1, c2) { - return c1.val.toLowerCase() === c2.val.toLowerCase(); - }); - }); - - - PRIMITIVES['char-ci?'] = - new PrimProc('char-ci>?', - 2, - true, false, - function(char1, char2, chars) { - chars.unshift(char2); - chars.unshift(char1); - arrayEach(chars, function(c, i) {check(c, isChar, 'char-ci>?', 'char', i+1, chars);}); - - return compare(chars, - function(c1, c2) { - return c1.val.toLowerCase() > c2.val.toLowerCase(); - }); - }); - - - PRIMITIVES['char-ci<=?'] = - new PrimProc('char-ci<=?', - 2, - true, false, - function(char1, char2, chars) { - chars.unshift(char2); - chars.unshift(char1); - arrayEach(chars, function(c, i) {check(c, isChar, 'char-ci<=?', 'char', i+1, chars);}); - - return compare(chars, - function(c1, c2) { - return c1.val.toLowerCase() <= c2.val.toLowerCase(); - }); - }); - - - PRIMITIVES['char-ci>=?'] = - new PrimProc('char-ci>=?', - 2, - true, false, - function(char1, char2, chars) { - chars.unshift(char2); - chars.unshift(char1); - arrayEach(chars, function(c, i) {check(c, isChar, 'char-ci>=?', 'char', i+1, chars);}); - - return compare(chars, - function(c1, c2) { - return c1.val.toLowerCase() >= c2.val.toLowerCase(); - }); - }); - - - PRIMITIVES['char-alphabetic?'] = - new PrimProc('char-alphabetic?', - 1, - false, false, - function(c) { - check(c, isChar, 'char-alphabetic?', 'char', 1); - return isAlphabeticString(c.val); - }); - - - PRIMITIVES['char-numeric?'] = - new PrimProc('char-numeric?', - 1, - false, false, - function(c) { - check(c, isChar, 'char-numeric?', 'char', 1); - return (c.val >= '0' && c.val <= '9'); - }); - - - PRIMITIVES['char-whitespace?'] = - new PrimProc('char-whitespace?', - 1, - false, false, - function(c) { - check(c, isChar, 'char-whitespace?', 'char', 1); - return isWhitespaceString(c.val); - }); - - - PRIMITIVES['char-upper-case?'] = - new PrimProc('char-upper-case?', - 1, - false, false, - function(c) { - check(c, isChar, 'char-upper-case?', 'char', 1); - return (isAlphabeticString(c.val) && c.val.toUpperCase() === c.val); - }); - - - PRIMITIVES['char-lower-case?'] = - new PrimProc('char-lower-case?', - 1, - false, false, - function(c) { - check(c, isChar, 'char-lower-case?', 'char', 1); - return (isAlphabeticString(c.val) && c.val.toLowerCase() === c.val); - }); - - - PRIMITIVES['char->integer'] = - new PrimProc('char->integer', - 1, - false, false, - function(c) { - check(c, isChar, 'char->integer', 'char', 1); - return c.val.charCodeAt(0); - }); - - - PRIMITIVES['integer->char'] = - new PrimProc('integer->char', - 1, - false, false, - function(num) { - check(num, function(x) { - if ( !isNatural(x) ) { - return false; - } - var n = jsnums.toFixnum(x); - return ((n >= 0 && n < 55296) || - (n > 57343 && n <= 1114111)); - }, - 'integer->char', - 'exact integer in [0,#x10FFFF], not in [#xD800,#xDFFF]', - 1); - - return types.character( String.fromCharCode(jsnums.toFixnum(num)) ); - }); - - - PRIMITIVES['char-upcase'] = - new PrimProc('char-upcase', - 1, - false, false, - function(c) { - check(c, isChar, 'char-upcase', 'char', 1); - return types.character( c.val.toUpperCase() ); - }); - - - PRIMITIVES['char-downcase'] = - new PrimProc('char-downcase', - 1, - false, false, - function(c) { - check(c, isChar, 'char-downcase', 'char', 1); - return types.character( c.val.toLowerCase() ); - }); - - - - - - var callCCPrim = new types.PrimProc('call/cc', - 1, - false, true, - function(aState, f) { - var continuationClosure = - state.captureContinuationClosure(aState); - aState.pushValue(continuationClosure); - aState.v = f; - aState.pushControl( - new control.CallControl(1)); - }); - - PRIMITIVES['call/cc'] = callCCPrim; - PRIMITIVES['call-with-current-continuation'] = callCCPrim; - - - - - ////////////////////////////////////////////////////////////////////// - - - - - - - - - ////////////////////////////////////////////////////////////////////// - - var GENSYM_COUNTER = 0; - - var gensymImpl = function(x) { - check(x, - function(x) { return isString(x) || isSymbol(x) }, - 'gensym', 'symbol or string', - 1); - return types.symbol(x.toString() + '' + (GENSYM_COUNTER++)); - }; - - PRIMITIVES['gensym'] = - new CasePrimitive( - 'gensym', - [new PrimProc('gensym', - 1, - false, - false, - gensymImpl), - new PrimProc('gensym', - 0, - false, - false, - function() { return gensymImpl('g') })]); - - - - - - - - - - - - /*************************** - *** Primitive Constants *** - ***************************/ - - - PRIMITIVES['eof'] = types.EOF; - PRIMITIVES['e'] = jsnums.e; - PRIMITIVES['empty'] = types.EMPTY; - PRIMITIVES['false'] = false; - PRIMITIVES['true'] = true; - PRIMITIVES['pi'] = jsnums.pi; - PRIMITIVES['null'] = types.EMPTY; - - - - - - - ////////////////////////////////////////////////////////////////////// - /** Parameters **/ - var PARAMZ = {}; - - PARAMZ['exception-handler-key'] = types.exceptionHandlerKey; - - - - /////////////////////////////////////////////////////////////// - - // getPrimitive: string (string | undefined) -> scheme-value - primitives.getPrimitive = function(name, resolvedModuleName) { - if (resolvedModuleName === undefined) { - return PRIMITIVES[name]; - } - - if (resolvedModuleName === types.symbol("moby/kernel")) { - return PRIMITIVES[name]; - } - - if (resolvedModuleName === types.symbol("moby/paramz")) { - return PARAMZ[name]; - } - - if (types.isEqual(resolvedModuleName, - types.list([types.symbol("quote"), types.symbol("#%kernel")]))) { - return PRIMITIVES[name]; - } - - if (types.isEqual(resolvedModuleName, - types.list([types.symbol("quote"), types.symbol("#%paramz")]))) { - return PARAMZ[name]; - } - - // FIXME: if we get to this point, this should be treated as an internal error... - return PRIMITIVES[name]; - }; - - primitives.isPrimitive = function(x) { - return x instanceof PrimProc; - }; - - - - - - scope.link.announceReady('primitives'); -})(this['plt']); - diff --git a/js-assembler/runtime-src/types.js b/js-assembler/runtime-src/types.js deleted file mode 100644 index 1f23e82..0000000 --- a/js-assembler/runtime-src/types.js +++ /dev/null @@ -1,573 +0,0 @@ -// The definitions of the basic types in Whalesong. -// -// Note: this originally came from js-vm, and as a result, -// there's quite a lot of cruft and unused code in this module. -// I need to filter and rip out the values that aren't used in Whalesong. - - -if (! this['plt']) { this['plt'] = {}; } - -// FIXME: there's a circularity between this module and helpers, and that circularly -// should not be there! - - -(function (scope) { - ////////////////////////////////////////////////////////////////////// - var types = {}; - scope['types'] = types; - - - - - var getEqHashCode = plt.baselib.hashes.getEqHashCode; - // makeLowLevelEqHash: -> hashtable - // Constructs an eq hashtable that uses Moby's getEqHashCode function. - var makeLowLevelEqHash = plt.baselib.hashes.makeLowLevelEqHash; - var toWrittenString = plt.baselib.format.toWrittenString; - var toDisplayedString = plt.baselib.format.toDisplayedString; - var toDomNode = plt.baselib.format.toDomNode; - - - - var appendChild = function(parent, child) { - parent.appendChild(child); - }; - - - - - var Symbol = plt.baselib.symbols.Symbol; - var Empty = plt.baselib.lists.Empty; - var Cons = plt.baselib.lists.Cons; - - - - - - - - var isNumber = jsnums.isSchemeNumber; - - var isReal = jsnums.isReal; - var isRational = jsnums.isRational; - var isComplex = isNumber; - var isInteger = jsnums.isInteger; - - var isNatural = function(x) { - return (jsnums.isExact(x) && isInteger(x) - && jsnums.greaterThanOrEqual(x, 0)); - }; - var isNonNegativeReal = function(x) { - return isReal(x) && jsnums.greaterThanOrEqual(x, 0); - }; - - var isString = plt.baselib.strings.isString; - - var equals = plt.baselib.equality.equals; - - // isList: Any -> Boolean - // Returns true if x is a list (a chain of pairs terminated by EMPTY). - var isList = function(x) { - while (x !== Empty.EMPTY) { - if (x instanceof Cons){ - x = x.rest; - } else { - return false; - } - } - return true; - }; - - - var makeList = function() { - var result = Empty.EMPTY; - for(var i = arguments.length-1; i >= 0; i--) { - result = Cons.makeInstance(arguments[i], result); - } - return result; - }; - - - var makeVector = function() { - return Vector.makeInstance(arguments.length, arguments); - }; - - - var makeVectorImmutable = function() { - var v = Vector.makeInstance(arguments.length, arguments); - v.mutable = false; - return v; - }; - - - var makeString = function(s) { - if (s instanceof plt.baselib.strings.Str) { - return s; - } - else if (s instanceof Array) { - // for (var i = 0; i < s.length; i++) { - // if ( typeof s[i] !== 'string' || s[i].length != 1 ) { - // return undefined; - // } - // } - return plt.baselib.strings.Str.makeInstance(s); - } - else if (typeof s === 'string') { - return plt.baselib.strings.Str.fromString(s); - } - else { - throw types.internalError('makeString expects and array of 1-character strings or a string;' + - ' given ' + s.toString(), - false); - } - }; - - - var makeHashEq = function(lst) { - var newHash = new plt.baselib.hashes.EqHashTable(); - while ( !isEmpty(lst) ) { - newHash.hash.put(lst.first.first, lst.first.rest); - lst = lst.rest; - } - return newHash; - }; - - - var makeHashEqual = function(lst) { - var newHash = new plt.baselib.hashes.EqualHashTable(); - while ( !isEmpty(lst) ) { - newHash.hash.put(lst.first.first, lst.first.rest); - lst = lst.rest; - } - return newHash; - }; - - - var Color = plt.baselib.structs.makeStructureType( - 'color', false, 3, 0, false, false); - - - - - - - ////////////////////////////////////////////////////////////////////// - -// var JsValue = function(name, val) { -// this.name = name; -// this.val = val; -// }; - -// JsValue.prototype.toString = function() { -// return '#'; -// }; - -// JsValue.prototype.toDomNode = function(cache) { -// return toDomNode(this.val, cache); -// }; - -// JsValue.prototype.equals = function(other, aUnionFind) { -// return (this.val === other.val); -// }; - -// // unbox: jsvalue -> any -// // Unwraps the value out of the JsValue box. -// JsValue.prototype.unbox = function() { -// return this.val; -// }; - - - -// var WrappedSchemeValue = function(val) { -// this.val = val; -// }; - -// WrappedSchemeValue.prototype.toString = function() { return toString(this.val); }; -// WrappedSchemeValue.prototype.toWrittenString = function(cache) { return toWrittenString(this.val, cache); }; -// WrappedSchemeValue.prototype.toDisplayedString = function(cache) { return toDisplayedString(this.val, cache); }; - - -// // unbox: jsvalue -> any -// // Unwraps the value out of the WrappedSchemeValue box. -// WrappedSchemeValue.prototype.unbox = function() { -// return this.val; -// }; - - - ////////////////////////////////////////////////////////////////////// - -// var WorldConfig = function(startup, shutdown, startupArgs) { -// this.startup = startup; -// this.shutdown = shutdown; -// this.startupArgs = startupArgs; -// }; - -// WorldConfig.prototype.toString = function() { -// return '#'; -// }; - -// WorldConfig.prototype.equals = function(other, aUnionFind) { -// return ( equals(this.startup, other.startup, aUnionFind) && -// equals(this.shutdown, other.shutdown, aUnionFind) && -// equals(this.shutdownArg, other.shutdownArg, aUnionFind) && -// equals(this.restartArg, other.restartArg, aUnionFind) ); -// }; - - -// var Effect = plt.baselib.structs.makeStructureType('effect', false, 0, 0, false, false); -// Effect.type.prototype.invokeEffect = function() { -// helpers.raise(types.incompleteExn( -// types.exnFail, -// 'effect type created without using make-effect-type', -// [])); -// }; - - -// var makeEffectType = function(name, superType, initFieldCnt, impl, guard) { -// if ( !superType ) { -// superType = Effect; -// } - -// var newType = plt.baselib.structs.makeStructureType(name, superType, initFieldCnt, 0, false, guard); -// var lastFieldIndex = newType.firstField + newType.numberOfFields; - -// newType.type.prototype.invokeEffect = function(aBigBang, k) { -// var schemeChangeWorld = new PrimProc('update-world', 1, false, false, -// function(worldUpdater) { -// //helpers.check(worldUpdater, helpers.procArityContains(1), -// // 'update-world', 'procedure (arity 1)', 1); - -// return new INTERNAL_PAUSE( -// function(caller, onSuccess, onFail) { -// aBigBang.changeWorld(function(w, k2) { -// caller(worldUpdater, -// [w], k2, -// function(e) { throw e; }, -// 'change-world (effect)'); -// }, -// function() { onSuccess(VOID_VALUE, 'restarting (change-world (effect))'); }); -// }); -// }); - -// var args = this._fields.slice(0, lastFieldIndex); -// args.unshift(schemeChangeWorld); -// return aBigBang.caller(impl, args, k, function(e) { throw e; }, 'invoking effect ' + name); -// } - -// return newType; -// }; - - -// var RenderEffect = plt.baselib.structs.makeStructureType('render-effect', false, 0, 0, false, false); -// RenderEffect.type.prototype.callImplementation = function(caller, k) { -// helpers.raise(types.incompleteExn( -// types.exnFail, -// 'render effect created without using make-render-effect-type', -// [])); -// }; - -// var makeRenderEffectType = function(name, superType, initFieldCnt, impl, guard) { -// if ( !superType ) { -// superType = RenderEffect; -// } - -// var newType = plt.baselib.structs.makeStructureType(name, superType, initFieldCnt, 0, false, guard); -// var lastFieldIndex = newType.firstField + newType.numberOfFields; - -// newType.type.prototype.callImplementation = function(caller, k) { -// var args = this._fields.slice(0, lastFieldIndex); -// caller(impl, args, k); -// } - -// return newType; -// }; - - ////////////////////////////////////////////////////////////////////// - - - - - - - - - - ////////////////////////////////////////////////////////////////////// - - - - - - ////////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////////////////////////// - -// var makeOptionPrimitive = function(name, -// numArgs, -// defaultVals, -// usesState, -// bodyF) { -// var makeNthPrimitive = function(n) { -// return new PrimProc(name, -// numArgs + n, -// false, -// usesState, -// function() { -// var expectedNumArgs = numArgs + n + (usesState ? 1 : 0); -// assert.equal(arguments.length, -// expectedNumArgs); -// var args = [arguments]; -// for (var i = 0; i < arguments.length; i++) { -// args.push(arguments[i]); -// } -// var startDefaults = i - numArgs - (usesState ? 1 : 0); -// return bodyF.apply( -// bodyF, -// args.concat(defaultVals.slice(startDefaults))); -// }); -// }; - -// var cases = []; -// for (var i = 0; i <= defaultVals.length; i++) { -// cases.push(makeNthPrimitive(i)); -// } -// return new CasePrimitive(name, cases); -// }; - - - - - - - - - - - - - ////////////////////////////////////////////////////////////////////// - - - // INTERNAL_CALL - // used for interaction between the Primitives and the interpreter (callPrimitiveProcedure). - // Don't confuse this with CallControl. -// var INTERNAL_CALL = function(operator, operands, k) { -// this.operator = operator; -// this.operands = operands; -// this.k = k; -// }; - -// // INTERNAL_PAUSE -// // used for interaction between the Primitive functions and the -// // interpreter. -// // Halts the interpreter, but passing onPause the functions necessary -// // to restart computation. -// var INTERNAL_PAUSE = function(onPause) { -// this.onPause = onPause; -// }; - - - - ////////////////////////////////////////////////////////////////////// - - -// // ContinuationPromptTag: symbol | false -> ContinuationPromptTag -// var ContinuationPromptTag = function(sym) { -// this.sym = sym; -// }; - -// var defaultContinuationPromptTag = new ContinuationPromptTag(); - -// var defaultContinuationPromptTagHandler = new PrimProc( -// 'default-continuation-prompt-tag-handler', -// 1, -// false, -// true, -// function(aState, thunk) { -// aState.pushControl( -// new control.ApplicationControl( -// new control.ConstantControl(thunk), -// [])); -// }); - - - ////////////////////////////////////////////////////////////////////// - - - - - - - - - ////////////////////////////////////////////////////////////////////// - // Exports - - - - types.symbol = Symbol.makeInstance; - types.rational = jsnums.makeRational; - types.floatpoint = jsnums.makeFloat; - types.complex = jsnums.makeComplex; - types.bignum = jsnums.makeBignum; - types.list = makeList; - types.vector = makeVector; - types.vectorImmutable = makeVectorImmutable; - types.regexp = function(p) { return new plt.baselib.regexps.RegularExpression(p) ; } - types.byteRegexp = function(p) { return new plt.baselib.regexps.ByteRegularExpression(p) ; } - types.character = plt.baselib.chars.Char.makeInstance; - types['string'] = makeString; - types.placeholder = function(x) { return new plt.baselib.placeholders.Placeholder(x); }; - types.box = function(x) { return new plt.baselib.boxes.Box(x, true); }; - types.boxImmutable = function(x) { return new plt.baselib.boxes.Box(x, false); }; - types.path = function(x) { return new plt.baselib.paths.Path(x); }; - types.bytes = function(x, mutable) { return new plt.baselib.bytes.Bytes(x, mutable); }; - types.bytesImmutable = function(x) { return new plt.baselib.bytes.Bytes(x, false); }; - types.keyword = function(k) { return new plt.baselib.keywords.Keyword(k); }; - types.pair = function(x, y) { return plt.baselib.lists.Cons.makeInstance(x, y); }; - types.hash = makeHashEqual; - types.hashEq = makeHashEq; -// types.jsValue = function(name, val) { return new JsValue(name, val); }; -// types.wrappedSchemeValue = function(val) { return new WrappedSchemeValue(val); }; - - - types.color = Color.constructor; - types.colorRed = function(x) { return Color.accessor(x, 0); }; - types.colorGreen = function(x) { return Color.accessor(x, 1); }; - types.colorBlue = function(x) { return Color.accessor(x, 2); }; - - - - types.FALSE = false; - types.TRUE = true; - types.EMPTY = Empty.EMPTY; - - types.equals = equals; - types.isNumber = isNumber; - - types.isReal = jsnums.isReal; - types.isRational = jsnums.isRational; - types.isComplex = isNumber; - types.isInteger = jsnums.isInteger; - types.isNatural = isNatural; - types.isNonNegativeReal = isNonNegativeReal; - - - types.isSymbol = function(x) { return x instanceof Symbol; }; - types.isChar = function(x) { return x instanceof plt.baselib.chars.Char; }; - types.isString = isString; - types.isPair = function(x) { return x instanceof Cons; }; - types.isList = isList; - types.isEmpty = function(x) { return x === Empty.EMPTY; }; - types.isVector = function(x) { return x instanceof Vector; }; - types.isBox = function(x) { return x instanceof plt.baselib.boxes.Box; }; - types.isPlaceholder = function(x) { return x instanceof plt.baselib.placeholders.Placeholder; }; - types.isHash = function(x) { return (x instanceof plt.baselib.hashes.EqHashTable || - x instanceof plt.baselib.hashes.EqualHashTable); }; - types.isByteString = function(x) { return x instanceof plt.baselib.bytes.Bytes; }; - types.isStruct = function(x) { return x instanceof Struct; }; - types.isColor = Color.predicate; - -// types.isFunction = function(x) { -// return (x instanceof PrimProc); -// }; - - -// types.isJsValue = function(x) { return x instanceof JsValue; }; -// types.isWrappedSchemeValue = function(x) { return x instanceof WrappedSchemeValue; }; - - types.cons = Cons.makeInstance; - - types.VOID = plt.baselib.constants.VOID_VALUE; - types.EOF = plt.baselib.constants.EOF_VALUE; - -// types.ContinuationPromptTag = ContinuationPromptTag; -// types.defaultContinuationPromptTag = defaultContinuationPromptTag; -// types.defaultContinuationPromptTagHandler = defaultContinuationPromptTagHandler; -// types.makeOptionPrimitive = makeOptionPrimitive; - -// types.internalCall = function(op, args, k) { return new INTERNAL_CALL(op, args, k); }; -// types.isInternalCall = function(x) { return (x instanceof INTERNAL_CALL); }; -// types.internalPause = function(onPause) { return new INTERNAL_PAUSE(onPause) }; -// types.isInternalPause = function(x) { return (x instanceof INTERNAL_PAUSE); }; - - - types.continuationMarkSet = function(dict) { return new plt.baselib.contmarks.ContinuationMarkSet(dict); }; - types.isContinuationMarkSet = function(x) { return x instanceof plt.baselib.contmarks.ContinuationMarkSet; }; -// types.isContinuationPromptTag = function(x) { return x instanceof ContinuationPromptTag; }; - - - types.Box = plt.baselib.boxes.Box; - types.Placeholder = plt.baselib.placeholders.Placeholder; - - - - types.isStructType = function(x) { return x instanceof plt.baselib.structs.StructType; }; - -// types.StructProc = StructProc; -// types.StructConstructorProc = StructConstructorProc; -// types.StructPredicateProc = StructPredicateProc; -// types.StructAccessorProc = StructAccessorProc; -// types.StructMutatorProc = StructMutatorProc; - - - - - types.makeLowLevelEqHash = makeLowLevelEqHash; - - - - /////////////////////////////////////// - // World-specific exports - -// // big bang info to be passed into a make-world-config startup argument -// var BigBangInfo = plt.baselib.structs.makeStructureType('bb-info', false, 2, 0, false, -// function(args, name, k) { -// //helpers.check(args[0], helpers.procArityContains(1), name, 'procedure (arity 1)', 1); -// //helpers.check(args[1], types.isJsValue, name, 'js-object', 2); -// return k(args); -// }); -// types.BigBangInfo = BigBangInfo; -// types.makeBigBangInfo = BigBangInfo.constructor; -// types.isBigBangInfo = BigBangInfo.predicate; -// types.bbInfoChangeWorld = function(info) { return BigBangInfo.accessor(info, 0); }; -// types.bbInfoToplevelNode = function(info) { return BigBangInfo.accessor(info, 1); }; - - - - // World config information for user-defined configurations -// types.worldConfig = function(startup, shutdown, pause, restart) { return new WorldConfig(startup, shutdown, pause, restart); }; -// types.isWorldConfig = function(x) { return x instanceof WorldConfig; }; - - - // exporting information to create effect types -// types.makeEffectType = makeEffectType; -// types.isEffectType = function(x) { -// return ((x instanceof plt.baselib.structs.StructType)&& x.type.prototype.invokeEffect) ? true : false; -// }; - -// types.isEffect = Effect.predicate; - - - // exporting functions to create render effect types -// types.makeRenderEffectType = makeRenderEffectType; -// types.isRenderEffectType = function(x) { -// return (x instanceof plt.baselib.structs.StructType && x.type.prototype.callImplementation) ? true : false; -// }; - -// types.isRenderEffect = RenderEffect.predicate; - - - - - scope.link.announceReady('types'); -})(this['plt']); - From b79a100e626e76c5ae44dbb8d47a3f208ae143d6 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Sat, 17 Sep 2011 22:41:05 -0400 Subject: [PATCH 19/22] cleaning dead code --- world/kernel.js | 867 ------------------------------------------------ 1 file changed, 867 deletions(-) diff --git a/world/kernel.js b/world/kernel.js index 83b4c44..21abc92 100644 --- a/world/kernel.js +++ b/world/kernel.js @@ -372,870 +372,3 @@ StopWhen.prototype.toRawHandler = function(MACHINE, toplevelNode) { var worldFunction = adaptWorldFunction(that.handler); return rawJsworld.stop_when(worldFunction); }; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// // This needs to be cleaned up! - - -// ////////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////////// - -// // The real low-level jsworld module: -// var _js = jsworld.Jsworld; - - -// var caller; -// var setCaller = function(c) { -// caller = function(op, args, k) { -// c(op, args, k, handleError); -// }; -// }; -// var unsetCaller = function() { -// caller = function(op, args, k) { -// throw new Error('caller not defined!'); -// }; -// }; -// unsetCaller(); - -// // The restarted and things to set it -// // Note that we never want to restart the same computation -// // more than once, so we throw an error if someone tries to do that -// var restarter; -// var setRestarter = function(r) { -// var hasRestarted = false; -// restarter = function(v) { -// if (hasRestarted) { -// throw new Error('Cannot restart twice!'); -// } -// hasRestarted = true; -// r(v); -// }; -// }; -// var unsetRestarter = function() { -// restarter = function() { -// throw new Error('restarter not defined!'); -// }; -// }; -// unsetRestarter(); - - -// var errorReporter = function(e) { -// // default: do nothing. -// }; - - - -// var terminator; -// var setTerminator = function(t) { -// terminator = t; -// }; -// var unsetTerminator = function() { -// terminator = function() { -// throw new Error('terminator not defined!'); -// }; -// }; -// unsetTerminator(); - - - -// // mutateStringsInDeepArray: array -> array -// // walks and in-place mutates Scheme strings to primitive strings. -// var mutateStringsInDeepArray = function(thing) { -// var i, length; -// if (typeof(thing) === 'object' && -// thing.constructor === Array) { -// length = thing.length; -// for (i = 0; i < length; i++) { -// thing[i] = mutateStringsInDeepArray(thing[i]); -// } -// } else if (types.isString(thing)) { -// return thing.toString(); -// } -// return thing; -// }; - - - - -// var userConfigs = []; - -// var startUserConfigs = function(k) { -// helpers.forEachK(userConfigs, -// function(aConfig, k2) { -// caller(aConfig.startup, aConfig.startupArgs, -// function(res) { -// aConfig.isRunning = true; -// aConfig.shutdownArg = res; -// k2() -// }); -// }, -// handleError, -// k); -// } - -// var shutdownUserConfigs = function(k) { -// // console.log('shutting down user configs'); -// var theConfigs = userConfigs; -// userConfigs = [] -// helpers.forEachK(theConfigs, -// function(aConfig, k2) { -// // console.log(' shutting down a config'); -// if (aConfig.isRunning) { -// aConfig.isRunning = false; -// caller(aConfig.shutdown, [aConfig.shutdownArg], k2); -// } else { -// k2(); -// } -// }, -// handleError, -// k); -// } - -// var expandHandler = function(handler) { -// return types.jsValue('function', function() { -// var wrappedStimulusArgs = []; -// for (var i = 0; i < arguments.length; i++) { -// wrappedStimulusArgs.push( helpers.wrapJsValue(arguments[i]) ); -// } - -// Jsworld.updateWorld( -// function(w, k) { -// var args = [w].concat(wrappedStimulusArgs); -// caller(handler, args, k); -// }, -// function() {}); -// }); -// }; - - -// // var unwrapWorldEffects = function(w) { -// // if ( _js.has_effects(w) ) { -// // var unwrappedEffects = -// // helpers.map(function(e) { -// // if ( types.isEffect(e) ) { -// // return types.makeJsworldEffect(function(k) { -// // caller(types.effectThunk(e), [], k); -// // }); -// // } -// // else { -// // return e; -// // } -// // }, -// // w.getEffects()); -// // var returnVal = _js.with_multiple_effects(w.getWorld(), unwrappedEffects); -// // return returnVal; -// // } -// // else { -// // return w; -// // } -// // }; - - -// var deepUnwrapJsValues = function(x, k) { -// if ( types.isJsValue(x) ) { -// k(x.unbox()); -// } -// else if ( types.isRenderEffect(x) ) { -// x.callImplementation(caller, function(y) { deepUnwrapJsValues(y, k); }); -// } -// // var effects = helpers.schemeListToArray( types.renderEffectEffects(x) ).reverse(); -// // types.setRenderEffectEffects(x, types.EMPTY); -// // -// // helpers.forEachK(effects, -// // function(ef, k2) { caller(ef, [], k2); }, -// // handleError, -// // function() { deepUnwrapJsValues(types.renderEffectDomNode(x), k); }); -// // } -// else if ( types.isPair(x) ) { -// deepUnwrapJsValues(x.first(), function(first) { -// deepUnwrapJsValues(x.rest(), function(rest) { -// k( types.cons(first, rest) ); -// }); -// }); -// } -// else { -// k(x); -// } -// }; - - - - - - - - -// // isHandler: X -> boolean -// // Right now, a handler is a function that consumes and produces -// // configs. We should tighten up the type check eventually. -// var isHandler = function(x) { -// return typeof(x) == 'function'; -// } - - - - -// ////////////////////////////////////////////////////////////////////// -// //From this point forward, we define wrappers to integrate jsworld -// //with Moby. - - -// // getBigBangWindow: -> window -// var getBigBangWindow = function() { -// if (window.document.getElementById("jsworld-div") !== undefined) { -// return window; -// } else { -// var newDiv = window.document.createElement("div"); -// newDiv.id = 'jsworld-div'; -// window.document.appendChild(newDiv); -// return window; -// } -// } - - -// // types are -// // sexp: (cons node (listof sexp)) -// // css-style: (node (listof (list string string))) - -// // Exports: - - - - -// var isPair = types.isPair; -// var isEmpty = function(x) { return x === types.EMPTY; }; -// var isList = function(x) { return (isPair(x) || isEmpty(x)); }; - - - -// // The default printWorldHook will write the written content of the node. -// // We probably want to invoke the pretty printer here instead! -// Jsworld.printWorldHook = function(world, node) { -// var newNode; -// if(node.lastChild == null) { -// newNode = types.toDomNode(world); -// node.appendChild(newNode); -// helpers.maybeCallAfterAttach(newNode); -// } else { -// newNode = types.toDomNode(world); -// node.replaceChild(newNode, node.lastChild); -// helpers.maybeCallAfterAttach(newNode); -// } -// }; - - - -// // Figure out the target of an event. -// // http://www.quirksmode.org/js/events_properties.html#target -// var findEventTarget = function(e) { -// var targ; -// if (e.target) -// targ = e.target; -// else if (e.srcElement) -// targ = e.srcElement; -// if (targ.nodeType == 3) // defeat Safari bug -// targ = targ.parentNode; -// return targ; -// } - -// // isNode: any -> boolean -// // Returns true if the thing has a nodeType. -// var isNode = function(thing) { -// return thing && typeof(thing.nodeType) != 'undefined'; -// } - - - -// // checkWellFormedDomTree: X X (or number undefined) -> void -// // Check to see if the tree is well formed. If it isn't, -// // we need to raise a meaningful error so the user can repair -// // the structure. -// // -// // Invariants: -// // The dom tree must be a pair. -// // The first element must be a node. -// // Each of the rest of the elements must be dom trees. -// // If the first element is a text node, it must NOT have children. -// var checkWellFormedDomTree = function(x, top, index) { -// var fail = function(formatStr, formatArgs) { -// throw types.schemeError( -// types.incompleteExn(types.exnFailContract, -// helpers.format(formatStr, formatArgs), -// [])); -// } - -// if (_js.isPage(x)) { -// return; -// } - -// if (types.isPair(x)) { -// var firstElt = x.first(); -// var restElts = x.rest(); - -// if (! isNode(firstElt)) { -// fail("on-draw: expected a dom-element, but received ~s instead, the first element within ~s", [firstElt, top]); -// } - -// if (firstElt.nodeType == Node.TEXT_NODE && !restElts.isEmpty() ) { -// fail("on-draw: the text node ~s must not have children. It has ~s", [firstElt, restElts]); -// } - -// var i = 2; -// while( !restElts.isEmpty() ) { -// checkWellFormedDomTree(restElts.first(), x, i); -// restElts = restElts.rest(); -// i++; -// } -// } else { -// var formatStr = "on-draw: expected a dom-s-expression, but received ~s instead"; -// var formatArgs = [x]; -// if (index != undefined) { -// formatStr += ", the ~a element within ~s"; -// formatArgs.push( helpers.ordinalize(index) ); -// formatArgs.push(top); -// } -// formatStr += "."; - -// fail(formatStr, formatArgs); -// } -// }; - - -// // Compatibility for attaching events to nodes. -// var attachEvent = function(node, eventName, fn) { -// if (node.addEventListener) { -// // Mozilla -// node.addEventListener(eventName, fn, false); -// } else { -// // IE -// node.attachEvent('on' + eventName, fn, false); -// } -// return function() { -// detachEvent(node, eventName, fn); -// } -// }; - -// var detachEvent = function(node, eventName, fn) { -// if (node.addEventListener) { -// // Mozilla -// node.removeEventListener(eventName, fn, false); -// } else { -// // IE -// node.detachEvent('on' + eventName, fn, false); -// } -// } - - -// var preventDefault = function(event) { -// if (event.preventDefault) { -// event.preventDefault(); -// } else { -// event.returnValue = false; -// } -// } - -// var stopPropagation = function(event) { -// if (event.stopPropagation) { -// event.stopPropagation(); -// } else { -// event.cancelBubble = true; -// } -// } - - -// // bigBang: world dom (listof (list string string)) (arrayof handler) -> world -// Jsworld.bigBang = function(initWorld, toplevelNode, handlers, theCaller, theRestarter, onFail) { -// // shutdownListeners: arrayof (-> void) -// // We maintain a list of thunks that need to be called as soon as we come out of -// // bigBang, to do cleanup. -// var shutdownListeners = []; - -// var onTermination = function(w) { -// for (var i = 0; i < shutdownListeners.length; i++) { -// try { -// shutdownListeners[i](); -// } catch (e) { } -// } -// shutdownUserConfigs(function() { -// unsetCaller(); -// theRestarter(w); -// }); -// } - - -// //console.log('in high level big-bang'); -// errorReporter = onFail; - -// setCaller(theCaller); -// setRestarter(theRestarter); -// setTerminator(function(w) { -// detachEvent(toplevelNode, 'click', absorber); -// shutdownUserConfigs(function() { -// unsetCaller(); -// unsetTerminator(); -// restarter(w); -// }); -// }); - -// var attribs = types.EMPTY; - -// // Ensure that the toplevelNode can be focused by mouse or keyboard -// toplevelNode.tabIndex = 0; - -// // Absorb all click events so they don't bubble up. -// var absorber = function(e) { -// preventDefault(e); -// stopPropagation(e); -// return false; -// } - -// attachEvent(toplevelNode, 'click', absorber); -// shutdownListeners.push(function() { detachEvent(toplevelNode, 'click', absorber)}); - - - -// var config = new world.Kernel.config.WorldConfig(); -// for(var i = 0; i < handlers.length; i++) { -// if (isList(handlers[i])) { -// attribs = handlers[i]; -// } -// else if (isHandler(handlers[i])) { -// config = handlers[i](config); -// } -// else if ( types.isWorldConfig(handlers[i]) ) { -// handlers[i].startupArgs = helpers.map(expandHandler, handlers[i].startupArgs); -// userConfigs.push(handlers[i]); -// } -// } -// config = config.updateAll({'changeWorld': Jsworld.updateWorld, -// 'shutdownWorld': Jsworld.shutdownWorld}); -// var stimuli = new world.Kernel.stimuli.StimuliHandler(config, caller, restarter); - -// var wrappedHandlers = []; -// var wrappedRedraw; -// var wrappedRedrawCss; - - -// if (config.lookup('onDraw')) { -// wrappedRedraw = function(w, k) { -// try { -// caller(config.lookup('onDraw'), [w], -// function(newDomTree) { -// deepUnwrapJsValues(newDomTree, function(unwrappedTree) { -// checkWellFormedDomTree(unwrappedTree, unwrappedTree, undefined); -// var result = [toplevelNode, -// helpers.deepListToArray(unwrappedTree)]; -// k(result); -// }); -// }); -// } catch (e) { -// handleError(e); -// // throw e; -// } -// } - -// if (config.lookup('onDrawCss')) { -// wrappedRedrawCss = function(w, k) { -// try { -// caller(config.lookup('onDrawCss'), [w], -// function(res) { -// var result = helpers.deepListToArray(res); -// result = mutateStringsInDeepArray(result); -// // plt.Kernel.setLastLoc(undefined); -// k(result); -// }); -// } catch (e) { -// handleError(e); -// // throw e; -// } -// } -// } -// else { -// wrappedRedrawCss = function(w, k) { k([]); }; -// } -// wrappedHandlers.push(_js.on_draw(wrappedRedraw, wrappedRedrawCss)); -// } else if (config.lookup('onRedraw')) { -// var reusableCanvas = undefined; -// var reusableCanvasNode = undefined; - -// wrappedRedraw = function(w, k) { -// try { -// //console.log('in onRedraw handler'); -// caller(config.lookup('onRedraw'), [w], -// function(aScene) { -// // Performance hack: if we're using onRedraw, we know -// // we've got a scene, so we optimize away the repeated -// // construction of a canvas object. -// if ( world.Kernel.isImage(aScene) ) { -// var width = aScene.getWidth(); -// var height = aScene.getHeight(); - -// if (! reusableCanvas) { -// reusableCanvas = world.Kernel.makeCanvas(width, height); -// // Note: the canvas object may itself manage objects, -// // as in the case of an excanvas. In that case, we must make -// // sure jsworld doesn't try to disrupt its contents! -// reusableCanvas.jsworldOpaque = true; -// reusableCanvasNode = _js.node_to_tree(reusableCanvas); -// } - -// reusableCanvas.width = width; -// reusableCanvas.height = height; -// var ctx = reusableCanvas.getContext("2d"); -// aScene.render(ctx, 0, 0); - -// k([toplevelNode, reusableCanvasNode]); -// } else { -// k([toplevelNode, _js.node_to_tree(types.toDomNode(aScene))]); -// } -// }); -// } catch (e) { -// handleError(e); -// // throw e; -// } -// } - -// wrappedRedrawCss = function(w, k) { -// //console.log('in RedrawCss handler'); -// k([[reusableCanvas, -// ["width", reusableCanvas.width + "px"], -// ["height", reusableCanvas.height + "px"]]]); -// } -// wrappedHandlers.push(_js.on_draw(wrappedRedraw, wrappedRedrawCss)); -// } else { -// wrappedHandlers.push(_js.on_world_change -// (function(w, k) { -// Jsworld.printWorldHook(w, toplevelNode); -// k(); -// })); -// } - -// if (config.lookup('tickDelay')) { -// var wrappedTick = function(w, k) { -// caller(config.lookup('onTick'), -// [w], -// k); -// } -// var wrappedDelay = jsnums.toFixnum( config.lookup('tickDelay') ); -// wrappedHandlers.push(_js.on_tick(wrappedDelay, wrappedTick)); -// } - -// if (config.lookup('stopWhen')) { -// wrappedHandlers.push(_js.stop_when( -// function(w, k) { -// caller(config.lookup('stopWhen'), [w], -// function(res) { k(res); }); -// })); -// } - - -// if (config.lookup('onKey')) { -// var wrappedKey = function(w, e, k) { -// caller(config.lookup('onKey'), [w, helpers.getKeyCodeName(e)], k); -// } -// wrappedHandlers.push(_js.on_key(wrappedKey)); -// toplevelNode.focus(); -// } - - -// if (config.lookup('initialEffect')) { -// var updaters = -// world.Kernel.applyEffect(config.lookup('initialEffect')); -// for (var i = 0 ; i < updaters.length; i++) { -// if (config.lookup('stopWhen') && -// config.lookup('stopWhen')([initWorld])) { -// break; -// } else { -// initWorld = updaters[i](initWorld); -// } -// } -// } - - -// _js.big_bang(toplevelNode, -// initWorld, -// wrappedHandlers, -// helpers.assocListToHash(attribs), -// terminator); - -// startUserConfigs(function() {}); - -// return { -// breaker: function() { -// handleError(types.schemeError( -// types.incompleteExn(types.exnBreak, 'user break', []))); -// } -// }; - -// } - - - -// var handleError = function(e) { -// // helpers.reportError(e); -// // When something bad happens, shut down -// // the world computation. -// // helpers.reportError("Shutting down jsworld computations"); -// // world.Kernel.stimuli.onShutdown(); -// world.Kernel.stimuli.massShutdown(); -// shutdownUserConfigs(function() { -// errorReporter(e); -// // console.log('Got an error, the error was:'); -// // console.log(e); -// if (typeof(console) !== 'undefined' && console.log) { -// if (e.stack) { -// console.log(e.stack); -// } -// else { -// console.log(e); -// } -// } -// if ( types.isSchemeError(e) ) { -// terminator(e); -// } -// else if ( types.isInternalError(e) ) { -// terminator(e); -// } -// else if (typeof(e) == 'string') { -// terminator( types.schemeError(types.incompleteExn(types.exnFail, e, [])) ); -// } -// else if (e instanceof Error) { -// terminator( types.schemeError(types.incompleteExn(types.exnFail, e.message, [])) ); -// } -// else { -// terminator( types.schemeError(e) ); -// } -// }); -// } - - - -// // updateWorld: CPS( CPS(world -> world) -> void ) -// Jsworld.updateWorld = function(updater, k) { -// var wrappedUpdater = function(w, k2) { -// try { -// updater(w, k2); -// } catch (e) { -// if (typeof(console) !== 'undefined' && console.log && e.stack) { -// console.log(e.stack); -// } -// handleError(e); -// // k2(w); -// } -// } - -// _js.change_world(wrappedUpdater, k); -// } - - - -// // shutdownWorld: -> void -// // Shut down all world computations. -// Jsworld.shutdownWorld = function() { -// _js.shutdown(); -// }; - - -// // var getAttribs = function(args) { -// // if (args.length == 0) { -// // return [] -// // } -// // if (args.length == 1) { -// // return helpers.assocListToHash(args[0]); -// // } else { -// // throw new Error("getAttribs recevied unexpected value for args: " -// // + args); -// // } -// // } - - -// Jsworld.p = _js.p; - -// Jsworld.div = _js.div; - -// Jsworld.buttonBang = function(updateWorldF, effectF, attribs) { -// var wrappedF = function(w, evt, k) { -// try { -// // FIXME: Get effects back online! -// // caller(effectF, [world], -// // function(effect) { -// caller(updateWorldF, [w], -// function(newWorld) { -// // world.Kernel.applyEffect(effect); -// k(newWorld); -// }); -// // }); -// } catch (e) { -// if (typeof(console) !== 'undefined' && console.log && e.stack) { -// console.log(e.stack); -// } -// handleError(e); -// // k(w); -// } -// } -// return _js.button(wrappedF, attribs); -// }; - - -// Jsworld.input = function(type, updateF, attribs) { -// var wrappedUpdater = function(w, evt, k) { -// caller(updateF, [w, evt], k); -// } -// return _js.input(type, wrappedUpdater, attribs); -// }; - - -// Jsworld.get_dash_input_dash_value = function(node) { -// // plt.Kernel.check(node, -// // function(x) { return (plt.Kernel.isString(node) || -// // node.nodeType == -// // Node.ELEMENT_NODE) }, -// // "get-input-value", -// // "dom-node", -// // 1); -// if (types.isString(node)) { -// return (document.getElementById(node).value || ""); -// } else { -// return (node.value || ""); -// } - -// }; - - - -// // Images. -// Jsworld.img = _js.img; - -// // text: string -> node -// Jsworld.text = _js.text; - -// Jsworld.select = function(options, updateF, attribs) { -// var wrappedUpdater = function(w, e, k) { -// // console.log(e); -// caller(updateF, [w, e.target.value], k); -// } -// return _js.select(attribs, options, wrappedUpdater); -// }; - - - - -// ////////////////////////////////////////////////////////////////////// -// Jsworld.emptyPage = _js.emptyPage; - -// Jsworld.placeOnPage = function(elt, left, top, page) { -// deepUnwrapJsValues(elt, function(newElt) { -// elt = types.toDomNode(newElt);}); -// return _js.placeOnPage(elt, left, top, page); -// }; - - - -// var convertAttribList = function(attribList) { -// var nextElt; -// var key, val; -// var hash = {}; -// while (attribList !== EMPTY) { -// nextElt = attribList.first; - -// key = nextElt.first; -// val = nextElt.rest.first; - -// key = String(key); - -// if (isString(val)) { -// val = String(val); -// } else if (isBoolean(val)) { -// // do nothing: the representation is the same. -// } else if (isSymbol(val)) { -// if (String(val) === 'true') { -// val = true; -// } else if (String(val) === 'false') { -// val = false; -// } else { -// val = String(val); -// } -// } else { -// // raise error: neither string nor boolean -// throw new Error( -// plt.baselib.format.format( -// "attribute value ~s neither a string nor a boolean", -// [val])); -// } -// hash[key] = val; -// attribList = attribList.rest; -// } -// return hash; -// } - - - - - - - - - - - - - From 96c168845f44cebb923e407a3f268377a123a21f Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Mon, 19 Sep 2011 11:21:04 -0400 Subject: [PATCH 20/22] simplifying the logic for the vmlCanvasManager check --- image/private/kernel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/image/private/kernel.js b/image/private/kernel.js index e9aae7e..7221e2b 100644 --- a/image/private/kernel.js +++ b/image/private/kernel.js @@ -139,7 +139,7 @@ var makeCanvas = function(width, height) { // KLUDGE: IE compatibility uses /js/excanvas.js, and dynamic // elements must be marked this way. - if (window && typeof window.G_vmlCanvasManager != 'undefined') { + if (window.G_vmlCanvasManager) { canvas = window.G_vmlCanvasManager.initElement(canvas); } return canvas; From 0f7320f946827791778e6181ddc62cfcf40887cf Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Mon, 19 Sep 2011 11:27:24 -0400 Subject: [PATCH 21/22] need to test map --- tests/more-tests/map.rkt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/more-tests/map.rkt diff --git a/tests/more-tests/map.rkt b/tests/more-tests/map.rkt new file mode 100644 index 0000000..1c1552e --- /dev/null +++ b/tests/more-tests/map.rkt @@ -0,0 +1,2 @@ +#lang planet dyoo/whalesong +(map (lambda (x y) (+ x y)) (list 1 2 3) (list 4 5 6)) From 23bd9eb9996043689ac1b3c85b7adc019956a438 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Mon, 19 Sep 2011 12:01:34 -0400 Subject: [PATCH 22/22] fix for checking procedure arity. Thanks to Jens for the bug report. --- js-assembler/runtime-src/baselib-arity.js | 2 +- js-assembler/runtime-src/runtime.js | 3 +++ tests/more-tests/map.expected | 4 ++++ tests/more-tests/map.rkt | 4 ++++ tests/run-more-tests.rkt | 1 + 5 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tests/more-tests/map.expected diff --git a/js-assembler/runtime-src/baselib-arity.js b/js-assembler/runtime-src/baselib-arity.js index 3fc80d7..1d3aa17 100644 --- a/js-assembler/runtime-src/baselib-arity.js +++ b/js-assembler/runtime-src/baselib-arity.js @@ -41,7 +41,7 @@ while (arity !== baselib.lists.EMPTY) { if (typeof(arity.first) === 'number') { if (arity.first === n) { return true; } - } else if (isArityAtLeast(arity)) { + } else if (isArityAtLeast(arity.first)) { if (n >= arityAtLeastValue(arity.first)) { return true; } } arity = arity.rest; diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index 2466d16..94d584b 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -222,6 +222,9 @@ this.mainModules = []; // Arrayof String this.params = { + // print-as-expression: boolean + 'print-as-expression' : true, + // currentDisplayer: DomNode -> Void // currentDisplayer is responsible for displaying to the browser. 'currentDisplayer': function(MACHINE, domNode) { diff --git a/tests/more-tests/map.expected b/tests/more-tests/map.expected new file mode 100644 index 0000000..5938c3c --- /dev/null +++ b/tests/more-tests/map.expected @@ -0,0 +1,4 @@ +(5 7 9) +(5 7 9) +(12 15 18) +(1 2 3) diff --git a/tests/more-tests/map.rkt b/tests/more-tests/map.rkt index 1c1552e..45ebce8 100644 --- a/tests/more-tests/map.rkt +++ b/tests/more-tests/map.rkt @@ -1,2 +1,6 @@ #lang planet dyoo/whalesong + (map (lambda (x y) (+ x y)) (list 1 2 3) (list 4 5 6)) +(map + (list 1 2 3) (list 4 5 6)) +(map + (list 1 2 3) (list 4 5 6) (list 7 8 9)) +(map + (list 1 2 3)) diff --git a/tests/run-more-tests.rkt b/tests/run-more-tests.rkt index 9a79ce7..7f48372 100644 --- a/tests/run-more-tests.rkt +++ b/tests/run-more-tests.rkt @@ -14,6 +14,7 @@ (test "more-tests/hello.rkt") (test "more-tests/sharing.rkt") (test "more-tests/simple-functions.rkt") +(test "more-tests/map.rkt") (test "more-tests/quasi.rkt") (test "more-tests/sk-generator.rkt") (test "more-tests/sk-generator-2.rkt")