00001 package plp.functional2.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
00024 public class Aplicacao implements Expressao {
00025
00026 private Expressao func;
00027 private List<? extends Expressao> argsExpressao;
00028
00029 public Aplicacao(Expressao f, Expressao... expressoes) {
00030 this(f, asList(expressoes));
00031 }
00032
00033 public Aplicacao(Expressao f, List<? extends Expressao> expressoes) {
00034 func = f;
00035 argsExpressao = expressoes;
00036 }
00037
00038 public Valor avaliar(AmbienteExecucao ambiente)
00039 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00040
00041 ValorFuncao funcao = (ValorFuncao) func.avaliar(ambiente);
00042
00043 Map<Id, Valor> mapIdValor = resolveParametersBindings(ambiente, funcao);
00044
00045 ambiente.incrementa();
00046
00047 includeValueBindings(ambiente, mapIdValor);
00048
00049 Expressao exp = funcao.getExp();
00050 Valor vresult = exp.avaliar(ambiente);
00051
00052 ambiente.restaura();
00053 return vresult;
00054 }
00055
00069 public boolean checaTipo(AmbienteCompilacao ambiente)
00070 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00071 Tipo tipo = getFuncType(ambiente);
00072
00073 boolean result;
00074
00075 TipoFuncao tipoFuncao = (TipoFuncao) tipo;
00076 result = tipoFuncao.checaTipo(ambiente, argsExpressao);
00077
00078 return result;
00079 }
00080
00081 private Tipo getFuncType(AmbienteCompilacao ambiente) {
00082 Tipo tipoFuncao = null;
00083 if (func instanceof Id) {
00084 tipoFuncao = ambiente.get((Id) func);
00085 } else if (func instanceof ValorFuncao) {
00086 tipoFuncao = ((ValorFuncao) func).getTipo(ambiente);
00087 }
00088
00089 if (tipoFuncao == null || tipoFuncao instanceof TipoPolimorfico) {
00090 ArrayList<Tipo> params = new ArrayList<Tipo>();
00091 for (Expressao valorReal : argsExpressao) {
00092 params.add(valorReal.getTipo(ambiente));
00093 }
00094 tipoFuncao = new TipoFuncao(params, new TipoPolimorfico());
00095 }
00096 return tipoFuncao;
00097 }
00098
00104 public List<? extends Expressao> getArgsExpressao() {
00105 return argsExpressao;
00106 }
00107
00113 public Expressao getFunc() {
00114 return func;
00115 }
00116
00130 public Tipo getTipo(AmbienteCompilacao ambiente)
00131 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00132
00133 Tipo tipo = getFuncType(ambiente);
00134
00135 TipoFuncao tipoFuncao = (TipoFuncao) tipo;
00136
00137 return tipoFuncao.getTipo(ambiente, argsExpressao);
00138 }
00139
00140 private void includeValueBindings(AmbienteExecucao ambiente,
00141 Map<Id, Valor> mapIdValor) throws VariavelJaDeclaradaException {
00142 for (Map.Entry<Id, Valor> mapeamento : mapIdValor.entrySet()) {
00143 Id id = mapeamento.getKey();
00144 Valor valor = mapeamento.getValue();
00145 ambiente.map(id, valor);
00146 }
00147 }
00148
00149 private Map<Id, Valor> resolveParametersBindings(AmbienteExecucao ambiente,
00150 DefFuncao funcao) throws VariavelNaoDeclaradaException,
00151 VariavelJaDeclaradaException {
00152 List<Id> parametrosId = funcao.getListaId();
00153 List<? extends Expressao> expressoesValorReal = argsExpressao;
00154
00155 Map<Id, Valor> mapIdValor = new HashMap<Id, Valor>();
00156
00157 Iterator<? extends Expressao> iterExpressoesValor = expressoesValorReal
00158 .iterator();
00159 for (Id id : parametrosId) {
00160 Expressao exp = iterExpressoesValor.next();
00161 Valor valorReal = exp.avaliar(ambiente);
00162 mapIdValor.put(id, valorReal);
00163 }
00164
00165 return mapIdValor;
00166 }
00167
00173 @Override
00174 public String toString() {
00175 return String.format("%s(%s)", func, listToString(argsExpressao, ","));
00176 }
00177
00178 }