|
|
Line 1: |
Line 1: |
| {{PRJPOAvisosEN20162017}}
| | #REDIRECT [[ist:Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2016-2017 (rascunho)]] |
| {{PRJPOMandatory20162017}}
| |
| {{TOCright}}
| |
|
| |
| {{Aviso|Esta página é obsoleta. Ver [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2016-2017|versão publicada]].}}
| |
|
| |
| O objectivo do projecto é criar uma aplicação que permite gerir um conjunto de programas e as expressões de que são compostos.
| |
| | |
| Neste texto, o tipo '''negrito''' indica um literal (i.e., é exactamente como apresentado); o símbolo <amsmath>\verb*| |</amsmath> indica um espaço; e o tipo ''itálico'' indica uma parte variável (i.e., uma descrição).
| |
| | |
| = Estrutura de expressões e programas =
| |
| | |
| Uma expressão é uma representação algébrica de uma quantidade, ou seja, todas as expressões podem ser avaliadas para obteção de um valor.
| |
| | |
| Uma expressão pode ser descrita por uma linguagem cuja interpretação resulta directamente, ou no valor (tipicamente, aplicável apenas em situações muito simples), ou na representação dessa expressão como uma estrutura de dados (tal como neste projecto), sobre a qual pode ser então executado o processo de avaliação, para determinação do valor correspondente.
| |
| | |
| Neste documento utiliza-se uma linguagem simples e uniforme para descrever qualquer expressão, que pode ser categorizada como expressão primitiva (literais e identificadores) ou como expressão composta (operadores).
| |
| | |
| == Expressões primitivas ==
| |
| | |
| As expressões primitivas, ou representam directamente um valor (expressões literais), ou referem outra expressão (identificadores).
| |
| | |
| ===Literais===
| |
| | |
| As expressões literais são de dois tipos: inteiros e cadeias de caracteres.
| |
| | |
| * Literais inteiros são números decimais não negativos, constituídos por sequências de 1 (um) ou mais dígitos de '''0''' a '''9'''. Exemplos: '''1''', '''23'''
| |
| * As cadeias de caracteres são delimitadas por aspas ('''"''') e podem conter quaisquer caracteres. <!--É possível designar caracteres por sequências especiais (iniciadas por '''\'''), especialmente úteis quando não existe representação gráfica directa. As sequências especiais correspondem aos caracteres [[wp:ASCII|ASCII]] LF, CR e HT ('''\n''', '''\r''' e '''\t''', respectivamente), aspa ('''\"'''), barra ('''\\''').--> Exemplos: '''"hello, world!\n"''', '''"abcd"'''.
| |
| | |
| === Identificadores ===
| |
| | |
| Um identificador permite referenciar um valor. A avaliação do identificador corresponde à obtenção do seu valor.
| |
| | |
| São iniciados por uma letra, seguindo-se 0 (zero) ou mais letras ou dígitos. O comprimento do nome é ilimitado e dois nomes são distintos se houver alteração de maiúscula para minúscula, ou vice-versa, de pelo menos um carácter.
| |
| | |
| Se for referenciado um identificador que não tenha sido definido, o valor devolvido é '''0''' (zero) e o identificador mantém-se indefinido.
| |
| | |
| == Expressões compostas ==
| |
| | |
| Uma expressão composta é constituída por um operador, podendo ter argumentos. Cada argumento é representado por uma expressão.
| |
| | |
| O valor de uma expressão composta corresponde à avaliação do operador sobre os seus argumentos (no caso dos operadores com argumentos) ou simplesmente do operador (no caso dos operadores sem argumentos). O tipo de argumentos e de resultado depende do operador.Por exemplo, há operadores que só suportam argumentos do tipo inteiro. A passagem de tipos inapropriados para um operador é um erro (mas esta verificação apenas deve ser feita quando
| |
| se executa o programa).
| |
| | |
| O formato de representação de uma expressão composta é como se segue:
| |
| | |
| '''(''' ''nome-do-operador'' ''argumento-1'' ... ''argumento-N'' ''')'''
| |
| | |
| Alguns operadores têm um número fixo de argumentos, enquanto outros têm um número variável de argumentos (operadores variádicos).
| |
| | |
| Exemplos:
| |
| * '''(add 1 2)''' -- representa a operação '''add''' com dois argumentos (expressões '''1''' e '''2'''), tendo o significado Java '''1+2'''
| |
| * '''(mul (add 1 2) 3)''' -- representa a operação '''mul''' com dois argumentos (expressões '''(add 1 2)''' e '''3'''), tendo o significado Java '''(1+2)*3'''
| |
| * '''(eq id1 id2)''' -- representa a operação '''eq''' com dois argumentos (expressões designadas pelos identificadores '''id1''' e '''id2''') e testa se os valores das expressões referidas pelos identificadores '''id1''' e '''id2''' são iguais
| |
| | |
| === Tabela de operadores ===
| |
| | |
| Os vários operadores e a correspondente semântica são apresentados na tabela. A maioria dos operadores segue a semântica da família da linguagem C, excepto onde explicitamente indicado. Tal como em C, os valores lógicos são 0 (zero) (valor falso), e diferente de zero (valor verdadeiro).
| |
| | |
| {|
| |
| | '''Designação'''
| |
| | '''Operadores'''
| |
| | '''Operandos'''
| |
| | '''Semântica'''
| |
| |-
| |
| ! style="vertical-align: top; font-weight: normal;" | aritméticos (unários)
| |
| ! style="vertical-align: top; font-weight: normal;" | '''neg'''
| |
| ! style="vertical-align: top; font-weight: normal;" | inteiros
| |
| ! style="vertical-align: top; font-weight: normal;" | C
| |
| |-
| |
| ! style="vertical-align: top; font-weight: normal;" | aritméticos (binários)
| |
| ! style="vertical-align: top; font-weight: normal;" | '''add''' '''sub''' '''mul''' '''div''' '''mod'''
| |
| ! style="vertical-align: top; font-weight: normal;" | inteiros
| |
| ! style="vertical-align: top; font-weight: normal;" | C
| |
| |-
| |
| ! style="vertical-align: top; font-weight: normal;" | comparação (binários)
| |
| ! style="vertical-align: top; font-weight: normal;" | '''lt le ge gt'''
| |
| ! style="vertical-align: top; font-weight: normal;" | inteiros
| |
| ! style="vertical-align: top; font-weight: normal;" | C
| |
| |-
| |
| ! style="vertical-align: top; font-weight: normal;" | igualdade (binários)
| |
| ! style="vertical-align: top; font-weight: normal;" | '''eq ne'''
| |
| ! style="vertical-align: top; font-weight: normal;" | inteiros
| |
| ! style="vertical-align: top; font-weight: normal;" | C
| |
| |-
| |
| ! style="vertical-align: top; font-weight: normal;" | lógicos (unários)
| |
| ! style="vertical-align: top; font-weight: normal;" | '''not'''
| |
| ! style="vertical-align: top; font-weight: normal;" | inteiros
| |
| ! style="vertical-align: top; font-weight: normal;" | C
| |
| |-
| |
| ! style="vertical-align: top; font-weight: normal;" | lógicos (binários)
| |
| ! style="vertical-align: top; font-weight: normal;" | '''and or'''
| |
| ! style="vertical-align: top; font-weight: normal;" | inteiros
| |
| ! style="vertical-align: top; font-weight: normal;" | C -- Para '''and''', o 2º argumento só é avaliado se o 1º não for falso. Para '''or''', o 2º argumento só é avaliado se o 1º não for verdadeiro.
| |
| |-
| |
| ! style="vertical-align: top; font-weight: normal;" | atribuição (binário)
| |
| ! style="vertical-align: top; font-weight: normal;" | '''set'''
| |
| ! style="vertical-align: top; font-weight: normal;" | todos os tipos
| |
| ! style="vertical-align: top; font-weight: normal;" | O valor da expressão (2º argumento) é associado ao identificador (1º argumento). O valor da expressão é o do seu 2º argumento.
| |
| |-
| |
| ! style="vertical-align: top; font-weight: normal;" | sequência (variádico)
| |
| ! style="vertical-align: top; font-weight: normal;" | '''seq'''
| |
| ! style="vertical-align: top; font-weight: normal;" | todos os tipos
| |
| ! style="vertical-align: top; font-weight: normal;" | As sub-expressões são avaliadas em sequência. O valor da expressão é o do seu último argumento.
| |
| |-
| |
| ! style="vertical-align: top; font-weight: normal;" | impressão (variádico)
| |
| ! style="vertical-align: top; font-weight: normal;" | '''print'''
| |
| ! style="vertical-align: top; font-weight: normal;" | todos os tipos
| |
| ! style="vertical-align: top; font-weight: normal;" | As sub-expressões são avaliadas em sequência e os valores correspondentes apresentados na saída. O valor da expressão é o do seu último argumento.
| |
| |-
| |
| ! style="vertical-align: top; font-weight: normal;" | leitura (sem argumentos)
| |
| ! style="vertical-align: top; font-weight: normal;" | '''readi''' '''reads'''
| |
| ! style="vertical-align: top; font-weight: normal;" | -
| |
| ! style="vertical-align: top; font-weight: normal;" | Pedem a introdução (pelo utilizador) de valores com os tipos correspondentes.
| |
| |-
| |
| ! style="vertical-align: top; font-weight: normal;" | condicional (trenário)
| |
| ! style="vertical-align: top; font-weight: normal;" | '''if'''
| |
| ! style="vertical-align: top; font-weight: normal;" | condição (1º argumento) deve ser inteira
| |
| ! style="vertical-align: top; font-weight: normal;" | C -- Comporta-se de modo semelhante ao do operador trenário '''?:''' (não exige concordância de tipos entre os 2º e 3º argumentos). Apenas é avaliado o argumento correspondente ao valor lógico indicado pela condição.
| |
| |-
| |
| ! style="vertical-align: top; font-weight: normal;" | ciclo (binário)
| |
| ! style="vertical-align: top; font-weight: normal;" | '''while'''
| |
| ! style="vertical-align: top; font-weight: normal;" | condição (1º argumento) deve ser inteira
| |
| ! style="vertical-align: top; font-weight: normal;" | Avalia o 1º argumento: se o valor lógico for falso, retorna-o; se o valor lógico for verdadeiro, avalia o 2º argumento, após o que reinicia o ciclo com nova avaliação do 1º argumento, etc. O valor da expressão é o valor da mais recente avaliação do seu primeiro argumento, ou seja, devolve sempre o valor correspondente à condição falsa ('''0''', zero).
| |
| |-
| |
| ! style="vertical-align: top; font-weight: normal;" | chamada (unário)
| |
| ! style="vertical-align: top; font-weight: normal;" | '''call'''
| |
| ! style="vertical-align: top; font-weight: normal;" | o nome do programa a chamar deve ser uma cadeia de caracteres
| |
| ! style="vertical-align: top; font-weight: normal;" | Executa o programa nomeado pelo argumento, devolvendo o valor da sua última expressão. <br>Exemplo: '''(call "nome-do-programa")'''
| |
| |}
| |
| | |
| === Exemplos de expressões compostas ===
| |
| | |
| Os exemplos seguintes apresentam casos de uso simples dos operadores acima.
| |
| | |
| Exemplo 1: sequência com 3 expressões (valor '''9'''):
| |
| * '''(seq (add 1 2) (sub 1 2) (mul (add 1 2) 3))'''
| |
| | |
| Exemplo 2: sequência com 5 expressões (valor '''"olá"'''):
| |
| * '''(seq (add 1 2) (sub 1 2) (mul (add 1 2) 3) (div 2 5) "olá")'''
| |
| | |
| Exemplo 3: sequência com 2 expressões (valor final '''0''') (note-se que esta sequência corresponde a um pequeno "programa" que apresenta o valor do identificador '''ix''' na saída):
| |
| * '''(seq (set ix 0) (while (lt ix 30) (seq (print "ix =" ix) (set ix (add ix 1)))))'''
| |
| | |
| == Estrutura de um programa ==
| |
| | |
| Um programa é formado por um conjunto de expressões, tem um nome e pode ser executado. A execução de um programa corresponde a avaliar todas as suas expressões sequencialmente, com início na primeira.
| |
| | |
| = Funcionalidade do Interpretador =
| |
| | |
| O interpretador permite interpretar (representar o texto como objectos) e avaliar expressões (calcular os seus valores). Possui também várias formas de preservar o seu estado (não é possível manter várias versões do estado do interpretador em simultâneo).
| |
| | |
| == Interpretação de expressões ==
| |
| | |
| As expressões, apresentadas ao interpretador em forma de texto, devem ser interpretadas antes de serem armazenadas. O texto original não é preservado. Note-se que o processo de interpretação (conversão do texto para estruturas/objectos) é diferente do de avaliação (conversão das estruturas/objectos para valores).
| |
| | |
| O texto a interpretar (expressões ou programas) pode ser providenciado via interface do próprio interpretador ou na forma de um ficheiro que contém um programa.
| |
| | |
| Uma falha de interpretação causa o lançamento de uma excepção no analisador do interpretador.
| |
| | |
| {{Suggestion|Note-se que não é necessário implementar de raiz o analisador de expressões e programas do interpretador. Será disponibilizado um analisador já parcialmente concretizado. Este analisador é responsável por processar um programa ou uma expressão e realizar a conversão de texto para a estrutura de dados correspondente. Será apenas necessário indicar as entidades utilizadas para representar um programa ou uma expressão.}}
| |
| | |
| == Armazenamento de programas ==
| |
| | |
| O interpretador permite associar nomes a programas, preservando-os. Note-se que isto não corresponde a guardar valores calculados por esses programas, mas a guardar as suas descrições, i.e., as resultantes da interpretação da forma textual correspondente. Se um nome já estiver em uso, a associação ao programa anterior é perdida.
| |
| | |
| == Interpretação de programas ==
| |
| | |
| A interpretação de programas e, consequentemente, das suas expressões, deve ser feita de forma flexível. Ou seja, deve ser possível -- sem alterar o código das expressões ou do interpretador -- definir novas formas de avaliação. Por omissão, a interpretação corresponde simplesmente à apresentação de uma forma textual do programa (e das suas expressões).
| |
| | |
| Uma outra interpretação possível é o cálculo dos valores das expressões do programa, correspondente à execução desse programa.
| |
| | |
| <!--== Escrita textual ==
| |
| | |
| É possível escrever todo o conteúdo da calculadora como uma sequência de atribuições de expressões a identificadores (ficheiro textual). Desta forma, o resultado da avaliação dessa sequência é indistinguível do conteúdo original da calculadora.
| |
| -->
| |
| == Serialização ==
| |
| | |
| É possível reiniciar, guardar e recuperar o estado actual do interpretador, preservando todos os programas e correspondentes nomes.
| |
| | |
| = Interacção com o Utilizador =
| |
| | |
| Descreve-se nesta secção a '''funcionalidade máxima''' da interface com o utilizador. Em geral, os comandos pedem toda a informação antes de proceder à sua validação (excepto onde indicado). Todos os menus têm automaticamente a opção '''Sair''' (fecha o menu).
| |
| | |
| As operações de leitura e escrita '''devem''' realizar-se através do objecto '''ist.po.ui.Dialog.IO'''. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] ('''po-uuilib''' e '''pex-app'''). As mensagens não podem ser usadas no núcleo da aplicação ('''pex-core'''). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes de qualquer implementação.
| |
| | |
| As excepções usadas na interacção, excepto se indicado, são subclasses de '''ist.po.ui.DialogException''', são lançadas pelos comandos e tratadas por '''ist.po.ui.Menu'''. Outras excepções não devem substituir as fornecidas nos casos descritos.
| |
| | |
| {{CVSCode|Note-se que os comandos e menus a seguir descritos, assim como o programa principal, já estão parcialmente implementados nas classes das ''packages'' '''pex.app''', '''pex.app.main''' e '''pex.app.evaluator'''. Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório CVS|CVS]] (módulo '''pex-app''').}}
| |
| | |
| == Menu Principal ==
| |
| | |
| As acções do menu, listadas em '''pex.app.main.MenuEntry''', permitem gerir a salvaguarda do estado da aplicação: [[#Salvaguarda do Estado Actual do Interpretador|Criar]], [[#Salvaguarda do Estado Actual do Interpretador|Abrir]], [[#Salvaguarda do Estado Actual do Interpretador|Guardar]], [[#Criação, Leitura e Escrita de Programas|Criar Programa]], [[#Criação, Leitura e Escrita de Programas|Ler Programa]], [[#Criação, Leitura e Escrita de Programas|Escrever Programa]] e [[#Manipulação de Programa|Manipulação de Programa]]. A classe '''pex.app.main.Message''' define os métodos para geração das mensagens de diálogo. Inicialmente, a aplicação tem uma memória vazia.
| |
| | |
| === Salvaguarda do Estado Actual do Interpretador ===
| |
| | |
| O conteúdo do interpretador (inclui todos os programas actualmente carregados pelo interpretador) pode ser guardado para posterior recuperação (via serialização Java: '''java.io.Serializable'''). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:
| |
| | |
| * '''Criar''' -- Cria um novo interpretador sem ficheiro associado.
| |
| * '''Abrir''' -- Carrega um interpretador anteriormente salvaguardado, ficando o interpretador carregado associado ao ficheiro nomeado: pede-se o nome do ficheiro a abrir ('''openFile()'''). Caso o ficheiro não exista, é apresentada a mensagem '''fileNotFound()'''.
| |
| * '''Guardar''' -- Guarda o estado actual do interpretador no ficheiro associado. Se não existir associação, pede-se o nome do ficheiro a utilizar, ficando a ele associado. Esta interacção realiza-se através do método '''newSaveAs()'''. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.
| |
| | |
| A opção '''Sair''' nunca guarda o estado da aplicação, mesmo que existam alterações.
| |
| | |
| {{CVSCode|Estes comandos já estão parcialmente implementados nas classes da ''package'' '''pex.app.main''' (disponível no CVS), respectivamente: '''New''', '''Open''', '''Save'''.}}
| |
| | |
| === Criação, Leitura e Escrita de Programas ===
| |
| | |
| É possível criar novos programas (vazios), ler programas a partir de ficheiros textuais e escrever programas sob a forma de ficheiros textuais. As operações são as seguintes:
| |
| | |
| * '''Criar Programa''' -- Permite criar um programa vazio. É pedido o nome do programa através de '''requestProgramId()'''. A utilização de um nome previamente registado substitui o programa a ele associado por um programa vazio.
| |
| * '''Ler Programa''' -- Permite ler e interpretar o texto de um programa a partir de um ficheiro. É lido o ficheiro indicado pelo método '''programFileName()'''. A leitura de novo ficheiro com o mesmo nome substitui o programa anterior com esse nome (nome do ficheiro indicado).
| |
| * '''Escrever Programa''' -- Permite guardar um programa como um ficheiro de texto, passível de ser lido novamente pelo interpretador. O interpretador pede o identificador do programa '''requestProgramId()''' e o nome do ficheiro onde deve ser guardado o programa, através do método '''programFileName()'''. Escritas no mesmo ficheiro substituem o conteúdo anterior, não ficando associado ao interpretador.
| |
| | |
| {{CVSCode|Estes comandos já estão parcialmente implementados nas classes da ''package'' '''pex.app.main''' (disponível no CVS), respectivamente: '''NewProgram''', '''ReadProgram''', '''WriteProgram'''.}}
| |
| | |
| === Manipulação de Programa ===
| |
| | |
| Abre o menu de edição (alteração) de um programa e do seu conteúdo. O interpretador pede o identificador do programa '''requestProgramId()'''. Se o programa não existir, é comunicado o erro através de '''noSuchProgram()'''.
| |
| | |
| Este comando já está parcialmente implementado na classe '''pex.app.main.EditProgram''' (disponível no CVS).
| |
| | |
| == Menu de Manipulação de Programas ==
| |
| | |
| Este menu permite efectuar operações sobre um programa. A lista completa é a seguinte: [[#Listar programa|Listar programa]], [[#Executar|Executar]], [[#Adicionar expressão|Adicionar expressão]], [[#Substituir expressão|Substituir expressão]], [[#Mostrar os identificadores presentes no programa|Mostrar os identificadores presentes no programa]], [[#Mostrar os identificadores não inicializados do programa|Mostrar os identificadores não inicializados do programa]].
| |
| | |
| As etiquetas das opções deste menu estão definidas na classe '''pex.app.evaluator.Label'''. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''pex.app.evaluator.Message'''.
| |
| | |
| {{CVSCode|Estes comandos já estão parcialmente implementados nas classes da ''package'' '''pex.app.evaluator''' (disponível no CVS), respectivamente: '''ShowProgram''', '''RunProgram''', '''AddExpression''', '''ReplaceExpression''', '''ShowAllIdentifiers''', '''ShowUninitializedIdentifiers'''.}}
| |
| | |
| === Listar programa ===
| |
| | |
| Este comando apresenta a lista de expressões do programa em formato textual.
| |
| | |
| === Executar Programa ===
| |
| | |
| Este comando executa o programa.
| |
| | |
| === Adicionar expressão ao programa ===
| |
| | |
| Este comando permite adicionar uma nova expressão ao programa. Para tal, é pedida a posição de inserção, através de '''requestPosition()''', sendo a nova expressão aí inserida. A nova expressão é lida como resposta a '''requestExpression()'''.
| |
| | |
| Se a indicação de posição for inválida, o comando deve lançar a excepção '''pex.app.BadPositionException''' e o programa não é alterado.
| |
| | |
| Note-se que a nova expressão é interpretada: se a excepção '''pex.ParserException''' (do "core") for recebida, então a excepção '''pex.app.BadExpressionException''' deve ser lançada pelo comando. Neste caso, o programa não deve ser alterado.
| |
| | |
| === Substituir expressão no programa ===
| |
| | |
| Este comando permite substituir uma expressão existente no programa por uma nova expressão. Para tal, é pedida a posição de inserção, através de '''requestPosition()''', sendo a expressão aí existente substituída pela nova expressão. A nova expressão é lida como resposta a '''requestExpression()'''.
| |
| | |
| Se a indicação de posição for inválida, o comando deve lançar a excepção '''pex.app.BadPositionException''' e o programa não é alterado.
| |
| | |
| Note-se que a nova expressão é interpretada: se a excepção '''pex.ParserException''' (do "core") for recebida, então a excepção '''pex.app.BadExpressionException''' deve ser lançada pelo comando. Neste caso, o programa não deve ser alterado.
| |
| | |
| === Mostrar os identificadores presentes no programa ===
| |
| | |
| Este comando permite listar todos os identificadores presentes no programa (apresentado um identificador por linha), tanto nas expressões de definição, como nas que usam identificadores.
| |
| | |
| === Mostrar os identificadores do programa sem inicialização explícita ===
| |
| | |
| Este comando permite listar todos os identificadores presentes no programa que não são objecto de nenhuma incialização explícita (apresentado um identificador por linha), i.e., não terem um valor previamente associado via operador '''set'''.
| |
| | |
| = Leitura de Programas a Partir de Ficheiros Textuais =
| |
|
| |
| Além das opções de manipulação de ficheiros descritas no [[#Salvaguarda do Documento Actual|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java '''[[#Execução dos Programas e Testes Automáticos|import]]'''. Este ficheiro contém um programa que é avaliado pelo interpretador. <!-- Se não existirem definições de variáveis, a avaliação não deixa traços na memória da calculadora. Apenas é lida a primeira expressão presente no ficheiro.--> O programa fica registado com o nome '''import'''.
| |
| | |
| == Exemplo de ficheiro a importar ==
| |
| | |
| Este programa é composto por três expressões, a última das quais é um ciclo.
| |
| | |
| (seq (add 1 2.3) (sub 1 2) (mul (add 1 2) 3))
| |
| (seq (add 1 2.3) (sub 1 2) (mul (add 1 2) 3.2) (div 2 5) "olá")
| |
| (seq (set ix 0) (while (lt ix 30) (seq (print "ix =" ix) (set ix (add ix 1)))))
| |
| | |
| == Exemplo de pequeno "programa" ==
| |
| | |
| Este exemplo corresponde a um pequeno "programa" ('''triangulos.pex''') para verificar se três segmentos de recta formam um triângulo. <!--Tal como no exemplo anterior, os identificadores '''a''', '''b''' e '''c''' ficam associados a valores usados durante a avaliação, embora a expressão do "programa" não seja memorizada.-->
| |
| | |
| (print "Introduza as dimensões do 1º lado do triângulo: ")
| |
| (set a (readi))
| |
| (print "Introduza as dimensões do 2º lado do triângulo: ")
| |
| (set b (readi))
| |
| (print "Introduza as dimensões do 3º lado do triângulo: ")
| |
| (set c (readi))
| |
| (if (lt a 1)
| |
| (print "As dimensões dos lados do triângulo devem ser positivas")
| |
| (if (lt b 1)
| |
| (print "As dimensões dos lados do triângulo devem ser positivas")
| |
| (if (lt c 1)
| |
| (print "As dimensões dos lados do triângulo devem ser positivas")
| |
| (if (le (add a b) c)
| |
| (print "Não é um triângulo")
| |
| (if (le (add a c) b)
| |
| (print "Não é um triângulo")
| |
| (if (le (add c b) a)
| |
| (print "Não é um triângulo")
| |
| (if (eq a b)
| |
| (if (eq b c)
| |
| (print "Triângulo equilátero")
| |
| (print "Triângulo isósceles"))
| |
| (if (eq b c)
| |
| (print "Triângulo isósceles")
| |
| (print "Triângulo escaleno")))))))))
| |
| | |
| <!--A aplicação pode produzir ficheiros textuais com o conteúdo da sua memória, mas nunca os lê a partir de nenhum comando.
| |
| -->
| |
| Embora o interpretador de expressões tenha de assinalar problemas relativos à interpretação de expressões mal especificadas, assume-se que não existem entradas mal-formadas nestes ficheiros (embora tenham de ser detectadas).
| |
| | |
| = Considerações sobre Flexibilidade e Eficiência =
| |
|
| |
| Devem ser possíveis extensões ou alterações de funcionalidade com impacto mínimo no código já produzido para a aplicação. O objectivo é aumentar a flexibilidade da aplicação relativamente ao suporte de novas funções. Em particular, a solução encontrada para salvaguardar textualmente o conteúdo do documento deve ser suficientemente flexível de modo a permitir visualizar o conteúdo de um documento noutro formato (por exemplo, XML) sem que isso implique alterações no código ''core'' da aplicação.
| |
| | |
| = Execução dos Programas e Testes Automáticos =
| |
| | |
| Usando os ficheiros '''test.pex''', '''test.in''' e '''test.out''', é possível verificar automaticamente o resultado correcto do programa. Note-se que é necessária a definição apropriada da variável '''CLASSPATH''' (ou da opção equivalente '''-cp''' do comando '''java'''), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação ('''pex.app.App.main'''). As propriedades são tratadas automaticamente pelo código de apoio.
| |
| | |
| java -Dimport=test.pex -Din=test.in -Dout=test.outhyp pex.app.App
| |
| | |
| Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída '''test.outhyp'''. Em caso de sucesso, os ficheiros das saídas esperada ('''test.out''') e obtida ('''test.outhyp''') devem ser iguais. A comparação pode ser feita com o comando:
| |
| | |
| diff -b test.out test.outhyp
| |
| | |
| Este comando não deve produzir qualquer resultado quando os ficheiros são iguais. Note-se, contudo, que este teste não garante o correcto funcionamento do código desenvolvido, apenas verificando alguns aspectos da sua funcionalidade.
| |
| | |
| [[category:Ensino]]
| |
| [[category:PO]]
| |
| [[category:Projecto de PO]]
| |
| [[en:Object-Oriented Programming]]
| |