package zinara.ast;
import java.io.IOException;
import zinara.ast.ASTNode;
import zinara.ast.Param;
import zinara.ast.type.Type;
import zinara.ast.expression.Expression;
import zinara.ast.expression.BooleanExp;
import zinara.ast.expression.Identifier;
import zinara.ast.type.*;
import zinara.code_generator.Genx86;
import zinara.exceptions.TypeClashException;
import zinara.exceptions.InvalidCodeException;
import zinara.symtable.*;
public class SingleDeclaration extends Declaration {
private Type type;
private String identifier;
private Status status;
private Expression expr;
private SymTable symTable;
public SingleDeclaration(Type t, String id, Expression expr, boolean var, SymTable st) throws TypeClashException {
// Type checking first
if (expr != null && !t.equals(expr.getType()))
throw new TypeClashException("Asignacion invalida: tipo de la expresion `" + expr + "`" + expr.getType() + " difiere del tipo " + t + " en la declaracion del identificador " + id);
// ...
this.type = t;
this.identifier = id;
this.expr = expr;
this.symTable = st;
if (var)
status = new Variable(); else status = new Constant(expr);
}
public SingleDeclaration(Type t, Identifier id, Expression expr, boolean var, SymTable st) throws TypeClashException {
// Type checking first
if (expr != null && !t.equals(expr.getType()))
throw new TypeClashException("Asignacion invalida: tipo de la expresion `" + expr + "`" + expr.getType() + " difiere del tipo " + t + " en la declaracion del identificador " + id.getIdentifier());
// ...
this.type = t;
this.identifier = id.getIdentifier();
this.expr = expr;
this.symTable = st;
if (var) status = new Variable(); else status = new Constant(expr);
}
public boolean isSingle(){
return true;
}
public Type getType(){
return this.type;
}
public String getId(){
return this.identifier;
}
public Expression getExpression() { return expr; }
public Status getStatus() { return status; }
public void setType(Type t) { this.type = t; }
public String toString() {
return "(Declaration: " + type + " " + identifier + " [" + status + "])";
}
public void tox86(Genx86 generator)
throws IOException,InvalidCodeException{
if (this.type instanceof RoutineType){
String label = generator.newLabel();
label = label + "_" + identifier;
RoutineType routine_type = (RoutineType)(symTable.getSymbol(identifier).type);
int local_vars;
//Seteo el offset de las variables de la subrutina
SymTable routineTable = routine_type.codeBlock.getSymTable();
String frame_p = generator.frame_pointer();
int word_size = generator.word_size();
local_vars = routineTable.reserve_mem_stack(word_size,frame_p);
routineTable.set_params_offset(frame_p,
word_size,
routine_type.args);
//Set del label del procedimiento en el Symtable
((RoutineType)(this.type)).label = label;
routine_type.label = label;
make_proc(generator,label,local_vars);
return;
}
if (expr != null) {
SymValue sv = symTable.getSymbol(identifier);
String exprReg;
String lvalueAddr = sv.getArea()+sv.getOffset();
expr.register = register;
if (type.equals(new BoolType())) {
booleanAssignationToX86(generator, lvalueAddr);
return;
}
expr.tox86(generator);
exprReg = generator.regName(expr.register,expr.type);
storeValue(generator, type, lvalueAddr, exprReg);
}
}
// This one can be improved =S
public void booleanAssignationToX86(Genx86 generator, String lvalueAddr)
throws IOException,InvalidCodeException{
BooleanExp bExpr = (BooleanExp)expr;
String nextDecl = generator.newLabel();
bExpr.yesLabel = generator.newLabel();
bExpr.noLabel = generator.newLabel();
//En caso de que bExpr necesite computarse
bExpr.register = register;
String bExprReg = generator.regName(bExpr.register,bExpr.type);
bExpr.tox86(generator);
if (!(bExpr instanceof BooleanExp)){
generator.add(bExprReg,"0");
generator.jz(bExpr.noLabel);
}
generator.writeLabel(bExpr.yesLabel);
generator.write(generator.movBool("[" + lvalueAddr + "]", "1"));
generator.write(generator.jump(nextDecl));
generator.writeLabel(bExpr.noLabel);
generator.write(generator.movBool("[" + lvalueAddr + "]", "0"));
generator.writeLabel(nextDecl);
}
private void storeValue(Genx86 generator, Type t, String lvalueAddr, String exprReg)
throws IOException,InvalidCodeException{
if ((t.getType() instanceof ListType)||
(t.getType() instanceof StringType)||
(t.getType() instanceof TupleType)||
(t.getType() instanceof DictType)){
String auxReg = generator.charRegName(register+1);
int listSize = t.getType().size();
String lvalueReg = generator.addrRegName(register+2);
generator.write(generator.save(register+1));
generator.write(generator.save(register+2));
generator.write(generator.mov(lvalueReg,lvalueAddr));
int j = 1;
for (int i = 0; i < listSize; i++) {
generator.write(generator.movChar(auxReg,"["+exprReg+"]"));
generator.write(generator.movChar("["+lvalueReg+"]",auxReg));
generator.write(generator.add(lvalueReg,"1"));
generator.write(generator.add(exprReg,"1"));
}
generator.write(generator.restore(register+2));
generator.write(generator.restore(register+1));
}
else{
generator.write(generator.mov("[" + lvalueAddr + "]",
exprReg, t.getType()));
}
}
private void make_proc(Genx86 generator,String label,int local_vars)
throws InvalidCodeException,IOException{
String asm = "";
String local_vars_size = Integer.toString(local_vars);
String frame_p = generator.frame_pointer();
String stack_p = generator.stack_pointer();
String word_size = Integer.toString(generator.word_size());
asm += label+":\n";
//Guardo la cadena dinamica
asm += generator.pushAddr(frame_p);
//Actualizo el frame pointer
asm += generator.mov(frame_p,stack_p);
//Variables locales
asm += generator.sub(stack_p,local_vars_size);
//Registros salvados
asm += generator.save_regs_callee();
generator.write(asm);
((RoutineType)type).codeBlock.register = 0;
((RoutineType)type).codeBlock.tox86(generator);
asm = "";
asm += generator.restore_regs_callee();
//Se desempila todo que esta despues de la cadena dinamica
asm += generator.mov(stack_p,frame_p);
//Se restaura la cadena dinamica
asm += generator.pop(frame_p);
//Return
asm += generator.ret();
generator.write(asm);
}
}