mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-07-02 15:40:38 +02:00
Better errors for odd-length keyword args
* libguile/vm-i-system.c (bind-kwargs): * libguile/vm.c (vm_error_kwargs_missing_value): * libguile/eval.c (error_missing_value) (prepare_boot_closure_env_for_apply): Adapt to mirror VM behavior. * libguile/keywords.c (scm_c_bind_keyword_arguments): Likewise. * module/ice-9/eval.scm (primitive-eval): Update to error on (foo #:kw) with a "Keyword argument has no value" instead of the horrible "odd argument list length". Also adapts to the expected args format for the keyword-argument-error exception printer in all cases. Matches 1.8 optargs behavior also. * test-suite/standalone/test-scm-c-bind-keyword-arguments.c (test_missing_value): (missing_value_error_handler): Update test. * test-suite/tests/optargs.test: Add tests.
This commit is contained in:
parent
f428e93ee7
commit
89ececea95
8 changed files with 142 additions and 91 deletions
|
@ -338,43 +338,58 @@
|
|||
env))))
|
||||
;; Now scan args for keywords.
|
||||
(let lp ((args args))
|
||||
(if (and (pair? args) (pair? (cdr args))
|
||||
(keyword? (car args)))
|
||||
(let ((kw-pair (assq (car args) kw))
|
||||
(v (cadr args)))
|
||||
(if kw-pair
|
||||
;; Found a known keyword; set its value.
|
||||
(list-set! env
|
||||
(- imax (cdr kw-pair)) v)
|
||||
;; Unknown keyword.
|
||||
(if (not aok)
|
||||
(scm-error
|
||||
'keyword-argument-error
|
||||
"eval" "Unrecognized keyword"
|
||||
'() (list (car args)))))
|
||||
(lp (cddr args)))
|
||||
(if (pair? args)
|
||||
(if rest?
|
||||
;; Be lenient parsing rest args.
|
||||
(lp (cdr args))
|
||||
(scm-error 'keyword-argument-error
|
||||
"eval" "Invalid keyword"
|
||||
'() (list (car args))))
|
||||
;; Finished parsing keywords. Fill in
|
||||
;; uninitialized kwargs by evalling init
|
||||
;; expressions in their appropriate
|
||||
;; environment.
|
||||
(let lp ((i (- imax kw-base))
|
||||
(inits inits))
|
||||
(if (pair? inits)
|
||||
(let ((tail (list-tail env i)))
|
||||
(if (eq? (car tail) unbound-arg)
|
||||
(set-car! tail
|
||||
(eval (car inits)
|
||||
(cdr tail))))
|
||||
(lp (1- i) (cdr inits)))
|
||||
;; Finally, eval the body.
|
||||
(eval body env))))))))))))))))
|
||||
(cond
|
||||
((pair? args)
|
||||
(cond
|
||||
((keyword? (car args))
|
||||
(let ((k (car args))
|
||||
(args (cdr args)))
|
||||
(cond
|
||||
((assq k kw)
|
||||
=> (lambda (kw-pair)
|
||||
;; Found a known keyword; set its value.
|
||||
(if (pair? args)
|
||||
(let ((v (car args))
|
||||
(args (cdr args)))
|
||||
(list-set! env
|
||||
(- imax (cdr kw-pair))
|
||||
v)
|
||||
(lp args))
|
||||
(scm-error 'keyword-argument-error
|
||||
"eval"
|
||||
"Keyword argument has no value"
|
||||
'() (list k)))))
|
||||
;; Otherwise unknown keyword.
|
||||
(aok
|
||||
(lp (if (pair? args) (cdr args) args)))
|
||||
(else
|
||||
(scm-error 'keyword-argument-error
|
||||
"eval" "Unrecognized keyword"
|
||||
'() (list k))))))
|
||||
(rest?
|
||||
;; Be lenient parsing rest args.
|
||||
(lp (cdr args)))
|
||||
(else
|
||||
(scm-error 'keyword-argument-error
|
||||
"eval" "Invalid keyword"
|
||||
'() (list (car args))))))
|
||||
(else
|
||||
;; Finished parsing keywords. Fill in
|
||||
;; uninitialized kwargs by evalling init
|
||||
;; expressions in their appropriate
|
||||
;; environment.
|
||||
(let lp ((i (- imax kw-base))
|
||||
(inits inits))
|
||||
(if (pair? inits)
|
||||
(let ((tail (list-tail env i)))
|
||||
(if (eq? (car tail) unbound-arg)
|
||||
(set-car! tail
|
||||
(eval (car inits)
|
||||
(cdr tail))))
|
||||
(lp (1- i) (cdr inits)))
|
||||
;; Finally, eval the body.
|
||||
(eval body env)))))
|
||||
)))))))))))
|
||||
|
||||
;; The "engine". EXP is a memoized expression.
|
||||
(define (eval exp env)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue