             [epicea.utils.access :as access] :reload-all))
 
 (spec/def ::unspecified nil?)
-
-(spec/def ::bool boolean?)
-(spec/def ::float float?)
-(spec/def ::double double?)
-(spec/def ::long #(instance? java.lang.Long %))
-(spec/def ::int #(or (instance? java.lang.Integer %)
-                     (int? %)))
 
 (spec/def ::dynamic (partial = :dynamic))
 

(def size-add +)
(def size-mul *)
(def size-max max)


;;;; Compute the size of a ::sized-type
(defmultiple compute-size get-pair-tag
  (:default [x] 1)
  (:vec [x] (let [value (get-pair-value x)]
              (size-mul (:count value) (compute-size (:type value)))))
  (:tagged [x] (compute-size (:data (get-pair-value x))))
  (:union [x] (reduce size-max (map compute-size (-> x get-pair-value :alts))))
  (:record [x] (reduce size-add (map (comp compute-size :value) 
                                    (-> x get-pair-value :fields))))
  (:unspecified [x] nil)
  (:vecdata [x] (reduce size-add (map compute-size (-> x get-pair-value :data)))))

  
(assert (= 1 (compute-size (spec/conform ::sized-type [:tag 119 :number]))))
(assert (= 1 (compute-size (spec/conform ::sized-type 3))))
(assert (= 3 (compute-size (spec/conform ::sized-type [:vec :number 3]))))
(assert (= 2 (compute-size (spec/conform ::sized-type [:union :number [:vec :number 2]]))))
(assert (= 2 (compute-size (spec/conform ::sized-type [:record :a :number :b :number]))))
(assert (= 3 (compute-size (spec/conform 
                            ::sized-type 
                            [:record :a :number :b :number :c :number]))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Grammar
(spec/def ::arg-name symbol?)


(spec/def ::record-field (spec/cat 
                          :key ::key
                          :value-type ::type))

(spec/def ::record (spec/cat
                    :type (partial = :record)
                    :fields (spec/* ::record-field)))

(spec/def ::vec (spec/cat
                 :type (partial = :vec)
                 :value-type ::type
                 :count ::count))

(spec/def ::vec-literal (spec/cat
                         :type (partial = :vecdata)
                         :data (spec/* ::type)))

(spec/def ::pointer (spec/cat
                     :type (partial = :pointer)
                     :value-type ::type))

(spec/def ::constant (spec/cat
                      :type (partial = :constant)
                      :value (constantly true)))

(spec/def ::type (spec/or :double ::double
                          :float ::float
                          :long ::long
                          :int ::int
                          :bool ::bool
                          :number ::number
                          :record ::record
                          :vec ::vec
                          :vec ::vec-literal
                          :pointer ::pointer
                          :unspecified ::unspecified ;; <-- a primitive building block
                          :constant ::constant
                          :dynamic ::dynamic))


(defn export-primitive [x]
  [:export x])
