Rexx
Rexx
Main page

Rexx

logo
Community Hub0 subscribers
Read side by side
from Wikipedia

Rexx
Paradigmmultiparadigm: procedural, structured
Designed byMike Cowlishaw
DeveloperMike Cowlishaw, IBM
First appeared1979; 46 years ago (1979)
Stable release
ANSI X3.274 / 1996; 29 years ago (1996)
Typing disciplineDynamic
Filename extensions.cmd, .bat, .exec, .rexx, .rex, EXEC
Major implementations
VM/SP R3,[1] TSO/E V2,[2] SAAREXX,[3][4] ARexx, BREXX, Regina,[5] Personal REXX, REXX/imc
Dialects
NetRexx, Object REXX, now ooREXX, KEXX
Influenced by
PL/I, ALGOL, EXEC, EXEC 2
Influenced
NetRexx, Object REXX
  • Rexx Programming at Wikibooks

Rexx (restructured extended executor) is a high-level programming language developed at IBM by Mike Cowlishaw.[6][7] Both proprietary and open source Rexx interpreters exist for a wide range of computing platforms, and compilers exist for IBM mainframe computers.[8] Rexx is used for scripting, application macros and application development. As a general purpose scripting language, Rexx is considered a precursor to Tcl and Python.

Rexx is supported in a variety of environments. It is the primary scripting language in some operating systems including OS/2, MVS, VM, AmigaOS and is used for macros in some software including SPF/PC, KEDIT, THE and ZOC. With an engine installed, Rexx can be used for scripting and macros in programs that use a Windows Scripting Host ActiveX scripting engine (such as VBScript or JScript). Rexx is supplied with VM/SP Release 3 on up, TSO/E Version 2 on up, OS/2 (1.3 and later, where it is officially named Procedures Language/2), AmigaOS Version 2 on up, PC DOS (7.0 or 2000), ArcaOS,[9] and Windows NT 4.0 (Resource Kit: Regina). In the late 1980s, Rexx became the common scripting language for IBM Systems Application Architecture, where it was renamed "SAA Procedure Language REXX".

A script is associated with a Rexx interpreter at runtime in various ways based on context. In mainframe computing, a Rexx script or command is sometimes referred to as an EXEC since that is the name of the file type used for similar CMS EXEC,[10] and EXEC 2[11] scripts and for Rexx scripts on VM/SP R3 through z/VM. The first line of a script specifies the use of a Rexx interpreter in a comment either by identifying the code as Rexx language or by file path via EXTPROC. On MVS, Rexx scripts may[a] be recognized by the low level qualifier "EXEC" or if the first line fetched from SYSPROC is a comment containing "REXX" then it is treated as Rexx (rather than CLIST), and a script fetched from SYSEXEC must be Rexx. On OS/2, Rexx scripts share the filename extension ".cmd" with other scripting languages, and the first line of the script specifies the interpreter to use. On Linux, Rexx scripts generally begin with a shebang. Rexx macros for Rexx-aware applications use extensions determined by the application.

Name

[edit]

Originally, the language was called REX, short for Reformed Executor, but an extra "X" was added to avoid confusion with other products. The name was originally all uppercase because that was the only way to represent it in mainframe code at the time. Both editions of Mike Cowlishaw's first book on the language use all-caps, REXX, although the cover graphic uses mixed case. His book on NetRexx uses mixed case but all caps in the cover graphic with large and small caps, NETREXX. An expansion that matches the abbreviation, REstructured eXtended eXecutor, was used for the system product in 1984.[12] The name Rexx (mixed case) is used in this article, and is commonly used elsewhere.

Attributes

[edit]

Objective and subjective attributes of Rexx include:

  • Simple syntax
  • Ability to route commands to multiple environments
  • Ability to support functions, procedures and commands associated with a specific invoking environment.
  • Built-in stack with the ability to interoperate with the host stack if there is one
  • Small instruction set
  • Free-form syntax; indentation is optional but can help readability
  • Case-insensitive tokens, including variable names
  • Character string basis
  • Dynamic data typing; no declarations
  • No reserved keywords, except in local context[b]
  • No include file facility
  • Arbitrary-precision arithmetic
  • Decimal arithmetic, floating-point
  • Rich selection of built-in functions, especially string and word processing
  • Automatic storage management
  • Crash protection
  • Content addressable data structures
  • Associative array
  • Straightforward access to system commands and facilities
  • Simple error-handling, and built-in tracing and debugger
  • Few artificial limitations
  • Simplified I/O facilities
  • Unconventional operators
  • Only partly supports Unix style command line parameters, except specific implementations
  • Provides no basic terminal control as part of the language, except specific implementations
  • Provides no generic way to include functions and subroutines from external libraries, except specific implementations

Some claim that Rexx is a relatively simple language. With only 23 instructions (such as call, parse, and select), it has a relatively small instruction set. Rexx has limited punctuation and formatting requirements. Rexx has only one data type, the character string. Some claim that such simplicities make Rexx relatively easy to debug.

Some claim that Rexx code looks similar to PL/I code, but has fewer notations. With fewer notations, it tends to be is harder to parse via a translator, but is easier to write. Simplifying coding was intentional as noted by the Rexx design goal of the principle of least astonishment.[12]

History

[edit]

pre–1990

[edit]

On his own time, Mike Cowlishaw developed the language and an interpreter for it in assembly language between 20 March 1979 and mid-1982 with the intent to replace the languages EXEC and EXEC 2.[6] Mike also intended Rexx to be a simplified and easier to learn version of PL/I, but some claim that Rexx has problematic differences from PL/I.

Rexx was first described in public at the SHARE 56 conference in Houston, Texas, in 1981,[13] where customer reaction, championed by Ted Johnston of SLAC, led to it being shipped as an IBM product in 1982.

Over the years IBM included Rexx in almost all of its operating systems (VM/CMS, MVS TSO/E, IBM OS/400, VSE/ESA, MUSIC/SP, AIX, PC DOS, and OS/2), and has made versions available for Novell NetWare, Windows, Java, and Linux.

The first non-IBM version was written for PC DOS by Charles Daney in 1984/5[7] and marketed by the Mansfield Software Group (founded by Kevin J. Kearney in 1986).[6] The first Rexx compiler appeared in 1987, written for CMS by Lundin and Woodruff.[14] Other versions have also been developed for Atari, AmigaOS, Unix (many variants), Solaris, DEC, Windows, Windows CE, Pocket PC, DOS, Palm OS, QNX, OS/2, Linux, BeOS, EPOC32/Symbian, AtheOS, OpenVMS,[15]: 309  Apple Macintosh, and Mac OS X.[16]

ARexx, a Rexx interpreter for Amiga, was included with AmigaOS 2 onwards and was popular for scripting and application control. Many Amiga applications have an "ARexx port" which allows control of the application via a Rexx script. Notably, a Rexx script can switch between Rexx ports to control multiple applications.

1990 to present

[edit]

In 1990, Cathie Dager of SLAC organized the first independent Rexx symposium, which led to the forming of the Rexx Language Association. Symposia are held annually.

