   ([interpreter locals] (->PushDslState interpreter locals)))
 
 
-(defn consume-as
-  [dslstep id stack]
+(defn consume
+  [dslstep stack & {:keys [as]}]
   (let [interpreter (:interpreter dslstep)
         old-stack (get-stack interpreter stack)
         old-locals (:locals dslstep)]

      (throw (Exception. (str "Push DSL Error: " stack " is empty")))
      (make-PushDslState
        (set-stack interpreter stack (pop old-stack))
        (assoc old-locals id (first old-stack)))
    )))


(def sixier (make-PushDslState six-ints))


(fact "consume-as returns a new PushDslState with a changed :interpreter and new locals"
  (:locals (consume-as sixier :int1 :integer)) => {:int1 6}
  (get-stack (:interpreter (consume-as sixier :int1 :integer)) :integer) => '(5 4 3 2 1))


(fact "consume-as throws an exception if the stack is empty"
  (:locals (consume-as sixier :nope :boolean)) => (throws #"Push DSL Error:"))


(fact "consume-as can be thread-firsted"
  (let [two-popped (-> sixier
                      (consume-as :int1 :integer)
                      (consume-as :int2 :integer))]
    (:locals two-popped) => {:int1 6, :int2 5}
    (get-stack (:interpreter two-popped) :integer) => '(4 3 2 1)))


(defn send-to
  [dslstep stack args function]
  (let [result (apply function (map (:locals dslstep) args))
        interpreter (:interpreter dslstep)]
    (assoc dslstep :interpreter (push-item interpreter stack result))))


(fact "`send-to` will apply the specified inline function to the dslstate locals named"
  (let [added (-> sixier
                    (consume-as :int1 :integer)
                    (consume-as :int2 :integer)
                    (send-to :integer [:int1 :int2] #(+ %1 %2)))]
  (get-stack (:interpreter added) :integer) => '(11 4 3 2 1)))

;; now there's another possibility that strikes me:
;; we could use a syntax like (consume % :integer :as :int1)
;; and that would permit      (consume % :integer)
;; which might put the consumed item in a little vector stack
;;
;; why?
;; because then integer-add might be
;;   -> interpreter 
;;      (consume :integer)
;;      (consume :integer)
;;      #(+ %1 %2)           (which would use the stack as args)
;; but that might be much harder to read :/


;; a simpler version yet (using an invisible stack inside the Interpreter itself, maybe?):
;; (grab :integer)
;; (grab :integer)
;; (place :integer #(+ %1 %2))




; (def-pushinstruction

;   :needs {:boolean 0}
;   :tags [:combinator :core]
;   :transaction
;     (consume-stack :boolean)
;     )


; (def-pushinstruction
