From da95994360a645ef98e8144657edd46df4a2b5d8 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Wed, 15 Jun 2011 17:54:39 -0400 Subject: [PATCH] working to adapt the primitives --- .../get-js-vm-implemented-primitives.rkt | 47 + js-assembler/runtime-src/runtime.js | 1110 +++++++++-------- scribblings/manual.scrbl | 81 +- 3 files changed, 685 insertions(+), 553 deletions(-) create mode 100644 js-assembler/get-js-vm-implemented-primitives.rkt diff --git a/js-assembler/get-js-vm-implemented-primitives.rkt b/js-assembler/get-js-vm-implemented-primitives.rkt new file mode 100644 index 0000000..79d5697 --- /dev/null +++ b/js-assembler/get-js-vm-implemented-primitives.rkt @@ -0,0 +1,47 @@ +#lang racket/base + +(require racket/runtime-path + racket/file + racket/contract + racket/list) +;; Get the list of primitives implemented in js-vm-primitives.js + +(define-runtime-path js-vm-primitives.js "runtime-src/js-vm-primitives.js") + +(define-runtime-path whalesong-primitives.js "runtime-src/primitives.js") + +;; sort&unique: (listof string) -> (listof string) +(define (sort&unique names) + (let ([ht (make-hash)]) + (for ([name names]) + (hash-set! ht name #t)) + (sort (for/list ([name (in-hash-keys ht)]) + name) + stringsymbol + (sort&unique + (map (lambda (a-str) + (substring a-str + (string-length "PRIMITIVES['") + (- (string-length a-str) (string-length "']")))) + (let ([contents (file->string js-vm-primitives.js)]) + (regexp-match* #px"PRIMITIVES\\[('|\")[^\\]]*('|\")\\]" contents)))))) + + + +(define whalesong-primitive-names + (map string->symbol + (sort&unique + (map (lambda (a-str) + (let ([match (regexp-match + #px"installPrimitiveProcedure\\(\\s+('|\")([^\\]]*)('|\")" a-str)]) + (third match))) + (let ([contents (file->string whalesong-primitives.js)]) + (regexp-match* #px"installPrimitiveProcedure\\(\\s+('|\")[^\\']*('|\")" contents)))))) + + +(provide/contract [js-vm-primitive-names (listof symbol?)] + [whalesong-primitive-names (listof symbol?)]) \ No newline at end of file diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index e1cf282..cec57a2 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -1,9 +1,7 @@ if(this['plt'] === undefined) { this['plt'] = {}; } - // All of the values here are namespaced under "plt.runtime". - (function(scope) { var runtime = {}; scope['runtime'] = runtime; @@ -19,10 +17,6 @@ if(this['plt'] === undefined) { this['plt'] = {}; } }; - - - - ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // We try to isolate the effect of external modules: all the identifiers we @@ -33,6 +27,9 @@ if(this['plt'] === undefined) { this['plt'] = {}; } var isPair = types.isPair; var isList = types.isList; var isVector = types.isVector; + var isEqual = types.isEqual; + + var NULL = types.EMPTY; var VOID = types.VOID; @@ -125,7 +122,7 @@ if(this['plt'] === undefined) { this['plt'] = {}; } "printer") - }; + }; this.primitives = Primitives; }; @@ -542,8 +539,11 @@ if(this['plt'] === undefined) { this['plt'] = {}; } }; + installPrimitiveConstant('pi', jsnums.pi); installPrimitiveConstant('e', jsnums.e); + installPrimitiveConstant('null', NULL); + installPrimitiveProcedure( 'display', makeList(1, 2), @@ -638,552 +638,588 @@ if(this['plt'] === undefined) { this['plt'] = {}; } // TODO: use installPrimitiveProcedure for the rest... - Primitives['<'] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - testArgument(MACHINE, - 'number', isNumber, firstArg, 0, '<'); - for (var i = 0; i < MACHINE.argcount - 1; i++) { - testArgument(MACHINE, - 'number', - isNumber, - MACHINE.env[MACHINE.env.length - 1 - i], - i, - '<'); - if (! (jsnums.lessThan(MACHINE.env[MACHINE.env.length - 1 - i], - MACHINE.env[MACHINE.env.length - 1 - i - 1]))) { - return false; - } - } - return true; - }; - Primitives['<'].arity = new ArityAtLeast(2); - Primitives['<'].displayName = '<'; - - Primitives['>'] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - testArgument(MACHINE, - 'number', isNumber, firstArg, 0, '>'); - for (var i = 0; i < MACHINE.argcount - 1; i++) { + installPrimitiveProcedure( + '<', + new ArityAtLeast(2), + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; testArgument(MACHINE, - 'number', - isNumber, - MACHINE.env[MACHINE.env.length - 1 - i], - i, - '>'); - if (! (jsnums.greaterThan(MACHINE.env[MACHINE.env.length - 1 - i], - MACHINE.env[MACHINE.env.length - 1 - i - 1]))) { - return false; + 'number', isNumber, firstArg, 0, '<'); + for (var i = 0; i < MACHINE.argcount - 1; i++) { + testArgument(MACHINE, + 'number', + isNumber, + MACHINE.env[MACHINE.env.length - 1 - i], + i, + '<'); + if (! (jsnums.lessThan(MACHINE.env[MACHINE.env.length - 1 - i], + MACHINE.env[MACHINE.env.length - 1 - i - 1]))) { + return false; + } } - } - return true; - }; - Primitives['>'].arity = new ArityAtLeast(2); - Primitives['>'].displayName = '>'; + return true; + }); - Primitives['<='] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - testArgument(MACHINE, - 'number', isNumber, firstArg, 0, '<='); - for (var i = 0; i < MACHINE.argcount - 1; i++) { + + installPrimitiveProcedure( + '>', + new ArityAtLeast(2), + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; testArgument(MACHINE, - 'number', - isNumber, - MACHINE.env[MACHINE.env.length - 1 - i], - i, - '<='); - if (! (jsnums.lessThanOrEqual(MACHINE.env[MACHINE.env.length - 1 - i], + 'number', isNumber, firstArg, 0, '>'); + for (var i = 0; i < MACHINE.argcount - 1; i++) { + testArgument(MACHINE, + 'number', + isNumber, + MACHINE.env[MACHINE.env.length - 1 - i], + i, + '>'); + if (! (jsnums.greaterThan(MACHINE.env[MACHINE.env.length - 1 - i], MACHINE.env[MACHINE.env.length - 1 - i - 1]))) { - return false; + return false; + } } - } - return true; - }; - Primitives['<='].arity = new ArityAtLeast(2); - Primitives['<='].displayName = '<='; + return true; + }); + + installPrimitiveProcedure( + '<=', + new ArityAtLeast(2), + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + testArgument(MACHINE, + 'number', isNumber, firstArg, 0, '<='); + for (var i = 0; i < MACHINE.argcount - 1; i++) { + testArgument(MACHINE, + 'number', + isNumber, + MACHINE.env[MACHINE.env.length - 1 - i], + i, + '<='); + if (! (jsnums.lessThanOrEqual(MACHINE.env[MACHINE.env.length - 1 - i], + MACHINE.env[MACHINE.env.length - 1 - i - 1]))) { + return false; + } + } + return true; + }); - Primitives['>='] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - testArgument(MACHINE, - 'number', isNumber, firstArg, 0, '>='); - for (var i = 0; i < MACHINE.argcount - 1; i++) { + installPrimitiveProcedure( + '>=', + new ArityAtLeast(2), + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + testArgument(MACHINE, + 'number', isNumber, firstArg, 0, '>='); + for (var i = 0; i < MACHINE.argcount - 1; i++) { + testArgument(MACHINE, + 'number', + isNumber, + MACHINE.env[MACHINE.env.length - 1 - i], + i, + '>='); + if (! (jsnums.greaterThanOrEqual(MACHINE.env[MACHINE.env.length - 1 - i], + MACHINE.env[MACHINE.env.length - 1 - i - 1]))) { + return false; + } + } + return true; + }); + + + installPrimitiveProcedure( + '+', + new ArityAtLeast(0), + function(MACHINE) { + var result = 0; + var i = 0; + for (i=0; i < MACHINE.argcount; i++) { + testArgument(MACHINE, + 'number', + isNumber, + MACHINE.env[MACHINE.env.length - 1 - i], + i, + '+'); + result = jsnums.add(result, MACHINE.env[MACHINE.env.length - 1 - i]); + }; + return result; + }); + + + installPrimitiveProcedure( + '*', + new ArityAtLeast(0), + function(MACHINE) { + var result = 1; + var i = 0; + for (i=0; i < MACHINE.argcount; i++) { + testArgument(MACHINE, + 'number', + isNumber, + MACHINE.env[MACHINE.env.length - 1 - i], + i, + '*'); + result = jsnums.multiply(result, MACHINE.env[MACHINE.env.length - 1 - i]); + } + return result; + }); + + installPrimitiveProcedure( + '-', + new ArityAtLeast(1), + function(MACHINE) { + if (MACHINE.argcount === 1) { + testArgument(MACHINE, + 'number', + isNumber, + MACHINE.env[MACHINE.env.length-1], + 0, + '-'); + 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++) { + testArgument(MACHINE, + 'number', + isNumber, + MACHINE.env[MACHINE.env.length-1-i], + i, + '-'); + result = jsnums.subtract(result, MACHINE.env[MACHINE.env.length - 1 - i]); + } + return result; + }); + + installPrimitiveProcedure( + '/', + new ArityAtLeast(1), + function(MACHINE) { + testArgument(MACHINE, + 'number', + isNumber, + MACHINE.env[MACHINE.env.length - 1], + 0, + '/'); + var result = MACHINE.env[MACHINE.env.length - 1]; + for (var i = 1; i < MACHINE.argcount; i++) { + testArgument(MACHINE, + 'number', + isNumber, + MACHINE.env[MACHINE.env.length-1-i], + i, + '/'); + result = jsnums.divide(result, MACHINE.env[MACHINE.env.length - 1 - i]); + } + return result; + }); + + + installPrimitiveProcedure( + 'add1', + 1, + 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); + }); + + + installPrimitiveProcedure( + 'sub1', + 1, + 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); + }); + + + installPrimitiveProcedure( + 'zero?', + 1, + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + return jsnums.equals(firstArg, 0); + }); + + + installPrimitiveProcedure( + 'cons', + 2, + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + var secondArg = MACHINE.env[MACHINE.env.length-2]; + return makePair(firstArg, secondArg); + }); + + + installPrimitiveProcedure( + 'list', + new ArityAtLeast(0), + function(MACHINE) { + var result = NULL; + for (var i = 0; i < MACHINE.argcount; i++) { + result = makePair(MACHINE.env[MACHINE.env.length - (MACHINE.argcount - i)], + result); + } + return result; + }); + + installPrimitiveProcedure( + 'car', + 1, + function(MACHINE) { testArgument(MACHINE, - 'number', - isNumber, - MACHINE.env[MACHINE.env.length - 1 - i], - i, - '>='); - if (! (jsnums.greaterThanOrEqual(MACHINE.env[MACHINE.env.length - 1 - i], - MACHINE.env[MACHINE.env.length - 1 - i - 1]))) { - return false; + 'pair', + isPair, + MACHINE.env[MACHINE.env.length - 1], + 0, + 'car'); + var firstArg = MACHINE.env[MACHINE.env.length-1]; + return firstArg.first; + }); + + installPrimitiveProcedure( + 'cdr', + 1, + function(MACHINE) { + testArgument(MACHINE, + 'pair', + isPair, + MACHINE.env[MACHINE.env.length - 1], + 0, + 'cdr'); + var firstArg = MACHINE.env[MACHINE.env.length-1]; + return firstArg.rest; + }); + + installPrimitiveProcedure( + 'pair?', + 1, + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + return isPair(firstArg); + }); + + installPrimitiveProcedure( + 'set-car!', + 2, + function(MACHINE) { + testArgument(MACHINE, + 'pair', + isPair, + MACHINE.env[MACHINE.env.length - 1], + 0, + 'set-car!'); + var firstArg = MACHINE.env[MACHINE.env.length-1]; + var secondArg = MACHINE.env[MACHINE.env.length-2]; + firstArg.first = secondArg; + return VOID; + }); + + + installPrimitiveProcedure( + 'set-cdr!', + 2, + function(MACHINE) { + testArgument(MACHINE, + 'pair', + isPair, + MACHINE.env[MACHINE.env.length - 1], + 0, + 'set-cdr!'); + var firstArg = MACHINE.env[MACHINE.env.length-1]; + var secondArg = MACHINE.env[MACHINE.env.length-2]; + firstArg.rest = secondArg; + return VOID; + }); + + + installPrimitiveProcedure( + 'not', + 1, + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + return (firstArg === false); + }); + + + installPrimitiveProcedure( + 'null?', + 1, + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + return firstArg === NULL; + }); + + + installPrimitiveProcedure( + 'vector', + new ArityAtLeast(0), + function(MACHINE) { + var i; + var result = []; + for (i = 0; i < MACHINE.argcount; i++) { + result.push(MACHINE.env[MACHINE.env.length-1-i]); } - } - return true; - }; - Primitives['>='].arity = new ArityAtLeast(2); - Primitives['>='].displayName = '>='; - + var newVector = makeVector.apply(null, result); + return newVector; + }); - Primitives['+'] = function(MACHINE) { - var result = 0; - var i = 0; - for (i=0; i < MACHINE.argcount; i++) { + + installPrimitiveProcedure( + 'vector->list', + 1, + function(MACHINE) { testArgument(MACHINE, - 'number', - isNumber, - MACHINE.env[MACHINE.env.length - 1 - i], - i, - '+'); - result = jsnums.add(result, MACHINE.env[MACHINE.env.length - 1 - i]); - }; - return result; - }; - Primitives['+'].arity = new ArityAtLeast(0); - Primitives['+'].displayName = '+'; - - - Primitives['*'] = function(MACHINE) { - var result = 1; - var i = 0; - for (i=0; i < MACHINE.argcount; i++) { - testArgument(MACHINE, - 'number', - isNumber, - MACHINE.env[MACHINE.env.length - 1 - i], - i, - '*'); - result = jsnums.multiply(result, MACHINE.env[MACHINE.env.length - 1 - i]); - } - return result; - }; - Primitives['*'].arity = new ArityAtLeast(0); - Primitives['*'].displayName = '*'; - - Primitives['-'] = function(MACHINE) { - if (MACHINE.argcount === 1) { - testArgument(MACHINE, - 'number', - isNumber, - MACHINE.env[MACHINE.env.length-1], - 0, - '-'); - 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++) { - testArgument(MACHINE, - 'number', - isNumber, - MACHINE.env[MACHINE.env.length-1-i], - i, - '-'); - result = jsnums.subtract(result, MACHINE.env[MACHINE.env.length - 1 - i]); - } - return result; - }; - Primitives['-'].arity = new ArityAtLeast(1); - Primitives['-'].displayName = '-'; - - Primitives['/'] = function(MACHINE) { - testArgument(MACHINE, - 'number', - isNumber, - MACHINE.env[MACHINE.env.length - 1], - 0, - '/'); - var result = MACHINE.env[MACHINE.env.length - 1]; - for (var i = 1; i < MACHINE.argcount; i++) { - testArgument(MACHINE, - 'number', - isNumber, - MACHINE.env[MACHINE.env.length-1-i], - i, - '/'); - result = jsnums.divide(result, MACHINE.env[MACHINE.env.length - 1 - i]); - } - return result; - }; - Primitives['/'].arity = new ArityAtLeast(1); - 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]; - return makePair(firstArg, secondArg); - }; - Primitives['cons'].arity = 2; - Primitives['cons'].displayName = 'cons'; - - - Primitives['list'] = function(MACHINE) { - var result = NULL; - for (var i = 0; i < MACHINE.argcount; i++) { - result = makePair(MACHINE.env[MACHINE.env.length - (MACHINE.argcount - i)], - result); - } - return result; - }; - Primitives['list'].arity = new ArityAtLeast(0); - Primitives['list'].displayName = 'list'; - - Primitives['car'] = function(MACHINE) { - testArgument(MACHINE, - 'pair', - isPair, - MACHINE.env[MACHINE.env.length - 1], - 0, - 'car'); - var firstArg = MACHINE.env[MACHINE.env.length-1]; - return firstArg.first; - }; - Primitives['car'].arity = 1; - Primitives['car'].displayName = 'car'; - - Primitives['cdr'] = function(MACHINE) { - testArgument(MACHINE, - 'pair', - isPair, - MACHINE.env[MACHINE.env.length - 1], - 0, - 'cdr'); - var firstArg = MACHINE.env[MACHINE.env.length-1]; - return firstArg.rest; - }; - Primitives['cdr'].arity = 1; - Primitives['cdr'].displayName = 'cdr'; - - Primitives['pair?'] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - return isPair(firstArg); - }; - Primitives['pair?'].arity = 1; - Primitives['pair?'].displayName = 'pair?'; - - Primitives['set-car!'] = function(MACHINE) { - testArgument(MACHINE, - 'pair', - isPair, - MACHINE.env[MACHINE.env.length - 1], - 0, - 'set-car!'); - var firstArg = MACHINE.env[MACHINE.env.length-1]; - var secondArg = MACHINE.env[MACHINE.env.length-2]; - firstArg.first = secondArg; - return VOID; - }; - Primitives['set-car!'].arity = 2; - Primitives['set-car!'].displayName = 'set-car!'; - - Primitives['set-cdr!'] = function(MACHINE) { - testArgument(MACHINE, - 'pair', - isPair, - MACHINE.env[MACHINE.env.length - 1], - 0, - 'set-cdr!'); - var firstArg = MACHINE.env[MACHINE.env.length-1]; - var secondArg = MACHINE.env[MACHINE.env.length-2]; - firstArg.rest = secondArg; - return VOID; - }; - Primitives['set-cdr!'].arity = 2; - Primitives['set-cdr!'].displayName = 'set-cdr!'; - - Primitives['not'] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - return (firstArg === false); - }; - Primitives['not'].arity = 1; - Primitives['not'].displayName = 'not'; - - Primitives['null'] = NULL; - - Primitives['null?'] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - return firstArg === NULL; - }; - Primitives['null?'].arity = 1; - Primitives['null?'].displayName = 'null?'; - - Primitives['vector'] = function(MACHINE) { - var i; - var result = []; - for (i = 0; i < MACHINE.argcount; i++) { - result.push(MACHINE.env[MACHINE.env.length-1-i]); - } - var newVector = makeVector.apply(null, result); - return newVector; - }; - Primitives['vector'].arity = new ArityAtLeast(0); - Primitives['vector'].displayName = 'vector'; - - Primitives['vector->list'] = function(MACHINE) { - testArgument(MACHINE, - 'vector', - isVector, - MACHINE.env[MACHINE.env.length - 1], - 0, - 'vector->list'); - var elts = MACHINE.env[MACHINE.env.length-1].elts; - var i; - var result = NULL; - for (i = 0; i < elts.length; i++) { - result = makePair(elts[elts.length - 1 - i], result); - } - return result; - }; - Primitives['vector->list'].arity = 1; - Primitives['vector->list'].displayName = 'vector->list'; - - Primitives['list->vector'] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - var result = []; - while (firstArg !== NULL) { - result.push(firstArg.first); - firstArg = firstArg.rest; - } - return makeVector.apply(null, result); - }; - Primitives['list->vector'].arity = 1; - Primitives['list->vector'].displayName = 'list->vector'; - - Primitives['vector-ref'] = function(MACHINE) { - testArgument(MACHINE, - 'vector', - isVector, - MACHINE.env[MACHINE.env.length - 1], - 0, - 'vector-ref'); - var elts = MACHINE.env[MACHINE.env.length-1].elts; - var index = MACHINE.env[MACHINE.env.length-2]; - return elts[index]; - }; - Primitives['vector-ref'].arity = 2; - Primitives['vector-ref'].displayName = 'vector-ref'; - - Primitives['vector-set!'] = function(MACHINE) { - testArgument(MACHINE, - 'vector', - isVector, - MACHINE.env[MACHINE.env.length - 1], - 0, - 'vector-set!'); - testArgument(MACHINE, - 'natural', - isNatural, - MACHINE.env[MACHINE.env.length - 2], - 1, - 'vector-set!'); - var elts = MACHINE.env[MACHINE.env.length-1].elts; - var index = jsnums.toFixnum(MACHINE.env[MACHINE.env.length-2]); - var val = MACHINE.env[MACHINE.env.length-3]; - elts[index] = val; - return VOID; - }; - Primitives['vector-set!'].arity = 3; - Primitives['vector-set!'].displayName = 'vector-set!'; - - - Primitives['vector-length'] = function(MACHINE) { - testArgument(MACHINE, - 'vector', - isVector, - MACHINE.env[MACHINE.env.length - 1], - 0, - 'vector-length'); - var firstArg = MACHINE.env[MACHINE.env.length-1].elts; - return firstArg.length; - }; - Primitives['vector-length'].arity = 1; - Primitives['vector-length'].displayName = 'vector-length'; - - - Primitives['make-vector'] = function(MACHINE) { - var value = 0; - testArgument(MACHINE, - 'natural', - isNatural, - MACHINE.env[MACHINE.env.length - 1], - 0, - 'make-vector'); - if (MACHINE.argcount == 2) { - value = MACHINE.env[MACHINE.env.length - 2]; - } - var length = jsnums.toFixnum(MACHINE.env[MACHINE.env.length-1]); - var arr = []; - for(var i = 0; i < length; i++) { - arr[i] = value; - } - return makeVector.apply(null, arr); - }; - Primitives['make-vector'].arity = makeList(1, 2); - Primitives['make-vector'].displayName = 'make-vector'; - - - - - - Primitives['symbol?'] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - return typeof(firstArg) === 'string'; - }; - Primitives['symbol?'].arity = 1; - Primitives['symbol?'].displayName = 'symbol?'; - - Primitives['symbol->string'] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - return firstArg; - }; - Primitives['symbol->string'].arity = 1; - Primitives['symbol->string'].displayName = 'symbol->string'; - - Primitives['string-append'] = function(MACHINE) { - var buffer = []; - var i; - for (i = 0; i < MACHINE.argcount; i++) { - buffer.push(MACHINE.env[MACHINE.env.length - 1 - i]); - } - return buffer.join(''); - }; - Primitives['string-append'].arity = new ArityAtLeast(0); - Primitives['string-append'].displayName = 'string-append'; - - Primitives['string-length'] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - return firstArg.length; - }; - Primitives['string-length'].arity = 1; - Primitives['string-length'].displayName = 'string-length'; - - Primitives['box'] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - var result = [firstArg]; - return result; - }; - Primitives['box'].arity = 1; - Primitives['box'].displayName = 'box'; - - Primitives['unbox'] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - return firstArg[0]; - }; - Primitives['unbox'].arity = 1; - Primitives['unbox'].displayName = 'unbox'; - - Primitives['set-box!'] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - var secondArg = MACHINE.env[MACHINE.env.length-2]; - firstArg[0] = secondArg; - return VOID; - }; - Primitives['set-box!'].arity = 2; - Primitives['set-box!'].displayName = 'set-box!'; - - Primitives['void'] = function(MACHINE) { - return VOID; - }; - Primitives['void'].arity = new ArityAtLeast(0); - Primitives['void'].displayName = 'void'; - - Primitives['eq?'] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - var secondArg = MACHINE.env[MACHINE.env.length-2]; - return firstArg === secondArg; - }; - Primitives['eq?'].arity = 2; - Primitives['eq?'].displayName = 'eq?'; - - Primitives['equal?'] = function(MACHINE) { - var firstArg = MACHINE.env[MACHINE.env.length-1]; - var secondArg = MACHINE.env[MACHINE.env.length-2]; - return isEqual(firstArg, secondArg); - }; - Primitives['equal?'].arity = 2; - Primitives['equal?'].displayName = 'equal?'; - - - var isEqual = types.isEqual; - - - Primitives['member'] = function(MACHINE) { - var x = MACHINE.env[MACHINE.env.length-1]; - var lst = MACHINE.env[MACHINE.env.length-2]; - var originalLst = lst; - while (true) { - if (! isList(lst)) { - raise(MACHINE, new Error("member: expected list" - + " as argument #2" - + " but received " + originalLst + " instead")); + 'vector', + isVector, + MACHINE.env[MACHINE.env.length - 1], + 0, + 'vector->list'); + var elts = MACHINE.env[MACHINE.env.length-1].elts; + var i; + var result = NULL; + for (i = 0; i < elts.length; i++) { + result = makePair(elts[elts.length - 1 - i], result); } - if (lst === NULL) { - return false; + return result; + }); + + + installPrimitiveProcedure( + 'list->vector', + 1, + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + var result = []; + while (firstArg !== NULL) { + result.push(firstArg.first); + firstArg = firstArg.rest; } - if (isEqual(x, (lst.first))) { - return lst; - } - lst = lst.rest; - } - }; - Primitives['member'].arity = 2; - Primitives['member'].displayName = 'member'; + return makeVector.apply(null, result); + }); - - Primitives['reverse'] = function(MACHINE) { - var rev = NULL; - var lst = MACHINE.env[MACHINE.env.length-1]; - while(lst !== NULL) { + installPrimitiveProcedure( + 'vector-ref', + 2, + function(MACHINE) { testArgument(MACHINE, - 'pair', isPair, lst, 0, 'reverse'); - rev = makePair(lst.first, rev); - lst = lst.rest; - } - return rev; - }; - Primitives['reverse'].arity = 1; - Primitives['reverse'].displayName = 'reverse'; + 'vector', + isVector, + MACHINE.env[MACHINE.env.length - 1], + 0, + 'vector-ref'); + var elts = MACHINE.env[MACHINE.env.length-1].elts; + var index = MACHINE.env[MACHINE.env.length-2]; + return elts[index]; + }); + + + installPrimitiveProcedure( + 'vector-set!', + 3, + function(MACHINE) { + testArgument(MACHINE, + 'vector', + isVector, + MACHINE.env[MACHINE.env.length - 1], + 0, + 'vector-set!'); + testArgument(MACHINE, + 'natural', + isNatural, + MACHINE.env[MACHINE.env.length - 2], + 1, + 'vector-set!'); + var elts = MACHINE.env[MACHINE.env.length-1].elts; + var index = jsnums.toFixnum(MACHINE.env[MACHINE.env.length-2]); + var val = MACHINE.env[MACHINE.env.length-3]; + elts[index] = val; + return VOID; + }); + + installPrimitiveProcedure( + 'vector-length', + 1, + function(MACHINE) { + testArgument(MACHINE, + 'vector', + isVector, + MACHINE.env[MACHINE.env.length - 1], + 0, + 'vector-length'); + var firstArg = MACHINE.env[MACHINE.env.length-1].elts; + return firstArg.length; + }); + + + installPrimitiveProcedure( + 'make-vector', + makeList(1, 2), + function(MACHINE) { + var value = 0; + testArgument(MACHINE, + 'natural', + isNatural, + MACHINE.env[MACHINE.env.length - 1], + 0, + 'make-vector'); + if (MACHINE.argcount == 2) { + value = MACHINE.env[MACHINE.env.length - 2]; + } + var length = jsnums.toFixnum(MACHINE.env[MACHINE.env.length-1]); + var arr = []; + for(var i = 0; i < length; i++) { + arr[i] = value; + } + return makeVector.apply(null, arr); + }); + + + + installPrimitiveProcedure( + 'symbol?', + 1, + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + return typeof(firstArg) === 'string'; + }); + + installPrimitiveProcedure( + 'symbol->string', + 1, + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + return firstArg; + }); + + installPrimitiveProcedure( + 'string-append', + new ArityAtLeast(0), + function(MACHINE) { + var buffer = []; + var i; + for (i = 0; i < MACHINE.argcount; i++) { + buffer.push(MACHINE.env[MACHINE.env.length - 1 - i]); + } + return buffer.join(''); + }); + + installPrimitiveProcedure( + 'string-length', + 1, + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + return firstArg.length; + }); + + installPrimitiveProcedure( + 'box', + 1, + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + var result = [firstArg]; + return result; + }); + + installPrimitiveProcedure( + 'unbox', + 1, + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + return firstArg[0]; + }); + + installPrimitiveProcedure( + 'set-box!', + 2, + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + var secondArg = MACHINE.env[MACHINE.env.length-2]; + firstArg[0] = secondArg; + return VOID; + }); + + installPrimitiveProcedure( + 'void', + new ArityAtLeast(0), + function(MACHINE) { + return VOID; + }); + + installPrimitiveProcedure( + 'eq?', + 2, + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + var secondArg = MACHINE.env[MACHINE.env.length-2]; + return firstArg === secondArg; + }); + + installPrimitiveProcedure( + 'equal?', + 2, + function(MACHINE) { + var firstArg = MACHINE.env[MACHINE.env.length-1]; + var secondArg = MACHINE.env[MACHINE.env.length-2]; + return isEqual(firstArg, secondArg); + }); + + + + installPrimitiveProcedure( + 'member', + 2, + function(MACHINE) { + var x = MACHINE.env[MACHINE.env.length-1]; + var lst = MACHINE.env[MACHINE.env.length-2]; + var originalLst = lst; + while (true) { + if (! isList(lst)) { + raise(MACHINE, new Error("member: expected list" + + " as argument #2" + + " but received " + originalLst + " instead")); + } + if (lst === NULL) { + return false; + } + if (isEqual(x, (lst.first))) { + return lst; + } + lst = lst.rest; + } + }); + + + + installPrimitiveProcedure( + 'reverse', + 1, + function(MACHINE) { + var rev = NULL; + var lst = MACHINE.env[MACHINE.env.length-1]; + while(lst !== NULL) { + testArgument(MACHINE, + 'pair', isPair, lst, 0, 'reverse'); + rev = makePair(lst.first, rev); + lst = lst.rest; + } + return rev; + }); @@ -1474,7 +1510,5 @@ if(this['plt'] === undefined) { this['plt'] = {}; } exports['HaltError'] = HaltError; - - scope.link.announceReady('runtime'); })(this['plt']); \ No newline at end of file diff --git a/scribblings/manual.scrbl b/scribblings/manual.scrbl index 907454a..ef12dbf 100644 --- a/scribblings/manual.scrbl +++ b/scribblings/manual.scrbl @@ -4,8 +4,12 @@ planet/resolver scribble/eval racket/sandbox - (for-label racket/base)) + (for-label racket/base) + racket/runtime-path + + "../js-assembler/get-js-vm-implemented-primitives.rkt") +@(define-runtime-path whalesong-path "..") @;; I may need an evaluator for some small examples. @@ -228,12 +232,15 @@ commands to do something interesting...) @section{Internals} @;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Skip this section if you're a regular user: this is really notes internal -to Whalesong development. +Please skip this section if you're a regular user: this is really +notes internal to Whalesong development, and is not relevant to most +people. -(This section should describe the internal details of the runtime, -including the type map from Racket values to JavaScript values. It -should also describe how to write FFI bindings.) + +These are notes that describe the internal details of the +implementation, including the type map from Racket values to +JavaScript values. It should also describe how to write FFI +bindings, eventually. @subsection{Architecture} @@ -246,15 +253,15 @@ compile that to an intermediate language, and finally assemble JavaScript. @verbatim|{ - AST IL JS - parse-bytecode.rkt ----------> compiler.rkt --------> assembler.rkt -------> - (todo) + AST IL + parse-bytecode.rkt -----> compiler.rkt ----> assembler.rkt + }| The IL is intended to be translated straightforwardly. We currently -have an assembler to JavaScript, as well as a simulator -in @filepath{simulator.rkt}. The simulator allows us to test the compiler in a -controlled environment. +have an assembler to JavaScript @filepath{js-assembler/assemble.rkt}, +as well as a simulator in @filepath{simulator/simulator.rkt}. The +simulator allows us to test the compiler in a controlled environment. @subsection{parser/parse-bytecode.rkt} @@ -275,7 +282,7 @@ we don't need any of the register-saving infrastructure in the original compiler. We also need to support slightly different linkage structures, since we want to support multiple value contexts. We're trying to generate code that works effectively on a machine like the -one described in \url{http://plt.eecs.northwestern.edu/racket-machine/}. +one described in @url{http://plt.eecs.northwestern.edu/racket-machine/}. The intermediate language is defined in @filepath{il-structs.rkt}, and a @@ -313,7 +320,7 @@ calls work: @item{ The head of each basic-blocked function checks to see if we should trampoline - (http://en.wikipedia.org/wiki/Trampoline_(computers))} + (@url{http://en.wikipedia.org/wiki/Trampoline_(computers)})} @item{We support a limited form of computed jump by assigning an attribute to the function corresponding to a return point. See @@ -350,11 +357,55 @@ browser for testing output. @;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -@section{Incomplete features} +@subsection{Incomplete features} @;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (This section should describe what needs to get done next.) +The only types that are mapped so far are +@itemlist[ +@item{immutable strings} +@item{numbers} +@item{pairs} +@item{null} +@item{void} +@item{vectors} +] +We need to bring around the following types previously defined in @tt{js-vm}: +(This list will shrink as I get to the work!) +@itemlist[ +@item{immutable vectors} +@item{regexp} +@item{byteRegexp} +@item{character} +@item{box} +@item{placeholder} +@item{path} +@item{bytes} +@item{immutable bytes} +@item{keywords} +@item{hash} +@item{hasheq} +@item{color} +@item{structs} +@item{struct types} +@item{exceptions} +@item{thread cells} + +@item{big bang info} +@item{worldConfig} +@item{effectType} +@item{renderEffectType} +@item{readerGraph} +] + +What are the list of primitives in @filepath{js-vm-primitives.js}? They are: +@(apply itemlist (map (lambda (name) + (item (symbol->string name))) + js-vm-primitive-names)) + + + (I should catalog the bug list in GitHub, as well as the feature list, so I have a better idea of what's needed to complete the project.)