diff options
-rw-r--r-- | build.xml | 1 | ||||
-rw-r--r-- | src/clj/clojure/core.clj | 20 | ||||
-rw-r--r-- | src/clj/clojure/main.clj | 35 | ||||
-rw-r--r-- | src/clj/clojure/reflect.clj | 123 | ||||
-rw-r--r-- | src/clj/clojure/reflect/java.clj | 253 | ||||
-rw-r--r-- | src/clj/clojure/repl.clj | 33 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 142 | ||||
-rw-r--r-- | src/jvm/clojure/lang/LispReader.java | 38 | ||||
-rw-r--r-- | src/jvm/clojure/lang/PersistentQueue.java | 22 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 328 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Symbol.java | 8 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Var.java | 4 | ||||
-rw-r--r-- | test/clojure/test_clojure.clj | 1 | ||||
-rw-r--r-- | test/clojure/test_clojure/data_structures.clj | 73 | ||||
-rw-r--r-- | test/clojure/test_clojure/ns_libs.clj | 8 | ||||
-rw-r--r-- | test/clojure/test_clojure/reflect.clj | 33 |
16 files changed, 779 insertions, 343 deletions
@@ -120,6 +120,7 @@ <arg value="clojure.java.browse-ui"/> <arg value="clojure.string"/> <arg value="clojure.data"/> + <arg value="clojure.reflect"/> </java> </target> diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index b399f6cf..2f5504cc 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -3755,19 +3755,23 @@ (defn ns-resolve "Returns the var or Class to which a symbol will be resolved in the - namespace, else nil. Note that if the symbol is fully qualified, - the var/Class to which it resolves need not be present in the - namespace." + namespace (unless found in the environement), else nil. Note that + if the symbol is fully qualified, the var/Class to which it resolves + need not be present in the namespace." {:added "1.0" :static true} - [ns sym] - (clojure.lang.Compiler/maybeResolveIn (the-ns ns) sym)) + ([ns sym] + (ns-resolve ns nil sym)) + ([ns env sym] + (when-not (contains? env sym) + (clojure.lang.Compiler/maybeResolveIn (the-ns ns) sym)))) (defn resolve - "same as (ns-resolve *ns* symbol)" + "same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)" {:added "1.0" :static true} - [sym] (ns-resolve *ns* sym)) + ([sym] (ns-resolve *ns* sym)) + ([env sym] (ns-resolve *ns* env sym))) (defn array-map "Constructs an array-map." @@ -5635,7 +5639,7 @@ (add-doc-and-meta *out* "A java.io.Writer object representing standard output for print operations. - Defaults to System/out" + Defaults to System/out, wrapped in an OutputStreamWriter" {:added "1.0"}) (add-doc-and-meta *err* diff --git a/src/clj/clojure/main.clj b/src/clj/clojure/main.clj index d52123fe..7aa74ab8 100644 --- a/src/clj/clojure/main.clj +++ b/src/clj/clojure/main.clj @@ -104,11 +104,11 @@ [e] (let [ex (repl-exception e) el (aget (.getStackTrace ex) 0)] - (.println *err* - (str (-> ex class .getSimpleName) - " " (.getMessage ex) " " - (when-not (instance? clojure.lang.Compiler$CompilerException ex) - (str " " (stack-element-str el))))))) + (binding [*out* *err*] + (println (str (-> ex class .getSimpleName) + " " (.getMessage ex) " " + (when-not (instance? clojure.lang.Compiler$CompilerException ex) + (str " " (stack-element-str el)))))))) (defn repl "Generic, reusable, read-eval-print loop. By default, reads from *in*, @@ -248,6 +248,14 @@ (doseq [[opt arg] inits] ((init-dispatch opt) arg))) +(defn- main-opt + "Call the -main function from a namespace with string arguments from + the command line." + [[_ main-ns & args] inits] + (with-bindings + (initialize args inits) + (apply (ns-resolve (doto (symbol main-ns) require) '-main) args))) + (defn- repl-opt "Start a repl with args and inits. Print greeting if no eval options were present" @@ -284,6 +292,8 @@ (or ({"-r" repl-opt "--repl" repl-opt + "-m" main-opt + "--main" main-opt nil null-opt "-h" help-opt "--help" help-opt @@ -316,14 +326,15 @@ java -cp clojure.jar clojure.main -i init.clj script.clj args...") With no options or args, runs an interactive Read-Eval-Print Loop init options: - -i, --init path Load a file or resource - -e, --eval string Evaluate expressions in string; print non-nil values + -i, --init path Load a file or resource + -e, --eval string Evaluate expressions in string; print non-nil values main options: - -r, --repl Run a repl - path Run a script from from a file or resource - - Run a script from standard input - -h, -?, --help Print this help message and exit + -m, --main ns-name Call the -main function from a namespace with args + -r, --repl Run a repl + path Run a script from from a file or resource + - Run a script from standard input + -h, -?, --help Print this help message and exit operation: @@ -332,7 +343,7 @@ java -cp clojure.jar clojure.main -i init.clj script.clj args...") - Binds *command-line-args* to a seq of strings containing command line args that appear after any main option - Runs all init options in order - - Runs a repl or script if requested + - Calls a -main function or runs a repl or script if requested The init options may be repeated and mixed freely, but must appear before any main option. The appearance of any eval option before running a repl diff --git a/src/clj/clojure/reflect.clj b/src/clj/clojure/reflect.clj new file mode 100644 index 00000000..cf639568 --- /dev/null +++ b/src/clj/clojure/reflect.clj @@ -0,0 +1,123 @@ +; Copyright (c) Rich Hickey. All rights reserved. +; The use and distribution terms for this software are covered by the +; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +; which can be found in the file epl-v10.html at the root of this distribution. +; By using this software in any fashion, you are agreeing to be bound by +; the terms of this license. +; You must not remove this notice, or any other, from this software. + +(ns ^{:author "Stuart Halloway" + :added "1.3" + :doc "Reflection on Host Types +Alpha - subject to change. + +Two main entry points: + +* type-reflect reflects on something that implements TypeReference. +* reflect (for REPL use) reflects on the class of an instance, or + on a class if passed a class + +Key features: + +* Exposes the read side of reflection as pure data. Reflecting + on a type returns a map with keys :bases, :flags, and :members. + +* Canonicalizes class names as Clojure symbols. Types can extend + to the TypeReference protocol to indicate that they can be + unambiguously resolved as a type name. The canonical format + requires one non-Java-ish convention: array brackets are <> + instead of [] so they can be part of a Clojure symbol. + +* Pluggable Reflectors for different implementations. The default + JavaReflector is good when you have a class in hand, or use + the AsmReflector for \"hands off\" reflection without forcing + classes to load. + +Platform implementers must: + +* Create an implementation of Reflector. +* Create one or more implementations of TypeReference. +* def default-reflector to be an instance that satisfies Reflector."} + clojure.reflect + (:require [clojure.set :as set])) + +(defprotocol Reflector + "Protocol for reflection implementers." + (do-reflect [reflector typeref])) + +(defprotocol TypeReference + "A TypeReference can be unambiguously converted to a type name on + the host platform. + + All typerefs are normalized into symbols. If you need to + normalize a typeref yourself, call typesym." + (typename [o] "Returns Java name as returned by ASM getClassName, e.g. byte[], java.lang.String[]")) + +(declare default-reflector) + +(defn type-reflect + "Alpha - subject to change. + Reflect on a typeref, returning a map with :bases, :flags, and + :members. In the discussion below, names are always Clojure symbols. + + :bases a set of names of the type's bases + :flags a set of keywords naming the boolean attributes + of the type. + :members a set of the type's members. Each membrer is a map + and can be a constructor, method, or field. + + Keys common to all members: + :name name of the type + :declaring-class name of the declarer + :flags keyword naming boolean attributes of the member + + Keys specific to constructors: + :parameter-types vector of parameter type names + :exception-types vector of exception type names + + Key specific to methods: + :parameter-types vector of parameter type names + :exception-types vector of exception type names + :return-type return type name + + Keys specific to fields: + :type type name + + Options: + + :ancestors in addition to the keys described above, also + include an :ancestors key with the entire set of + ancestors, and add all ancestor members to + :members. + :reflector implementation to use. Defaults to JavaReflector, + AsmReflector is also an option." + {:added "1.3"} + [typeref & options] + (let [{:keys [ancestors reflector]} + (merge {:reflector default-reflector} + (apply hash-map options)) + refl (partial do-reflect reflector) + result (refl typeref)] + ;; could make simpler loop of two args: names an + (if ancestors + (let [make-ancestor-map (fn [names] + (zipmap names (map refl names)))] + (loop [reflections (make-ancestor-map (:bases result))] + (let [ancestors-visited (set (keys reflections)) + ancestors-to-visit (set/difference (set (mapcat :bases (vals reflections))) + ancestors-visited)] + (if (seq ancestors-to-visit) + (recur (merge reflections (make-ancestor-map ancestors-to-visit))) + (apply merge-with into result {:ancestors ancestors-visited} + (map #(select-keys % [:members]) (vals reflections))))))) + result))) + +(defn reflect + "Alpha - subject to change. + Reflect on the type of obj (or obj itself if obj is a class). + Return value and options are the same as for type-reflect. " + {:added "1.3"} + [obj & options] + (apply type-reflect (if (class? obj) obj (class obj)) options)) + +(load "reflect/java") diff --git a/src/clj/clojure/reflect/java.clj b/src/clj/clojure/reflect/java.clj new file mode 100644 index 00000000..9a030899 --- /dev/null +++ b/src/clj/clojure/reflect/java.clj @@ -0,0 +1,253 @@ +; Copyright (c) Rich Hickey. All rights reserved. +; The use and distribution terms for this software are covered by the +; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +; which can be found in the file epl-v10.html at the root of this distribution. +; By using this software in any fashion, you are agreeing to be bound by +; the terms of this license. +; You must not remove this notice, or any other, from this software. + +;; Java-specific parts of clojure.reflect +(in-ns 'clojure.reflect) + +(require '[clojure.set :as set] + '[clojure.string :as str]) +(import '[clojure.asm ClassReader ClassVisitor Type] + '[java.lang.reflect Modifier] + java.io.InputStream) + +(extend-protocol TypeReference + clojure.lang.Symbol + (typename [s] (str/replace (str s) "<>" "[]")) + + Class + ;; neither .getName not .getSimpleName returns the right thing, so best to delegate to Type + (typename + [c] + (typename (Type/getType c))) + + Type + (typename + [t] + (-> (.getClassName t)))) + +(defn- typesym + "Given a typeref, create a legal Clojure symbol version of the + type's name." + [t] + (-> (typename t) + (str/replace "[]" "<>") + (symbol))) + +(defn- resource-name + "Given a typeref, return implied resource name. Used by Reflectors + such as ASM that need to find and read classbytes from files." + [typeref] + (-> (typename typeref) + (str/replace "." "/") + (str ".class"))) + +(defn- access-flag + [[name flag & contexts]] + {:name name :flag flag :contexts (set (map keyword contexts))}) + +(defn- field-descriptor->class-symbol + "Convert a Java field descriptor to a Clojure class symbol. Field + descriptors are described in section 4.3.2 of the JVM spec, 2nd ed.: + http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#14152" + [^String d] + {:pre [(string? d)]} + (typesym (Type/getType d))) + +(defn- internal-name->class-symbol + "Convert a Java internal name to a Clojure class symbol. Internal + names uses slashes instead of dots, e.g. java/lang/String. See + Section 4.2 of the JVM spec, 2nd ed.: + + http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#14757" + [d] + {:pre [(string? d)]} + (typesym (Type/getObjectType d))) + +(def ^{:doc "The Java access bitflags, along with their friendly names and +the kinds of objects to which they can apply."} + flag-descriptors + (vec + (map access-flag + [[:public 0x0001 :class :field :method] + [:private 0x002 :class :field :method] + [:protected 0x0004 :class :field :method] + [:static 0x0008 :field :method] + [:final 0x0010 :class :field :method] + ;; :super is ancient history and is unfindable (?) by + ;; reflection. skip it + #_[:super 0x0020 :class] + [:synchronized 0x0020 :method] + [:volatile 0x0040 :field] + [:bridge 0x0040 :method] + [:varargs 0x0080 :method] + [:transient 0x0080 :field] + [:native 0x0100 :method] + [:interface 0x0200 :class] + [:abstract 0x0400 :class :method] + [:strict 0x0800 :method] + [:synthetic 0x1000 :class :field :method] + [:annotation 0x2000 :class] + [:enum 0x4000 :class :field :inner]]))) + +(defn- parse-flags + "Convert reflection bitflags into a set of keywords." + [flags context] + (reduce + (fn [result fd] + (if (and (get (:contexts fd) context) + (not (zero? (bit-and flags (:flag fd))))) + (conj result (:name fd)) + result)) + #{} + flag-descriptors)) + +(defrecord Constructor + [name declaring-class parameter-types exception-types flags]) + +(defn- constructor->map + [^java.lang.reflect.Constructor constructor] + (Constructor. + (symbol (.getName constructor)) + (typesym (.getDeclaringClass constructor)) + (vec (map typesym (.getParameterTypes constructor))) + (vec (map typesym (.getExceptionTypes constructor))) + (parse-flags (.getModifiers constructor) :method))) + +(defn- declared-constructors + "Return a set of the declared constructors of class as a Clojure map." + [^Class cls] + (set (map + constructor->map + (.getDeclaredConstructors cls)))) + +(defrecord Method + [name return-type declaring-class parameter-types exception-types flags]) + +(defn- method->map + [^java.lang.reflect.Method method] + (Method. + (symbol (.getName method)) + (typesym (.getReturnType method)) + (typesym (.getDeclaringClass method)) + (vec (map typesym (.getParameterTypes method))) + (vec (map typesym (.getExceptionTypes method))) + (parse-flags (.getModifiers method) :method))) + +(defn- declared-methods + "Return a set of the declared constructors of class as a Clojure map." + [^Class cls] + (set (map + method->map + (.getDeclaredMethods cls)))) + +(defrecord Field + [name type declaring-class flags]) + +(defn- field->map + [^java.lang.reflect.Field field] + (Field. + (symbol (.getName field)) + (typesym (.getType field)) + (typesym (.getDeclaringClass field)) + (parse-flags (.getModifiers field) :field))) + +(defn- declared-fields + "Return a set of the declared fields of class as a Clojure map." + [^Class cls] + (set (map + field->map + (.getDeclaredFields cls)))) + +(deftype JavaReflector [classloader] + Reflector + (do-reflect [_ typeref] + (let [cls (Class/forName (typename typeref) false classloader)] + {:bases (not-empty (set (map typesym (bases cls)))) + :flags (parse-flags (.getModifiers cls) :class) + :members (set/union (declared-fields cls) + (declared-methods cls) + (declared-constructors cls))}))) + +(def ^:private default-reflector + (JavaReflector. (.getContextClassLoader (Thread/currentThread)))) + +(defn- parse-method-descriptor + [^String md] + {:parameter-types (vec (map typesym (Type/getArgumentTypes md))) + :return-type (typesym (Type/getReturnType md))}) + +(defprotocol ClassResolver + (^InputStream resolve-class [this name] + "Given a class name, return that typeref's class bytes as an InputStream.")) + +(extend-protocol ClassResolver + clojure.lang.Fn + (resolve-class [this typeref] (this typeref)) + + ClassLoader + (resolve-class [this typeref] + (.getResourceAsStream this (resource-name typeref)))) + +(deftype AsmReflector [class-resolver] + Reflector + (do-reflect [_ typeref] + (with-open [is (resolve-class class-resolver typeref)] + (let [class-symbol (typesym typeref) + r (ClassReader. is) + result (atom {:bases #{} :flags #{} :members #{}})] + (.accept + r + (reify + ClassVisitor + (visit [_ version access name signature superName interfaces] + (let [flags (parse-flags access :class) + ;; ignore java.lang.Object on interfaces to match reflection + superName (if (and (flags :interface) + (= superName "java/lang/Object")) + nil + superName) + bases (->> (cons superName interfaces) + (remove nil?) + (map internal-name->class-symbol) + (map symbol) + (set) + (not-empty))] + (swap! result merge {:bases bases + :flags flags}))) + (visitSource [_ name debug]) + (visitInnerClass [_ name outerName innerName access]) + (visitField [_ access name desc signature value] + (swap! result update-in [:members] (fnil conj #{}) + (Field. (symbol name) + (field-descriptor->class-symbol desc) + class-symbol + (parse-flags access :field))) + nil) + (visitMethod [_ access name desc signature exceptions] + (when-not (= name "<clinit>") + (let [constructor? (= name "<init>")] + (swap! result update-in [:members] (fnil conj #{}) + (let [{:keys [parameter-types return-type]} (parse-method-descriptor desc) + flags (parse-flags access :method)] + (if constructor? + (Constructor. class-symbol + class-symbol + parameter-types + (vec (map internal-name->class-symbol exceptions)) + flags) + (Method. (symbol name) + return-type + class-symbol + parameter-types + (vec (map internal-name->class-symbol exceptions)) + flags)))))) + nil) + (visitEnd [_]) + ) 0) + @result)))) + diff --git a/src/clj/clojure/repl.clj b/src/clj/clojure/repl.clj index 2f50223d..77ef9dad 100644 --- a/src/clj/clojure/repl.clj +++ b/src/clj/clojure/repl.clj @@ -131,20 +131,23 @@ str-or-pattern." most recent repl exception (*e), and a depth of 12." {:added "1.3"} ([] (pst 12)) - ([depth] - (when-let [e *e] - (pst (root-cause e) depth))) + ([e-or-depth] + (if (instance? Throwable e-or-depth) + (pst e-or-depth 12) + (when-let [e *e] + (pst (root-cause e) e-or-depth)))) ([^Throwable e depth] - (.println *err* (str (-> e class .getSimpleName) " " (.getMessage e))) - (let [st (.getStackTrace e) - cause (.getCause e)] - (doseq [el (take depth - (remove #(#{"clojure.lang.RestFn" "clojure.lang.AFn"} (.getClassName %)) - st))] - (.println *err* (str \tab (stack-element-str el)))) - (when cause - (.println *err* "Caused by:") - (pst cause (min depth - (+ 2 (- (count (.getStackTrace cause)) - (count st))))))))) + (binding [*out* *err*] + (println (str (-> e class .getSimpleName) " " (.getMessage e))) + (let [st (.getStackTrace e) + cause (.getCause e)] + (doseq [el (take depth + (remove #(#{"clojure.lang.RestFn" "clojure.lang.AFn"} (.getClassName %)) + st))] + (println (str \tab (stack-element-str el)))) + (when cause + (println "Caused by:") + (pst cause (min depth + (+ 2 (- (count (.getStackTrace cause)) + (count st)))))))))) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 24cb9359..b1b4d84e 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -34,51 +34,51 @@ import java.lang.reflect.Modifier; public class Compiler implements Opcodes{ -static final Symbol DEF = Symbol.create("def"); -static final Symbol LOOP = Symbol.create("loop*"); -static final Symbol RECUR = Symbol.create("recur"); -static final Symbol IF = Symbol.create("if"); -static final Symbol LET = Symbol.create("let*"); -static final Symbol LETFN = Symbol.create("letfn*"); -static final Symbol DO = Symbol.create("do"); -static final Symbol FN = Symbol.create("fn*"); -static final Symbol QUOTE = Symbol.create("quote"); -static final Symbol THE_VAR = Symbol.create("var"); -static final Symbol DOT = Symbol.create("."); -static final Symbol ASSIGN = Symbol.create("set!"); -//static final Symbol TRY_FINALLY = Symbol.create("try-finally"); -static final Symbol TRY = Symbol.create("try"); -static final Symbol CATCH = Symbol.create("catch"); -static final Symbol FINALLY = Symbol.create("finally"); -static final Symbol THROW = Symbol.create("throw"); -static final Symbol MONITOR_ENTER = Symbol.create("monitor-enter"); -static final Symbol MONITOR_EXIT = Symbol.create("monitor-exit"); -static final Symbol IMPORT = Symbol.create("clojure.core", "import*"); -//static final Symbol INSTANCE = Symbol.create("instance?"); -static final Symbol DEFTYPE = Symbol.create("deftype*"); -static final Symbol CASE = Symbol.create("case*"); - -//static final Symbol THISFN = Symbol.create("thisfn"); -static final Symbol CLASS = Symbol.create("Class"); -static final Symbol NEW = Symbol.create("new"); -static final Symbol THIS = Symbol.create("this"); -static final Symbol REIFY = Symbol.create("reify*"); -//static final Symbol UNQUOTE = Symbol.create("unquote"); -//static final Symbol UNQUOTE_SPLICING = Symbol.create("unquote-splicing"); -//static final Symbol SYNTAX_QUOTE = Symbol.create("clojure.core", "syntax-quote"); -static final Symbol LIST = Symbol.create("clojure.core", "list"); -static final Symbol HASHMAP = Symbol.create("clojure.core", "hash-map"); -static final Symbol VECTOR = Symbol.create("clojure.core", "vector"); -static final Symbol IDENTITY = Symbol.create("clojure.core", "identity"); - -static final Symbol _AMP_ = Symbol.create("&"); -static final Symbol ISEQ = Symbol.create("clojure.lang.ISeq"); +static final Symbol DEF = Symbol.intern("def"); +static final Symbol LOOP = Symbol.intern("loop*"); +static final Symbol RECUR = Symbol.intern("recur"); +static final Symbol IF = Symbol.intern("if"); +static final Symbol LET = Symbol.intern("let*"); +static final Symbol LETFN = Symbol.intern("letfn*"); +static final Symbol DO = Symbol.intern("do"); +static final Symbol FN = Symbol.intern("fn*"); +static final Symbol QUOTE = Symbol.intern("quote"); +static final Symbol THE_VAR = Symbol.intern("var"); +static final Symbol DOT = Symbol.intern("."); +static final Symbol ASSIGN = Symbol.intern("set!"); +//static final Symbol TRY_FINALLY = Symbol.intern("try-finally"); +static final Symbol TRY = Symbol.intern("try"); +static final Symbol CATCH = Symbol.intern("catch"); +static final Symbol FINALLY = Symbol.intern("finally"); +static final Symbol THROW = Symbol.intern("throw"); +static final Symbol MONITOR_ENTER = Symbol.intern("monitor-enter"); +static final Symbol MONITOR_EXIT = Symbol.intern("monitor-exit"); +static final Symbol IMPORT = Symbol.intern("clojure.core", "import*"); +//static final Symbol INSTANCE = Symbol.intern("instance?"); +static final Symbol DEFTYPE = Symbol.intern("deftype*"); +static final Symbol CASE = Symbol.intern("case*"); + +//static final Symbol THISFN = Symbol.intern("thisfn"); +static final Symbol CLASS = Symbol.intern("Class"); +static final Symbol NEW = Symbol.intern("new"); +static final Symbol THIS = Symbol.intern("this"); +static final Symbol REIFY = Symbol.intern("reify*"); +//static final Symbol UNQUOTE = Symbol.intern("unquote"); +//static final Symbol UNQUOTE_SPLICING = Symbol.intern("unquote-splicing"); +//static final Symbol SYNTAX_QUOTE = Symbol.intern("clojure.core", "syntax-quote"); +static final Symbol LIST = Symbol.intern("clojure.core", "list"); +static final Symbol HASHMAP = Symbol.intern("clojure.core", "hash-map"); +static final Symbol VECTOR = Symbol.intern("clojure.core", "vector"); +static final Symbol IDENTITY = Symbol.intern("clojure.core", "identity"); + +static final Symbol _AMP_ = Symbol.intern("&"); +static final Symbol ISEQ = Symbol.intern("clojure.lang.ISeq"); static final Keyword inlineKey = Keyword.intern(null, "inline"); static final Keyword inlineAritiesKey = Keyword.intern(null, "inline-arities"); static final Keyword staticKey = Keyword.intern(null, "static"); static final Keyword arglistsKey = Keyword.intern(null, "arglists"); -static final Symbol INVOKE_STATIC = Symbol.create("invokeStatic"); +static final Symbol INVOKE_STATIC = Symbol.intern("invokeStatic"); static final Keyword volatileKey = Keyword.intern(null, "volatile"); static final Keyword implementsKey = Keyword.intern(null, "implements"); @@ -87,13 +87,13 @@ static final String COMPILE_STUB_PREFIX = "compile__stub"; static final Keyword protocolKey = Keyword.intern(null, "protocol"); static final Keyword onKey = Keyword.intern(null, "on"); -static final Symbol NS = Symbol.create("ns"); -static final Symbol IN_NS = Symbol.create("in-ns"); +static final Symbol NS = Symbol.intern("ns"); +static final Symbol IN_NS = Symbol.intern("in-ns"); -//static final Symbol IMPORT = Symbol.create("import"); -//static final Symbol USE = Symbol.create("use"); +//static final Symbol IMPORT = Symbol.intern("import"); +//static final Symbol USE = Symbol.intern("use"); -//static final Symbol IFN = Symbol.create("clojure.lang", "IFn"); +//static final Symbol IFN = Symbol.intern("clojure.lang", "IFn"); static final public IPersistentMap specials = PersistentHashMap.create( DEF, new DefExpr.Parser(), @@ -213,25 +213,25 @@ static final public Var IN_CATCH_FINALLY = Var.create(null); static final public Var LOADER = Var.create(); //String -static final public Var SOURCE = Var.intern(Namespace.findOrCreate(Symbol.create("clojure.core")), - Symbol.create("*source-path*"), "NO_SOURCE_FILE"); +static final public Var SOURCE = Var.intern(Namespace.findOrCreate(Symbol.intern("clojure.core")), + Symbol.intern("*source-path*"), "NO_SOURCE_FILE"); //String -static final public Var SOURCE_PATH = Var.intern(Namespace.findOrCreate(Symbol.create("clojure.core")), - Symbol.create("*file*"), "NO_SOURCE_PATH"); +static final public Var SOURCE_PATH = Var.intern(Namespace.findOrCreate(Symbol.intern("clojure.core")), + Symbol.intern("*file*"), "NO_SOURCE_PATH"); //String -static final public Var COMPILE_PATH = Var.intern(Namespace.findOrCreate(Symbol.create("clojure.core")), - Symbol.create("*compile-path*"), null); +static final public Var COMPILE_PATH = Var.intern(Namespace.findOrCreate(Symbol.intern("clojure.core")), + Symbol.intern("*compile-path*"), null); //boolean -static final public Var COMPILE_FILES = Var.intern(Namespace.findOrCreate(Symbol.create("clojure.core")), - Symbol.create("*compile-files*"), Boolean.FALSE); +static final public Var COMPILE_FILES = Var.intern(Namespace.findOrCreate(Symbol.intern("clojure.core")), + Symbol.intern("*compile-files*"), Boolean.FALSE); -static final public Var INSTANCE = Var.intern(Namespace.findOrCreate(Symbol.create("clojure.core")), - Symbol.create("instance?")); +static final public Var INSTANCE = Var.intern(Namespace.findOrCreate(Symbol.intern("clojure.core")), + Symbol.intern("instance?")); -static final public Var ADD_ANNOTATIONS = Var.intern(Namespace.findOrCreate(Symbol.create("clojure.core")), - Symbol.create("add-annotations")); +static final public Var ADD_ANNOTATIONS = Var.intern(Namespace.findOrCreate(Symbol.intern("clojure.core")), + Symbol.intern("add-annotations")); //Integer static final public Var LINE = Var.create(0); @@ -305,7 +305,7 @@ static Symbol resolveSymbol(Symbol sym){ Namespace ns = namespaceFor(sym); if(ns == null || ns.name.name == sym.ns) return sym; - return Symbol.create(ns.name.name, sym.name); + return Symbol.intern(ns.name.name, sym.name); } Object o = currentNS().getMapping(sym); if(o == null) @@ -315,7 +315,7 @@ static Symbol resolveSymbol(Symbol sym){ else if(o instanceof Var) { Var v = (Var) o; - return Symbol.create(v.ns.name.name, v.sym.name); + return Symbol.intern(v.ns.name.name, v.sym.name); } return null; @@ -331,7 +331,7 @@ static class DefExpr implements Expr{ final static Method bindRootMethod = Method.getMethod("void bindRoot(Object)"); final static Method setTagMethod = Method.getMethod("void setTag(clojure.lang.Symbol)"); final static Method setMetaMethod = Method.getMethod("void setMeta(clojure.lang.IPersistentMap)"); - final static Method symcreate = Method.getMethod("clojure.lang.Symbol create(String, String)"); + final static Method symintern = Method.getMethod("clojure.lang.Symbol intern(String, String)"); public DefExpr(String source, int line, Var var, Expr init, Expr meta, boolean initProvided){ this.source = source; @@ -3610,7 +3610,7 @@ static public class ObjExpr implements Expr{ } final static Method kwintern = Method.getMethod("clojure.lang.Keyword intern(String, String)"); - final static Method symcreate = Method.getMethod("clojure.lang.Symbol create(String)"); + final static Method symintern = Method.getMethod("clojure.lang.Symbol intern(String)"); final static Method varintern = Method.getMethod("clojure.lang.Var intern(clojure.lang.Symbol, clojure.lang.Symbol)"); @@ -4093,7 +4093,7 @@ static public class ObjExpr implements Expr{ gen.push(((Symbol) value).ns); gen.push(((Symbol) value).name); gen.invokeStatic(Type.getType(Symbol.class), - Method.getMethod("clojure.lang.Symbol create(String,String)")); + Method.getMethod("clojure.lang.Symbol intern(String,String)")); } else if(value instanceof Keyword) { @@ -6148,7 +6148,7 @@ private static Expr analyzeSymbol(Symbol sym) throws Exception{ { if(namespaceFor(sym) == null) { - Symbol nsSym = Symbol.create(sym.ns); + Symbol nsSym = Symbol.intern(sym.ns); Class c = HostExpr.maybeClass(nsSym, false); if(c != null) { @@ -6209,7 +6209,7 @@ static Namespace namespaceFor(Symbol sym){ static Namespace namespaceFor(Namespace inns, Symbol sym){ //note, presumes non-nil sym.ns // first check against currentNS' aliases... - Symbol nsSym = Symbol.create(sym.ns); + Symbol nsSym = Symbol.intern(sym.ns); Namespace ns = inns.lookupAlias(nsSym); if(ns == null) { @@ -6227,7 +6227,7 @@ static public Object resolveIn(Namespace n, Symbol sym, boolean allowPrivate) th if(ns == null) throw new Exception("No such namespace: " + sym.ns); - Var v = ns.findInternedVar(Symbol.create(sym.name)); + Var v = ns.findInternedVar(Symbol.intern(sym.name)); if(v == null) throw new Exception("No such var: " + sym); else if(v.ns != currentNS() && !v.isPublic() && !allowPrivate) @@ -6270,7 +6270,7 @@ static public Object maybeResolveIn(Namespace n, Symbol sym) throws Exception{ Namespace ns = namespaceFor(n, sym); if(ns == null) return null; - Var v = ns.findInternedVar(Symbol.create(sym.name)); + Var v = ns.findInternedVar(Symbol.intern(sym.name)); if(v == null) return null; return v; @@ -6302,7 +6302,7 @@ static Var lookupVar(Symbol sym, boolean internNew) throws Exception{ if(ns == null) return null; //throw new Exception("No such namespace: " + sym.ns); - Symbol name = Symbol.create(sym.name); + Symbol name = Symbol.intern(sym.name); if(internNew && ns == currentNS()) var = currentNS().intern(name); else @@ -6320,7 +6320,7 @@ static Var lookupVar(Symbol sym, boolean internNew) throws Exception{ { //introduce a new var in the current ns if(internNew) - var = currentNS().intern(Symbol.create(sym.name)); + var = currentNS().intern(Symbol.intern(sym.name)); } else if(o instanceof Var) { @@ -6478,8 +6478,8 @@ static public void writeClassFile(String internalName, byte[] bytecode) throws E } public static void pushNS(){ - Var.pushThreadBindings(PersistentHashMap.create(Var.intern(Symbol.create("clojure.core"), - Symbol.create("*ns*")), null)); + Var.pushThreadBindings(PersistentHashMap.create(Var.intern(Symbol.intern("clojure.core"), + Symbol.intern("*ns*")), null)); } public static ILookupThunk getLookupThunk(Object target, Keyword k){ @@ -7124,7 +7124,7 @@ public static class NewInstanceMethod extends ObjMethod{ if(tag != null) hinted = true; if(p.getNamespace() != null) - p = Symbol.create(p.name); + p = Symbol.intern(p.name); Class pclass = tagClass(tag); pclasses[i] = pclass; psyms[i] = p; diff --git a/src/jvm/clojure/lang/LispReader.java b/src/jvm/clojure/lang/LispReader.java index 91a854e7..35addd7c 100644 --- a/src/jvm/clojure/lang/LispReader.java +++ b/src/jvm/clojure/lang/LispReader.java @@ -22,22 +22,22 @@ import java.lang.*; public class LispReader{ -static final Symbol QUOTE = Symbol.create("quote"); -static final Symbol THE_VAR = Symbol.create("var"); -//static Symbol SYNTAX_QUOTE = Symbol.create(null, "syntax-quote"); -static Symbol UNQUOTE = Symbol.create("clojure.core", "unquote"); -static Symbol UNQUOTE_SPLICING = Symbol.create("clojure.core", "unquote-splicing"); -static Symbol CONCAT = Symbol.create("clojure.core", "concat"); -static Symbol SEQ = Symbol.create("clojure.core", "seq"); -static Symbol LIST = Symbol.create("clojure.core", "list"); -static Symbol APPLY = Symbol.create("clojure.core", "apply"); -static Symbol HASHMAP = Symbol.create("clojure.core", "hash-map"); -static Symbol HASHSET = Symbol.create("clojure.core", "hash-set"); -static Symbol VECTOR = Symbol.create("clojure.core", "vector"); -static Symbol WITH_META = Symbol.create("clojure.core", "with-meta"); -static Symbol META = Symbol.create("clojure.core", "meta"); -static Symbol DEREF = Symbol.create("clojure.core", "deref"); -//static Symbol DEREF_BANG = Symbol.create("clojure.core", "deref!"); +static final Symbol QUOTE = Symbol.intern("quote"); +static final Symbol THE_VAR = Symbol.intern("var"); +//static Symbol SYNTAX_QUOTE = Symbol.intern(null, "syntax-quote"); +static Symbol UNQUOTE = Symbol.intern("clojure.core", "unquote"); +static Symbol UNQUOTE_SPLICING = Symbol.intern("clojure.core", "unquote-splicing"); +static Symbol CONCAT = Symbol.intern("clojure.core", "concat"); +static Symbol SEQ = Symbol.intern("clojure.core", "seq"); +static Symbol LIST = Symbol.intern("clojure.core", "list"); +static Symbol APPLY = Symbol.intern("clojure.core", "apply"); +static Symbol HASHMAP = Symbol.intern("clojure.core", "hash-map"); +static Symbol HASHSET = Symbol.intern("clojure.core", "hash-set"); +static Symbol VECTOR = Symbol.intern("clojure.core", "vector"); +static Symbol WITH_META = Symbol.intern("clojure.core", "with-meta"); +static Symbol META = Symbol.intern("clojure.core", "meta"); +static Symbol DEREF = Symbol.intern("clojure.core", "deref"); +//static Symbol DEREF_BANG = Symbol.intern("clojure.core", "deref!"); static IFn[] macros = new IFn[256]; static IFn[] dispatchMacros = new IFn[256]; @@ -50,8 +50,8 @@ static Pattern intPat = "([-+]?)(?:(0)|([1-9][0-9]*)|0[xX]([0-9A-Fa-f]+)|0([0-7]+)|([1-9][0-9]?)[rR]([0-9A-Za-z]+)|0[0-9]+)(N)?"); static Pattern ratioPat = Pattern.compile("([-+]?[0-9]+)/([0-9]+)"); static Pattern floatPat = Pattern.compile("([-+]?[0-9]+(\\.[0-9]*)?([eE][-+]?[0-9]+)?)(M)?"); -static final Symbol SLASH = Symbol.create("/"); -static final Symbol CLOJURE_SLASH = Symbol.create("clojure.core","/"); +static final Symbol SLASH = Symbol.intern("/"); +static final Symbol CLOJURE_SLASH = Symbol.intern("clojure.core","/"); //static Pattern accessorPat = Pattern.compile("\\.[a-zA-Z_]\\w*"); //static Pattern instanceMemberPat = Pattern.compile("\\.([a-zA-Z_][\\w\\.]*)\\.([a-zA-Z_]\\w*)"); //static Pattern staticMemberPat = Pattern.compile("([a-zA-Z_][\\w\\.]*)\\.([a-zA-Z_]\\w*)"); @@ -929,7 +929,7 @@ public static class ListReader extends AFn{ } static class CtorReader extends AFn{ - static final Symbol cls = Symbol.create("class"); + static final Symbol cls = Symbol.intern("class"); public Object invoke(Object reader, Object leftangle) throws Exception{ PushbackReader r = (PushbackReader) reader; diff --git a/src/jvm/clojure/lang/PersistentQueue.java b/src/jvm/clojure/lang/PersistentQueue.java index fb7781c3..674fd790 100644 --- a/src/jvm/clojure/lang/PersistentQueue.java +++ b/src/jvm/clojure/lang/PersistentQueue.java @@ -17,22 +17,24 @@ import java.util.Iterator; /**
* conses onto rear, peeks/pops from front
* See Okasaki's Batched Queues
- * This differs in that it uses a PersistentArrayList as the rear, which is in-order,
+ * This differs in that it uses a PersistentVector as the rear, which is in-order, * so no reversing or suspensions required for persistent use
*/
-public class PersistentQueue extends Obj implements IPersistentList, Collection{
+public class PersistentQueue extends Obj implements IPersistentList, Collection, Counted{ -final public static PersistentQueue EMPTY = new PersistentQueue(null, null, null);
+final public static PersistentQueue EMPTY = new PersistentQueue(null, 0, null, null); //*
+final int cnt; final ISeq f;
final PersistentVector r;
//static final int INITIAL_REAR_SIZE = 4;
int _hash = -1;
-PersistentQueue(IPersistentMap meta, ISeq f, PersistentVector r){
+PersistentQueue(IPersistentMap meta, int cnt, ISeq f, PersistentVector r){ super(meta);
+ this.cnt = cnt; this.f = f;
this.r = r;
}
@@ -93,11 +95,11 @@ public PersistentQueue pop(){ f1 = RT.seq(r);
r1 = null;
}
- return new PersistentQueue(meta(), f1, r1);
+ return new PersistentQueue(meta(), cnt - 1, f1, r1); }
public int count(){
- return RT.count(f) + RT.count(r);
+ return cnt; }
public ISeq seq(){
@@ -108,17 +110,17 @@ public ISeq seq(){ public PersistentQueue cons(Object o){
if(f == null) //empty
- return new PersistentQueue(meta(), RT.list(o), null);
+ return new PersistentQueue(meta(), cnt + 1, RT.list(o), null); else
- return new PersistentQueue(meta(), f, (r != null ? r : PersistentVector.EMPTY).cons(o));
+ return new PersistentQueue(meta(), cnt + 1, f, (r != null ? r : PersistentVector.EMPTY).cons(o)); }
public IPersistentCollection empty(){
- return EMPTY.withMeta(meta());
+ return EMPTY.withMeta(meta()); }
public PersistentQueue withMeta(IPersistentMap meta){
- return new PersistentQueue(meta, f, r);
+ return new PersistentQueue(meta, cnt, f, r); }
static class Seq extends ASeq{
diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index c0d3e4ce..97abd85a 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -29,189 +29,189 @@ import java.nio.charset.Charset; public class RT{ -static final public Boolean T = Boolean.TRUE;//Keyword.intern(Symbol.create(null, "t")); -static final public Boolean F = Boolean.FALSE;//Keyword.intern(Symbol.create(null, "t")); +static final public Boolean T = Boolean.TRUE;//Keyword.intern(Symbol.intern(null, "t")); +static final public Boolean F = Boolean.FALSE;//Keyword.intern(Symbol.intern(null, "t")); static final public String LOADER_SUFFIX = "__init"; //simple-symbol->class final static IPersistentMap DEFAULT_IMPORTS = map( -// Symbol.create("RT"), "clojure.lang.RT", -// Symbol.create("Num"), "clojure.lang.Num", -// Symbol.create("Symbol"), "clojure.lang.Symbol", -// Symbol.create("Keyword"), "clojure.lang.Keyword", -// Symbol.create("Var"), "clojure.lang.Var", -// Symbol.create("Ref"), "clojure.lang.Ref", -// Symbol.create("IFn"), "clojure.lang.IFn", -// Symbol.create("IObj"), "clojure.lang.IObj", -// Symbol.create("ISeq"), "clojure.lang.ISeq", -// Symbol.create("IPersistentCollection"), +// Symbol.intern("RT"), "clojure.lang.RT", +// Symbol.intern("Num"), "clojure.lang.Num", +// Symbol.intern("Symbol"), "clojure.lang.Symbol", +// Symbol.intern("Keyword"), "clojure.lang.Keyword", +// Symbol.intern("Var"), "clojure.lang.Var", +// Symbol.intern("Ref"), "clojure.lang.Ref", +// Symbol.intern("IFn"), "clojure.lang.IFn", +// Symbol.intern("IObj"), "clojure.lang.IObj", +// Symbol.intern("ISeq"), "clojure.lang.ISeq", +// Symbol.intern("IPersistentCollection"), // "clojure.lang.IPersistentCollection", -// Symbol.create("IPersistentMap"), "clojure.lang.IPersistentMap", -// Symbol.create("IPersistentList"), "clojure.lang.IPersistentList", -// Symbol.create("IPersistentVector"), "clojure.lang.IPersistentVector", -Symbol.create("Boolean"), Boolean.class, -Symbol.create("Byte"), Byte.class, -Symbol.create("Character"), Character.class, -Symbol.create("Class"), Class.class, -Symbol.create("ClassLoader"), ClassLoader.class, -Symbol.create("Compiler"), Compiler.class, -Symbol.create("Double"), Double.class, -Symbol.create("Enum"), Enum.class, -Symbol.create("Float"), Float.class, -Symbol.create("InheritableThreadLocal"), InheritableThreadLocal.class, -Symbol.create("Integer"), Integer.class, -Symbol.create("Long"), Long.class, -Symbol.create("Math"), Math.class, -Symbol.create("Number"), Number.class, -Symbol.create("Object"), Object.class, -Symbol.create("Package"), Package.class, -Symbol.create("Process"), Process.class, -Symbol.create("ProcessBuilder"), ProcessBuilder.class, -Symbol.create("Runtime"), Runtime.class, -Symbol.create("RuntimePermission"), RuntimePermission.class, -Symbol.create("SecurityManager"), SecurityManager.class, -Symbol.create("Short"), Short.class, -Symbol.create("StackTraceElement"), StackTraceElement.class, -Symbol.create("StrictMath"), StrictMath.class, -Symbol.create("String"), String.class, -Symbol.create("StringBuffer"), StringBuffer.class, -Symbol.create("StringBuilder"), StringBuilder.class, -Symbol.create("System"), System.class, -Symbol.create("Thread"), Thread.class, -Symbol.create("ThreadGroup"), ThreadGroup.class, -Symbol.create("ThreadLocal"), ThreadLocal.class, -Symbol.create("Throwable"), Throwable.class, -Symbol.create("Void"), Void.class, -Symbol.create("Appendable"), Appendable.class, -Symbol.create("CharSequence"), CharSequence.class, -Symbol.create("Cloneable"), Cloneable.class, -Symbol.create("Comparable"), Comparable.class, -Symbol.create("Iterable"), Iterable.class, -Symbol.create("Readable"), Readable.class, -Symbol.create("Runnable"), Runnable.class, -Symbol.create("Callable"), Callable.class, -Symbol.create("BigInteger"), BigInteger.class, -Symbol.create("BigDecimal"), BigDecimal.class, -Symbol.create("ArithmeticException"), ArithmeticException.class, -Symbol.create("ArrayIndexOutOfBoundsException"), ArrayIndexOutOfBoundsException.class, -Symbol.create("ArrayStoreException"), ArrayStoreException.class, -Symbol.create("ClassCastException"), ClassCastException.class, -Symbol.create("ClassNotFoundException"), ClassNotFoundException.class, -Symbol.create("CloneNotSupportedException"), CloneNotSupportedException.class, -Symbol.create("EnumConstantNotPresentException"), EnumConstantNotPresentException.class, -Symbol.create("Exception"), Exception.class, -Symbol.create("IllegalAccessException"), IllegalAccessException.class, -Symbol.create("IllegalArgumentException"), IllegalArgumentException.class, -Symbol.create("IllegalMonitorStateException"), IllegalMonitorStateException.class, -Symbol.create("IllegalStateException"), IllegalStateException.class, -Symbol.create("IllegalThreadStateException"), IllegalThreadStateException.class, -Symbol.create("IndexOutOfBoundsException"), IndexOutOfBoundsException.class, -Symbol.create("InstantiationException"), InstantiationException.class, -Symbol.create("InterruptedException"), InterruptedException.class, -Symbol.create("NegativeArraySizeException"), NegativeArraySizeException.class, -Symbol.create("NoSuchFieldException"), NoSuchFieldException.class, -Symbol.create("NoSuchMethodException"), NoSuchMethodException.class, -Symbol.create("NullPointerException"), NullPointerException.class, -Symbol.create("NumberFormatException"), NumberFormatException.class, -Symbol.create("RuntimeException"), RuntimeException.class, -Symbol.create("SecurityException"), SecurityException.class, -Symbol.create("StringIndexOutOfBoundsException"), StringIndexOutOfBoundsException.class, -Symbol.create("TypeNotPresentException"), TypeNotPresentException.class, -Symbol.create("UnsupportedOperationException"), UnsupportedOperationException.class, -Symbol.create("AbstractMethodError"), AbstractMethodError.class, -Symbol.create("AssertionError"), AssertionError.class, -Symbol.create("ClassCircularityError"), ClassCircularityError.class, -Symbol.create("ClassFormatError"), ClassFormatError.class, -Symbol.create("Error"), Error.class, -Symbol.create("ExceptionInInitializerError"), ExceptionInInitializerError.class, -Symbol.create("IllegalAccessError"), IllegalAccessError.class, -Symbol.create("IncompatibleClassChangeError"), IncompatibleClassChangeError.class, -Symbol.create("InstantiationError"), InstantiationError.class, -Symbol.create("InternalError"), InternalError.class, -Symbol.create("LinkageError"), LinkageError.class, -Symbol.create("NoClassDefFoundError"), NoClassDefFoundError.class, -Symbol.create("NoSuchFieldError"), NoSuchFieldError.class, -Symbol.create("NoSuchMethodError"), NoSuchMethodError.class, -Symbol.create("OutOfMemoryError"), OutOfMemoryError.class, -Symbol.create("StackOverflowError"), StackOverflowError.class, -Symbol.create("ThreadDeath"), ThreadDeath.class, -Symbol.create("UnknownError"), UnknownError.class, -Symbol.create("UnsatisfiedLinkError"), UnsatisfiedLinkError.class, -Symbol.create("UnsupportedClassVersionError"), UnsupportedClassVersionError.class, -Symbol.create("VerifyError"), VerifyError.class, -Symbol.create("VirtualMachineError"), VirtualMachineError.class, -Symbol.create("Thread$UncaughtExceptionHandler"), Thread.UncaughtExceptionHandler.class, -Symbol.create("Thread$State"), Thread.State.class, -Symbol.create("Deprecated"), Deprecated.class, -Symbol.create("Override"), Override.class, -Symbol.create("SuppressWarnings"), SuppressWarnings.class - -// Symbol.create("Collection"), "java.util.Collection", -// Symbol.create("Comparator"), "java.util.Comparator", -// Symbol.create("Enumeration"), "java.util.Enumeration", -// Symbol.create("EventListener"), "java.util.EventListener", -// Symbol.create("Formattable"), "java.util.Formattable", -// Symbol.create("Iterator"), "java.util.Iterator", -// Symbol.create("List"), "java.util.List", -// Symbol.create("ListIterator"), "java.util.ListIterator", -// Symbol.create("Map"), "java.util.Map", -// Symbol.create("Map$Entry"), "java.util.Map$Entry", -// Symbol.create("Observer"), "java.util.Observer", -// Symbol.create("Queue"), "java.util.Queue", -// Symbol.create("RandomAccess"), "java.util.RandomAccess", -// Symbol.create("Set"), "java.util.Set", -// Symbol.create("SortedMap"), "java.util.SortedMap", -// Symbol.create("SortedSet"), "java.util.SortedSet" +// Symbol.intern("IPersistentMap"), "clojure.lang.IPersistentMap", +// Symbol.intern("IPersistentList"), "clojure.lang.IPersistentList", +// Symbol.intern("IPersistentVector"), "clojure.lang.IPersistentVector", +Symbol.intern("Boolean"), Boolean.class, +Symbol.intern("Byte"), Byte.class, +Symbol.intern("Character"), Character.class, +Symbol.intern("Class"), Class.class, +Symbol.intern("ClassLoader"), ClassLoader.class, +Symbol.intern("Compiler"), Compiler.class, +Symbol.intern("Double"), Double.class, +Symbol.intern("Enum"), Enum.class, +Symbol.intern("Float"), Float.class, +Symbol.intern("InheritableThreadLocal"), InheritableThreadLocal.class, +Symbol.intern("Integer"), Integer.class, +Symbol.intern("Long"), Long.class, +Symbol.intern("Math"), Math.class, +Symbol.intern("Number"), Number.class, +Symbol.intern("Object"), Object.class, +Symbol.intern("Package"), Package.class, +Symbol.intern("Process"), Process.class, +Symbol.intern("ProcessBuilder"), ProcessBuilder.class, +Symbol.intern("Runtime"), Runtime.class, +Symbol.intern("RuntimePermission"), RuntimePermission.class, +Symbol.intern("SecurityManager"), SecurityManager.class, +Symbol.intern("Short"), Short.class, +Symbol.intern("StackTraceElement"), StackTraceElement.class, +Symbol.intern("StrictMath"), StrictMath.class, +Symbol.intern("String"), String.class, +Symbol.intern("StringBuffer"), StringBuffer.class, +Symbol.intern("StringBuilder"), StringBuilder.class, +Symbol.intern("System"), System.class, +Symbol.intern("Thread"), Thread.class, +Symbol.intern("ThreadGroup"), ThreadGroup.class, +Symbol.intern("ThreadLocal"), ThreadLocal.class, +Symbol.intern("Throwable"), Throwable.class, +Symbol.intern("Void"), Void.class, +Symbol.intern("Appendable"), Appendable.class, +Symbol.intern("CharSequence"), CharSequence.class, +Symbol.intern("Cloneable"), Cloneable.class, +Symbol.intern("Comparable"), Comparable.class, +Symbol.intern("Iterable"), Iterable.class, +Symbol.intern("Readable"), Readable.class, +Symbol.intern("Runnable"), Runnable.class, +Symbol.intern("Callable"), Callable.class, +Symbol.intern("BigInteger"), BigInteger.class, +Symbol.intern("BigDecimal"), BigDecimal.class, +Symbol.intern("ArithmeticException"), ArithmeticException.class, +Symbol.intern("ArrayIndexOutOfBoundsException"), ArrayIndexOutOfBoundsException.class, +Symbol.intern("ArrayStoreException"), ArrayStoreException.class, +Symbol.intern("ClassCastException"), ClassCastException.class, +Symbol.intern("ClassNotFoundException"), ClassNotFoundException.class, +Symbol.intern("CloneNotSupportedException"), CloneNotSupportedException.class, +Symbol.intern("EnumConstantNotPresentException"), EnumConstantNotPresentException.class, +Symbol.intern("Exception"), Exception.class, +Symbol.intern("IllegalAccessException"), IllegalAccessException.class, +Symbol.intern("IllegalArgumentException"), IllegalArgumentException.class, +Symbol.intern("IllegalMonitorStateException"), IllegalMonitorStateException.class, +Symbol.intern("IllegalStateException"), IllegalStateException.class, +Symbol.intern("IllegalThreadStateException"), IllegalThreadStateException.class, +Symbol.intern("IndexOutOfBoundsException"), IndexOutOfBoundsException.class, +Symbol.intern("InstantiationException"), InstantiationException.class, +Symbol.intern("InterruptedException"), InterruptedException.class, +Symbol.intern("NegativeArraySizeException"), NegativeArraySizeException.class, +Symbol.intern("NoSuchFieldException"), NoSuchFieldException.class, +Symbol.intern("NoSuchMethodException"), NoSuchMethodException.class, +Symbol.intern("NullPointerException"), NullPointerException.class, +Symbol.intern("NumberFormatException"), NumberFormatException.class, +Symbol.intern("RuntimeException"), RuntimeException.class, +Symbol.intern("SecurityException"), SecurityException.class, +Symbol.intern("StringIndexOutOfBoundsException"), StringIndexOutOfBoundsException.class, +Symbol.intern("TypeNotPresentException"), TypeNotPresentException.class, +Symbol.intern("UnsupportedOperationException"), UnsupportedOperationException.class, +Symbol.intern("AbstractMethodError"), AbstractMethodError.class, +Symbol.intern("AssertionError"), AssertionError.class, +Symbol.intern("ClassCircularityError"), ClassCircularityError.class, +Symbol.intern("ClassFormatError"), ClassFormatError.class, +Symbol.intern("Error"), Error.class, +Symbol.intern("ExceptionInInitializerError"), ExceptionInInitializerError.class, +Symbol.intern("IllegalAccessError"), IllegalAccessError.class, +Symbol.intern("IncompatibleClassChangeError"), IncompatibleClassChangeError.class, +Symbol.intern("InstantiationError"), InstantiationError.class, +Symbol.intern("InternalError"), InternalError.class, +Symbol.intern("LinkageError"), LinkageError.class, +Symbol.intern("NoClassDefFoundError"), NoClassDefFoundError.class, +Symbol.intern("NoSuchFieldError"), NoSuchFieldError.class, +Symbol.intern("NoSuchMethodError"), NoSuchMethodError.class, +Symbol.intern("OutOfMemoryError"), OutOfMemoryError.class, +Symbol.intern("StackOverflowError"), StackOverflowError.class, +Symbol.intern("ThreadDeath"), ThreadDeath.class, +Symbol.intern("UnknownError"), UnknownError.class, +Symbol.intern("UnsatisfiedLinkError"), UnsatisfiedLinkError.class, +Symbol.intern("UnsupportedClassVersionError"), UnsupportedClassVersionError.class, +Symbol.intern("VerifyError"), VerifyError.class, +Symbol.intern("VirtualMachineError"), VirtualMachineError.class, +Symbol.intern("Thread$UncaughtExceptionHandler"), Thread.UncaughtExceptionHandler.class, +Symbol.intern("Thread$State"), Thread.State.class, +Symbol.intern("Deprecated"), Deprecated.class, +Symbol.intern("Override"), Override.class, +Symbol.intern("SuppressWarnings"), SuppressWarnings.class + +// Symbol.intern("Collection"), "java.util.Collection", +// Symbol.intern("Comparator"), "java.util.Comparator", +// Symbol.intern("Enumeration"), "java.util.Enumeration", +// Symbol.intern("EventListener"), "java.util.EventListener", +// Symbol.intern("Formattable"), "java.util.Formattable", +// Symbol.intern("Iterator"), "java.util.Iterator", +// Symbol.intern("List"), "java.util.List", +// Symbol.intern("ListIterator"), "java.util.ListIterator", +// Symbol.intern("Map"), "java.util.Map", +// Symbol.intern("Map$Entry"), "java.util.Map$Entry", +// Symbol.intern("Observer"), "java.util.Observer", +// Symbol.intern("Queue"), "java.util.Queue", +// Symbol.intern("RandomAccess"), "java.util.RandomAccess", +// Symbol.intern("Set"), "java.util.Set", +// Symbol.intern("SortedMap"), "java.util.SortedMap", +// Symbol.intern("SortedSet"), "java.util.SortedSet" ); // single instance of UTF-8 Charset, so as to avoid catching UnsupportedCharsetExceptions everywhere static public Charset UTF8 = Charset.forName("UTF-8"); -static public final Namespace CLOJURE_NS = Namespace.findOrCreate(Symbol.create("clojure.core")); -//static final Namespace USER_NS = Namespace.findOrCreate(Symbol.create("user")); +static public final Namespace CLOJURE_NS = Namespace.findOrCreate(Symbol.intern("clojure.core")); +//static final Namespace USER_NS = Namespace.findOrCreate(Symbol.intern("user")); final static public Var OUT = - Var.intern(CLOJURE_NS, Symbol.create("*out*"), new OutputStreamWriter(System.out)); + Var.intern(CLOJURE_NS, Symbol.intern("*out*"), new OutputStreamWriter(System.out)); final static public Var IN = - Var.intern(CLOJURE_NS, Symbol.create("*in*"), + Var.intern(CLOJURE_NS, Symbol.intern("*in*"), new LineNumberingPushbackReader(new InputStreamReader(System.in))); final static public Var ERR = - Var.intern(CLOJURE_NS, Symbol.create("*err*"), + Var.intern(CLOJURE_NS, Symbol.intern("*err*"), new PrintWriter(new OutputStreamWriter(System.err), true)); final static Keyword TAG_KEY = Keyword.intern(null, "tag"); -final static public Var AGENT = Var.intern(CLOJURE_NS, Symbol.create("*agent*"), null); -final static public Var READEVAL = Var.intern(CLOJURE_NS, Symbol.create("*read-eval*"), T); -final static public Var ASSERT = Var.intern(CLOJURE_NS, Symbol.create("*assert*"), T); -final static public Var MATH_CONTEXT = Var.intern(CLOJURE_NS, Symbol.create("*math-context*"), null); +final static public Var AGENT = Var.intern(CLOJURE_NS, Symbol.intern("*agent*"), null); +final static public Var READEVAL = Var.intern(CLOJURE_NS, Symbol.intern("*read-eval*"), T); +final static public Var ASSERT = Var.intern(CLOJURE_NS, Symbol.intern("*assert*"), T); +final static public Var MATH_CONTEXT = Var.intern(CLOJURE_NS, Symbol.intern("*math-context*"), null); static Keyword LINE_KEY = Keyword.intern(null, "line"); static Keyword FILE_KEY = Keyword.intern(null, "file"); static Keyword DECLARED_KEY = Keyword.intern(null, "declared"); static Keyword DOC_KEY = Keyword.intern(null, "doc"); final static public Var USE_CONTEXT_CLASSLOADER = - Var.intern(CLOJURE_NS, Symbol.create("*use-context-classloader*"), T); -//final static public Var CURRENT_MODULE = Var.intern(Symbol.create("clojure.core", "current-module"), + Var.intern(CLOJURE_NS, Symbol.intern("*use-context-classloader*"), T); +//final static public Var CURRENT_MODULE = Var.intern(Symbol.intern("clojure.core", "current-module"), // Module.findOrCreateModule("clojure/user")); -final static Symbol LOAD_FILE = Symbol.create("load-file"); -final static Symbol IN_NAMESPACE = Symbol.create("in-ns"); -final static Symbol NAMESPACE = Symbol.create("ns"); -static final Symbol IDENTICAL = Symbol.create("identical?"); -final static Var CMD_LINE_ARGS = Var.intern(CLOJURE_NS, Symbol.create("*command-line-args*"), null); +final static Symbol LOAD_FILE = Symbol.intern("load-file"); +final static Symbol IN_NAMESPACE = Symbol.intern("in-ns"); +final static Symbol NAMESPACE = Symbol.intern("ns"); +static final Symbol IDENTICAL = Symbol.intern("identical?"); +final static Var CMD_LINE_ARGS = Var.intern(CLOJURE_NS, Symbol.intern("*command-line-args*"), null); //symbol -final public static Var CURRENT_NS = Var.intern(CLOJURE_NS, Symbol.create("*ns*"), +final public static Var CURRENT_NS = Var.intern(CLOJURE_NS, Symbol.intern("*ns*"), CLOJURE_NS); -final static Var FLUSH_ON_NEWLINE = Var.intern(CLOJURE_NS, Symbol.create("*flush-on-newline*"), T); -final static Var PRINT_META = Var.intern(CLOJURE_NS, Symbol.create("*print-meta*"), F); -final static Var PRINT_READABLY = Var.intern(CLOJURE_NS, Symbol.create("*print-readably*"), T); -final static Var PRINT_DUP = Var.intern(CLOJURE_NS, Symbol.create("*print-dup*"), F); -final static Var WARN_ON_REFLECTION = Var.intern(CLOJURE_NS, Symbol.create("*warn-on-reflection*"), F); -final static Var ALLOW_UNRESOLVED_VARS = Var.intern(CLOJURE_NS, Symbol.create("*allow-unresolved-vars*"), F); - -final static Var IN_NS_VAR = Var.intern(CLOJURE_NS, Symbol.create("in-ns"), F); -final static Var NS_VAR = Var.intern(CLOJURE_NS, Symbol.create("ns"), F); -static final Var PRINT_INITIALIZED = Var.intern(CLOJURE_NS, Symbol.create("print-initialized")); -static final Var PR_ON = Var.intern(CLOJURE_NS, Symbol.create("pr-on")); -//final static Var IMPORTS = Var.intern(CLOJURE_NS, Symbol.create("*imports*"), DEFAULT_IMPORTS); +final static Var FLUSH_ON_NEWLINE = Var.intern(CLOJURE_NS, Symbol.intern("*flush-on-newline*"), T); +final static Var PRINT_META = Var.intern(CLOJURE_NS, Symbol.intern("*print-meta*"), F); +final static Var PRINT_READABLY = Var.intern(CLOJURE_NS, Symbol.intern("*print-readably*"), T); +final static Var PRINT_DUP = Var.intern(CLOJURE_NS, Symbol.intern("*print-dup*"), F); +final static Var WARN_ON_REFLECTION = Var.intern(CLOJURE_NS, Symbol.intern("*warn-on-reflection*"), F); +final static Var ALLOW_UNRESOLVED_VARS = Var.intern(CLOJURE_NS, Symbol.intern("*allow-unresolved-vars*"), F); + +final static Var IN_NS_VAR = Var.intern(CLOJURE_NS, Symbol.intern("in-ns"), F); +final static Var NS_VAR = Var.intern(CLOJURE_NS, Symbol.intern("ns"), F); +static final Var PRINT_INITIALIZED = Var.intern(CLOJURE_NS, Symbol.intern("print-initialized")); +static final Var PR_ON = Var.intern(CLOJURE_NS, Symbol.intern("pr-on")); +//final static Var IMPORTS = Var.intern(CLOJURE_NS, Symbol.intern("*imports*"), DEFAULT_IMPORTS); final static IFn inNamespace = new AFn(){ public Object invoke(Object arg1) throws Exception{ Symbol nsname = (Symbol) arg1; @@ -278,12 +278,12 @@ static public void addURL(Object url) throws Exception{ static{ Keyword arglistskw = Keyword.intern(null, "arglists"); - Symbol namesym = Symbol.create("name"); - OUT.setTag(Symbol.create("java.io.Writer")); - CURRENT_NS.setTag(Symbol.create("clojure.lang.Namespace")); + Symbol namesym = Symbol.intern("name"); + OUT.setTag(Symbol.intern("java.io.Writer")); + CURRENT_NS.setTag(Symbol.intern("clojure.lang.Namespace")); AGENT.setMeta(map(DOC_KEY, "The agent currently running an action on this thread, else nil")); - AGENT.setTag(Symbol.create("clojure.lang.Agent")); - MATH_CONTEXT.setTag(Symbol.create("java.math.MathContext")); + AGENT.setTag(Symbol.intern("clojure.lang.Agent")); + MATH_CONTEXT.setTag(Symbol.intern("java.math.MathContext")); Var nv = Var.intern(CLOJURE_NS, NAMESPACE, bootNamespace); nv.setMacro(); Var v; @@ -419,8 +419,8 @@ static void doInit() throws Exception{ RT.map(CURRENT_NS, CURRENT_NS.deref(), WARN_ON_REFLECTION, WARN_ON_REFLECTION.deref())); try { - Symbol USER = Symbol.create("user"); - Symbol CLOJURE = Symbol.create("clojure.core"); + Symbol USER = Symbol.intern("user"); + Symbol CLOJURE = Symbol.intern("clojure.core"); Var in_ns = var("clojure.core", "in-ns"); Var refer = var("clojure.core", "refer"); diff --git a/src/jvm/clojure/lang/Symbol.java b/src/jvm/clojure/lang/Symbol.java index dbf3b36e..247f4b36 100644 --- a/src/jvm/clojure/lang/Symbol.java +++ b/src/jvm/clojure/lang/Symbol.java @@ -49,14 +49,6 @@ static public Symbol intern(String nsname){ return new Symbol(nsname.substring(0, i).intern(), nsname.substring(i + 1).intern()); } -static public Symbol create(String name_interned){ - return new Symbol(null, name_interned); -} - -static public Symbol create(String ns_interned, String name_interned){ - return new Symbol(ns_interned, name_interned); -} - private Symbol(String ns_interned, String name_interned){ this.name = name_interned; this.ns = ns_interned; diff --git a/src/jvm/clojure/lang/Var.java b/src/jvm/clojure/lang/Var.java index 6df652b0..ca3b9533 100644 --- a/src/jvm/clojure/lang/Var.java +++ b/src/jvm/clojure/lang/Var.java @@ -100,10 +100,10 @@ public String toString(){ public static Var find(Symbol nsQualifiedSym){ if(nsQualifiedSym.ns == null) throw new IllegalArgumentException("Symbol must be namespace-qualified"); - Namespace ns = Namespace.find(Symbol.create(nsQualifiedSym.ns)); + Namespace ns = Namespace.find(Symbol.intern(nsQualifiedSym.ns)); if(ns == null) throw new IllegalArgumentException("No such namespace: " + nsQualifiedSym.ns); - return ns.findInternedVar(Symbol.create(nsQualifiedSym.name)); + return ns.findInternedVar(Symbol.intern(nsQualifiedSym.name)); } public static Var intern(Symbol nsName, Symbol sym){ diff --git a/test/clojure/test_clojure.clj b/test/clojure/test_clojure.clj index a82ed0ae..2f3fc4f8 100644 --- a/test/clojure/test_clojure.clj +++ b/test/clojure/test_clojure.clj @@ -65,6 +65,7 @@ :def :keywords :data + :reflect ]) (def test-namespaces diff --git a/test/clojure/test_clojure/data_structures.clj b/test/clojure/test_clojure/data_structures.clj index a1f5b825..7679b2b6 100644 --- a/test/clojure/test_clojure/data_structures.clj +++ b/test/clojure/test_clojure/data_structures.clj @@ -112,40 +112,45 @@ ;; *** Collections *** (deftest test-count - (are [x y] (= x y) - (count nil) 0 - - (count ()) 0 - (count '(1)) 1 - (count '(1 2 3)) 3 - - (count []) 0 - (count [1]) 1 - (count [1 2 3]) 3 - - (count #{}) 0 - (count #{1}) 1 - (count #{1 2 3}) 3 - - (count {}) 0 - (count {:a 1}) 1 - (count {:a 1 :b 2 :c 3}) 3 - - (count "") 0 - (count "a") 1 - (count "abc") 3 - - (count (into-array [])) 0 - (count (into-array [1])) 1 - (count (into-array [1 2 3])) 3 - - (count (java.util.ArrayList. [])) 0 - (count (java.util.ArrayList. [1])) 1 - (count (java.util.ArrayList. [1 2 3])) 3 - - (count (java.util.HashMap. {})) 0 - (count (java.util.HashMap. {:a 1})) 1 - (count (java.util.HashMap. {:a 1 :b 2 :c 3})) 3 ) + (let [EMPTY clojure.lang.PersistentQueue/EMPTY] + (are [x y] (= (count x) y) + EMPTY 0 + (into EMPTY [:a :b]) 2 + (-> (into EMPTY [:a :b]) pop pop) 0 + + nil 0 + + () 0 + '(1) 1 + '(1 2 3) 3 + + [] 0 + [1] 1 + [1 2 3] 3 + + #{} 0 + #{1} 1 + #{1 2 3} 3 + + {} 0 + {:a 1} 1 + {:a 1 :b 2 :c 3} 3 + + "" 0 + "a" 1 + "abc" 3 + + (into-array []) 0 + (into-array [1]) 1 + (into-array [1 2 3]) 3 + + (java.util.ArrayList. []) 0 + (java.util.ArrayList. [1]) 1 + (java.util.ArrayList. [1 2 3]) 3 + + (java.util.HashMap. {}) 0 + (java.util.HashMap. {:a 1}) 1 + (java.util.HashMap. {:a 1 :b 2 :c 3}) 3 )) ; different types (are [x] (= (count [x]) 1) diff --git a/test/clojure/test_clojure/ns_libs.clj b/test/clojure/test_clojure/ns_libs.clj index 75d8ce1e..37afacb3 100644 --- a/test/clojure/test_clojure/ns_libs.clj +++ b/test/clojure/test_clojure/ns_libs.clj @@ -73,6 +73,14 @@ #"Integer already refers to: class java.lang.Integer" (defrecord Integer []))))) +(deftest resolution + (let [s (gensym)] + (are [result expr] (= result expr) + #'clojure.core/first (ns-resolve 'clojure.core 'first) + nil (ns-resolve 'clojure.core s) + nil (ns-resolve 'clojure.core {'first :local-first} 'first) + nil (ns-resolve 'clojure.core {'first :local-first} s)))) + (deftest refer-error-messages (let [temp-ns (gensym)] (binding [*ns* *ns*] diff --git a/test/clojure/test_clojure/reflect.clj b/test/clojure/test_clojure/reflect.clj new file mode 100644 index 00000000..416092ac --- /dev/null +++ b/test/clojure/test_clojure/reflect.clj @@ -0,0 +1,33 @@ +(ns clojure.test-clojure.reflect + (:use clojure.data [clojure.reflect :as reflect] clojure.test clojure.pprint) + (:import [clojure.reflect AsmReflector JavaReflector])) + +(defn nodiff + [x y] + (let [[x-only y-only common] (diff x y)] + (when (or x-only y-only) + (is false (with-out-str (pprint {:x-only x-only + :y-only y-only + :common common})))))) + +(deftest compare-reflect-and-asm + (let [cl (.getContextClassLoader (Thread/currentThread)) + asm-reflector (AsmReflector. cl) + java-reflector (JavaReflector. cl)] + (doseq [classname '[java.lang.Runnable + java.lang.Object + java.io.FileInputStream + clojure.lang.Compiler + clojure.lang.PersistentVector]] + (nodiff (type-reflect classname :reflector asm-reflector) + (type-reflect classname :reflector java-reflector))))) + +(deftest field-descriptor->class-symbol-test + (are [s d] (= s (@#'reflect/field-descriptor->class-symbol d)) + 'clojure.asm.Type<><> "[[Lclojure/asm/Type;" + 'int "I" + 'java.lang.Object "Ljava.lang.Object;")) + +(deftest internal-name->class-symbol-test + (are [s n] (= s (@#'reflect/internal-name->class-symbol n)) + 'java.lang.Exception "java/lang/Exception")) |