|
|
| (126 intermediate revisions by the same user not shown) |
| 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}}
| |
| <!--'''<font color="red">ÉPOCA NORMAL</font>'''-->
| |
| | |
| O objectivo do projecto é criar uma aplicação que permite ver e gerir um conjunto de expressões.
| |
| | |
| Neste texto que se segue, o tipo '''negrito''' indica um literal (i.e., é exactamente como apesentado); 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).
| |
| | |
| = Funcionalidade da Calculadora =
| |
| | |
| A calculadora permite interpretar e avaliar expressões. Possui também várias formas de preservar o seu estado.
| |
| | |
| == Interpretação de expressões ==
| |
| | |
| As expressões, apresentadas à calculadora em forma de texto, devem ser interpretadas antes de serem armazenadas. O texto original não é preservado.
| |
| | |
| O texto de uma expressão a interpretar pode ser providenciado via interface da própria calculadora ou na forma de um ficheiro que contém a expressão.
| |
| | |
| A falha de interpretação de uma expressão causa o lançamento da excepção '''pex.ParserException'''.
| |
| | |
| == Armazenamento de expressões ==
| |
| | |
| A calculadora permite associar expressões a identificadores, preservando-as. Note-se que isto não corresponde a guardar o valor da expressão, mas a guardar toda a informação sobre a expressão, resultante da interpretação da forma textual. Se o identificador já estever em uso, a associação à expressão anterior é perdida.
| |
| | |
| A calculadora permite, dado um identificador, recuperar a expressão a ele associada. Se o identificador não tiver sido definido, o valor nulo é retornado e o identificador mantém-se indefinido.
| |
| | |
| Os identificadores definidos na calculadora podem ser utilizados na escrita de novas expressões, antes ou depois de terem sido definidos (são sempre avaliados quando a expressão onde ocorrem é avaliada, i.e., não são "expandidos" quando a expressão onde ocorrem é interpretada).
| |
| | |
| == Avaliação de expressões ==
| |
| | |
| A avaliação de expressões guardadas na calculadora é feita de forma flexível, sendo possível -- sem alterar o código das expressões ou da calculadora -- definir novas formas de avaliação. O avaliador por omissão calcula simplesmente o valor de uma expressão.
| |
| | |
| Uma outra "avaliação" possível é a produção de descrições textuais a partir de expressões (isto permite recuperar a forma inicial das expressões).
| |
| | |
| == 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 a sessão de interacção com o utilizador.
| |
| | |
| = Estrutura de uma expressão =
| |
| | |
| Uma expressão é uma representação algébrica de uma quantidade: todas as expressões têm um tipo e devolvem um valor.
| |
| | |
| Uma expressão pode ser descrita por uma linguagem cuja interpretação resulta na representação dessa expressão como uma estrutura de dados, sobre a qual pode ser executado o processo de avaliação, para determinação do valor da expressão.
| |
| | |
| 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 três tipos: inteiros, reais e cadeias de caracteres.
| |
| | |
| * Um literal inteiro é um número não negativo. Literais inteiros decimais são constituídos por sequências de 1 (um) ou mais dígitos de '''0''' a '''9'''. Exemplos: '''1''', '''23'''
| |
| * Um literal reais é expressos em notação científica (tal como em C). Um literal sem '''.''' (ponto decimal) nem parte exponencial é do tipo inteiro. Exemplos: '''12.34e-24''' = 12.34 x 10<sup>-24</sup>.
| |
| * 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 ===
| |
| | |
| 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.
| |
| | |
| == Expressões compostas ==
| |
| | |
| Os valores das expressões compostas correspondem à avaliação de um operador sobre os seus argumentos. O tipo de argumentos e de resultado depende do operador: alguns operadores podem aceitar vários tipos de argumentos e produzir vários tipos de resultados, enquanto outros podem restringir tanto os tipos dos argumentos como o do resultado.
| |
| | |
| 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'''), tedo 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'''), tedo 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, reais
| |
| ! 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, reais
| |
| ! style="vertical-align: top; font-weight: normal;" | C -- '''mod''' é apenas para inteiros
| |
| |-
| |
| ! 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, reais, strings
| |
| ! style="vertical-align: top; font-weight: normal;" | C -- Para cadeias de caracteres, como '''strcmp'''
| |
| |-
| |
| ! 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, reais
| |
| ! style="vertical-align: top; font-weight: normal;" | C -- Para cadeias de caracteres, como '''strcmp'''
| |
| |-
| |
| ! 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''', '''readr''', '''reads'''
| |
| ! style="vertical-align: top; font-weight: normal;" | inteiros, reais, cadeias de caracteres (respectivamente)
| |
| ! 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, returna-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.
| |
| |}
| |
| | |
| === 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.3) (sub 1 2) (mul (add 1 2) 3))'''
| |
| | |
| Exemplo 2: seuência com 5 expressões (valor '''"olá"'''):
| |
| * '''(seq (add 1 2.3) (sub 1 2) (mul (add 1 2) 3.2) (div 2 0) "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)))))'''
| |
| | |
| = 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-uilib''' e '''pex-support'''). As mensagens não podem ser usadas no núcleo da aplicação ("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.
| |
| | |
| 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.textui''', '''pex.textui.main''' e '''pex.textui.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-textui''').
| |
| | |
| == Menu Principal ==
| |
| | |
| As acções do menu, listadas em '''pex.textui.main.MenuEntry''', permitem gerir a salvaguarda do estado da aplicação, assim como operar sobre o documento actual: [[#Salvaguarda do Documento Actual|Criar]], [[#Salvaguarda do Documento Actual|Abrir]], [[#Salvaguarda do Documento Actual|Guardar]], [[#Salvaguarda do Documento Actual|Guardar Textualmente]] e [[#Editar|Editar]]. A classe '''pex.textui.main.Message''' define os métodos para geração das mensagens de diálogo. Inicialmente, a aplicação tem um calculadora vazia.
| |
| | |
| === Salvaguarda do Documento Actual ===
| |
| | |
| O conteúdo do documento 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 documento anónimo não associado a nenhum ficheiro.
| |
| * '''Abrir''' -- Carrega um documento anteriormente salvaguardado, ficando o documento 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 documento actual no ficheiro associado. Se não existir associação, pede-se o nome do ficheiro a utilizar, ficando a ele associada. 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.
| |
| * '''Guardar Textualmente''' -- Guarda as expressões da calculadora num ficheiro. O nome do ficheiro a abrir para escrita é sempre pedido ('''openFile()'''), não ficando associado à calculadora. Esta interacção realiza-se através do método '''newSaveAs()'''. Escritas no mesmo ficheiro substituem o conteúdo anterior.
| |
| | |
| A opção '''Sair''' nunca guarda o estado da aplicação, mesmo que existam alterações.
| |
| | |
| Estes comandos já estão parcialmente implementados nas classes da ''package'' '''pex.textui.main''' (disponível no CVS): '''New''', '''Open''', '''Save''', '''WriteDescription'''.
| |
| | |
| === Editar ===
| |
| | |
| Abre o menu de edição (alteração) do documento e do seu conteúdo, estabelecendo como secção actual o nível de topo do documento.
| |
| | |
| Este comando já está parcialmente implementado na classe da ''package'' '''pex.textui.main''' (disponível no CVS): '''Edit'''.
| |
| | |
| == Menu de Edição ==
| |
| | |
| Este menu permite efectuar operações sobre um documento. A lista completa é a seguinte: [[#Alterar título|Alterar título]], [[#Listar secções|Listar secções]], [[#Mostrar conteúdo|Mostrar conteúdo]], [[#Ir para secção|Ir para secção]], [[#Inserir secção|Inserir secção]], [[#Nomear secção|Nomear secção]], [[#Remover secção|Remover secção]], [[#Inserir parágrafo|Inserir parágrafo]], [[#Nomear parágrafo|Nomear parágrafo]], [[#Alterar parágrafo|Alterar parágrafo]], [[#Remover parágrafo|Remover parágrafo]].
| |
| | |
| As etiquetas das opções deste menu estão definidas na classe '''edt.textui.section.MenuEntry'''. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''edt.textui.section.Message'''.
| |
| | |
| Em todos os casos, só podem ser indicados secções e parágrafos filhos da secção actual. O documento é estruturalmente semelhante a uma secção, sendo considerado a secção raiz (na primeira abertura deste menu).
| |
| | |
| === Alterar título ===
| |
| | |
| Permite alterar o título da secção actual (ou do próprio documento). Para tal, pede-se o novo título ('''requestSectionTitle()''').
| |
| | |
| Este comando já está parcialmente implementado na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''ChangeTitle'''.
| |
| | |
| === Listar secções ===
| |
| | |
| É apresentada a lista de títulos de todas as subsecções da secção actual (recursivamente): cada título entre chavetas é precedido pelo seu identificador único entre parênteses rectos (ou só os parânteses, caso o identificador não esteja definido). Se algum título for vazio, apresentam-se apenas as chavetas.
| |
| | |
| Exemplos:
| |
| [x123] {Isto é um título}
| |
| [] {Isto é outro título}
| |
| [w83] {}
| |
| [] {}
| |
| | |
| Este comando já está parcialmente implementado na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''ListSections'''.
| |
| | |
| === Mostrar conteúdo ===
| |
| | |
| Apresenta o título e todo o conteúdo da secção actual: o texto de cada parágrafo é apresentado por ordem; cada secção é apresentada tal como no caso da apresentação do índice, seguida dos seus parágrafos e subsecções (apresentação recursiva).
| |
| | |
| Este comando já está parcialmente implementado na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''ShowContent'''.
| |
| | |
| === Ir para secção ===
| |
| | |
| Permite seleccionar a secção indicada pelo utilizador (através da especificação do identificador local '''requestSectionId()'''). Se a secção indicada não existir, continua na secção actual, sendo apresentada a mensagem '''noSuchSection()'''. Caso contrário, é apresentada a mensagem '''newActiveSection()''' e o menu de edição de secções é aberto para a secção seleccionada.
| |
| | |
| Este comando já está parcialmente implementado na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''SelectSection'''.
| |
| | |
| === Inserir secção ===
| |
| | |
| Permite inserir uma subsecção antes de outra de referência (indicada pelo identificador local '''requestSectionId()'''). É pedido o título ('''requestSectionTitle()''') da nova secção. Se a subsecção de referência não existir, insere a nova subsecção no final da secção actual.
| |
| | |
| Este comando já está parcialmente implementado na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''InsertSection'''.
| |
| | |
| === Nomear secção ===
| |
| | |
| Permite atribuir um identificador único (no contexto do documento) a uma secção. É pedido o identificador local (inteiro) da subsecção a identificar ('''requestSectionId()''') e o identificador único a atribuir ('''requestUniqueId()''') (cadeia de caracteres). Se a secção não existir é apresentada a mensagem '''noSuchSection()''' e a acção termina. Se o identificador já existir, passa a designar a nova secção (a ligação anterior é destruída). Se a secção já tiver um identificador, a mensagem de aviso '''sectionNameChanged()''' é apresentada e é atribuído o novo identificador único à secção.
| |
| | |
| Este comando já está parcialmente implementado na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''NameSection'''.
| |
| | |
| === Remover secção ===
| |
| | |
| Permite remover a secção indicada pelo utilizador através do identificador local ('''requestSectionId()'''). Se a secção indicada não existir, apresenta a mensagem '''noSuchSection()''' e não realiza nenhuma acção.
| |
| | |
| Este comando já está parcialmente implementado na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''RemoveSection'''.
| |
| | |
| === Inserir parágrafo ===
| |
| | |
| Permite inserir um novo parágrafo antes de outro parágrafo da secção actual. É pedido o número do parágrafo de referência ('''requestParagraphId()''') e o texto do novo parágrafo ('''requestParagraphContent()'''). Se o parágrafo de referência não existir, insere o novo parágrafo no final da sequência de parágrafos da secção.
| |
| | |
| Este comando já está parcialmente implementado na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''InsertParagraph'''.
| |
| | |
| === Nomear parágrafo ===
| |
| | |
| Permite atribuir um identificador único (no contexto do documento) a um parágrafo. É pedido o número do parágrafo a identificar ('''requestParagraphId()''') e o identificador único a atribuir ('''requestUniqueId()''') (cadeia de caracteres). Se o parágrafo não existir é apresentada a mensagem '''noSuchParagraph()''' e a acção termina. Se o identificador já existir, passa a designar o novo parágrafo (a ligação anterior é destruída). Se o parágrafo já tiver um identificador, a mensagem de aviso '''paragraphNameChanged()''' é apresentada e é atribuído o novo identificador único ao parágrafo.
| |
| | |
| Este comando já está parcialmente implementado na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''NameParagraph'''.
| |
| | |
| === Alterar parágrafo ===
| |
| | |
| Permite alterar o texto do parágrafo indicado. É pedido o número do parágrafo a alterar ('''requestParagraphId()''') e o texto do novo parágrafo ('''requestParagraphContent()'''). Se o parágrafo indicado não existir, apresenta a mensagem '''noSuchParagraph()''' e não realiza nenhuma acção.
| |
| | |
| Este comando já está parcialmente implementado na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''EditParagraph'''.
| |
| | |
| === Remover parágrafo ===
| |
| | |
| Permite remover o parágrafo indicado pelo utilizador ('''requestParagraphId()'''). Se o parágrafo indicado não existir, apresenta a mensagem '''noSuchParagraph()''' e não realiza nenhuma acção.
| |
| | |
| Este comando já está parcialmente implementado na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''RemoveParagraph'''.
| |
| | |
| = Leitura de Expressões 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 '''import''' (apresentada abaixo; este exemplo está no ficheiro '''test.pex'''). Este ficheiro contém uma expressão que é avaliada pela calculadora, podendo ser usado como forma cómoda de inicialização da sua memória (através de expressões '''set'''). 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.
| |
| | |
| == Exemplo de ficheiro a importar ==
| |
| | |
| Note-se que a sequência de topo garante que são lidas todas as outras. Note-se também que, apesar de nenhuma sequência ser memorizada, o identificador '''ix''' fica registado (associado à expressão correspondente ao último valor da iteração).
| |
| | |
| (seq
| |
| (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 0) "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.
| |
| | |
| (seq
| |
| (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 calculadora 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 da calculadora tenha de assinalar problemas relativos à interpretação de expressões mal especificadas, assume-se que não há 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 o editor de texto. O objectivo é aumentar a flexibilidade da aplicação relativamente ao suporte de novas funções. Em particular, a solução encontrada para visualizar o conteúdo do documento deve ser suficientemente flexível por forma a que se possa 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.import''', '''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 ('''edt.textui.TextEditor.main'''). As propriedades são tratadas automaticamente pelo código de apoio.
| |
| | |
| java -Dimport=test.import -Din=test.in -Dout=test.outhyp edt.textui.TextEditor
| |
| | |
| 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]]
| |