summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-04-05 22:30:01 +0000
committerRich Hickey <richhickey@gmail.com>2008-04-05 22:30:01 +0000
commitee2250dd7a5b6d6c99d276fa333ca663a555f5e8 (patch)
treeed1bcbcd6d55013f2ca88c470a82b98866a55ac5 /src
parentdd837d94fca1f502f62def7d734d98bff3b0b20a (diff)
phase 2 enhanced host calls, (.member target ...), (target.member ...), and (classname. ctor-args) macroexpansions
Diffstat (limited to 'src')
-rw-r--r--src/boot.clj14
-rw-r--r--src/jvm/clojure/lang/Compiler.java62
2 files changed, 58 insertions, 18 deletions
diff --git a/src/boot.clj b/src/boot.clj
index 208db231..a0bd71ae 100644
--- a/src/boot.clj
+++ b/src/boot.clj
@@ -1587,21 +1587,17 @@ not-every? (comp not every?))
"If form represents a macro form, returns its expansion,
else returns form."
[form]
- (let [v (and (seq? form) (. clojure.lang.Compiler (isMacro (first form))))]
- (if v
- (apply @v (rest form))
- form)))
+ (. clojure.lang.Compiler (macroexpand1 form)))
(defn macroexpand
"Repeatedly calls macroexpand-1 on form until it no longer
represents a macro form, then returns it. Note neither
macroexpand-1 nor macroexpand expand macros in subforms."
[form]
- (let [ex (macroexpand-1 form)
- v (and (seq? ex) (. clojure.lang.Compiler (isMacro (first ex))))]
- (if v
- (macroexpand ex)
- ex)))
+ (let [ex (macroexpand-1 form)]
+ (if (identical? ex form)
+ form
+ (macroexpand ex))))
(defn create-struct
"Returns a structure basis object."
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index 15b7afcf..f18a9602 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -698,7 +698,7 @@ static public abstract class HostExpr implements Expr{
}
else
{
- ISeq call = (ISeq) ((RT.third(form) instanceof ISeq)?RT.third(form):RT.rest(RT.rest(form)));
+ ISeq call = (ISeq) ((RT.third(form) instanceof ISeq) ? RT.third(form) : RT.rest(RT.rest(form)));
if(!(RT.first(call) instanceof Symbol))
throw new IllegalArgumentException("Malformed member expression");
Symbol sym = (Symbol) RT.first(call);
@@ -3341,15 +3341,13 @@ static public Var isMacro(Object op) throws Exception{
return null;
}
-private static Expr analyzeSeq(C context, ISeq form, String name) throws Exception{
- Integer line = (Integer) LINE.get();
- try
+public static Object macroexpand1(Object x) throws Exception{
+ if(x instanceof ISeq)
{
- if(RT.meta(form) != null && RT.meta(form).containsKey(RT.LINE_KEY))
- line = (Integer) RT.meta(form).valAt(RT.LINE_KEY);
- Var.pushThreadBindings(
- RT.map(LINE, line));
+ ISeq form = (ISeq) x;
Object op = RT.first(form);
+ if(isSpecial(op))
+ return x;
//macro expansion
Var v = isMacro(op);
if(v != null)
@@ -3357,13 +3355,59 @@ private static Expr analyzeSeq(C context, ISeq form, String name) throws Excepti
try
{
Var.pushThreadBindings(RT.map(RT.MACRO_META, ((IObj) form).meta()));
- return analyze(context, v.applyTo(form.rest()));
+ return v.applyTo(form.rest());
}
finally
{
Var.popThreadBindings();
}
}
+ else
+ {
+ if(op instanceof Symbol)
+ {
+ Symbol sym = (Symbol) op;
+ String sname = sym.name;
+ //(.substring s 2 5) => (. s substring 2 5)
+ if(sym.name.charAt(0) == '.')
+ {
+ Symbol meth = Symbol.intern(sname.substring(1));
+ return RT.listStar(DOT, RT.second(form), meth, form.rest().rest());
+ }
+ else
+ {
+ //(s.substring 2 5) => (. s substring 2 5)
+ int idx = sname.indexOf('.');
+ if(idx > 0 && idx < sname.length() - 1 && idx == sname.lastIndexOf('.'))
+ {
+ Symbol target = Symbol.intern(sname.substring(0, idx));
+ Symbol meth = Symbol.intern(sname.substring(idx + 1));
+ return RT.listStar(DOT, target, meth, form.rest());
+ }
+ //(StringBuilder. "foo") => (new StringBuilder "foo")
+ else if(idx == sname.length() - 1)
+ return RT.listStar(NEW, Symbol.intern(sname.substring(0, idx)), form.rest());
+ }
+ }
+ }
+ }
+ return x;
+}
+
+private static Expr analyzeSeq(C context, ISeq form, String name) throws Exception{
+ Integer line = (Integer) LINE.get();
+ try
+ {
+ if(RT.meta(form) != null && RT.meta(form).containsKey(RT.LINE_KEY))
+ line = (Integer) RT.meta(form).valAt(RT.LINE_KEY);
+ Var.pushThreadBindings(
+ RT.map(LINE, line));
+
+ Object me = macroexpand1(form);
+ if(me != form)
+ return analyze(context, me);
+
+ Object op = RT.first(form);
IParser p;
if(op.equals(FN))
return FnExpr.parse(context, form, name);