In 1992, the two most widely used open-source ports appeared: Ian Collier's REXX/imc for Unix and Anders Christensen's Regina[5] (later adopted by Mark Hessling) for Windows and Unix. BRexx was developed by Vasilis N Vlachoudis, a nuclear scientist at CERN. It runs on a range of operating systems, including Unix, Linux, BSD, macOS and Windows. Its small size means it can run on an Android mobile phone. BRexx/370 is a version that runs on IBM mainframes.[15]: 359–383 [17]

OS/2 has a visual development system from Watcom VX-REXX. Another dialect was VisPro REXX from Hockware.

Portable Rexx by Kilowatt and Personal Rexx by Quercus are two Rexx interpreters designed for DOS and can be run under Windows as well using a command prompt. Since the mid-1990s, two newer variants of Rexx have appeared:

  • NetRexx: compiles to Java byte-code via Java source code; this has no reserved keywords at all, and uses the Java object model, and is therefore not generally upwards-compatible with 'classic' Rexx.
  • Object REXX: an object-oriented generally upwards-compatible version of Rexx.

In 1996 the American National Standards Institute (ANSI) published a standard for Rexx: ANSI X3.274–1996 "Information Technology – Programming Language REXX".[c] More than two dozen books on Rexx have been published since 1985.

Rexx marked its 25th anniversary on 20 March 2004, which was celebrated at the Rexx Language Association's 15th International REXX Symposium in Böblingen, Germany, in May 2004.

On October 12, 2004, IBM announced their plan to release their Object REXX implementation's sources under the Common Public License. Recent releases of Object REXX contain an ActiveX Windows Scripting Host (WSH) scripting engine implementing this version of the Rexx language.

On February 22, 2005, the first public release of Open Object Rexx (ooRexx) was announced. This product contains a WSH scripting engine which allows for programming of the Windows operating system and applications with Rexx in the same fashion in which Visual Basic and JScript are implemented by the default WSH installation and Perl, Tcl, Python third-party scripting engines.

In January 2018 the TIOBE index listed Rexx at position 30.[19] Since 2018 it has been either outside the top 50, or, more frequently, outside the top 100.

In 2019, the 30th Rexx Language Association Symposium marked the 40th anniversary of Rexx. The symposium was held in Hursley, England, where Rexx was first designed and implemented.[20]

Toolkits

[edit]
  • RexxUtil – a package of file and directory functions, windowed I/O, and functions to access system services such as WAIT and POST – is available for most Rexx environments.[21][22][23]
  • Rexx/Tk – a toolkit for graphics to be used in Rexx programmes in the same fashion as Tcl/Tk – is widely available.
  • RexxEd – an integrated development environment (IDE) for Rexx – was developed for Windows.[15]: 390 
  • RxSock for network communication as well as other add-ons to and implementations of Regina Rexx have been developed, and a Rexx interpreter for the Windows command line is supplied in most resource kits for various versions of Windows and works in DOS as well.

Host environment

[edit]

A Rexx host environment is a named interface for sending commands to an, e.g., application, operating system, subsystem. The Rexx interpreter initially has a list of known environments; the first in the list is known as the default environment. A Rexx script use the ADDRESS statement to change the default environment and may also use it to send a single command to a specific environment without changing the default environment.

Syntax

[edit]

Instruction types

[edit]

Rexx has three instruction types[24]: 31 

  • Assignments – Single clause of the form symbol=expression, assigns a value to a variable; e.g. count=count+1, would add 1 to value in variable "count".
  • Keyword instructions – The keyword is the first word of the instruction; e.g. say "Message", would print the word 'Message'.
  • Commands – an expression that the interpreter evaluates and passes as a command to the default environment; e.g. "sleep 10" would cause a Unix-like host environment to produce a ten seconds delay.

Address instruction

[edit]

The address instruction has three roles:

  • An address instruction with no operand interchanges the first two host environments; normally this reinstate the previous default environment.
  • An address instruction with only an environment moves it to the beginning of the list, making it the default environment.
  • An address instruction with an environment and an expression passes the value of the expression as a command to the specified environment.

The ANSI standard added options for redirecting the input and output of commands.

Do groups

[edit]

The language provides do groups for two purposes:

  • To treat a group of instructions within an if or select statement as a unit for purposes of flow control.
  • For loop control, similar to many other languages. A single do group may optionally contain repetitor phrases, conditional phrases, or both, with termination whenever any of them is satisfied.

A do group begins with do and ends with end. A single group may serve both purposes. In the related ooRexx and NetRexx, there is both a do and a loop keyword, with almost identical semantics; they differ in that a simple do is equivalent to do 1 while a simple loop is equivalent to loop forever.

An iteration of a do group may be terminated with an iterate statement and the entire group may be terminated with a leave statement.

Simple do

[edit]

Although it is valid anywhere, a simple do is specifically useful inside conditional statements:

if foo=bar
then
  do
    i=1;j=3
  end
else
  do
    i=2;j=4
  end

Conditional loop

[edit]

The language supports testing a condition either before (do while) or after (do until) executing a group of code via syntax:

do while [condition]
  [instructions]
end
do until [condition]
  [instructions]
end

Simple repetitive loop

[edit]

The language permits counted loops, where an expression is computed at the start of the loop and the instructions within the loop are executed that many times:

do expression
  [instructions]
end

Controlled Repetitive Loops

[edit]

A loop can increment a variable and stop when a limit is reached.

do index=start [to limit] [by increment] [for count]
  [instructions]
end

The increment value is 1 if the by clause is omitted. The loop continues forever if the limit to clause is omitted, unless terminated earlier by another clause or by a leave statement.

Unconditional loop

[edit]

The language supports an unconditional loop via forever that continues until the loop is terminated or the program is terminated.

do forever
  [instructions]
end

Combined loop

[edit]

Repetitive elements and conditional phrases can be combined in the same loop;[24]: 50  e.g.:

do i=1 while i<=3; say i; end
do index=start [to limit] [by increment] [for count] [while condition]
  [instructions]
end
do expression [until condition]
  [instructions]
end

Conditional

[edit]

The language provides for conditional execution via if, then and else for a group delimited by do and end.

if [condition] then
  do
  [instructions]
  end
else
  do
  [instructions]
  end

For a single instruction, do and end can be omitted.

if [condition] then
  [instruction]
else
  [instruction]

Multiple condition branching

[edit]

The language provides multiple condition branching via select which derives from the SELECT; form of the PL/I SELECT statement .[d] Like similar constructs in other dynamic languages, Rexx's when clauses specify full conditions – not equality tests of a single value for the statement as some languages do. In that, they are more like cascading if-then-else code than like the C or Java switch statement.

select
  when [condition] then
    [instruction or nop]
  when [condition] then
    do
    [instructions or nop]
    end
  otherwise
    [instructions or nop]
end

The nop instruction is required if no action is associated with a when condition.

The otherwise clause is optional. If omitted and no when conditions are met, then the syntax condition is raised.

Variable

[edit]

Typing system

[edit]

Variables are typeless and initially are evaluated as their names in upper case. Thus a variable's type can vary with its use in the program:

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 */

Evaluation

[edit]

If no novalue condition handler is configured, then an undefined variable evaluates to its name, in upper case. The built-in function SYMBOL returns "VAR" for a defined variable and does not trigger novalue even if not defined. The VALUE function gets the value of a variable without triggering a novalue condition, but its main purpose is to read and set environment variables, similar to POSIX getenv and putenv.

