Rexx ( Restructured Extended Executor ) es un lenguaje de programación que puede interpretarse o compilarse . Fue desarrollado en IBM por Mike Cowlishaw . [6] [7] Es un lenguaje de programación estructurado y de alto nivel diseñado para facilitar su aprendizaje y lectura. Existen intérpretes Rexx propietarios y de código abierto para una amplia gama de plataformas informáticas; existen compiladores para ordenadores mainframe de IBM . [8]
Rexx es un lenguaje completo que puede utilizarse como lenguaje de scripting , lenguaje de macros y lenguaje de desarrollo de aplicaciones. A menudo se utiliza para procesar datos y texto y generar informes; esto significa que Rexx funciona bien en la programación de Common Gateway Interface (CGI) y se utiliza para este propósito, al igual que los lenguajes posteriores como Perl . Rexx es el lenguaje de scripting principal en algunos sistemas operativos, por ejemplo OS/2 , MVS , VM , AmigaOS , y también se utiliza como lenguaje de macros interno en algún otro software, como SPF/PC , KEDIT , THE y el emulador de terminal ZOC . Además, el lenguaje Rexx se puede utilizar para scripting y macros en cualquier programa que utilice lenguajes de motores de scripting ActiveX de Windows Scripting Host (por ejemplo, VBScript y JScript) si uno de los motores Rexx está instalado.
Rexx se suministra con VM/SP Release 3 en adelante, TSO/E Versión 2 en adelante, OS/2 (1.3 y posteriores, donde se llama oficialmente Procedures Language/2 ), AmigaOS Versión 2 en adelante, PC DOS ( 7.0 o 2000 ), ArcaOS , [9] y Windows NT 4.0 (Kit de recursos: Regina). Los scripts REXX para CMS comparten el tipo de archivo EXEC con EXEC y EXEC2, y la primera línea del script especifica el intérprete que se utilizará. Los scripts REXX para MVS pueden [a] ser reconocidos por el calificador de bajo nivel EXEC o pueden [b] ser reconocidos por el contexto y la primera línea. Los scripts REXX para OS/2 comparten la extensión de nombre de archivo .cmd con otros lenguajes de script, y la primera línea del script especifica el intérprete que se utilizará. Las macros REXX para aplicaciones compatibles con REXX utilizan extensiones determinadas por la aplicación. A finales de la década de 1980, Rexx se convirtió en el lenguaje de programación común para IBM Systems Application Architecture , donde pasó a llamarse "SAA Procedure Language REXX".
En la programación de mainframe, a un script o comando Rexx a veces se lo denomina EXEC en un guiño al tipo de archivo CMS utilizado para EXEC , [10] EXEC 2 [11] y scripts REXX en CP/CMS y VM/370 a z/VM .
Rexx tiene las siguientes características y funciones:
Rexx tiene sólo veintitrés instrucciones, en gran medida evidentes (como call
, parse
y select
) con requisitos mínimos de puntuación y formato. Es esencialmente un lenguaje casi de formato libre con un único tipo de datos, la cadena de caracteres; esta filosofía significa que todos los datos son visibles (simbólicos) y la depuración y el seguimiento se simplifican.
La sintaxis de Rexx es similar a la de PL/I , pero tiene menos notaciones; esto hace que sea más difícil de analizar (por programa) pero más fácil de usar, excepto en casos en los que los hábitos de PL/I pueden llevar a sorpresas. Uno de los objetivos de diseño de REXX fue el principio del menor asombro . [12]
Rexx fue diseñado e implementado por primera vez, en lenguaje ensamblador , como un proyecto "de tiempo libre" entre el 20 de marzo de 1979 y mediados de 1982 por Mike Cowlishaw de IBM, originalmente como un lenguaje de programación de scripts para reemplazar los lenguajes EXEC y EXEC 2. [ 6] Fue diseñado para ser un lenguaje de macros o scripts para cualquier sistema. Como tal, Rexx se considera un precursor de Tcl y Python . Rexx también fue pensado por su creador para ser una versión simplificada y más fácil de aprender del lenguaje de programación PL/I . Sin embargo, algunas diferencias con PL/I pueden hacer tropezar a los incautos.
Se describió por primera vez en público en la conferencia SHARE 56 en Houston, Texas, en 1981, [13] donde la reacción de los clientes, defendida por Ted Johnston de SLAC , llevó a que se enviara como un producto de IBM en 1982.
A lo largo de los años, IBM incluyó Rexx en casi todos sus sistemas operativos ( VM/CMS , MVS TSO/E , IBM OS/400 , VSE/ESA , AIX , PC DOS y OS/2 ) y puso a disposición versiones para Novell NetWare , Windows , Java y Linux .
La primera versión no IBM fue escrita para PC DOS por Charles Daney en 1984/5 [7] y comercializada por Mansfield Software Group (fundado por Kevin J. Kearney en 1986). [6] La primera versión del compilador apareció en 1987, escrita para CMS por Lundin y Woodruff. [14] También se han desarrollado otras versiones para Atari , AmigaOS , Unix (muchas variantes), Solaris , DEC , Windows , Windows CE , Pocket PC , DOS , Palm OS , QNX , OS/2 , Linux , BeOS , EPOC32 / Symbian , AtheOS , OpenVMS , [15] : p.305 Apple Macintosh y Mac OS X. [ 16]
La versión de Rexx para Amiga , llamada ARexx , se incluyó con AmigaOS 2 en adelante y fue popular para la creación de scripts y el control de aplicaciones. Muchas aplicaciones de Amiga tienen un "puerto ARexx" integrado que permite controlar la aplicación desde Rexx. Un solo script de Rexx podría incluso cambiar entre diferentes puertos de Rexx para controlar varias aplicaciones en ejecución.
En 1990, Cathie Dager de SLAC organizó el primer simposio independiente sobre REXX, que dio origen a la Asociación de Lenguas REXX. Los simposios se celebran anualmente.
Existen varias versiones gratuitas de Rexx. En 1992 aparecieron las dos versiones de código abierto más utilizadas : REXX/imc de Ian Collier para Unix y Regina [5] de Anders Christensen (posteriormente adoptada por Mark Hessling) para Windows y Unix. BREXX es muy conocido para las plataformas WinCE y Pocket PC, y ha sido "adaptado" a VM/370 y MVS .
OS/2 tiene un sistema de desarrollo visual de Watcom VX-REXX . Otro dialecto era VisPro REXX de Hockware.
Portable Rexx de Kilowatt y Personal Rexx de Quercus son dos intérpretes de Rexx diseñados para DOS y que también pueden ejecutarse en Windows mediante un símbolo del sistema. Desde mediados de los años 90, han aparecido dos variantes más nuevas de Rexx:
En 1996, el Instituto Nacional Estadounidense de Estándares (ANSI) publicó un estándar para Rexx: ANSI X3.274–1996 "Tecnología de la información: lenguaje de programación REXX". [17] Desde 1985 se han publicado más de dos docenas de libros sobre Rexx.
Rexx celebró su 25º aniversario el 20 de marzo de 2004, lo que se celebró en el 15º Simposio Internacional REXX de la Asociación de Idiomas REXX en Böblingen, Alemania, en mayo de 2004.
El 12 de octubre de 2004, IBM anunció su plan de publicar las fuentes de su implementación de Object REXX bajo la Licencia Pública Común . Las versiones recientes de Object REXX contienen un motor de scripts ActiveX Windows Scripting Host (WSH) que implementa esta versión del lenguaje Rexx.
El 22 de febrero de 2005 se anunció el primer lanzamiento público de Open Object Rexx (ooRexx). Este producto contiene un motor de scripts WSH que permite programar el sistema operativo Windows y aplicaciones con Rexx de la misma manera en que Visual Basic y JScript se implementan mediante la instalación predeterminada de WSH y los motores de scripts de terceros Perl , Tcl y Python .
A partir de enero de 2017, [update]REXX fue incluido en el índice TIOBE como uno de los cincuenta idiomas en su top 100 que no pertenece al top 50. [18]
En 2019, el 30.º Simposio de la Asociación del Lenguaje Rexx marcó el 40.º aniversario de Rexx. El simposio se celebró en Hursley, Inglaterra, donde se diseñó e implementó por primera vez Rexx. [19]
El kit de herramientas RexxUtil es un paquete de funciones que está disponible para la mayoría de las implementaciones de Rexx y la mayoría de los sistemas operativos host. [20] [21] [22] RexxUtil es un paquete de funciones de archivo y directorio, E/S en ventanas y funciones para acceder a servicios del sistema como WAIT y POST.
Rexx/Tk, un kit de herramientas para gráficos que se puede utilizar en programas Rexx de la misma manera que Tcl/Tk, está ampliamente disponible.
Se ha desarrollado un IDE Rexx, RxxxEd, para Windows. [15] Se han desarrollado RxSock para comunicación en red, así como otros complementos e implementaciones de Regina Rexx, y se suministra un intérprete Rexx para la línea de comandos de Windows en la mayoría de los kits de recursos para varias versiones de Windows y funciona en todas ellas, así como en DOS.
Originalmente, el lenguaje se llamaba Rex ( Reformed Executor ); la "X" adicional se agregó para evitar colisiones con los nombres de otros productos. REX originalmente estaba todo en mayúsculas porque el código del mainframe estaba orientado a mayúsculas. El estilo en aquellos días era tener nombres en mayúsculas, en parte porque casi todo el código todavía estaba en mayúsculas en ese entonces. Para el producto se convirtió en REXX, y ambas ediciones del libro de Mike Cowlishaw usan todo en mayúsculas. La expansión a REstructured eXtended eXecutor se utilizó para el producto del sistema en 1984. [12]
La estructura de control de bucle en Rexx comienza con a DO
y termina con an , END
pero viene en varias variedades. NetRexx usa la palabra clave LOOP
en lugar de DO
for para realizar un bucle, mientras que ooRexx trata LOOP
and DO
como equivalentes al realizar un bucle.
Rexx admite una variedad de bucles de programación estructurada tradicionales mientras prueba una condición antes ( do while
) o después ( do until
) de que se ejecute la lista de instrucciones:
hacer mientras [ condición ] [ instrucciones ] fin
hacer hasta que [ condición ] [ instrucciones ] termine
Como la mayoría de los lenguajes, Rexx puede realizar un bucle mientras incrementa una variable de índice y detenerse cuando se alcanza un límite:
hacer índice = inicio [ para limitar ] [ por incremento ] [ para contar ] [ instrucciones ] fin
Se puede omitir el incremento y el valor predeterminado es 1. También se puede omitir el límite, lo que hace que el bucle continúe para siempre.
Rexx permite bucles contados, donde una expresión se calcula al inicio del bucle y las instrucciones dentro del bucle se ejecutan esa cantidad de veces:
hacer expresión [ instrucciones ] fin
Rexx puede incluso repetir el proceso hasta que finalice el programa:
hacer por siempre [ instrucciones ] fin
Un programa puede salir del bucle actual con la leave
instrucción, que es la forma normal de salir de un do forever
bucle, o puede cortocircuitarlo con la iterate
instrucción.
Al igual que PL/I , Rexx permite combinar elementos condicionales y repetitivos en el mismo bucle: [23]
hacer índice = inicio [ hasta el límite ] [ por incremento ] [ para contar ] [ mientras condición ] [ instrucciones ] fin
hacer expresión [ hasta condición ] [ instrucciones ] fin
Condiciones de prueba con IF
:
si [ condición ] entonces hacer [ instrucciones ] fin de lo contrario hacer [ instrucciones ] fin
La ELSE
cláusula es opcional.
Para instrucciones individuales, DO
también END
se puede omitir:
si [ condición ] entonces [ instrucción ] de lo contrario [ instrucción ]
La sangría es opcional, pero ayuda a mejorar la legibilidad.
SELECT es la estructura CASE de Rexx , derivada de la forma SELECT; [c] de la sentencia SELECT de PL/I . Al igual que algunas implementaciones de construcciones CASE en otros lenguajes dinámicos, las cláusulas WHEN de Rexx especifican condiciones completas, que no necesitan estar relacionadas entre sí. En ese sentido, se parecen más a conjuntos de código en cascada que a la sentencia switch de C o Java . IF-THEN-ELSEIF-THEN-...-ELSE
seleccione cuando [ condición ] entonces [ instrucción ] o NOP cuando [ condición ] entonces haga [ instrucciones ] o NOP fin de lo contrario [ instrucciones ] o NOP fin
La instrucción NOP no realiza "ninguna operación" y se utiliza cuando el programador no desea hacer nada en un lugar donde se requerirían una o más instrucciones.
La cláusula OTHERWISE es opcional. Si se omite y no se cumple ninguna condición WHEN, se genera la condición SYNTAX.
Las variables en Rexx no tienen tipo y, en un principio, se evalúan como sus nombres, en mayúsculas. Por lo tanto, el tipo de una variable puede variar con su uso en el programa:
decir hola /* => HOLA */ hola = 25 decir hola /* => 25 */ hola = "decir 5 + 3" decir hola /* => decir 5 + 3 */ interpretar hola /* => 8 */ eliminar hola decir hola /* => HOLA */
A diferencia de muchos otros lenguajes de programación, el Rexx clásico no tiene soporte directo para matrices de variables direccionadas por un índice numérico. En su lugar, proporciona variables compuestas . [24] Una variable compuesta consiste en un tallo seguido de una cola. Se utiliza un .
(punto) para unir el tallo a la cola. Si las colas utilizadas son numéricas, es fácil producir el mismo efecto que una matriz.
¿ i = 1 a 10 ? raíz i = 10 - i final
Posteriormente existen las siguientes variables con los siguientes valores: stem.1 = 9, stem.2 = 8, stem.3 = 7
...
A diferencia de las matrices, no es necesario que el índice de una variable raíz tenga un valor entero. Por ejemplo, el siguiente código es válido:
i = raíz 'lunes' . i = 2
En Rexx también es posible establecer un valor predeterminado para un tallo.
tallo . = 'Desconocido' tallo . 1 = 'EE. UU.' tallo . 44 = 'Reino Unido' tallo . 33 = 'Francia'
Luego de estas asignaciones el término stem.3
produciría 'Unknown'
.
También se puede borrar todo el tallo con la instrucción DROP.
tallo de caída
Esto también tiene el efecto de eliminar cualquier valor predeterminado establecido previamente.
Por convención (y no como parte del lenguaje), el compuesto stem.0
se utiliza a menudo para llevar un registro de cuántos elementos hay en una raíz; por ejemplo, un procedimiento para agregar una palabra a una lista podría codificarse de la siguiente manera:
add_word : procedimiento exponer diccionario . analizar arg w n = diccionario . 0 + 1 diccionario . n = w diccionario . 0 = n devolver
También es posible tener varios elementos en la cola de una variable compuesta. Por ejemplo:
m = 'Julio' d = 15 y = 2005 día . y . m . d = 'Viernes'
Se pueden utilizar múltiples elementos de cola numéricos para proporcionar el efecto de una matriz multidimensional.
Características similares a las variables compuestas de Rexx se encuentran en muchos otros lenguajes (incluyendo matrices asociativas en AWK , hashes en Perl y Hashtables en Java ). La mayoría de estos lenguajes proporcionan una instrucción para iterar sobre todas las claves (o colas en términos de Rexx) de dicha construcción, pero esto falta en el Rexx clásico. En su lugar, es necesario mantener listas auxiliares de valores de cola según sea apropiado. Por ejemplo, en un programa para contar palabras, se podría utilizar el siguiente procedimiento para registrar cada aparición de una palabra.
add_word : procedimiento exponer count . word_list analizar arg w . count . w = count . w + 1 /* asumir que count. se ha establecido en 0 */ si count . w = 1 entonces word_list = word_list w devolver
y luego más tarde:
hacer i = 1 a palabras ( lista_palabras ) w = palabra ( lista_palabras , i ) decir w contar.w fin
A costa de cierta claridad es posible combinar estas técnicas en un único eje:
add_word : procedimiento exponer diccionario . analizar arg w . diccionario . w = diccionario . w + 1 si diccionario . w = 1 /* asumir diccionario . = 0 */ entonces hacer n = diccionario . 0 + 1 diccionario . n = w diccionario . 0 = n fin retorno
y más tarde:
hago i = 1 a diccionario . 0 w = diccionario . yo digo i w diccionario . w fin
Rexx no proporciona ninguna red de seguridad en este caso, por lo que si una de las palabras resulta ser un número entero menor, dictionary.0
esta técnica fallará misteriosamente.
Las implementaciones recientes de Rexx, incluyendo Object REXX de IBM y las implementaciones de código abierto como ooRexx, incluyen una nueva construcción de lenguaje para simplificar la iteración sobre el valor de una raíz, o sobre otro objeto de colección como una matriz, una tabla o una lista.
¿ Debo sobrescribir el radical i ? Digo, el radical i '-->' termina .
En resumen, las variables compuestas proporcionan un mecanismo para crear casi cualquier tipo de estructura de datos en Rexx. Entre ellas se incluyen listas o matrices simples, matrices n-dimensionales, matrices dispersas o densas, árboles equilibrados o no equilibrados, registros y más.
La PARSE
instrucción es particularmente potente; combina algunas funciones útiles para el manejo de cadenas. Su sintaxis es:
analizar [ superior ] origen [ plantilla ]
donde origen especifica la fuente:
arg
(argumentos, en el nivel superior y al final de la línea de comandos)linein
(entrada estándar, por ejemplo, teclado)pull
(Cola de datos Rexx o entrada estándar)source
(información sobre cómo se ejecutó el programa)value
(una expresión) with
: la palabra clave with
es necesaria para indicar dónde termina la expresiónvar
(una variable)version
(número de versión/lanzamiento)y la plantilla puede ser:
upper
es opcional; si se especifica, los datos se convertirán a mayúsculas antes del análisis.
Utilizando una lista de variables como plantilla
myVar = "John Smith" analizar var myVar firstName lastName decir "El nombre es:" firstName decir "El apellido es:" lastName
muestra lo siguiente:
El primer nombre es: John El apellido es: Smith
Usando un delimitador como plantilla:
myVar = "Smith, John" analizar var myVar Apellido "," Nombre decir "El nombre es:" nombre decir "El apellido es:" apellido
También muestra lo siguiente:
El primer nombre es: John El apellido es: Smith
Uso de delimitadores de números de columna:
myVar = "(202) 123-1234" analizar var MyVar 2 AreaCode 5 7 SubNumber decir "El código de área es:" AreaCode decir "El número de suscriptor es:" SubNumber
muestra lo siguiente:
El código de área es: 202 El número de abonado es: 123-1234
Una plantilla puede utilizar una combinación de variables, delimitadores literales y delimitadores de números de columna.
La instrucción INTERPRET evalúa su argumento y trata su valor como una instrucción Rexx. A veces, INTERPRET es la forma más clara de realizar una tarea, pero a menudo se utiliza cuando es posible utilizar un código más claro, por ejemplo, value()
.
Otros usos de INTERPRET son la aritmética de precisión arbitraria (decimal) de Rexx (incluidas las comparaciones difusas), el uso de la declaración PARSE con plantillas programáticas, matrices con raíz y matrices dispersas. [ ¿cómo? ]
/* demostrar INTERPRET con cuadrado(4) => 16 */ X = 'cuadrado' interpreta 'decir' X || '(4) ; salir' CUADRADO : devolver arg ( 1 )** 2
Esto muestra 16 y sale. Debido a que los contenidos de las variables en Rexx son cadenas, incluidos números racionales con exponentes e incluso programas completos, Rexx ofrece interpretar cadenas como expresiones evaluadas.
Esta característica podría usarse para pasar funciones como parámetros de función , como pasar SIN o COS a un procedimiento para calcular integrales.
Rexx ofrece únicamente funciones matemáticas básicas como ABS, DIGITS, MAX, MIN, SIGN, RANDOM y un conjunto completo de conversiones hexadecimales y binarias con operaciones de bits. Las funciones más complejas como SIN se implementaron desde cero o se obtuvieron de bibliotecas externas de terceros . Algunas bibliotecas externas, generalmente las implementadas en lenguajes tradicionales, no admitían precisión extendida.
Las versiones posteriores (no clásicas) admiten CALL variable
construcciones. Junto con la función incorporada VALUE
, CALL se puede utilizar en lugar de muchos casos de INTERPRET
. Este es un programa clásico:
/* terminado por la entrada "exit" o similar */ do forever ; interpret linein () ; fin
Una "calculadora Rexx" un poco más sofisticada:
X = 'ingresa BYE para salir' hacer hasta X = 'BYE' ; interpretar 'decir' X ; extraer X ; fin
PULL
es la abreviatura de parse upper pull
. Asimismo, ARG
es la abreviatura de parse upper arg
.
El poder de la instrucción INTERPRET tenía otros usos. El paquete de software Valour dependía de la capacidad interpretativa de Rexx para implementar un entorno OOP . Otro uso se encontró en un producto inédito de Westinghouse llamado Time Machine que era capaz de recuperarse completamente después de un error fatal.
decir dígitos () fuzz () formulario () /* => 9 0 CIENTÍFICO */ decir 999999999 + 1 /* => 1.000000000E+9 */ dígitos numéricos 10 /* solo limitado por la memoria disponible */ decir 999999999 + 1 /* => 1000000000 */ decir 0,999999999 = 1 /* => 0 (falso) */ fuzz numérico 3 decir 0,99999999 = 1 /* => 1 (verdadero) */ decir 0,99999999 == 1 /* => 0 (falso) */ digamos 100 * 123456789 /* => 1.23456789E+10 */ ingeniería de formato numérico digamos 100 * 123456789 /* => 12.34567890E+9 */ decir 53 // 7 /* => 4 (resto de la división)*/
La instrucción SIGNAL está pensada para cambios anormales en el flujo de control (consulte la siguiente sección). Sin embargo, se puede utilizar incorrectamente y tratarla como la instrucción GOTO que se encuentra en otros lenguajes (aunque no es estrictamente equivalente, porque termina bucles y otras construcciones). Esto puede producir código difícil de leer.
En Rexx es posible interceptar y gestionar errores y otras excepciones mediante la instrucción SIGNAL. Existen siete condiciones del sistema: ERROR, FAILURE, HALT, NOVALUE, NOTREADY, LOSDDIGITS y SYNTAX. El manejo de cada una de ellas se puede activar y desactivar en el código fuente según se desee.
El siguiente programa se ejecutará hasta que el usuario lo finalice:
señal de detención ; hacer a = 1 decir a hacer 100000 /* un retraso */ fin fin detención : decir "El programa fue detenido por el usuario" salir
Una declaración intercepta el uso de variables no definidas, que de otro modo obtendrían su propio nombre (en mayúsculas) como valor. Independientemente del estado de la condición, el estado de una variable siempre se puede verificar con la función incorporada que devuelve VAR para las variables definidas.signal on novalue
NOVALUE
SYMBOL
La VALUE
función se puede utilizar para obtener el valor de las variables sin activar una NOVALUE
condición, pero su propósito principal es leer y establecer variables de entorno , similar a POSIX getenv
y putenv
.
ERROR
FAILURE
HALT
NOVALUE
NOTREADY
SYNTAX
LOSTDIGITS
Cuando una condición es manejada por SIGNAL ON
, las variables del sistema SIGL
y RC
se pueden analizar para comprender la situación. RC contiene el código de error de Rexx y SIGL contiene el número de línea donde surgió el error.
A partir de la versión 4 de Rexx, las condiciones pueden recibir nombres y también existe una CALL ON
construcción. Esto resulta útil si no existen necesariamente funciones externas:
ChangeCodePage : procedimiento /* proteger la configuración de SIGNAL */ señal en nombre de sintaxis ChangeCodePage . Trap return SysQueryProcessCodePage () ChangeCodePage . Trap : return 1004 /* windows-1252 en OS/2 */
¿Podría haber un alto factor de asombro asociado con la nueva característica? Si el usuario aplica incorrectamente una característica por accidente y provoca lo que le parece un resultado impredecible, esa característica tiene un alto factor de asombro y, por lo tanto, es indeseable. Si una característica necesaria tiene un alto factor de asombro, puede ser necesario rediseñar la característica.