00001 package plp.functional1.expression;
00002
00003 import static plp.expressions1.util.ToStringProvider.listToString;
00004
00005 import java.util.HashMap;
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.IdentificadorJaDeclaradoException;
00016 import plp.expressions2.memory.VariavelJaDeclaradaException;
00017 import plp.expressions2.memory.VariavelNaoDeclaradaException;
00018 import plp.functional1.declaration.DecFuncao;
00019 import plp.functional1.declaration.DeclaracaoFuncional;
00020 import plp.functional1.memory.AmbienteExecucaoFuncional;
00021 import plp.functional1.util.DefFuncao;
00022
00023 public class ExpDeclaracao implements Expressao {
00024
00025 List<? extends DeclaracaoFuncional> seqdecFuncional;
00026 Expressao expressao;
00027
00028 public ExpDeclaracao(
00029 List<? extends DeclaracaoFuncional> declaracoesFuncionais,
00030 Expressao expressaoArg) {
00031 seqdecFuncional = declaracoesFuncionais;
00032 expressao = expressaoArg;
00033 }
00034
00040 public List<? extends DeclaracaoFuncional> getSeqdecFuncional() {
00041 return seqdecFuncional;
00042 }
00043
00049 public Expressao getExpressao() {
00050 return expressao;
00051 }
00052
00058 @Override
00059 public String toString() {
00060 return String.format("let %s in %s",
00061 listToString(seqdecFuncional, ","), expressao);
00062 }
00063
00064 public Valor avaliar(AmbienteExecucao ambienteFuncional)
00065 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00066 AmbienteExecucaoFuncional ambiente = (AmbienteExecucaoFuncional) ambienteFuncional;
00067 ambiente.incrementa();
00068
00069
00070
00071
00072 Map<Id, Valor> auxIdValor = new HashMap<Id, Valor>();
00073 Map<Id, DefFuncao> auxIdValorFuncao = new HashMap<Id, DefFuncao>();
00074
00075 resolveBindings(ambiente, auxIdValor, auxIdValorFuncao);
00076
00077 includeBindings(ambiente, auxIdValor, auxIdValorFuncao);
00078
00079 Valor vresult = expressao.avaliar(ambiente);
00080 ambiente.restaura();
00081 return vresult;
00082 }
00083
00084 private void includeBindings(AmbienteExecucaoFuncional ambiente,
00085 Map<Id, Valor> auxIdValor, Map<Id, DefFuncao> auxIdValorFuncao)
00086 throws VariavelJaDeclaradaException {
00087
00088 for (Map.Entry<Id, Valor> idValor : auxIdValor.entrySet()) {
00089 ambiente.map(idValor.getKey(), idValor.getValue());
00090 }
00091
00092 for (Map.Entry<Id, DefFuncao> idFuncao : auxIdValorFuncao.entrySet()) {
00093 try {
00094 ambiente.mapFuncao(idFuncao.getKey(), idFuncao.getValue());
00095 } catch (IdentificadorJaDeclaradoException e) {
00096 throw new VariavelJaDeclaradaException(idFuncao.getKey());
00097 }
00098 }
00099 }
00100
00101 private void resolveBindings(AmbienteExecucaoFuncional ambiente,
00102 Map<Id, Valor> auxIdValor, Map<Id, DefFuncao> auxIdValorFuncao)
00103 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00104
00105 for (DeclaracaoFuncional decFuncional : this.seqdecFuncional) {
00106 if (decFuncional.getAridade() == 0) {
00107 auxIdValor.put(decFuncional.getId(), decFuncional
00108 .getExpressao().avaliar(ambiente));
00109 } else {
00110 DecFuncao decFuncao = (DecFuncao) decFuncional;
00111 DefFuncao valorFuncao = decFuncao.getFuncao();
00112 auxIdValorFuncao.put(decFuncional.getId(), valorFuncao);
00113 }
00114 }
00115 }
00116
00130 public boolean checaTipo(AmbienteCompilacao ambiente)
00131 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00132 ambiente.incrementa();
00133
00134 boolean result = false;
00135 try {
00136 result = checkTypeBindings(ambiente);
00137 if (result) {
00138 Map<Id, Tipo> resolvedTypes = resolveTypeBidings(ambiente);
00139 includeTypeBindings(ambiente, resolvedTypes);
00140 result = expressao.checaTipo(ambiente);
00141 }
00142 } finally {
00143 ambiente.restaura();
00144 }
00145 return result;
00146 }
00147
00148 private Map<Id, Tipo> resolveTypeBidings(AmbienteCompilacao ambiente)
00149 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00150 Map<Id, Tipo> resolvedTypes = new HashMap<Id, Tipo>();
00151
00152 for (DeclaracaoFuncional decFuncional : this.seqdecFuncional) {
00153 if (resolvedTypes.put(decFuncional.getId(), decFuncional
00154 .getTipo(ambiente)) != null)
00155 throw new VariavelJaDeclaradaException(decFuncional.getId());
00156 }
00157 return resolvedTypes;
00158 }
00159
00160 private boolean checkTypeBindings(AmbienteCompilacao ambiente)
00161 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00162 boolean result = true;
00163 for (DeclaracaoFuncional decFuncional : this.seqdecFuncional) {
00164 if (!decFuncional.checaTipo(ambiente)) {
00165 result = false;
00166 break;
00167 }
00168 }
00169 return result;
00170 }
00171
00172 private void includeTypeBindings(AmbienteCompilacao ambiente,
00173 Map<Id, Tipo> resolvedTypes) throws VariavelJaDeclaradaException {
00174 for (Id id : resolvedTypes.keySet()) {
00175 ambiente.map(id, resolvedTypes.get(id));
00176 }
00177 }
00178
00192 public Tipo getTipo(AmbienteCompilacao ambiente)
00193 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00194 ambiente.incrementa();
00195 for (DeclaracaoFuncional decFuncional : this.seqdecFuncional) {
00196 if (decFuncional.getAridade() == 0) {
00197 ambiente.map(decFuncional.getId(), decFuncional.getExpressao()
00198 .getTipo(ambiente));
00199 } else {
00200 DecFuncao decFuncao = (DecFuncao) decFuncional;
00201 ambiente.map(decFuncional.getId(), decFuncao.getTipo(ambiente));
00202 }
00203 }
00204 Tipo vresult = expressao.getTipo(ambiente);
00205 ambiente.restaura();
00206 return vresult;
00207 }
00208
00209 }