package org.rascalmpl.interpreter.cursors; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import org.rascalmpl.value.IBool; import org.rascalmpl.value.IConstructor; import org.rascalmpl.value.IDateTime; import org.rascalmpl.value.IExternalValue; import org.rascalmpl.value.IInteger; import org.rascalmpl.value.IList; import org.rascalmpl.value.IMap; import org.rascalmpl.value.INode; import org.rascalmpl.value.INumber; import org.rascalmpl.value.IRational; import org.rascalmpl.value.IReal; import org.rascalmpl.value.ISet; import org.rascalmpl.value.ISourceLocation; import org.rascalmpl.value.IString; import org.rascalmpl.value.IValue; import org.rascalmpl.value.type.ITypeVisitor; import org.rascalmpl.value.type.Type; public class CursorFactory implements ITypeVisitor<IValue, RuntimeException> { public static IValue makeCursor(IValue value, Context ctx) { CursorFactory fact = new CursorFactory(value, ctx); return value.getType().accept(fact); } private static class AtomCursor extends Cursor implements InvocationHandler { public AtomCursor(IValue value) { super(value); } public AtomCursor(IValue value, Context ctx) { super(value, ctx); } @Override public boolean equals(Object obj) { return getWrappedValue().equals(obj); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String name = method.getName(); if (name.equals("up") || name.equals("root") || name.equals("getCtx") || name.equals("getWrappedValue") || name.equals("toString")) { return method.invoke(this, args); } return method.invoke(getWrappedValue(), args); } } private static IValue atomCursor(Class<? extends IValue> cls, IValue value, Context ctx) { return (IValue) Proxy.newProxyInstance(CursorFactory.class.getClassLoader(), new Class[]{cls, ICursor.class}, new AtomCursor(value, ctx)); } private IValue value; private Context ctx; private CursorFactory(IValue value, Context ctx) { this.value = value; this.ctx = ctx; } @Override public IValue visitReal(Type type) throws RuntimeException { return atomCursor(IReal.class, value, ctx); } @Override public IValue visitInteger(Type type) throws RuntimeException { return atomCursor(IInteger.class, value, ctx); } @Override public IValue visitRational(Type type) throws RuntimeException { return atomCursor(IRational.class, value, ctx); } @Override public IValue visitList(Type type) throws RuntimeException { return new ListCursor((IList) value, ctx); } @Override public IValue visitMap(Type type) throws RuntimeException { return new MapCursor((IMap)value, ctx); } @Override public IValue visitNumber(Type type) throws RuntimeException { return atomCursor(INumber.class, value, ctx); } @Override public IValue visitAlias(Type type) throws RuntimeException { return type.getAliased().accept(this); } @Override public IValue visitSet(Type type) throws RuntimeException { return new SetCursor((ISet) value, ctx); } @Override public IValue visitSourceLocation(Type type) throws RuntimeException { return atomCursor(ISourceLocation.class, value, ctx); } @Override public IValue visitString(Type type) throws RuntimeException { return atomCursor(IString.class, value, ctx); } @Override public IValue visitNode(Type type) throws RuntimeException { return new NodeCursor((INode)value, ctx); } @Override public IValue visitConstructor(Type type) throws RuntimeException { return new ConstructorCursor((IConstructor)value, ctx); } @Override public IValue visitAbstractData(Type type) throws RuntimeException { return new ConstructorCursor((IConstructor)value, ctx); } @Override public IValue visitTuple(Type type) throws RuntimeException { return new TupleCursor(value, ctx); } @Override public IValue visitValue(Type type) throws RuntimeException { return value; } @Override public IValue visitVoid(Type type) throws RuntimeException { return value; } @Override public IValue visitBool(Type type) throws RuntimeException { return atomCursor(IBool.class, value, ctx); } @Override public IValue visitParameter(Type type) throws RuntimeException { return value; } @Override public IValue visitExternal(Type type) throws RuntimeException { return atomCursor(IExternalValue.class, value, ctx); } @Override public IValue visitDateTime(Type type) throws RuntimeException { return atomCursor(IDateTime.class, value, ctx); } }