This repository has moved: jvm.tools.analyzer
Clojars Dependency: [analyze "0.3.0"]
Clojure's analysis compilation phase holds rich information about Clojure forms, like type/reflection information.
analyze provides an interface to this phase, callable a la carte. The output is similar to ClojureScript's analyzer.
Supports Clojure 1.4.0 or later.
Pull requests accepted from registered Clojure contributers
http://clojure.org/contributing
0.3.0
- New Hygienic transformation namespace,
analyze.hygiene
ast-hy
, AST -> hygienic ASTemit-hy
, hygienic AST -> hygienic form
map->form
now extensible- Fix emitting variadic method twice in
map->form
case for :fn-expr
0.2.6
- More macroexpansion cases
eval
forms after analysing them- changes to :deftype*
0.2.5
- More cases for
map->form
- Fix :fn-expr case for
map->form
, now emitsfn*
instead offn
0.2.4
- More cases for
map->form
0.2.3
- Add
analyze.emit-form/map->form
- Support Clojure 1.4.0+
0.2.2
- Revert to not
eval
ing forms before analysing
0.2.1
eval
forms before analysing them
analyze.core=> (ast [1])
{:op :constant, :env {:locals {}, :ns {:name analyze.core}}, :val [1]}
analyze.core=> (-> (ast (if true 1 2)) clojure.pprint/pprint)
{:op :if,
:env {:line 5, :locals {}, :ns {:name analyze.core}},
:test
{:op :boolean,
:env {:locals {}, :ns {:name analyze.core}},
:val true},
:then
{:op :number, :env {:locals {}, :ns {:name analyze.core}}, :val 1},
:else
{:op :number, :env {:locals {}, :ns {:name analyze.core}}, :val 2}}
nil
analyze.core=> (-> (ast (fn [x] (+ x 1))) clojure.pprint/pprint)
{:op :fn-expr,
:env {:locals {}, :ns {:name analyze.core}},
:methods
({:op :fn-method,
:env {:locals {}, :ns {:name analyze.core}},
:body
{:op :do,
:env {:locals {}, :ns {:name analyze.core}},
:exprs
({:op :static-method,
:env
{:line 6, :source "REPL", :locals {}, :ns {:name analyze.core}},
:class clojure.lang.Numbers,
:method-name "add",
:method
{:name add,
:return-type java.lang.Number,
:declaring-class clojure.lang.Numbers,
:parameter-types [java.lang.Object long],
:exception-types [],
:flags #{:static :public}},
:args
({:op :local-binding-expr,
:env {:locals {}, :ns {:name analyze.core}},
:local-binding
{:op :local-binding,
:env {:locals {}, :ns {:name analyze.core}},
:sym x,
:tag nil,
:init nil},
:tag nil}
{:op :number,
:env {:locals {}, :ns {:name analyze.core}},
:val 1}),
:tag nil})},
:required-params
({:op :local-binding,
:env {:locals {}, :ns {:name analyze.core}},
:sym x,
:tag nil,
:init nil}),
:rest-param nil}),
:variadic-method nil,
:tag nil}
nil
analyze.core=> (require '[analyze.emit-form :as e])
nil
analyze.core=> (-> (ast 1) e/emit-form)
1
analyze.core=> (-> (ast [(+ 1 2)]) e/emit-form)
[(. clojure.lang.Numbers add 1 2)]
analyze
is a thin wrapper over clojure.lang.Compiler
, so to get our
hands on analysis results some compromises are made.
The following form normally evaluates to the Var clojure.set/intersection
, but
analyses to clojure.core/require
.
;normal evaluation
(eval
'(do
(require '[clojure.set])
(refer 'clojure.set
:only '[intersection]
:rename '{intersection require})
require))
;=> #'clojure.set/intersection
;analysis result
(-> (ast
(do (require '[clojure.set])
(refer 'clojure.set
:only '[intersection]
:rename '{intersection require})
require))
:exprs last :var)
;=> #'clojure.core/require
- analyze a leiningen
project.clj
file - analyze
clojure.core
- use :locals if necessary
See analyze.examples.*
namespaces.
- Jonas Enlund (jonase)
- Nicola Mometto (Bronsa)
- Chris Gray (chrismgray)