REXX es un lenguaje bastante antiguo y avanzado para su época. Apareció, según Wikipedia, en 1979, es decir, recientemente cumplió 40 años. No es el lenguaje más anticuado, por supuesto, sino una edad decente.
Rexx es una abreviatura, significa Ejecutor Extendido Reestructurado, lo que probablemente nos remite a sus antepasados EXEC / EXEC2. Lo conocí en el sistema operativo VM / SP 3, donde vino a reemplazar precisamente estos lenguajes de secuencias de comandos. Luego fue popular en OS / 2, utilizado en muchos otros sistemas operativos, y se crearon muchas implementaciones y dialectos derivados.
No prestó demasiada atención a Habré, intentaré llenar los vacíos en este artículo.
Antepasados, Orígenes, Autores
La implementación del lenguaje original tenía un autor, un empleado de IBM Mike Cowlishaw. Esta implementación fue escrita en el ensamblador S / 360.
Wikipedia cree que REXX fue influenciado por PL / 1, EXEC y EXEC2, y Algol. En general, sí, este lenguaje está sin duda en su sintaxis: el heredero de Algol (o Pascal, si lo desea). Es decir, bucles, bloques, etc. las construcciones no están rodeadas por llaves, sino por palabras clave, do / end, por ejemplo. En cuanto a EXEC y EXEC2, REXX fue creado como un reemplazo para ellos, y tal vez no tenga nada más que ver con ellos. Pero en comparación con PL / 1 REXX es mucho más simple y el propósito del lenguaje es completamente diferente.
Aspecto del código REXX:
/* 1 10 */ sum = 0 do count = 1 to 10 say count sum = sum + count end say " " sum"."
Caracteristicas
¿Cuál, en mi opinión, fue lo más interesante o inusual en este idioma?
1. La sintaxis del lenguaje es bastante libre, no es Fortran, por supuesto. Algol y Pascal se ven más. En básico en general, también.
Hay operadores típicos de la programación estructural.
Hay funciones y procedimientos. Aquí, es un poco inusual que el procedimiento oculte todas las variables del código de llamada de forma predeterminada, pero algunas de ellas pueden estar disponibles utilizando la construcción de clave exponer <lista de variables>.
Escribir es dinámico. Una variable puede interpretarse como una cadena o como un número, en diferentes momentos de ejecución, y también puede no definirse (esto puede verificarse, aunque esté torcido). De hecho, el lenguaje tiene un tipo de datos primitivo: cadenas sobre las cuales se pueden realizar operaciones aritméticas si la cadena es un número correcto.
Aquí hay un pequeño ejemplo de 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 */
Esto muestra que la variable indefinida en la primera (y última) línea se calcula en su nombre en mayúsculas. Esta es la forma de verificar la incertidumbre.
La declaración de interpretación es un análogo de lo que hoy se suele llamar eval.
El manejo de errores es quizás más similar a Básico:
signal on halt do forever ... /* */ end halt: /* . halt, */ exit
Este es el proceso de finalización del programa (por botón desde la terminal). Además de detener, hay otras "señales", que incluyen, por ejemplo, la sintaxis (error de sintaxis en el código interpretado). No recuerdo que prácticamente lo apliqué, pero es bastante lógico verificar la corrección sintáctica, por ejemplo, lo que se alimenta a la entrada de interpretación.
2. No tenía expresiones regulares, como decimos en Perl (sin embargo, quedaban casi 10 años antes de Perl). El concepto mismo de expresiones regulares apareció antes, y ciertamente ya eran, digamos, la utilidad grep ya existía. En cambio, estaba el operador de análisis, que es un análogo simplificado de los habituales, con la sustitución de grupos en variables.
parse [origin] [template]
Es decir Analizamos el contenido de la fuente (que podría ser un argumento para una función, variable, expresión, etc.) para el cumplimiento de la plantilla. La plantilla podría contener literales que separan los valores y las variables que recibieron el valor de la fuente entre estos separadores. En cierto modo, parece grupos en expresiones regulares.
fio = ', ' parse var fio firstName ',' LastName say firstName say LastName
Esto, por supuesto, es mucho más simple que las expresiones regulares, aunque solo sea porque no había metacaracteres como \ d, no hay repetición en forma de * o +, no hay alternativas, nada de eso.
3. Rexx tenía una API que permitía que se usara como lenguaje de programación no solo para el sistema operativo (CMS), sino también para cualquier otro programa que admitiera esta API. Es decir de hecho, era un lenguaje de escritura DSL. Probablemente uno de los primeros. Al mismo tiempo, el tiempo de ejecución podría implementar y proporcionar al intérprete funciones o comandos adicionales que están disponibles como resultado del programa.
Se parecía a esto: al iniciar el editor de texto XEDIT, buscaba en algún lugar de los discos accesibles un archivo llamado PROFILE XEDIT, que contenía un script REXX. Este script podría asignar teclas de función y definir comandos adicionales disponibles desde XEDIT. En términos de significado, hoy está más cerca de .bashrc, por ejemplo. O su análogo para vim.
En consecuencia, los procedimientos y funciones REXX definidos en PROFILE XEDIT podrían ejecutar comandos del editor y acceder a información sobre archivos abiertos, incluido el contenido del archivo mismo.
4. No requería ninguna sintaxis especial para transmitir comandos al entorno host (es decir, el sistema operativo o, por ejemplo, un editor de texto). En cambio, todas las expresiones que Rexx no reconoció se pasaron a la ejecución. Por lo tanto, para escribir el comando del sistema operativo dentro del script, fue suficiente encerrarlo entre comillas, por ejemplo:
'list * * * (stack'
Se puede construir un comando concatenando constantes y variables de cadena. El símbolo de la operación de concatenación era simplemente un espacio.
Para transferir el comando a otra aplicación, había una declaración de dirección. Por ejemplo, al usar el editor de texto XEDIT en el entorno, para ejecutar no el comando XEDIT, sino el sistema operativo (CMS), tenía que hacer esto:
address cms 'list * * * (stack'
5. El CMS implementó una API para acceder a la pila de comandos del sistema operativo, que Rexx también usó para intercambiar datos. El comando anterior devolvió la lista resultante de archivos a la pila, desde donde el script podría recogerlos, leyendo una línea como entrada estándar. De alguna manera, esto es similar a las tuberías Unix, pero difiere un poco de ellas. Una tubería sigue siendo una secuencia de bytes, y una pila en CMS es una colección de cadenas. En general, esta es una diferencia típica entre la ideología de Unix y el sistema operativo de IBM, donde los archivos estaban orientados en gran medida a cadenas fijas o variables (pero al mismo tiempo conocidas).
6. Como parte de la API, las aplicaciones podrían tener acceso a las variables de script Rexx, podrían leerlas y modificarlas. Esta era otra forma de intercambiar datos.
7. Se implementó una aritmética bastante efectiva de precisión arbitraria. Arbitrario, esto significa, por ejemplo, 100 caracteres o más, cuánta memoria es suficiente.
8. Gestión de memoria: automática. Aunque había, por ejemplo, un operador de eliminación para eliminar el valor de una variable (una matriz asociativa o sus elementos), pero en cualquier caso, no tenía que hacer negocios con punteros y tamaños de bloque.
9. Como la única estructura de datos, pero al mismo tiempo muy universal, había matrices asociativas, muy similares a JavaScript, por ejemplo. Es decir, si escribe a.1, este es un elemento de la matriz a con la tecla 1. Si escribe ab, entonces este es un elemento con la tecla b.
Digamos el procedimiento para agregar una palabra al diccionario:
add_word: procedure expose dictionary. parse arg w n = dictionary.0 + 1 dictionary.n = w dictionary.0 = n return
La variable del diccionario en este fragmento es nuestra matriz asociativa. El procedimiento no devuelve esta matriz, pero la hace accesible desde el exterior (mediante la exposición). dictionary.0 almacena el número de elementos en el diccionario (esto es solo una convención y, como puede ver, lo ejecutamos nosotros mismos), dictionary.n es la enésima palabra del diccionario.
10. El lenguaje no tenía acceso de bajo nivel a la memoria ni a la API OC, aunque en principio era bastante posible escribir algo similar para él. Puedo nombrar un par de ejemplos de extensiones de lenguaje, uno diseñado para trabajar con una base de datos SQL / DS (DB2), y el segundo, para intercambiar mensajes entre máquinas virtuales dentro de VM / SP. Es decir, todo lo que puede organizar como DSL, en principio, se puede implementar.
Soporte REXX en aplicaciones
Además del CMS en sí, REXX apoyó de inmediato el editor de texto XEDIT principal. Le permitía escribir macros en REXX, que podrían colgarse en las teclas de función, o invocar comandos, ya sea desde la línea de comandos o como los llamados. Los comandos de "Prefijo", que se ingresaron junto a la (s) línea (s) del texto, y le permitieron (a ellos) ser manipulados. Por ejemplo, el comando d le permitió eliminar la línea junto a la que ingresó, había comandos para copiar o mover, y otros. Una macro en REXX podría, por ejemplo, convertir una cadena en mayúsculas o minúsculas.
La segunda aplicación que soportaba el lenguaje en mi memoria se llamaba DMS (Sistema de administración de pantalla para CMS (DMS / CMS)), y era una herramienta para desarrollar programas interactivos que consisten en paneles. Desde REXX fue posible seleccionar uno de los formularios dibujados previamente, llenar sus campos con valores y mostrarlos en la pantalla. Después de que el usuario presionó una tecla de función, el programa recibió el control y las variables REXX contenían los valores de los campos modificados. El análogo funcional más cercano de DMS lo llamaría HTML y sus formas. Y en términos de complejidad (simplicidad) de desarrollo, esto fue quizás incluso un poco más fácil, aunque HTML ciertamente gana en términos de capacidades expresivas (por ejemplo, no había imágenes en absoluto en DMS, lo cual es comprensible para los terminales de texto).
Otra aplicación que vale la pena mencionar se llama ISPF. Pero ya era mucho más amplio que DMS, y se parecía más al entorno de desarrollo integrado, como se ve ahora, ajustado para terminales de texto. Y sí, el editor de texto también fue programado en REXX.
Comenzando con VM / SP 6, CMS introdujo herramientas para crear ventanas virtuales de tamaño variable en la pantalla del terminal y mostrar texto en ellas. La API correspondiente apareció para REXX (más precisamente, era principalmente una extensión de REXX).
Otra aplicación muy interesante de REXX fue el llamado operador automático. Esta era una aplicación que se ejecutaba en la máquina virtual del operador del sistema operativo, que recibía todos los mensajes que generalmente llegaban al terminal del operador y permitía que fueran procesados por software. Controlador de comandos: secuencia de comandos REXX. Así, por ejemplo, fue posible dar algunas capacidades de operador a muchas personas, para lo cual estas personas simplemente enviaron mensajes a la máquina virtual del operador, y el controlador (en nombre del usuario privilegiado, el operador) ejecutó algunos comandos para ellos. Bueno, por ejemplo, monté volúmenes de disco o cinta en el sistema.
Pero las posibilidades no se limitaban a cosas tan simples. Por ejemplo, no puede enviar un mensaje al usuario si no está en el sistema. Envíelo al operador automático, lo guarda en la cola y luego (después de recibir un mensaje de que el usuario ha iniciado sesión) lo envía a quien lo necesita. De hecho, esta es una implementación simple de correo electrónico con un pequeño script REXX.
Impacto en el desarrollo
Diría que con el advenimiento de REXX en VM / SP 3, comenzamos a escribir en él una parte significativa de lo que se escribió anteriormente, por ejemplo, en PL / 1. Este es un lenguaje bastante poderoso y al mismo tiempo simple que le permite estructurar adecuadamente aplicaciones relativamente grandes. En primer lugar, probablemente debido a sus capacidades de integración, cuando se usaba como DSL.
La capacidad de satisfacer consultas de bases de datos (SQL / DS), mostrar formularios en pantalla, leer y escribir archivos cubre una parte importante de las necesidades de desarrollo de aplicaciones de negocios.
Obviamente, a muchas personas les gustó el idioma. Estaba en OS / 2, estaba en Amigami, en Windows, y en muchos otros lugares. Más tarde hubo Object REXX con extensiones de objeto, y NetREXX para JVM. Lo principal es que este lenguaje aún está vivo. Y, en general, si tuviera que elegir en qué escribir los scripts hoy, considerando, por ejemplo, Rexx, bash, el lenguaje completamente pájaro cmd.exe, definitivamente elegiría el primero. Pero en comparación con los lenguajes ya más nuevos, como Perl, Python y muchos, muchos otros, no todo es tan obvio. Digamos que la idea de Rexx sobre la transferencia de comandos y variables al tiempo de ejecución fue buena, pero la idea, digamos COM, con su orientación a objetos, es aún más funcional.
A pesar de los últimos 40 años, todavía se usa en IBM z OS, y un libro de idiomas, según Wikipedia, se lanzó muy recientemente, alrededor de 2012. Es muy posible descargar implementaciones en vivo para diferentes sistemas operativos y probarlo usted mismo.