00001 package plp.functional2.expression;
00002
00003 import java.util.Collections;
00004 import java.util.HashMap;
00005 import java.util.HashSet;
00006 import java.util.Iterator;
00007 import java.util.List;
00008 import java.util.Map;
00009 import java.util.Set;
00010
00011 import plp.expressions1.util.Tipo;
00012 import plp.expressions2.expression.Expressao;
00013 import plp.expressions2.expression.Id;
00014 import plp.expressions2.expression.Valor;
00015 import plp.expressions2.memory.AmbienteCompilacao;
00016 import plp.expressions2.memory.AmbienteExecucao;
00017 import plp.expressions2.memory.VariavelJaDeclaradaException;
00018 import plp.expressions2.memory.VariavelNaoDeclaradaException;
00019 import plp.functional2.util.PartialInstantiatorVisitor;
00020
00021 public class Aplicacao implements Expressao {
00022
00023 private Expressao func;
00024 private List<Expressao> argsExpressao;
00025
00026 public Aplicacao(Expressao f, List<Expressao> expressoes) {
00027 func = f;
00028 argsExpressao = expressoes;
00029 }
00030
00036 public String toString() {
00037 StringBuffer sb = new StringBuffer();
00038 sb.append(func.toString());
00039 sb.append(" (");
00040 sb.append(argsExpressao.toString());
00041 sb.append(')');
00042 return sb.toString();
00043 }
00044
00045 public Valor avaliar(AmbienteExecucao ambiente)
00046 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00047
00048 ValorFuncao funcao = (ValorFuncao)func.avaliar(ambiente);
00049
00050 Map<Id,Valor> mapIdValor = resolveParametersBindings(ambiente, funcao);
00051
00052 ambiente.incrementa();
00053
00054 includeValueBindings(ambiente, mapIdValor);
00055
00056 Expressao expInterna = funcao.getExp();
00057 Valor vresult;
00058
00059 if (expInterna instanceof ValorFuncao) {
00060 ValorFuncao temp = (ValorFuncao) expInterna;
00061 Set variaveisLocais = Collections.unmodifiableSet(new HashSet<Id>(temp.getListaId()));
00062 vresult = (Valor)
00063 PartialInstantiatorVisitor.getInstance().visit(temp, ambiente, variaveisLocais);
00064 } else {
00065 vresult = expInterna.avaliar(ambiente);
00066 }
00067 ambiente.restaura();
00068 return vresult;
00069 }
00070
00071 private void includeValueBindings(AmbienteExecucao ambiente, Map<Id,Valor> mapIdValor)
00072 throws VariavelJaDeclaradaException {
00073 for(Map.Entry<Id,Valor> mapeamento:mapIdValor.entrySet()){
00074 Id id = mapeamento.getKey();
00075 Valor valor = mapeamento.getValue();
00076 ambiente.map(id, valor);
00077 }
00078 }
00079
00080 private Map<Id,Valor> resolveParametersBindings(AmbienteExecucao ambiente, ValorFuncao funcao)
00081 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00082 List<Id> parametrosId = funcao.getListaId();
00083 List<Expressao> expressoesValorReal = argsExpressao;
00084
00085 Map<Id,Valor> mapIdValor = new HashMap<Id,Valor>();
00086
00087 Iterator<Expressao> iterExpressoesValor = expressoesValorReal.iterator();
00088 for(Id id:parametrosId){
00089 Expressao exp = iterExpressoesValor.next();
00090 Valor valorReal = exp.avaliar(ambiente);
00091 mapIdValor.put(id, valorReal);
00092 }
00093
00094 return mapIdValor;
00095 }
00096
00108 public boolean checaTipo(AmbienteCompilacao ambiente)
00109 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00110
00111 Id t = (Id)func;
00112 Tipo tipoFuncao = ambiente.get(t);
00113
00114 return checkArgumentListSize(tipoFuncao)
00115 && checkArgumentTypes(ambiente, tipoFuncao) ;
00116 }
00117
00118 private boolean checkArgumentTypes(
00119 AmbienteCompilacao ambiente,
00120 Tipo tipoFuncao)
00121 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00122 boolean result = true;
00123 List<Expressao> expressoesValorReal = argsExpressao;
00124 for(Expressao valorReal:expressoesValorReal){
00125 if (!valorReal.checaTipo(ambiente)) {
00126 result = false;
00127 }
00128 Tipo tipoArg = valorReal.getTipo(ambiente);
00129 if (tipoArg.intersecao(tipoFuncao).eVoid()) {
00130 result = false;
00131 }
00132 tipoFuncao = tipoFuncao.getProx();
00133 }
00134 return result;
00135 }
00136
00137 private boolean checkArgumentListSize(Tipo tipoFuncao) {
00138 boolean res;
00139 {
00140 res = true;
00141
00142 List<Expressao> expressoesValorReal = argsExpressao;
00143
00144 Tipo aux = tipoFuncao;
00145
00146 int tamanhoTipo = 0;
00147 while (aux != null) {
00148 tamanhoTipo++;
00149 aux = aux.getProx();
00150 }
00151 if ((tamanhoTipo - 1) != expressoesValorReal.size()) {
00152 res = false;
00153 }
00154
00155 }
00156 return res;
00157 }
00158
00170 public Tipo getTipo(AmbienteCompilacao ambiente)
00171 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00172
00173 Id id = (Id)func;
00174 Tipo t = ambiente.get(id);
00175 while (t.getProx() != null) {
00176 t = t.getProx();
00177 }
00178 return t;
00179 }
00180
00185 public Id getFunc() {
00186
00187 Id t = (Id)func;
00188 return t;
00189
00190 }
00191
00196 public List<Expressao> getArgsExpressao() {
00197 return argsExpressao;
00198 }
00199
00200 }