Permalink
Browse files

Add statistics interface functions.

  • Loading branch information...
1 parent efb9090 commit 99833fc1e79f6cffc3153024bf5c22c3c811180f @frenchy64 frenchy64 committed Sep 4, 2013
View
@@ -1,3 +1,7 @@
+0.2.3
+- Handle expected types for def forms
+- Add clojure.core.typed/statistics, clojure.core.typed/var-coverage
+
0.2.2
- Add AOT classes to jar
- decreases load time from 20s to 5s
View
@@ -1,4 +1,4 @@
-(defproject core.typed "0.1.27-SNAPSHOT"
+(defproject core.typed "0.2.3-SNAPSHOT"
:description "Gradual typing for Clojure"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
@@ -6,7 +6,7 @@ for checking namespaces, cf for checking individual forms."}
(:require [clojure.pprint :as pprint]
[clojure.set :as set]
[clojure.string :as str]
- [clojure.core.typed.current-impl :as impl :refer [v]]
+ [clojure.core.typed.current-impl :as impl]
[clojure.core.typed.profiling :as p]
[clojure.java.io :as io])
(:refer-clojure :exclude [type]))
@@ -74,9 +74,9 @@ for checking namespaces, cf for checking individual forms."}
Intended for use at the REPL."
[mname]
(load-if-needed)
- (let [type-reflect (v 'clojure.reflect/type-reflect)
- unparse-type (v 'clojure.core.typed.parse-unparse/unparse-type)
- Method->Type (v 'clojure.core.typed.check/Method->Type)
+ (let [type-reflect (impl/v 'clojure.reflect/type-reflect)
+ unparse-type (impl/v 'clojure.core.typed.parse-unparse/unparse-type)
+ Method->Type (impl/v 'clojure.core.typed.check/Method->Type)
ms (->> (type-reflect (Class/forName (namespace mname)))
:members
(filter #(and (instance? clojure.reflect.Method %)
@@ -1328,6 +1328,77 @@ for checking namespaces, cf for checking individual forms."}
(flush))
:ok))))))))
+; (ann all-defs-in-ns [Namespace -> (Set Symbol)])
+(defn ^:private ^:no-wiki
+ all-defs-in-ns
+ [ns]
+ {:pre [(instance? clojure.lang.Namespace ns)]}
+ (set
+ (map #(symbol (str (ns-name ns)) (str %))
+ (clojure.set/difference
+ (set (keys (ns-map ns)))
+ (set (keys (ns-refers ns)))
+ (set (keys (ns-imports ns)))))))
+
+;(ann statistics [(U Symbol (Coll Symbol)) -> (Map Symbol Stats)])
+(defn statistics
+ "Takes a collection of namespace symbols and returns a map mapping the namespace
+ symbols to a map of data"
+ [nsyms]
+ (assert (and (coll? nsyms) (every? symbol? nsyms))
+ "Must pass a collection of symbols to statistics")
+ (reduce (fn [stats nsym]
+ (let [_ (check-ns nsym :collect-only true)
+ ns (find-ns nsym)
+ _ (assert ns (str "Namespace " nsym " not found"))]
+ (conj stats
+ [nsym
+ {:vars {:all-vars (all-defs-in-ns ns)
+ :no-checks (let [all-no-checks @(impl/v 'clojure.core.typed.var-env/CLJ-NOCHECK-VAR?)]
+ (filter (fn [s] (= (namespace s) nsym)) all-no-checks))
+ :var-annotations (let [annots @(impl/v 'clojure.core.typed.var-env/CLJ-VAR-ANNOTATIONS)]
+ (->> annots
+ (filter (fn [[k v]] (= (namespace k) (str nsym))))
+ (map (fn [[k v]] [k (binding [*verbose-types* true]
+ ((impl/v 'clojure.core.typed.parse-unparse/unparse-type)
+ v))]))
+ (into {})))}}])))
+ {} nsyms))
+
+; (ann var-coverage [(Coll Symbol) -> nil])
+(defn var-coverage
+ "Summarises annotated var coverage statistics to *out*
+ for namespaces nsyms, a collection of symbols or a symbol/namespace.
+ Defaults to the current namespace if no argument provided."
+ ([] (var-coverage *ns*))
+ ([nsyms-or-nsym]
+ (assert (or (instance? clojure.lang.Namespace nsyms-or-nsym)
+ (symbol? nsyms-or-nsym)
+ (and (coll? nsyms-or-nsym) (every? symbol? nsyms-or-nsym)))
+ "Must pass a collection of symbols or a symbol/namespace to var-coverage")
+ (let [nsyms (if ((some-fn symbol? #(instance? clojure.lang.Namespace %))
+ nsyms-or-nsym)
+ [(ns-name nsyms-or-nsym)]
+ nsyms-or-nsym)
+ stats (statistics nsyms)
+ nall-vars (->> (vals stats)
+ (map :vars)
+ (map :all-vars)
+ (apply set/union)
+ set
+ count)
+ nannotated-vars (->> (vals stats)
+ (map :vars)
+ (map :var-annotations)
+ (map count)
+ (apply +))
+ perc (if (zero? nall-vars)
+ 0
+ (long (* (/ nannotated-vars nall-vars) 100)))]
+ (println (str "Found " nannotated-vars " annotated vars out of " nall-vars " vars"))
+ (println (str perc "% var annotation coverage"))
+ (flush))))
+
(comment
(check-ns 'clojure.core.typed.test.example)
@@ -306,7 +306,7 @@
) ;end tc-ignore
;TODO to check, needs support for instance field
-(t/ann ^:no-check var->symbol [Var -> Symbol])
+(t/ann ^:no-check var->symbol [(Var Any) -> Symbol])
(defn var->symbol [^Var var]
{:pre [(var? var)]
:post [(symbol? %)
@@ -34,6 +34,21 @@
(assert *current-used-vars*)
(assert *current-checked-var-defs*))
+(defn var-annotations []
+ @*current-var-annotations*)
+
+(defn var-no-checks []
+ (assert-var-env)
+ @*current-nocheck-var?*)
+
+(defn used-vars []
+ (assert-var-env)
+ @*current-used-vars*)
+
+(defn checked-vars []
+ (assert-var-env)
+ @*current-checked-var-defs*)
+
(defn add-var-type [sym type]
(assert-var-env)
(when (contains? @*current-var-annotations* sym)

0 comments on commit 99833fc

Please sign in to comment.