mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 11:50:28 +02:00
prompt handlers are always inline
* libguile/control.h (SCM_F_PROMPT_INLINE, SCM_PROMPT_INLINE_P): Remove; prompts always have "inline" handlers now. * libguile/control.c (scm_c_make_prompt): Remove inline_handler_p arg. * libguile/vm-i-system.c (prompt): * module/language/assembly/decompile-bytecode.scm (decode-load-program): * module/language/assembly/compile-bytecode.scm (write-bytecode): Adapt to prompt changes. * module/language/glil.scm (make-glil-prompt, glil-prompt-inline?): Remove inline? flag. (parse-glil, unparse-glil): * module/language/glil/compile-assembly.scm (glil->assembly): Adapt to <glil-prompt> change. * module/language/tree-il/compile-glil.scm (flatten): Require the handler of a <prompt> to be a lambda-case. * module/language/tree-il/primitives.scm (*primitive-expand-table*): Ensure that the handler of a <prompt> is a lambda-case. * module/language/tree-il/inline.scm (inline!): Simplify a degenerate case: (lambda args (apply (lambda ...) args)) => (lambda ...).
This commit is contained in:
parent
f5b1f76af4
commit
ea6b18e82f
10 changed files with 78 additions and 99 deletions
|
@ -49,16 +49,13 @@ SCM_DEFINE (scm_atprompt, "@prompt", 4, 0, 0,
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
SCM
|
SCM
|
||||||
scm_c_make_prompt (SCM vm, SCM k, SCM handler, scm_t_uint8 inline_handler_p,
|
scm_c_make_prompt (SCM vm, SCM k, SCM handler, scm_t_uint8 escape_only_p)
|
||||||
scm_t_uint8 escape_only_p)
|
|
||||||
{
|
{
|
||||||
scm_t_bits tag;
|
scm_t_bits tag;
|
||||||
SCM ret;
|
SCM ret;
|
||||||
struct scm_prompt_registers *regs;
|
struct scm_prompt_registers *regs;
|
||||||
|
|
||||||
tag = scm_tc7_prompt;
|
tag = scm_tc7_prompt;
|
||||||
if (inline_handler_p)
|
|
||||||
tag |= SCM_F_PROMPT_INLINE;
|
|
||||||
if (escape_only_p)
|
if (escape_only_p)
|
||||||
tag |= SCM_F_PROMPT_ESCAPE;
|
tag |= SCM_F_PROMPT_ESCAPE;
|
||||||
ret = scm_words (tag, 5);
|
ret = scm_words (tag, 5);
|
||||||
|
|
|
@ -20,14 +20,12 @@
|
||||||
#define SCM_CONTROL_H
|
#define SCM_CONTROL_H
|
||||||
|
|
||||||
|
|
||||||
#define SCM_F_PROMPT_INLINE 0x1
|
#define SCM_F_PROMPT_ESCAPE 0x1
|
||||||
#define SCM_F_PROMPT_ESCAPE 0x2
|
|
||||||
|
|
||||||
#define SCM_PROMPT_P(x) (!SCM_IMP (x) && SCM_TYP7(x) == scm_tc7_prompt)
|
#define SCM_PROMPT_P(x) (!SCM_IMP (x) && SCM_TYP7(x) == scm_tc7_prompt)
|
||||||
#define SCM_PROMPT_FLAGS(x) (SCM_CELL_WORD ((x), 0) >> 8)
|
#define SCM_PROMPT_FLAGS(x) (SCM_CELL_WORD ((x), 0) >> 8)
|
||||||
#define SCM_PROMPT_INLINE_P(x) (SCM_PROMPT_FLAGS (x) & SCM_F_PROMPT_INLINE)
|
|
||||||
#define SCM_PROMPT_ESCAPE_P(x) (SCM_PROMPT_FLAGS (x) & SCM_F_PROMPT_ESCAPE)
|
#define SCM_PROMPT_ESCAPE_P(x) (SCM_PROMPT_FLAGS (x) & SCM_F_PROMPT_ESCAPE)
|
||||||
#define SCM_PROMPT_TAG(x) (SCM_CELL_OBJECT ((x), 1)
|
#define SCM_PROMPT_TAG(x) (SCM_CELL_OBJECT ((x), 1))
|
||||||
#define SCM_PROMPT_REGISTERS(x) ((struct scm_prompt_registers*)SCM_CELL_WORD ((x), 2))
|
#define SCM_PROMPT_REGISTERS(x) ((struct scm_prompt_registers*)SCM_CELL_WORD ((x), 2))
|
||||||
#define SCM_PROMPT_DYNENV(x) (SCM_CELL_OBJECT ((x), 3))
|
#define SCM_PROMPT_DYNENV(x) (SCM_CELL_OBJECT ((x), 3))
|
||||||
#define SCM_PROMPT_HANDLER(x) (SCM_CELL_OBJECT ((x), 4))
|
#define SCM_PROMPT_HANDLER(x) (SCM_CELL_OBJECT ((x), 4))
|
||||||
|
@ -44,7 +42,6 @@ struct scm_prompt_registers
|
||||||
|
|
||||||
|
|
||||||
SCM_INTERNAL SCM scm_c_make_prompt (SCM vm, SCM k, SCM handler,
|
SCM_INTERNAL SCM scm_c_make_prompt (SCM vm, SCM k, SCM handler,
|
||||||
scm_t_uint8 inline_handler_p,
|
|
||||||
scm_t_uint8 escape_only_p);
|
scm_t_uint8 escape_only_p);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1450,13 +1450,12 @@ VM_DEFINE_INSTRUCTION (82, make_symbol, "make-symbol", 0, 1, 1)
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
VM_DEFINE_INSTRUCTION (83, prompt, "prompt", 5, 2, 0)
|
VM_DEFINE_INSTRUCTION (83, prompt, "prompt", 4, 2, 0)
|
||||||
{
|
{
|
||||||
scm_t_int32 offset;
|
scm_t_int32 offset;
|
||||||
scm_t_uint8 inline_handler_p, escape_only_p;
|
scm_t_uint8 escape_only_p;
|
||||||
SCM k, handler, prompt;
|
SCM k, handler, prompt;
|
||||||
|
|
||||||
inline_handler_p = FETCH ();
|
|
||||||
escape_only_p = FETCH ();
|
escape_only_p = FETCH ();
|
||||||
FETCH_OFFSET (offset);
|
FETCH_OFFSET (offset);
|
||||||
POP (handler);
|
POP (handler);
|
||||||
|
@ -1466,13 +1465,12 @@ VM_DEFINE_INSTRUCTION (83, prompt, "prompt", 5, 2, 0)
|
||||||
/* Push the prompt onto the dynamic stack. The setjmp itself has to be local
|
/* Push the prompt onto the dynamic stack. The setjmp itself has to be local
|
||||||
to this procedure. */
|
to this procedure. */
|
||||||
/* FIXME: do more error checking */
|
/* FIXME: do more error checking */
|
||||||
prompt = scm_c_make_prompt (vm, k, handler, inline_handler_p, escape_only_p);
|
prompt = scm_c_make_prompt (vm, k, handler, escape_only_p);
|
||||||
scm_i_set_dynwinds (scm_cons (prompt, scm_i_dynwinds ()));
|
scm_i_set_dynwinds (scm_cons (prompt, scm_i_dynwinds ()));
|
||||||
if (SCM_PROMPT_SETJMP (prompt))
|
if (SCM_PROMPT_SETJMP (prompt))
|
||||||
{
|
{
|
||||||
/* The prompt exited nonlocally. Cache the regs back from the vp, and go
|
/* The prompt exited nonlocally. Cache the regs back from the vp, and go
|
||||||
to the handler or post-handler label. (The meaning of the label differs
|
to the handler.
|
||||||
depending on whether the prompt's handler is rendered inline or not.)
|
|
||||||
*/
|
*/
|
||||||
CACHE_REGISTER (); /* Really we only need SP. FP and IP should be
|
CACHE_REGISTER (); /* Really we only need SP. FP and IP should be
|
||||||
unmodified. */
|
unmodified. */
|
||||||
|
|
|
@ -119,8 +119,7 @@
|
||||||
((br-if-nargs-lt ,hi ,lo ,l) (write-byte hi) (write-byte lo) (write-break l))
|
((br-if-nargs-lt ,hi ,lo ,l) (write-byte hi) (write-byte lo) (write-break l))
|
||||||
((br-if-nargs-gt ,hi ,lo ,l) (write-byte hi) (write-byte lo) (write-break l))
|
((br-if-nargs-gt ,hi ,lo ,l) (write-byte hi) (write-byte lo) (write-break l))
|
||||||
((mv-call ,n ,l) (write-byte n) (write-break l))
|
((mv-call ,n ,l) (write-byte n) (write-break l))
|
||||||
((prompt ,inline-handler? ,escape-only? ,l)
|
((prompt ,escape-only? ,l) (write-byte escape-only?) (write-break l))
|
||||||
(write-byte inline-handler?) (write-byte escape-only?) (write-break l))
|
|
||||||
(else
|
(else
|
||||||
(cond
|
(cond
|
||||||
((< (instruction-length inst) 0)
|
((< (instruction-length inst) 0)
|
||||||
|
|
|
@ -90,8 +90,8 @@
|
||||||
(lp (cons `(,br ,hi ,lo ,(ensure-label rel1 rel2 rel3)) out)))
|
(lp (cons `(,br ,hi ,lo ,(ensure-label rel1 rel2 rel3)) out)))
|
||||||
((mv-call ,n ,rel1 ,rel2 ,rel3)
|
((mv-call ,n ,rel1 ,rel2 ,rel3)
|
||||||
(lp (cons `(mv-call ,n ,(ensure-label rel1 rel2 rel3)) out)))
|
(lp (cons `(mv-call ,n ,(ensure-label rel1 rel2 rel3)) out)))
|
||||||
((prompt ,n0 ,n1 ,rel1 ,rel2 ,rel3)
|
((prompt ,n0 ,rel1 ,rel2 ,rel3)
|
||||||
(lp (cons `(prompt ,n0 ,n1 ,(ensure-label rel1 rel2 rel3)) out)))
|
(lp (cons `(prompt ,n0 ,(ensure-label rel1 rel2 rel3)) out)))
|
||||||
(else
|
(else
|
||||||
(lp (cons exp out))))))))))
|
(lp (cons exp out))))))))))
|
||||||
|
|
||||||
|
|
|
@ -75,8 +75,7 @@
|
||||||
<glil-mv-call> make-glil-mv-call glil-mv-call?
|
<glil-mv-call> make-glil-mv-call glil-mv-call?
|
||||||
glil-mv-call-nargs glil-mv-call-ra
|
glil-mv-call-nargs glil-mv-call-ra
|
||||||
|
|
||||||
<glil-prompt> make-glil-prompt glil-prompt?
|
<glil-prompt> make-glil-prompt glil-prompt? glil-prompt-label glil-prompt-escape-only?
|
||||||
glil-prompt-label glil-prompt-inline? glil-prompt-escape-only?
|
|
||||||
|
|
||||||
parse-glil unparse-glil))
|
parse-glil unparse-glil))
|
||||||
|
|
||||||
|
@ -105,7 +104,7 @@
|
||||||
(<glil-branch> inst label)
|
(<glil-branch> inst label)
|
||||||
(<glil-call> inst nargs)
|
(<glil-call> inst nargs)
|
||||||
(<glil-mv-call> nargs ra)
|
(<glil-mv-call> nargs ra)
|
||||||
(<glil-prompt> label inline? escape-only?))
|
(<glil-prompt> label escape-only?))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,8 +132,8 @@
|
||||||
((branch ,inst ,label) (make-glil-branch inst label))
|
((branch ,inst ,label) (make-glil-branch inst label))
|
||||||
((call ,inst ,nargs) (make-glil-call inst nargs))
|
((call ,inst ,nargs) (make-glil-call inst nargs))
|
||||||
((mv-call ,nargs ,ra) (make-glil-mv-call nargs ra))
|
((mv-call ,nargs ,ra) (make-glil-mv-call nargs ra))
|
||||||
((prompt ,label ,inline? ,escape-only?)
|
((prompt ,label ,escape-only?)
|
||||||
(make-glil-prompt label inline? escape-only?))
|
(make-glil-prompt label escape-only?))
|
||||||
(else (error "invalid glil" x))))
|
(else (error "invalid glil" x))))
|
||||||
|
|
||||||
(define (unparse-glil glil)
|
(define (unparse-glil glil)
|
||||||
|
@ -167,5 +166,5 @@
|
||||||
((<glil-branch> inst label) `(branch ,inst ,label))
|
((<glil-branch> inst label) `(branch ,inst ,label))
|
||||||
((<glil-call> inst nargs) `(call ,inst ,nargs))
|
((<glil-call> inst nargs) `(call ,inst ,nargs))
|
||||||
((<glil-mv-call> nargs ra) `(mv-call ,nargs ,ra))
|
((<glil-mv-call> nargs ra) `(mv-call ,nargs ,ra))
|
||||||
((<glil-prompt> label inline? escape-only?)
|
((<glil-prompt> label escape-only?)
|
||||||
`(prompt ,label ,inline? escape-only?))))
|
`(prompt ,label escape-only?))))
|
||||||
|
|
|
@ -514,10 +514,8 @@
|
||||||
((<glil-mv-call> nargs ra)
|
((<glil-mv-call> nargs ra)
|
||||||
(emit-code `((mv-call ,nargs ,ra))))
|
(emit-code `((mv-call ,nargs ,ra))))
|
||||||
|
|
||||||
((<glil-prompt> label inline? escape-only?)
|
((<glil-prompt> label escape-only?)
|
||||||
(emit-code `((prompt ,(if inline? 1 0)
|
(emit-code `((prompt ,(if escape-only? 1 0) ,label))))))
|
||||||
,(if escape-only? 1 0)
|
|
||||||
,label))))))
|
|
||||||
|
|
||||||
(define (dump-object x addr)
|
(define (dump-object x addr)
|
||||||
(define (too-long x)
|
(define (too-long x)
|
||||||
|
|
|
@ -1041,14 +1041,10 @@
|
||||||
((<prompt> src tag body handler)
|
((<prompt> src tag body handler)
|
||||||
(let ((H (make-label))
|
(let ((H (make-label))
|
||||||
(POST (make-label))
|
(POST (make-label))
|
||||||
(inline? (lambda-case? handler))
|
|
||||||
(escape-only? (hashq-ref allocation x)))
|
(escape-only? (hashq-ref allocation x)))
|
||||||
;; First, set up the prompt.
|
;; First, set up the prompt.
|
||||||
(comp-push tag)
|
(comp-push tag)
|
||||||
(if inline?
|
(emit-code src (make-glil-prompt H escape-only?))
|
||||||
(emit-code #f (make-glil-const #f)) ;; push #f as handler
|
|
||||||
(comp-push handler))
|
|
||||||
(emit-code src (make-glil-prompt H inline? escape-only?))
|
|
||||||
|
|
||||||
;; Then we compile the body, with its normal return path, unwinding
|
;; Then we compile the body, with its normal return path, unwinding
|
||||||
;; before proceeding.
|
;; before proceeding.
|
||||||
|
@ -1087,13 +1083,10 @@
|
||||||
(emit-code #f (make-glil-call 'unwind 0))
|
(emit-code #f (make-glil-call 'unwind 0))
|
||||||
(emit-branch #f 'br (or RA POST))))
|
(emit-branch #f 'br (or RA POST))))
|
||||||
|
|
||||||
;; Now the handler.
|
|
||||||
(emit-label H)
|
(emit-label H)
|
||||||
(cond
|
;; Now the handler. The stack is now made up of the continuation, and
|
||||||
(inline?
|
;; then the args to the continuation (pushed separately), and then the
|
||||||
;; The inlined handler. The stack is now made up of the continuation,
|
;; number of args, including the continuation.
|
||||||
;; and then the args to the continuation (pushed separately), and
|
|
||||||
;; then the number of args, including the continuation.
|
|
||||||
(record-case handler
|
(record-case handler
|
||||||
((<lambda-case> req opt kw rest vars body alternate)
|
((<lambda-case> req opt kw rest vars body alternate)
|
||||||
(if (or opt kw alternate)
|
(if (or opt kw alternate)
|
||||||
|
@ -1112,26 +1105,8 @@
|
||||||
(,loc (error "badness" x loc))))
|
(,loc (error "badness" x loc))))
|
||||||
(reverse vars))
|
(reverse vars))
|
||||||
(comp-tail body)
|
(comp-tail body)
|
||||||
(emit-code #f (make-glil-unbind)))))
|
(emit-code #f (make-glil-unbind))))
|
||||||
(else
|
|
||||||
;; The handler was on the heap, so here we're just processing its
|
|
||||||
;; return values.
|
|
||||||
(case context
|
|
||||||
((tail)
|
|
||||||
(emit-code #f (make-glil-call 'return/nvalues 1)))
|
|
||||||
((push)
|
|
||||||
;; truncate to one value, leave on stack
|
|
||||||
(emit-code #f (make-glil-mv-bind '(handler-ret) #f))
|
|
||||||
(emit-code #f (make-glil-unbind)))
|
|
||||||
((vals)
|
|
||||||
(emit-branch #f 'br MVRA))
|
|
||||||
((drop)
|
|
||||||
;; truncate to 0 vals
|
|
||||||
(emit-code #f (make-glil-mv-bind '() #f))
|
|
||||||
(emit-code #f (make-glil-unbind))
|
|
||||||
(if RA (emit-branch #f 'br RA))))))
|
|
||||||
|
|
||||||
;; The POST label, if necessary.
|
|
||||||
(if (or (eq? context 'push)
|
(if (or (eq? context 'push)
|
||||||
(and (eq? context 'drop) (not RA)))
|
(and (eq? context 'drop) (not RA)))
|
||||||
(emit-label POST))))
|
(emit-label POST))))
|
||||||
|
|
|
@ -110,15 +110,29 @@
|
||||||
((<fix> vars body)
|
((<fix> vars body)
|
||||||
(if (null? vars) body x))
|
(if (null? vars) body x))
|
||||||
|
|
||||||
((<prompt> src tag body handler)
|
((<lambda-case> req opt rest kw vars body alternate)
|
||||||
;; If the handler is a simple lambda, inline it.
|
(let ()
|
||||||
(if (and (lambda? handler)
|
(define (args-compatible? args vars)
|
||||||
(record-case (lambda-body handler)
|
(let lp ((args args) (vars vars))
|
||||||
((<lambda-case> req opt kw rest alternate)
|
(cond
|
||||||
(and (pair? req) (not opt) (not kw) (not alternate)))
|
((null? args) (null? vars))
|
||||||
(else #f)))
|
((null? vars) #f)
|
||||||
(make-prompt src tag body (lambda-body handler))
|
((and (lexical-ref? (car args))
|
||||||
x))
|
(eq? (lexical-ref-gensym (car args)) (car vars)))
|
||||||
|
(lp (cdr args) (cdr vars)))
|
||||||
|
(else #f))))
|
||||||
|
|
||||||
|
(and (not opt) (not kw) (not alternate)
|
||||||
|
(record-case body
|
||||||
|
((<application> proc args)
|
||||||
|
;; (lambda args (apply (lambda ...) args)) => (lambda ...)
|
||||||
|
(and (primitive-ref? proc)
|
||||||
|
(eq? (primitive-ref-name proc) '@apply)
|
||||||
|
(pair? args)
|
||||||
|
(lambda? (car args))
|
||||||
|
(args-compatible? (cdr args) vars)
|
||||||
|
(lambda-body (car args))))
|
||||||
|
(else #f)))))
|
||||||
|
|
||||||
(else #f)))
|
(else #f)))
|
||||||
(post-order! inline1 x))
|
(post-order! inline1 x))
|
||||||
|
|
|
@ -434,19 +434,21 @@
|
||||||
((src fluid exp) (make-dynset src fluid exp))
|
((src fluid exp) (make-dynset src fluid exp))
|
||||||
(else #f)))
|
(else #f)))
|
||||||
|
|
||||||
(hashq-set! *primitive-expand-table*
|
|
||||||
'prompt
|
|
||||||
(case-lambda
|
|
||||||
((src tag thunk handler)
|
|
||||||
(make-prompt src tag (make-application #f thunk '())
|
|
||||||
handler #f))
|
|
||||||
(else #f)))
|
|
||||||
(hashq-set! *primitive-expand-table*
|
(hashq-set! *primitive-expand-table*
|
||||||
'@prompt
|
'@prompt
|
||||||
(case-lambda
|
(case-lambda
|
||||||
((src tag thunk handler)
|
((src tag exp handler)
|
||||||
(make-prompt src tag (make-application #f thunk '())
|
(let ((args-sym (gensym)))
|
||||||
handler))
|
(make-prompt
|
||||||
|
src tag exp
|
||||||
|
;; If handler itself is a lambda, the inliner can do some
|
||||||
|
;; trickery here.
|
||||||
|
(make-lambda-case
|
||||||
|
(tree-il-src handler) '() #f 'args #f '() (list args-sym)
|
||||||
|
(make-application #f (make-primitive-ref #f 'apply)
|
||||||
|
(list handler
|
||||||
|
(make-lexical-ref #f 'args args-sym)))
|
||||||
|
#f))))
|
||||||
(else #f)))
|
(else #f)))
|
||||||
|
|
||||||
(hashq-set! *primitive-expand-table*
|
(hashq-set! *primitive-expand-table*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue