package li2.plp.imperative2.command; import li2.plp.expressions1.util.Tipo; import li2.plp.expressions2.expression.Id; import li2.plp.expressions2.memory.IdentificadorJaDeclaradoException; import li2.plp.expressions2.memory.IdentificadorNaoDeclaradoException; import li2.plp.expressions2.memory.VariavelJaDeclaradaException; import li2.plp.expressions2.memory.VariavelNaoDeclaradaException; import li2.plp.imperative1.command.Comando; import li2.plp.imperative1.memory.AmbienteCompilacaoImperativa; import li2.plp.imperative1.memory.AmbienteExecucaoImperativa; import li2.plp.imperative1.memory.EntradaVaziaException; import li2.plp.imperative1.memory.ErroTipoEntradaException; import li2.plp.imperative1.memory.ListaValor; import li2.plp.imperative2.declaration.DefProcedimento; import li2.plp.imperative2.declaration.ListaDeclaracaoParametro; import li2.plp.imperative2.memory.AmbienteExecucaoImperativa2; import li2.plp.imperative2.util.TipoProcedimento; public class ChamadaProcedimento implements Comando { private Id nomeProcedimento; private ListaExpressao parametrosReais; public ChamadaProcedimento(Id nomeProcedimento, ListaExpressao parametrosReais) { this.nomeProcedimento = nomeProcedimento; this.parametrosReais = parametrosReais; } public AmbienteExecucaoImperativa executar(AmbienteExecucaoImperativa amb) throws IdentificadorNaoDeclaradoException, IdentificadorJaDeclaradoException, EntradaVaziaException, ErroTipoEntradaException { AmbienteExecucaoImperativa2 ambiente = (AmbienteExecucaoImperativa2) amb; DefProcedimento procedimento = ambiente .getProcedimento(nomeProcedimento); /* * o incrementa e o restaura neste ponto servem para criar as variveis * que serao utilizadas pela execucao do procedimento */ ambiente.incrementa(); ListaDeclaracaoParametro parametrosFormais = procedimento .getParametrosFormais(); AmbienteExecucaoImperativa2 aux = bindParameters(ambiente, parametrosFormais); aux = (AmbienteExecucaoImperativa2) procedimento.getComando().executar( aux); aux.restaura(); return aux; } /** * insere no contexto o resultado da associacao entre cada parametro formal * e seu correspondente parametro atual */ private AmbienteExecucaoImperativa2 bindParameters( AmbienteExecucaoImperativa2 ambiente, ListaDeclaracaoParametro parametrosFormais) throws VariavelJaDeclaradaException, VariavelNaoDeclaradaException { ListaValor listaValor = parametrosReais.avaliar(ambiente); while (listaValor.length() > 0) { ambiente.map(parametrosFormais.getHead().getId(), listaValor .getHead()); parametrosFormais = (ListaDeclaracaoParametro) parametrosFormais .getTail(); listaValor = (ListaValor) listaValor.getTail(); } return ambiente; } /** * Realiza a verificacao de tipos desta chamada de procedimento, onde os * tipos dos parametros formais devem ser iguais aos tipos dos parametros * reais na ordem em que se apresentam. * * @param ambiente * o ambiente que contem o mapeamento entre identificadores e * tipos. * @return true se a chamada de procedimeno est� bem tipada; * false caso contrario. */ public boolean checaTipo(AmbienteCompilacaoImperativa amb) throws IdentificadorJaDeclaradoException, IdentificadorNaoDeclaradoException { Tipo tipoProcedimento = amb.get(this.nomeProcedimento); TipoProcedimento tipoParametrosReais = new TipoProcedimento( parametrosReais.getTipos(amb)); return tipoProcedimento.eIgual(tipoParametrosReais); } }