REXX est une langue assez ancienne et avancée pour son époque. Il est apparu, selon Wikipédia, en 1979, c'est-à-dire qu'il a récemment eu 40 ans. Pas la langue la plus ancienne, bien sûr, mais un âge décent.
Rexx est une abréviation, cela signifie Restructured Extended Executor, qui nous renvoie probablement à ses ancêtres EXEC / EXEC2. Je l'ai rencontré dans le système d'exploitation VM / SP 3, où il est venu remplacer précisément ces langages de script. Ensuite, il était populaire dans OS / 2, utilisé dans de nombreux autres systèmes d'exploitation, et de nombreuses implémentations et dialectes dérivés ont été créés.
Il n'a pas fait trop attention à Habré, je vais essayer de combler les lacunes de cet article.
Ancêtres, origines, auteurs
L'implémentation de la langue d'origine avait un auteur, un employé d'IBM Mike Cowlishaw. Cette implémentation a été écrite dans l'assembleur S / 360.
Wikipedia estime que REXX a été influencé par PL / 1, EXEC et EXEC2, et Algol. Dans l'ensemble, oui, cette langue est sans aucun doute dans sa syntaxe - l'héritière d'Algol (ou Pascal, si vous voulez). Autrement dit, boucles, blocs, etc. les constructions ne sont pas entourées d'accolades, mais de mots-clés, do / end, par exemple. Quant à EXEC et EXEC2, REXX a été créé en remplacement d'eux, et peut-être cela n'a plus rien à voir avec eux. Mais par rapport à PL / 1, REXX est beaucoup plus simple et le but du langage est complètement différent.
À quoi ressemble le code REXX:
/* 1 10 */ sum = 0 do count = 1 to 10 say count sum = sum + count end say " " sum"."
CARACTÉRISTIQUES
Qu'est-ce qui, à mon avis, était le plus intéressant ou inhabituel dans cette langue?
1. La syntaxe du langage est assez libre, ce n'est pas Fortran, bien sûr. Algol et Pascal regardent le plus. De base en général aussi.
Il existe des opérateurs typiques de la programmation structurelle.
Il y a des fonctions et des procédures. Ici, il est un peu inhabituel que la procédure masque par défaut toutes les variables du code appelant, mais certaines d'entre elles peuvent être rendues disponibles à l'aide de la construction de la clé exposer <liste des variables>.
La frappe est dynamique. Une variable peut être interprétée comme une chaîne ou comme un nombre, à différents moments d'exécution, et peut également ne pas être définie (cela peut être vérifié, bien qu'il soit tordu). En fait, le langage possède un type de données primitif - des chaînes sur lesquelles des opérations arithmétiques peuvent être effectuées si la chaîne est un nombre correct.
Voici un petit exemple 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 */
Cela montre que la variable non définie dans la première (et dernière) ligne est calculée en son nom en lettres majuscules. C'est le moyen de vérifier l'incertitude.
La déclaration interprète est un analogue de ce que l'on appelle généralement aujourd'hui eval.
La gestion des erreurs est peut-être plus similaire à Basic:
signal on halt do forever ... /* */ end halt: /* . halt, */ exit
Il s'agit du traitement de fin de programme (par bouton depuis le terminal). Outre l'arrêt, il existe d'autres «signaux» dont, par exemple, la syntaxe (erreur de syntaxe dans le code interprété). Je ne me souviens pas que je l'ai pratiquement appliqué, mais il est tout à fait logique de vérifier l'exactitude syntaxique, par exemple, ce qui est appliqué à l'entrée d'interprétation.
2. Il n'avait pas d'expressions régulières, comme on dit en Perl (il restait cependant près de 10 ans avant Perl). Le concept même des expressions régulières est apparu plus tôt, et elles étaient certainement déjà, disons, l'utilitaire grep déjà existant. Au lieu de cela, il y avait l'opérateur d'analyse, qui est un analogue simplifié des réguliers, avec la substitution de groupes en variables.
parse [origin] [template]
C'est-à-dire nous analysons le contenu de la source (qui pourrait être un argument pour une fonction, une variable, une expression, etc.) pour la conformité avec le modèle. Le modèle peut contenir des littéraux séparant les valeurs et les variables qui ont reçu la valeur de la source entre ces séparateurs. D'une certaine manière, cela ressemble à des groupes dans les expressions régulières.
fio = ', ' parse var fio firstName ',' LastName say firstName say LastName
Bien sûr, cela est beaucoup plus simple que les expressions régulières, ne serait-ce que parce qu'il n'y avait pas de méta-caractères comme \ d, pas de répétition sous la forme de * ou +, pas d'alternatives, rien de tout cela.
3. Rexx avait une API qui lui permettait d'être utilisé comme langage de script non seulement pour le système d'exploitation (CMS), mais aussi pour tout autre programme prenant en charge cette API. C'est-à-dire en fait, c'était un langage d'écriture DSL. Probablement l'un des premiers. Dans le même temps, le runtime pourrait implémenter et fournir à l'interpréteur des fonctions ou commandes supplémentaires disponibles à la suite du programme.
Cela ressemblait à ceci: au démarrage de l'éditeur de texte XEDIT, il cherchait quelque part sur les disques accessibles un fichier appelé PROFILE XEDIT, qui contenait un script REXX. Ce script pourrait affecter des touches de fonction et définir des commandes supplémentaires disponibles à partir de XEDIT. En termes de sens, il est aujourd'hui plus proche de .bashrc, par exemple. Ou son analogue pour vim.
Par conséquent, les procédures et fonctions REXX définies dans PROFILE XEDIT peuvent exécuter des commandes de l'éditeur et accéder aux informations sur les fichiers ouverts, y compris le contenu du fichier lui-même.
4. Il ne nécessitait aucune syntaxe spéciale pour transmettre des commandes à l'environnement hôte (c'est-à-dire le système d'exploitation ou, disons, un éditeur de texte). Au lieu de cela, toutes les expressions que Rexx n'a pas reconnues ont été transmises à l'exécution. Ainsi, pour écrire la commande OS à l'intérieur du script, il suffisait de la mettre entre guillemets, par exemple:
'list * * * (stack'
Une commande pourrait être construite en concaténant des constantes de chaîne et des variables. Le symbole de l'opération de concaténation était simplement un espace.
Pour transférer la commande vers une autre application, il y avait une déclaration d'adresse. Par exemple, lorsque vous utilisez l'éditeur de texte XEDIT dans l'environnement, afin d'exécuter non pas la commande XEDIT, mais le système d'exploitation (CMS), vous devez procéder comme suit:
address cms 'list * * * (stack'
5. Le CMS a implémenté une API pour accéder à la pile de commandes du système d'exploitation, que Rexx a également utilisée pour échanger des données. La commande ci-dessus a renvoyé la liste résultante des fichiers dans la pile, d'où le script pouvait les récupérer, en lisant une ligne comme entrée standard. À certains égards, cela est similaire aux tuyaux Unix, mais il en diffère quelque peu. Un canal est toujours un flux d'octets, et une pile dans CMS est une collection de chaînes. En général, il s'agit d'une différence typique entre l'idéologie d'Unix et le système d'exploitation d'IBM, où les fichiers étaient largement orientés vers des chaînes fixes ou variables (mais en même temps connues).
6. Dans le cadre de l'API, les applications pouvaient avoir accès aux variables de script Rexx, elles pouvaient les lire et les modifier. C'était une autre façon d'échanger des données.
7. Une arithmétique assez efficace d'exactitude arbitraire a été mise en œuvre. Arbitraire - cela signifie par exemple 100 caractères ou plus - la quantité de mémoire est suffisante.
8. Gestion de la mémoire - automatique. Bien qu'il y ait eu, par exemple, un opérateur de suppression pour supprimer la valeur d'une variable (un tableau associatif ou ses éléments), mais en tout cas, vous n'aviez rien à faire avec des pointeurs et des tailles de bloc.
9. En tant que seule structure de données, mais en même temps très universelle, il existait des tableaux associatifs, très similaires au javascript par exemple. Autrement dit, si vous écrivez a.1, c'est un élément du tableau a avec la clé 1. Si vous écrivez ab, alors c'est un élément avec la clé b.
Disons la procédure pour ajouter un mot au dictionnaire:
add_word: procedure expose dictionary. parse arg w n = dictionary.0 + 1 dictionary.n = w dictionary.0 = n return
La variable de dictionnaire de ce fragment est notre tableau associatif. La procédure ne retourne pas ce tableau, mais le rend accessible de l'extérieur (en utilisant expose). dictionary.0 stocke le nombre d'éléments dans le dictionnaire (ce n'est qu'une convention, et comme vous pouvez le voir, nous l'exécutons nous-mêmes), dictionary.n est le nième mot du dictionnaire.
10. La langue n'avait pas d'accès de bas niveau à la mémoire ou à l'API OC, bien qu'en principe il était tout à fait possible d'écrire quelque chose de similaire pour elle. Je peux nommer quelques exemples d'extensions de langage, l'un a été conçu pour fonctionner avec une base de données SQL / DS (DB2) et le second - pour échanger des messages entre des machines virtuelles au sein de VM / SP. Autrement dit, tout ce que vous pouvez organiser en DSL, en principe, peut être implémenté.
Prise en charge de REXX dans les applications
En plus du CMS lui-même, REXX a immédiatement pris en charge l'éditeur de texte XEDIT principal. Il vous a permis d'écrire des macros sur REXX, qui pouvaient être accrochées aux touches de fonction, ou d'appeler des commandes, soit à partir de la ligne de commande, soit comme soi-disant. Des commandes de «préfixe», qui ont été saisies à côté de la ou des lignes du texte, et qui leur ont permis d'être manipulées. Par exemple, la commande d vous a permis de supprimer la ligne à côté de laquelle vous avez entré, il y avait des commandes de copie ou de déplacement, et d'autres. Une macro sur REXX pourrait, par exemple, convertir une chaîne en majuscules ou en minuscules.
La deuxième application qui supportait la langue dans ma mémoire s'appelait DMS (Display Management System for CMS (DMS / CMS)), et c'était un outil pour développer des programmes interactifs composés de panneaux. À partir de REXX, il était possible de sélectionner l'un des formulaires pré-dessinés, de remplir ses champs avec des valeurs et de les afficher à l'écran. Une fois que l'utilisateur a appuyé sur une touche de fonction, le programme a reçu le contrôle et les variables REXX contenaient les valeurs des champs modifiés. L'analogue fonctionnel le plus proche de DMS j'appellerais HTML et ses formes. Et en termes de complexité (simplicité) de développement, c'était peut-être même un peu plus facile, bien que HTML gagne certainement en termes de capacités expressives (par exemple, il n'y avait aucune image dans DMS, ce qui est compréhensible par les terminaux texte).
Une autre application qui mérite d'être mentionnée s'appelait ISPF. Mais il était déjà beaucoup plus large que DMS et ressemblait davantage à l'environnement de développement intégré, tel qu'il semble maintenant, ajusté pour les terminaux de texte. Et oui, l'éditeur de texte a également été programmé dans REXX.
À partir de VM / SP 6, CMS a introduit des outils pour créer des fenêtres virtuelles de taille variable sur l'écran du terminal et y afficher du texte. L'API correspondante est apparue pour REXX (plus précisément, il s'agissait principalement d'une extension de REXX).
Une autre application très intéressante de REXX était le soi-disant auto-opérateur. Il s'agissait d'une application exécutée dans la machine virtuelle de l'opérateur du système d'exploitation, qui recevait tous les messages qui arrivaient généralement sur le terminal de l'opérateur et leur permettait d'être traités par un logiciel. Gestionnaire de commandes - script REXX. Ainsi, par exemple, il a été possible de donner certaines capacités d'opérateur à de nombreuses personnes, pour lesquelles ces personnes ont simplement envoyé des messages à la machine virtuelle de l'opérateur, et le gestionnaire (au nom de l'utilisateur privilégié, l'opérateur) a exécuté certaines commandes pour eux. Eh bien, par exemple, j'ai monté des volumes de disque ou de bande dans le système.
Mais les possibilités n'étaient pas limitées à des choses aussi simples. Par exemple, vous ne pouvez pas envoyer de message à l'utilisateur s'il n'est pas dans le système. Envoyez-le à l'opérateur automatique, il l'enregistre dans la file d'attente, puis (après avoir reçu un message indiquant que l'utilisateur est connecté) l'envoie à qui il est nécessaire. En fait, il s'agit d'une implémentation de messagerie simple avec un petit script REXX.
Impact sur le développement
Je dirais qu'avec l'avènement de REXX dans VM / SP 3, nous avons commencé à y écrire une partie importante de ce qui était précédemment écrit par exemple sur PL / 1. C'est un langage assez puissant et en même temps toujours simple qui vous permet de structurer correctement des applications relativement grandes. Tout d'abord, probablement en raison de ses capacités d'intégration, lorsqu'il était utilisé comme DSL.
La capacité de répondre aux requêtes de base de données (SQL / DS), d'afficher des formulaires d'écran, de lire et d'écrire des fichiers couvre une partie importante des besoins de développement d'applications métier.
De toute évidence, beaucoup de gens ont aimé la langue. Il était sous OS / 2, sur Amigami, sous Windows, et bien d'autres où. Plus tard, il y a eu Object REXX avec des extensions d'objet et NetREXX pour JVM. L'essentiel est que cette langue soit toujours vivante. Et en général, si je devais choisir sur quoi écrire des scripts aujourd'hui, alors en considérant par exemple Rexx, bash, le langage complètement oiseau cmd.exe - je choisirais certainement le premier. Mais en comparaison avec des langages déjà plus récents, comme Perl, Python et bien d'autres, tout n'est pas si évident. Disons, l'idée de Rexx sur le transfert de commandes et de variables au runtime était bonne - mais l'idée, disons COM, avec son orientation d'objet, est toujours plus fonctionnelle.
Malgré les 40 dernières années, il est toujours utilisé dans IBM z OS, et un livre de langue, selon Wikipedia, a été publié très récemment, vers 2012. Pour différents systèmes d'exploitation, il est tout à fait possible de télécharger des implémentations en direct et de l'essayer vous-même.