package scriptingLanguage.variables;
import java.lang.reflect.Array;
import java.util.ArrayList;
import scriptingLanguage.Interpreter;
import scriptingLanguage.Token;
import scriptingLanguage.Type;
import scriptingLanguage.errors.InterpreterException;
import scriptingLanguage.errors.NullAccessException;
import scriptingLanguage.errors.UnexpectedTypeException;
import scriptingLanguage.frames.AbstractFrame;
import scriptingLanguage.frames.errors.FrameAccessException;
public class ArrayClass extends AbstractClass<AbstractClass<?>> {
public ArrayClass(String name, AbstractFrame frame, Type<?> tokenType) throws UnexpectedTypeException, FrameAccessException {
super(name, (name = name.substring(6)).contains("array:") ? new ArrayClass(name, frame, new Type<ArrayClass>(name)) : frame.getType(frame.getImport(name)), tokenType);
}
private ArrayClass(String name, AbstractClass<?> source, Type<?> tokenType) {
super(name, source, tokenType);
}
@Override
public Token eval(AbstractClass<?> caller, Token parameters, AbstractFrame frame) throws ArrayIndexOutOfBoundsException, IllegalArgumentException, InterpreterException {
if (parameters.getCarType().equals(Interpreter.curlyBracesType)) { //This is a contents-initialized array
Token value = (Token) parameters.getCar();
ArrayList<Variable<?>> values = new ArrayList<>();
do {
Token val = new Token(), head = val;
do {
head = head.append(value.singular());
} while (!(value = value.getNextToken()).isNull() && !value.getCarType().equals(Interpreter.separatorType));
if ((Variable<?>) getSource() instanceof ArrayClass)
values.add((Variable<?>) (val.getCarType().equals(Interpreter.curlyBracesType) ? getSource().eval(caller, val, frame).getCar() : Interpreter.evalInner(caller, val, frame).getCar()));
else
values.add((Variable<?>) frame.getInterpreter().eval(caller, val.getFirstToken(), frame).getCar());
} while (!(value = value.getNextToken()).isNull());
Object source = Array.newInstance(Variable.class, values.size());
for (int i = 0; i < values.size(); i++)
Array.set(source, i, values.get(i));
return new Token(new ArrayObject((AbstractClass<Object>) getSource(), source), getTokenType());
}
int length = ((Variable<Integer>) parameters.getCar()).getSource();
Object source = Array.newInstance(Variable.class, length);
if ((parameters = parameters.getNextToken()).isNull())
for (int i = 0; i < length; i++)
Array.set(source, i, Interpreter.NULL);
else
for (int i = 0; i < length; i++)
Array.set(source, i, getSource().eval(caller, parameters, frame).getCar());
return new Token(new ArrayObject(this, source), getTokenType());
}
public static ArrayClass makeArrayClass(AbstractClass<?> valueType, int depth) {
if (depth == 0)
return new ArrayClass("array:" + valueType.getName(), valueType, new Type<Object>("array:" + valueType.getName()));
AbstractClass<?> inner = makeArrayClass(valueType, depth - 1);
return new ArrayClass("array:" + inner.getName(), inner, new Type<Object>("array:" + inner.getName()));
}
@Override
public int extend(AbstractClass<?> type) throws NullAccessException {
if (!(type instanceof ArrayClass))
return -1;
return getSource().extend((AbstractClass<?>) type.getSource());
}
@Override
public Variable<AbstractClass<?>> clone() {
return new ArrayClass(getName(), getSource(), getTokenType());
}
@Override
public Token makePlaceholder() {
return new Token(new ArrayObject(getSource(), null), getTokenType());
}
}