package zinara.ast.expression;
import zinara.code_generator.*;
import java.util.ArrayList;
import zinara.ast.type.IntType;
import zinara.ast.type.ListType;
import zinara.ast.type.DictType;
import zinara.ast.type.StringType;
import zinara.ast.type.TupleType;
import zinara.ast.type.Type;
import zinara.exceptions.TypeClashException;
import zinara.exceptions.InvalidCodeException;
import java.io.IOException;
// invariant: every element of the value has the same type
public class ListExp extends Expression {
public ArrayList value; // arraylist of expressions
public ListExp(ArrayList v) throws TypeClashException {
value = v;
Type t = ((Expression)value.get(0)).getType();
boolean consistency = true;
for (int i = 1; i < value.size(); i++)
consistency = consistency && (t.equals(((Expression)value.get(i)).getType()));
if (!consistency)
throw new TypeClashException("La lista " + toString() + " tiene inconsistencia de tipos");
}
public ListExp(Expression e1, Expression e2) throws TypeClashException {
if (!(e1.getType() instanceof IntType))
throw new TypeClashException("La expresion " + e1 + " debe ser del tipo <INT>");
if (!e1.isStaticallyKnown())
throw new TypeClashException("La expresion " + e1 + " debe ser conocida a tiempo de compilacion");
if (!(e2.getType() instanceof IntType))
throw new TypeClashException("La expresion " + e2 + " debe ser del tipo <INT>");
if (!e2.isStaticallyKnown())
throw new TypeClashException("La expresion " + e2 + " debe ser conocida a tiempo de compilacion");
Object i1 = e1.staticValue(), i2 = e2.staticValue();
if (!(i1 instanceof Integer))
throw new TypeClashException("La expresion " + e1 + " no pudo ser reducida a Integer");
if (!(i2 instanceof Integer))
throw new TypeClashException("La expresion " + e2 + " no pudo ser reducida a Integer");
value = new ArrayList();
for (int i = ((Integer)i1).intValue(); i < ((Integer)i2).intValue(); i++)
value.add(new IntegerExp(i));
}
public ListExp() { value = new ArrayList(); }
public Type getType() throws TypeClashException {
if (type != null) return type;
type = (value.size() > 0 ? new ListType(((Expression)value.get(0)).getType(), value.size()) : new ListType(null,0));
return type;
}
public String toString() {
String ret = "[";
for (int i = 0; i < value.size(); i++)
ret += (Expression)value.get(i) + ", ";
return (value.size() == 0 ? ret : ret.substring(0, ret.length()-2)) + "]";
}
public void tox86(Genx86 generator)
throws IOException, InvalidCodeException{
Expression expr;
Type listType = ((ListType)type).getInsideType();
String reg = generator.regName(register,listType);
String regAddr = generator.addrRegName(register);
for (int i = value.size()-1; i >= 0 ; i--) {
//Se genera el valor
expr = (Expression)value.get(i);
expr.register = register;
if (expr instanceof BooleanExp){
String ret = generator.newLabel();
boolValue(generator,expr,ret,reg);
generator.writeLabel(ret);
}
else
expr.tox86(generator);
//Se pushea en la pila
if (!(expr instanceof ListExp)&&
!(expr instanceof DictExp)&&
!(expr instanceof TupleExp)&&
!(expr instanceof StringExp))
generator.write(generator.push(reg,listType.size()));
}
//Por ultimo, devuelvo la direccion donde comienza la lista
generator.write(generator.mov(regAddr,generator.stack_pointer()));
}
public boolean isStaticallyKnown() {
boolean isk = true;
Expression v;
for (int i = 0; i < value.size(); i++) {
v = (Expression)value.get(i);
isk = isk && v.isStaticallyKnown();
}
return isk;
}
public Object staticValue() {
ArrayList result = new ArrayList();
for (int i = 0; i < value.size(); i++)
result.add(((Expression)value.get(i)).staticValue());
return result;
}
}