REXX é uma linguagem avançada e bastante antiga para a época. Ele apareceu, de acordo com a Wikipedia, em 1979, ou seja, recentemente completou 40 anos. Não é a linguagem mais antiquada, é claro, mas é uma idade decente.
Rexx é uma abreviação, significa Restructured Extended Executor, que provavelmente se refere a seus ancestrais EXEC / EXEC2. Eu o conheci no sistema operacional VM / SP 3, onde ele veio substituir precisamente essas linguagens de script. Em seguida, tornou-se popular no OS / 2, usado em muitos outros sistemas operacionais, e muitas implementações e dialetos derivados foram criados.
Ele não prestou muita atenção em Habré, tentarei preencher as lacunas deste artigo.
Antepassados, Origens, Autores
A implementação do idioma original tinha um autor, um funcionário do IBM Mike Cowlishaw. Esta implementação foi escrita no assembler do S / 360.
A Wikipedia acredita que o REXX foi influenciado por PL / 1, EXEC e EXEC2 e Algol. No geral, sim, essa linguagem está, sem dúvida, em sua sintaxe - o herdeiro de Algol (ou Pascal, se você preferir). Ou seja, loops, blocos, etc. as construções não são cercadas por chaves, mas por palavras-chave, do / end, por exemplo. Quanto ao EXEC e EXEC2, o REXX foi criado como um substituto para eles e talvez não tenha mais nada a ver com eles. Mas comparado ao PL / 1 REXX é muito mais simples, e o objetivo do idioma é completamente diferente.
Como é o código REXX:
/* 1 10 */ sum = 0 do count = 1 to 10 say count sum = sum + count end say " " sum"."
Funcionalidades
Qual, na minha opinião, foi o mais interessante ou incomum nesse idioma?
1. A sintaxe da linguagem é bastante livre, não é Fortran, é claro. Algol e Pascal parecem mais. No básico em geral também.
Existem operadores típicos de programação estrutural.
Existem funções e procedimentos. Aqui, é um pouco incomum que o procedimento oculte todas as variáveis do código de chamada por padrão, mas algumas delas podem ser disponibilizadas usando a construção de chave expor <lista de variáveis>.
Digitar é dinâmico. Uma variável pode ser interpretada como uma sequência ou como um número, em diferentes momentos da execução, e também não pode ser definida (isso pode ser verificado, embora esteja torto). De fato, a linguagem possui um tipo de dados primitivo - sequências sobre as quais operações aritméticas podem ser executadas se a sequência for um número correto.
Aqui está um pequeno exemplo da Wikipedia:
say hello /* => HELLO */ hello = 25 say hello /* => 25 */ hello = "say 5 + 3" say hello /* => say 5 + 3 */ interpret hello /* => 8 */ drop hello say hello /* => HELLO */
Isso mostra que a variável indefinida na primeira (e última) linha é calculada em seu nome em letras maiúsculas. Esta é a maneira de verificar se há incerteza.
A declaração de interpretação é uma analogia do que hoje é geralmente chamado de eval.
O tratamento de erros talvez seja mais parecido com o Básico:
signal on halt do forever ... /* */ end halt: /* . halt, */ exit
Este é o processamento da conclusão do programa (pelo botão do terminal). Além da parada, existem outros "sinais", incluindo, por exemplo, sintaxe (erro de sintaxe no código interpretado). Não me lembro de ter aplicado praticamente, mas é bastante lógico verificar a exatidão sintática, por exemplo, o que é fornecido à entrada de interpretação.
2. Não tinha expressões regulares, como dizemos em Perl (quase 10 anos foram deixados antes de Perl, no entanto). O próprio conceito de expressões regulares apareceu anteriormente, e elas certamente já eram, digamos, o utilitário grep já existia. Em vez disso, havia o operador de análise, que é um análogo simplificado de regulares, com a substituição de grupos em variáveis.
parse [origin] [template]
I.e. analisamos o conteúdo da fonte (que pode ser um argumento para uma função, variável, expressão etc.) quanto à conformidade com o modelo. O modelo pode conter literais que separam os valores e variáveis que receberam o valor da fonte entre esses separadores. De certa forma, parece grupos em expressões regulares.
fio = ', ' parse var fio firstName ',' LastName say firstName say LastName
É claro que isso é muito mais simples do que expressões regulares, apenas porque não havia meta caracteres como \ d, nenhuma repetição na forma de * ou +, nenhuma alternativa, nada disso.
3. A Rexx tinha uma API que permitia que ela fosse usada como uma linguagem de script, não apenas para o SO (CMS), mas também para qualquer outro programa que suporta essa API. I.e. de fato, era uma linguagem de escrita DSL. Provavelmente um dos primeiros. Ao mesmo tempo, o tempo de execução pode implementar e fornecer ao intérprete funções ou comandos adicionais disponíveis como resultado do programa.
Era algo assim: ao iniciar o editor de texto XEDIT, ele procurou em algum lugar nos discos acessíveis um arquivo chamado PROFILE XEDIT, que continha um script REXX. Esse script pode atribuir teclas de função e definir comandos adicionais disponíveis no XEDIT. Em termos de significado, hoje é o mais próximo de .bashrc, por exemplo. Ou seu análogo para vim.
Dessa forma, os procedimentos e funções do REXX definidos no PROFILE XEDIT podem executar comandos do editor e acessar informações sobre arquivos abertos, incluindo o conteúdo do próprio arquivo.
4. Não era necessária nenhuma sintaxe especial para a transmissão de comandos para o ambiente host (ou seja, o SO ou, digamos, um editor de texto). Em vez disso, todas as expressões que a Rexx não reconheceu foram passadas para execução. Portanto, para escrever o comando do SO dentro do script, basta colocá-lo entre aspas, por exemplo:
'list * * * (stack'
Um comando pode ser construído concatenando constantes e variáveis de sequência. O símbolo da operação de concatenação era simplesmente um espaço.
Para transferir o comando para outro aplicativo, havia uma declaração de endereço. Por exemplo, ao usar o editor de texto XEDIT no ambiente, para executar não o comando XEDIT, mas o sistema operacional (CMS), você deve fazer o seguinte:
address cms 'list * * * (stack'
5. O CMS implementou uma API para acessar a pilha de comandos do SO, que a Rexx também usou para trocar dados. O comando acima retornou a lista de arquivos resultante para a pilha, de onde o script poderia buscá-los, lendo uma linha como entrada padrão. De certa forma, isso é semelhante aos pipes do Unix, mas difere um pouco deles. Um canal ainda é um fluxo de bytes, e uma pilha no CMS é uma coleção de seqüências de caracteres. Em geral, essa é uma diferença típica entre a ideologia do Unix e o SO da IBM, onde os arquivos foram amplamente orientados para comprimentos de strings fixos ou variáveis (mas ao mesmo tempo conhecidos).
6. Como parte da API, os aplicativos podem ter acesso às variáveis de script Rexx, eles podem ler e modificá-las. Essa era outra maneira de trocar dados.
7. Uma aritmética bastante eficaz de precisão arbitrária foi implementada. Arbitrário - isso significa, por exemplo, 100 caracteres ou mais - quanta memória é suficiente.
8. Gerenciamento de memória - automático. Embora houvesse, por exemplo, um operador drop para excluir o valor de uma variável (uma matriz associativa ou seus elementos), mas, em qualquer caso, você não tinha negócios com ponteiros e tamanhos de bloco.
9. Como a única estrutura de dados universal, mas ao mesmo tempo muito universal, havia arrays associativos, muito semelhantes ao javascript, por exemplo. Ou seja, se você escrever a.1, este é um elemento da matriz a com a chave 1. Se você escrever ab, esse é um elemento com a chave b.
Digamos que o procedimento para adicionar uma palavra ao dicionário:
add_word: procedure expose dictionary. parse arg w n = dictionary.0 + 1 dictionary.n = w dictionary.0 = n return
A variável de dicionário neste fragmento é nossa matriz associativa. O procedimento não retorna essa matriz, mas a torna acessível a partir do exterior (usando exposição). dictionary.0 armazena o número de elementos no dicionário (isso é apenas uma convenção e, como você pode ver, nós mesmos o executamos), dictionary.n é a enésima palavra do dicionário.
10. O idioma não tinha acesso de baixo nível à memória ou à API do OC, embora, em princípio, fosse possível escrever algo semelhante para ele. Posso citar alguns exemplos de extensões de idioma, um foi projetado para funcionar com um banco de dados SQL / DS (DB2) e o segundo - para trocar mensagens entre máquinas virtuais na VM / SP. Ou seja, tudo o que você pode organizar como DSL, em princípio, pode ser implementado.
Suporte do REXX em aplicativos
Além do próprio CMS, o REXX deu suporte imediato ao principal editor de texto XEDIT. Permite escrever macros no REXX, que podem ser penduradas nas teclas de função, ou chamar comandos, a partir da linha de comando ou como os chamados. Comandos "Prefixo", que foram inseridos ao lado da (s) linha (s) do texto e permitiram que ele (eles) fosse manipulado. Por exemplo, o comando d permitiu excluir a linha ao lado da qual você inseriu, havia comandos de copiar ou mover e outros. Uma macro no REXX pode, por exemplo, converter uma sequência em maiúsculas ou minúsculas.
O segundo aplicativo que suportava o idioma em minha memória se chamava DMS (Sistema de Gerenciamento de Vídeo para CMS (DMS / CMS)) e era uma ferramenta para o desenvolvimento de programas interativos compostos por painéis. No REXX foi possível selecionar um dos formulários pré-desenhados, preencher seus campos com valores e exibir na tela. Depois que o usuário pressionou uma tecla de função, o programa recebeu o controle de volta e as variáveis REXX continham os valores dos campos alterados. O análogo funcional mais próximo do DMS chamaria HTML e suas formas. E em termos de complexidade (simplicidade) do desenvolvimento, isso talvez tenha sido um pouco mais fácil, embora o HTML certamente vença em termos de recursos expressivos (por exemplo, não havia imagens no DMS, o que é compreensível pelos terminais de texto).
Outro aplicativo que vale a pena mencionar foi chamado ISPF. Mas já era muito mais amplo que o DMS e era mais parecido com o ambiente de desenvolvimento integrado, como parece agora, ajustado para terminais de texto. E sim, o editor de texto também foi programado no REXX.
Começando com VM / SP 6, o CMS introduziu ferramentas para criar janelas virtuais de tamanho variável na tela do terminal e exibir texto nelas. A API correspondente apareceu para o REXX (mais precisamente, era principalmente uma extensão do REXX).
Outra aplicação muito interessante do REXX foi o chamado operador automático. Esse era um aplicativo em execução na máquina virtual do operador do SO, que recebia todas as mensagens que geralmente chegavam ao terminal do operador e permitia que elas fossem processadas por software. Manipulador de comandos - script REXX. Assim, por exemplo, foi possível fornecer alguns recursos ao operador para muitas pessoas, para as quais essas pessoas simplesmente enviaram mensagens para a máquina virtual do operador e o manipulador (em nome do usuário privilegiado, o operador) executou alguns comandos para eles. Bem, por exemplo, montei volumes de disco ou fita no sistema.
Mas as possibilidades não se limitaram a coisas tão simples. Por exemplo, você não pode enviar uma mensagem para o usuário se não estiver no sistema. Envie-o para o operador automático, salve-o na fila e, em seguida (depois de receber uma mensagem de que o usuário está logado), envie-o para quem é necessário. De fato, essa é uma implementação simples de email com um pequeno script REXX.
Impacto no Desenvolvimento
Eu diria que, com o advento do REXX no VM / SP 3, começamos a escrever nele uma parte significativa do que foi escrito anteriormente, por exemplo, no PL / 1. Essa é uma linguagem bastante poderosa e ao mesmo tempo simples que permite estruturar adequadamente aplicativos relativamente grandes. Primeiro de tudo, provavelmente devido aos seus recursos de integração, quando foi usado como DSL.
A capacidade de atender a consultas de banco de dados (SQL / DS), exibir formulários de tela, ler e gravar arquivos cobrem uma parte significativa das necessidades de desenvolvimento de aplicativos de negócios.
Obviamente, muitas pessoas gostaram do idioma. Ele estava no OS / 2, estava no Amigami, no Windows e em muitos outros lugares. Posteriormente, havia o Object REXX com extensões de objeto e o NetREXX para JVM. O principal é que esse idioma ainda esteja vivo. E, em geral, se eu tivesse que escolher o que escrever scripts hoje, considerando, por exemplo, Rexx, bash, a linguagem completamente completa cmd.exe - eu definitivamente escolheria o primeiro. Mas, em comparação com linguagens já mais recentes, como Perl, Python e muitas outras - tudo não é tão óbvio. Por exemplo, a ideia do Rexx sobre transferir comandos e variáveis para o tempo de execução foi boa - mas a idéia, digamos, COM, com sua orientação a objetos, ainda é mais funcional.
Apesar dos últimos 40 anos, ele ainda é usado no IBM z OS, e um livro de idiomas, de acordo com a Wikipedia, foi lançado muito recentemente, por volta de 2012. Para sistemas operacionais diferentes, é bem possível fazer o download de implementações ao vivo e experimentar você mesmo.