diff --git a/js-assembler/assemble-helpers.rkt b/js-assembler/assemble-helpers.rkt index 513e63c..5bcf180 100644 --- a/js-assembler/assemble-helpers.rkt +++ b/js-assembler/assemble-helpers.rkt @@ -19,7 +19,8 @@ assemble-arity assemble-jump assemble-display-name - assemble-location) + assemble-location + assemble-numeric-constant) (require/typed typed/racket/base [regexp-split (Regexp String -> (Listof String))]) @@ -110,7 +111,7 @@ [(empty? val) (format "RUNTIME.NULL")] [(number? val) - (format "(~s)" val)] + (assemble-numeric-constant val)] [else (format "~s" val)]))) @@ -126,6 +127,15 @@ + +(: assemble-numeric-constant (Number -> String)) +(define (assemble-numeric-constant val) + (format "(~s)" val)) + + + + + (: assemble-lexical-reference (EnvLexicalReference -> String)) (define (assemble-lexical-reference a-lex-ref) (if (EnvLexicalReference-unbox? a-lex-ref) diff --git a/js-assembler/assemble-open-coded.rkt b/js-assembler/assemble-open-coded.rkt index 8c13742..93a204e 100644 --- a/js-assembler/assemble-open-coded.rkt +++ b/js-assembler/assemble-open-coded.rkt @@ -5,7 +5,8 @@ "../compiler/lexical-structs.rkt" "../compiler/kernel-primitives.rkt" racket/string - racket/list) + racket/list + typed/rackunit) (provide open-code-kernel-primitive-procedure) @@ -28,45 +29,48 @@ (case operator [(+) (cond [(empty? checked-operands) - "0"] + (assemble-numeric-constant 0)] [else - (string-append "(" (string-join checked-operands " + ") ")")])] + (assemble-binop-chain "jsnums.add" checked-operands)])] [(-) (cond [(empty? (rest checked-operands)) - (format "(-(~a))" (first checked-operands))] + (assemble-binop-chain "jsnums.subtract" (cons "0" checked-operands))] [else - (string-append "(" (string-join checked-operands "-") ")")])] + (assemble-binop-chain "jsnums.subtract" checked-operands)])] [(*) (cond [(empty? checked-operands) - "1"] + (assemble-numeric-constant 1)] [else - (string-append "(" (string-join checked-operands "*") ")")])] + (assemble-binop-chain "jsnums.multiply" checked-operands)])] [(/) - (string-append "(" (string-join checked-operands "/") ")")] + (assemble-binop-chain "jsnums.divide" checked-operands)] [(add1) - (format "(~a + 1)" (first checked-operands))] + (assemble-binop-chain "jsnums.add" (cons "1" checked-operands))] [(sub1) - (format "(~a - 1)" (first checked-operands))] - + (assemble-binop-chain "jsnums.subtract" (append checked-operands (list "1")))] + [(<) - (assemble-chain "<" checked-operands)] + (assemble-boolean-chain "jsnums.lessThan" checked-operands)] [(<=) - (assemble-chain "<=" checked-operands)] + (assemble-boolean-chain "jsnums.lessThanOrEqual" checked-operands)] [(=) - (assemble-chain "===" checked-operands)] + (assemble-boolean-chain "jsnums.equals" checked-operands)] [(>) - (assemble-chain ">" checked-operands)] + (assemble-boolean-chain "jsnums.greaterThan" checked-operands)] [(>=) - (assemble-chain ">=" checked-operands)] + (assemble-boolean-chain "jsnums.greaterThanOrEqual" checked-operands)] + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + [(cons) (format "[~a, ~a]" (first checked-operands) (second checked-operands))] @@ -95,8 +99,32 @@ (format "(~a === ~a)" (first checked-operands) (second checked-operands))]))) -(: assemble-chain (String (Listof String) -> String)) -(define (assemble-chain rator rands) + +(: assemble-binop-chain (String (Listof String) -> String)) +(define (assemble-binop-chain rator rands) + (cond + [(empty? rands) + ""] + [(empty? (rest rands)) + (first rands)] + [else + (assemble-binop-chain + rator + (cons (string-append rator "(" (first rands) ", " (second rands) ")") + (rest (rest rands))))])) + +(check-equal? (assemble-binop-chain "jsnums.add" '("3" "4" "5")) + "jsnums.add(jsnums.add(3, 4), 5)") +(check-equal? (assemble-binop-chain "jsnums.subtract" '("0" "42")) + "jsnums.subtract(0, 42)") + + + + + + +(: assemble-boolean-chain (String (Listof String) -> String)) +(define (assemble-boolean-chain rator rands) (string-append "(" (string-join (let: loop : (Listof String) ([rands : (Listof String) rands]) (cond @@ -105,7 +133,7 @@ [(empty? (rest rands)) '()] [else - (cons (format "(~a ~a ~a)" (first rands) rator (second rands)) + (cons (format "(~a(~a,~a))" rator (first rands) (second rands)) (loop (rest rands)))])) "&&") ")")) diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index 3986e7f..c7f870e 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -23,12 +23,10 @@ if(this['plt'] === undefined) { this['plt'] = {}; } }; - var isNumber = function(x) { return typeof(x) === 'number'; }; - - var isNatural = function(x) { return typeof(x) === 'number' && - x >= 0 && - Math.floor(x) === x; }; + var isNumber = jsnums.isSchemeNumber; + var isNatural = function(x) { return (jsnums.isInteger(x) && + jsnums.greaterThanOrEqual(x, 0)); } var isPair = function(x) { return (typeof(x) == 'object' && x.length === 2 && @@ -605,9 +603,9 @@ if(this['plt'] === undefined) { this['plt'] = {}; } - Primitives['pi'] = Math.PI; + Primitives['pi'] = jsnums.pi; - Primitives['e'] = Math.E; + Primitives['e'] = jsnums.e; Primitives['='] = function(MACHINE) { var firstArg = MACHINE.env[MACHINE.env.length-1]; @@ -619,8 +617,8 @@ if(this['plt'] === undefined) { this['plt'] = {}; } MACHINE.env[MACHINE.env.length - 1 - i], i, '='); - if (MACHINE.env[MACHINE.env.length - 1 - i] !== - MACHINE.env[MACHINE.env.length - 1 - i - 1]) { + if (! (jsnums.equals(MACHINE.env[MACHINE.env.length - 1 - i], + MACHINE.env[MACHINE.env.length - 1 - i - 1]))) { return false; } } @@ -641,8 +639,8 @@ if(this['plt'] === undefined) { this['plt'] = {}; } MACHINE.env[MACHINE.env.length - 1 - i], i, '<'); - if (! (MACHINE.env[MACHINE.env.length - 1 - i] < - MACHINE.env[MACHINE.env.length - 1 - i - 1])) { + if (! (jsnums.lessThan(MACHINE.env[MACHINE.env.length - 1 - i], + MACHINE.env[MACHINE.env.length - 1 - i - 1]))) { return false; } } @@ -662,8 +660,8 @@ if(this['plt'] === undefined) { this['plt'] = {}; } MACHINE.env[MACHINE.env.length - 1 - i], i, '>'); - if (! (MACHINE.env[MACHINE.env.length - 1 - i] > - MACHINE.env[MACHINE.env.length - 1 - i - 1])) { + if (! (jsnums.greaterThan(MACHINE.env[MACHINE.env.length - 1 - i], + MACHINE.env[MACHINE.env.length - 1 - i - 1]))) { return false; } } @@ -683,8 +681,8 @@ if(this['plt'] === undefined) { this['plt'] = {}; } MACHINE.env[MACHINE.env.length - 1 - i], i, '<='); - if (! (MACHINE.env[MACHINE.env.length - 1 - i] <= - MACHINE.env[MACHINE.env.length - 1 - i - 1])) { + if (! (jsnums.lessThanOrEqual(MACHINE.env[MACHINE.env.length - 1 - i], + MACHINE.env[MACHINE.env.length - 1 - i - 1]))) { return false; } } @@ -705,8 +703,8 @@ if(this['plt'] === undefined) { this['plt'] = {}; } MACHINE.env[MACHINE.env.length - 1 - i], i, '>='); - if (! (MACHINE.env[MACHINE.env.length - 1 - i] >= - MACHINE.env[MACHINE.env.length - 1 - i - 1])) { + if (! (jsnums.greaterThanOrEqual(MACHINE.env[MACHINE.env.length - 1 - i], + MACHINE.env[MACHINE.env.length - 1 - i - 1]))) { return false; } } @@ -726,7 +724,7 @@ if(this['plt'] === undefined) { this['plt'] = {}; } MACHINE.env[MACHINE.env.length - 1 - i], i, '+'); - result += MACHINE.env[MACHINE.env.length - 1 - i]; + result = jsnums.add(result, MACHINE.env[MACHINE.env.length - 1 - i]); }; return result; }; @@ -744,7 +742,7 @@ if(this['plt'] === undefined) { this['plt'] = {}; } MACHINE.env[MACHINE.env.length - 1 - i], i, '*'); - result *= MACHINE.env[MACHINE.env.length - 1 - i]; + result = jsnums.multiply(result, MACHINE.env[MACHINE.env.length - 1 - i]); } return result; }; @@ -759,7 +757,7 @@ if(this['plt'] === undefined) { this['plt'] = {}; } MACHINE.env[MACHINE.env.length-1], 0, '-'); - return -(MACHINE.env[MACHINE.env.length-1]); + return jsnums.subtract(0, MACHINE.env[MACHINE.env.length-1]); } var result = MACHINE.env[MACHINE.env.length - 1]; for (var i = 1; i < MACHINE.argcount; i++) { @@ -769,7 +767,7 @@ if(this['plt'] === undefined) { this['plt'] = {}; } MACHINE.env[MACHINE.env.length-1-i], i, '-'); - result -= MACHINE.env[MACHINE.env.length - 1 - i]; + result = jsnums.subtract(result, MACHINE.env[MACHINE.env.length - 1 - i]); } return result; }; @@ -791,7 +789,7 @@ if(this['plt'] === undefined) { this['plt'] = {}; } MACHINE.env[MACHINE.env.length-1-i], i, '/'); - result /= MACHINE.env[MACHINE.env.length - 1 - i]; + result = jsnums.divide(result, MACHINE.env[MACHINE.env.length - 1 - i]); } return result; }; @@ -799,6 +797,47 @@ if(this['plt'] === undefined) { this['plt'] = {}; } Primitives['/'].displayName = '/'; + + Primitives['add1'] = function(MACHINE) { + testArgument(MACHINE, + 'number', + isNumber, + MACHINE.env[MACHINE.env.length - 1], + 0, + 'add1'); + var firstArg = MACHINE.env[MACHINE.env.length-1]; + return jsnums.add(firstArg, 1); + }; + Primitives['add1'].arity = 1; + Primitives['add1'].displayName = 'add1'; + + Primitives['sub1'] = function(MACHINE) { + testArgument(MACHINE, + 'number', + isNumber, + MACHINE.env[MACHINE.env.length - 1], + 0, + 'sub1'); + var firstArg = MACHINE.env[MACHINE.env.length-1]; + return jsnums.subtract(firstArg, 1); + }; + Primitives['sub1'].arity = 1; + Primitives['sub1'].displayName = 'sub1'; + + Primitives['zero?'] = function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + return jsnums.equals(firstArg, 0); + }; + Primitives['zero?'].arity = 1; + Primitives['zero?'].displayName = 'zero?'; + + + + + + + + Primitives['cons'] = function(MACHINE) { var firstArg = MACHINE.env[MACHINE.env.length-1]; var secondArg = MACHINE.env[MACHINE.env.length-2]; @@ -896,39 +935,6 @@ if(this['plt'] === undefined) { this['plt'] = {}; } Primitives['null?'].arity = 1; Primitives['null?'].displayName = 'null?'; - Primitives['add1'] = function(MACHINE) { - testArgument(MACHINE, - 'number', - isNumber, - MACHINE.env[MACHINE.env.length - 1], - 0, - 'add1'); - var firstArg = MACHINE.env[MACHINE.env.length-1]; - return firstArg + 1; - }; - Primitives['add1'].arity = 1; - Primitives['add1'].displayName = 'add1'; - - Primitives['sub1'] = function(MACHINE) { - testArgument(MACHINE, - 'number', - isNumber, - MACHINE.env[MACHINE.env.length - 1], - 0, - 'sub1'); - var firstArg = MACHINE.env[MACHINE.env.length-1]; - return firstArg - 1; - }; - Primitives['sub1'].arity = 1; - Primitives['sub1'].displayName = 'sub1'; - - Primitives['zero?'] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - return firstArg === 0; - }; - Primitives['zero?'].arity = 1; - Primitives['zero?'].displayName = 'zero?'; - Primitives['vector'] = function(MACHINE) { var i; var result = []; @@ -994,7 +1000,7 @@ if(this['plt'] === undefined) { this['plt'] = {}; } 0, 'vector-set!'); var firstArg = MACHINE.env[MACHINE.env.length-1]; - var secondArg = MACHINE.env[MACHINE.env.length-2]; + var secondArg = jsnums.toFixnum(MACHINE.env[MACHINE.env.length-2]); var thirdArg = MACHINE.env[MACHINE.env.length-3]; firstArg[secondArg] = thirdArg; return null; @@ -1010,7 +1016,7 @@ if(this['plt'] === undefined) { this['plt'] = {}; } MACHINE.env[MACHINE.env.length - 1], 0, 'vector-length'); - var firstArg = MACHINE.env[MACHINE.env.length-1]; + var firstArg = MACHINE.env[jsnums.toFixnum(MACHINE.env.length-1)]; return firstArg.length; }; Primitives['vector-length'].arity = 1; @@ -1028,7 +1034,7 @@ if(this['plt'] === undefined) { this['plt'] = {}; } if (MACHINE.argcount == 2) { value = MACHINE.env[MACHINE.env.length - 2]; } - var length = MACHINE.env[MACHINE.env.length-1]; + var length = jsnums.toFixnum(MACHINE.env[MACHINE.env.length-1]); var arr = []; for(var i = 0; i < length; i++) { arr[i] = value;