00001
00002 package plp.functional1.expression;
00003
00004 import java.util.HashMap;
00005 import java.util.List;
00006 import java.util.Map;
00007
00008 import plp.expressions1.util.Tipo;
00009 import plp.expressions2.expression.Expressao;
00010 import plp.expressions2.expression.Id;
00011 import plp.expressions2.expression.Valor;
00012 import plp.expressions2.memory.AmbienteCompilacao;
00013 import plp.expressions2.memory.AmbienteExecucao;
00014 import plp.expressions2.memory.VariavelJaDeclaradaException;
00015 import plp.expressions2.memory.VariavelNaoDeclaradaException;
00016 import plp.functional1.declaration.DecFuncao;
00017 import plp.functional1.declaration.DeclaracaoFuncional;
00018 import plp.functional1.memory.AmbienteExecucaoFuncional;
00019 import plp.functional1.util.ValorFuncao;
00020
00021 public class ExpDeclaracao implements Expressao {
00022
00023 List<DeclaracaoFuncional> seqdecFuncional;
00024 Expressao expressao;
00025
00026 public ExpDeclaracao(List<DeclaracaoFuncional> declaracoesFuncionais, Expressao expressaoArg) {
00027 seqdecFuncional = declaracoesFuncionais;
00028 expressao = expressaoArg;
00029 }
00030
00036 public String toString() {
00037 StringBuffer sb = new StringBuffer();
00038 sb.append("let ");
00039 sb.append(seqdecFuncional.toString());
00040 sb.append("\nin\n");
00041 sb.append(expressao.toString());
00042 return sb.toString();
00043 }
00044
00045 public Valor avaliar(AmbienteExecucao ambienteFuncional)
00046 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00047 AmbienteExecucaoFuncional ambiente =
00048 (AmbienteExecucaoFuncional) ambienteFuncional;
00049 ambiente.incrementa();
00050
00051
00052
00053
00054 Map<Id,Valor> auxIdValor = new HashMap<Id,Valor>();
00055 Map<Id,ValorFuncao> auxIdValorFuncao = new HashMap<Id,ValorFuncao>();
00056
00057 resolveBindings(ambiente, auxIdValor, auxIdValorFuncao);
00058
00059 includeBindings(ambiente, auxIdValor, auxIdValorFuncao);
00060
00061 Valor vresult = expressao.avaliar(ambiente);
00062 ambiente.restaura();
00063 return vresult;
00064 }
00065
00066 private void includeBindings(
00067 AmbienteExecucaoFuncional ambiente,
00068 Map<Id,Valor> auxIdValor,
00069 Map<Id,ValorFuncao> auxIdValorFuncao)
00070 throws VariavelJaDeclaradaException {
00071
00072 for(Map.Entry<Id,Valor> idValor:auxIdValor.entrySet()){
00073 Id id = (Id) idValor.getKey();
00074 Valor valor = (Valor) idValor.getValue();
00075 ambiente.map(id, valor);
00076 }
00077
00078 for(Map.Entry<Id,ValorFuncao> idValorFuncao:auxIdValorFuncao.entrySet()){
00079 Id id = (Id) idValorFuncao.getKey();
00080 ValorFuncao valor = (ValorFuncao) idValorFuncao.getValue();
00081 ambiente.mapFuncao(id, valor);
00082 }
00083 }
00084
00085 private void resolveBindings(
00086 AmbienteExecucaoFuncional ambiente,
00087 Map<Id,Valor> auxIdValor,
00088 Map<Id,ValorFuncao> auxIdValorFuncao)
00089 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00090
00091 for(DeclaracaoFuncional decFuncional:this.seqdecFuncional){
00092 if (decFuncional.getAridade() == 0) {
00093 auxIdValor.put(
00094 decFuncional.getID(),
00095 decFuncional.getExpressao().avaliar(ambiente));
00096 } else {
00097 DecFuncao decFuncao = (DecFuncao) decFuncional;
00098 ValorFuncao valorFuncao = decFuncao.getFuncao();
00099 auxIdValorFuncao.put(decFuncional.getID(), valorFuncao);
00100 }
00101 }
00102 }
00103
00115 public boolean checaTipo(AmbienteCompilacao ambiente)
00116 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00117 ambiente.incrementa();
00118
00119 boolean result = false;
00120 try {
00121 result = checkTypeBindings(ambiente);
00122 if (result) {
00123 Map<Id,Tipo> resolvedTypes = resolveTypeBidings(ambiente);
00124 includeTypeBindings(ambiente,resolvedTypes);
00125 result = expressao.checaTipo(ambiente);
00126 }
00127 } finally {
00128 ambiente.restaura();
00129 }
00130 return result;
00131 }
00132
00133 private Map<Id,Tipo> resolveTypeBidings(AmbienteCompilacao ambiente)
00134 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00135 Map<Id,Tipo> resolvedTypes = new HashMap<Id,Tipo>();
00136
00137 for(DeclaracaoFuncional decFuncional:this.seqdecFuncional){
00138 if (resolvedTypes.put(decFuncional.getID(),decFuncional.getTipo(ambiente)) != null) {
00139 throw new VariavelJaDeclaradaException (decFuncional.getID());
00140 }
00141 }
00142 return resolvedTypes;
00143 }
00144
00145 private boolean checkTypeBindings(AmbienteCompilacao ambiente)
00146 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00147 boolean result = true;
00148 for(DeclaracaoFuncional decFuncional:this.seqdecFuncional){
00149 if (!decFuncional.checaTipo(ambiente)) {
00150 ambiente.restaura();
00151 result = false;
00152 }
00153 }
00154 return result;
00155 }
00156
00157
00158 private void includeTypeBindings(AmbienteCompilacao ambiente, Map<Id,Tipo> resolvedTypes)
00159 throws VariavelJaDeclaradaException {
00160 for(Id id:resolvedTypes.keySet()){
00161 Tipo type = (Tipo) resolvedTypes.get(id);
00162 ambiente.map(id, type);
00163 }
00164 }
00165
00177 public Tipo getTipo(AmbienteCompilacao ambiente)
00178 throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
00179 ambiente.incrementa();
00180 for(DeclaracaoFuncional decFuncional:this.seqdecFuncional){
00181 if (decFuncional.getAridade() == 0) {
00182 ambiente.map(
00183 decFuncional.getID(),
00184 decFuncional.getExpressao().getTipo(ambiente));
00185 } else {
00186 DecFuncao decFuncao = (DecFuncao) decFuncional;
00187 Tipo tipo = decFuncao.getFuncao().getTipo(ambiente);
00188 if (tipo != Tipo.TIPO_INDEFINIDO) {
00189 ambiente.map(decFuncional.getID(), tipo);
00190 }
00191 }
00192 }
00193 Tipo vresult = expressao.getTipo(ambiente);
00194 ambiente.restaura();
00195 return vresult;
00196 }
00197
00202 public List<DeclaracaoFuncional> getSeqdecFuncional() {
00203 return seqdecFuncional;
00204 }
00205
00210 public Expressao getExpressao() {
00211 return expressao;
00212 }
00213
00214 }