Compound variable

[edit]

The language provides the compound variable construct which supports adding fields (called tails) to a variable (called a stem in this context) to support data structures such as lists, arrays, n-dimensional arrays, sparse or dense arrays, balanced or unbalanced trees and records.

The language does not provide special support for numeric array indexing like many other languages do. Instead, a compound variable with numeric tails produce a similar effect.[25]

The following code defines variables stem.1 = 9, stem.2 = 8, stem.3 = 7...

do i = 1 to 10
  stem.i = 10 - i
end

Unlike a typical array, a tail (index) need not identify (be named) an integer value. For example, the following code is valid:

i = 'Monday'
stem.i = 2

A default value can be assigned to a stem via . but no tail.

stem. = 'Unknown'
stem.1 = 'USA'
stem.44 = 'UK'
stem.33 = 'France'

In this case stem.3, for example, evaluates to the default value, 'Unknown'.

The whole stem (including any default value) can be erased with the drop statement.

drop stem.

By convention (not part of the language) the compound stem.0 is often used to keep track of how many items are in a stem, for example a procedure to add a word to a list might be coded like this:

add_word: procedure expose dictionary.
  parse arg w
  n = dictionary.0 + 1
  dictionary.n = w
  dictionary.0 = n
return

A stem can have multiple tails. For example:

m = 'July'
d = 15
y = 2005
day.y.m.d = 'Friday'

Multiple numerical tail elements can be used to provide the effect of a multi-dimensional array.

Features similar to the compound variable are found in other languages including associative arrays in AWK, hashes in Perl and hash tables in Java, dynamic objects in JavaScript. Most of these languages provide a mechanism to iterate over the keys (tails) of such a construct, but this is lacking in classic Rexx. Instead, it is necessary to store additional information. For example, the following procedure might be used to count each occurrence of a word.

add_word: procedure expose count. word_list
  parse arg w .
  count.w = count.w + 1 /* assume count. has been set to 0 */
  if count.w = 1 then word_list = word_list w
return

and then later:

do i = 1 to words(word_list)
  w = word(word_list,i)
  say w count.w
end

More recent Rexx variants, including Object REXX and ooRexx, provide a construct to iterate over the tails of a stem.

do i over stem.
  say i '-->' stem.i
end

Parse

[edit]

The parse instruction provides string-handling via syntax:

parse [upper] origin [template]

If upper is included then the input is converted to upper case before parsing.

origin describes the input as one of the following:

  • arg – arguments, at top level tail of command line
  • linein – standard input, e.g. keyboard
  • pull – Rexx data queue or standard input
  • source – info on how program was executed
  • value expression withwith indicates the end of the expression
  • var – a variable
  • version – version/release number

template can be a combination of variables, literal delimiters, and column number delimiters.

Examples

[edit]

Using a list of variables as template:

myVar = "John Smith"
parse var myVar firstName lastName
say "First name is:" firstName
say "Last name is:" lastName

displays:

First name is: John
Last name is: Smith

Using column number delimiters:

myVar = "(202) 123-1234"
parse var MyVar 2 AreaCode 5 7 SubNumber
say "Area code is:" AreaCode
say "Subscriber number is:" SubNumber

displays:

Area code is: 202
Subscriber number is: 123-1234

Interpret

[edit]

The interpret instruction evaluates its argument as a Rexx statement allowing for evaluation of code formatted at runtime. Uses include passing a function as a parameter, arbitrary precision arithmetic, use of the parse statement with programmatic templates, stemmed arrays, and sparse arrays.[how?] The following example displays 16 and exits.

X = 'square'
interpret 'say' X || '(4) ; exit'
SQUARE: return arg(1)**2

The Valour software package relied upon Rexx's interpretive ability to implement an OOP environment.[citation needed] Another use was found in an unreleased Westinghouse product called Time Machine that was able to fully recover following an otherwise fatal error.[citation needed]

Numeric

[edit]
say digits() fuzz() form() /* => 9 0 SCIENTIFIC */
say 999999999+1 /* => 1.000000000E+9 */
numeric digits 10 /* only limited by available memory */
say 999999999+1 /* => 1000000000 */

say 0.9999999999=1 /* => 0 (false) */
numeric fuzz 3
say 0.99999999=1 /* => 1 (true) */
say 0.99999999==1 /* => 0 (false) */

say 100*123456789 /* => 1.23456789E+10 */
numeric form engineering
say 100*123456789 /* => 12.34567890E+9 */

say 53 // 7   /* => 4   (rest of division)*/

Calculation of the value √2:

numeric digits 50
n=2; r=1
do forever /* Newton's method */
  rr=(n/r+r)/2
  if r=rr then leave
  r=rr
end
say "SqRt" n "=" r

Output: SqRt 2 = 1.414213562373095048801688724209698078569671875377

Calculation of the value e:

numeric digits 50
e=2.5; f=0.5
do n=3
  f=f/n
  ee=e+f
  if e=ee then leave
  e=ee
end
say "e =" e

Output: e = 2.7182818284590452353602874713526624977572470936998

Error handling

[edit]

