mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 20:00:19 +02:00
with a rest arg, allow for keywords anywhere
* libguile/vm-i-system.c (br-if-nargs-gt): Fix variable declaration placement. (bind-kwargs): Patch mostly by Ludovic: it seems that in the mode in which we have rest args, the keywords can appear anywhere. Bummer. Change to allow for this. * module/ice-9/optargs.scm (parse-lambda-case): Same, add a permissive-keys clause that handles the case in which there's a rest argument.
This commit is contained in:
parent
222831b443
commit
ff74e44ecb
2 changed files with 63 additions and 29 deletions
|
@ -537,9 +537,10 @@ VM_DEFINE_INSTRUCTION (42, br_if_nargs_lt, "br-if-nargs-lt", 5, 0, 0)
|
||||||
VM_DEFINE_INSTRUCTION (43, br_if_nargs_gt, "br-if-nargs-gt", 5, 0, 0)
|
VM_DEFINE_INSTRUCTION (43, br_if_nargs_gt, "br-if-nargs-gt", 5, 0, 0)
|
||||||
{
|
{
|
||||||
scm_t_ptrdiff n;
|
scm_t_ptrdiff n;
|
||||||
|
scm_t_int32 offset;
|
||||||
|
|
||||||
n = FETCH () << 8;
|
n = FETCH () << 8;
|
||||||
n += FETCH ();
|
n += FETCH ();
|
||||||
scm_t_int32 offset;
|
|
||||||
FETCH_OFFSET (offset);
|
FETCH_OFFSET (offset);
|
||||||
if (sp - (fp - 1) > n)
|
if (sp - (fp - 1) > n)
|
||||||
ip += offset;
|
ip += offset;
|
||||||
|
@ -613,54 +614,65 @@ VM_DEFINE_INSTRUCTION (47, bind_optionals_shuffle, "bind-optionals/shuffle", 6,
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Flags that determine whether other keywords are allowed, and whether a
|
||||||
|
rest argument is expected. These values must match those used by the
|
||||||
|
glil->assembly compiler. */
|
||||||
|
#define F_ALLOW_OTHER_KEYS 1
|
||||||
|
#define F_REST 2
|
||||||
|
|
||||||
VM_DEFINE_INSTRUCTION (48, bind_kwargs, "bind-kwargs", 5, 0, 0)
|
VM_DEFINE_INSTRUCTION (48, bind_kwargs, "bind-kwargs", 5, 0, 0)
|
||||||
{
|
{
|
||||||
scm_t_uint16 idx;
|
scm_t_uint16 idx;
|
||||||
scm_t_ptrdiff nkw;
|
scm_t_ptrdiff nkw;
|
||||||
int allow_other_keys_and_rest;
|
int kw_and_rest_flags;
|
||||||
SCM kw;
|
SCM kw;
|
||||||
idx = FETCH () << 8;
|
idx = FETCH () << 8;
|
||||||
idx += FETCH ();
|
idx += FETCH ();
|
||||||
|
/* XXX: We don't actually use NKW. */
|
||||||
nkw = FETCH () << 8;
|
nkw = FETCH () << 8;
|
||||||
nkw += FETCH ();
|
nkw += FETCH ();
|
||||||
allow_other_keys_and_rest = FETCH ();
|
kw_and_rest_flags = FETCH ();
|
||||||
|
|
||||||
if (!(allow_other_keys_and_rest & 2)
|
if (!(kw_and_rest_flags & F_REST)
|
||||||
&&(sp - (fp - 1) - nkw) % 2)
|
&& ((sp - (fp - 1) - nkw) % 2))
|
||||||
goto vm_error_kwargs_length_not_even;
|
goto vm_error_kwargs_length_not_even;
|
||||||
|
|
||||||
CHECK_OBJECT (idx);
|
CHECK_OBJECT (idx);
|
||||||
kw = OBJECT_REF (idx);
|
kw = OBJECT_REF (idx);
|
||||||
/* switch nkw to be a negative index below sp */
|
|
||||||
for (nkw = -(sp - (fp - 1) - nkw) + 1; nkw < 0; nkw += 2)
|
/* Switch NKW to be a negative index below SP. */
|
||||||
|
for (nkw = -(sp - (fp - 1) - nkw) + 1; nkw < 0; nkw++)
|
||||||
{
|
{
|
||||||
SCM walk;
|
SCM walk;
|
||||||
if (!scm_is_keyword (sp[nkw]))
|
|
||||||
{
|
if (scm_is_keyword (sp[nkw]))
|
||||||
if (allow_other_keys_and_rest & 2)
|
{
|
||||||
/* reached the end of keywords, but we have a rest arg; just cut
|
for (walk = kw; scm_is_pair (walk); walk = SCM_CDR (walk))
|
||||||
out */
|
{
|
||||||
break;
|
if (scm_is_eq (SCM_CAAR (walk), sp[nkw]))
|
||||||
else
|
{
|
||||||
goto vm_error_kwargs_invalid_keyword;
|
SCM si = SCM_CDAR (walk);
|
||||||
}
|
LOCAL_SET (SCM_I_INUMP (si) ? SCM_I_INUM (si) : scm_to_long (si),
|
||||||
for (walk = kw; scm_is_pair (walk); walk = SCM_CDR (walk))
|
sp[nkw + 1]);
|
||||||
{
|
break;
|
||||||
if (scm_is_eq (SCM_CAAR (walk), sp[nkw]))
|
}
|
||||||
{
|
}
|
||||||
SCM si = SCM_CDAR (walk);
|
if (!(kw_and_rest_flags & F_ALLOW_OTHER_KEYS) && !scm_is_pair (walk))
|
||||||
LOCAL_SET (SCM_I_INUMP (si) ? SCM_I_INUM (si) : scm_to_long (si),
|
goto vm_error_kwargs_unrecognized_keyword;
|
||||||
sp[nkw + 1]);
|
|
||||||
break;
|
nkw++;
|
||||||
}
|
}
|
||||||
}
|
else if (!(kw_and_rest_flags & F_REST))
|
||||||
if (!(allow_other_keys_and_rest & 1) && !scm_is_pair (walk))
|
goto vm_error_kwargs_invalid_keyword;
|
||||||
goto vm_error_kwargs_unrecognized_keyword;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef F_ALLOW_OTHER_KEYS
|
||||||
|
#undef F_REST
|
||||||
|
|
||||||
|
|
||||||
VM_DEFINE_INSTRUCTION (49, push_rest, "push-rest", 2, -1, -1)
|
VM_DEFINE_INSTRUCTION (49, push_rest, "push-rest", 2, -1, -1)
|
||||||
{
|
{
|
||||||
scm_t_ptrdiff n;
|
scm_t_ptrdiff n;
|
||||||
|
|
|
@ -311,7 +311,7 @@
|
||||||
;; it has to be this way, vars are allocated in this order
|
;; it has to be this way, vars are allocated in this order
|
||||||
(set-car! slots-tail args-tail)
|
(set-car! slots-tail args-tail)
|
||||||
(if (pair? kw-indices)
|
(if (pair? kw-indices)
|
||||||
(key slots (cdr slots-tail) args-tail inits)
|
(permissive-keys slots (cdr slots-tail) args-tail inits)
|
||||||
(rest-or-key slots (cdr slots-tail) '() inits #f)))
|
(rest-or-key slots (cdr slots-tail) '() inits #f)))
|
||||||
((pair? kw-indices)
|
((pair? kw-indices)
|
||||||
;; fail early here, because once we're in keyword land we throw
|
;; fail early here, because once we're in keyword land we throw
|
||||||
|
@ -322,6 +322,28 @@
|
||||||
#f) ;; fail
|
#f) ;; fail
|
||||||
(else
|
(else
|
||||||
slots)))
|
slots)))
|
||||||
|
(define (permissive-keys slots slots-tail args-tail inits)
|
||||||
|
(cond
|
||||||
|
((null? args-tail)
|
||||||
|
(if (null? inits)
|
||||||
|
slots
|
||||||
|
(begin
|
||||||
|
(if (eq? (car slots-tail) *uninitialized*)
|
||||||
|
(set-car! slots-tail (apply (car inits) slots)))
|
||||||
|
(permissive-keys slots (cdr slots-tail) '() (cdr inits)))))
|
||||||
|
((not (keyword? (car args-tail)))
|
||||||
|
(permissive-keys slots slots-tail (cdr args-tail) inits))
|
||||||
|
((and (keyword? (car args-tail))
|
||||||
|
(pair? (cdr args-tail))
|
||||||
|
(assq-ref kw-indices (car args-tail)))
|
||||||
|
=> (lambda (i)
|
||||||
|
(list-set! slots i (cadr args-tail))
|
||||||
|
(permissive-keys slots slots-tail (cddr args-tail) inits)))
|
||||||
|
((and (keyword? (car args-tail))
|
||||||
|
(pair? (cdr args-tail))
|
||||||
|
allow-other-keys?)
|
||||||
|
(permissive-keys slots slots-tail (cddr args-tail) inits))
|
||||||
|
(else (error "unrecognized keyword" args-tail))))
|
||||||
(define (key slots slots-tail args-tail inits)
|
(define (key slots slots-tail args-tail inits)
|
||||||
(cond
|
(cond
|
||||||
((null? args-tail)
|
((null? args-tail)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue