mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-17 17:20:29 +02:00
Compile cps $prompt form to javascript
This commit is contained in:
parent
48e84c5a2c
commit
5827ad4f03
4 changed files with 85 additions and 8 deletions
|
@ -1,6 +1,7 @@
|
||||||
(define-module (language cps compile-js)
|
(define-module (language cps compile-js)
|
||||||
#:use-module (language cps)
|
#:use-module (language cps)
|
||||||
#:use-module (language js-il)
|
#:use-module ((language js-il)
|
||||||
|
#:renamer (lambda (x) (if (eqv? x 'make-prompt) 'make-prompt* x)))
|
||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:export (compile-js))
|
#:export (compile-js))
|
||||||
|
|
||||||
|
@ -106,6 +107,11 @@
|
||||||
(make-continue label (map make-id (cons* proc k args))))
|
(make-continue label (map make-id (cons* proc k args))))
|
||||||
(($ $values values)
|
(($ $values values)
|
||||||
(make-continue k (map make-id values)))
|
(make-continue k (map make-id values)))
|
||||||
|
(($ $prompt escape? tag handler)
|
||||||
|
(make-seq
|
||||||
|
(list
|
||||||
|
(make-prompt* escape? tag handler)
|
||||||
|
(make-continue k '()))))
|
||||||
(_
|
(_
|
||||||
(make-continue k (list (compile-exp* exp))))))
|
(make-continue k (list (compile-exp* exp))))))
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
make-branch branch
|
make-branch branch
|
||||||
make-return return
|
make-return return
|
||||||
make-id id
|
make-id id
|
||||||
|
make-seq seq
|
||||||
|
make-prompt prompt
|
||||||
))
|
))
|
||||||
|
|
||||||
;; Copied from (language cps)
|
;; Copied from (language cps)
|
||||||
|
@ -64,6 +66,8 @@
|
||||||
(define-js-type branch test consequence alternate)
|
(define-js-type branch test consequence alternate)
|
||||||
(define-js-type id name)
|
(define-js-type id name)
|
||||||
(define-js-type return val)
|
(define-js-type return val)
|
||||||
|
(define-js-type seq body)
|
||||||
|
(define-js-type prompt escape? tag handler)
|
||||||
|
|
||||||
(define (unparse-js exp)
|
(define (unparse-js exp)
|
||||||
(match exp
|
(match exp
|
||||||
|
|
|
@ -155,6 +155,15 @@
|
||||||
(make-call (make-refine *scheme* (make-const "Closure"))
|
(make-call (make-refine *scheme* (make-const "Closure"))
|
||||||
(list (name->id label) (make-const nfree)))))
|
(list (name->id label) (make-const nfree)))))
|
||||||
|
|
||||||
|
(($ il:prompt escape? tag handler)
|
||||||
|
;; never a tailcall
|
||||||
|
(make-call (make-refine (make-refine *scheme* (make-const "primitives"))
|
||||||
|
(make-const "prompt"))
|
||||||
|
(list (compile-const escape?) (name->id tag) (name->id handler))))
|
||||||
|
|
||||||
|
(($ il:seq body)
|
||||||
|
(make-block (map compile-exp body)))
|
||||||
|
|
||||||
(($ il:id name)
|
(($ il:id name)
|
||||||
(name->id name))))
|
(name->id name))))
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ var scheme = {
|
||||||
env : {},
|
env : {},
|
||||||
cache: [],
|
cache: [],
|
||||||
builtins: [],
|
builtins: [],
|
||||||
|
dynstack : [],
|
||||||
// TODO: placeholders
|
// TODO: placeholders
|
||||||
FALSE : false,
|
FALSE : false,
|
||||||
TRUE : true,
|
TRUE : true,
|
||||||
|
@ -283,22 +284,55 @@ scheme.primitives["resolve"] = function (sym, is_bound) {
|
||||||
scheme.initial_cont = function (x) { return x; };
|
scheme.initial_cont = function (x) { return x; };
|
||||||
scheme.primitives.return = function (x) { return x; };
|
scheme.primitives.return = function (x) { return x; };
|
||||||
scheme.is_true = function (obj) {
|
scheme.is_true = function (obj) {
|
||||||
return !(obj == scheme.FALSE || obj == scheme.NIL);
|
return !(obj === scheme.FALSE || obj === scheme.NIL);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Builtins
|
||||||
|
var apply = function(self, k, f, arg) {
|
||||||
|
return f.fun(f.freevars, k, arg);
|
||||||
|
};
|
||||||
|
|
||||||
|
var values = function(self, k, arg) {
|
||||||
|
|
||||||
|
return k(arg);
|
||||||
|
};
|
||||||
|
|
||||||
|
var abort_to_prompt = function(self, k, prompt, arg) {
|
||||||
|
|
||||||
|
var idx = find_prompt(prompt);
|
||||||
|
var spec = scheme.dynstack[idx];
|
||||||
|
|
||||||
|
var kont = undefined; // actual value doesn't matter
|
||||||
|
|
||||||
|
if (!scheme.is_true(spec[1])) {
|
||||||
|
// TODO: handle multivalue continations
|
||||||
|
// compare with callcc
|
||||||
|
var f = function (self, k2, val) {
|
||||||
|
return k(val);
|
||||||
|
};
|
||||||
|
kont = new scheme.Closure(f, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
unwind(idx);
|
||||||
|
|
||||||
|
var handler = spec[2];
|
||||||
|
|
||||||
|
return handler(kont, arg);
|
||||||
|
};
|
||||||
|
|
||||||
|
var call_with_values = not_implemented_yet;
|
||||||
|
|
||||||
var callcc = function (self, k, closure) {
|
var callcc = function (self, k, closure) {
|
||||||
var f = function (self, k2, val) {
|
var f = function (self, k2, val) {
|
||||||
return k(val);
|
return k(val);
|
||||||
};
|
};
|
||||||
return closure.fun(closure, k, new scheme.Closure(f, 0));
|
return closure.fun(closure, k, new scheme.Closure(f, 0));
|
||||||
};
|
};
|
||||||
|
scheme.builtins[0] = new scheme.Closure(apply, 0);
|
||||||
|
scheme.builtins[1] = new scheme.Closure(values, 0);
|
||||||
|
scheme.builtins[2] = new scheme.Closure(abort_to_prompt, 0);
|
||||||
|
scheme.builtins[3] = new scheme.Closure(call_with_values, 0);
|
||||||
scheme.builtins[4] = new scheme.Closure(callcc, 0);
|
scheme.builtins[4] = new scheme.Closure(callcc, 0);
|
||||||
// #define FOR_EACH_VM_BUILTIN(M) \
|
|
||||||
// M(apply, APPLY, 2, 0, 1) \
|
|
||||||
// M(values, VALUES, 0, 0, 1) \
|
|
||||||
// M(abort_to_prompt, ABORT_TO_PROMPT, 1, 0, 1) \
|
|
||||||
// M(call_with_values, CALL_WITH_VALUES, 2, 0, 0) \
|
|
||||||
// M(call_with_current_continuation, CALL_WITH_CURRENT_CONTINUATION, 1, 0, 0)
|
|
||||||
|
|
||||||
// Structs
|
// Structs
|
||||||
scheme.primitives["struct?"] = not_implemented_yet;
|
scheme.primitives["struct?"] = not_implemented_yet;
|
||||||
|
@ -331,3 +365,27 @@ scheme.primitives["variable?"] = not_implemented_yet;
|
||||||
// Dynamic Wind
|
// Dynamic Wind
|
||||||
scheme.primitives["wind"] = not_implemented_yet;
|
scheme.primitives["wind"] = not_implemented_yet;
|
||||||
scheme.primitives["unwind"] = not_implemented_yet;
|
scheme.primitives["unwind"] = not_implemented_yet;
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
scheme.primitives["prompt"] = function(escape_only, tag, handler){
|
||||||
|
scheme.dynstack.unshift([tag, escape_only, handler]);
|
||||||
|
};
|
||||||
|
|
||||||
|
var unwind = function (idx) {
|
||||||
|
// TODO: call winders
|
||||||
|
scheme.dynstack = scheme.dynstack.slice(idx+1);
|
||||||
|
};
|
||||||
|
|
||||||
|
var find_prompt = function(prompt) {
|
||||||
|
var eq = scheme.primitives["eq?"];
|
||||||
|
function test(x){
|
||||||
|
return scheme.is_true(eq(x,prompt)) || scheme.is_true(eq(x,scheme.TRUE));
|
||||||
|
};
|
||||||
|
for (idx in scheme.dynstack) {
|
||||||
|
if (test(scheme.dynstack[idx][0])) {
|
||||||
|
return idx;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// FIXME: should error
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue