8c853f632f8c

Clean up and fix the anonymous variable handling
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Fri, 08 Jul 2016 18:14:05 +0000
parents 2415dbe555d2
children 92c590f78133
branches/tags (none)
files package-test.lisp src/wam/compiler.lisp

Changes

--- a/package-test.lisp	Fri Jul 08 17:03:54 2016 +0000
+++ b/package-test.lisp	Fri Jul 08 18:14:05 2016 +0000
@@ -2,7 +2,7 @@
   (:use
     #:cl
     #:5am
-    #:bones))
+    ))
 
 (defpackage #:bones-test.paip
   (:use
--- a/src/wam/compiler.lisp	Fri Jul 08 17:03:54 2016 +0000
+++ b/src/wam/compiler.lisp	Fri Jul 08 18:14:05 2016 +0000
@@ -144,10 +144,7 @@
   (make-instance 'variable-node :variable variable))
 
 (defun make-argument-variable-node (variable)
-  (make-instance 'argument-variable-node
-                 :variable (if (eq variable +wildcard-symbol+)
-                             (gensym "?")
-                             variable)))
+  (make-instance 'argument-variable-node :variable variable))
 
 (defun make-list-node (head tail)
   (make-instance 'list-node :head head :tail tail))
@@ -191,6 +188,7 @@
             (if space-before " ~A =" "~A = ")
             (node-secondary-register node))))
 
+
 (defgeneric dump-node (node))
 
 (defmethod dump-node ((node node))
@@ -337,24 +335,10 @@
 (defun find-anonymous-variables (clause)
   "Return a list of all anonymous variables in `clause`.
 
-  Anonymous variables are non-argument-position variables that are only ever
-  used once.
+  Anonymous variables are variables that are only ever used once.
 
   "
-  ;; clause: ((member :x (list* :y :rest)) ;-
-  ;;          (member :x :rest))
-  ;;
-  ;; terms: (member :x (list* :y :rest))
-  ;;        (member :x :rest)
-  (flet ((argument-variables (term)
-           (remove-if-not #'variablep (cdr term)))
-         (non-argument-variables (term)
-           (loop :for argument :in (cdr term)
-                 :when (consp argument)
-                 :append (tree-collect #'variablep (cdr argument)))))
-    (let ((terms (remove-if-not #'consp clause)))
-      (set-difference (unique-items (mapcan #'non-argument-variables terms))
-                      (mapcan #'argument-variables terms)))))
+  (unique-items (tree-collect #'variablep clause)))
 
 
 (defun determine-clause-properties (head body)
@@ -560,6 +544,17 @@
        (setf (slot-value ,instance ,slot) ,value-form))))
 
 
+(defun variable-anonymous-p (state variable)
+  "Return whether `variable` is considered anonymous in `state`"
+  (ensure-boolean
+    (member variable (allocation-state-anonymous-variables state))))
+
+
+(defun allocate-variable-register (state variable)
+  (if (variable-anonymous-p state variable)
+    (make-anonymous-register)
+    (ensure-variable state variable)))
+
 (defun allocate-nonvariable-register (state)
   "Allocate and return a register for something that's not a variable."
   ;; We need to allocate registers for things like structures and lists, but we
@@ -579,14 +574,11 @@
 
 (defmethod allocate-register ((node variable-node) state)
   (set-when-unbound node 'register
-    (if (member (node-variable node)
-                (allocation-state-anonymous-variables state))
-      (make-anonymous-register)
-      (ensure-variable state (node-variable node)))))
+    (allocate-variable-register state (node-variable node))))
 
 (defmethod allocate-register ((node argument-variable-node) state)
   (set-when-unbound node 'secondary-register
-    (ensure-variable state (node-variable node))))
+    (allocate-variable-register state (node-variable node))))
 
 (defmethod allocate-register ((node structure-node) state)
   (set-when-unbound node 'register
@@ -1046,11 +1038,15 @@
            ;; Reset the list of seen registers (grep for "clown car" above)
            (setf seen (remove-if #'register-temporary-p seen)))
          (handle-argument (argument-register source-register)
-           ;; OP X_n A_i
-           (let ((newp (push-if-new source-register seen :test #'register=)))
-             (push-instruction (find-opcode :argument newp mode source-register)
-                               source-register
-                               argument-register)))
+           (if (register-anonymous-p source-register)
+             ;; Crazy, but we can just drop argument-position anonymous
+             ;; variables on the floor at this point.
+             nil
+             ;; OP X_n A_i
+             (let ((newp (push-if-new source-register seen :test #'register=)))
+               (push-instruction (find-opcode :argument newp mode source-register)
+                                 source-register
+                                 argument-register))))
          (handle-structure (destination-register functor arity)
            ;; OP functor reg
            (push destination-register seen)
@@ -1083,9 +1079,10 @@
            ;; might need to do some resetting but not end in a CALL.
            (reset-seen))
          (handle-register (register)
-           ;; OP reg
-           (if (eq (register-type register) :anonymous)
+           (if (register-anonymous-p register)
+             ;; VOID 1
              (push-instruction (find-opcode :register nil mode register) 1)
+             ;; OP reg
              (let ((first-seen (push-if-new register seen :test #'register=)))
                (push-instruction
                  (find-opcode :register first-seen mode register)