package lf3.plp.functional2.declaration; import static lf3.plp.expressions1.util.ToStringProvider.listToString; import java.util.ArrayList; import java.util.List; import java.util.Map; import lf3.plp.expressions1.util.Tipo; import lf3.plp.expressions2.expression.Expressao; import lf3.plp.expressions2.expression.Id; import lf3.plp.expressions2.expression.Valor; import lf3.plp.expressions2.memory.AmbienteCompilacao; import lf3.plp.expressions2.memory.AmbienteExecucao; import lf3.plp.expressions2.memory.VariavelJaDeclaradaException; import lf3.plp.expressions2.memory.VariavelNaoDeclaradaException; import lf3.plp.functional1.declaration.DeclaracaoFuncional; import lf3.plp.functional1.util.TipoFuncao; import lf3.plp.functional1.util.TipoPolimorfico; import lf3.plp.functional2.expression.ValorFuncao; /** * @author S�rgio * * To change this generated comment edit the template variable "typecomment": * Window>Preferences>Java>Templates. To enable and disable the creation of type * comments go to Window>Preferences>Java>Code Generation. */ public class DecFuncao implements DeclaracaoFuncional { private Id id; private ValorFuncao valorFuncao; public DecFuncao(Id idFun, ValorFuncao valorFuncao) { this.id = idFun; this.valorFuncao = valorFuncao; } /** * Retorna uma representacao String desta expressao. Util para depuracao. * * @return uma representacao String desta expressao. */ @Override public String toString() { return String.format("fun %s (%s) = %s", id, listToString(valorFuncao .getListaId(), ","), getExpressao()); } public Id getId() { return id; } public Expressao getExpressao() { return valorFuncao.getExp(); } public ValorFuncao getFuncao() { return valorFuncao; } /** * Retorna a aridade da funcao declarada. Variaveis tem aridade 0. * * @return a aridade da funcao declarada. */ private int getAridade() { return valorFuncao.getAridade(); } /** * Realiza a verificacao de tipos desta declara��o. * * @param amb * o ambiente de compila��o. * @return true se os tipos da expressao sao validos; * false caso contrario. * @exception VariavelNaoDeclaradaException * se existir um identificador nao declarado no ambiente. * @exception VariavelNaoDeclaradaException * se existir um identificador declarado mais de uma vez no * mesmo bloco do ambiente. */ public boolean checaTipo(AmbienteCompilacao ambiente) throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException { ambiente.incrementa(); List params = new ArrayList(getAridade()); for (int i = 0; i < getAridade(); i++) { params.add(new TipoPolimorfico()); } Tipo tipo = new TipoFuncao(params, new TipoPolimorfico()); // Mapeia a pr�pria fun��o no ambiente para permitir recurs�o. ambiente.map(id, tipo); boolean result = valorFuncao.checaTipo(ambiente); ambiente.restaura(); return result; } /** * Retorna os tipos possiveis da fun��o declarada. * * @param amb * o ambiente que contem o mapeamento entre identificadores e * tipos. * @return os tipos possiveis desta declara��o. * @exception VariavelNaoDeclaradaException * se houver uma variável não declarada no * ambiente. * @exception VariavelJaDeclaradaException * se houver uma mesma variável declarada duas vezes * no mesmo bloco do ambiente. * @precondition this.checaTipo(); */ public Tipo getTipo(AmbienteCompilacao amb) throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException { amb.incrementa(); List params = new ArrayList(getAridade()); for (int i = 0; i < getAridade(); i++) { params.add(new TipoPolimorfico()); } Tipo tipo = new TipoFuncao(params, new TipoPolimorfico()); amb.map(id, tipo); Tipo result = valorFuncao.getTipo(amb); amb.restaura(); return result; } public void setValorFuncao(ValorFuncao valorFuncao) { this.valorFuncao = valorFuncao; } public DecFuncao clone() { return new DecFuncao(this.id.clone(), this.valorFuncao.clone()); } @Override public void elabora(AmbienteExecucao amb, AmbienteExecucao aux) throws VariavelJaDeclaradaException { aux.map(getId(), getFuncao()); //passos a mais AmbienteExecucao ambienteClone = amb.clone(); ambienteClone.incrementa(); ambienteClone.map(getId(), getFuncao()); getFuncao().setId(getId()); } @Override public void elabora(AmbienteCompilacao amb, AmbienteCompilacao aux) throws VariavelJaDeclaradaException { aux.map(getId(), getTipo(amb)); } @Override public void incluir(AmbienteExecucao amb, AmbienteExecucao aux) throws VariavelJaDeclaradaException { amb.map(getId(), aux.get(getId())); } @Override public void incluir(AmbienteCompilacao amb, AmbienteCompilacao aux, boolean incluirCuringa) throws VariavelJaDeclaradaException { boolean ehCuringa = (aux.get(getId()) == TipoPolimorfico.CURINGA); boolean incluir = (ehCuringa&&incluirCuringa) || (!ehCuringa); if(incluir) amb.map(getId(), aux.get(getId())); } @Override public void reduzir(AmbienteExecucao amb) { setValorFuncao((ValorFuncao)getFuncao().reduzir(amb)); } }