Skip to content
This repository has been archived by the owner on Oct 26, 2018. It is now read-only.

frenchy64/analyze

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 

This repository has moved: jvm.tools.analyzer

Clojars Dependency: [analyze "0.3.0"]

Interface to Clojure's Analyzer

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.

Contributing

Pull requests accepted from registered Clojure contributers

http://clojure.org/contributing

Changelog

0.3.0

  • New Hygienic transformation namespace, analyze.hygiene
    • ast-hy, AST -> hygienic AST
    • emit-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 emits fn* instead of fn

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 evaling forms before analysing

0.2.1

  • eval forms before analysing them

Usage

Generating AST from syntax

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

Syntax from AST

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)]

Known Issues

Incorrect handling of Var mappings within the same form

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

Todo

  • analyze a leiningen project.clj file
  • analyze clojure.core
  • use :locals if necessary

Examples

See analyze.examples.* namespaces.

Contributors

  • Jonas Enlund (jonase)
  • Nicola Mometto (Bronsa)
  • Chris Gray (chrismgray)

About

Interface to Clojure's Analyzer

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •