Update of /project/movitz/cvsroot/movitz
In directory clnet:/tmp/cvs-serv30554
Modified Files:
compiler.lisp
Log Message:
First implementation of new &key-parsing strategy.
--- /project/movitz/cvsroot/movitz/compiler.lisp 2007/02/17 19:24:28 1.174
+++ /project/movitz/cvsroot/movitz/compiler.lisp 2007/02/19 20:24:38 1.175
@@ -8,7 +8,7 @@
;;;; Created at: Wed Oct 25 12:30:49 2000
;;;; Distribution: See the accompanying file COPYING.
;;;;
-;;;; $Id: compiler.lisp,v 1.174 2007/02/17 19:24:28 ffjeld Exp $
+;;;; $Id: compiler.lisp,v 1.175 2007/02/19 20:24:38 ffjeld Exp $
;;;;
;;;;------------------------------------------------------------------
@@ -789,6 +789,9 @@
(multiple-value-bind (const-list num-jumpers jumpers-map borrower-map)
(layout-funobj-vector all-constants-plist
all-key-args-constants
+ #+ignore (mapcar (lambda (x)
+ (cons (movitz-read x) 1))
+ '(:a :b :c :d))
all-jumper-sets
(borrowed-bindings funobj))
(setf (movitz-funobj-num-jumpers funobj) num-jumpers
@@ -2655,7 +2658,7 @@
(defun make-binding-map () nil)
(defun new-binding-located-p (binding map)
- (check-type binding (or binding (cons keyword binding)))
+ (check-type binding (or null binding (cons keyword binding)))
(and (assoc binding map) t))
(defun frame-map-size (map)
@@ -2830,19 +2833,9 @@
(when sub (process sub))))))
(process code)
(map nil #'process include-programs))
- (if (not key-args-set)
- (values constants jumper-sets nil)
- (loop with key-args-constants = nil
- for (object count) on constants by #'cddr
- if (not (member object key-args-set))
- append (list object count) into non-key-constants
- else
- do (setf key-args-constants
- (merge 'list key-args-constants (list (cons object count)) #'<
- :key (lambda (x)
- (position (car x) key-args-set))))
- finally
- (return (values non-key-constants jumper-sets key-args-constants))))))
+ (loop for key-arg in key-args-set
+ do (remf constants key-arg))
+ (values constants jumper-sets key-args-set)))
(defun layout-funobj-vector (constants key-args-constants jumper-sets borrowing-bindings)
(let* ((jumpers (loop with x
@@ -2851,7 +2844,12 @@
do (setf x (nconc x (copy-list set)))
finally (return x)))
(num-jumpers (length jumpers))
- (stuff (append key-args-constants
+ (stuff (append (mapcar (lambda (c)
+ (cons c 1))
+ key-args-constants)
+ (when key-args-constants
+ (list (cons (movitz-read 0)
+ 1)))
(sort (loop for (constant count) on constants by #'cddr
unless (or (eq constant *movitz-nil*)
(eq constant (image-t-symbol *image*)))
@@ -3136,9 +3134,11 @@
(funobj-binding))))
(:init-lexvar
(destructuring-bind (binding &key init-with-register init-with-type
- protect-registers protect-carry)
+ protect-registers protect-carry
+ shared-reference-p)
(cdr instruction)
- (declare (ignore protect-registers protect-carry init-with-type))
+ (declare (ignore protect-registers protect-carry init-with-type
+ shared-reference-p))
(cond
((not init-with-register)
(take-note-of-init binding pc))
@@ -3320,6 +3320,9 @@
(when (and (binding-lended-p binding)
(not (typep binding 'borrowed-binding))
(not (getf (binding-lending binding) :stack-cons-location)))
+ #+ignore
+ (assert (not (typep binding 'keyword-function-argument)) ()
+ "Can't lend keyword binding ~S." binding)
;; (warn "assigning lending-cons for ~W at ~D" binding stack-frame-position)
(let ((cons-pos (frame-map-next-free-location frame-map function-env 2)))
(setf (new-binding-location (cons :lended-cons binding) frame-map)
@@ -3346,6 +3349,40 @@
(plusp (car (gethash binding var-counts '(0)))))
(setf (new-binding-location binding frame-map)
(forwarding-binding-target binding))))
+ ;; Keyword bindings
+ (flet ((set-exclusive-location (binding location)
+ (assert (not (rassoc location frame-map))
+ () "Fixed location ~S for ~S is taken by ~S."
+ location binding (rassoc location frame-map))
+ (setf (new-binding-location binding frame-map) location)))
+ (when (key-vars-p function-env)
+ (when (= 0 (rest-args-position function-env))
+ (set-exclusive-location (loop for var in (required-vars function-env)
+ as binding = (movitz-binding var function-env nil)
+ thereis (when (= 0 (function-argument-argnum binding))
+ binding))
+ 1))
+ (when (>= 1 (rest-args-position function-env))
+ (set-exclusive-location (loop for var in (required-vars function-env)
+ as binding = (movitz-binding var function-env nil)
+ thereis (when (= 1 (function-argument-argnum binding))
+ binding))
+ 2)))
+ (loop for key-var in (key-vars function-env)
+ as key-binding =
+ (or (movitz-binding key-var function-env nil)
+ (error "No binding for key-var ~S." key-var))
+ as supplied-p-binding =
+ (when (optional-function-argument-supplied-p-var key-binding)
+ (or (movitz-binding (optional-function-argument-supplied-p-var key-binding)
+ function-env nil)
+ (error "No binding for supplied-p-var ~S."
+ (optional-function-argument-supplied-p-var key-binding))))
+ as location upfrom 3 by 2
+ do (set-exclusive-location key-binding location)
+ (assert supplied-p-binding)
+ (set-exclusive-location supplied-p-binding (1+ location))))
+ ;; Now, use assing-env-bindings on the remaining bindings.
(loop for env in
(loop with z = nil
for b being the hash-keys of var-counts using (hash-value c)
@@ -4293,7 +4330,7 @@
"From a (normal) <lambda-list>, add bindings to <env>."
(let ((arg-pos 0))
(multiple-value-bind (required-vars optional-vars rest-var key-vars auxes allow-p
- min-args max-args edx-var oddeven key-p)
+ min-args max-args edx-var oddeven key-vars-p)
(decode-normal-lambda-list lambda-list)
(declare (ignore auxes))
(setf (min-args env) min-args
@@ -4356,6 +4393,8 @@
(movitz-env-add-binding env (make-instance 'supplied-p-function-argument
:name supplied-p-parameter)))
formal)))
+ (when (or rest-var key-vars-p)
+ (setf (rest-args-position env) arg-pos))
(when rest-var
(check-type rest-var symbol)
(let ((formal (shadow-when-special rest-var env)))
@@ -4363,11 +4402,30 @@
(movitz-env-add-binding env (make-instance 'rest-function-argument
:name formal
:argnum (post-incf arg-pos)))))
- (when key-p
- ;; We need to check at run-time whether keyword checking is supressed or not.
- (setf (allow-other-keys-var env)
- (movitz-env-add-binding env (make-instance 'located-binding
- :name (gensym "allow-other-keys-var-")))))
+;;; (when key-vars-p
+;;; ;; We need to check at run-time whether keyword checking is supressed or not.
+;;; (setf (allow-other-keys-var env)
+;;; (movitz-env-add-binding env (make-instance 'located-binding
+;;; :name (gensym "allow-other-keys-var-")))))
+ (when key-vars-p
+ (setf (key-vars-p env) t)
+ (when (>= 1 (rest-args-position env))
+ (let ((name (gensym "save-ebx-for-keyscan")))
+ (setf (required-vars env)
+ (append (required-vars env)
+ (list name)))
+ (movitz-env-add-binding env (make-instance 'register-required-function-argument
+ :name name
+ :argnum 1
+ :declarations '(muerte.cl:ignore)))
+ (setf (movitz-env-get name 'ignore nil env) t)))
+ (when (= 0 (rest-args-position env))
+ (let ((name (gensym "save-eax-for-keyscan")))
+ (push name (required-vars env))
+ (movitz-env-add-binding env (make-instance 'register-required-function-argument
+ :name name
+ :argnum 0))
+ (setf (movitz-env-get name 'ignore nil env) t))))
(setf (key-vars env)
(loop for spec in key-vars
with rest-var-name =
@@ -4379,21 +4437,23 @@
:argnum (post-incf arg-pos)))
name)))
collect
- (multiple-value-bind (formal keyword-name init-form supplied-p-parameter)
+ (multiple-value-bind (formal keyword-name init-form supplied-p)
(decode-keyword-formal spec)
- (setf formal (shadow-when-special formal env))
- (movitz-env-add-binding env (make-instance 'keyword-function-argument
- :name formal
- 'init-form init-form
- 'supplied-p-var supplied-p-parameter
- :keyword-name keyword-name
- :rest-var-name rest-var-name))
- (when supplied-p-parameter
- (setf supplied-p-parameter
- (shadow-when-special supplied-p-parameter env))
+ (let ((formal
+ (shadow-when-special formal env))
+ (supplied-p-parameter
+ (or supplied-p
+ (gensym "supplied-p-"))))
+ (movitz-env-add-binding env (make-instance 'keyword-function-argument
+ :name formal
+ 'init-form init-form
+ 'supplied-p-var supplied-p-parameter
+ :keyword-name keyword-name
+ :rest-var-name rest-var-name))
(movitz-env-add-binding env (make-instance 'supplied-p-function-argument
- :name supplied-p-parameter)))
- formal)))
+ :name (shadow-when-special supplied-p-parameter env)))
+ formal))))
+ #+ignore
(multiple-value-bind (key-decode-map key-decode-shift)
(best-key-encode (key-vars env))
(setf (key-decode-map env) key-decode-map
@@ -4508,7 +4568,7 @@
(edx-location
(and (edx-var env)
(new-binding-location (edx-var env) frame-map :default nil))))
- ;; (warn "l0: ~S, l1: ~S" location-0 location-1)
+ #+ignore (warn "l0: ~S, l1: ~S" location-0 location-1)
(assert (not (and location-0
(eql location-0 location-1))) ()
"Compiler bug: two bindings in same location.")
@@ -4775,8 +4835,7 @@
(required-vars (required-vars env))
(optional-vars (optional-vars env))
(rest-var (rest-var env))
- (key-vars (key-vars env))
- (allow-other-keys-p (allow-other-keys-p env)))
+ (key-vars (key-vars env)))
(when (and (not rest-var)
key-vars
(not (= 1 (length key-vars))))
@@ -4912,148 +4971,81 @@
:init-with-type list))))
(when key-vars
(play-with-keys key-vars))
- (cond
+ (when (key-vars-p env)
;; &key processing..
- ((and (not rest-var)
- (= 1 (length key-vars)))
- (let* ((key-var-name (decode-keyword-formal (first key-vars)))
- (binding (movitz-binding key-var-name env))
- (position (function-argument-argnum
- (movitz-binding (keyword-function-argument-rest-var-name binding) env)))
- (supplied-p-var (optional-function-argument-supplied-p-var binding))
- (supplied-p-binding (movitz-binding supplied-p-var env)))
- (setq need-normalized-ecx-p t)
- (cond
- ((and (movitz-constantp (optional-function-argument-init-form binding))
- (< 1 position))
- `((:init-lexvar ,binding)
- ,@(when supplied-p-var
- `((:init-lexvar ,supplied-p-binding)))
- ,@(compiler-call #'compile-form
- :form (list 'muerte.cl:quote
- (eval-form (optional-function-argument-init-form binding) env nil))
- :funobj funobj
- :env env
- :result-mode :ebx)
- ,@(when supplied-p-var
- `((:store-lexical ,supplied-p-binding :edi :type null)))
- (:arg-cmp ,(+ 2 position))
- (:jb 'default-done)
- (:movl (:ebp (:ecx 4) ,(* -4 (1- position))) :eax)
- (:load-constant ,(movitz-read (keyword-function-argument-keyword-name binding)) :eax :op :cmpl)
- ,@(if allow-other-keys-p
- `((:jne 'default-done))
- `((:jne '(:sub-program (unknown-key) (:int 101)))))
- ,@(when supplied-p-var
- `((:movl (:edi ,(global-constant-offset 't-symbol)) :eax)
- (:store-lexical ,supplied-p-binding :eax
- :type (eql ,(image-t-symbol *image*)))))
- (:movl (:ebp (:ecx 4) ,(* -4 (1- (1+ position)))) :ebx)
- default-done
- (:store-lexical ,binding :ebx :type t)))
- (t `((:init-lexvar ,binding)
- ,@(when supplied-p-var
- `((:init-lexvar ,supplied-p-binding)))
- (:arg-cmp ,(+ 2 position))
- (:jb '(:sub-program (default)
- ,@(append
- (when supplied-p-var
- `((:store-lexical ,supplied-p-binding :edi
- :type null)))
- (compiler-call #'compile-form
- :form (optional-function-argument-init-form binding)
- :funobj funobj
- :env env
- :result-mode :ebx)
- `((:jmp 'default-done)))))
- ,@(case position
- (0 `((:load-constant ,(movitz-read (keyword-function-argument-keyword-name binding))
- :eax :op :cmpl)))
- (1 `((:load-constant ,(movitz-read (keyword-function-argument-keyword-name binding))
- :ebx :op :cmpl)))
- (t `((:load-constant ,(movitz-read (keyword-function-argument-keyword-name binding))
- :eax :op :cmpl))))
- ,@(if allow-other-keys-p
- `((:jne 'default))
- `((:jne '(:sub-program (unknown-key) (:int 101)))))
- ,@(when supplied-p-var
- `((:movl (:edi ,(global-constant-offset 't-symbol)) :eax)
- (:store-lexical ,supplied-p-binding :eax
- :type (eql ,(image-t-symbol *image*)))))
- ,@(case position
- (0 nil) ; it's already in ebx
- (t `((:movl (:ebp (:ecx 4) ,(* -4 (1- (1+ position)))) :ebx))))
- default-done
- (:store-lexical ,binding :ebx :type t))))))
- (t #+ignore
- (pushnew (movitz-print (movitz-funobj-name funobj))
- (aref *xx* (length key-vars)))
- #+ignore
- (when key-vars
- (warn "KEY-FUN: ~D" (length key-vars)))
- (append
- `((:declare-key-arg-set ,@(mapcar (lambda (k)
- (movitz-read
- (keyword-function-argument-keyword-name
- (movitz-binding (decode-keyword-formal k) env))))
- key-vars)))
- (loop with rest-binding = (movitz-binding rest-var env)
- for key-var in key-vars
- as key-var-name = (decode-keyword-formal key-var)
- as binding = (movitz-binding key-var-name env)
- as supplied-p-var = (optional-function-argument-supplied-p-var binding)
- as supplied-p-binding = (movitz-binding supplied-p-var env)
- and keyword-ok-label = (make-symbol (format nil "keyword-~A-ok" key-var-name))
- and keyword-not-supplied-label = (gensym)
- do (assert binding)
- if (not (movitz-constantp (optional-function-argument-init-form binding)))
- append
- `((:init-lexvar ,binding)
- (:load-constant ,(movitz-read (keyword-function-argument-keyword-name binding)) :ecx)
- (:load-lexical ,rest-binding :ebx)
- (:call (:edi ,(global-constant-offset 'keyword-search)))
- (:jz ',keyword-not-supplied-label)
- (:store-lexical ,binding :eax :type t)
- ,@(when supplied-p-var
- `((:movl (:edi ,(global-constant-offset 't-symbol)) :eax)
- (:init-lexvar ,supplied-p-binding
- :init-with-register :eax
- :init-with-type (eql ,(image-t-symbol *image*)))))
- (:jmp ',keyword-ok-label)
- ,keyword-not-supplied-label
- ,@(when supplied-p-var
- `((:store-lexical ,supplied-p-binding :edi :type null)))
+ (setq need-normalized-ecx-p t)
+ (append
+ `((:declare-key-arg-set ,@(mapcar (lambda (k)
+ (movitz-read
+ (keyword-function-argument-keyword-name
+ (movitz-binding (decode-keyword-formal k) env))))
+ key-vars)))
+ (make-immediate-move (* +movitz-fixnum-factor+
+ (rest-args-position env))
+ :edx)
+ `((:call (:edi ,(global-constant-offset 'decode-keyargs-default))))
+ (unless (allow-other-keys-p env)
+ `((:testl :eax :eax)
+ (:jnz '(:sub-program (unknown-keyword)
+ (:int 72)))))
+ (loop for key-var in key-vars
+ as key-location upfrom 3 by 2
+ as key-var-name =
+ (decode-keyword-formal key-var)
+ as binding =
+ (movitz-binding key-var-name env)
+ as supplied-p-binding =
+ (movitz-binding (optional-function-argument-supplied-p-var binding)
+ env)
+ as keyword-ok-label = (make-symbol (format nil "keyword-~A-ok" key-var-name))
+ do (assert binding)
+ ;; (not (movitz-constantp (optional-function-argument-init-form binding)))
+ append
+ `((:init-lexvar ,binding
+ :init-with-register ,binding
+ :init-with-type t
+ :shared-reference-p t)
+ (:init-lexvar ,supplied-p-binding
+ :init-with-register ,supplied-p-binding
+ :init-with-type t
+ :shared-reference-p t))
+ append
+ (when (optional-function-argument-init-form binding)
+ `((:cmpl :edi (:ebp ,(stack-frame-offset (1+ key-location))))
+ (:jne ',keyword-ok-label)
,@(compiler-call #'compile-form
:form (optional-function-argument-init-form binding)
[187 lines skipped]