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