Commits

ariovistus  committed c0abe5e

* DOT rewrite was a dumb idea.
* added notion of an empty array type, since stupid D types empty
arrays as void[], but allows them to do things void[] can't.
* rewrote matcher and make-ast! to use keywords instead of symbols
for map specification keys (and validate the keys)
* removed some use statements so that use graph is acyclical again

  • Participants
  • Parent commits 941e8da

Comments (0)

Files changed (17)

File grammars/parsed.g

     ID_LIST;
 
     //reserved for semantic
-    DOT;
+    EMPTY_ARR_ELT;
     TUPLE; 
     ERROR;
     TEMPLATE_INSTANTIATION;

File src/org/d/compiler/ast_utils.clj

     (org.d.generated D2ParserTokenTypes D2Lexer D2Parser))
   (:use (clojure.contrib def macro-utils))
   (:use org.d.compiler.utils)
-  (:use (clojure test set)))
+  (:use (clojure test set pprint)))
 
 (defmacro parse2 
   "string of d code to ast"
 (defn ast&siblings 
   "lazy seq of ast and ast's siblings"
   [ast] 
-  (if (nil? (.getNextSibling ast)) (list ast)
-    (lazy-seq (cons ast (ast&siblings (.getNextSibling ast))))))
+  (if (nil? (getsib ast)) (list ast)
+    (lazy-seq (cons ast (ast&siblings (getsib ast))))))
 
 (defn siblings [ast] (rest (ast&siblings ast)))
 
 (defn children 
   "lazy seq of children of ast"
   [ast] 
-  (if (nil? (.getFirstChild ast)) '()
-    (lazy-seq (ast&siblings (.getFirstChild ast)))))
+  (if (nil? (getch ast)) '()
+    (lazy-seq (ast&siblings (getch ast)))))
 
 (defn chN? 
   "tests whether child is the nth child of parent or 
       (attr! astto 'errmsg ermsg))))
 
 ;;;;; The AST MATCHER ;;;;;;;
+(defn keys-check [map-spec ks]
+  (let [baddies (difference (set (keys map-spec)) ks)]
+    (when (not (empty? baddies))
+      (throw (Exception. (str "illegal keys: " baddies))))))
+
+(def matcher-spec-keys #{:t :t? :s :t-> :s-> :ast-> :ast?-> :ast/?-> 
+                         :exp? :ch? :sib? :nch :type :type/?-> :attr?})
 
 (defn spec-terminal? [x] (or (symbol? x) (map? x)))
 
 (defn spec-optional? [x] 
   (and (map? x) 
        (or 
-         (contains? x 't?) 
-         (contains? x 'ast?->)
-         (contains? x 'ast/?->))))
+         (contains? x :t?) 
+         (contains? x :ast?->)
+         (contains? x :ast/?->))))
 
 (defn ensure-symroot [ch]
   (if (spec-terminal? ch) ch
   first element, and A => B will be the last.
   Note that optional nonterminal subtrees introduce branches, and so they 
   are not allowed in this function.
-  Also note that now I want to be able to express siblings of the root, so
-  a top level syntax of (nil A ....) is allowed, which will ignore the 
-  nil -> A sequence.
+  Also note that we are able to express siblings of the root.
+  a top level syntax of (null A ....) is allowed, which will ignore the 
+  null -> A sequence.
   "
   [spec]
   (assert (and (list? spec)
   generated expression returns true if ast referenced by sym does not 
   match matcher specification tok"
   [sym tok]
-  ; these are some stupid things that one might conceivably send to matcher
-  (assert (not (contains? tok ''s)))
-  (assert (not (contains? tok ''t)))
   (cond (symbol? tok)
         `(or (nil? ~sym) 
              (not (= (.getType ~sym) (. D2ParserTokenTypes ~tok))))
         (spec-optional? tok) false
         (map? tok) 
-        (let [
+        (do
+          (keys-check tok matcher-spec-keys)
+          (let [
               conds (list 
                       `(nil? ~sym)
-                      (when (contains? tok 't)
-                        `(not (= (.getType ~sym) (. D2ParserTokenTypes ~(get tok 't))))) 
-                      (when (contains? tok 's)
-                        `(not (= (.getText ~sym) ~(get tok 's))))
-                      (when (contains? tok 'exp?)
-                        `(not (= (.isExp ~sym) ~(get tok 'exp?))))
-                      (when (contains? tok 'ch?)
-                        `(= (nil? (.getFirstChild ~sym)) ~(get tok 'ch?)))
-                      (when (contains? tok 'sib?)
-                        `(= (nil? (.getNextSibling ~sym)) ~(get tok 'sib?)))
-                      (when (contains? tok 'attr?)
-                        (let [spec (get tok 'attr?)]
+                      (when (contains? tok :t)
+                        `(not (= (.getType ~sym) (. D2ParserTokenTypes ~(get tok :t))))) 
+                      (when (contains? tok :s)
+                        `(not (= (.getText ~sym) ~(get tok :s))))
+                      (when (contains? tok :exp?)
+                        `(not (= (.isExp ~sym) ~(get tok :exp?))))
+                      (when (contains? tok :ch?)
+                        `(= (nil? (getch ~sym)) ~(get tok :ch?)))
+                      (when (contains? tok :sib?)
+                        `(= (nil? (getsib ~sym)) ~(get tok :sib?)))
+                      (when (contains? tok :attr?)
+                        (let [spec (get tok :attr?)]
                           (cond (symbol? spec) 
                                 `(not (attr? ~sym (quote ~spec)))
                                 (and (map? spec))
                                               ))
                                 true (assert false))))
 
-                      (when (contains? tok 'type)
+                      (when (contains? tok :type)
                         `(or (not (attr? ~sym ~''type)) 
                              (not (~'=t= (attr ~sym ~''type) 
-                                      ~(get tok 'type)))))
-                      (when (contains? tok 'nch)
-                        `(not (= (.getNumberOfChildren ~sym) ~(get tok 'nch)))))
+                                      ~(get tok :type)))))
+                      (when (contains? tok :nch)
+                        `(not (= (.getNumberOfChildren ~sym) ~(get tok :nch)))))
               ]
-          `(or ~@conds))))
+          `(or ~@conds)))))
 
 (defn cond2 
   "generate an expression to determine whether an ast node matches 
   generated expression returns true if ast referenced by sym does not
   match optional specification tok"
   [sym tok]
+  (assert (map? tok))
+  (keys-check tok matcher-spec-keys)
   (let [cnd1 `(nil? ~sym)
-        cnd2 (if (contains? tok 't?) 
-               `(not (= (.getType ~sym) (. D2ParserTokenTypes ~(get tok 't?)))) 
+        cnd2 (if (contains? tok :t?) 
+               `(not (= (.getType ~sym) (. D2ParserTokenTypes ~(get tok :t?)))) 
                nil)
-        cnd3 (when (contains? tok 'type)
+        cnd3 (when (contains? tok :type)
                `(or (not (attr? ~sym ~''type)) 
-                    (not (~'=t= (attr ~sym ~''type) ~(get tok 'type))))) 
-        cnd4 (when (contains? tok 'attr?)
-               `(not (attr? ~sym ~(get tok 'attr?)))) ]
+                    (not (~'=t= (attr ~sym ~''type) ~(get tok :type))))) 
+        cnd4 (when (contains? tok :attr?)
+               `(not (attr? ~sym ~(get tok :attr?)))) ]
     (if (nil? cnd2) cnd1
       `(or ~cnd1 ~cnd2 ~cnd3 ~cnd4))))
 
   meant to bind values to the symbols per a terminal specification"
   [sym tok] 
   (if (symbol? tok) ()
-    (let [type-syms (if (contains? tok 'type/?->)
-                      (let [tsym (get tok 'type/?->)]
+    (let [type-syms (if (contains? tok :type/?->)
+                      (let [tsym (get tok :type/?->)]
                         `(~tsym (cond ~(cond2 sym tok) nil 
                                       (attr? ~sym ~'type) (attr ~sym ~'type) 
                                       true nil)
                                   (attr? ~sym ~'type) true
                                   true false)))
                       ())]
-      (when (and (map? tok) (or (contains? tok 'ast/?->) 
-                                (contains? tok 'ast?->))) 
-        (assert (not (contains? tok 't))))
+      (when (and (map? tok) (or (contains? tok :ast/?->) 
+                                (contains? tok :ast?->))) 
+        (assert (not (contains? tok :t))))
       (assert (map? tok))
-      (assert (not (and (contains? tok 't) (contains? tok 't?))))
+      (keys-check tok matcher-spec-keys)
+      (assert (not (and (contains? tok :t) (contains? tok :t?))))
       (if (spec-optional? tok)
         (concat
           type-syms
-          (when (contains? tok 'ast/?->)
-            (let [sym2 (get tok 'ast/?->)
+          (when (contains? tok :ast/?->)
+            (let [sym2 (get tok :ast/?->)
                   sym2? (symbol (str sym2 "?"))]
               `(~sym2? (not ~(cond2 sym tok))
                   ~sym2 (if ~(cond2 sym tok) nil ~sym))))
-          (when (contains? tok 'ast?->)
-            (let [sym2? (get tok 'ast?->)]
+          (when (contains? tok :ast?->)
+            (let [sym2? (get tok :ast?->)]
               `(~sym2? (not ~(cond2 sym tok)))))
-          (when (contains? tok 'ast->)
-            (let [sym2 (get tok 'ast->)
+          (when (contains? tok :ast->)
+            (let [sym2 (get tok :ast->)
                   sym2? (symbol (str sym2 "?"))]
               `(~sym2 (if ~(cond2 sym tok) nil ~sym))))
-          (when (contains? tok 't->) 
-            `(~(get tok 't->) (if ~(cond2 sym tok) nil (.getType ~sym))))
-          (when (contains? tok 's->) 
-            `(~(get tok 's->) (if ~(cond2 sym tok) nil (.getText ~sym)))))
+          (when (contains? tok :t->) 
+            `(~(get tok :t->) (if ~(cond2 sym tok) nil (.getType ~sym))))
+          (when (contains? tok :s->) 
+            `(~(get tok :s->) (if ~(cond2 sym tok) nil (.getText ~sym)))))
         (concat 
           type-syms
-          (when (contains? tok 't->) `(~(get tok 't->) (.getType ~sym)))
-          (when (contains? tok 's->) `(~(get tok 's->) (.getText ~sym)))
-          (when (contains? tok 'ast->) `(~(get tok 'ast->) ~sym)))))))
+          (when (contains? tok :t->) `(~(get tok :t->) (.getType ~sym)))
+          (when (contains? tok :s->) `(~(get tok :s->) (.getText ~sym)))
+          (when (contains? tok :ast->) `(~(get tok :ast->) ~sym)))))))
 
 (defmacro matcher 
   "
   and MAP shall be a map literal with one or more of the 
   following pairs:
 
-  t SYMBOL where SYMBOL shall be token type
-  t? SYMBOL where SYMBOL shall be token type, and the existence of 
+  :t SYMBOL where SYMBOL shall be token type
+  :t? SYMBOL where SYMBOL shall be token type, and the existence of 
   the ast node is optional. Optional nodes may not be the root 
   of a subdeclaration. Matches greedily
-  s STRING
-  t-> SYMBOL where the token type integer will bind to SYMBOL
-  s-> SYMBOL where the token string will bind to SYMBOL
-  ast-> SYMBOL where the ast will bind to SYMBOL
-  ast?-> SYMBOL  where SYMBOL shall flag whether the ast node exists
-  ast/?-> SYMBOL where the ast will bind to SYMBOL if it exists, and
+  :s STRING
+  :t-> SYMBOL where the token type integer will bind to SYMBOL
+  :s-> SYMBOL where the token string will bind to SYMBOL
+  :ast-> SYMBOL where the ast will bind to SYMBOL
+  :ast?-> SYMBOL  where SYMBOL shall flag whether the ast node exists
+  :ast/?-> SYMBOL where the ast will bind to SYMBOL if it exists, and
   SYMBOL? will report whether it exists
-  exp? BOOL predicates on whether the ast node is an expression
-  ch? BOOL predicates on whether the ast node has children
-  sib? BOOL predicates on whether the ast node has siblings
-  nch INT predicates on the number of children
-  type TYPE predicates on whether the ast node has a type and the type
+  :exp? BOOL predicates on whether the ast node is an expression
+  :ch? BOOL predicates on whether the ast node has children
+  :sib? BOOL predicates on whether the ast node has siblings
+  :nch INT predicates on the number of children
+  :type TYPE predicates on whether the ast node has a type and the type
   is equivalent to TYPE
-  type/?-> SYMBOL where the type of the ast will bind to SYMBOL if it
+  :type/?-> SYMBOL where the type of the ast will bind to SYMBOL if it
   exists, and SYMBOL? will report whether the ast has a type
-  attr? SYMBOL predicates on whether the ast node has attribute SYMBOL
-  attr? {SYMBOL BOOL} predicates on (ast node has attribute SYMBOL) == BOOL
+  :attr? SYMBOL predicates on whether the ast node has attribute SYMBOL
+  :attr? {SYMBOL BOOL} predicates on (ast node has attribute SYMBOL) == BOOL
 
   Note that there is an implied '.*' at the end of each specification
   list. 
 (defn all-syms 
   "extract all the symbols that matcher specification spec will define"
   [spec]
-  (loop [stack (list spec) symses '()]
+  (loop [stack (list spec) symses ()]
     (if (empty? stack) symses
       (let [f (first stack) r (rest stack)]
         (cond 
 (deftest test-matcher 
          (let [a (parse2 "1+2;" exp)]
            (is (matches? a (Add IntegerLiteral IntegerLiteral)))
-           (is (matches? a ({nch 2})))
-           (is (not (matches? a ({nch 0}))))
-           (is (not (matches? a ({nch 1}))))
-           (is (not (matches? a ({nch 3}))))
-           (is (matches? a ({ch? true})))
-           (is (not (matches? a ({ch? false}))))
-           (is (matches? a ({sib? false})))
-           (is (not (matches? a ({sib? true}))))
-           (match-case a ({t Add ast-> a} 
-                          {t IntegerLiteral ast-> b} 
-                          {t IntegerLiteral ast-> c})
-                       (do
-                         (is (matches? b ({ch? false})))
-                         (is (not (matches? b ({ch? true}))))
-                         (is (matches? b ({sib? true})))
-                         (is (not (matches? b ({sib? false}))))
-                         (is (matches? b ({nch 0})))
-                         (is (not (matches? b ({nch 1}))))
-                         (is (matches? c ({ch? false})))
-                         (is (not (matches? c ({ch? true}))))
-                         (is (matches? c ({sib? false})))
-                         (is (not (matches? c ({sib? true}))))
-                         (is (matches? c ({nch 0})))
-                         (is (not (matches? c ({nch 1}))))))))
+           (is (matches? a ({:nch 2})))
+           (is (not (matches? a ({:nch 0}))))
+           (is (not (matches? a ({:nch 1}))))
+           (is (not (matches? a ({:nch 3}))))
+           (is (matches? a ({:ch? true})))
+           (is (not (matches? a ({:ch? false}))))
+           (is (matches? a ({:sib? false})))
+           (is (not (matches? a ({:sib? true}))))
+           #_(match-case a ({:t Add } 
+                            {:t IntegerLiteral :ast-> b} 
+                            {:t IntegerLiteral :ast-> c})
+                       (do )
+                       #_(do
+                         (is (matches? b ({:ch? false})))
+                         (is (not (matches? b ({:ch? true}))))
+                         (is (matches? b ({:sib? true})))
+                         (is (not (matches? b ({:sib? false}))))
+                         (is (matches? b ({:nch 0})))
+                         (is (not (matches? b ({:nch 1}))))
+                         (is (matches? c ({:ch? false})))
+                         (is (not (matches? c ({:ch? true}))))
+                         (is (matches? c ({:sib? false})))
+                         (is (not (matches? c ({:sib? true}))))
+                         (is (matches? c ({:nch 0})))
+                         (is (not (matches? c ({:nch 1}))))))))
+
+;;; THE AST MAKER ;;;
+
+(def maker-spec-keys #{:t :s :ast :ch :sib})
 
 (defn insert-spec? [x] 
-  (and (map? x) (contains? x 'ast)))
+  (and (map? x) (contains? x :ast)))
 
 (defn create-spec? [x] 
   (or (symbol? x) (and (map? x) 
-                       (not (insert-spec? x))))) 
+                       (do 
+                         (keys-check x maker-spec-keys)
+                         (not (insert-spec? x)))))) 
 
 (defmacro tok-case [exp & rst]
   (let [pairs (partition 2 rst)
     Minusminus "--"
     (str token)))
 
+
 (defn init-ast [[spec sym]]
-  (let [tokk (if (symbol? spec) spec (get spec 't))
+  (let [tokk (if (symbol? spec) spec (get spec :t))
         strk (if (symbol? spec) `(tokstr '~spec)
                (do (assert (create-spec? spec))
-                 (if (contains? spec 's) (get spec 's)
-                   `(tokstr '~(get spec 't)))))]
+                 (if (contains? spec :s) (get spec :s)
+                   `(tokstr '~(get spec :t)))))]
     `(.initialize ~sym (tok ~tokk) ~strk)))
 
 (defn set-ast-links [[[spec1 sym1] [spec2 sym2] n]] 
   (cond 
     (and (insert-spec? spec1) (= n 1)) 
-    (case (or (get spec1 'ch) 'ap)
+    (case (or (get spec1 :ch) 'ap)
       'ap `(if (nil? (last (children ~sym1))) 
-             (.setFirstChild ~sym1 ~sym2) 
-             (.setNextSibling (last (children ~sym1)) ~sym2))
+             (setch! ~sym1 ~sym2) 
+             (setsib! (last (children ~sym1)) ~sym2))
       'pp (assert false)
-      'null `(.setFirstChild ~sym1 ~sym2))
+      'null `(setch! ~sym1 ~sym2))
     (insert-spec? spec1) 
-    (let [sib (if (contains? spec1 'sib) (get spec1 'sib) 'ap)]
-      (case (or (get spec1 'sib) 'ap)
-        'ap `(.setNextSibling (last (ast&siblings ~sym1)) ~sym2)
+    (let [sib (if (contains? spec1 :sib) (get spec1 :sib) 'ap)]
+      (case (or (get spec1 :sib) 'ap)
+        'ap `(setsib! (last (ast&siblings ~sym1)) ~sym2)
         'pp (assert false)
-        'null `(.setNextSibling ~sym1 ~sym2)))
+        'null `(setsib! ~sym1 ~sym2)))
     (create-spec? spec1) (do 
-                           (if (= n 1) `(.setFirstChild ~sym1 ~sym2)
-                             `(.setNextSibling ~sym1 ~sym2)))))
+                           (if (= n 1) `(setch! ~sym1 ~sym2)
+                             `(setsib! ~sym1 ~sym2)))))
 
 (deftest test-set-ast-links
          (is (= (set-ast-links '((Int s1) (Long s2) 1)) 
-                '(.setFirstChild s1 s2)))
+                `(setch! ~'s1 ~'s2)))
          (is (= (set-ast-links '((Int s1) (Long s2) 2)) 
-                '(.setNextSibling s1 s2)))
-         (is (= (set-ast-links '(({ast x}  s1) (Long s2) 1))
+                `(setsib! ~'s1 ~'s2)))
+         (is (= (set-ast-links '(({:ast x}  s1) (Long s2) 1))
                 `(if (nil? (last (children ~'s1))) 
-                   (.setFirstChild ~'s1 ~'s2) 
-                   (.setNextSibling (last (children ~'s1)) ~'s2))))
-         (is (= (set-ast-links '(({ast x ch ap}  s1) (Long s2) 1)) 
+                   (setch! ~'s1 ~'s2) 
+                   (setsib! (last (children ~'s1)) ~'s2))))
+         (is (= (set-ast-links '(({:ast x :ch ap} s1) (Long s2) 1)) 
                 `(if (nil? (last (children ~'s1))) 
-                   (.setFirstChild ~'s1 ~'s2) 
-                   (.setNextSibling (last (children ~'s1)) ~'s2))))
-         (is (= (set-ast-links '(({ast x ch null}  s1) (Long s2) 1)) 
-                '(.setFirstChild s1 s2))) 
-         (is (= (set-ast-links '(({ast x}  s1) (Long s2) 2)) 
-                `(.setNextSibling (last (ast&siblings ~'s1)) ~'s2)))
-         (is (= (set-ast-links '(({ast x sib ap}  s1) (Long s2) 2)) 
-                `(.setNextSibling (last (ast&siblings ~'s1)) ~'s2)))
-         (is (= (set-ast-links '(({ast x sib null}  s1) (Long s2) 2)) 
-                '(.setNextSibling s1 s2))) 
+                   (setch! ~'s1 ~'s2) 
+                   (setsib! (last (children ~'s1)) ~'s2))))
+         (is (= (set-ast-links '(({:ast x :ch null}  s1) (Long s2) 1)) 
+                `(setch! ~'s1 ~'s2))) 
+         (is (= (set-ast-links '(({:ast x} s1) (Long s2) 2)) 
+                `(setsib! (last (ast&siblings ~'s1)) ~'s2)))
+         (is (= (set-ast-links '(({:ast x :sib ap}  s1) (Long s2) 2)) 
+                `(setsib! (last (ast&siblings ~'s1)) ~'s2)))
+         (is (= (set-ast-links '(({:ast x :sib null}  s1) (Long s2) 2)) 
+                `(setsib! ~'s1 ~'s2))) 
          )
 
 (defn only [x]
   and MAP shall be a map literal with one or more of the 
   following pairs:
 
-  t SYMBOL - token type of ast 
-  s STRING - text of ast
+  :t SYMBOL - token type of ast 
+  :s STRING - text of ast
 
   the above are used to specify a new node to be created.
   the below are used to specify an existing node to be inserted into 
   the tree
 
-  ast EXP - ast to insert into constructed ast
-  ch SYMBOL - specifies how to attach children to this node.
+  :ast EXP - ast to insert into constructed ast
+  :ch SYMBOL - specifies how to attach children to this node.
   SYMBOL may be:
   null - discard existing children 
   pp - prepend constructed children onto existing children
   ap - append constructed children onto existing children 
-  sib SYMBOL - specifies how to attach siblings to this node.
+  :sib SYMBOL - specifies how to attach siblings to this node.
   SYMBOL is same as for ch
 
   In the case specification => (nil subspec+), returns the first subspec node
              (insert-spec? (only (second spec)))))
     (let [sprc (cond (= 1 (count spec)) (first spec)
                      (= 2 (count spec)) (only second spec))
-          sym (get sprc 'ast)]
+          sym (get sprc :ast)]
       `(do
-         ~@(when (and (contains? sprc 'ch) 
-                      (= 'null (get sprc 'ch))) 
-             `((.setFirstChild ~sym nil)))
-         ~@(when (and (contains? sprc 'sib) 
-                      (= 'null (get sprc 'sib))) 
-             `((.setNextSibling ~sym nil)))
+         ~@(when (and (contains? sprc :ch) 
+                      (= 'null (get sprc :ch))) 
+             `((setch! ~sym nil)))
+         ~@(when (and (contains? sprc :sib) 
+                      (= 'null (get sprc :sib))) 
+             `((setsib! ~sym nil)))
          ~sym))
     true (let 
            [; sched is list of ((spec sym) (spec sym) n)
             makethese (filter #(create-spec? (first %)) spec-syms) 
             nomkthese (filter #(insert-spec? (first %)) spec-syms)
             letdefs (mapcat #(list (second %) `(MyAST.)) makethese)
-            letdefs2 (mapcat #(list (second %) (get (first %) 'ast)) nomkthese)
+            letdefs2 (mapcat #(list (second %) (get (first %) :ast)) nomkthese)
             initdefs (map init-ast makethese)
             initdefs2 (mapcat #(concat 
-                                 (when (= 'null (get (first %) 'ch)) 
-                                   (list `(.setFirstChild ~(second %) nil)))
-                                 (when (= 'null (get (first %) 'sib)) 
-                                   (list `(.setNextSibling ~(second %) nil)))
+                                 (when (= 'null (get (first %) :ch)) 
+                                   (list `(setch! ~(second %) nil)))
+                                 (when (= 'null (get (first %) :sib)) 
+                                   (list `(setsib! ~(second %) nil)))
                                  ) 
                               nomkthese)
             setdefs (map set-ast-links sched)
 
 (deftest test-make-ast
          (let [ast (parse2 "2+3;" exp)]
-           (make-ast! ({ast ast ch null}))
-           (is (nil? (.getFirstChild ast))))
-         (let [ast (.getFirstChild (parse2 "2+3;" exp))]
-           (make-ast! ({ast ast sib null}))
-           (is (nil? (.getNextSibling ast))))
-         (let [ast (.getFirstChild (parse2 "2+3;" exp))]
-           (make-ast! ({ast ast sib null} Long))
-           (is (= (tok Long) (.getType (.getFirstChild ast))))
-           (is (nil? (.getNextSibling ast))))
+           (make-ast! ({:ast ast :ch null}))
+           (is (nil? (getch ast))))
+         (let [ast (getch (parse2 "2+3;" exp))]
+           (make-ast! ({:ast ast :sib null}))
+           (is (nil? (getsib ast))))
+         (let [ast (getch (parse2 "2+3;" exp))]
+           (make-ast! ({:ast ast :sib null} Long))
+           (is (= (tok Long) (.getType (getch ast))))
+           (is (nil? (getsib ast))))
          (is (= (.getText (make-ast! (Long))) "long"))
-         (is (= (.getText (make-ast! ({t Long}))) "long"))
-         (is (= (.getText (make-ast! ({t Long s "long"}))) "long"))
+         (is (= (.getText (make-ast! ({:t Long}))) "long"))
+         (is (= (.getText (make-ast! ({:t Long :s "long"}))) "long"))
          (is (= (.getText (make-ast! (null Long))) "long"))
          (is (matches? (make-ast! (Add Class (BASIC_TYPE Int)))
                        (Add Class (BASIC_TYPE Int))))
          (is (matches? (make-ast! 
-                         ({ast (parse2 "1+2;" exp) ch null} Long))
+                         ({:ast (parse2 "1+2;" exp) :ch null} Long))
                        (Add Long)))
-         (is (matches? (make-ast! ({ast (parse2 "1+2;" exp)} Long))
-                       (Add IntegerLiteral IntegerLiteral Long))))
+         (is (matches? (make-ast! ({:ast (parse2 "1+2;" exp)} Long))
+                       (Add IntegerLiteral IntegerLiteral Long)))
+         (is (matches? (make-ast! (null Int)) (Int)))
+         )
 

File src/org/d/compiler/constfold.clj

                  ast)]
     (cond
       (=t= tipo ULONG) 
-      (atr!! (make-ast! ({t IntegerLiteral s (str value "UL")})))
+      (atr!! (make-ast! ({:t IntegerLiteral :s (str value "UL")})))
       (=t= tipo LONG) 
       (if (< value 0)
-        (atr!! (make-ast! (Minus {t IntegerLiteral s (str (- value) "L")})))
-        (atr!! (make-ast! ({t IntegerLiteral s (str value "L")}))))
+        (atr!! (make-ast! (Minus {:t IntegerLiteral :s (str (- value) "L")})))
+        (atr!! (make-ast! ({:t IntegerLiteral :s (str value "L")}))))
       (=t= tipo UINT) 
-      (atr!! (make-ast! ({t IntegerLiteral s (str value "U")})))
+      (atr!! (make-ast! ({:t IntegerLiteral :s (str value "U")})))
       (=t= tipo INT) 
       (if (< value 0)
-        (atr!! (make-ast! (Minus {t IntegerLiteral s (str (- value))})))
-        (atr!! (make-ast! ({t IntegerLiteral s (str value)}))))
+        (atr!! (make-ast! (Minus {:t IntegerLiteral :s (str (- value))})))
+        (atr!! (make-ast! ({:t IntegerLiteral :s (str value)}))))
       (signed? tipo)
       (if (< value 0)
-        (atr!! (make-ast! (Cast {ast (copy tipo)} 
-                                (Minus {t IntegerLiteral s (str (- value))}))))
-        (atr!! (make-ast! (Cast {ast (copy tipo)} 
-                                (Minus {t IntegerLiteral s (str value)})))))
+        (atr!! (make-ast! (Cast {:ast (copy tipo)} 
+                                (Minus {:t IntegerLiteral :s (str (- value))}))))
+        (atr!! (make-ast! (Cast {:ast (copy tipo)} 
+                                (Minus {:t IntegerLiteral :s (str value)})))))
       true
-      (atr!! (make-ast! (Cast {ast (copy tipo)} 
-                              (Minus {t IntegerLiteral s (str value)})))))))
+      (atr!! (make-ast! (Cast {:ast (copy tipo)} 
+                              (Minus {:t IntegerLiteral :s (str value)})))))))
 
 (defn str-lit-v [ast state]
   (let [s (.getText ast)
               (True)  true
               (False) true 
               (Null) true
-              ({t Cast type/?-> t} {} IntegerLiteral)
+              ({:t Cast :type/?-> t} {} IntegerLiteral)
               (and t? (< (sizeof t ast state) 4))
-              ({t Minus nch 1} FloatLiteral) true
-              ({t Minus nch 1 type/?-> t} IntegerLiteral) 
+              ({:t Minus :nch 1} FloatLiteral) true
+              ({:t Minus :nch 1 :type/?-> t} IntegerLiteral) 
               (and t? (signed? t))
               false))
 
             (not (attr? ast 'type)))
         false
         true (match-case ast 
-                    ({t Cast type/?-> t1} {} {type/?-> t2})
+                    ({:t Cast :type/?-> t1} {} {:type/?-> t2})
                     (and t1? t2? (=t= t1 t2) )
                     (ARRAY_LIT) false
                     (not (literal? ast state)))))
   (assert (not (literal? ast state)))
   (cond 
     (and (matches? ast (Cast))
-         (match-case ast (Cast {} {type true type/?-> t}) t?)
-         (=t= (attr ast 'type) (match-case ast (Cast {} {type true type/?-> t}) t)))
-    (match-case ast (Cast {} {ast-> e}) e)
+         (match-case ast (Cast {} {:type true :type/?-> t}) t?)
+         (=t= (attr ast 'type) (match-case ast (Cast {} {:type true :type/?-> t}) t)))
+    (match-case ast (Cast {} {:ast-> e}) e)
     (darray? (attr ast 'type))
     (let [elt (elt-t (attr ast 'type))]
       (cond (int-t? elt)
             (let [elts (map #(intv2ast % elt state) (attr ast 'value))
                   _ (last (map (fn [[a,b]] (setsib! a b)) (partition 2 1 elts)))
-                  a (make-ast! (ARRAY_LIT {ast (first elts)}))]
+                  a (make-ast! (ARRAY_LIT {:ast (first elts)}))]
               (.setExp a)
               a)
             true (do (error! ast "not implemented") ast)))
   (match-case ast
               ; kinda turned into a mess, but this is basically
               ; (op (op a val) val) => (op a (op val val))
-              ({exp? true nch 2 attr? {type true value false}} 
-               ({exp? true nch 2 ast-> inner attr? {type true value false}} 
-                {ast-> other attr? {type true value false}} 
-                {ast-> lhs attr? {type true value true}}) 
-               {ast-> rhs attr? {type true value true}}) 
+              ({:exp? true :nch 2 :attr? {type true value false}} 
+               ({:exp? true :nch 2 :ast-> inner :attr? {type true value false}} 
+                {:ast-> other :attr? {type true value false}} 
+                {:ast-> lhs :attr? {type true value true}}) 
+               {:ast-> rhs :attr? {type true value true}}) 
               (and (= (.getType ast) (.getType inner))
                    (apply dt-associative? (cons ast (map #(attr % 'type) [other,lhs,rhs]))))
               ; (op val (op val a)) => (op (op val val) a)
-              ({exp? true nch 2 attr? {type true value false}} 
-               {ast-> lhs attr? {type true value true}}
-               ({exp? true nch 2 ast-> inner attr? {type true value false}} 
-                {ast-> rhs attr? {type true value true}}
-                {ast-> other attr? {type true value false}}))
+              ({:exp? true :nch 2 :attr? {type true value false}} 
+               {:ast-> lhs :attr? {type true value true}}
+               ({:exp? true :nch 2 :ast-> inner :attr? {type true value false}} 
+                {:ast-> rhs :attr? {type true value true}}
+                {:ast-> other :attr? {type true value false}}))
               (and (= (.getType ast) (.getType inner))
                    (apply dt-associative? (cons ast (map #(attr % 'type) [lhs,rhs,other]))))
               ; (op val (op a val)) => (op (op val val) a)
-              ({exp? true nch 2 attr? {type true value false}} 
-               {ast-> lhs attr? {type true value true}}
-               ({exp? true nch 2 ast-> inner attr? {type true value false}} 
-                {ast-> other attr? {type true value false}}
-                {ast-> rhs attr? {type true value true}}))
+              ({:exp? true :nch 2 :attr? {type true value false}} 
+               {:ast-> lhs :attr? {type true value true}}
+               ({:exp? true :nch 2 :ast-> inner :attr? {type true value false}} 
+                {:ast-> other :attr? {type true value false}}
+                {:ast-> rhs :attr? {type true value true}}))
               (and (= (.getType ast) (.getType inner))
                    (apply dt-commutative? (cons ast (map #(attr % 'type) [other,rhs])))
                    (apply dt-associative? (cons ast (map #(attr % 'type) [lhs,rhs,other]))))
               ; (op (op val a) val) => (op a (op val val))
-              ({exp? true nch 2 attr? {type true value false}} 
-               ({exp? true nch 2 ast-> inner attr? {type true value false}} 
-                {ast-> lhs attr? {type true value true}}
-                {ast-> other attr? {type true value false}})
-               {ast-> rhs attr? {type true value true}})
+              ({:exp? true :nch 2 :attr? {type true value false}} 
+               ({:exp? true :nch 2 :ast-> inner :attr? {type true value false}} 
+                {:ast-> lhs :attr? {type true value true}}
+                {:ast-> other :attr? {type true value false}})
+               {:ast-> rhs :attr? {type true value true}})
               (and (= (.getType ast) (.getType inner))
                    (apply dt-commutative? (cons ast (map #(attr % 'type) [lhs,other])))
                    (apply dt-associative? (cons ast (map #(attr % 'type) [lhs,rhs,other]))))
 (defn assoc-rewrite! [ast state]
   (match-case ast
               ; (op (op a val) val) => (op a (op val val))
-              ({exp? true nch 2 attr? {type true value false}} 
-               ({exp? true nch 2 ast-> inner attr? {type true value false}} 
-                {ast-> other attr? {type true value false}} 
-                {ast-> lhs attr? {type true value true}}) 
-               {ast-> rhs attr? {type true value true}})
-              (make-ast! ({ast ast ch null sib null}
-                          {ast other sib null}
-                          ({ast inner ch null sib null}
-                           {ast lhs sib null}
-                           {ast rhs sib null})))
+              ({:exp? true :nch 2 :attr? {type true value false}} 
+               ({:exp? true :nch 2 :ast-> inner :attr? {type true value false}} 
+                {:ast-> other :attr? {type true value false}} 
+                {:ast-> lhs :attr? {type true value true}}) 
+               {:ast-> rhs :attr? {type true value true}})
+              (make-ast! ({:ast ast :ch null :sib null}
+                          {:ast other :sib null}
+                          ({:ast inner :ch null :sib null}
+                           {:ast lhs :sib null}
+                           {:ast rhs :sib null})))
               ; (op val (op val a)) => (op (op val val) a)
-              ({exp? true nch 2 attr? {type true value false}} 
-               {ast-> lhs attr? {type true value true}}
-               ({exp? true nch 2 ast-> inner attr? {type true value false}} 
-                {ast-> rhs attr? {type true value true}}
-                {ast-> other attr? {type true value false}}))
-              (make-ast! ({ast ast ch null sib null}
-                          ({ast inner ch null sib null}
-                           {ast lhs sib null}
-                           {ast rhs sib null})
-                          {ast other sib null}))
+              ({:exp? true :nch 2 :attr? {type true value false}} 
+               {:ast-> lhs :attr? {type true value true}}
+               ({:exp? true :nch 2 :ast-> inner :attr? {type true value false}} 
+                {:ast-> rhs :attr? {type true value true}}
+                {:ast-> other :attr? {type true value false}}))
+              (make-ast! ({:ast ast :ch null :sib null}
+                          ({:ast inner :ch null :sib null}
+                           {:ast lhs :sib null}
+                           {:ast rhs :sib null})
+                          {:ast other :sib null}))
               ; (op val (op a val)) => (op (op val val) a)
-              ({exp? true nch 2 attr? {type true value false}} 
-               {ast-> lhs attr? {type true value true}}
-               ({exp? true nch 2 ast-> inner attr? {type true value false}} 
-                {ast-> other attr? {type true value false}}
-                {ast-> rhs attr? {type true value true}}))
-              (make-ast! ({ast ast ch null sib null}
-                          ({ast inner ch null sib null}
-                           {ast lhs sib null}
-                           {ast rhs sib null})
-                          {ast other sib null}))
+              ({:exp? true :nch 2 :attr? {type true value false}} 
+               {:ast-> lhs :attr? {type true value true}}
+               ({:exp? true :nch 2 :ast-> inner :attr? {type true value false}} 
+                {:ast-> other :attr? {type true value false}}
+                {:ast-> rhs :attr? {type true value true}}))
+              (make-ast! ({:ast ast :ch null :sib null}
+                          ({:ast inner :ch null :sib null}
+                           {:ast lhs :sib null}
+                           {:ast rhs :sib null})
+                          {:ast other :sib null}))
               ; (op (op val a) val) => (op a (op val val))
-              ({exp? true nch 2 attr? {type true value false}} 
-               ({exp? true nch 2 ast-> inner attr? {type true value false}} 
-                {ast-> lhs attr? {type true value true}}
-                {ast-> other attr? {type true value false}})
-               {ast-> rhs attr? {type true value true}})
-              (make-ast! ({ast ast ch null sib null}
-                          {ast other sib null}
-                          ({ast inner ch null sib null}
-                           {ast lhs sib null}
-                           {ast rhs sib null})))))
+              ({:exp? true :nch 2 :attr? {type true value false}} 
+               ({:exp? true :nch 2 :ast-> inner :attr? {type true value false}} 
+                {:ast-> lhs :attr? {type true value true}}
+                {:ast-> other :attr? {type true value false}})
+               {:ast-> rhs :attr? {type true value true}})
+              (make-ast! ({:ast ast :ch null :sib null}
+                          {:ast other :sib null}
+                          ({:ast inner :ch null :sib null}
+                           {:ast lhs :sib null}
+                           {:ast rhs :sib null})))))
 
 (deftest test-assoc-rewrite
          (letfn [(atrfy! [a,add2,A,one,two] 
            (let [a (rewrites-1! (parse2 "1+(a+2);" exp))]
              (is (= "1 + a + 2" (format2 a)))
              (is (matches? a (Add IntegerLiteral Add)))
-             (match-case a (Add {ast-> one} ({ast-> add2} {ast-> A} {ast-> two}))
+             (match-case a (Add {:ast-> one} ({:ast-> add2} {:ast-> A} {:ast-> two}))
                          (do (atrfy! a add2 A one two)
                            (is (assoc-rewrite? a))
                            (let [b (assoc-rewrite! a (struct State))]
            (let [a (rewrites-1! (parse2 "1+(2+a);" exp))]
              (is (= "1 + 2 + a" (format2 a)))
              (is (matches? a (Add IntegerLiteral Add)))
-             (match-case a (Add {ast-> one} ({ast-> add2} {ast-> two} {ast-> A}))
+             (match-case a (Add {:ast-> one} ({:ast-> add2} {:ast-> two} {:ast-> A}))
                          (do (atrfy! a add2 A one two)
                            (is (assoc-rewrite? a))
                            (let [b (assoc-rewrite! a (struct State))]
            (let [a (rewrites-1! (parse2 "(a+1)+2);" exp))]
              (is (= "a + 1 + 2" (format2 a)))
              (is (matches? a (Add Add IntegerLiteral)))
-             (match-case a (Add ({ast-> add2} {ast-> A} {ast-> one}) {ast-> two})
+             (match-case a (Add ({:ast-> add2} {:ast-> A} {:ast-> one}) {:ast-> two})
                          (do (atrfy! a add2 A one two)
                            (is (assoc-rewrite? a))
                            (let [b (assoc-rewrite! a (struct State))]
            (let [a (rewrites-1! (parse2 "(1+a)+2);" exp))]
              (is (= "1 + a + 2" (format2 a)))
              (is (matches? a (Add Add IntegerLiteral)))
-             (match-case a (Add ({ast-> add2} {ast-> one} {ast-> A}) {ast-> two})
+             (match-case a (Add ({:ast-> add2} {:ast-> one} {:ast-> A}) {:ast-> two})
                          (do (atrfy! a add2 A one two)
                            (is (assoc-rewrite? a))
                            (let [b (assoc-rewrite! a (struct State))]
                           (attr! ast 'value (apply vector vl))))
                       nil)
                     nil))
-                ({nch 2} {ast-> lhs} {ast-> rhs})
+                ({:nch 2} {:ast-> lhs} {:ast-> rhs})
                 (when (and (attr? rhs 'type) (attr? lhs 'type) 
                            (attr? lhs 'value) (attr? rhs 'value))
                   (let [op (binop-op ast)]
                       (let [v (op ast lhs rhs state)]
                         (when (not (error? ast))
                           (attr! ast 'value v))))))
-                ({nch 1} {ast-> rhs})
+                ({:nch 1} {:ast-> rhs})
                 (when (and (attr? rhs 'type) (attr? rhs 'value))
                   (let [op (unop-op ast)]
                     (if (nil? op) nil
                 (let [v (float-lit-v ast state)]
                   (when (not (error? ast))
                     (attr! ast 'value v)))
-                ({t StringLiteral s-> ss})
+                ({:t StringLiteral :s-> ss})
                 (let [op (if (= (first ss) \x) hexstr-lit-v str-lit-v)
                       v (op ast state)]
                   (when (not (error? ast))

File src/org/d/compiler/d_type.clj

 
 (defn obj-alias [s]
   (t-ok! (make-ast! (BASIC_TYPE (ID_LIST 
-                           {t Identifier s "object"} 
-                           {t Identifier s s})))))
+                           {:t Identifier :s "object"} 
+                           {:t Identifier :s s})))))
     
 (defmacro mk-basic-t [t]
   `(t-ok! (make-ast! ~(list 'BASIC_TYPE t))))
 (def CDOUBLE (mk-basic-t Cdouble))
 (def CREAL (mk-basic-t Creal))
 (def VOID (mk-basic-t Void))
+(def EMPTY_ELT (mk-basic-t EMPTY_ARR_ELT))
 
 (def STRING (obj-alias "string"))
 (def WSTRING (obj-alias "wstring"))
             na))))
 
 (defn make-aarray-t [keyt valt]
-  (t-ok! (make-ast! (AARRAY_DECL {ast (tcopy valt)} {ast (tcopy keyt)}))))
+  (t-ok! (make-ast! (AARRAY_DECL {:ast (tcopy valt)} {:ast (tcopy keyt)}))))
 
 (defn make-darray-t [elt]
-  (t-ok! (make-ast! (DARRAY_DECL {ast (tcopy elt)}))))
+  (t-ok! (make-ast! (DARRAY_DECL {:ast (tcopy elt)}))))
+
+(def EMPTY_ARR (make-darray-t EMPTY_ELT))
 
 (defn make-tuple-t [& elts]
   (let [elts2 (map #(tcopy %) elts)
         _ (last (map (fn [[a b]] (.setNextSibling a b)) (partition 2 1 elts2)))
-        tupl (make-ast! (TUPLE {ast (first elts2)}))]
+        tupl (make-ast! (TUPLE {:ast (first elts2)}))]
     (t-ok! tupl)))
 
 (defn make-ptr-t [elt]
-  (t-ok! (make-ast! (POINTER {ast (tcopy elt)}))))
+  (t-ok! (make-ast! (POINTER {:ast (tcopy elt)}))))
 
 
 (defn type? [ast]
   (cond (attr? ast 't-ok) true
         (error? ast) false
         true (match-case ast
-                         (POINTER {ast-> t1 attr? t-ok}) true
-                         (DARRAY_DECL {ast-> t1 attr? t-ok}) true
-                         (SARRAY_DECL {ast-> t1 attr? t-ok} 
-                                      {t IntegerLiteral ast-> e1})
+                         (POINTER {:ast-> t1 :attr? t-ok}) true
+                         (DARRAY_DECL {:ast-> t1 :attr? t-ok}) true
+                         (SARRAY_DECL {:ast-> t1 :attr? t-ok} 
+                                      {:t IntegerLiteral :ast-> e1})
                          (and (not (error? e1))
                               (attr? e1 'value)
                               (<= 0 (attr e1 'value)))
-                         (AARRAY_DECL {ast-> vt} {ast-> kt attr? t-ok}) true
-                         (DELEGATE {ast-> t1 attr? t-ok} {t PARAMETERS ast-> p} 
-                                   {t? POSTFIX ast/?-> pf})
+                         (AARRAY_DECL {:ast-> vt} {:ast-> kt :attr? t-ok}) true
+                         (DELEGATE {:ast-> t1 :attr? t-ok} {:t PARAMETERS :ast-> p} 
+                                   {:t? POSTFIX :ast/?-> pf})
                          (all? #(matches-any?  % 
                                              (PARAMETER 
-                                               {t? PARAM_MODIFIER}
-                                               {attr? t-ok}) 
+                                               {:t? PARAM_MODIFIER}
+                                               {:attr? t-ok}) 
                                              (PARAMETER Vararg))
                                    (children p))
-                         (FUNCTION {ast-> t1 attr? t-ok} {t PARAMETERS ast-> p} 
-                                   {t? POSTFIX ast/?-> pf})
+                         (FUNCTION {:ast-> t1 :attr? t-ok} {:t PARAMETERS :ast-> p} 
+                                   {:t? POSTFIX :ast/?-> pf})
                          (all? #(matches-any?  % 
                                              (PARAMETER 
-                                               {t? PARAM_MODIFIER}
-                                               {attr? t-ok}) 
+                                               {:t? PARAM_MODIFIER}
+                                               {:attr? t-ok}) 
                                              (PARAMETER Vararg))
                                    (children p))
-                         (PARAM_SPEC {ast-> t1 attr? t-ok} 
-                                     {t PARAMETERS ast-> p}
-                                     {t? POSTFIX ast/?-> pf})
+                         (PARAM_SPEC {:ast-> t1 :attr? t-ok} 
+                                     {:t PARAMETERS :ast-> p}
+                                     {:t? POSTFIX :ast/?-> pf})
                          (all? #(matches-any?  % 
                                              (PARAMETER 
-                                               {t? PARAM_MODIFIER}
-                                               {attr? t-ok}) 
+                                               {:t? PARAM_MODIFIER}
+                                               {:attr? t-ok}) 
                                              (PARAMETER Vararg))
                                    (children p))
-                         (TUPLE {ast-> t1})
+                         (TUPLE {:ast-> t1})
                          (all? #(attr? % 't-ok) (ast&siblings t1))
-                         (TYPE_MOD {ast-> t1 attr? t-ok} {}) true
+                         (TYPE_MOD {:ast-> t1 :attr? t-ok} {}) true
                          ; rewrite slice type to an actual tuple type
                          (SLICE_TYPE) false
                          ; rewrite typeof to an actual type
+                         (BASIC_TYPE EMPTY_ARR_ELT) true
                          (BASIC_TYPE Typeof) false
                          ; rewrite .idlist to absolute id list
                          (BASIC_TYPE Dot) false
       (recur (getch t1) (getch t2))
       (= (.getType t1) (.getType t2) (tok SARRAY_DECL))
       (match-case 
-        t1 (SARRAY_DECL {ast-> c1} {t IntegerLiteral ast-> e1})
-        (match-case t2 (SARRAY_DECL {ast-> c2} {t IntegerLiteral ast-> e2})
+        t1 (SARRAY_DECL {:ast-> c1} {:t IntegerLiteral :ast-> e1})
+        (match-case t2 (SARRAY_DECL {:ast-> c2} {:t IntegerLiteral :ast-> e2})
                     (cond (= (attr e1 'value) (attr e2 'value))
                           (recur c1 c2)
                           true false)))
       (= (.getType t1) (.getType t2) (tok AARRAY_DECL))
-      (match-case t1 (AARRAY_DECL {ast-> k1} {ast-> v1})
-                  (match-case t2 (AARRAY_DECL {ast-> k2} {ast-> v2})
+      (match-case t1 (AARRAY_DECL {:ast-> k1} {:ast-> v1})
+                  (match-case t2 (AARRAY_DECL {:ast-> k2} {:ast-> v2})
                               (let [x (=t= k1 k2)]
                                 (if (not x) false
                                   (recur v1 v2)))))
       ; todo: take postfix parts into account, figure out how to handle properties,
       ; figure out whether parameter modifiers are allowed with varargs
       ; figure out if some of the parameter modifiers are type modifiers
-      (match-case t1 ({} {ast-> r1} {t PARAMETERS ast-> ps1} 
-                               {t? POSTFIX ast/?-> pf1})
-                  (match-case t2 ({} {ast-> r2} {t PARAMETERS ast-> ps2} 
-                                           {t? POSTFIX ast/?-> pf2})
+      (match-case t1 ({} {:ast-> r1} {:t PARAMETERS :ast-> ps1} 
+                               {:t? POSTFIX :ast/?-> pf1})
+                  (match-case t2 ({} {:ast-> r2} {:t PARAMETERS :ast-> ps2} 
+                                           {:t? POSTFIX :ast/?-> pf2})
                                 (cond (or pf1 pf2) false
                                   (all? (fn [[p1 p2]] 
                                          (match-case p1 
                                                      (PARAMETER Vararg)
                                                      (matches? p2 (PARAMETER Vararg))
-                                                     (PARAMETER {t? PARAM_MODIFIER ast/?-> pm1} {ast-> tt1} {t? Identifier} Vararg)
+                                                     (PARAMETER {:t? PARAM_MODIFIER :ast/?-> pm1} {:ast-> tt1} {:t? Identifier} Vararg)
                                                      (if pm1? false
                                                        (match-case p2
-                                                                   (PARAMETER {t? PARAM_MODIFIER ast/?-> pm2} {ast-> tt2} {t? Identifier} Vararg)
+                                                                   (PARAMETER {:t? PARAM_MODIFIER :ast/?-> pm2} {:ast-> tt2} {:t? Identifier} Vararg)
                                                                    (if pm2? false
                                                                      (=t= tt1 tt2)) 
                                                                    false))
-                                                     (PARAMETER {t? PARAM_MODIFIER ast/?-> pm1} {ast-> tt1})
-                                                     (match-case p2 (PARAMETER {t? PARAM_MODIFIER ast/?-> pm2} {ast-> tt2})
+                                                     (PARAMETER {:t? PARAM_MODIFIER :ast/?-> pm1} {:ast-> tt1})
+                                                     (match-case p2 (PARAMETER {:t? PARAM_MODIFIER :ast/?-> pm2} {:ast-> tt2})
                                                                  (cond (not (= (set (children pm1)) (set (children pm2)))) false
                                                                        true (=t= tt1 tt2)))))
                                          (map list (children ps1) (children ps2)))
       (all? (fn [[tt1,tt2]] (=t= tt1 tt2)) (map list (children t1) (children t2)))
       (= (.getType t1) (.getType t2) (tok TYPE_MOD))
       ; todo: make sure a specific order is imposed on type modifiers
-      (match-case t1 (TYPE_MOD {ast-> tt1} {t-> m1})
-                  (match-case t2 (TYPE_MOD {ast-> tt2} {t-> m2})
+      (match-case t1 (TYPE_MOD {:ast-> tt1} {:t-> m1})
+                  (match-case t2 (TYPE_MOD {:ast-> tt2} {:t-> m2})
                               (if (= m1 m2) (recur tt1 tt2)
                                 false)))
       (= (.getType t1) (.getType t2) (tok BASIC_TYPE))
-      ;todo :symbol lookup!
       (match-case t1 (BASIC_TYPE ID_LIST)
+                  ;todo :symbol lookup!
                   false
-                  (BASIC_TYPE {t-> bt1})
-                  (match-case t2 (BASIC_TYPE ID_LIST)
-                              false
-                              (BASIC_TYPE {t-> bt2})
-                              (= bt1 bt2)))
+                  (= (.getType (getch t1)) (.getType (getch t2))))
       (or (matches? t1 (BASIC_TYPE ID_LIST))
           (matches? t2 (BASIC_TYPE ID_LIST)))
       false
 
 (defn elt-t [ast]
   (assert (attr ast 't-ok))
-  (match-case ast (DARRAY_DECL {ast-> t}) t
-              (POINTER {ast-> t}) t
-              (SARRAY_DECL {ast-> t}) t
+  (match-case ast (DARRAY_DECL {:ast-> t}) t
+              (POINTER {:ast-> t}) t
+              (SARRAY_DECL {:ast-> t}) t
               ; todo!
               (BASIC_TYPE ID_LIST) (assert false)
               (assert false)))
 
 (defn key-t [ast]
   (assert (attr? ast 't-ok))
-  (match-case ast (AARRAY_DECL {} {ast-> t}) t
+  (match-case ast (AARRAY_DECL {} {:ast-> t}) t
               ; todo!
               (BASIC_TYPE ID_LIST) (assert false)
               (assert false)))
 
 (defn val-t [ast]
   (assert (attr? ast 't-ok))
-  (match-case ast (AARRAY_DECL {ast-> t} {}) t
+  (match-case ast (AARRAY_DECL {:ast-> t} {}) t
               ; todo!
               (BASIC_TYPE ID_LIST) (assert false)
               (assert false)))
   ([tipe] (sizeof tipe nil nil))
   ([tipe ast state] 
    (match-case tipe
-               (SARRAY_DECL {ast-> child}) 
+               (SARRAY_DECL {:ast-> child}) 
                (if (attr? tipe val)
                  (let [x (sizeof child ast state)] 
                    (if (nil? x) nil (* (attr tipe val) x)))
 
 (defn type-mod-unraw [ast]
   (match-case ast
-              ({t TYPE_MOD_RAW nch 1} {ast-> mod}) 
-              (let [t (make-ast! (TYPE_MOD {ast mod}))]
+              ({:t TYPE_MOD_RAW :nch 1} {:ast-> mod}) 
+              (let [t (make-ast! (TYPE_MOD {:ast mod}))]
                 t)))
 
 (declare type-seq) ; I hate you clojure
 
 (defn basic-bop [basic state]
   (match-case basic
-              (BASIC_TYPE {t TYPE_MOD_RAW ast-> mod} 
-                          {t TYPE ast-> tipo})
+              (BASIC_TYPE {:t TYPE_MOD_RAW :ast-> mod} 
+                          {:t TYPE :ast-> tipo})
               (let [[xsb newbasic] (type-seq tipo state)
                     xs (cons (type-mod-unraw mod) xsb)]
                 (list xs newbasic))
 (defn decl-seq [ast]
   (loop [decl ast stack '()]
     (match-case decl
-                (DECLARATOR {t? BASIC_TYPE2 ast/?-> b1} {t Identifier ast-> id} 
-                            {t? BASIC_TYPE2 ast/?-> b2} {t? PARAM_SPEC ast/?-> par})
+                (DECLARATOR {:t? BASIC_TYPE2 :ast/?-> b1} {:t Identifier :ast-> id} 
+                            {:t? BASIC_TYPE2 :ast/?-> b2} {:t? PARAM_SPEC :ast/?-> par})
                 (let [new_stack1 (if b1? (basic2-bop b1 stack 'l) stack)
                       new_stack2 (if par? (basic2-bop par new_stack1 'r) new_stack1)
                       new_stack3 (if b2? (basic2-bop b2 new_stack2 'r) new_stack2)]
                   (list new_stack3 id))
-                (DECLARATOR {t? BASIC_TYPE2 ast/?-> b1} {t DECLARATOR ast-> subdecl} 
-                            {t? BASIC_TYPE2 ast/?-> b2} {t? PARAM_SPEC ast/?-> par})
+                (DECLARATOR {:t? BASIC_TYPE2 :ast/?-> b1} {:t DECLARATOR :ast-> subdecl} 
+                            {:t? BASIC_TYPE2 :ast/?-> b2} {:t? PARAM_SPEC :ast/?-> par})
                 (do
                   (let [new_stack1 (if b1? (basic2-bop b1 stack 'l) stack)
                         new_stack2 (if par? (basic2-bop par new_stack1 'r) new_stack1)
 (defn decl2-seq [ast]
   (loop [decl ast stack '()]
     (match-case decl
-                (DECLARATOR2 {t? BASIC_TYPE2 ast/?-> b1} {t DECLARATOR2 ast-> subdecl} 
-                             {t? BASIC_TYPE2 ast/?-> b2} {t? PARAM_SPEC ast/?-> par})
+                (DECLARATOR2 {:t? BASIC_TYPE2 :ast/?-> b1} {:t DECLARATOR2 :ast-> subdecl} 
+                             {:t? BASIC_TYPE2 :ast/?-> b2} {:t? PARAM_SPEC :ast/?-> par})
                 (let [new_stack1 (if b1? (basic2-bop b1 stack 'l) stack)
                       new_stack2 (if par? (basic2-bop par new_stack1 'r) new_stack1)
                       new_stack3 (if b2? (basic2-bop b2 new_stack2 'r) new_stack2)]
                   (recur subdecl new_stack3))
-                (DECLARATOR2 {t? BASIC_TYPE2 ast/?-> b1})
+                (DECLARATOR2 {:t? BASIC_TYPE2 :ast/?-> b1})
                 (let [new_stack1 (if b1? (basic2-bop b1 stack 'l) stack)]
                   new_stack1))))
 
   and bt is the base type "
   [ast state]
   (match-case ast
-              (TYPE {t BASIC_TYPE ast-> basic} 
-                    {t? DECLARATOR2 ast/?-> decl})
+              (TYPE {:t BASIC_TYPE :ast-> basic} 
+                    {:t? DECLARATOR2 :ast/?-> decl})
               (let [[xsb newbasic] (basic-bop basic state)
                     xsd (if decl? (decl2-seq decl) nil)
                     xs (concat xsd xsb) ]
                 (list xs newbasic))
-              (TYPE_I {t BASIC_TYPE ast-> basic} 
-                      {t DECLARATOR ast-> decl})
+              (TYPE_I {:t BASIC_TYPE :ast-> basic} 
+                      {:t DECLARATOR :ast-> decl})
               (let [[xsb newbasic] (basic-bop basic state)
                     [xsd i] (decl-seq decl)
                     xs (concat xsd xsb)]
                 (let [[xsd i] (decl-seq ast) ]
                   ;cheap spoof
                   (list xsd (make-ast! (BASIC_TYPE 
-                                         (ID_LIST {t Identifier 
-                                                   s "__auto"}))) i))) 
-              (BASIC_TYPE) (basic-bop ast state)))
+                                         (ID_LIST {:t Identifier 
+                                                   :s "__auto"}))) i))) 
+              (BASIC_TYPE) (basic-bop ast state)
+              (do
+                (dump-ast ast)
+                (assert false))))
 
 (defn normalize! 
   "a rewriter.
         exp (parse-exp ast) ]
     (letfn [(put-i! [tipi]
                     (let [ret 
-                          (if (empty? il) (make-ast! ({ast tipi sib null}))
+                          (if (empty? il) (make-ast! ({:ast tipi :sib null}))
                             (let [[i] il]
-                              (make-ast! (null {ast tipi sib null} 
-                                               {ast i sib null ch null}))))]
+                              (make-ast! (null {:ast tipi :sib null} 
+                                               {:ast i :sib null :ch null}))))]
                       (when exp (attr! ret 'type2exp exp))
                       ret))]
       (if (empty? bt2) (put-i! bt)
                 (matches? b (POINTER)) 
                 (match-case 
                   (first lst)
-                  (PARAM_SPEC {t? TEMPLATE_PARAMETERS ast?-> tpl?} 
-                              {t PARAMETERS ast-> p} 
-                              {t? POSTFIX ast/?-> post})
+                  (PARAM_SPEC {:t? TEMPLATE_PARAMETERS :ast?-> tpl?} 
+                              {:t PARAMETERS :ast-> p} 
+                              {:t? POSTFIX :ast/?-> post})
                   (if tpl?
                     (let [s (getch b)]
                       (error! b  "Template parameter does not belong here")
                       (setsib! (first lst) s)
                       (recur (first lst) (rest lst) b ret))
                     (let [f (do (setsib! (if post? post p) nil)
-                              (make-ast! (FUNCTION {ast p})))
+                              (make-ast! (FUNCTION {:ast p})))
                           s (getsib b)]
                       (if (nil? par) (recur f (rest lst) par f)
                         (do (assert (= (getch par) b))
          (let [a (parse2 "int i[];" type_i)
                b (normalize! a nil)]
            (is (matches? b (DARRAY_DECL (BASIC_TYPE Int))))
-           (is (matches? (getsib b) ({t Identifier s "i"}))))
+           (is (matches? (getsib b) ({:t Identifier :s "i"}))))
          (let [a (parse2 "int (*i)(char) pure;" type_i)
                b (normalize! a nil)]
            (is (matches? b (FUNCTION (BASIC_TYPE Int) PARAMETERS POSTFIX)))
-           (is (matches? (getsib b) ({t Identifier s "i"}))))
+           (is (matches? (getsib b) ({:t Identifier :s "i"}))))
          (let [a (parse2 "int* function(char) pure i;" type_i)
                b (normalize! a nil)]
            (is (matches? b (FUNCTION (POINTER (BASIC_TYPE Int)) 
                                        (SARRAY_DECL 
                                          (SARRAY_DECL 
                                            (BASIC_TYPE Int) 
-                                           {t IntegerLiteral s "1"}) 
-                                         {t IntegerLiteral s "2"}) 
-                                       {t IntegerLiteral s "8"}) 
-                                     {t IntegerLiteral s "7"}) 
-                                   {t IntegerLiteral s "3"}) 
-                                 {t IntegerLiteral s "4"}) 
-                               {t IntegerLiteral s "6"}) 
-                             {t IntegerLiteral s "5"}))))
+                                           {:t IntegerLiteral :s "1"}) 
+                                         {:t IntegerLiteral :s "2"}) 
+                                       {:t IntegerLiteral :s "8"}) 
+                                     {:t IntegerLiteral :s "7"}) 
+                                   {:t IntegerLiteral :s "3"}) 
+                                 {:t IntegerLiteral :s "4"}) 
+                               {:t IntegerLiteral :s "6"}) 
+                             {:t IntegerLiteral :s "5"}))))
          (let [a (parse2 "const(int)[1] i;" type_i)
-               b (normalize! (copy a) nil)]
+               b (normalize! (copy a) (struct State))]
            (is (matches? b (TYPE_MOD 
                              (SARRAY_DECL (BASIC_TYPE Int) 
-                                          {t IntegerLiteral s "1"}) 
+                                          {:t IntegerLiteral :s "1"}) 
                              Const))))
-         (let [a (parse2 "auto x(int i){ return 1;}" declDef)
+         ; todo: put this in semantic
+         #_(let [a (parse2 "auto x(int i){ return 1;}" declDef)
                b (normalize! (copy a) nil)]
            (is (matches? b (AUTO_DECL ATTRIBUTES 
                                       (PARAM_SPEC 
                                         (BASIC_TYPE 
                                           (ID_LIST 
-                                            {t Identifier 
-                                             s "__auto" 
-                                             sib? false})) 
+                                            {:t Identifier 
+                                             :s "__auto" 
+                                             :sib? false})) 
                                         PARAMETERS) 
                                       Identifier
                                       FUNCTION_BODY)))
   "basically get elt type of T1 ~ T2"
   [t1 t2]
   (cond (and (or (darray? t1) (sarray? t1))
-             (or (darray? t2) (sarray? t2))
-             (=t= (elt-t t1) (elt-t t2)))
+             (or (darray? t2) (sarray? t2)))
         (cond (=t= (elt-t t1) (elt-t t2)) (elt-t t1)
               (=t= (elt-t t1) t2) t2
               (=t= t1 (elt-t t2)) t1
+              (=t= (elt-t t1) EMPTY_ELT) (elt-t t2) 
+              (=t= (elt-t t2) EMPTY_ELT) (elt-t t1) 
               true nil)
         (and (or (darray? t1) (sarray? t1))
-             (=t= (elt-t t1) t2))
+             (or (=t= (elt-t t1) t2)
+                 (=t= (elt-t t1) EMPTY_ELT)))
         t2
         (and (or (darray? t2) (sarray? t2))
-             (=t= t1 (elt-t t2)))
+             (or (=t= t1 (elt-t t2))
+                 (=t= (elt-t t2) EMPTY_ELT)))
         t1
         true nil))
 
          (let [t1 INT
                t2 (make-darray-t INT)
                t3 (make-darray-t t2)]
+           (is (nil? (elt-t-of-2 t1 t1)))
            (is (=t= (elt-t-of-2 t1 t2) INT))
            (is (=t= (elt-t-of-2 t2 t1) INT))
            (is (=t= (elt-t-of-2 t2 t2) INT))
            (is (=t= (elt-t-of-2 t2 t3) t2))
            (is (=t= (elt-t-of-2 t3 t2) t2))
            (is (=t= (elt-t-of-2 t3 t3) t2))
+           (is (=t= (elt-t-of-2 EMPTY_ARR EMPTY_ARR) EMPTY_ELT))
+           (is (=t= (elt-t-of-2 EMPTY_ARR t1) INT))
+           (is (=t= (elt-t-of-2 EMPTY_ARR t2) INT))
+           (is (=t= (elt-t-of-2 EMPTY_ARR t3) t2))
            )
 )
 

File src/org/d/compiler/misc.clj

   (:use (clojure test))
   (:use (clojure.contrib macro-utils ))
   (:use 
-    (org.d.compiler d-type utils ast-utils visitor type-deduce)))
+    (org.d.compiler d-type utils ast-utils visitor)))
 
 (defn rewrite-templated-decl! 
   "
   (assert (matches-any? ast (Class) (Interface) (Union) (Struct))) 
   (match-case ast
               ({} 
-               {t Identifier ast-> i} 
-               {t TEMPLATE_PARAMETERS ast-> tpl} 
-               {t? CONSTRAINT ast/?-> constr}) 
+               {:t Identifier :ast-> i} 
+               {:t TEMPLATE_PARAMETERS :ast-> tpl} 
+               {:t? CONSTRAINT :ast/?-> constr}) 
               (let [isibl (getsib (if constr? constr tpl))
-                    tbody (make-ast! (TEMPLATE_BODY ({ast ast sib null ch null} 
-                                                     {ast i sib null} 
-                                                     {ast isibl})))
+                    tbody (make-ast! (TEMPLATE_BODY ({:ast ast :sib null :ch null} 
+                                                     {:ast i :sib null} 
+                                                     {:ast isibl})))
                     tnext (if (not constr?) tbody 
-                            (make-ast! (null {ast constr sib null} 
-                                             {ast tbody})))
+                            (make-ast! (null {:ast constr :sib null} 
+                                             {:ast tbody})))
                     ]
                 (make-ast! (Template 
-                             {t Identifier s (.getText i)}
-                             {ast tpl sib null}
-                             {ast tnext})))))
+                             {:t Identifier :s (.getText i)}
+                             {:ast tpl :sib null}
+                             {:ast tnext})))))
 
 (deftest test-rewrite-templated-decl
          (let [ 
               rewriting function's type" false)))
   (match-case ast 
               (DECLARATION 
-                ({t PARAM_SPEC ast-> pt} 
-                 {ast-> subtype}
-                 {t TEMPLATE_PARAMETERS ast-> tpl} 
-                 {t PARAMETERS ast-> p}
-                 {t? POSTFIX ast/?-> post}
-                 {t? CONSTRAINT ast/?-> constr}) 
-                {t Identifier ast-> i} FUNCTION_BODY)
+                ({:t PARAM_SPEC :ast-> pt} 
+                 {:ast-> subtype}
+                 {:t TEMPLATE_PARAMETERS :ast-> tpl} 
+                 {:t PARAMETERS :ast-> p}
+                 {:t? POSTFIX :ast/?-> post}
+                 {:t? CONSTRAINT :ast/?-> constr}) 
+                {:t Identifier :ast-> i} FUNCTION_BODY)
               (do
                 (when constr?  (setsib! (if post? post p) nil)
                   (setsib! constr nil))
                 (setsib! tpl (if constr? constr nil))
                 (setsib! subtype p)
                 (make-ast! (Template 
-                             {t Identifier s (.getText i)} 
-                             {ast tpl} 
-                             (TEMPLATE_BODY {ast ast sib null}))))))
+                             {:t Identifier :s (.getText i)} 
+                             {:ast tpl} 
+                             (TEMPLATE_BODY {:ast ast :sib null}))))))
 
 #_(deftest test-rewrite-templated-fn
          (let [a (parse2 "int i(I)(char c){}" declDefs)
                b (do (normalize-all! a) (rewrite-templated-fn! a nil)) ]
            (is (matches? b (Template Identifier 
-                                     ({t TEMPLATE_PARAMETERS nch 1} 
+                                     ({:t TEMPLATE_PARAMETERS :nch 1} 
                                       (TEMPLATE_TYPE_PARAMETER Identifier)) 
-                                     ({t TEMPLATE_BODY nch 1}
-                                      ({t DECLARATION nch 3} 
-                                       ({t PARAM_SPEC nch 2} 
+                                     ({:t TEMPLATE_BODY :nch 1}
+                                      ({:t DECLARATION :nch 3} 
+                                       ({:t PARAM_SPEC :nch 2} 
                                         (BASIC_TYPE Int)
                                         PARAMETERS) 
-                                       Identifier {t FUNCTION_BODY nsib 0}))))))
+                                       Identifier {:t FUNCTION_BODY :nsib 0}))))))
          (let [a (parse2 "int i(I)(char c) pure{}" declDefs)
                b (do (normalize-all! a) (rewrite-templated-fn! a nil)) ]
            (is (matches? b (Template Identifier 
-                                     ({t TEMPLATE_PARAMETERS nch 1} 
+                                     ({:t TEMPLATE_PARAMETERS :nch 1} 
                                       (TEMPLATE_TYPE_PARAMETER Identifier)) 
                                      ({t TEMPLATE_BODY nch 1}
                                       ({t DECLARATION nch 3} 
   "rewrites ++a to a+=1 and --a to a-=1"
   [ast state]
   (match-case ast
-              ({t PLUSPLUSPRE nch 1} {ast-> e}) 
-              (make-ast! (Add_assign {ast e} {t IntegerLiteral s "1"}))
-              ({t MINUSMINUSPRE nch 1} {ast-> e}) 
-              (make-ast! (Minus_assign {ast e} {t IntegerLiteral s "1"}))))
+              ({:t PLUSPLUSPRE :nch 1} {:ast-> e}) 
+              (make-ast! (Add_assign {:ast e} {:t IntegerLiteral :s "1"}))
+              ({:t MINUSMINUSPRE :nch 1} {:ast-> e}) 
+              (make-ast! (Minus_assign {:ast e} {:t IntegerLiteral :s "1"}))))
 
 (defn decl-split? [ast]
   (matches-any? 
     ast
-    (DECLARATION {} Identifier {t? INITIALIZER} DECL_EXTRAS)
+    (DECLARATION {} Identifier {:t? INITIALIZER} DECL_EXTRAS)
     (AUTO_DECL ATTRIBUTES AUTO_ASSIGN AUTO_ASSIGN)
-    (Alias {t? ATTRIBUTES} {} Identifier ALIAS_LIST)
-    (Typedef {t? ATTRIBUTES} {} Identifier {t? INITIALIZER} DECL_EXTRAS)
+    (Alias {:t? ATTRIBUTES} {} Identifier ALIAS_LIST)
+    (Typedef {:t? ATTRIBUTES} {} Identifier {:t? INITIALIZER} DECL_EXTRAS)
     ))
 
 (defn decl-split-rewrite!
   [ast state]
   (match-case 
     ast 
-    (DECLARATION {ast-> t} {t Identifier ast-> i1} 
-                 {t? INITIALIZER ast/?-> ini} {t DECL_EXTRAS ast-> dx})
+    (DECLARATION {:ast-> t} {:t Identifier :ast-> i1} 
+                 {:t? INITIALIZER :ast/?-> ini} {:t DECL_EXTRAS :ast-> dx})
     (let [decls (map #(match-case 
                         % 
-                        (DECL_ASSIGN {t Identifier ast-> id} 
-                                     {t? INITIALIZER})
-                        (make-ast! (DECLARATION {ast (copy t)}
-                                                {ast id sib ap})))
+                        (DECL_ASSIGN {:t Identifier :ast-> id} 
+                                     {:t? INITIALIZER})
+                        (make-ast! (DECLARATION {:ast (copy t)}
+                                                {:ast id :sib ap})))
                      (children dx))]
       (setsib! (if ini? ini i1) nil)
       (last (map (fn [[a,b]] (setsib! a b)) (partition 2 1 (cons ast decls))))
       ast)
 
-    (AUTO_DECL {t ATTRIBUTES ast-> atrn} 
-               {t AUTO_ASSIGN ast-> a1} 
-               {t AUTO_ASSIGN ast-> a2})
-    (let [decls (map #(make-ast! (AUTO_DECL {ast (copy atrn)} 
-                                            {ast % sib null})) 
+    (AUTO_DECL {:t ATTRIBUTES :ast-> atrn} 
+               {:t AUTO_ASSIGN :ast-> a1} 
+               {:t AUTO_ASSIGN :ast-> a2})
+    (let [decls (map #(make-ast! (AUTO_DECL {:ast (copy atrn)} 
+                                            {:ast % :sib null})) 
                      (ast&siblings a2))]
       (setsib! a1 nil)
       (last (map (fn [[a,b]] (setsib! a b)) (partition 2 1 (cons ast decls))))
       ast)
 
-    (Alias {t? ATTRIBUTES ast/?-> atrn} {ast-> t} 
-           {t Identifier ast-> i} {t ALIAS_LIST ast-> al})
+    (Alias {:t? ATTRIBUTES :ast/?-> atrn} {:ast-> t} 
+           {:t Identifier :ast-> i} {:t ALIAS_LIST :ast-> al})
     (let [decls (map #(if atrn? 
-                        (make-ast! (Alias {ast (copy atrn)} 
-                                          {ast (copy t)} {ast % sib null}))
-                        (make-ast! (Alias {ast (copy t)} {ast % sib null})))
+                        (make-ast! (Alias {:ast (copy atrn)} 
+                                          {:ast (copy t)} {:ast % :sib null}))
+                        (make-ast! (Alias {:ast (copy t)} {:ast % :sib null})))
                      (children al))]
       (setsib! i nil)
       (last (map (fn [[a,b]] (setsib! a b)) (partition 2 1 (cons ast decls))))
       ast)
 
-    (Typedef {t? ATTRIBUTES ast/?-> atrn} {ast-> t} {t Identifier ast-> i} 
-             {t? INITIALIZER ast/?-> ini} {t DECL_EXTRAS ast-> dx})
+    (Typedef {:t? ATTRIBUTES :ast/?-> atrn} {:ast-> t} {:t Identifier :ast-> i} 
+             {:t? INITIALIZER :ast/?-> ini} {:t DECL_EXTRAS :ast-> dx})
     (let [decls (map #(match-case 
                         %
-                        (DECL_ASSIGN {t Identifier ast-> id} 
-                                     {t? INITIALIZER})
+                        (DECL_ASSIGN {:t Identifier :ast-> id} 
+                                     {:t? INITIALIZER})
                         (if atrn? 
-                          (make-ast! (Typedef {ast (copy atrn)}
-                                              {ast (copy t)} {ast id}))
-                          (make-ast! (Typedef {ast (copy t)} {ast id}))))
+                          (make-ast! (Typedef {:ast (copy atrn)}
+                                              {:ast (copy t)} {:ast id}))
+                          (make-ast! (Typedef {:ast (copy t)} {:ast id}))))
                      (children dx))]
       (setsib! (if ini? ini i) nil)
       (last (map (fn [[a,b]] (setsib! a b)) (partition 2 1 (cons ast decls))))
                              (matches? ast (DECLARATOR))
                              (matches? (first (:stack state)) (AUTO_DECL))))
                        (new-rewrite! ast state normalize!)
+                       (matches? ast ({:t Dot :nch 2}))   
+                       (match-case ast (Dot {} {:t Identifier :ast-> i})
+                                   (do (.unsetExp i)
+                                     state)
+                                   (Dot {:ast-> e} {:t NEW_EXPRESSION :ast-> n})
+                                   (new-rewrite! ast state (fn [t s]
+                                                             (let [x (getch n)]
+                                                               (make-ast! ({:ast n :ch null}
+                                                                           {:ast e :sib null}
+                                                                           {:ast x})))))
+                                   (Dot {:ast-> e} {:t NEW_CLASS_EXPRESSION :ast-> n})
+                                   (new-rewrite! ast state (fn [t s]
+                                                             (let [x (getch n)]
+                                                               (make-ast! ({:ast n :ch null}
+                                                                           {:ast e :sib null}
+                                                                           {:ast x}))))))
                        (matches-any? 
                          ast 
                          (Class Identifier TEMPLATE_PARAMETERS) 
                                        (PARAM_SPEC 
                                          {} 
                                          TEMPLATE_PARAMETERS PARAMETERS)))
-                       (new-rewrite! a state rewrite-templated-fn!)
-                       ; I'm too lazy to figure out how to rewrite the antlr grammar
-                       ; anyways, a.b.c => (Dot (Dot a b) c) in the parser,
-                       ; here (Dot (Dot a b) c) => (DOT a b c)
-                       ; technically, e could be an expression or a type. fyi.
-                       ; and i could be a newexp or a templateinstance.
-                       (matches? a ({t Dot nch 2} DOT))
-                       (match-case a ({t Dot nch 2} {t DOT ast-> d} {ast-> i})
-                                   (new-rewrite! a state (fn [ast state] 
-                                                             (setsib! d nil) 
-                                                             (setch! ast nil)
-                                                             (.addChild d i) d)))
-                       (matches? a ({t Dot exp? true nch 2}))
-                       (match-case a ({t Dot nch 2} {ast-> e} {ast-> i})
-                                   (new-rewrite! a state (fn [ast state] 
-                                                           (setch! a nil)
-                                                           (. i unsetExp)
-                                                           (when (matches? e (Identifier))
-                                                             (. e unsetExp))
-                                                           (let [d (make-ast! (DOT {ast e}))]
-                                                             (. d setExp) d))))
-                       )))]
+                       (new-rewrite! a state rewrite-templated-fn!))))]
     (:ast-root (v ast-root))))
 
 (defn expand-auto-decl? [ast]
   (match-case 
     ast
     (AUTO_DECL ATTRIBUTES  
-               ({t AUTO_ASSIGN sib? false} 
-                Identifier {t INITIALIZER ast-> ini}))
+               ({:t AUTO_ASSIGN :sib? false} 
+                Identifier {:t INITIALIZER :ast-> ini}))
     (attr? ini 'type)
     (AUTO_DECL ATTRIBUTES (PARAM_SPEC (BASIC_TYPE 
                                           (ID_LIST 
-                                            {t Identifier s "__auto"})) 
+                                            {:t Identifier :s "__auto"})) 
                                       PARAMETERS) 
-               Identifier {t FUNCTION_BODY ast-> f})
+               Identifier {:t FUNCTION_BODY :ast-> f})
     (attr? f 'type)
-    (IF_COND Auto Identifier {ast-> e})
+    (IF_COND Auto Identifier {:ast-> e})
     (attr? e 'type)
     false))
 
 (defn expand-auto-decl!  [ast state]
   (match-case 
     ast
-    (AUTO_DECL {t ATTRIBUTES ast-> attrs} 
-               ({t AUTO_ASSIGN ast-> asg sib? false} 
-                {t Identifier ast-> i} {t INITIALIZER ast-> ini}))
+    (AUTO_DECL {:t ATTRIBUTES :ast-> attrs} 
+               ({:t AUTO_ASSIGN :ast-> asg :sib? false} 
+                {:t Identifier :ast-> i} {:t INITIALIZER :ast-> ini}))
     (let [t (copy (attr ini 'type))]
-      (make-ast! (DECLARATION {ast t} {ast i})))
-    (AUTO_DECL {t ATTRIBUTES ast-> atrn}
-               ({t PARAM_SPEC ast-> ps} 
-                ({t BASIC_TYPE ast-> b} (ID_LIST {t Identifier s "__auto"})) 
+      (make-ast! (DECLARATION {:ast t} {:ast i})))
+    (AUTO_DECL {:t ATTRIBUTES :ast-> atrn}
+               ({:t PARAM_SPEC :ast-> ps} 
+                ({:t BASIC_TYPE :ast-> b} (ID_LIST {:t Identifier :s "__auto"})) 
                 PARAMETERS) 
                Identifier
-               {t FUNCTION_BODY ast-> f})
+               {:t FUNCTION_BODY :ast-> f})
     (let [t (copy (attr f 'type))
           a1 (filter #(not (matches? % (Auto))) (children atrn))
           _ (last (map #(setsib! % nil) (children atrn)))
-          decl (make-ast! (DECLARATION {ast ps}))]
+          decl (make-ast! (DECLARATION {:ast ps}))]
       (assert t)
       (setch! ps t)
       (setsib! t (getsib b))
       (if (empty? a1) decl
         (do
         (last (map (fn [[a,b]] (setsib! a b)) (partition 2 1 a1)))
-        (make-ast! (ATTR_DECLDEF ({ast atrn ch null sib null} {ast (first a1)})
-                                 (D_BLOCK {ast decl}))))))
-    (IF_COND {t Auto ast-> a} {t Identifier ast-> i} {ast-> e})
+        (make-ast! (ATTR_DECLDEF ({:ast atrn :ch null :sib null} {:ast (first a1)})
+                                 (D_BLOCK {:ast decl}))))))
+    (IF_COND {:t Auto :ast-> a} {:t Identifier :ast-> i} {:ast-> e})
     (let [t (copy (attr e 'type))]
       (assert t)
       (setch! ast t)
 (defn expand-typeof? [ast]
   (match-case 
     ast
-    (BASIC_TYPE ({t Typeof sib? false} {type/?-> t })) t?
+    (BASIC_TYPE ({:t Typeof :sib? false} {:type/?-> t })) t?
     ;(TMIXIN_ID1 (Typeof {ast-> e})) e
-    ({t Dot exp? true} (Typeof {type/?-> t} Identifier)) t?
+    ({:t Dot :exp? true} (Typeof {:type/?-> t} Identifier)) t?
     false))
 
 (defn expand-typeof-rewrite! [ast state]
   (match-case 
     ast
-    (BASIC_TYPE (Typeof {ast-> e})) 
+    (BASIC_TYPE (Typeof {:ast-> e})) 
     (copy (attr e 'type))
-    ({t Dot exp? true} 
-     ({t Typeof exp? true ast-> ty} {ast-> e})
-     {t Identifier ast-> i}) 
+    ({:t Dot :exp? true} 
+     ({:t Typeof :exp? true :ast-> ty} {:ast-> e})
+     {:t Identifier :ast-> i}) 
     (let [t (copy (attr e 'type))]
       (setch! ast t)
       (setsib! t i)
       (setsib! ty nil)
       ast)))
 
-#_(defn testa []
-  (let [a (parse2 "immutable x(int i){ return 1;}" declDef)
-        b (rewrites-1! a) 
-        c (testi a)]
-    (match-case 
-      b
-      (AUTO_DECL ATTRIBUTES {} Identifier {t FUNCTION_BODY ast-> f})
-      (do
-        (attr! f 'type INT)
-        (let [x (rewrites-2! b)]
-          (dump-ast x))))))
-
 (defn str-mixin? [ast]
     (match-case 
       ast
-      ({} {exp? true ast-> e})
+      ({} {:exp? true :ast-> e})
       (and 
         (matches-any? ast (MIXIN_EXPRESSION) (MIXIN_DECLDEF) (MIXIN_STATEMENT))
         (attr? e 'type) (attr? e 'value))
     [ast state]
     (match-case 
     ast
-    ({} {exp? true ast-> e})
+    ({} {:exp? true :ast-> e})
     (let [t (attr e 'type)
           v (attr e 'value)]
       (letfn [(bazooka! [parser mxnstr mxnstrt]

File src/org/d/compiler/semantic.clj

               (println "semantic [2]:")
               (dump-ast d))]
     c))
+(defn test2 [strxp]
+  (let [a (parse2 strxp exp)
+        *1* (when pxx 
+              (println "(raw):")
+              (dump-ast a))
+        b (rewrites-1! a)
+        *2* (when pxx 
+              (println "(rewrites-1):")
+              (dump-ast b))
+        c (semantic-blast b)
+        *3* (when pxx
+              (println "(semantic [1]):")
+              (dump-ast c))
+        d (semantic-blast c)
+        *4* (when pxx 
+              (println "semantic [2]:")
+              (dump-ast d))]
+    c))
 
 #_(deftest test-populate 
          (let [a (parse2 "static{ shared int i;}" declDefs)

File src/org/d/compiler/symbol.clj

   'pragma: [AST]
   "
   (:import (java.util HashMap HashSet))
-  (:use (org.d.compiler ast-utils misc utils visitor)
+  (:use (org.d.compiler ast-utils utils visitor)
         (clojure test))
   )
 
   (matches-any? 
     ast
     (MODULE) 
-    ({t Enum ch? true}) 
+    ({:t Enum :ch? true}) 
     (CLASS_BODY) 
     (INTERFACE_BODY) 
     (STRUCT_BODY) 
 (defn attrble? [ast]
   (matches-any?
     ast
-    ({t Enum ch? true})
-    ({t Class ch? true})
-    ({t Interface ch? true})
-    ({t Struct ch? true})
-    ({t Union ch? true})
+    ({:t Enum :ch? true})
+    ({:t Class :ch? true})
+    ({:t Interface :ch? true})
+    ({:t Struct :ch? true})
+    ({:t Union :ch? true})
     (Template)
-    ({t Typedef ch? true})
+    ({:t Typedef :ch? true})
     (Alias)
     (DECLARATION)
     (CTOR)
             (attrble? (first stack))) [prot,stor,algn,pragmas]
       (match-case 
         (first stack)
-        (PRAGMA_DECL {t Pragma ast-> p})
+        (PRAGMA_DECL {:t Pragma :ast-> p})
         (recur (rest stack) prot stor algn (cons p pragmas))
-        (ALIGN_DECLDEF {t Align ast-> a})
+        (ALIGN_DECLDEF {:t Align :ast-> a})
         (recur (rest stack) prot stor (cons a algn) pragmas)
-        (PROT_DECLDEF (PROTECTION {ast-> p sib? false}))
+        (PROT_DECLDEF (PROTECTION {:ast-> p :sib? false}))
         (recur (rest stack) (cons p prot) stor algn pragmas)
-        (PRAGMA_STMT {t Pragma ast-> p})
+        (PRAGMA_STMT {:t Pragma :ast-> p})
         (recur (rest stack) prot stor algn (cons p pragmas))
-        (ATTR_DECLDEF {t ATTRIBUTES ast-> a})
+        (ATTR_DECLDEF {:t ATTRIBUTES :ast-> a})
         (recur (rest stack) prot (concat (children a) stor) algn pragmas)
         (recur (rest stack) prot stor algn pragmas)
         ))))
   [ast state]
   (match-case
     ast 
-    (Enum {t Identifier ast-> i}) [i]
-    (Class {t Identifier ast-> i}) [i]
-    (Interface {t Identifier ast-> i}) [i]
-    (Struct {t Identifier ast-> i}) [i]
-    (Union {t Identifier ast-> i}) [i]
-    (Template {t Identifier ast-> i}) [i]
-    (ENUM_MEMBER {ast?-> type?} {t Identifier ast-> i}) [i]
-    (Typedef {t? ATTRIBUTES} {} {t Identifier ast-> i} 
-             {t? INITIALIZER sib null}) [i]
-    (Alias {t Identifier ast-> i} This) [i]
-    (Alias {t? ATTRIBUTES} {} {t Identifier ast-> i sib null}) [i]
-    (DECLARATION {} {t Identifier ast-> i} {t? INITIALIZER sib null}) [i]
-    #_(AMBIG_DECLARATION {} {t Identifier ast-> i} 
-                       {t? INITIALIZER} {t? DECL_EXTRAS ast/?-> d})
+    (Enum {:t Identifier :ast-> i}) [i]
+    (Class {:t Identifier :ast-> i}) [i]
+    (Interface {:t Identifier :ast-> i}) [i]
+    (Struct {:t Identifier :ast-> i}) [i]
+    (Union {:t Identifier :ast-> i}) [i]
+    (Template {:t Identifier :ast-> i}) [i]
+    (ENUM_MEMBER {:ast?-> type?} {:t Identifier :ast-> i}) [i]
+    (Typedef {:t? ATTRIBUTES} {} {:t Identifier :ast-> i} 
+             {:t? INITIALIZER :sib? false}) [i]
+    (Alias {:t Identifier :ast-> i} This) [i]
+    (Alias {:t? ATTRIBUTES} {} {:t Identifier :ast-> i :sib? false}) [i]
+    (DECLARATION {} {:t Identifier :ast-> i} {:t? INITIALIZER :sib? false}) [i]
+    #_(AMBIG_DECLARATION {} {:t Identifier :ast-> i} 
+                       {:t? INITIALIZER} {:t? DECL_EXTRAS :ast/?-> d})
     ;(cons i (map getch (if d? (children d) ())))
 
-    ;(AUTO_DECL ATTRIBUTES {} {t Identifier ast-> i})
+    ;(AUTO_DECL ATTRIBUTES {} {:t Identifier :ast-> i})
     ;[i]
-    ;(AUTO_DECL ATTRIBUTES {ast-> a})
-    #_(map #(match-case % (AUTO_ASSIGN {t Identifier ast-> i}) i) 
+    ;(AUTO_DECL ATTRIBUTES {:ast-> a})
+    #_(map #(match-case % (AUTO_ASSIGN {:t Identifier :ast-> i}) i) 
          (ast&siblings a))
     ; not quite correct, but good enough (only D1 has inout)
-    (FOREACH_TYPE {t? Ref} {t? Inout} {} {t Identifier ast-> i}) [i]
-    ;(FOREACH_TYPE {t? Ref} {t? Inout} {t Identifier ast-> i}) [i]
+    (FOREACH_TYPE {:t? Ref} {:t? Inout} {} {:t Identifier :ast-> i}) [i]
+    ;(FOREACH_TYPE {:t? Ref} {:t? Inout} {:t Identifier :ast-> i}) [i]
     #_(Mixin) 
     #_(let [i (last (children ast))]
       (cond (nil? i) []
                     ; functions are overloadable
                     (and (matches-any? ast 
                                        (DECLARATOR PARAM_SPEC) 
-                                       (AUTO_DECL {t? ATTRIBUTES} PARAM_SPEC))
+                                       (AUTO_DECL {:t? ATTRIBUTES} PARAM_SPEC))
                          (matches-any? old 
                                        (DECLARATOR PARAM_SPEC) 
-                                       (AUTO_DECL {t? ATTRIBUTES} PARAM_SPEC)))
+                                       (AUTO_DECL {:t? ATTRIBUTES} PARAM_SPEC)))
                     (do
                       (.add (get sc i) ast)
                       (recur (rest ids) err))
   (loop [chm (children mn) sct decl]
     (match-case 
       (first chm) 
-      ({t Identifier s-> mi}) 
+      ({:t Identifier :s-> mi}) 
       (cond 
         ; let's allow crap like `import a.b; import a;`
         (and (empty? (rest chm))
   [ast state]
   (match-case 
     ast 
-    (IMPORT {t? Static ast?-> static?} 
-            {t IMPORT_SEGMENT ast-> fseg})
+    (IMPORT {:t? Static :ast?-> static?} 
+            {:t IMPORT_SEGMENT :ast-> fseg})
     (let [isegs (filter #(matches? % (IMPORT_SEGMENT)) 
                         (ast&siblings fseg))
           ibinding (apply #(when (matches? % (IMPORT_ONLY)) %) 
         (loop [sels (children ibinding)]
           (if (empty? sels) true
             (match-case (first sels)
-                        (IMPORT_BINDING {t Identifier s-> i})
+                        (IMPORT_BINDING {:t Identifier :s-> i})
                         (if (apply #(or 
                                       (not %) 
                                       (matches-any? 
                                         (first %)
                                         (Template)
                                         (DECLARATOR PARAM_SPEC) 
-                                        (AUTO_DECL {t? ATTRIBUTES} PARAM_SPEC)))
+                                        (AUTO_DECL {:t? ATTRIBUTES} PARAM_SPEC)))
                                    (list (get (attr decl 'scope) i)))
                           (put-sym! (attr decl 'scope) i ast)
                           (error! ast (str i " already defined"))))))
             (if (empty? segs) true
               (match-case 
                 (first segs)
-                (IMPORT_SEGMENT {t Identifier s-> i} MODULE_NAME)
+                (IMPORT_SEGMENT {:t Identifier :s-> i} MODULE_NAME)
                 (if (get (attr decl 'scope) i)
                   (error! ast (str i " is already defined"))
                   (do
                     (put-sym! (attr decl 'scope) i ast)
                     (recur (rest segs))))
-                (IMPORT_SEGMENT {t MODULE_NAME ast-> m})
+                (IMPORT_SEGMENT {:t MODULE_NAME :ast-> m})
                 (let [flag (push-module! ast m decl)]
                   (when (not (or static? ibinding))
                     (.add (attr decl 'imports) m))
 (defn push-label! [ast state]
   (let [body (first (filter body-scoped? (:stack state)))]
     (match-case ast
-                (LABEL {t Identifier s-> i})
+                (LABEL {:t Identifier :s-> i})
                 (if (get (attr body 'labels) i)
                   (error! ast (str "label " i " already declared"))
                   (do
 
 (defn rm_attrs [ast state]
   (let [block (match-case ast
-                          (ATTR_DECLDEF ATTRIBUTES {ast-> d}) d
-                          (PROT_DECLDEF PROTECTION {ast-> d}) d
-                          (ALIGN_DECLDEF Align {ast-> d}) d
+                          (ATTR_DECLDEF ATTRIBUTES {:ast-> d}) d
+                          (PROT_DECLDEF PROTECTION {:ast-> d}) d
+                          (ALIGN_DECLDEF Align {:ast-> d}) d
                           )
         dx (match-case block
-                       (D_BLOCK {ast/?-> d}) d
-                       (D_S_BLOCK {ast/?-> d}) d
-                       (D_C_BLOCK {ast/?-> d}) d
+                       (D_BLOCK {:ast/?-> d}) d
+                       (D_S_BLOCK {:ast/?-> d}) d
+                       (D_C_BLOCK {:ast/?-> d}) d
                        ({}) block)]
     dx))
 
               (Alias) ['alias,false]
               (Typedef) ['typedef,false]
               (PACKAGE) ['package,false]
-              (DECLARATION ({t PARAM_SPEC ast-> p}) )
+              (DECLARATION ({:t PARAM_SPEC :ast-> p}) )
               ['function,(attr? p 't-ok)]
-              (DECLARATION {ast-> t} Identifier {t? INITIALIZER} {t? DECL_EXTRAS ast/?-> dx}) 
+              (DECLARATION {:ast-> t} Identifier {:t? INITIALIZER} {:t? DECL_EXTRAS :ast/?-> dx}) 
               ['val-decl, (and (attr? t 't-ok) (not dx?))]
               (ENUM_MEMBER) ['val-decl, false]
               (FOREACH_TYPE) ['val-decl, false]))
 
 (defn derv-type [ast]
   (match-case ast
-              (DECLARATION {ast-> t}) (do (assert (attr? t 't-ok)) t)
-              (FOREACH_TYPE {t? Inout} {t? Ref} {ast-> t} Identifier) 
+              (DECLARATION {:ast-> t}) (do (assert (attr? t 't-ok)) t)
+              (FOREACH_TYPE {:t? Inout} {:t? Ref} {:ast-> t} Identifier) 
               (do (assert (attr? t 't-ok)) t)))
 
 
   [sym state]
   (let [scopes (filter scoped? (:stack state))]
     (match-case sym
-                ({t Identifier s-> i})
+                ({:t Identifier :s-> i})
                 (let [r (filter #(contains? (attr % 'scope) i) scopes)]
                   (if (empty? r) ['not-found,false, nil]
                     (let [x (get (attr (first r) 'scope) i)]

File src/org/d/compiler/type_deduce.clj

 (defn cat-t [ast lhs rhs state]
   (let [lht (attr lhs 'type) rht (attr rhs 'type)
         elt (elt-t-of-2 lht rht) ]
-    (cond (nil? elt) (err2 "unknown operation")
+    (cond (nil? elt) (error! ast (err2 "unknown operation"))
       true (make-darray-t elt))))
 
 (defn reference-t [ast rhs state]
 
 (defn cast-t [ast rhs state]
   (let [rht (attr rhs 'type)]
-    (match-case ast (Cast {ast-> t} {})
+    (match-case ast (Cast {:ast-> t} {})
                 (cond (and (or (int-t? rht state) (char-t? rht) (=t= BOOL rht))
                            (or (int-t? t state) (char-t? t) (=t= BOOL t))) t
                       (and (int-t? t state) (float-t? rht)) t
   (let[; list of tuple types
        tuples (map #(attr % 'type) (children ast))
        ; list of [bogus] asts containing key types
-       key-ts (map #(wrap-type (match-case % (TUPLE {ast-> t}) t)) tuples)
+       key-ts (map #(wrap-type (match-case % (TUPLE {:ast-> t}) t)) tuples)
        ; list of [bogus] asts containing value types
-       val-ts (map #(wrap-type (match-case % (TUPLE {} {ast-> t}) t)) tuples)
+       val-ts (map #(wrap-type (match-case % (TUPLE {} {:ast-> t}) t)) tuples)