Merge branch 'minor-compiler-fixes' into 'develop'
Fix some minor compiler bugs Closes #545 See merge request embeddable-common-lisp/ecl!191
This commit is contained in:
commit
4c7658a6fe
5 changed files with 47 additions and 19 deletions
|
|
@ -151,13 +151,14 @@
|
|||
;; This recursive algorithm is guaranteed to stop when functions
|
||||
;; do not change.
|
||||
(let ((new-type (compute-closure-type fun))
|
||||
(to-be-updated (fun-child-funs fun)))
|
||||
to-be-updated)
|
||||
;; Same type
|
||||
(when (eq new-type old-type)
|
||||
(return-from update-fun-closure-type nil))
|
||||
(when (fun-global fun)
|
||||
(cmpnote "Function ~A is global but is closed over some variables.~%~{~A ~}"
|
||||
(fun-name fun) (mapcar #'var-name (fun-referenced-vars fun))))
|
||||
(setf to-be-updated (append (fun-child-funs fun) (fun-referencing-funs fun)))
|
||||
(setf (fun-closure fun) new-type)
|
||||
;; All external, non-global variables become of type closure
|
||||
(when (eq new-type 'CLOSURE)
|
||||
|
|
|
|||
|
|
@ -361,12 +361,13 @@ The function thus belongs to the type of functions that ecl_make_cfun accepts."
|
|||
&aux (requireds (first lambda-list))
|
||||
(optionals (second lambda-list))
|
||||
(rest (third lambda-list)) rest-loc
|
||||
(key-flag (fourth lambda-list))
|
||||
(keywords (fifth lambda-list))
|
||||
(allow-other-keys (sixth lambda-list))
|
||||
(nreq (length requireds))
|
||||
(nopt (/ (length optionals) 3))
|
||||
(nkey (/ (length keywords) 4))
|
||||
(varargs (or optionals rest keywords allow-other-keys))
|
||||
(varargs (or optionals rest key-flag allow-other-keys))
|
||||
(fname-in-ihs-p (or (policy-debug-variable-bindings)
|
||||
(and (policy-debug-ihs-frame)
|
||||
(or description fname))))
|
||||
|
|
@ -380,13 +381,13 @@ The function thus belongs to the type of functions that ecl_make_cfun accepts."
|
|||
|
||||
(if (and fname ;; named function
|
||||
;; no required appears in closure,
|
||||
(dolist (var (car lambda-list) t)
|
||||
(dolist (var requireds t)
|
||||
(declare (type var var))
|
||||
(when (var-ref-ccb var) (return nil)))
|
||||
(null (second lambda-list)) ;; no optionals,
|
||||
(null (third lambda-list)) ;; no rest parameter, and
|
||||
(null (fourth lambda-list))) ;; no keywords.
|
||||
(setf *tail-recursion-info* (cons *tail-recursion-info* (car lambda-list)))
|
||||
(null optionals) ;; no optionals,
|
||||
(null rest) ;; no rest parameter, and
|
||||
(null key-flag)) ;; no keywords.
|
||||
(setf *tail-recursion-info* (cons *tail-recursion-info* requireds))
|
||||
(setf *tail-recursion-info* nil))
|
||||
|
||||
;; check arguments
|
||||
|
|
@ -396,7 +397,7 @@ The function thus belongs to the type of functions that ecl_make_cfun accepts."
|
|||
(when varargs
|
||||
(when requireds
|
||||
(wt-nl "if (ecl_unlikely(narg<" nreq ")) FEwrong_num_arguments_anonym();"))
|
||||
(unless (or rest keywords allow-other-keys)
|
||||
(unless (or rest key-flag allow-other-keys)
|
||||
(wt-nl "if (ecl_unlikely(narg>" (+ nreq nopt) ")) FEwrong_num_arguments_anonym();"))))
|
||||
(open-inline-block))
|
||||
|
||||
|
|
@ -429,9 +430,10 @@ The function thus belongs to the type of functions that ecl_make_cfun accepts."
|
|||
when (unboxed var)
|
||||
do (setf (var-loc var) (wt-decl var)))
|
||||
;; dont create rest or varargs if not used
|
||||
(when (and rest (< (var-ref rest) 1))
|
||||
(when (and rest (< (var-ref rest) 1)
|
||||
(not (eq (var-kind rest) 'SPECIAL)))
|
||||
(setq rest nil
|
||||
varargs (or optionals keywords allow-other-keys)))
|
||||
varargs (or optionals key-flag allow-other-keys)))
|
||||
;; Declare &optional variables
|
||||
(do ((opt optionals (cdddr opt)))
|
||||
((endp opt))
|
||||
|
|
@ -453,7 +455,7 @@ The function thus belongs to the type of functions that ecl_make_cfun accepts."
|
|||
((eq closure-type 'LEXICAL)
|
||||
(format nil "lex~D" (1- *level*)))
|
||||
(t "narg"))))
|
||||
(if (setq simple-varargs (and (not (or rest keywords allow-other-keys))
|
||||
(if (setq simple-varargs (and (not (or rest key-flag allow-other-keys))
|
||||
(<= (+ nreq nopt) si::c-arguments-limit)))
|
||||
(wt-nl "va_list args; va_start(args,"
|
||||
(last-variable)
|
||||
|
|
@ -502,8 +504,8 @@ The function thus belongs to the type of functions that ecl_make_cfun accepts."
|
|||
(wt-nl "}"))
|
||||
(wt-nl-close-brace)))
|
||||
|
||||
(when (or rest keywords allow-other-keys)
|
||||
(cond ((not (or keywords allow-other-keys))
|
||||
(when (or rest key-flag allow-other-keys)
|
||||
(cond ((not (or key-flag allow-other-keys))
|
||||
(wt-nl rest-loc " = cl_grab_rest_args(args);"))
|
||||
(t
|
||||
(cond (keywords
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@
|
|||
do (let ((var (gensym)))
|
||||
(setf iterators (cons var iterators)
|
||||
for-statements (list* :for var in-or-on arg for-statements))))
|
||||
`(loop ,@list-1-form
|
||||
,@fun-with
|
||||
`(loop ,@fun-with
|
||||
,@list-1-form
|
||||
,@for-statements
|
||||
,do-or-collect (funcall ,function ,@iterators)
|
||||
,@finally-form))))
|
||||
|
|
|
|||
|
|
@ -210,10 +210,11 @@
|
|||
(return-from expand-member
|
||||
`(ffi:c-inline (,value ,list) (:object :object) :object
|
||||
"ecl_member(#0,#1)" :one-liner t :side-effects nil)))))
|
||||
(ext:with-unique-names (%value %sublist %elt)
|
||||
(ext:with-unique-names (%value %list %sublist %elt)
|
||||
`(let ((,%value ,value)
|
||||
(,%list ,list)
|
||||
,@init)
|
||||
(do-in-list (,%elt ,%sublist ,list)
|
||||
(do-in-list (,%elt ,%sublist ,%list)
|
||||
(when ,(funcall test-function %value
|
||||
(funcall key-function %elt))
|
||||
(return ,%sublist)))))))
|
||||
|
|
@ -251,10 +252,11 @@
|
|||
`(ffi:c-inline (,value ,list) (:object :object) :object
|
||||
"ecl_assqlp(#0,#1)" :one-liner t :side-effects nil)))))
|
||||
(when test-function
|
||||
(ext:with-unique-names (%value %sublist %elt %car)
|
||||
(ext:with-unique-names (%value %list %sublist %elt %car)
|
||||
`(let ((,%value ,value)
|
||||
(,%list ,list)
|
||||
,@init)
|
||||
(do-in-list (,%elt ,%sublist ,list)
|
||||
(do-in-list (,%elt ,%sublist ,%list)
|
||||
(when ,%elt
|
||||
(let ((,%car (cons-car (optional-type-check ,%elt cons))))
|
||||
(when ,(funcall test-function %value
|
||||
|
|
|
|||
|
|
@ -1606,3 +1606,26 @@
|
|||
(check-fn (make-fn (1+ si::c-arguments-limit)))
|
||||
(check-fn (make-fn (1- si::c-arguments-limit)))
|
||||
(check-fn (make-fn si::c-arguments-limit))))
|
||||
|
||||
;;; Date 2020-03-18
|
||||
;;; URL: https://gitlab.com/embeddable-common-lisp/ecl/issues/545
|
||||
;;; Description
|
||||
;;;
|
||||
;;; The closure type for local functions calling global closures was
|
||||
;;; not determined correctly to also be a global closure.
|
||||
(test cmp.0075.local-fun.closure-type
|
||||
(ext:with-clean-symbols (*function*)
|
||||
(defvar *function*)
|
||||
(let ((result
|
||||
(funcall
|
||||
(compile nil
|
||||
(lambda (b)
|
||||
(flet ((%f10 () b))
|
||||
(flet ((%f4 () (%f10)))
|
||||
(incf b)
|
||||
(setf *function* #'%f10) ; makes a global
|
||||
; closure out of %f10
|
||||
(%f4)))))
|
||||
3)))
|
||||
(is (eq result 4))
|
||||
(is (eq (funcall *function*) 4)))))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue