package lf2.plp.functional2.expression;
import java.util.HashMap;
import java.util.Map;
import lf2.plp.expressions1.util.Tipo;
import lf2.plp.expressions2.expression.Expressao;
import lf2.plp.expressions2.expression.Id;
import lf2.plp.expressions2.expression.Valor;
import lf2.plp.expressions2.memory.AmbienteCompilacao;
import lf2.plp.expressions2.memory.AmbienteExecucao;
import lf2.plp.expressions2.memory.ContextoCompilacao;
import lf2.plp.expressions2.memory.ContextoExecucao;
import lf2.plp.expressions2.memory.VariavelJaDeclaradaException;
import lf2.plp.expressions2.memory.VariavelNaoDeclaradaException;
import lf2.plp.functional1.declaration.DeclaracaoFuncional;
public class ExpDeclaracao implements Expressao {
protected DeclaracaoFuncional declaracao;
protected Expressao expressao;
public ExpDeclaracao(DeclaracaoFuncional declaracao,
Expressao expressaoArg) {
this.declaracao = declaracao;
expressao = expressaoArg;
}
/**
* Retorna uma representacao String desta expressao. Util para depuracao.
*
* @return uma representacao String desta expressao.
*/
// @Override
// public String toString() {
// return String.format("let %s in %s",
// listToString(seqdecFuncional, ","), expressao);
// }
public Valor avaliar(AmbienteExecucao ambiente)
throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
ambiente.incrementa();
// Como declaracoes feitas neste nivel nao devem ter influencia
// mutua, armazenamos os valores em uma ambiente auxiliar, para depois
// fazer o mapeamento.
AmbienteExecucao aux = new ContextoExecucao();
aux.incrementa();
declaracao.elabora(ambiente,aux);
declaracao.incluir(ambiente,aux);
aux.restaura();
Valor vresult = expressao.avaliar(ambiente);
if(vresult instanceof ValorFuncao)
vresult.reduzir(ambiente);
ambiente.restaura();
return vresult;
}
/**
* Realiza a verificacao de tipos desta expressao.
*
* @param amb
* o ambiente de compila��o.
* @return true se os tipos da expressao sao validos;
* false caso contrario.
* @exception VariavelNaoDeclaradaException
* se existir um identificador nao declarado no ambiente.
* @exception VariavelNaoDeclaradaException
* se existir um identificador declarado mais de uma vez no
* mesmo bloco do ambiente.
*/
public boolean checaTipo(AmbienteCompilacao ambiente)
throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
ambiente.incrementa();
boolean result = false;
try {
result = declaracao.checaTipo(ambiente);
if (result) {
AmbienteCompilacao aux = new ContextoCompilacao();
aux.incrementa();
declaracao.elabora(ambiente, aux);
declaracao.incluir(ambiente, aux,true);
aux.restaura();
result = expressao.checaTipo(ambiente);
}
} finally {
ambiente.restaura();
}
return result;
}
/**
* Retorna os tipos possiveis desta expressao.
*
* @param amb
* o ambiente de compila��o.
* @return os tipos possiveis desta expressao.
* @exception VariavelNaoDeclaradaException
* se existir um identificador nao declarado no ambiente.
* @exception VariavelNaoDeclaradaException
* se existir um identificador declarado mais de uma vez no
* mesmo bloco do ambiente.
* @precondition this.checaTipo();
*/
public Tipo getTipo(AmbienteCompilacao ambiente)
throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
ambiente.incrementa();
Tipo vresult = null;
AmbienteCompilacao aux = new ContextoCompilacao();
aux.incrementa();
declaracao.elabora(ambiente, aux);
declaracao.incluir(ambiente, aux,false);
aux.restaura();
vresult = expressao.getTipo(ambiente);
ambiente.restaura();
return vresult;
}
/**
* Returns the expressao.
*
* @return Expressao
*/
public Expressao getExpressao() {
return expressao;
}
public Expressao reduzir(AmbienteExecucao ambiente) {
ambiente.incrementa();
declaracao.reduzir(ambiente);
this.expressao = expressao.reduzir(ambiente);
ambiente.restaura();
return this;
}
public ExpDeclaracao clone(){
ExpDeclaracao retorno;
// List novaLista = new ArrayList(this.seqdecFuncional.size());
//
// for (DeclaracaoFuncional dec : this.seqdecFuncional){
// novaLista.add(dec.clone());
//
//// if (dec.getAridade() == 0) {
//// DecVariavel decVar = (DecVariavel) dec;
//// novaLista.add(new DecVariavel(decVar.getId().clone(), decVar.getExpressao().clone()));
//// } else {
//// DecFuncao decFuncao = (DecFuncao) dec;
//// novaLista.add(new DecFuncao(decFuncao.getId().clone(), decFuncao.getFuncao().clone()));
//// }
// }
retorno = new ExpDeclaracao(declaracao.clone(), this.expressao.clone());
return retorno;
}
}