summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2007-09-03 22:31:49 +0000
committerRich Hickey <richhickey@gmail.com>2007-09-03 22:31:49 +0000
commitc0b1333eb25fea97a04de528d5c8f612bd098e89 (patch)
tree7d71596545f0a3e6f983b1f27eaa1b6eb6347d72 /src
parenta51a104cfff59b7b27628dcc66885d712510879f (diff)
added assign, support rebinding of Var via set
Diffstat (limited to 'src')
-rw-r--r--src/jvm/clojure/lang/BytecodeCompiler.java38
-rw-r--r--src/jvm/clojure/lang/Var.java7
2 files changed, 40 insertions, 5 deletions
diff --git a/src/jvm/clojure/lang/BytecodeCompiler.java b/src/jvm/clojure/lang/BytecodeCompiler.java
index 1dd51e80..3412fbb8 100644
--- a/src/jvm/clojure/lang/BytecodeCompiler.java
+++ b/src/jvm/clojure/lang/BytecodeCompiler.java
@@ -152,6 +152,34 @@ static class DefExpr implements Expr{
}
}
+static class AssignExpr implements Expr{
+ final AssignableExpr target;
+ final Expr val;
+
+
+ public AssignExpr(AssignableExpr target, Expr val){
+ this.target = target;
+ this.val = val;
+ }
+
+ public Object eval() throws Exception{
+ return target.evalAssign(val);
+ }
+
+ public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ target.emitAssign(context, fn, gen, val);
+ }
+
+ public static Expr parse(C context, ISeq form) throws Exception{
+ if(RT.length(form) != 3)
+ throw new IllegalArgumentException("Malformed assignment, expecting (= target val)");
+ Expr target = analyze(C.EXPRESSION, RT.second(form));
+ if(!(target instanceof AssignableExpr))
+ throw new IllegalArgumentException("Invalid assignment target");
+ return new AssignExpr((AssignableExpr) target, analyze(C.EXPRESSION, RT.third(form)));
+ }
+}
+
static class VarExpr implements Expr, AssignableExpr{
final Var var;
final Symbol tag;
@@ -180,7 +208,7 @@ static class VarExpr implements Expr, AssignableExpr{
}
public void emitAssign(C context, FnExpr fn, GeneratorAdapter gen,
- Expr val) throws Exception{
+ Expr val){
fn.emitVar(gen, var);
val.emit(C.EXPRESSION, fn, gen);
gen.invokeVirtual(VAR_TYPE, setMethod);
@@ -243,7 +271,7 @@ static abstract class LiteralExpr implements Expr{
static interface AssignableExpr{
Object evalAssign(Expr val) throws Exception;
- void emitAssign(C context, FnExpr fn, GeneratorAdapter gen, Expr val) throws Exception;
+ void emitAssign(C context, FnExpr fn, GeneratorAdapter gen, Expr val);
}
static abstract class HostExpr implements Expr{
@@ -330,7 +358,7 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{
}
public void emitAssign(C context, FnExpr fn, GeneratorAdapter gen,
- Expr val) throws Exception{
+ Expr val){
target.emit(C.EXPRESSION, fn, gen);
gen.push(fieldName);
val.emit(C.EXPRESSION, fn, gen);
@@ -367,7 +395,7 @@ static class StaticFieldExpr extends FieldExpr implements AssignableExpr{
}
public void emitAssign(C context, FnExpr fn, GeneratorAdapter gen,
- Expr val) throws Exception{
+ Expr val){
gen.push(className);
gen.push(fieldName);
val.emit(C.EXPRESSION, fn, gen);
@@ -1372,6 +1400,8 @@ private static Expr analyzeSeq(C context, ISeq form, String name) throws Excepti
return HostExpr.parse(context, form);
else if(op.equals(THE_VAR))
return TheVarExpr.parse(context, form);
+ else if(op.equals(ASSIGN))
+ return AssignExpr.parse(context, form);
else
return InvokeExpr.parse(context, form);
}
diff --git a/src/jvm/clojure/lang/Var.java b/src/jvm/clojure/lang/Var.java
index 42ecde91..267bc7ee 100644
--- a/src/jvm/clojure/lang/Var.java
+++ b/src/jvm/clojure/lang/Var.java
@@ -124,7 +124,12 @@ public Object set(Object val){
Box b = getThreadBinding();
if(b != null)
return (b.val = val);
- throw new IllegalStateException(String.format("Can't change root binding of: %s with set", sym));
+ if(hasRoot())
+ {
+ bindRoot(val);
+ return val;
+ }
+ throw new IllegalStateException(String.format("Can't establish root binding of: %s with set", sym));
}
public Object getRoot(){