class Foo{
private final Object obj0;
private final Object obj1;
private final Object def;
Public Foo(obj0,obj1,def){
this.obj0 = obj0;
this.obj1 = obj1;
this.def = def;
}
public int foo(long v){
if (v==0) return obj0;
else if (v==1) return obj1;
else return def;
}
}
I now want to redefine method Foo.foo
and add a case at runtime:
class Foo{
private final Object obj0;
private final Object obj1;
private final Object def;
Public Foo(obj0,obj1,def){
this.obj0 = obj0;
this.obj1 = obj1;
this.def = def;
}
public int foo(long v){
if (v==0) return obj0;
else if (v==1) return obj1;
else if (v==2) return obj2_fixed_when_added;
else return def;
}
}
Now conceptually this sounds pretty easy. In pseudo code:
visit method Foo.foo{
boolean transformed = false;
for(stmt : Foo.foo.body){
if (transformed || stmt is not if){
emit unchanged
}else if (stmt is IF){
visit if-clause
visit else-clause
emit IF
}else{
emit new ELSIF for case v==2
emit stmt unchanged
transformed = true;
}
}
}
Problem then is that we're working with bytecode and the AST doesn't really deal with statements, let alone IF abstractions.
So what I can do in this case is use the fact that all the guards are mutually exclusive and each case returns on its own and just redefine the method like
public int foo(long v){
if (v==2) return obj2_fixed_when_added;
if (v==0) return obj0;
else if (v==1) return obj1;
else return def;
}
which is basically
visit method Foo.foo{
emit new IF for v==2
emit rest of method body unchanged
}
Crude, but does the job, I guess, and we can now reload the class to make the changes available.
The problem then becomes the
return obj2_fixed_when_added;
If I can just create a new Instance of whatever obj2_fixed_when_added
is, I'd do so.
However, what do I do if I can not and want to set it to one specific Object the transformer generates as he inserts the new IF?
Aucun commentaire:
Enregistrer un commentaire