M.P.I - 1998/99 - Trabalho Prático Nr. 3
[ DI/UM ]

Introdução

Este trabalho deve ser realizado por grupos com um máximo de três alunos. Deve ser entregue até ao dia 5 de Janeiro de 1999, na recepção do Departamento de Informática , e nele deve constar:

Objectivo do projecto

Pretende-se construir uma calculadora de bolso com interface gráfica. Para isso optou-se por se distinguir duas componentes no projecto:

A interface com o utilizador consiste numa janela que simula uma vulgar calculadora de bolso: dispõe de um visor e de um conjunto de teclas que permitem digitar os números e operações pretendidas. O cálculo dessas operações é delegado a um processo autónomo que, recebendo a informação relativa às teclas digitadas, informa a interface relativamente ao que deve ser visualizado. O diagrama seguinte pretende representar a estrutura do projecto nas suas duas componentes:

Neste trabalho é já fornecida a interface gráfica com o utilizador. Pretende-se então definir um programa na linguagem HASKELL que funcione como servidor de cálculo da calculadora. Ver na última secção os pacotes de programas desenvolvidos pela equipa docente para permitir a realização deste trabalho.

O servidor de cálculo

Chamaremos Servidor de cálculo ao programa em HASKELL que será responsável pelo bom funcionamento da nossa calculadora . Este programa funciona segundo um ciclo que:

Para entendermos que tipo de processamento devemos considerar, note-se que a acção associada a uma tecla depende das que a precederam (e.g. quando se digita a tecla ``='' é efectuada a operação determinada pelas teclas anteriores). Temos então de introduzir o conceito de estado da calculadora, por forma a ser registada a informação a ser mantida pelo programa e que será actualizada ``ao longo dos ciclos de interacção com a interface''.

Podemos então identificar a funcionalidade do servidor de cálculo com a das chamadas máquinas de estados. Uma máquina de estados é fácil de realizar em programação funcional, uma vez que o seu modo de operação é facilmente emulado por uma função que, em cada momento, determina (com base na informação da tecla digitada e no estado actual), qual o próximo estado e a mensagem a ser enviada à interface.

Uma tal função diz-se uma função de transição de estado e tem o tipo:

hscalc :: (String,Estado) -> (String,Estado)

onde Estado é o tipo escolhido para armazenar o estado da aplicação. Vai ter que ser ainda definida uma constante estado_inicial, do tipo Estado, que denotará o estado inicial da aplicação. Então, o pretendido servidor de cálculo poderá ter a forma do seguinte fragmento de código HASKELL :

module Main where

import HsCalc (Estado, hscalc, estado_inicial)

main :: IO ()
main = loop estado_inicial

loop :: Estado -> IO ()
loop e = do --IO
           i <- getLine
           let (o,e') = hscalc (i,e)
           putStr (o ++ "\n")
           loop e'
Nota: Este módulo é de facto análogo à aplicação que consta do «pacote» fornecido para realizar este trabalho prático no sistema operativo LINUX. Na versão para o sistema MS-WINDOWS a aplicação é substancialmente diferente e será objecto de comentários adiante.

A linha de import destina-se a definir os parâmetros atrás referidos. Entendendo getLine e putStr como primitivas para a comunicação com o processo de interface , vemos então que o servidor de cálculo se limita a reagir aos estímulos da interface de acordo com o estabelecido na função de transição hscalc.

Ora o que se pretende realizar neste trabalho é precisamente o módulo responsável pela definição dessa função de transição : o módulo HsCalc.

Como exemplo, apresenta-se de seguida uma definição desse módulo onde simplesmente se ``repete'' a informação recebida da interface (i.e. faz-se o eco dessa informação):

module HsCalc where

type Estado = ()

estado_inicial = ()

hscalc :: (String, Estado) -> (String, Estado)
hscalc = id

Repare-se que neste exemplo não se faz uso do estado, e daí a sua definição como (). É evidente que a funcionalidade que se espera terá que conduzir a definições mais interessantes para esse tipo...!

Sugestões para o desenvolvimento do projecto

Neste trabalho pretende-se que cada grupo defina o módulo HsCalc que ``dá vida'' à interace gráfica fornecida no «material disponível». Essa ``interface'' dispõe de vários tipos de teclas:

A essência deste trabalho consiste em codificar o módulo HsCalc que permita implementar toda a funcionalidade descrita. Há que atender à precedência das operações binárias (2+3*4 deve dar 14 e, por isso, se viermos a digitar essa sequência de teclas e obtivermos 24, isto é, (2+3)*4, as precedências estarão erradas...).

Trata-se de um trabalho com razoável complexidade que pode ser mais ou menos valorizado conforme a qualidade e/ou quantidade de informação tida em conta. Admite-se que não se faça uso de toda a interface (algumas teclas podem ficar inactivas). Em vez de se propôr uma funcionalidade básica para a calculadora deixa-se ao critério de cada grupo qual a porção da funcionalidade que se propõe implementar. Alguns exemplos de aspectos implementáveis são:

Outras questões relativas ao comportamento da calculadora são também deixadas ao critério de cada grupo (como o comportamento em situações anómalas, etc.). Tipicamente, essas questões podem ser resolvidas por analogia, isto é, verificando como reage uma calculadora «real».

Implementação da comunicação entre processos

Este projecto consta de um conjunto de aplicações independentes que cooperam entre si para um fim determinado. Deste forma, estamos já a recorrer a facilidades sofisticadas dos sistemas operativos que suportam a execução destas aplicações.

Neste domínio, limitações no capítulo da gestão de processos do sistema MS-WINDOWS 95/98 obrigam-nos a tornear alguns pontos cuja solução no sistema LINUX é trivial. É evidente que essas dificuldades saem fora do âmbito deste curso. A sua referência neste enunciado deve-se somente ao facto de se traduzirem por diferenças entre as versões dos dois sistemas operativos.

Apresenta-se agora uma breve descrição do mecanismo de comunicação entre os processos em cada um dos sistemas:

LINUX

O processo responsável pela interface gráfica é implementado numa linguagem de script particularmente vocacionada para a realização desse tipo de aplicações: TCLTK . Esse processo gere a janela respectiva e invoca um sub-processo que executa o programa HASKELL srvcalc.hs. A comunicação entre os processos é realizada por via do stdin e stdout, que se traduz no facto de, sobre o ponto de vista do programa HASKELL , ser indiferente estar a interagir com o processo de interface ou com um utilizador via teclado e monitor .

MS-Windows

No sistema MS-WINDOWS a interface é realizada por intermédio de uma página WWW . Para a invocação do servidor de cálculo faz-se com que o HASKELL seja suportado como linguagem de script do Internet Explorer . Para isso é necessário instalar algum software adicional, processo que é referido detalhadamente no ficheiro README.TXT contido no «material disponível».

Material disponível

Linux
Quem pretender realizar este trabalho em ambiente LINUX deverá fazer o 'download' do seguinte ficheiro .tgz (2076 bytes ). Começar primeiro por ler o ficheiro README.TXT que fica disponível na directoria criada após a decompactação.
MS Windows
Quem pretender realizar este trabalho em ambiente MS-WINDOWS deverá fazer o 'download' de três ficheiros .tgz (533 Kbyte , 470 Kbyte e 530 Kbyte ). Começar por decompactar o primeiro e por ler o ficheiro README.TXT que fica disponível na directoria criada. Nesse ficheiro encontram-se instruções para utilização dos outros ficheiros (de 470 Kbyte e de 530 Kbyte ).


Voltar à página principal de MP-I .
Outras disciplinas leccionadas pelo DIUM

12/14/1998
J.N. Oliveira