Created
January 23, 2020 08:23
-
-
Save Col-E/05f74bd0ee6f5716a394e0cb6c615667 to your computer and use it in GitHub Desktop.
Simulation Draft
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sim; | |
import java.util.Stack; | |
/** | |
* Method invoke context. | |
*/ | |
public class Context { | |
private final VirtualValue<?>[] locals; | |
private final Stack<VirtualValue<?>> stack = new Stack<>(); | |
private final Context parent; | |
private final VirtualMethod method; | |
public Context(Context parent, VirtualMethod method) { | |
this.locals = new VirtualValue<?>[method.resolve().maxLocals]; | |
this.parent = parent; | |
this.method = method; | |
} | |
/** | |
* @return Context for the prior method in the call-stack. | |
*/ | |
public Context getParent() { | |
return parent; | |
} | |
/** | |
* @return Method this context pertains to. | |
*/ | |
public VirtualMethod getMethod() { | |
return method; | |
} | |
/** | |
* @return Local variables. | |
*/ | |
public VirtualValue<?>[] getLocals() { | |
return locals; | |
} | |
/** | |
* @return Stack values. | |
*/ | |
public Stack<VirtualValue<?>> getStack() { | |
return stack; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sim; | |
/** | |
* Identifiable member, field or method. | |
*/ | |
public interface Identifiable { | |
String getName(); | |
String getDescriptor(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sim; | |
import org.objectweb.asm.tree.MethodNode; | |
/** | |
* Runnable type, implying this type resolves to a method-node and has a class parent. | |
*/ | |
public interface Invokable extends Identifiable, Resolvable<MethodNode, VirtualClass> { | |
/** | |
* @param ctx Starting context. | |
* @return Return value of method. | |
*/ | |
default VirtualValue<?> invoke(Context ctx) { | |
// TODO: Method simulation logic goes here | |
return null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sim; | |
import org.objectweb.asm.Type; | |
public class ObjectFactory { | |
public static <V> VirtualValue<V> create(String descriptor) { | |
Type type = Type.getType(descriptor); | |
if (type.getSort() < Type.ARRAY) { | |
// primitive, default to 0 | |
return new VirtualValue<V>(type, (V) Integer.valueOf(0)); | |
} else { | |
// TODO: May want special cases for different types? | |
// object, default to null | |
return new VirtualValue<V>(type, null); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sim; | |
/** | |
* Item can resolve links to relevant data types. | |
* | |
* @param <R> Type to resolve to. | |
* @param <P> Resolvable parent type. | |
*/ | |
public interface Resolvable<R, P> { | |
P parent(); | |
R resolve(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sim; | |
/** | |
* Runs a method in a class. | |
*/ | |
public class Simulation { | |
private final VirtualClass startClass; | |
private final VirtualMethod startMethod; | |
public Simulation(VirtualClass clazz, VirtualMethod method) { | |
this.startClass = clazz; | |
this.startMethod = method; | |
} | |
/** | |
* @param args | |
* Array of locals to use as the initial context. | |
* @return Execution result. | |
*/ | |
public VirtualValue<?> run(VirtualValue<?> ... args) { | |
Context ctx = new Context(null, startMethod); | |
int index = 0; | |
for (VirtualValue<?> arg : args) { | |
ctx.getLocals()[index] = arg; | |
index += arg.getType().getSize(); | |
} | |
return startMethod.invoke(ctx); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sim; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Optional; | |
import org.objectweb.asm.Type; | |
import org.objectweb.asm.tree.ClassNode; | |
/** | |
* Class type wrapper. | |
*/ | |
public class VirtualClass extends VirtualValue<Object> implements Resolvable<ClassNode, Object> { | |
private final List<VirtualField<?>> fields = new ArrayList<>(); | |
private final List<VirtualMethod> methods = new ArrayList<>(); | |
public VirtualClass(Type type) { | |
super(type, null); | |
// TODO: Populate fields & methods | |
// - Cache the fetched values so other VirtualClass instances can grab them too | |
// without having to do a lookup every time | |
} | |
public List<VirtualField<?>> getFields() { | |
return fields; | |
} | |
public List<VirtualMethod> getMethods() { | |
return methods; | |
} | |
public Optional<VirtualField<?>> getField(String name, String descriptor) { | |
return fields.stream() | |
.filter(vf -> vf.getName().equals(name) && vf.getDescriptor().equals(descriptor)) | |
.findFirst(); | |
} | |
public Optional<VirtualMethod> getMethod(String name, String descriptor) { | |
return methods.stream() | |
.filter(vm -> vm.getName().equals(name) && vm.getDescriptor().equals(descriptor)) | |
.findFirst(); | |
} | |
@Override | |
public Object parent() { | |
return null; | |
} | |
@Override | |
public ClassNode resolve() { | |
// TODO: Fetch classnode instance | |
return null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sim; | |
import org.objectweb.asm.tree.ClassNode; | |
import org.objectweb.asm.tree.FieldNode; | |
/** | |
* Field wrapper. | |
* | |
* @param <T> Object value type. | |
*/ | |
public class VirtualField<T> extends VirtualMember<FieldNode> { | |
private final VirtualValue<T> value; | |
public VirtualField(VirtualClass owner, String name, String descriptor) { | |
super(owner, name, descriptor); | |
this.value = ObjectFactory.create(descriptor); | |
} | |
public VirtualValue<T> getValue() { | |
return value; | |
} | |
@Override | |
public FieldNode resolve() { | |
ClassNode owner = parent().resolve(); | |
for (FieldNode fn : owner.fields) | |
if (fn.name.endsWith(getName()) && fn.desc.equals(getDescriptor())) | |
return fn; | |
return null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sim; | |
/** | |
* Generic member wrapper. | |
* | |
* @param <R> Type to resolve to. | |
*/ | |
public abstract class VirtualMember<R> implements Resolvable<R, VirtualClass>, Identifiable { | |
private final VirtualClass owner; | |
private final String name; | |
private final String descriptor; | |
public VirtualMember(VirtualClass owner, String name, String descriptor) { | |
this.owner = owner; | |
this.name = name; | |
this.descriptor = descriptor; | |
} | |
public VirtualClass getOwner() { | |
return owner; | |
} | |
@Override | |
public String getName() { | |
return name; | |
} | |
@Override | |
public String getDescriptor() { | |
return descriptor; | |
} | |
@Override | |
public VirtualClass parent() { | |
return owner; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sim; | |
import org.objectweb.asm.tree.ClassNode; | |
import org.objectweb.asm.tree.MethodNode; | |
/** | |
* Method wrapper. | |
*/ | |
public class VirtualMethod extends VirtualMember<MethodNode> implements Invokable { | |
public VirtualMethod(VirtualClass owner, String name, String descriptor) { | |
super(owner, name, descriptor); | |
} | |
@Override | |
public MethodNode resolve() { | |
ClassNode owner = parent().resolve(); | |
for (MethodNode mn : owner.methods) | |
if (mn.name.endsWith(getName()) && mn.desc.equals(getDescriptor())) | |
return mn; | |
return null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sim; | |
import org.objectweb.asm.Type; | |
/** | |
* Value wrapper. | |
* | |
* @param <V> Wrapped value type. | |
*/ | |
public class VirtualValue<V> { | |
private final Type type; | |
private V value; | |
public VirtualValue(Type type, V value) { | |
this.type = type; | |
this.value = value; | |
} | |
public Type getType() { | |
return type; | |
} | |
public V getValue() { | |
return value; | |
} | |
public void setValue(V value) { | |
this.value = value; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment