mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-24 20:30:28 +02:00
compile call/cc, yee ha
* libguile/vm-i-system.c (call, goto/args): Add a FIXME for handling the case in which a call to the interpreter returns a values object. (call/cc, goto/cc): Flesh out, and handle full continuations (with the C stack also). * module/language/scheme/translate.scm (custom-transformer-table): Compile call-with-current-continuation. This is necessary so that the called procedure is called in tail position. * module/system/il/compile.scm (codegen): Translate apply to goto/apply, call/cc to goto/cc, etc when in tail position.
This commit is contained in:
parent
f63ea2ce78
commit
76282387ea
3 changed files with 80 additions and 14 deletions
|
@ -524,6 +524,7 @@ VM_DEFINE_INSTRUCTION (call, "call", 1, -1, 1)
|
||||||
POP (args);
|
POP (args);
|
||||||
SYNC_REGISTER ();
|
SYNC_REGISTER ();
|
||||||
*sp = scm_apply (x, args, SCM_EOL);
|
*sp = scm_apply (x, args, SCM_EOL);
|
||||||
|
/* FIXME what if SCM_VALUESP(*sp) */
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -694,6 +695,7 @@ VM_DEFINE_INSTRUCTION (goto_args, "goto/args", 1, -1, 1)
|
||||||
POP (args);
|
POP (args);
|
||||||
SYNC_REGISTER ();
|
SYNC_REGISTER ();
|
||||||
*sp = scm_apply (x, args, SCM_EOL);
|
*sp = scm_apply (x, args, SCM_EOL);
|
||||||
|
/* FIXME what if SCM_VALUESP(*sp) */
|
||||||
goto vm_return;
|
goto vm_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -830,20 +832,67 @@ VM_DEFINE_INSTRUCTION (goto_apply, "goto/apply", 1, -1, 1)
|
||||||
goto vm_goto_args;
|
goto vm_goto_args;
|
||||||
}
|
}
|
||||||
|
|
||||||
VM_DEFINE_INSTRUCTION (call_cc, "call/cc", 1, 1, 1)
|
VM_DEFINE_INSTRUCTION (call_cc, "call/cc", 0, 1, 1)
|
||||||
{
|
{
|
||||||
SYNC_BEFORE_GC ();
|
int first;
|
||||||
PUSH (capture_vm_cont (vp));
|
SCM proc, cont;
|
||||||
nargs = 1;
|
POP (proc);
|
||||||
goto vm_call;
|
SYNC_ALL ();
|
||||||
|
cont = scm_make_continuation (&first);
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
PUSH (proc);
|
||||||
|
PUSH (cont);
|
||||||
|
nargs = 1;
|
||||||
|
goto vm_call;
|
||||||
|
}
|
||||||
|
else if (SCM_VALUESP (cont))
|
||||||
|
{
|
||||||
|
/* multiple values returned to continuation */
|
||||||
|
SCM values;
|
||||||
|
values = scm_struct_ref (cont, SCM_INUM0);
|
||||||
|
if (SCM_NULLP (values))
|
||||||
|
goto vm_error_wrong_num_args;
|
||||||
|
/* non-tail context does not accept multiple values? */
|
||||||
|
PUSH (SCM_CAR (values));
|
||||||
|
NEXT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PUSH (cont);
|
||||||
|
NEXT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VM_DEFINE_INSTRUCTION (goto_cc, "goto/cc", 1, 1, 1)
|
VM_DEFINE_INSTRUCTION (goto_cc, "goto/cc", 0, 1, 1)
|
||||||
{
|
{
|
||||||
SYNC_BEFORE_GC ();
|
int first;
|
||||||
PUSH (capture_vm_cont (vp));
|
SCM proc, cont;
|
||||||
nargs = 1;
|
POP (proc);
|
||||||
goto vm_goto_args;
|
SYNC_ALL ();
|
||||||
|
cont = scm_make_continuation (&first);
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
PUSH (proc);
|
||||||
|
PUSH (cont);
|
||||||
|
nargs = 1;
|
||||||
|
goto vm_goto_args;
|
||||||
|
}
|
||||||
|
else if (SCM_VALUESP (cont))
|
||||||
|
{
|
||||||
|
/* multiple values returned to continuation */
|
||||||
|
SCM values;
|
||||||
|
values = scm_struct_ref (cont, SCM_INUM0);
|
||||||
|
nvalues = scm_ilength (values);
|
||||||
|
while (!SCM_NULLP (values))
|
||||||
|
PUSH (SCM_CAR (values));
|
||||||
|
goto vm_return_values;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PUSH (cont);
|
||||||
|
goto vm_return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VM_DEFINE_INSTRUCTION (return, "return", 0, 0, 1)
|
VM_DEFINE_INSTRUCTION (return, "return", 0, 0, 1)
|
||||||
|
|
|
@ -331,6 +331,17 @@
|
||||||
((,producer ,consumer)
|
((,producer ,consumer)
|
||||||
(make-ghil-mv-call e l (retrans producer) (retrans consumer))))
|
(make-ghil-mv-call e l (retrans producer) (retrans consumer))))
|
||||||
|
|
||||||
|
;; FIXME: not hygienic, relies on @call-with-current-continuation
|
||||||
|
;; not being shadowed
|
||||||
|
(call-with-current-continuation
|
||||||
|
((,proc)
|
||||||
|
(retrans `(@call-with-current-continuation ,proc)))
|
||||||
|
(else #f))
|
||||||
|
|
||||||
|
(@call-with-current-continuation
|
||||||
|
((,proc)
|
||||||
|
(make-ghil-inline e l 'call/cc (list (retrans proc)))))
|
||||||
|
|
||||||
(receive
|
(receive
|
||||||
((,formals ,producer-exp . ,body)
|
((,formals ,producer-exp . ,body)
|
||||||
;; Lovely, self-referential usage. Not strictly necessary, the
|
;; Lovely, self-referential usage. Not strictly necessary, the
|
||||||
|
|
|
@ -331,10 +331,16 @@
|
||||||
((<ghil-inline> env loc inline args)
|
((<ghil-inline> env loc inline args)
|
||||||
;; ARGS...
|
;; ARGS...
|
||||||
;; (INST NARGS)
|
;; (INST NARGS)
|
||||||
;; FIXME: translate between call and goto/args, etc
|
(let ((tail-table '((call . goto/args)
|
||||||
(push-call! loc inline args)
|
(apply . goto/apply)
|
||||||
(maybe-drop)
|
(call/cc . goto/cc))))
|
||||||
(maybe-return))
|
(cond ((and tail (assq-ref tail-table inline))
|
||||||
|
=> (lambda (tail-inst)
|
||||||
|
(push-call! loc tail-inst args)))
|
||||||
|
(else
|
||||||
|
(push-call! loc inline args)
|
||||||
|
(maybe-drop)
|
||||||
|
(maybe-return)))))
|
||||||
|
|
||||||
((<ghil-values> env loc values)
|
((<ghil-values> env loc values)
|
||||||
(cond (tail ;; (lambda () (values 1 2))
|
(cond (tail ;; (lambda () (values 1 2))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue