|
1593 | 1593 | (get-in env [:locals sym])) |
1594 | 1594 | [sym tag]))))))) |
1595 | 1595 |
|
1596 | | -(defn- add-predicate-induced-tags |
1597 | | - "Looks at the test and adds any tags which are induced by virtue |
1598 | | - of the predicate being satisfied. For example in (if (string? x) x :bar) |
| 1596 | +(defn- truth-induced-tag |
| 1597 | + "Refine a tag to exclude clj-nil if the test is a simple symbol." |
| 1598 | + [env test] |
| 1599 | + (when (and (symbol? test) |
| 1600 | + (nil? (namespace test))) |
| 1601 | + (let [analyzed-symbol (no-warn (analyze (assoc env :context :expr) test))] |
| 1602 | + (when-let [tag (:tag analyzed-symbol)] |
| 1603 | + (when (and (set? tag) |
| 1604 | + (contains? tag 'clj-nil)) |
| 1605 | + [test (canonicalize-type (disj tag 'clj-nil))]))))) |
| 1606 | + |
| 1607 | +(defn- set-test-induced-tags |
| 1608 | + "Looks at the test and sets any tags which are induced by virtue |
| 1609 | + of the test being truthy. For example in (if (string? x) x :bar) |
1599 | 1610 | the local x in the then branch must be of string type." |
1600 | 1611 | [env test] |
1601 | 1612 | (let [[local tag] (or (simple-predicate-induced-tag env test) |
1602 | | - (type-check-induced-tag env test))] |
| 1613 | + (type-check-induced-tag env test) |
| 1614 | + (truth-induced-tag env test))] |
1603 | 1615 | (cond-> env |
1604 | | - local (update-in [:locals local :tag] (fn [prev-tag] |
1605 | | - (if (or (nil? prev-tag) |
1606 | | - (= 'any prev-tag)) |
1607 | | - tag |
1608 | | - prev-tag)))))) |
| 1616 | + local (assoc-in [:locals local :tag] tag)))) |
1609 | 1617 |
|
1610 | 1618 | (defmethod parse 'if |
1611 | 1619 | [op env [_ test then else :as form] name _] |
|
1614 | 1622 | (when (> (count form) 4) |
1615 | 1623 | (throw (compile-syntax-error env "Too many arguments to if" 'if))) |
1616 | 1624 | (let [test-expr (disallowing-recur (analyze (assoc env :context :expr) test)) |
1617 | | - then-expr (allowing-redef (analyze (add-predicate-induced-tags env test) then)) |
| 1625 | + then-expr (allowing-redef (analyze (set-test-induced-tags env test) then)) |
1618 | 1626 | else-expr (allowing-redef (analyze env else))] |
1619 | 1627 | {:env env :op :if :form form |
1620 | 1628 | :test test-expr :then then-expr :else else-expr |
|
0 commit comments