REXX Language implementation
String instructions operate on length-delimited string payloads. RXAS registers are not statically typed: each instruction reads or writes the string or integer payload described below without copying unrelated payloads or public flags.
In UTF builds, character positions and lengths are zero-based Unicode code-point
counts unless an instruction explicitly says one-based or byte-oriented.
Instructions that validate text raise UNICODE_ERROR; strict byte comparisons
and the legacy byte-oriented trim/truncate operations do not validate UTF-8.
appendAppend one register’s complete string payload to another in place.
| Opcode | Form | Effect |
|---|---|---|
0x008f |
append rDst,rSrc |
Set rDst to rDst || rSrc. |
Both operands are string registers. rDst is resized and its VM-private UTF
lookup cache is reset. rSrc is unchanged, and self-append is supported.
No catchable VM signal is defined; allocation failure is fatal.
.globals=0
main() .locals=2
load r0,"Hello"
load r1,"!"
append r0,r1
ret
concat, sappend.
appendcharAppend one Unicode code point, supplied as an integer payload, to a string.
| Opcode | Form | Effect |
|---|---|---|
0x008c |
appendchar rString,rCodepoint |
Append rCodepoint to rString. |
rCodepoint is an integer register. UTF builds encode it as UTF-8. The
destination lookup cache is reset; the source register is unchanged.
No signal is raised. A non-scalar integer is not rejected, but clears the destination’s known-valid UTF state.
.globals=0
main() .locals=2
load r0,"A"
load r1,66
appendchar r0,r1
ret
concchar, padstr.
concatConcatenate two strings without inserting a blank.
| Opcode | Form | Effect |
|---|---|---|
0x0086 |
concat rDst,rLeft,rRight |
Concatenate two register strings. |
0x0087 |
concat rDst,rLeft,"text" |
Use a string constant on the right. |
0x0088 |
concat rDst,"text",rRight |
Use a string constant on the left. |
The destination string is replaced and its private lookup cache resets. Register sources are unchanged and may alias the destination.
No catchable VM signal is defined.
.globals=0
main() .locals=3
load r1,"Hello"
load r2,"World"
concat r0,r1,r2
ret
append, sconcat.
conccharAppend the code point at a zero-based character index in a source string.
| Opcode | Form | Effect |
|---|---|---|
0x008d |
concchar rDst,rString,rIndex |
Append rString[rIndex] to rDst. |
rIndex is an integer register and is restored after temporary internal use.
Locating the code point may update the source’s private lookup cache; this is
not observable RXAS state. rDst is appended to, not cleared.
Invalid UTF-8 raises UNICODE_ERROR. There is no explicit index-range signal;
the index must name an existing character.
.globals=0
main() .locals=3
load r0,""
load r1,"abc"
load r2,1
concchar r0,r1,r2
ret
appendchar, strchar.
hexcharFormat a selected source character as uppercase hexadecimal.
| Opcode | Form | Effect |
|---|---|---|
0x0098 |
hexchar rDst,rString,rIndex |
Format the zero-based character at rIndex. |
By default rDst receives the low byte of the code point as two hex digits. If
its incoming string contains UTFV1, it receives four UTF-8 bytes padded to
eight digits; UTFV2 requests only the actual UTF-8 bytes. The destination
lookup cache resets; locating the character may update the source’s private
cache without changing its value.
Invalid UTF-8 raises UNICODE_ERROR. There is no explicit range signal;
rIndex must name an existing character.
.globals=0
main() .locals=3
load r0,""
load r1,"A"
load r2,0
hexchar r0,r1,r2
ret
strchar.
padstrAppend one integer code point repeatedly to an existing string.
| Opcode | Form | Effect |
|---|---|---|
0x00a3 |
padstr rDst,rCodepoint,rCount |
Append the code point rCount times. |
rCodepoint and rCount are integer registers. The destination is not cleared
first. A zero or negative count appends nothing; otherwise its private lookup
cache is reset.
No signal is raised. Invalid Unicode scalar integers are not rejected.
.globals=0
main() .locals=3
load r0,""
load r1,42
load r2,3
padstr r0,r1,r2
ret
appendchar, trunc.
poscharFind the first occurrence of an integer code point in a string.
| Opcode | Form | Effect |
|---|---|---|
0x0099 |
poschar rIndex,rString,rCodepoint |
Return a zero-based index or -1. |
The result overwrites rIndex’s integer payload. The search starts at the
beginning. The logical string and code-point register remain unchanged; any
UTF lookup caching is private to the VM.
Invalid UTF-8 raises UNICODE_ERROR; not found returns -1.
.globals=0
main() .locals=3
load r1,"abc"
load r2,98
poschar r0,r1,r2
ret
strpos, strchar.
sappendAppend one ASCII blank and then another register’s string payload.
| Opcode | Form | Effect |
|---|---|---|
0x008e |
sappend rDst,rSrc |
Set rDst to rDst || " " || rSrc. |
The blank is inserted even if either string is empty. rDst is resized and its
private lookup cache resets. rSrc is unchanged; self-append is supported.
No catchable VM signal is defined; allocation failure is fatal.
.globals=0
main() .locals=2
load r0,"Hello"
load r1,"World"
sappend r0,r1
ret
append, sconcat.
sconcatConcatenate two strings with exactly one ASCII blank between them.
| Opcode | Form | Effect |
|---|---|---|
0x0089 |
sconcat rDst,rLeft,rRight |
Join two register strings. |
0x008a |
sconcat rDst,rLeft,"text" |
Use a string constant on the right. |
0x008b |
sconcat rDst,"text",rRight |
Use a string constant on the left. |
The destination is replaced and its private lookup cache resets. The intervening
blank is unconditional. Register sources are unchanged and may alias rDst.
No catchable VM signal is defined; allocation failure is fatal.
.globals=0
main() .locals=3
load r1,"Hello"
load r2,"World"
sconcat r0,r1,r2
ret
concat, sappend.
scopyCopy only a register’s string payload.
| Opcode | Form | Effect |
|---|---|---|
0x000b |
scopy rDst,rSrc |
Copy the logical string to rDst. |
The destination receives the bytes, character count, and VM-private UTF validity state; its private lookup cache resets. Integer, float, decimal, binary, attributes, and public flags are not copied. The source is unchanged.
This instruction does not raise a signal.
.globals=0
main() .locals=2
load r1,"copy"
scopy r0,r1
ret
copy, concat.
seqTest two strings for exact equality.
| Opcode | Form | Effect |
|---|---|---|
0x0074 |
seq rResult,rLeft,rRight |
Compare two register strings. |
0x0075 |
seq rResult,rLeft,"text" |
Compare a register with a string constant. |
This is a length-aware byte comparison with no numeric coercion or
trailing-blank padding. rResult receives integer 1 for equality or 0
otherwise. Sources are unchanged.
The comparison does not validate UTF-8 and does not raise a signal.
.globals=0
main() .locals=3
load r1,"same"
load r2,"same"
seq r0,r1,r2
ret
sne, rseq.
sgtTest exact lexicographic greater-than ordering.
| Opcode | Form | Effect |
|---|---|---|
0x007a |
sgt rResult,rLeft,rRight |
Compare two register strings. |
0x007b |
sgt rResult,rLeft,"text" |
Constant on the right. |
0x007c |
sgt rResult,"text",rRight |
Constant on the left. |
Strings are compared as length-aware byte sequences with no numeric coercion
or blank padding. rResult receives integer 1 or 0; sources are unchanged.
The comparison does not validate UTF-8 and does not signal.
.globals=0
main() .locals=3
load r1,"b"
load r2,"a"
sgt r0,r1,r2
ret
sgte, slt.
sgteTest exact lexicographic greater-than-or-equal ordering.
| Opcode | Form | Effect |
|---|---|---|
0x007d |
sgte rResult,rLeft,rRight |
Compare two register strings. |
0x007e |
sgte rResult,rLeft,"text" |
Constant on the right. |
0x007f |
sgte rResult,"text",rRight |
Constant on the left. |
Comparison is strict and byte-oriented, without numeric conversion or blank
padding. rResult receives integer 1 or 0. Sources are unchanged.
The comparison does not validate UTF-8 and does not signal.
.globals=0
main() .locals=3
load r1,"b"
load r2,"b"
sgte r0,r1,r2
ret
sgt, slte.
sltTest exact lexicographic less-than ordering.
| Opcode | Form | Effect |
|---|---|---|
0x0080 |
slt rResult,rLeft,rRight |
Compare two register strings. |
0x0081 |
slt rResult,rLeft,"text" |
Constant on the right. |
0x0082 |
slt rResult,"text",rRight |
Constant on the left. |
Comparison is a strict length-aware byte ordering. rResult receives integer
1 or 0; sources remain unchanged.
The comparison does not validate UTF-8 and does not signal.
.globals=0
main() .locals=3
load r1,"a"
load r2,"b"
slt r0,r1,r2
ret
slte, sgt.
slteTest exact lexicographic less-than-or-equal ordering.
| Opcode | Form | Effect |
|---|---|---|
0x0083 |
slte rResult,rLeft,rRight |
Compare two register strings. |
0x0084 |
slte rResult,rLeft,"text" |
Constant on the right. |
0x0085 |
slte rResult,"text",rRight |
Constant on the left. |
Comparison is strict and byte-oriented. rResult receives integer 1 or 0;
source strings are unchanged.
The comparison does not validate UTF-8 and does not signal.
.globals=0
main() .locals=3
load r1,"a"
load r2,"a"
slte r0,r1,r2
ret
slt, sgte.
sneTest two strings for exact inequality.
| Opcode | Form | Effect |
|---|---|---|
0x0078 |
sne rResult,rLeft,rRight |
Compare two register strings. |
0x0079 |
sne rResult,rLeft,"text" |
Compare a register with a constant. |
This is the inverse of strict seq, including length. rResult receives
integer 1 when the byte strings differ and 0 otherwise. Sources are unchanged.
The comparison does not validate UTF-8 and does not signal.
.globals=0
main() .locals=3
load r1,"a"
load r2,"b"
sne r0,r1,r2
ret
seq.
stobConvert a string payload to the VM’s narrow Boolean convention.
| Opcode | Form | Effect |
|---|---|---|
0x00eb |
stob rValue |
Write an integer Boolean in the same register. |
The integer payload becomes 1 only when the string is exactly the single byte
1; every other string becomes 0. The string payload is unchanged.
This instruction does not raise a conversion signal.
.globals=0
main() .locals=1
load r0,"1"
stob r0
ret
stoi, itob, btos.
stofParse a register’s complete string payload as a binary64 value.
| Opcode | Form | Effect |
|---|---|---|
0x00ec |
stof rValue |
Write the float payload in the same register. |
The string payload remains unchanged. The whole logical string must match the VM numeric parser’s float grammar.
Invalid or out-of-range numeric text raises CONVERSION_ERROR.
.globals=0
main() .locals=1
load r0,"12.5"
stof r0
ret
ftos, stoi, stod.
stoiParse a register’s complete string payload as a VM integer, either in place or directly into a separate destination.
| Opcode | Form | Effect |
|---|---|---|
0x00ed |
stoi rValue |
Write the integer payload in the same register. |
0x0128 |
stoi rResult,rValue |
Parse rValue.string directly into rResult.int. |
The source string payload remains unchanged. In the two-register form the source register receives no integer side effect. The parser requires a complete valid integer representation within the VM integer range.
Invalid or out-of-range text raises CONVERSION_ERROR.
.globals=0
main() .locals=1
load r0,"42"
stoi r0
ret
itos, stof, stob.
strcharRead a Unicode code point from a string into an integer payload.
| Opcode | Form | Effect |
|---|---|---|
0x0096 |
strchar rCodepoint,rString,rIndex |
Read zero-based character rIndex. |
UTF builds return the Unicode scalar value at the explicit zero-based character index; non-UTF builds return the byte value. The source is unchanged.
Invalid UTF-8 raises UNICODE_ERROR. An index outside the source raises
OUT_OF_RANGE.
.globals=0
main() .locals=3
load r1,"A"
load r2,0
strchar r0,r1,r2
ret
hexchar, concchar, substring.
strlenReturn a string’s logical character length.
| Opcode | Form | Effect |
|---|---|---|
0x0095 |
strlen rLength,rString |
Write the character count to rLength. |
UTF builds count Unicode code points; non-UTF builds count bytes. The source string is unchanged. Only the destination integer payload is written.
Invalid UTF-8 raises UNICODE_ERROR.
.globals=0
main() .locals=2
load r1,"abc"
strlen r0,r1
ret
substring, trunc.
strlowerCopy a string and convert it to lowercase.
| Opcode | Form | Effect |
|---|---|---|
0x009d |
strlower rDst,rSrc |
Lowercase rSrc into rDst. |
The destination is replaced and its private lookup cache resets. UTF builds use the project Unicode case mapping. The source is unchanged; destination aliasing is supported.
Invalid UTF-8 raises UNICODE_ERROR. Length-changing Unicode mappings are a
documentation-only implementation ambiguity: the opcode does not explicitly
recompute logical length metadata after conversion.
.globals=0
main() .locals=2
load r1,"Mixed"
strlower r0,r1
ret
strupper.
strposFind a substring using one-based Rexx positions.
| Opcode | Form | Effect |
|---|---|---|
0x00a4 |
strpos rStartResult,rNeedle,rHaystack |
Search from and return a one-based position. |
On entry rStartResult contains the one-based start; on return it is overwritten
with the one-based match position or 0. UTF positions count code points. The
haystack value is unchanged. Both source buffers may be NUL-terminated
internally without changing logical text.
Invalid UTF-8 raises UNICODE_ERROR. A nonpositive start or a start beyond the
haystack returns 0.
.globals=0
main() .locals=3
load r0,1
load r1,"World"
load r2,"Hello World"
strpos r0,r1,r2
ret
poschar, seq.
strupperCopy a string and convert it to uppercase.
| Opcode | Form | Effect |
|---|---|---|
0x009e |
strupper rDst,rSrc |
Uppercase rSrc into rDst. |
The destination is replaced and its private lookup cache resets. UTF builds use the project Unicode case mapping. The source remains unchanged and may alias the destination.
Invalid UTF-8 raises UNICODE_ERROR. The current implementation does not
explicitly refresh length metadata after a length-changing Unicode mapping.
.globals=0
main() .locals=2
load r1,"Mixed"
strupper r0,r1
ret
strlower.
substcutTruncate a string in place to a number of leading Unicode characters.
| Opcode | Form | Effect |
|---|---|---|
0x00a2 |
substcut rString,rLength |
Keep at most rLength leading characters. |
rLength is an integer register. Byte and character lengths are updated and
the private lookup cache resets. A length beyond the string leaves it
unchanged. A negative integer converts to a large unsigned size and therefore
also leaves the string unchanged.
Invalid UTF-8 raises UNICODE_ERROR; out-of-range lengths do not signal.
.globals=0
main() .locals=2
load r0,"abcdef"
load r1,3
substcut r0,r1
ret
trunc, substring.
substringCopy a character range using an explicit zero-based start and length.
| Opcode | Form | Effect |
|---|---|---|
0x00a1 |
substring rDst,rSrc,rStart,rLength |
Copy characters [rStart,rStart+rLength). |
rStart and rLength are integer registers. A negative start clamps to zero;
a nonpositive length yields an empty destination; and a start or length beyond
the source clips to its character count. The source is unchanged and
destination/source aliasing is supported.
Invalid UTF-8 raises UNICODE_ERROR; clipping does not signal.
.globals=0
main() .locals=4
load r1,"abcdef"
load r2,1
load r3,2
substring r0,r1,r2,r3
ret
strchar, substcut, trunc.
swapExchange two complete register bindings. The instruction is deprecated, but its effect is persistent.
| Opcode | Form | Effect |
|---|---|---|
0x01fe |
swap rLeft,rRight |
Exchange the two register storage bindings. |
The VM swaps the two pointers in the current frame’s register table. All value payloads, attributes, reference/native payloads, and status flags therefore move together with their storage. This is not a payload copy and does not allocate. Subsequent uses of either register number see the other register’s former complete value.
This instruction does not raise a signal.
.globals=0
main() .locals=2
load r0,"left"
load r1,"right"
swap r0,r1
say r0
say r1
ret
right
left
copy, move, link.
transcharTranslate one integer code point through two parallel character lists.
| Opcode | Form | Effect |
|---|---|---|
0x009f |
transchar rCodepoint,rReplacementList,rSearchList |
Replace a matched code point. |
rCodepoint supplies and receives an integer. The VM scans rSearchList; a
match at character index i selects character i from rReplacementList. No
match preserves the input. VM-private UTF lookup caches may change during
scanning without becoming observable value state.
Invalid UTF-8 in either list raises UNICODE_ERROR. The replacement list must
cover every matching search-list position; the VM has no separate bounds
signal for a shorter replacement list.
.globals=0
main() .locals=3
load r0,97
load r1,"A"
load r2,"a"
transchar r0,r1,r2
ret
poschar, strchar.
trimlRemove repeated leading bytes from a string.
| Opcode | Form | Effect |
|---|---|---|
0x0090 |
triml rString,rIgnored |
Deprecated in-place ASCII-space trim; operand 2 is ignored. |
0x0092 |
triml rDst,rSrc,rTrim |
Copy, then trim the first byte of rTrim. |
The two-register form removes leading ASCII spaces. The three-register form is
byte-oriented and removes only repetitions of rTrim’s first byte; an empty
trim string removes nothing. The result is NUL-terminated. Character-count
metadata is not consistently recomputed by these legacy forms.
No signal is raised and UTF-8 is not validated.
.globals=0
main() .locals=3
load r1," text"
load r2," "
triml r0,r1,r2
ret
trimr, trunc.
trimrRemove repeated trailing bytes from a string.
| Opcode | Form | Effect |
|---|---|---|
0x0091 |
trimr rString,rIgnored |
Deprecated in-place ASCII-space trim; operand 2 is ignored. |
0x0093 |
trimr rDst,rSrc,rTrim |
Copy, then trim the first byte of rTrim. |
The two-register form removes trailing ASCII spaces. The three-register form
removes only repetitions of the first byte in rTrim; an empty trim string
removes nothing. The source remains unchanged in the three-register form.
Character-count metadata is not consistently refreshed.
No signal is raised and UTF-8 is not validated.
.globals=0
main() .locals=3
load r1,"text!!!"
load r2,"!"
trimr r0,r1,r2
ret
triml, trunc.
truncCopy a string and cap its logical byte length.
| Opcode | Form | Effect |
|---|---|---|
0x0094 |
trunc rDst,rSrc,rLength |
Keep at most rLength bytes. |
Despite the historical description saying characters, the implementation
compares rLength with the byte length. Negative lengths become zero. It can
therefore split a UTF-8 sequence and does not recompute character metadata.
Use substcut for character truncation.
This instruction does not validate UTF-8 and raises no range signal.
.globals=0
main() .locals=3
load r1,"abcdef"
load r2,3
trunc r0,r1,r2
ret
substcut, substring.