package scriptingLanguage.variables;
import java.lang.reflect.Array;
import scriptingLanguage.Interpreter;
import scriptingLanguage.Token;
import scriptingLanguage.errors.InterpreterException;
import scriptingLanguage.errors.InvalidAccessException;
import scriptingLanguage.errors.InvalidAssignmentException;
import scriptingLanguage.errors.NullAccessException;
import scriptingLanguage.errors.UndefinedResultException;
import scriptingLanguage.errors.UnexpectedTypeException;
import scriptingLanguage.frames.AbstractFrame;
/**
* Represents and array for an Interpreter. Arrays are nested Array.newInstance(ArrayObject) until the last one, which is of
* the type that this array holds
*
* @author Joshua Lipstone
*/
public class ArrayObject extends AbstractObject<Object> {
//Source is an Object generated via Array.newInstance
public ArrayObject(AbstractClass<?> type, Object source) {
super(type, source);
}
/**
* @param parameters
* This should have the following structure: (index1, integerType)+ ((get, identifierType)|(set,
* indentifierType, {@literal <}value{@literal>}). The value for set should be fully evaluated.
*/
@Override
public Token eval(AbstractClass<?> caller, Token parameters, AbstractFrame frame) throws ArrayIndexOutOfBoundsException, IllegalArgumentException, InterpreterException {
int index = (int) ((Variable<Integer>) parameters.getCar()).getSource();
if ((parameters = parameters.getNextToken()).isNull() || parameters.getCar().equals("get"))
return new Token(Array.get(getSource(), index), ((Variable<?>) Array.get(getSource(), index)).getType().getTokenType());
if (parameters.getCar().equals("set")) {
if (((Variable<?>) (parameters = parameters.getNextToken()).getCar()).getType().extend((AbstractClass<?>) getType().getSource()) == -1)
throw new InvalidAssignmentException("Cannot assign a value of the type, " + ((Variable<?>) parameters.getCar()).getType() + " to " + getType().getSource());
Array.set(getSource(), index, parameters.getCar());
return new Token(Interpreter.NULL, Interpreter.voidType);
}
return ((Variable<?>) Array.get(getSource(), index)).eval(caller, parameters, frame);
}
@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 void write(Variable<?> data) throws InvalidAccessException {
super.write(data);
}
@Override
public Variable<Object> clone() {
return new ArrayObject(getType(), getSource());
}
@Override
public String toString() {
String output = "{";
int len = Array.getLength(getSource());
int i = 0;
for (; i < len - 1; i++)
output = output + Array.get(getSource(), i) + ",";
return output + Array.get(getSource(), i) + "}";
}
}