package zinara.ast;
import zinara.ast.Param;
import zinara.ast.RoutineGenerator;
import zinara.ast.expression.Expression;
import zinara.ast.expression.BooleanExp;
import zinara.ast.expression.Identifier;
import zinara.ast.expression.ListExp;
import zinara.ast.type.Type;
import zinara.ast.type.FunctionType;
import zinara.ast.type.RoutineType;
import zinara.ast.type.ListType;
import zinara.ast.type.TupleType;
import zinara.ast.type.DictType;
import zinara.code_generator.*;
import zinara.exceptions.InvalidCodeException;
import zinara.symtable.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
public class RoutineGenerator{
public static void gen_routine(Genx86 generator,
SymTable symTable,
String func_name,
ArrayList expr_list,
int register,
boolean isFunction)
throws InvalidCodeException,IOException{
String code = "";
SymValue proc = symTable.getSymValueForId(func_name);
RoutineType routine = (RoutineType)(proc.type);
Expression expr;
Type exprType;
String reg;
String ax;
int params_size = 0;
code += generator.save_regs_caller(register);
for (int i = 0; i < expr_list.size() ; i++){
expr = (Expression)expr_list.get(i);
expr.register = register;
//Caso por valor
if ( ((Param)routine.getArgument(i)).byValue() ){
//Seteo el nombre correcto del registro a utilizar
//exprType = expr.getType();
exprType = expr.type;
reg = generator.regName(register,exprType);
/*********Se pushea en la pila*********/
//Si es un tipo basico lo pusheo
if (!(exprType instanceof ListType)&&
!(exprType instanceof TupleType)&&
!(exprType instanceof DictType)){
//Se genera el valor
if (expr instanceof BooleanExp){
String ret = generator.newLabel();
boolValue(generator,expr,ret,reg);
generator.writeLabel(ret);
}
else
expr.tox86(generator);
reg = generator.regName(register,exprType);
generator.write(generator.push(reg,exprType));
}
//Si es el identificador de una lista, hay que copiarlo
else if ((expr.type.getType() instanceof ListType)&&
(expr instanceof Identifier)) {
String stack_p = generator.stack_pointer();
reg = generator.addrRegName(register);
((Identifier)expr).currentDirection(generator);
copyList(generator,expr.type,reg,register+1);
}
//Si es un tipo compuesto literal, ya se genero en la pila
else{
//Se genera el valor
expr.tox86(generator);
reg = generator.regName(register,exprType);
generator.write(generator.push(reg,exprType.size()));
}
params_size += exprType.size();
}
//Caso por referencia
else{
//Seteo el nombre correcto del registro a utilizar
reg = generator.addrRegName(register);
((Identifier)expr).currentDirection(generator);
generator.write(generator.pushAddr(reg));
params_size += generator.word_size();
}
}
//Llamada
code += generator.call(routine.label);
//Se desempilan los parametros
code += generator.add(generator.stack_pointer(),
Integer.toString(params_size));
//Se restauran los registros
code += generator.restore_regs_caller(register);
//Devolucion del argumento si es una funcion
if (isFunction){
reg = generator.regName(register,((FunctionType)routine).getReturnType());
ax = generator.regName(0,((FunctionType)routine).getReturnType());
code += generator.mov(reg,ax);
}
generator.write(code);
}
public static void copyList(Genx86 generator,Type t,
String listAddr,int free_register)
throws IOException,InvalidCodeException{
generator.save(free_register);
Type listType = ((ListType)t.getType()).getInsideType();
String auxReg = generator.charRegName(free_register);
int listSize = ((ListType)t.getType()).size();
String listEnd = Integer.toString((listSize-1)*listType.size());
//Apunto al final de la lista ya que, como se va a poner
//en la pila, de otra forma quedaria alrevez
generator.write(generator.add(listAddr,listEnd));
for (int i = 0; i < listSize; i++) {
generator.write(generator.movChar(auxReg,"["+listAddr+"]"));
generator.write(generator.pushChar(auxReg));
generator.write(generator.sub(listAddr,"1"));
}
generator.restore(free_register);
}
public static void copyDict(Genx86 generator,Type t,
String dictAddr,int free_register)
throws IOException,InvalidCodeException{
generator.save(free_register);
Type itemType;
String itemTypeSize;
String auxReg;
Iterator it = ((DictType)t).getIterator();
String dictEnd = Integer.toString(((DictType)t).size());
//Apunto al final de la lista ya que, como se va a poner
//en la pila, de otra forma quedaria alrevez
generator.write(generator.add(dictAddr,dictEnd));
while(it.hasNext()){
itemType = (Type)(it.next());
itemTypeSize = Integer.toString(itemType.size());
auxReg = generator.regName(free_register,itemType);
generator.write(generator.mov(auxReg,"["+dictAddr+"]",itemType));
generator.write(generator.push(auxReg,itemType));
generator.write(generator.sub(dictAddr,itemTypeSize));
}
generator.restore(free_register);
}
public static void boolValue(Genx86 generate, Expression expr,
String ret, String reg)
throws IOException,InvalidCodeException{
String yesLabel = generate.newLabel();
String noLabel = generate.newLabel();
expr.yesLabel = yesLabel;
expr.noLabel = noLabel;
expr.tox86(generate);
generate.writeLabel(yesLabel);
generate.write(generate.movBool(reg,"1"));
generate.write(generate.jump(ret));
generate.writeLabel(noLabel);
generate.write(generate.movBool(reg,"0"));
}
}