00001
00002 package plp.functional1.expression;
00003
00004 import static java.util.Arrays.asList;
00005 import static plp.expressions1.util.ToStringProvider.listToString;
00006
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.IdentificadorNaoDeclaradoException;
00019 import plp.expressions2.memory.VariavelJaDeclaradaException;
00020 import plp.expressions2.memory.VariavelNaoDeclaradaException;
00021 import plp.functional1.memory.AmbienteExecucaoFuncional;
00022 import plp.functional1.util.DefFuncao;
00023 import plp.functional1.util.TipoFuncao;
00024
00025 public class Aplicacao implements Expressao {
00026
00027 private Id func;
00028 private List<? extends Expressao> argsExpressao;
00029
00030 public Aplicacao(Id f, Expressao... expressoes) {
00031 this(f, asList(expressoes));
00032 }
00033
00034 public Aplicacao(Id f, List<? extends Expressao> expressoes) {
00035 func = f;
00036 argsExpressao = expressoes;
00037 }
00038
00039 public Valor avaliar(AmbienteExecucao ambiente)
00040 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00041 AmbienteExecucaoFuncional ambienteFuncional = (AmbienteExecucaoFuncional) ambiente;
00042
00043 DefFuncao funcao;
00044 try {
00045 funcao = ambienteFuncional.getFuncao(func);
00046 } catch (IdentificadorNaoDeclaradoException e) {
00047 throw new VariavelJaDeclaradaException(func);
00048 }
00049
00050 Map<Id, Valor> mapIdValor = resolveParametersBindings(ambiente, funcao);
00051
00052 ambiente.incrementa();
00053
00054 includeValueBindings(ambiente, mapIdValor);
00055
00056 Valor vresult = funcao.getExp().avaliar(ambiente);
00057 ambiente.restaura();
00058 return vresult;
00059 }
00060
00074 public boolean checaTipo(AmbienteCompilacao ambiente)
00075 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00076 boolean result;
00077 Tipo aux = ambiente.get(func);
00078
00079 if (aux instanceof TipoFuncao) {
00080 TipoFuncao tipoFuncao = (TipoFuncao) aux;
00081
00082 result = tipoFuncao.checaTipo(ambiente, argsExpressao);
00083 } else {
00084
00085
00086
00087
00088
00089 result = false;
00090 }
00091 return result;
00092 }
00093
00099 public List<? extends Expressao> getArgsExpressao() {
00100 return argsExpressao;
00101 }
00102
00108 public Id getFunc() {
00109 return func;
00110 }
00111
00125 public Tipo getTipo(AmbienteCompilacao ambiente)
00126 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00127 TipoFuncao tipoFuncao = (TipoFuncao) ambiente.get(func);
00128 return tipoFuncao.getTipo(ambiente, argsExpressao);
00129 }
00130
00131 private void includeValueBindings(AmbienteExecucao ambiente,
00132 Map<Id, Valor> mapIdValor) throws VariavelJaDeclaradaException {
00133 for (Map.Entry<Id, Valor> mapeamento : mapIdValor.entrySet()) {
00134 Id id = mapeamento.getKey();
00135 Valor valor = mapeamento.getValue();
00136 ambiente.map(id, valor);
00137 }
00138 }
00139
00140 private Map<Id, Valor> resolveParametersBindings(AmbienteExecucao ambiente,
00141 DefFuncao funcao) throws VariavelNaoDeclaradaException,
00142 VariavelJaDeclaradaException {
00143 List<Id> parametrosId = funcao.getListaId();
00144 List<? extends Expressao> expressoesValorReal = argsExpressao;
00145
00146 Map<Id, Valor> mapIdValor = new HashMap<Id, Valor>();
00147
00148 Iterator<? extends Expressao> iterExpressoesValor = expressoesValorReal
00149 .iterator();
00150 for (Id id : parametrosId) {
00151 Expressao exp = iterExpressoesValor.next();
00152 Valor valorReal = exp.avaliar(ambiente);
00153 mapIdValor.put(id, valorReal);
00154 }
00155 return mapIdValor;
00156 }
00157
00163 @Override
00164 public String toString() {
00165 return String.format("%s(%s)", func, listToString(argsExpressao, ","));
00166 }
00167
00168 }