00001
00002 package plp.functional1.expression;
00003
00004 import java.util.HashMap;
00005 import java.util.Iterator;
00006 import java.util.List;
00007 import java.util.Map;
00008
00009 import plp.expressions1.util.Tipo;
00010 import plp.expressions2.expression.Expressao;
00011 import plp.expressions2.expression.Id;
00012 import plp.expressions2.expression.Valor;
00013 import plp.expressions2.memory.AmbienteCompilacao;
00014 import plp.expressions2.memory.AmbienteExecucao;
00015 import plp.expressions2.memory.VariavelJaDeclaradaException;
00016 import plp.expressions2.memory.VariavelNaoDeclaradaException;
00017 import plp.functional1.memory.AmbienteExecucaoFuncional;
00018 import plp.functional1.util.ValorFuncao;
00019
00020 public class Aplicacao implements Expressao {
00021
00022 private Id func;
00023 private List<Expressao> argsExpressao;
00024
00025 public Aplicacao(Id f, List<Expressao> expressoes) {
00026 func = f;
00027 argsExpressao = expressoes;
00028 }
00029
00035 public String toString() {
00036 StringBuffer sb = new StringBuffer();
00037 sb.append(func.toString());
00038 sb.append(" (");
00039 sb.append(argsExpressao.toString());
00040 sb.append(')');
00041 return sb.toString();
00042 }
00043
00044 public Valor avaliar(AmbienteExecucao ambiente)
00045 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00046 AmbienteExecucaoFuncional ambienteFuncional =
00047 (AmbienteExecucaoFuncional) ambiente;
00048
00049 ValorFuncao funcao = ambienteFuncional.getFuncao(func);
00050
00051 Map<Id,Valor> mapIdValor = resolveParametersBindings(ambiente, funcao);
00052
00053 ambiente.incrementa();
00054
00055 includeValueBindings(ambiente, mapIdValor);
00056
00057 Valor vresult = funcao.getExp().avaliar(ambiente);
00058 ambiente.restaura();
00059 return vresult;
00060 }
00061
00062 private void includeValueBindings(AmbienteExecucao ambiente, Map<Id,Valor> mapIdValor)
00063 throws VariavelJaDeclaradaException {
00064 for(Map.Entry<Id,Valor> mapeamento:mapIdValor.entrySet()){
00065 Id id = (Id) mapeamento.getKey();
00066 Valor valor = (Valor) mapeamento.getValue();
00067 ambiente.map(id, valor);
00068 }
00069 }
00070
00071 private Map<Id,Valor> resolveParametersBindings(AmbienteExecucao ambiente, ValorFuncao funcao)
00072 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00073 List<Id> parametrosId = funcao.getListaId();
00074 List<Expressao> expressoesValorReal = argsExpressao;
00075
00076 Map<Id,Valor> mapIdValor = new HashMap<Id,Valor>();
00077
00078 Iterator<Expressao> iterExpressoesValor = expressoesValorReal.iterator();
00079 for(Id id:parametrosId){
00080 Expressao exp = iterExpressoesValor.next();
00081 Valor valorReal = exp.avaliar(ambiente);
00082 mapIdValor.put(id, valorReal);
00083 }
00084 return mapIdValor;
00085 }
00086
00098 public boolean checaTipo(AmbienteCompilacao ambiente)
00099 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00100
00101 Tipo tipoFuncao = ambiente.get(func);
00102
00103 return checkArgumentListSize(tipoFuncao)
00104 && checkArgumentTypes(ambiente, tipoFuncao) ;
00105 }
00106
00107 private boolean checkArgumentTypes(
00108 AmbienteCompilacao ambiente,
00109 Tipo tipoFuncao)
00110 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00111 boolean result = true;
00112 List<Expressao> expressoesValorReal = argsExpressao;
00113
00114
00115 for(Expressao valorReal:expressoesValorReal){
00116 if (!valorReal.checaTipo(ambiente)) {
00117 result = false;
00118 }
00119 Tipo tipoArg = valorReal.getTipo(ambiente);
00120 if (tipoArg.intersecao(tipoFuncao).eVoid()) {
00121 result = false;
00122 }
00123 tipoFuncao = tipoFuncao.getProx();
00124 }
00125 return result;
00126 }
00127
00128 private boolean checkArgumentListSize(Tipo tipoFuncao) {
00129 boolean res;
00130 {
00131 res = true;
00132
00133 List expressoesValorReal = argsExpressao;
00134
00135 Tipo aux = tipoFuncao;
00136
00137 int tamanhoTipo = 0;
00138 while (aux != null) {
00139 tamanhoTipo++;
00140 aux = aux.getProx();
00141 }
00142 if ((tamanhoTipo - 1) != expressoesValorReal.size()) {
00143 res = false;
00144 }
00145
00146 }
00147 return res;
00148 }
00149
00161 public Tipo getTipo(AmbienteCompilacao ambiente)
00162 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00163 Tipo t = ambiente.get(func);
00164 while (t.getProx() != null) {
00165 t = t.getProx();
00166 }
00167 return t;
00168 }
00169
00174 public Id getFunc() {
00175 return func;
00176 }
00177
00182 public List<Expressao> getArgsExpressao() {
00183 return argsExpressao;
00184 }
00185 }