package scriptingLanguage.variables;
import java.util.ArrayList;
import scriptingLanguage.Interpreter;
import scriptingLanguage.Token;
import scriptingLanguage.errors.InterpreterException;
import scriptingLanguage.errors.InvalidAccessException;
import scriptingLanguage.errors.NullAccessException;
import scriptingLanguage.errors.UndefinedResultException;
import scriptingLanguage.errors.UnexpectedTypeException;
import scriptingLanguage.frames.AbstractFrame;
import scriptingLanguage.frames.Frame;
public class InterpreterObject extends AbstractObject<Token> {
private Frame[] frames;
private AbstractObject<?> superObject;
public InterpreterObject(InterpreterClass type, AbstractObject<?> superObject, Frame[] frames) {
super(type);
this.frames = frames;
this.superObject = superObject;
}
@Override
public Token eval(AbstractClass<?> caller, Token parameters, AbstractFrame frame) throws InterpreterException {
if (!parameters.getNextToken().getCarType().equals(Interpreter.parenthesesType)) {
Access access = Access.getAccess(caller, getType());
if (!frames[access.intValue()].hasVariable((String) parameters.getCar()))
return superObject.eval(caller, parameters, frame);
return frames[access.intValue()].readVariable((String) parameters.getCar());
}
String name = (String) parameters.getCar();
ArrayList<Token> arguments = Interpreter.evalFunctionArguments(caller, (Token) parameters.getNextToken().getCar(), frame);
if (arguments.size() == 0 && name.equals("getClass"))
return frames[0].readVariable("class");
name = Interpreter.evalFunctionName(name, arguments);
Access access = Access.getAccess(caller, getType());
if (!frames[access.intValue()].hasVariable(name))
return superObject.eval(caller, parameters, frame);
return ((AbstractMethod<?>) frames[access.intValue()].readVariable(name).getCar()).eval(arguments);
}
@Override
public AbstractObject<?> castData(AbstractClass<?> output, AbstractFrame frame) throws UnexpectedTypeException, UndefinedResultException, NullAccessException {
if (extend(output) == -1)
throw new UnexpectedTypeException("Instances of the " + getType().getName() + " type cannot be cast to " + output.getName());
//TODO figure out how to implement method hiding when necessary
return this; //Funny thing, actually. The way that a cast object operates doesn't actually change all that much when generics aren't a factor. Those would be hell.
}
@Override
public Variable<Token> clone() {
return new InterpreterObject((InterpreterClass) getType(), superObject, frames);
}
@Override
public void write(Variable<?> data) throws InvalidAccessException {
super.write(data);
InterpreterObject newData = (InterpreterObject) data;
frames = newData.frames;
superObject = newData.superObject;
}
}