The signal instruction configures the runtime to run custom code to handle a system condition if triggered. Conditions include:

  • error – Positive return code from a system command
  • failure – Negative return code from a system command (e.g. command doesn't exist)
  • halt – Abnormal termination
  • novalue – A variable name was used but the variable is not defined
  • notready – Input or output error (e.g. read attempts beyond end of file)
  • syntax – Invalid program syntax, or some other error condition
  • lostdigits – Significant digits were lost (ANSI Rexx, not in TRL second edition)

The following fragment prints a message when the user terminates (halts) it:

signal on halt;
do a = 1
  say a
  do 100000 /* a delay */
  end
end
halt:
say "The program was stopped by the user"
exit

Since Rexx version 4, a handler can be named. In the following example, the handler ChangeCodePage.Trap is configured to handle a syntax condition.

ChangeCodePage: procedure
  signal on syntax name ChangeCodePage.Trap
return SysQueryProcessCodePage()

ChangeCodePage.Trap: return 1004

When a condition is handled (as configured via signal on), the condition can be analyzed via RC which indicates the last error code and SIGL which indicates the line number of the code that triggered the condition.

See also

[edit]

Notes

[edit]

References

[edit]

Further reading

[edit]
[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
REXX (Restructured Extended Executor) is a versatile, procedural programming language designed for ease of use in scripting, macro programming, prototyping, and general application development, featuring human-like syntax, string-based data handling, and high portability across systems.[1] Developed by Mike Cowlishaw at IBM UK Laboratories in Hursley and the Thomas J. Watson Research Center between 1979 and 1982, REXX was first implemented under the Conversational Monitor System (CMS) in IBM's Virtual Machine/System Product (VM/SP) Release 3 in 1983, evolving through extensive user feedback via the VNET network connecting over 1,400 mainframes.[1][2] Its design prioritizes readability with free-format syntax, minimal punctuation, English-like keywords (e.g., IF-THEN-ELSE, DO-END loops), and no variable declarations or strong typing—all data treated as strings for natural manipulation.[1][3] Key features include arbitrary-precision arithmetic, robust string processing, dynamic scoping, built-in debugging and tracing, and the ability to issue system commands or interlanguage calls while remaining largely system-independent, making it suitable for applications ranging from short scripts to programs exceeding one million lines.[1][3] In environments like z/OS, REXX serves as an interpreted (or optionally compiled) language for TSO/E commands, ISPF dialogs, system automation, and rapid prototyping, often compared to the simplicity of COBOL for job control.[3] Standardized by the American National Standards Institute (ANSI) as X3.274-1996 (later INCITS 274-1996 with reaffirmations), the language ensures consistent interpretation across compliant implementations, promoting portability and reliability.[4] Variants like NetRexx extend its capabilities for Java integration, enhancing performance and security in modern contexts.[3] Widely adopted in IBM mainframe ecosystems for over four decades, REXX remains influential for its balance of simplicity and power, influencing scripting languages and continuing use in enterprise automation.[1][5]

Introduction

Name and Origin

REXX, originally conceived as REX (Reformed Executor), emerged as a programming language designed to enhance ease of use in scripting tasks. The name REX was first noted on March 20, 1979, with the initial specification dated March 29, 1979, reflecting its intent as a reformed approach to command execution. By 1982, it was renamed Rexx with an additional "x" to distinguish it from existing products and avoid potential naming conflicts. Upon its first release in 1983 as part of IBM's VM/SP Release 3, the name was expanded to REstructured eXtended eXecutor, underscoring its restructured syntax and extended capabilities for execution in diverse environments.[6][1] The language was developed by Mike F. Cowlishaw, an IBM engineer, primarily at the IBM United Kingdom Laboratories Limited in Hursley, England, with contributions during 1979–1982 also involving the IBM Thomas J. Watson Research Center in Yorktown Heights, New York. Cowlishaw initiated the project as a personal endeavor to address the limitations of existing scripting tools under the VM/CMS operating system, prioritizing human readability and simplicity over computational efficiency. This focus stemmed from observations of the cumbersome nature of prior languages, aiming to create a tool that felt more natural for non-expert users.[1][7] REXX's foundational purpose was to serve as a portable, English-like replacement for the EXEC and CLIST scripting languages used by VM/CMS operators, facilitating system administration, rapid prototyping, and macro programming. By emphasizing straightforward syntax and portability across IBM systems, it sought to reduce errors and accelerate development for tasks like command automation and personal computing utilities, marking a shift toward user-centric design in procedural languages.[1][6]

Key Attributes

Rexx features a simple, English-like syntax designed for readability and ease of use, consisting of only 23 basic instructions with no globally reserved keywords, which enables free-form coding without rigid formatting requirements.[1] This approach allows developers to write code in a natural style, mixing upper and lower case letters and using optional punctuation, making it accessible even to those unfamiliar with programming conventions.[1] The language employs dynamic typing with typeless variables that do not require declaration and treat all data as strings, automatically converting types as needed during operations.[8] Arithmetic operations support arbitrary-precision decimal calculations, defaulting to nine significant digits but configurable via the NUMERIC instruction to handle up to thousands of digits for precise computations.[9] Rexx includes over 60 built-in functions for tasks such as mathematical operations, string manipulation, and environment queries, enhancing its utility for everyday scripting needs.[10] Portability is achieved through abstraction of the host environment, allowing Rexx programs to interact with various operating systems and applications via the ADDRESS instruction without direct platform-specific code.[11] These attributes stem from Rexx's origins at IBM, where it was engineered for versatility across mainframe systems. Key strengths include its human-readable nature, which suits non-programmers for tasks like writing macros, rapid prototyping, and educational purposes, while limitations encompass the absence of native support for include files—requiring workarounds like subroutine calls—and incomplete integration with Unix-style pipes in non-specialized environments, often necessitating external tools or extensions.[1][12][13] In terms of popularity, Rexx maintains a low profile in general metrics, with TIOBE Index ratings historically below 0.1% as of 2018 and remaining outside the top 50 languages in subsequent years, reflecting its niche endurance in mainframe and legacy systems. Despite this, recent developments indicate renewed interest in Rexx for modern scripting, highlighted by open-source advancements and articles promoting its revival for cross-platform use in 2022.[14]

History

Early Development (1979–1989)

The development of Rexx originated in 1979 when Mike Cowlishaw, working at IBM's United Kingdom Laboratories in Hursley, England, began prototyping a scripting language initially named REX to simplify command and macro programming within IBM's mainframe environments.[1] The first specification was documented on March 29, 1979, and an initial implementation was completed later that year, allowing for internal testing and feedback through IBM's VNET network, which connected over 1,400 mainframes across 40 countries.[15] By 1980, a more stable version (2.00) was in use internally at IBM for prototyping, education, and personal programming tasks, emphasizing readability and ease of use over complex syntax.[16] The language stabilized in 1982, with the name adjusted to REXX by adding an "X" to distinguish it from other tools, and it was formally named as such in 1984.[15] Its first production release came with VM/SP Release 3 in 1983, integrated as the System Product Interpreter for the Conversational Monitor System (CMS) under VM/CMS, marking Rexx's debut as a tool for dialog management and command scripting in virtual machine environments.[17] Prior to any public standard, Rexx remained proprietary to IBM, with early adoption focused on system administration tasks, where it began replacing older procedural languages like EXEC by offering more natural syntax for scripting host commands and automating routines.[1] Initial external awareness emerged through IBM's technical documentation and reference manuals, such as the Virtual Machine/System Product: System Product Interpreter Reference, which highlighted its role in enhancing productivity for CMS users.[15] Expansion accelerated in the mid-to-late 1980s as Rexx was ported to additional IBM platforms. In 1988, it was introduced to MVS/TSO environments as part of TSO Extensions (TSO/E) Version 2, enabling REXX execs for batch and interactive processing on MVS systems.[18] By 1987, IBM designated Rexx as the standard procedures language within its Systems Application Architecture (SAA), promoting portability across systems like VM, MVS, and OS/400, with implementations following for OS/2 in Extended Edition 1.2 (1989) and RS/6000 running AIX (also 1989).[16] This integration solidified Rexx's proprietary status while fostering its use in cross-platform scripting, though it remained without a public standard until later efforts.[15]

Standardization and Growth (1990–2010)

The first Rexx Symposium for Developers and Users, held on June 11, 1990, at the Stanford Linear Accelerator Center (SLAC), marked a pivotal moment in the language's evolution beyond IBM's proprietary ecosystems. Organized by Cathie Dager of SLAC, the event brought together developers and users to discuss Rexx's potential for broader adoption, fostering enthusiasm that led to the formation of the Rexx Language Association (RexxLA) in 1991. This symposium highlighted the need for standardization to ensure portability across diverse platforms, setting the stage for international collaboration.[19][20] In response to growing demand for interoperability, the American National Standards Institute (ANSI) published the X3.274-1996 standard, titled "Information Technology - Programming Language REXX," which defined the core syntax, semantics, and constraints of the language to facilitate portability. This standard, reaffirmed in 2001 with supplements addressing errata, emphasized Rexx's decimal arithmetic capabilities and ensured compatibility without introducing major syntax alterations from prior IBM implementations. Influenced by similar efforts in language standardization, such as ISO/IEC 13211:1994 for Prolog, the ANSI standard promoted Rexx's use in multi-vendor environments by focusing on compliance rather than radical changes. Early IBM implementations served as the foundational reference for this standardization, providing a stable baseline for the core language features.[21][22] The 1990s saw significant growth through open-source implementations that extended Rexx to non-IBM platforms. Regina, an interpreter for Unix systems written in ANSI C using lex and yacc, was announced in May 1992 by Anders Christensen, enabling Rexx scripting on Linux, Solaris, and other Unix variants with full compliance to the emerging standards. Similarly, REXX/imc, developed by Ian Collier in 1992 for SunOS and later ported to other Unix systems, provided another open-source option that supported Rexx's procedural capabilities in academic and research settings. These efforts democratized access to Rexx, allowing its use in utilities, education, and system administration without reliance on proprietary hardware.[23][20] IBM contributed to this expansion with Object REXX (ooRexx), an object-oriented extension that maintained upward compatibility with classic Rexx while adding classes, inheritance, and integration with the System Object Model (SOM). A prototype was demonstrated at the 1992 Rexx Symposium, with the first official release in 1996 as part of OS/2 Warp 4, initially targeting OS/2 but soon ported to Windows and AIX. This version enhanced Rexx's applicability in graphical user interfaces and enterprise applications, aligning with IBM's Systems Application Architecture (SAA) push to extend Rexx as a standard procedure language to non-IBM platforms like AS/400 and VSE. The RexxUtil toolkit, introduced during this period for OS/2 and Windows, provided essential extensions such as file I/O, directory manipulation, and system event handling, further bolstering practical deployment without altering the core syntax.[24][20][25] Rexx's footprint widened through ports to additional environments, including expansions of ARexx for the Amiga platform, which was integrated into AmigaOS 2.0 in 1990 and further developed with AmigaOS 3.0 in 1992 to support inter-application scripting via ports. Implementations for Windows and Linux proliferated in the late 1990s, often leveraging Regina or ooRexx, positioning Rexx as a versatile scripting tool akin to early influences on languages like Tcl for automation and rapid prototyping. By the 2000s, Rexx had matured into a compliant, portable language used in education for teaching procedural programming and in utilities for cross-platform task automation. The 2004 International Rexx Symposium in Germany celebrated the language's 25th anniversary, underscoring its enduring relevance and community-driven growth.[26][27]

Modern Era and Recent Developments (2011–present)

In 2019, the Rexx Language Association (RexxLA) hosted its 30th annual symposium in Hursley, United Kingdom, commemorating the 40th anniversary of Rexx's initial development at IBM.[28] The event featured presentations on classic Rexx, NetRexx, and Open Object Rexx (ooRexx), underscoring the language's enduring legacy in scripting and automation.[29] Rexx maintains significant relevance in modern computing, particularly for scripting on IBM z/OS mainframes and general-purpose automation tasks. IBM's z/OS TSO/E REXX Reference documentation, updated through 2021, details its integration for executing programs in TSO/E environments, including access to z/OS UNIX System Services for hybrid workflows.[30] Similarly, the 2022 Using REXX and z/OS UNIX System Services guide highlights its role in invoking callable services, enabling seamless interaction between mainframe and Unix-like systems.[31] Articles on Opensource.com in 2022 promoted Rexx as a versatile scripting language for contemporary open-source environments, emphasizing its simplicity for tasks like text processing and system administration.[14][32] Recent implementations have seen active maintenance and enhancements. The Regina Rexx interpreter, hosted on SourceForge, continues ongoing updates, with file modifications as recent as March 2025, ensuring ANSI compliance and portability across Unix-like platforms, Windows, and OS/2.[33] ooRexx, the open-source object-oriented extension, released version 5.0.0 in December 2022, introducing features like annotations for classes, methods, and attributes, along with the new RexxInfo class to bolster object-oriented programming capabilities.[34] Version 5.1.0 reached general availability in 2025, with further improvements in performance, command redirection, bug fixes, and feature enhancements for integrated scripting.[35] In 2025, the Open Mainframe Project's Winter Mentorship program advanced Rexx's tooling by developing a Language Server Protocol (LSP) extension for Visual Studio Code using the Langium framework, enhancing IDE support for syntax highlighting, autocompletion, and diagnostics in mainframe development.[36] RexxLA sustains community engagement through annual symposia, such as the 35th International Rexx Language Symposium in March 2024 in Brisbane, Australia, which included hybrid online participation to discuss portability in cloud-mainframe environments.[28] The 36th symposium, held in May 2025 in Vienna, Austria, featured updates including the ooRexx 5.1.0 release and ongoing adaptations for hybrid environments.[28] While no major updates to the ANSI Rexx standard have occurred since 1996, efforts emphasize Rexx's adaptability for hybrid cloud integrations, leveraging its cross-platform interpreters to bridge legacy mainframe applications with modern distributed systems.[4]

Implementations

Host Environments

REXX is an interpreted scripting language that is typically embedded within host operating systems and applications, allowing it to execute in environments such as IBM z/OS via TSO/E, z/VM through CMS, and various implementations on Windows, Unix, and Linux systems using dedicated interpreters.[30][37][38] In these hosts, REXX programs, known as execs, interact with the underlying system without making direct operating system calls, promoting portability across diverse platforms.[39] A key mechanism for this portability is the abstract interface provided by host command environments, which insulate REXX from platform-specific details. The ADDRESS instruction routes commands to these environments, such as ADDRESS SYSTEM to invoke shell commands like listing files, enabling REXX to issue system-level operations indirectly through the host's defined processors.[40] For instance, in z/OS TSO/E, REXX execs can run interactively or as batch jobs using utilities like IKJEFT01, facilitating automated processing of mainframe tasks without direct MVS interactions.[41] Similarly, in the Amiga operating system, ARexx integrates with applications via message ports, allowing scripts to control programs like text editors or databases through host addresses. In IBM CICS environments, REXX serves as a scripting language for transaction processing, where execs can be invoked via CICS transactions to manage resources like temporary storage queues or automate workflows.[42] The evolution of REXX host interactions began with IBM's Systems Application Architecture (SAA) initiative in 1987, which standardized REXX as a common procedures language across platforms like MVS, VM, and OS/2, defining consistent host command environments to enhance interoperability.[43] In modern contexts, REXX continues to adapt through integrations like Eclipse-based editors in IBM Developer for z/OS, which provide syntax highlighting and debugging for mainframe scripts, and containerized emulations using Docker with tools like Hercules to simulate z/OS environments on commodity hardware.[44][45] These advancements maintain REXX's role in hybrid cloud and DevOps pipelines while preserving its core portability principles.[44]

Major Implementations and Toolkits

Rexx implementations vary across platforms, with a focus on maintaining compatibility with the ANSI X3.274-1996 standard while adding platform-specific extensions. The original IBM implementation, known as RXAPI or System Rexx, remains the reference for mainframe environments, supporting z/OS, z/VM, and VSE systems through integrated APIs for OS interaction and command stacking.[46] This version includes ongoing updates bundled with IBM operating systems, ensuring backward compatibility and support for enterprise scripting tasks like database access via DB2.[46] Open-source alternatives emphasize portability. Regina, an ANSI-compliant interpreter, runs on Unix-like systems (Linux, macOS, BSD), Windows, and Android, with features like thread safety, interprocess communication, and extensions for stream I/O and bit operations.[38] Its latest release, version 3.9.7, continues active maintenance for cross-platform scripting.[47] Similarly, BRexx provides a lightweight, high-performance option for Linux, Windows, DOS, and emulated mainframes, incorporating dynamic linking and database functions while adhering to TRL-2 standards.[48] Object-oriented extensions build on classic Rexx syntax. ooRexx, originally developed by IBM with contributions from Simon Nash and others in the early 1990s, introduces classes, methods, and GUI support via ooDialog, remaining fully backward-compatible with ANSI Rexx.[49] The open-source project, managed by the Rexx Language Association, released version 5.1.0 in May 2025, adding enhancements like improved concurrency and Unicode handling across Windows, Linux, and Android.[35] NetRexx, a 1996 variant with Java-like syntax, compiles to JVM bytecode for seamless integration with Java libraries, supporting web servlets and enterprise applications; its current version 5.01-GA (as of May 2025) is maintained openly for cross-platform use.[50] Platform-specific ports include ARexx for AmigaOS and emulators like AROS and MorphOS, where it serves as the default interprocess communication tool since 1988, with ANSI compliance and ongoing use in legacy environments.[51] REXX for PHP embeds Rexx commands into PHP scripts for web development, allowing native Rexx functions in includable PHP files.[52] Toolkits extend Rexx's capabilities without altering core syntax. RexxUtil provides cross-platform utilities for file I/O, dialogs, and system calls on Windows, VM, and Unix.[53] Rexx/Tk enables GUI development using Tcl/Tk, supporting widgets and event handling on major platforms under GNU LGPL. Rexx/SQL facilitates database connectivity via ODBC and CLI standards, compatible with interpreters like Regina and ooRexx.[54] The Rexx Language Support extension for Visual Studio Code provides LSP-based features like syntax highlighting and autocompletion for editing Rexx code (as of August 2025).[55] All major implementations target ANSI X3.274 compliance, with extensions like NetRexx diverging for specialized environments.[53]

Syntax and Language Features

Instruction Types and Basic Syntax

REXX features a free-form syntax that provides programmers with considerable flexibility in code layout. There are no restrictions on where an instruction may start within a line, and code can span multiple lines without mandatory indentation. Clauses—the fundamental units of executable code—are delimited by semicolons or by the end of a line, allowing multiple clauses to appear on a single line when separated by semicolons. The language treats keywords and symbols in a case-insensitive manner, while preserving the case of string literals.[56][57] Comments in REXX are enclosed within /* and */ delimiters, which can encompass multiple lines and are entirely ignored during execution. These comments support nesting, with implementations required to handle at least ten levels. and are commonly used at the start of programs to describe their purpose.[57][58] REXX instructions fall into three main categories: assignments, keyword instructions, and commands. Assignments bind the result of an expression to one or more symbols using the equals sign (=), as in total = 0 or, with templates for pattern matching, first second = "apple banana cherry", which assigns "apple" to first and "banana" to second while leaving "cherry" unassigned. Keyword instructions invoke built-in language functions, such as SAY, which directs the evaluated expression to the standard output stream: SAY "Hello, World!" produces the literal output "Hello, World!". Commands facilitate interaction with the host system and are prefixed by the ADDRESS instruction, which specifies the target environment (e.g., SYSTEM or TSO) followed by the command string, like ADDRESS SYSTEM "ls".[56][57][58] Expressions within instructions are evaluated from left to right, subject to operator precedence that prioritizes operations such as exponentiation over addition. Parentheses can alter this order explicitly. The PARSE ARG instruction processes program arguments using a template to distribute values into variables, for example, PARSE ARG user input assigns the first argument to user and the second to input. Programs typically conclude with the EXIT instruction, which halts execution and optionally sets a return value via an expression, such as EXIT 0 to indicate successful completion.[59][57][58] The following example illustrates a basic REXX program structure incorporating these elements:
/* Greeting program that processes an argument */
PARSE ARG name
IF name = "" THEN name = "World"
SAY "Hello," name "!"
EXIT 0
This code parses an input argument into name, defaults it if absent, outputs a greeting, and exits cleanly.[58][57]

Control Structures

Rexx provides structured control mechanisms for managing program flow, including iterative loops via DO groups, conditional execution with IF statements, and multi-way branching through SELECT constructs. These features enable programmers to implement repetitive tasks, decision-making logic, and switch-like behavior in a readable and flexible manner, drawing from the language's design emphasis on simplicity and clarity.[57] The primary looping construct in Rexx is the DO group, which encloses a block of instructions between DO and END keywords, allowing for single execution or repetition based on specified criteria. Simple DO groups execute their instructions once without iteration, serving to group multiple statements, as in DO; say 'Grouped'; say 'statements'; END;. For repetitive execution, a DO group can specify an iteration count, such as DO 5; say i; END;, which repeats the block five times while implicitly setting a counter variable i from 1 to 5. Controlled iteration uses the form DO name=initial TO final [BY increment]; ... END;, where the loop variable name advances from initial to final in steps of increment (defaulting to 1), for example, DO i=1 TO 10 BY 2; say i; END;, outputting odd numbers from 1 to 9. Conditional variants include DO WHILE condition; ... END;, which tests the condition before each iteration and continues only if true, and DO UNTIL condition; ... END;, which tests after each iteration and stops when true; both can combine with iteration specs, like DO i=1 TO 10 WHILE i<6; say i; END;. Infinite loops use DO FOREVER; ... END;, requiring explicit termination via other controls. These DO types support nesting and can mix iteration and conditions for complex loops, with the control variable's final value retained after execution.[57][53] Conditional execution relies on the IF statement, structured as IF condition THEN instruction [ELSE instruction];, where the THEN clause executes if the condition evaluates to true (non-zero and non-null in Rexx's logical sense), and the optional ELSE provides an alternative for false conditions. For multi-statement blocks, IF uses a DO group: IF condition THEN DO; instructions; END; [ELSE DO; instructions; END;]. This supports multi-way decisions through nested IFs or chained ELSE clauses, though deeply nested forms can reduce readability. For instance, IF x > 0 THEN SAY 'Positive' ELSE SAY 'Non-positive'; demonstrates basic usage, while IF answer='YES' THEN DO; say 'OK!'; ELSE say 'Why not?'; END; handles grouped actions. ELSE clauses pair with the nearest unmatched IF, ensuring unambiguous scoping in nests.[57][53] For switch-like multi-way branching, Rexx employs the SELECT construct: SELECT; WHEN condition THEN instruction; [WHEN condition THEN instruction; ...] [OTHERWISE instruction;] END;, which evaluates WHEN conditions in order and executes the first true one's THEN clause, falling to OTHERWISE if none match. Multi-statement WHEN or OTHERWISE blocks require DO-END, as in:
SELECT;
  WHEN x=1 THEN DO; say 'One'; END;
  WHEN x=2 THEN say 'Two';
  OTHERWISE say 'Other';
END;
This structure promotes efficient handling of multiple discrete cases, with OTHERWISE being optional but recommended for completeness. Conditions in IF, SELECT, and DO loops involve Rexx's expression evaluation, where logical truth is any non-zero numeric or non-null string value.[57][53] Within DO loops, flow can be altered using LEAVE and ITERATE. LEAVE [loopname]; immediately exits the innermost (or named) DO group, useful for early termination, such as in DO i=1 TO 10; if i=5 THEN LEAVE; say i; END;, which outputs 1 through 4. Conversely, ITERATE [loopname]; skips remaining instructions in the current iteration and advances to the next, for example, DO i=1 TO 4; if i=2 THEN ITERATE; say i; END;, outputting 1, 3, and 4. Rexx lacks a direct break equivalent outside loops but uses SIGNAL for broader exits, though LEAVE and ITERATE suffice for most iterative control without overlapping variable scoping issues, as loop variables are local to their DO group unless explicitly declared otherwise.[57][53]

Variables and Data Handling

In REXX, variables are typeless and require no explicit declaration; they are created implicitly upon the first assignment using the equals operator (=). For instance, the statement x = 5 creates the variable x and assigns it the value 5, which can be a string, number, or expression result. Variable names, known as symbols, consist of letters (A-Z, a-z), digits (0-9), and periods (.), starting with a letter or period, and are case-insensitive by default, though implementations may vary in preserving case.[41][53] When a variable is referenced before assignment, its behavior depends on the context and implementation settings. In string contexts, an unassigned variable substitutes its own name in uppercase letters (e.g., referencing foo outputs "FOO"), unless the variable has been explicitly dropped, in which case it may raise the NOVALUE condition. In numeric contexts, referencing an unassigned variable raises the NOVALUE condition unless trapped with SIGNAL ON NOVALUE, allowing programmers to handle such cases gracefully without strong typing enforcement. This design promotes flexibility while encouraging explicit error handling for uninitialized data.[60][53][41] REXX employs a dynamic typing system with no distinction between integers, floats, or other numeric types; all variables store strings internally, and type conversion occurs automatically based on usage. For example, assigning y = "123" treats y as the string "123", but using it in a numeric operation like z = y + 1 converts it to the number 123, resulting in z = 124. The DATATYPE built-in function can inspect a variable's effective type (e.g., NUM for numeric, CHAR for character string), but no compile-time or runtime type checking enforces fixed types, reducing errors from type mismatches.[41][53][60] Expressions involving variables are evaluated from left to right, respecting operator precedence (e.g., exponentiation ** before multiplication * and division /, which precede addition + and subtraction -), with parentheses overriding the order. Numbers in expressions are interpreted as decimal unless specified otherwise (e.g., 3.14 or 1E3 for scientific notation), while non-numeric strings remain as-is. Lazy evaluation is not strictly defined, but variable substitution occurs just before operations, allowing indirect references without immediate resolution. For example:
total = price * (1 + tax_rate)
Here, if price is "10.00" and tax_rate is 0.08, total becomes 10.80 after implicit conversions.[41][53] Compound variables extend scalar handling by using a stem (a symbol followed by a period, e.g., arr.) combined with a tail (a derived symbol or expression, e.g., arr.1), forming dynamic structures like arrays or associative storage without predefined sizes. Assignment creates elements on demand, such as arr.1 = "value", and the special tail .0 often tracks the number of elements (e.g., arr.0 = 3). Tails support indirect referencing via tail notation, where the tail is another variable or expression (e.g., i = 2; word.i = "hello" sets word.2 to "hello"). This enables flexible data structures, like:
do i = 1 to 3
  data.i = i * 10
end
resulting in data.1 = 10, data.2 = 20, and data.3 = 30, with automatic indexing.[60][53][41] Special variables provide access to runtime state without explicit assignment. The RC variable holds the return code from the previous external command, function call, or address space invocation (e.g., after ADDRESS TSO "LISTDS", RC might be 0 for success). The single dot (.) represents the current iteration index in loops or the result of the last evaluated expression in certain contexts. These, along with reserved symbols like SIGL (signal label) and RESULT (routine return value), are predefined in the variable pool and cannot be freely reassigned in standard implementations. Tail notation in compounds often interacts with these for dynamic access, such as word.RC to index by return code value. The NOVALUE condition further safeguards against unintended references to unset special or compound elements.[41][53][60]

String Processing and Evaluation

Rexx provides robust facilities for string manipulation and dynamic evaluation, primarily through the PARSE instruction and the INTERPRET instruction, enabling efficient scripting for data extraction and code generation.[61] These tools allow developers to split input strings into variables using customizable templates and to execute strings as Rexx code at runtime, making Rexx particularly suited for processing command-line arguments, user input, and generated scripts.[62][63] The PARSE instruction assigns data from various sources to one or more variables according to specified parsing rules.[62] Its general syntax is PARSE [UPPER] [source] [WITH] template_list, where the optional UPPER clause converts the source string to uppercase before parsing, and the source can be one of several variants: ARG for program arguments, EXTERNAL for terminal input, NUMERIC for settings like DIGITS and FUZZ, PULL for data queue or input stream, SOURCE for program invocation details, VALUE followed by an expression, VAR followed by a variable name, or VERSION for language level information.[62] For instance, PARSE ARG args extracts command-line arguments into variables, while PARSE PULL line reads the next line from input and parses it.[64] Templates consist of symbols or patterns separated by blanks, with multiple templates separated by commas; if no template is provided, the source string is prepared but not assigned.[62] Parsing operates positionally on the source string, assigning substrings to variables based on template elements.[65] Basic templates split by default on blanks into words, but advanced patterns include wildcards for precise control: a single period (.) matches one or more characters until the next template element or end of string, .n matches exactly n characters, and .d matches a single digit.[65] String literals in templates match exact sequences, which can be case-sensitive, and relative positioning like +n skips n characters after a match.[65] Rexx does not support regular expressions in templates, relying instead on these simple yet powerful positional and wildcard rules for common parsing tasks.[65] An example is PARSE VAR line a b c, which splits a string variable line by spaces into three variables; for patterned parsing, PARSE VALUE time() WITH hours '.' mins '.' secs extracts components from a time string like "12.34.56" into hours, mins, and secs.[62] Another is PARSE UPPER ARG word1 .3 rest, which uppercases arguments, assigns the first word to word1, the next three characters to a variable, and the remainder to rest.[64] These mechanisms integrate seamlessly with variables for dynamic content handling, such as building templates from computed values.[65] The INTERPRET instruction enables dynamic execution by evaluating a string expression as Rexx code, effectively treating it as if it were a clause in the program.[63] Its syntax is simply INTERPRET expression;, where the expression is first evaluated to a string, a semicolon is appended if absent, and the result is then executed.[63] This allows for runtime code generation, such as constructing loops or assignments from data; for example, INTERPRET 'data = 4' assigns the value 4 to the variable data.[63] More complex uses include cmd = 'DO 3; SAY "Hello!"; END'; INTERPRET cmd, which outputs "Hello!" three times.[63] However, INTERPRET has limitations: it cannot handle label clauses, partial constructs like a standalone LEAVE without a full loop, or nested dynamic instructions that alter control flow unexpectedly.[63] Due to its power, INTERPRET poses risks such as code injection if the expression incorporates untrusted input, so it should be used cautiously, often with debugging via TRACE Results or Interactive modes to inspect execution.[63] For simpler evaluations without full instruction execution, the VALUE function serves as a safer alternative.[63]

Numeric Operations and Precision

Rexx provides arbitrary-precision decimal arithmetic, allowing computations with extremely large numbers without overflow, controlled primarily through the NUMERIC instruction. This instruction sets the precision and behavior for arithmetic operations and comparisons. The NUMERIC DIGITS n clause specifies the number of significant digits for calculations, with a default of 9; conforming implementations must support at least 999, though the maximum is implementation-defined. values below 9 reduce precision and should be used cautiously to avoid unexpected rounding effects.[66][67][60] The NUMERIC FUZZ m clause defines the tolerance for numeric comparisons by ignoring the specified number of least significant digits, with a default of 0 and a maximum equal to the current DIGITS value minus 1; during comparisons, the effective precision is temporarily reduced by the fuzz amount, treating numbers as equal if their difference falls within this tolerance.[67] The NUMERIC FORM clause determines the exponential notation for output: SCIENTIFIC (default, using powers of 10, e.g., 1.23E+4) or ENGINEERING (using powers of 1,000, e.g., 1.23E+3 for 1,230); this affects how results exceeding the displayable digits are formatted when converted to strings.[67] Omitting operands in the NUMERIC instruction displays the current settings, and built-in functions DIGITS(), FUZZ(), and FORM() return these values as strings.[68] Arithmetic operations in Rexx include addition (+), subtraction (-), multiplication (*), division (/ for exact decimal division), integer division (% which truncates toward zero), remainder (//), and exponentiation (** with a non-negative integer exponent). All operations respect the current NUMERIC DIGITS setting for precision, handling big decimals exactly; for example, 12345678901234567890 + 1 yields the precise result without truncation. Division (/) produces results rounded to the current precision, while integer division (%) discards the fractional part toward zero, and remainder (//) follows the sign of the dividend. Invalid operations, such as division by zero, raise errors.[69][70] Relevant built-in functions support numeric manipulation under the current settings: ABS(number) returns the absolute value, SIGN(number) returns -1 for negative, 0 for zero, or 1 for positive inputs, and TRUNC(number [, n]) truncates to the integer part (default n=0) or to n decimal places, always toward zero. These functions, along with others like FORMAT(), adhere to NUMERIC precision except where specified otherwise. For output in engineering notation, the FORMAT function can specify an exponent type of 'E' to force powers of 1,000 regardless of the NUMERIC FORM setting.[71][68] To illustrate precision control, consider setting high accuracy for approximations: NUMERIC DIGITS 50 followed by pi = 22 / 7 retains the result as a 50-digit decimal (approximately 3.14285714285714285714285714285714285714285714286), demonstrating exact handling without premature rounding; lowering DIGITS to 5 would yield 3.1429 after rounding. Such capabilities enable precise financial or scientific computations, but users must manage DIGITS to balance accuracy and performance, as higher values increase computation time.[66][70] Limitations include truncation toward zero in integer division and the TRUNC function, which may differ from rounding behaviors in other languages; Rexx does not natively support complex numbers or floating-point binary arithmetic, relying instead on decimal representation throughout. Errors occur for non-numeric inputs in arithmetic contexts, promoting robust numeric handling.[69][70]

Error Handling and Debugging

Rexx employs a condition-based mechanism for error handling, allowing programs to trap and respond to specific runtime events without a traditional try-catch construct. Conditions such as ERROR, FAILURE, HALT, NOVALUE, and SYNTAX can be trapped using the SIGNAL ON or CALL ON instructions, which enable or disable traps for these events.[72] When a condition occurs, control transfers to a designated internal label, where the program can handle the error, log details, or take corrective action. The SIGNAL ON variant immediately branches to the trap routine and does not return, making it suitable for fatal errors, while CALL ON invokes the routine as a subroutine, allowing execution to resume afterward.[72] The ERROR condition is raised when a host command returns a positive return code indicating an error, unless a FAILURE trap is active.[72] FAILURE triggers on negative return codes from commands, signifying severe issues like command failures.[72] HALT occurs due to external interruptions, such as user-initiated stops.[72] NOVALUE is raised when referencing an uninitialized simple variable, helping prevent unintended behaviors in scripting.[72] SYNTAX handles parsing or runtime syntax errors, though it only works with SIGNAL ON.[72] Traps are initially off and can be specified with a label, such as SIGNAL ON NOVALUE NAME badvar, directing flow to the badvar: label upon occurrence. In the handler, the special variable RC holds the return code for command-related conditions, enabling inspection of the error severity.[72] For example, the following code traps a NOVALUE condition:
SIGNAL ON NOVALUE NAME trap_novalue
x = y + 1  /* y is uninitialized */
trap_novalue:
  SAY "Variable not set: " RC
  EXIT 1  /* Terminate with [error code](/page/Error_code) */
Here, the trap routine displays a message and uses the EXIT instruction to end the program, setting the overall return code to 1, which is stored in the invoker's RC variable if applicable.[73] The EXIT instruction unconditionally terminates the exec, optionally specifying a numeric value as the return code to propagate success (0) or failure status back to the caller or environment.[73] In some implementations like Object REXX, handlers can use PROPAGATE to re-raise the condition up the call chain for further processing.[74] Debugging in Rexx primarily relies on the TRACE instruction, which logs program execution details to aid in identifying issues. TRACE options include ALL, which displays every clause before execution; RESULTS, showing expressions and their outcomes; NORMAL, tracing only errored commands; and OFF to disable tracing.[75] For interactive debugging, the ? prefix pauses at each traced line, allowing step-by-step inspection, while ! inhibits host command execution to test logic safely.[75] Host environments often support interactive modes where TRACE can be toggled dynamically, combined with condition traps for comprehensive error diagnosis. For instance, TRACE ALL followed by SIGNAL ON SYNTAX enables full visibility into syntax errors during development.[75] This facility provides flexible, non-intrusive tools for scripting errors, emphasizing Rexx's suitability for interactive and automated tasks.[72]

Current Status (as of 2026)

REXX remains actively maintained and used in 2026, particularly in niche and legacy environments such as IBM mainframes (z/OS, z/VM, IBM i), where it is bundled and supported for scripting, automation, batch job control, and system management. Development continues through open-source implementations managed by the Rexx Language Association (RexxLA). Key implementations include:
  • Open Object Rexx (ooRexx): The primary open-source, object-oriented extension, with version 5.1.0 released in 2025 featuring enhancements like JSON class improvements and multi-threading tracing. A 5.2.0 beta is available, showing ongoing progress.
  • Regina REXX: A popular ANSI-compliant classic interpreter with recent stable and preview releases.
  • IBM proprietary versions still integrated in mainframe products.
The RexxLA organizes the 37th International Rexx Language Symposium in Barcelona, Spain (May 3–6, 2026, with online participation), demonstrating sustained community interest. Tools such as VS Code extensions (including Broadcom OPS/REXX support), IntelliJ plugins, Exercism tracks, and GitHub activity (e.g., Advent of Code solutions) reflect modern tooling and educational use. While not mainstream (outside TIOBE top 50–100), REXX endures in enterprise automation, mainframe operations, and enthusiast scripting due to its reliability, simplicity, and integration. Multiple free interpreters exist across platforms, and it remains ISO/ANSI standardized.

References

User Avatar
No comments yet.