00001 package plp.functional3.expression;
00002
00003 import static java.util.Arrays.asList;
00004 import static plp.expressions1.util.ToStringProvider.listToString;
00005
00006 import java.util.ArrayList;
00007 import java.util.HashMap;
00008 import java.util.Iterator;
00009 import java.util.List;
00010 import java.util.Map;
00011
00012 import plp.expressions1.util.Tipo;
00013 import plp.expressions2.expression.Expressao;
00014 import plp.expressions2.expression.Id;
00015 import plp.expressions2.expression.Valor;
00016 import plp.expressions2.memory.AmbienteCompilacao;
00017 import plp.expressions2.memory.AmbienteExecucao;
00018 import plp.expressions2.memory.VariavelJaDeclaradaException;
00019 import plp.expressions2.memory.VariavelNaoDeclaradaException;
00020 import plp.functional1.util.DefFuncao;
00021 import plp.functional1.util.TipoFuncao;
00022 import plp.functional1.util.TipoPolimorfico;
00023 import plp.functional2.expression.ValorFuncao;
00024
00025 public class Aplicacao implements Expressao {
00026
00027 private Expressao func;
00028 private List<? extends Expressao> argsExpressao;
00029
00030 public Aplicacao(Expressao f, Expressao... expressoes) {
00031 this(f, asList(expressoes));
00032 }
00033
00034 public Aplicacao(Expressao f, List<? extends Expressao> expressoes) {
00035 func = f;
00036 argsExpressao = expressoes;
00037 }
00038
00039 public Valor avaliar(AmbienteExecucao ambiente)
00040 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00041
00042 ValorFuncao funcao = (ValorFuncao) func.avaliar(ambiente);
00043
00044 Map<Id, Valor> mapIdValor = resolveParametersBindings(ambiente, funcao);
00045
00046 ambiente.incrementa();
00047
00048 includeValueBindings(ambiente, mapIdValor);
00049
00050 Expressao exp = funcao.getExp();
00051 Valor vresult = exp.avaliar(ambiente);
00052
00053 ambiente.restaura();
00054 return vresult;
00055 }
00056
00070 public boolean checaTipo(AmbienteCompilacao ambiente)
00071 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00072 Tipo tipo = getFuncType(ambiente);
00073
00074 boolean result;
00075
00076 TipoFuncao tipoFuncao = (TipoFuncao) tipo;
00077 result = tipoFuncao.checaTipo(ambiente, argsExpressao);
00078
00079 return result;
00080 }
00081
00082 private Tipo getFuncType(AmbienteCompilacao ambiente) {
00083 Tipo tipoFuncao = null;
00084 if (func instanceof Id) {
00085 tipoFuncao = ambiente.get((Id) func);
00086 } else if (func instanceof ValorFuncao) {
00087 tipoFuncao = ((ValorFuncao) func).getTipo(ambiente);
00088 }
00089
00090 if (tipoFuncao == null || tipoFuncao instanceof TipoPolimorfico) {
00091 ArrayList<Tipo> params = new ArrayList<Tipo>();
00092 for (Expressao valorReal : argsExpressao) {
00093 params.add(valorReal.getTipo(ambiente));
00094 }
00095 tipoFuncao = new TipoFuncao(params, new TipoPolimorfico());
00096 }
00097 return tipoFuncao;
00098 }
00099
00105 public List<? extends Expressao> getArgsExpressao() {
00106 return argsExpressao;
00107 }
00108
00114 public Expressao getFunc() {
00115 return func;
00116 }
00117
00131 public Tipo getTipo(AmbienteCompilacao ambiente)
00132 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00133
00134 Tipo tipo = getFuncType(ambiente);
00135
00136 TipoFuncao tipoFuncao = (TipoFuncao) tipo;
00137
00138 return tipoFuncao.getTipo(ambiente, argsExpressao);
00139 }
00140
00141 private void includeValueBindings(AmbienteExecucao ambiente,
00142 Map<Id, Valor> mapIdValor) throws VariavelJaDeclaradaException {
00143 for (Map.Entry<Id, Valor> mapeamento : mapIdValor.entrySet()) {
00144 Id id = mapeamento.getKey();
00145 Valor valor = mapeamento.getValue();
00146 ambiente.map(id, valor);
00147 }
00148 }
00149
00150 private Map<Id, Valor> resolveParametersBindings(AmbienteExecucao ambiente,
00151 DefFuncao funcao) throws VariavelNaoDeclaradaException,
00152 VariavelJaDeclaradaException {
00153 List<Id> parametrosId = funcao.getListaId();
00154 List<? extends Expressao> expressoesValorReal = argsExpressao;
00155
00156 Map<Id, Valor> mapIdValor = new HashMap<Id, Valor>();
00157
00158 Iterator<? extends Expressao> iterExpressoesValor = expressoesValorReal.iterator();
00159 for (Id id : parametrosId) {
00160
00161 if (id instanceof VarargsId){
00162
00163 ValorLista valorLista = ValorLista.getInstancia(null, null);
00164
00165 while (iterExpressoesValor.hasNext()) {
00166 valorLista = valorLista.cons(iterExpressoesValor.next().avaliar(ambiente));
00167 }
00168
00169
00170
00171
00172
00173 mapIdValor.put(new Id(id.getIdName()), valorLista.inverter());
00174 } else {
00175 Expressao exp = iterExpressoesValor.next();
00176 Valor valorReal = exp.avaliar(ambiente);
00177 mapIdValor.put(id, valorReal);
00178 }
00179 }
00180
00181 return mapIdValor;
00182 }
00183
00189 @Override
00190 public String toString() {
00191 return String.format("%s(%s)", func, listToString(argsExpressao, ","));
00192 }
00193 }