Trabalho
Extra
Descreva resumidamente uma linguagem
de programação diferente de tudo o que você já viu. Utilize no máximo uma
página. Preferencialmente menos. Escreva apenas o suficiente para que o leitor
possa ter uma idéia de como
é e como funciona a linguagem. Não é necessário a
gramática da linguagem ou descrições detalhadas.
A linguagem pode ser de propósito
geral, específica (para uma certa finalidade), gráfica, fácil, difícil,
absurda, razoável, útil, inútil, impossível de ser implementada, etc.
Como exemplo, veja a língua Andrômeda. Esta é uma língua natural e não uma
linguagem de programação. Mas serve como exemplo.
Exemplos de construções de
linguagens ou linguagens são dados abaixo. Cada item trata de uma linguagem
diferente.
- Esta linguagem permite comandos que
começam com @begin e terminam com @end. Todos os comandos entre @begin e
@end são executados em tempo de compilação e podem manipular informações
disponíveis ao compilador como a lista de variáveis locais, a lista de
subrotinas já declaradas, etc. Entre @begin e @end, comandos print
produzem saída que é passada ao compilador e compiladas. É como se
@begin comandos @end
fosse substituído pela saída produzida pelos comandos print. Exemplo:
void repeat() {
@begin
print(“int “);
for(char ch = ‘a’; ch < ‘h’;
ch++)
print( ch + “, “);
print(“h;”);
@end
...
}
Este código, quando compilado, seria equivalente a
void repeat() {
int a, b, c, d, e, f, g, h;
...
}
- Esta linguagem é Orientada a Objetos. A
atribuição “p = s”
em
// sintaxe de
Java
Stack s = new Stack();
Pilha p = new Pilha();
p = s;
é ilegal. Os tipos são
incompatíveis (assuma isto). Além disto, os métodos de Stack estão em
Inglês e os de Pilha, em Português, embora sejam métodos equivalentes
(assuma isto também).
O programador constrói
uma classe shell que traduz os métodos Stack para os de Pilha. Ao atribuir
s a p, um objeto da classe shell é criado e acoplado a s antes da
atribuição. Assim, pode-se chamar os métodos de Stack do objeto apontado
por s usando-se os métodos em Português de Pilha:
p.empilha(1); // chama
push(1) do objeto apontado por s
Poder-se-ia aplicar o mesmo aos tipos básicos:
int i = 1.5;
O valor de i é 1, mas na
verdade o 1.5 está guardado dentro de i e reaparece em alguns casos:
float f = i;
// f receberá 1.5 e não 1
System.out.println(2*i); //
imprime 3
Um outro tipo de objeto shell poderia ser acoplado a
um objeto normal de tal forma que alguns métodos do objeto fossem
substituídos pelos do shell. Por exemplo, um método chamado “search” do
objeto shell substituiria um método de mesmo nome do objeto. Naturalmente,
há uma classe shell definida pelo programador. Exemplo:
Stack s = new Stack();
attachShell(s, new
StackShell()); // acopla o shell ao
objeto
s.push(1);
Assumindo que StackShell
possui um método push, em “s.push(1)” do código acima o método chamado
seria push de StackShell.
- Os comandos das linguagens convencionais
estão no imperativo: “faça isto, faça aquilo”. Na linguagem deste item,
poderíamos ter comandos no passado, futuro, condicional, etc. Assim, o
primeiro comando de um procedimento poderia estar no presente, o segundo
no futuro e o terceiro no condicional (só seria executado se algum outro
comando já o fosse). O comando no futuro só seria executado algum tempo
pré-fixado depois de iniciado o procedimento. Poderia existir um tempo
diferente para cada procedimento. Os comandos no presente seriam executados
todos concorrentemente, já que todos devem acontecer no presente, o que
implica simultaneidade. Esta sugestão de linguagem foi “projetada” por eu
e Jander.
- O Jander também fez a sua linguagem: Moro.
- Nesta linguagem, um programa seria
composto por blocos de código colocados em uma grade quadrangular, iguais
aos de um Autômata
Celular (AC) bidimensional. Cada bloco de código é colocado em uma das
células da grade e possui uma entrada de cada um dos vizinhos (exceto os
vizinhos transversais). Cada bloco envia a saída do que produz para todos
os seus vizinhos (de uma maneira que iremos explicar adiante). Há blocos
ativos, que são executados e blocos inativos, que não são executados. Uma
configuração inicial diz quais os blocos ativos. Um relógio regula a
execução dos blocos de código. Ao primeiro tick, os blocos ativos são
executados e enviam a sua saída para os vizinhos. Algumas regras dizem
quais os blocos ficaram ativos ou inativos para o próximo passo (tick),
igual a um Autômata Celular. No próximo tick, tudo se repete: os blocos
ativos pegam as entradas produzidas pelos vizinhos no passo anterior (ou 0
se um vizinho estava inativo) e produzem saídas passadas aos vizinhos.
Tenho mais algumas idéias mas não tenho tempo de escrevê-las todas aqui.
Se alguém quiser conhecê-las, me procure.