REXX Language implementation
ADDRESS sends commands or function requests to a named external environment.
It is implemented through the current compiler-exit and VM environment protocol.
Basic command form:
address system "echo hello"
Command output and error streams can be captured:
address command "echo #42" output out error err
say out
ADDRESS host-variable anchors such as :name and ${name} are compiler
auto-expose syntax. Their command meaning belongs to the selected environment
handler; the VM carries binding values and write-back updates.
The current native registration API is environment based:
rxvml_address_register_callback_environment(ctx, name, id,
command_cb, function_cb, userdata);
The old command-only callback registration form is retired.
See Procedures and Arguments Section
CALL routine [ parameter ] [, [ parameter ] … ]
DO [ repetitor ] [ conditional ] ; [ clauses ]
expr ::= DO ; [ clauses ] END
END [ symbol ] ;
repetitor : = symbol = expri [ TO exprt ] [ BY exprb ] [ FOR exprf ]
conditional : = WHILE exprw UNTIL expru
The DO/END statement is the command employed to iterate and group multiple statements into a singular block. This instruction consists of multiple clauses.
When DO ... END appears where an expression is expected, it is parsed as a block expression. In that form the body must yield a value using LEAVE WITH expr.
Simple DO ... END groups may also carry block-scoped signal handlers using
ON SIGNAL clauses. The handler clauses are valid only on a simple DO group,
not on counted, conditional, forever, or expression-form DO. To protect code
inside a loop, nest a simple signal-handling DO ... END group inside the loop
body.
EXIT [ expr ] ;
Causes the Rexx program to cease execution and, optionally, returns the expression expr to the calling program.
IF expr [;] THEN [;] statement
[ ELSE [;] statement ]
This provides the standard conditional statement structure.
ITERATE [ symbol ] ;
The ITERATE instruction will execute the innermost, active loop in which the ITERATE instruction is situated repeatedly. If a symbol is specified, it will execute the innermost, active loop having the symbol as the control variable repeatedly.
LEAVE [ symbol ] ;
LEAVE WITH expr ;
This statement terminates the innermost, active loop. If symbol is specified, it terminates the innermost, active loop having symbol as control variable.
LEAVE WITH expr is distinct from loop-control LEAVE. It exits the innermost enclosing expression-form DO ... END block and returns the value of expr to the parent expression.
NOP ;
The NOP instruction is the “null operation” directive; it executes without performing any operation.
OPTIONS expr ;
The OPTIONS instruction is used to set various interpreter-specific options. See Language Level and Options Section
PARSE [ option ] [ CASELESS ] type [ template ] ;
Current implementation status:
PARSE VALUE ..., PARSE VAR ..., and PARSE ARG ... are implemented through the certified PARSE exit.PARSE ARG uses the current procedure’s arg() compatibility view.main, that means command-line arguments.... tail if present, or an empty source string if there is no ... tail.See Procedures and Arguments Section.
SAY [ expr ] ;
Evaluates the expression expr and prints the resulting string onto the standard output stream.
SELECT [expression] [;] WHEN expression [, expression …] [;] THEN [;] instruction [;] [WHEN expression [, expression …] [;] THEN [;] instruction [;]] … [OTHERWISE [;] [instruction] [;] …] END [;]
The SELECT statement allows you to conditionally evaluate multiple expressions and execute corresponding instructions based on the first expression that evaluates to true (1).
There are two styles of the SELECT statement in cREXX:
expression after the SELECT keyword. Each WHEN expression is evaluated as a standalone boolean condition.expression after the SELECT keyword. The expression is evaluated once, and its result is implicitly compared for equality (=) against each WHEN expression.If a WHEN condition is met, its associated THEN instruction is executed, and control exits the SELECT block. If no WHEN condition is met, the OTHERWISE block (if present) is executed. If no WHEN condition is met and an OTHERWISE block is absent, the SELECT statement acts as a NOP (null operation) and does nothing.
Signals are Level B error/condition objects implementing .signal.
Rexx-created signals can be raised with a signal object or with the compact
named forms:
signal .signal("error", "message")
signal error
signal error "message"
Procedure-scoped handlers are installed with SIGNAL ON and removed with
SIGNAL OFF:
signal on conversion_error call handle_conversion
signal on error, syntax call handle_problem
signal off conversion_error
handle_conversion: procedure = .signalaction
arg problem = .signal
say problem.source()
return .signalaction.skip()
The handler procedure receives one .signal argument and returns a
.signalaction: .signalaction.skip(), .signalaction.retry(), or
.signalaction.fail().
Block-scoped handlers use ON SIGNAL clauses on a simple DO ... END group:
do
risky_work()
on signal conversion_error as problem
say problem.source()
on signal error, syntax
call cleanup()
on signal
call log_unhandled_signal()
end
The statements before the first ON SIGNAL clause are the protected body.
Normal completion skips the handlers. A handler that completes normally leaves
the DO block. ON SIGNAL with no names catches all maskable signals.
AS name binds the current .signal object; if AS is omitted, no signal
object is available to that handler.
Only a simple DO ... END group can carry ON SIGNAL clauses. Counted,
conditional, forever, and expression-form DO loops do not carry handlers
directly. To protect code inside a loop, put a simple signal-handling
DO ... END group inside the loop body.
TRACE enables or disables VM breakpoint-backed tracing for the current call
frame and procedures called from it.
The initial supported forms are:
trace off
trace normal
trace rexx
trace asm
TRACE NORMAL and TRACE REXX currently both trace authored Rexx clauses and
skip the runtime/debugger internals by default. TRACE ASM traces VM/RXAS
instruction information and includes source text where metadata is available.
TRACE OFF disables breakpoint tracing and resets the trace runtime state.
TRACE is implemented as a certified compiler exit. It requires normal compiler exit loading; compiling with exits disabled rejects the statement rather than treating it as an implicit command.
Arguments can be passed to a procedure by reference or by value. When an argument is passed by reference, the procedure can modify the original variable that was passed to it. When an argument is passed by value, a copy of the variable is passed to the procedure, and any changes made to the copy do not affect the original variable.
The user-visible rules are:
ARG name = type is pass by value.ARG expose name = type is pass by reference.expose.By example:
ARG a1 = 0, a2 = .int, expose a3 = .aclass, ?a4 = .aclass, a5 = .string[]
Examples:
bump: procedure = .int
arg value = .int
value = value + 1
return value
x = 10
say bump(x)
say x /* still 10 */
bumpref: procedure = .void
arg expose value = .int
value = value + 1
return
x = 10
call bumpref(x)
say x /* now 11 */
The last arguments declaration can be an ellipsis (‘…’), this is used to show that 0 or more arguments can be provided. For example:
ARG a1 = 0, a2 = .int, … = .string
Pseudo Array arg allows access to the ‘…’ arguments. Also see the Arrays section.
... tail, the count forms return 0The type of this Pseudo is the type of the ‘…’ argument
The compatibility arg() operator is designed to provide some compatibility with classic REXX; by example:
... tail, arg() returns 0 and the E/O probe forms operate on that empty tailIn the event that a module file contains instructions preceding a PROCEDURE instruction, an implicit procedure named main() is automatically generated within the namespace of the module file. The arguments for this procedure can be accessed through the pseudo array arg or arg() operator. This implicit main() case is the compatibility bridge that maps classic arg(n) access onto command-line arguments when no explicit signature is present. The return type of the implicitly defined main() procedure is automatically set to either int or void.