diff --git a/experiments/fact/foo2.html b/experiments/fact/foo2.html index 93c8b96..adb01ce 100644 --- a/experiments/fact/foo2.html +++ b/experiments/fact/foo2.html @@ -1,6 +1,6 @@ - diff --git a/experiments/fact/foo2.js b/experiments/fact/foo2.js index 7062211..34ddd2e 100644 --- a/experiments/fact/foo2.js +++ b/experiments/fact/foo2.js @@ -96,45 +96,31 @@ var MACHINE={env: new TopEnvironment(), argl:undefined, val:undefined, cont:undefined, - stack: []}; + stack: [], + label: undefined}; -// harness: (->) (->) -> void -var trampoline = function(initialJump, k) { - var thunk = initialJump; - MACHINE.callsBeforeTrampoline = 100; - while(thunk) { - try { - thunk(); - break; - } catch (e) { - if (typeof(e) === 'function') { - thunk = e; - MACHINE.callsBeforeTrampoline = 100; - } else { - throw e; - } - } - } - k(); -}; - var invoke = function(k) { MACHINE.cont = k; - program(1, function() {}); + MACHINE.label = 1; + program(function() {}); }; -var program = function(label, k) { +var program = function(k) { while(true) { - switch(label) { + if (typeof(MACHINE.label) === 'function') { + MACHINE.label(); + return; + } + + switch(MACHINE.label) { case 1: - if(--MACHINE.callsBeforeTrampoline < 0) { throw start23; } MACHINE.val=(new Closure(MACHINE.env, 2)); - label = 3; + MACHINE.label = 3; break; @@ -149,17 +135,17 @@ var program = function(label, k) { MACHINE.argl=[MACHINE.val,MACHINE.argl]; if((typeof(MACHINE.proc) === 'function')){ MACHINE.val=MACHINE.proc(MACHINE.argl); - label = MACHINE.cont(); + MACHINE.label = MACHINE.cont(); break;} - MACHINE.val=(MACHINE.proc.label); - label = MACHINE.val(); + MACHINE.val=(MACHINE.proc.MACHINE.label); + MACHINE.label = MACHINE.val(); break; case 3: (MACHINE.env).globalBindings["factorial"] = MACHINE.val; MACHINE.val="ok"; MACHINE.val=(new Closure(MACHINE.env, 4)); - label = 9; + MACHINE.label = 9; break; case 4: @@ -175,21 +161,21 @@ var program = function(label, k) { MACHINE.argl=[MACHINE.val,MACHINE.argl]; if((typeof(MACHINE.proc) === 'function')){ MACHINE.val=MACHINE.proc(MACHINE.argl); - label=5; + MACHINE.label=5; break;} MACHINE.cont=5; - MACHINE.val=(MACHINE.proc.label); - label = MACHINE.val(); + MACHINE.val=(MACHINE.proc.MACHINE.label); + MACHINE.label = MACHINE.val(); break; case 5: MACHINE.env=MACHINE.stack.pop(); MACHINE.cont=MACHINE.stack.pop(); if((!(MACHINE.val))){ - label=6; + MACHINE.label=6; break;} MACHINE.val=(MACHINE.env).valss[0][1]; - label = MACHINE.cont(); + MACHINE.label = MACHINE.cont(); break; @@ -207,13 +193,13 @@ var program = function(label, k) { MACHINE.argl=[MACHINE.val,MACHINE.argl]; if((typeof(MACHINE.proc) === 'function')){ MACHINE.val=MACHINE.proc(MACHINE.argl); - label=7; + MACHINE.label=7; break;} MACHINE.cont=7; - MACHINE.val=(MACHINE.proc.label); - label = MACHINE.val(); + MACHINE.val=(MACHINE.proc.MACHINE.label); + MACHINE.label = MACHINE.val(); break; - + case 7: MACHINE.argl=[MACHINE.val, undefined]; MACHINE.env=MACHINE.stack.pop(); @@ -226,11 +212,11 @@ var program = function(label, k) { MACHINE.argl=[MACHINE.val,MACHINE.argl]; if((typeof(MACHINE.proc) === 'function')){ MACHINE.val=MACHINE.proc(MACHINE.argl); - label=8; + MACHINE.label=8; break;} MACHINE.cont=8; - MACHINE.val=(MACHINE.proc.label); - label = MACHINE.val(); + MACHINE.val=(MACHINE.proc.MACHINE.label); + MACHINE.label = MACHINE.val(); break; @@ -241,16 +227,16 @@ var program = function(label, k) { MACHINE.cont=MACHINE.stack.pop(); if((typeof(MACHINE.proc) === 'function')){ MACHINE.val=MACHINE.proc(MACHINE.argl); - label = MACHINE.cont(); + MACHINE.label = MACHINE.cont(); break; } - MACHINE.val=(MACHINE.proc.label); - label = MACHINE.val(); + MACHINE.val=(MACHINE.proc.MACHINE.label); + MACHINE.label = MACHINE.val(); break; case 9: (MACHINE.env).globalBindings["fact-iter"] = MACHINE.val; MACHINE.val="ok"; - label = MACHINE.cont(); + MACHINE.label = MACHINE.cont(); break; } } diff --git a/experiments/fact/foo2.js~ b/experiments/fact/foo2.js~ deleted file mode 100644 index a65c7bc..0000000 --- a/experiments/fact/foo2.js~ +++ /dev/null @@ -1,243 +0,0 @@ -// Type representations: -// -// number are numbers -// -// cons pairs are [first, rest] -// -// function closures are Closures -// primitive procedures are regular functions. - -var TopEnvironment = function() { - this.globalBindings = { - '=': function(argl) { - return argl[0] === argl[1][0]; - }, - - '+': function(argl) { - return argl[0] + argl[1][0]; - }, - - '*': function(argl) { - return argl[0] * argl[1][0]; - }, - - '-': function(argl) { - return argl[0] - argl[1][0]; - }, - - '/': function(argl) { - return argl[0] / argl[1][0]; - } - }; - this.valss = []; -}; - -var ExtendedEnvironment = function(parent, vs) { - var vals = []; - while(vs) { - vals.push(vs[0]); - vs = vs[1]; - } - this.valss = parent.valss.slice(); - this.valss.unshift(vals); - this.globalBindings = parent.globalBindings; -}; - - -// A closure consists of its free variables as well as a label -// into its text segment. -var Closure = function(env, label) { - this.env = env; - this.label = label; -}; - - -// adaptToJs: closure -> (array (X -> void) -> void) -// Converts closures to functions that can be called from the -// JavaScript toplevel. -Closure.prototype.adaptToJs = function() { - var that = this; - return function(args, k) { - var oldEnv = MACHINE.env; - var oldCont = MACHINE.cont; - var oldProc = MACHINE.proc; - var oldArgl = MACHINE.argl; - var oldVal = MACHINE.val; - trampoline( - function() { - var proc = that; - MACHINE.proc = proc; - MACHINE.argl = undefined; - for(var i = args.length - 1; i >= 0; i--) { - MACHINE.argl = [args[i], MACHINE.argl]; - } - - MACHINE.cont = function() { - var result = MACHINE.val; - MACHINE.env = oldEnv; - MACHINE.cont = oldCont; - MACHINE.proc = oldProc; - MACHINE.argl = oldArgl; - MACHINE.val = oldVal; - k(result); - }; - - proc.label(); - }, - function() { - }); - } -}; - - - -var MACHINE={callsBeforeTrampoline: 100, - env: new TopEnvironment(), - proc:undefined, - argl:undefined, - val:undefined, - cont:undefined, - stack: []}; - - -// harness: (->) (->) -> void -var trampoline = function(initialJump, k) { - var thunk = initialJump; - MACHINE.callsBeforeTrampoline = 100; - while(thunk) { - try { - thunk(); - break; - } catch (e) { - if (typeof(e) === 'function') { - thunk = e; - MACHINE.callsBeforeTrampoline = 100; - } else { - throw e; - } - } - } - k(); -}; - -var invoke = function(k) { -var start23=function(){ -if(--MACHINE.callsBeforeTrampoline < 0) { throw start23; } -MACHINE.val=(new Closure(MACHINE.env, entry1)); -return afterLambda2();}; - -var entry1=function(){ -if(--MACHINE.callsBeforeTrampoline < 0) { throw entry1; } -MACHINE.env=(MACHINE.proc.env); -MACHINE.env=new ExtendedEnvironment(MACHINE.env, MACHINE.argl); -if (! (MACHINE.env).globalBindings.hasOwnProperty("fact-iter")) { throw new Error("Not bound: " + "fact-iter"); } -MACHINE.proc=((MACHINE.env).globalBindings["fact-iter"]); -MACHINE.val=1; -MACHINE.argl=[MACHINE.val, undefined]; -MACHINE.val=(MACHINE.env).valss[0][0]; -MACHINE.argl=[MACHINE.val,MACHINE.argl]; -if((typeof(MACHINE.proc) === 'function')){ -MACHINE.val=MACHINE.proc(MACHINE.argl); -return MACHINE.cont();} -MACHINE.val=(MACHINE.proc.label); -return MACHINE.val();}; - - -var afterLambda2=function(){ -if(--MACHINE.callsBeforeTrampoline < 0) { throw afterLambda2; } -(MACHINE.env).globalBindings["factorial"] = MACHINE.val; -MACHINE.val="ok"; -MACHINE.val=(new Closure(MACHINE.env, entry6)); -return afterLambda7();}; - -var entry6=function(){ -if(--MACHINE.callsBeforeTrampoline < 0) { throw entry6; } -MACHINE.env=(MACHINE.proc.env); -MACHINE.env=new ExtendedEnvironment(MACHINE.env, MACHINE.argl); -MACHINE.stack.push(MACHINE.cont); -MACHINE.stack.push(MACHINE.env); -if (! (MACHINE.env).globalBindings.hasOwnProperty("=")) { throw new Error("Not bound: " + "="); } -MACHINE.proc=((MACHINE.env).globalBindings["="]); -MACHINE.val=0; -MACHINE.argl=[MACHINE.val, undefined]; -MACHINE.val=(MACHINE.env).valss[0][0]; -MACHINE.argl=[MACHINE.val,MACHINE.argl]; -if((typeof(MACHINE.proc) === 'function')){ -MACHINE.val=MACHINE.proc(MACHINE.argl); -return afterCall13();} -MACHINE.cont=afterCall13; -MACHINE.val=(MACHINE.proc.label); -return MACHINE.val();}; - - -var afterCall13=function(){ -if(--MACHINE.callsBeforeTrampoline < 0) { throw afterCall13; } -MACHINE.env=MACHINE.stack.pop(); -MACHINE.cont=MACHINE.stack.pop(); -if((!(MACHINE.val))){ -return falseBranch9();} -MACHINE.val=(MACHINE.env).valss[0][1]; -return MACHINE.cont();}; - -var falseBranch9=function(){ -if(--MACHINE.callsBeforeTrampoline < 0) { throw falseBranch9; } -if (! (MACHINE.env).globalBindings.hasOwnProperty("fact-iter")) { throw new Error("Not bound: " + "fact-iter"); } -MACHINE.proc=((MACHINE.env).globalBindings["fact-iter"]); -MACHINE.stack.push(MACHINE.cont); -MACHINE.stack.push(MACHINE.proc); -MACHINE.stack.push(MACHINE.env); -if (! (MACHINE.env).globalBindings.hasOwnProperty("*")) { throw new Error("Not bound: " + "*"); } -MACHINE.proc=((MACHINE.env).globalBindings["*"]); -MACHINE.val=(MACHINE.env).valss[0][0]; -MACHINE.argl=[MACHINE.val, undefined]; -MACHINE.val=(MACHINE.env).valss[0][1]; -MACHINE.argl=[MACHINE.val,MACHINE.argl]; -if((typeof(MACHINE.proc) === 'function')){ -MACHINE.val=MACHINE.proc(MACHINE.argl); -return afterCall19();} -MACHINE.cont=afterCall19; -MACHINE.val=(MACHINE.proc.label); -return MACHINE.val();}; - - -var afterCall19=function(){ -if(--MACHINE.callsBeforeTrampoline < 0) { throw afterCall19; } -MACHINE.argl=[MACHINE.val, undefined]; -MACHINE.env=MACHINE.stack.pop(); -MACHINE.stack.push(MACHINE.argl); -if (! (MACHINE.env).globalBindings.hasOwnProperty("-")) { throw new Error("Not bound: " + "-"); } -MACHINE.proc=((MACHINE.env).globalBindings["-"]); -MACHINE.val=1; -MACHINE.argl=[MACHINE.val, undefined]; -MACHINE.val=(MACHINE.env).valss[0][0]; -MACHINE.argl=[MACHINE.val,MACHINE.argl]; -if((typeof(MACHINE.proc) === 'function')){ -MACHINE.val=MACHINE.proc(MACHINE.argl); -return afterCall16();} -MACHINE.cont=afterCall16; -MACHINE.val=(MACHINE.proc.label); -return MACHINE.val();}; - - - -var afterCall16=function(){ -if(--MACHINE.callsBeforeTrampoline < 0) { throw afterCall16; } -MACHINE.argl=MACHINE.stack.pop(); -MACHINE.argl=[MACHINE.val,MACHINE.argl]; -MACHINE.proc=MACHINE.stack.pop(); -MACHINE.cont=MACHINE.stack.pop(); -if((typeof(MACHINE.proc) === 'function')){ -MACHINE.val=MACHINE.proc(MACHINE.argl); -return MACHINE.cont();} -MACHINE.val=(MACHINE.proc.label); -return MACHINE.val();}; - - -var afterLambda7=function(){ -if(--MACHINE.callsBeforeTrampoline < 0) { throw afterLambda7; } -(MACHINE.env).globalBindings["fact-iter"] = MACHINE.val; -MACHINE.val="ok"; -return MACHINE.cont();}; - -MACHINE.cont = k; -trampoline(start23, function() {}); }; \ No newline at end of file diff --git a/package.rkt b/package.rkt index 1c7fd94..886541d 100644 --- a/package.rkt +++ b/package.rkt @@ -29,11 +29,19 @@ (package s-exp (current-output-port))) -(test '(define (factorial n) +#;(test '(define (factorial n) (if (= n 0) 1 (* (factorial (- n 1)) n)))) +(test '(begin + (define (factorial n) + (fact-iter n 1)) + (define (fact-iter n acc) + (if (= n 0) + acc + (fact-iter (- n 1) (* acc n)))))) + #;(test '(define (gauss n) (if (= n 0) 0