 (def size-mul *)
 (def size-max max)
 
+
+;;;; Compute the size of a ::sized-type
 (defmultiple compute-size get-pair-tag
   (:vec [x] (let [value (get-pair-value x)]
               (size-mul (:count value) (compute-size (:type value)))))
-  (:double [x] 1)
+  (:number [x] 1)
   (: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)))))
+                                    (-> 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 :double]))))
+(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 :double 3]))))
-(assert (= 2 (compute-size (spec/conform ::sized-type [:union :double [:vec :double 2]]))))
-(assert (= 2 (compute-size (spec/conform ::sized-type [:record :a :double :b :double]))))
+(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 ::arg-decl (spec/cat
+                    :type ::type
+                    :name ::arg-name))
+
+(spec/def ::arg-list (spec/* ::arg-decl))
+
+(spec/def ::statement (constantly true))
+
+(spec/def ::typed-fun (spec/cat
+                       :return-type ::type
+                       :arg-list (spec/spec ::arg-list)
+                       :body (spec/* ::statement)))
+(assert (not= 
+         ::spec/invalid 
+         (spec/conform ::typed-fun [nil [:double 'a :double 'b] :a :b :c])))


(spec/def ::vecdata (spec/cat
                     :type (partial = :vecdata)
                     :values (spec/* ::sized-type)))

;; Compile time tagging
(spec/def ::tagged (spec/cat

            [epicea.utils.defmultiple :refer [defmultiple]]
            [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 #(instance? java.lang.Integer %))
(spec/def ::primitive (spec/or
                       :bool (partial = :bool)
                       :float (partial = :float)
                       :long (partial = :long)
                       :double (partial = :double)
                       :int (partial = :int)))
(spec/def ::dynamic (partial = :dynamic))

(spec/def ::number (spec/or :type #(or (= % :number)
                                       (= % :double))
                            :literal number?))
(spec/def ::count number?)
(spec/def ::key keyword?)

