mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-01 04:10:18 +02:00
add special case for (apply values ...)
* libguile/vm-engine.c (vm_run): Move nvalues to the top level, to avoid (spurious, it seems) gcc warnings about it being used uninitialized. * libguile/vm-i-system.c (halt, return/values): Adapt to gcc silliness. Deindent some of return/values. (return/values*): New instruction, does what (apply values . args) would do. * module/language/scheme/translate.scm (custom-transformer-table): Move the apply and @apply cases here from inline.scm, because we need some more cleverness when dealing with cases like (apply values . args). (lookup-apply-transformer): Define an eval transformer for `values', turning it into ghil-values*. * module/system/il/compile.scm (codegen): Compile <ghil-values*> into return/values*. * module/system/il/ghil.scm: Add <ghil-values*> and accessors. (ghil-lookup): Add optional argument, define?, which if false tells us not to actually cache the binding if it is not found in the toplevel. * module/system/il/inline.scm: Remove apply clauses. * module/system/vm/frame.scm (bootstrap-frame?): Update heuristic for bootstrap-frame?, as the bootstrap frame is now 5 bytes since it accepts multiple values.
This commit is contained in:
parent
a222b0fa91
commit
ef24c01bff
7 changed files with 115 additions and 57 deletions
|
@ -65,6 +65,7 @@ vm_run (SCM vm, SCM program, SCM args)
|
||||||
|
|
||||||
/* Internal variables */
|
/* Internal variables */
|
||||||
int nargs = 0;
|
int nargs = 0;
|
||||||
|
int nvalues = 0;
|
||||||
long start_time = scm_c_get_internal_run_time ();
|
long start_time = scm_c_get_internal_run_time ();
|
||||||
// SCM dynwinds = SCM_EOL;
|
// SCM dynwinds = SCM_EOL;
|
||||||
SCM err_msg;
|
SCM err_msg;
|
||||||
|
|
|
@ -55,7 +55,6 @@ VM_DEFINE_INSTRUCTION (nop, "nop", 0, 0, 0)
|
||||||
VM_DEFINE_INSTRUCTION (halt, "halt", 0, 0, 0)
|
VM_DEFINE_INSTRUCTION (halt, "halt", 0, 0, 0)
|
||||||
{
|
{
|
||||||
SCM ret;
|
SCM ret;
|
||||||
int nvalues;
|
|
||||||
vp->time += scm_c_get_internal_run_time () - start_time;
|
vp->time += scm_c_get_internal_run_time () - start_time;
|
||||||
HALT_HOOK ();
|
HALT_HOOK ();
|
||||||
nvalues = SCM_I_INUM (*sp--);
|
nvalues = SCM_I_INUM (*sp--);
|
||||||
|
@ -859,11 +858,16 @@ VM_DEFINE_INSTRUCTION (return, "return", 0, 0, 1)
|
||||||
|
|
||||||
VM_DEFINE_INSTRUCTION (return_values, "return/values", 1, -1, -1)
|
VM_DEFINE_INSTRUCTION (return_values, "return/values", 1, -1, -1)
|
||||||
{
|
{
|
||||||
|
/* nvalues declared at top level, because for some reason gcc seems to think
|
||||||
|
that perhaps it might be used without declaration. Fooey to that, I say. */
|
||||||
|
SCM *data;
|
||||||
|
|
||||||
|
nvalues = FETCH ();
|
||||||
|
vm_return_values:
|
||||||
EXIT_HOOK ();
|
EXIT_HOOK ();
|
||||||
RETURN_HOOK ();
|
RETURN_HOOK ();
|
||||||
{
|
|
||||||
int nvalues = FETCH ();
|
data = SCM_FRAME_DATA_ADDRESS (fp);
|
||||||
SCM *data = SCM_FRAME_DATA_ADDRESS (fp);
|
|
||||||
#ifdef THE_GOVERNMENT_IS_AFTER_ME
|
#ifdef THE_GOVERNMENT_IS_AFTER_ME
|
||||||
if (stack_base != data + 4)
|
if (stack_base != data + 4)
|
||||||
abort ();
|
abort ();
|
||||||
|
@ -906,9 +910,6 @@ VM_DEFINE_INSTRUCTION (return_values, "return/values", 1, -1, -1)
|
||||||
else
|
else
|
||||||
goto vm_error_no_values;
|
goto vm_error_no_values;
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Restore the last program */
|
/* Restore the last program */
|
||||||
program = SCM_FRAME_PROGRAM (fp);
|
program = SCM_FRAME_PROGRAM (fp);
|
||||||
CACHE_PROGRAM ();
|
CACHE_PROGRAM ();
|
||||||
|
@ -917,6 +918,28 @@ VM_DEFINE_INSTRUCTION (return_values, "return/values", 1, -1, -1)
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VM_DEFINE_INSTRUCTION (return_values_star, "return/values*", 1, -1, -1)
|
||||||
|
{
|
||||||
|
SCM l;
|
||||||
|
|
||||||
|
nvalues = FETCH ();
|
||||||
|
#ifdef THE_GOVERNMENT_IS_AFTER_ME
|
||||||
|
if (nvalues < 1)
|
||||||
|
abort ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
nvalues--;
|
||||||
|
POP (l);
|
||||||
|
while (SCM_CONSP (l))
|
||||||
|
{
|
||||||
|
PUSH (SCM_CAR (l));
|
||||||
|
l = SCM_CDR (l);
|
||||||
|
nvalues++;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto vm_return_values;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Local Variables:
|
Local Variables:
|
||||||
c-file-style: "gnu"
|
c-file-style: "gnu"
|
||||||
|
|
|
@ -302,10 +302,36 @@
|
||||||
(start-stack
|
(start-stack
|
||||||
((,tag ,expr) (retrans expr)))
|
((,tag ,expr) (retrans expr)))
|
||||||
|
|
||||||
|
;; FIXME: not hygienic, relies on @apply not being shadowed
|
||||||
|
(apply
|
||||||
|
(,args (retrans `(@apply ,@args))))
|
||||||
|
|
||||||
|
(@apply
|
||||||
|
((,proc ,arg1 . ,args)
|
||||||
|
(let ((args (cons (retrans arg1) (map retrans args))))
|
||||||
|
(cond ((and (symbol? proc)
|
||||||
|
(not (ghil-lookup e proc #f))
|
||||||
|
(and=> (module-variable (current-module) proc)
|
||||||
|
(lambda (var)
|
||||||
|
(and (variable-bound? var)
|
||||||
|
(lookup-apply-transformer (variable-ref var))))))
|
||||||
|
;; that is, a variable, not part of this compilation
|
||||||
|
;; unit, but defined in the toplevel environment, and has
|
||||||
|
;; an apply transformer registered
|
||||||
|
=> (lambda (t) (t e l args)))
|
||||||
|
(else (make-ghil-inline e l 'apply
|
||||||
|
(cons (retrans proc) args)))))))
|
||||||
|
|
||||||
(values
|
(values
|
||||||
((,x) (retrans x))
|
((,x) (retrans x))
|
||||||
(,args (make-ghil-values e l (map retrans args))))))
|
(,args (make-ghil-values e l (map retrans args))))))
|
||||||
|
|
||||||
|
(define (lookup-apply-transformer proc)
|
||||||
|
(cond ((eq? proc values)
|
||||||
|
(lambda (e l args)
|
||||||
|
(make-ghil-values* e l args)))
|
||||||
|
(else #f)))
|
||||||
|
|
||||||
(define (trans-quasiquote e l x level)
|
(define (trans-quasiquote e l x level)
|
||||||
(cond ((not (pair? x)) x)
|
(cond ((not (pair? x)) x)
|
||||||
((memq (car x) '(unquote unquote-splicing))
|
((memq (car x) '(unquote unquote-splicing))
|
||||||
|
|
|
@ -312,6 +312,17 @@
|
||||||
(push-code! #f (make-glil-call #:inst 'variable-ref #:nargs 0))
|
(push-code! #f (make-glil-call #:inst 'variable-ref #:nargs 0))
|
||||||
(push-call! loc 'call values))))
|
(push-call! loc 'call values))))
|
||||||
|
|
||||||
|
((<ghil-values*> env loc values)
|
||||||
|
(cond (tail ;; (lambda () (apply values '(1 2)))
|
||||||
|
(push-call! loc 'return/values* values))
|
||||||
|
(drop ;; (lambda () (apply values '(1 2)) 3)
|
||||||
|
(for-each comp-drop values))
|
||||||
|
(else ;; (lambda () (list (apply values '(10 12)) 1))
|
||||||
|
(push-code! #f (make-glil-const #:obj 'values))
|
||||||
|
(push-code! #f (make-glil-call #:inst 'link-now #:nargs 1))
|
||||||
|
(push-code! #f (make-glil-call #:inst 'variable-ref #:nargs 0))
|
||||||
|
(push-call! loc 'apply values))))
|
||||||
|
|
||||||
((<ghil-call> env loc proc args)
|
((<ghil-call> env loc proc args)
|
||||||
;; PROC
|
;; PROC
|
||||||
;; ARGS...
|
;; ARGS...
|
||||||
|
|
|
@ -75,6 +75,9 @@
|
||||||
<ghil-values> make-ghil-values ghil-values?
|
<ghil-values> make-ghil-values ghil-values?
|
||||||
ghil-values-env ghil-values-loc ghil-values-values
|
ghil-values-env ghil-values-loc ghil-values-values
|
||||||
|
|
||||||
|
<ghil-values*> make-ghil-values* ghil-values*?
|
||||||
|
ghil-values*-env ghil-values*-loc ghil-values*-values
|
||||||
|
|
||||||
<ghil-var> make-ghil-var ghil-var?
|
<ghil-var> make-ghil-var ghil-var?
|
||||||
ghil-var-env ghil-var-name ghil-var-kind ghil-var-type ghil-var-value
|
ghil-var-env ghil-var-name ghil-var-kind ghil-var-type ghil-var-value
|
||||||
ghil-var-index
|
ghil-var-index
|
||||||
|
@ -114,7 +117,8 @@
|
||||||
(<ghil-lambda> env loc vars rest meta body)
|
(<ghil-lambda> env loc vars rest meta body)
|
||||||
(<ghil-call> env loc proc args)
|
(<ghil-call> env loc proc args)
|
||||||
(<ghil-inline> env loc inline args)
|
(<ghil-inline> env loc inline args)
|
||||||
(<ghil-values> env loc values)))
|
(<ghil-values> env loc values)
|
||||||
|
(<ghil-values*> env loc values)))
|
||||||
|
|
||||||
|
|
||||||
;;;
|
;;;
|
||||||
|
@ -168,15 +172,17 @@
|
||||||
;; which will be looked up at runtime with respect to the module that
|
;; which will be looked up at runtime with respect to the module that
|
||||||
;; was current when the lambda was bound, at runtime. The variable will
|
;; was current when the lambda was bound, at runtime. The variable will
|
||||||
;; be resolved when it is first used.
|
;; be resolved when it is first used.
|
||||||
(define (ghil-lookup env sym)
|
(define (ghil-lookup env sym . define?)
|
||||||
(let loop ((e env))
|
(let loop ((e env))
|
||||||
(record-case e
|
(record-case e
|
||||||
((<ghil-toplevel-env> table)
|
((<ghil-toplevel-env> table)
|
||||||
(let ((key (cons (module-name (current-module)) sym)))
|
(let ((key (cons (module-name (current-module)) sym)))
|
||||||
(or (assoc-ref table key)
|
(or (assoc-ref table key)
|
||||||
|
(and (or (null? define?)
|
||||||
|
(car define?))
|
||||||
(let ((var (make-ghil-var (car key) (cdr key) 'module)))
|
(let ((var (make-ghil-var (car key) (cdr key) 'module)))
|
||||||
(apush! key var (ghil-toplevel-env-table e))
|
(apush! key var (ghil-toplevel-env-table e))
|
||||||
var))))
|
var)))))
|
||||||
((<ghil-env> parent table variables)
|
((<ghil-env> parent table variables)
|
||||||
(let ((found (assq-ref table sym)))
|
(let ((found (assq-ref table sym)))
|
||||||
(if found
|
(if found
|
||||||
|
|
|
@ -198,12 +198,3 @@
|
||||||
(x) x
|
(x) x
|
||||||
(x y) (cons x y)
|
(x y) (cons x y)
|
||||||
(x y . rest) (cons x (cons* y . rest)))
|
(x y . rest) (cons x (cons* y . rest)))
|
||||||
|
|
||||||
(define-inline apply (proc . args)
|
|
||||||
(apply proc . args))
|
|
||||||
|
|
||||||
;; From ice-9/r4rs.scm; actually not that bad of a strategy for handling
|
|
||||||
;; the (apply apply ...) case
|
|
||||||
|
|
||||||
(define-inline @apply (proc . args)
|
|
||||||
(apply proc . args))
|
|
||||||
|
|
|
@ -46,8 +46,8 @@
|
||||||
|
|
||||||
(define (bootstrap-frame? frame)
|
(define (bootstrap-frame? frame)
|
||||||
(let ((code (program-bytecode (frame-program frame))))
|
(let ((code (program-bytecode (frame-program frame))))
|
||||||
(and (= (uniform-vector-length code) 3)
|
(and (= (uniform-vector-length code) 5)
|
||||||
(= (uniform-vector-ref code 2)
|
(= (uniform-vector-ref code 4)
|
||||||
(instruction->opcode 'halt)))))
|
(instruction->opcode 'halt)))))
|
||||||
|
|
||||||
(define (make-frame-chain frame addr)
|
(define (make-frame-chain frame addr)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue