Merge remote-tracking branch 'origin/master'

This commit is contained in:
Danny Yoo 2011-06-05 16:12:39 -04:00
commit 31f96bd40a
11 changed files with 6136 additions and 5750 deletions

90
NOTES
View File

@ -595,4 +595,92 @@ benchmarks
being able to write modules in javascript
being able to bundle external resources (like images)
being able to bundle external resources (like images)
----------------------------------------------------------------------
June 2, 2011
We need a mechanism for attaching external resources to a program and
to be able to refer to them. External resources refer to things like:
Images
HTML files
Sounds
Each of these should be findable by path, and they should also be
packaged when a program is built. The user should be able to say
something like this:
(define my-html-file (local-resource-path ...))
and the packager should automatically be able to statically walk
though all local-resource-path calls.
These files must be represented as separate files.
There may be additional resources that need to be included, though
they aren't directly used in the program. (Say, for example, an image
is refered to in an html resource. Maybe we should have a toplevel
element (include-resources ...) that take in a bunch of
build-resource-path.
(include-resources (build-resource-path ...)
...)
The Whalesong make system needs to know how to deal with resources.
I also want to be able to refer to external web resources, and somehow
capture or cache them during building.
Imaginary: I would like to be able to write something like this:
(define my-file (remote-resource-path ...))
and be able to treat my-file as if it were a local resource. During
packaging, the file should be directly downloaded.
Other things to consider:
We may need to consider workarounds for same-origin policy
restrictions.
Can resources be input-port sources?
----------------------------------------------------------------------
I've at least imported the libraries from Moby so that they're loaded
in the same runtime. However, there are some ugly things happening
here: for some reason, there's a circular dependency between types and
helpers. That dependency needs to be cut! I've added a workaround
for now, using the link library to delay initialization until the
modules are present, but this is an unsatisfactory solution. We
really shouldn't get into this problem in the first place... I must
do a lot of code cleanup once things stabilize...
----------------------------------------------------------------------
June 3, 2011
How do I test what I'm integrating? I should at least absorb the
js-vm test suite, at the very least.
11am: I'm going to spend the next hour trying to disentangle the
circularity between helpers and types.
The parameters I'm using to control bounce are too high for Firefox,
leading it to raise the dialog about an out of control jva process. Not good.

View File

@ -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)])))
@ -124,6 +125,97 @@
(format "[~a, ~a]" (first vals) (loop (rest vals)))])))
;; Slightly ridiculous definition, but I need it to get around what appear to
;; be Typed Racket bugs in its numeric tower.
(define-predicate int? Integer)
(: assemble-numeric-constant (Number -> String))
(define (assemble-numeric-constant a-num)
(: floating-number->js (Real -> String))
(define (floating-number->js a-num)
(cond
[(eqv? a-num -0.0)
"jsnums.negative_zero"]
[(eqv? a-num +inf.0)
"jsnums.inf"]
[(eqv? a-num -inf.0)
"jsnums.negative_inf"]
[(eqv? a-num +nan.0)
"jsnums.nan"]
[else
(string-append "jsnums.makeFloat(" (number->string a-num) ")")]))
;; FIXME: fix the type signature when typed-racket isn't breaking on
;; (define-predicate ExactRational? (U Exact-Rational))
(: rational-number->js (Real -> String))
(define (rational-number->js a-num)
(cond [(= (denominator a-num) 1)
(string-append (integer->js (ensure-integer (numerator a-num))))]
[else
(string-append "jsnums.makeRational("
(integer->js (ensure-integer (numerator a-num)))
", "
(integer->js (ensure-integer (denominator a-num)))
")")]))
(: ensure-integer (Any -> Integer))
(define (ensure-integer x)
(if (int? x)
x
(error "not an integer: ~e" x)))
(: integer->js (Integer -> String))
(define (integer->js an-int)
(cond
;; non-overflow case
[(< (abs an-int) 9e15)
(number->string an-int)]
;; overflow case
[else
(string-append "jsnums.makeBignum("
(format "~s" (number->string an-int))
")")]))
(cond
[(and (exact? a-num) (rational? a-num))
(rational-number->js a-num)]
[(real? a-num)
(floating-number->js a-num)]
[(complex? a-num)
(string-append "jsnums.makeComplex("
(assemble-numeric-constant (real-part a-num))
", "
(assemble-numeric-constant (imag-part a-num))
")")]))
(: assemble-lexical-reference (EnvLexicalReference -> String))

View File

@ -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)))]))
"&&")
")"))
@ -123,7 +151,7 @@
(let: ([test-string : String
(case domain
[(number)
(format "(typeof(~a) === 'number')"
(format "(jsnums.isSchemeNumber(~a))"
operand-string)]
[(string)
(format "(typeof(~a) === 'string')"

View File

@ -1,16 +1,54 @@
#lang racket/base
;; Function to get the runtime library.
;;
;; The resulting Javascript will produce a file that loads:
;;
;;
;; jquery at the the toplevel
;; HashTable at the toplevel
;; jsnums at the toplevel
;;
;; followed by:
;;
;; plt.link
;; plt.helpers
;; plt.types
;; plt.primitives
;; plt.runtime
(require racket/contract
racket/runtime-path
racket/port)
(provide/contract [get-runtime (-> string?)])
(define-runtime-path jquery.js "runtime-src/jquery-1.6.1.min.js")
(define-runtime-path runtime.js "mini-runtime.js")
(define-runtime-path hashtable.js "runtime-src/jshashtable-2.1_src.js")
(define-runtime-path jsnums.js "runtime-src/js-numbers.js")
(define-runtime-path link.js "runtime-src/link.js")
(define-runtime-path helpers.js "runtime-src/helpers.js")
(define-runtime-path types.js "runtime-src/types.js")
(define-runtime-path primitives.js "runtime-src/primitives.js")
(define-runtime-path runtime.js "runtime-src/runtime.js")
;; The order matters here. link needs to come near the top, because
;; the other modules below have some circular dependencies that are resolved
;; by link.
(define files (list jquery.js
hashtable.js
jsnums.js
link.js
helpers.js
types.js
primitives.js
runtime.js))
(define (path->string p)
@ -19,11 +57,8 @@
(port->string ip))))
(define text (string-append
(path->string jquery.js)
(path->string runtime.js)))
(define text (apply string-append
(map path->string files)))
(define (get-runtime)

View File

@ -4,6 +4,7 @@
"quote-cdata.rkt"
"../make.rkt"
"../make-structs.rkt"
(planet dyoo/closure-compile:1:1)
(prefix-in runtime: "get-runtime.rkt")
(prefix-in racket: racket/base))
@ -87,13 +88,6 @@
;; get-runtime: -> string
(define (get-runtime)
(let ([buffer (open-output-string)])
(write-runtime buffer)
(get-output-string buffer)))
;; write-runtime: output-port -> void
(define (write-runtime op)
(let ([packaging-configuration
@ -121,6 +115,19 @@
(define *the-runtime*
(let ([buffer (open-output-string)])
(write-runtime buffer)
(closure-compile
(get-output-string buffer))))
;; get-runtime: -> string
(define (get-runtime)
*the-runtime*)
;; *header* : string
@ -144,7 +151,8 @@ EOF
(package source-code
#:should-follow? (lambda (src p) #t)
#:output-port buffer)
(get-output-string buffer)))
(closure-compile
(get-output-string buffer))))
@ -152,7 +160,8 @@ EOF
(define (get-standalone-code source-code)
(let ([buffer (open-output-string)])
(write-standalone-code source-code buffer)
(get-output-string buffer)))
(closure-compile
(get-output-string buffer))))
;; write-standalone-code: source output-port -> void

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
// Lightweight linking of the modules.
// There are circular dependencies across the modules unfortunately, so we
// need a mechanism for letting them link to each other.
if (! this['plt']) { this['plt'] = {}; }
(function(scope) {
var link = {};
scope['link'] = link;
// link.ready: (string (string -> void)) -> void
// When the name announces that it's ready, calls the function f.
link.ready = function(name, f) {
readyWaiters[name] = readyWaiters[name] || [];
readyWaiters[name].push(f);
if (linkIsReady[name]) {
notifySingle(f, name);
}
};
// link.announceReady: string -> void
// Lets the world know that the name is ready.
link.announceReady = function(name) {
var i;
linkIsReady[name] = true;
notifyAll(name);
};
// notifyAll: string -> void
// Tell all listeners that the name is ready.
var notifyAll = function(name) {
var waiters = readyWaiters[name] || [], i;
for (i = 0 ; i < waiters.length; i++) {
notifySingle(waiters[i], name);
}
readyWaiters[name] = [];
};
// Tell a single listener that the name is ready.
var notifySingle = function(f, name) {
setTimeout(function() { f(name); },
0);
};
// linkIsReady: (Hashtable String Boolean)
var linkIsReady = {};
// readyWaiters: (Hashtable String (Arrayof (String -> Void)))
var readyWaiters = {};
})(this['plt']);

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,10 @@
if(this['plt'] === undefined) {
this['plt'] = {};
}
if(this['plt'] === undefined) { this['plt'] = {}; }
// All of the values here are namespaced under "plt.runtime".
(function() {
this['plt']['runtime'] = {};
var exports = this['plt']['runtime'];
(function(scope) {
var runtime = {};
scope['runtime'] = runtime;
@ -26,12 +23,10 @@
};
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 &&
@ -608,9 +603,9 @@
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];
@ -622,8 +617,8 @@
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;
}
}
@ -644,8 +639,8 @@
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;
}
}
@ -665,8 +660,8 @@
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;
}
}
@ -686,8 +681,8 @@
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;
}
}
@ -708,8 +703,8 @@
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;
}
}
@ -729,7 +724,7 @@
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;
};
@ -747,7 +742,7 @@
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;
};
@ -762,7 +757,7 @@
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++) {
@ -772,7 +767,7 @@
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;
};
@ -794,7 +789,7 @@
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;
};
@ -802,6 +797,47 @@
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];
@ -899,39 +935,6 @@
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 = [];
@ -997,7 +1000,7 @@
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;
@ -1013,7 +1016,7 @@
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;
@ -1031,7 +1034,7 @@
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;
@ -1343,8 +1346,8 @@
// Executes all programs that have been labeled as a main module
var invokeMains = function(machine, succ, fail) {
plt.runtime.ready(function() {
machine = machine || plt.runtime.currentMachine;
runtime.ready(function() {
machine = machine || runtime.currentMachine;
succ = succ || function() {};
fail = fail || function() {};
var mainModules = machine.mainModules.slice();
@ -1368,7 +1371,7 @@
// Exports
var exports = runtime;
exports['currentMachine'] = new Machine();
exports['invokeMains'] = invokeMains;
@ -1433,4 +1436,6 @@
exports['HaltError'] = HaltError;
}).call(this);
scope.link.announceReady('runtime');
})(this['plt']);

File diff suppressed because it is too large Load Diff

View File

@ -213,9 +213,15 @@ var comet = function() {
sendRequest("/eval",
function(req) {
// debug:
if (window.console && typeof(console.log) === 'function') { console.log(req.responseText); }
var invoke = eval(req.responseText)();
//if (window.console && typeof(console.log) === 'function') {
// console.log(req.responseText);
//}
try {
var invoke = eval(req.responseText)();
} catch (e) {
if (window.console && window.console.log && e.stack) { window.console.log(e.stack); }
throw e;
}
var output = [];
var startTime, endTime;
var params = { currentDisplayer: function(v) {