public class CoreWords extends WordSet
Constructor and Description |
---|
CoreWords() |
Modifier and Type | Method and Description |
---|---|
void |
abort(XT xt)
Empty the data stack and perform the function of
Quit ,
which includes emptying the return stack, without displaying
a message. |
void |
abortQuote(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
abs(XT xt)
Return the absolute value of top (n).
|
void |
accept(XT xt)
Receive a string of at most top (+n1) characters, placing it
at next (c-addr), returns the actual number of character read.
|
void |
actionOf(XT xt)
Interpret:
Stack{"
name delimited by a
space. |
void |
addressUnitBits(XT xt)
Size of one address unit, in bits.
|
void |
again(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
align(XT xt)
If the data-space pointer is not aligned, reserve enough space
to align it.
|
void |
aligned(XT xt)
a-addr is the first aligned address greater than or
equal to addr . |
void |
allot(XT xt)
If
n is greater than zero, reserve n address
units of data space. |
void |
and(XT xt) |
void |
base(XT xt)
Return the address of the special variable containing the
current number-conversion radix.
|
void |
begin(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
bracketCompile(XT xt)
Append the execution semantics of the definition represented
by
xt to the execution semantics of the current
definition. |
void |
bracketTick(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
bufferColon(XT xt)
Skip leading space delimiters.
|
void |
carageReturn(XT xt)
Cause subsequent output to appear at the beginning of the next
line.
|
void |
CASE(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
cellPlus(XT xt)
Add the size in address units of a cell to
a-addr1 ,
giving a-addr2 . |
void |
cells(XT xt)
n2 is the size in address units of n1 cells. |
void |
character(XT xt)
Return the first character of the next word in the input stream.
|
void |
charComma(XT xt)
Reserve space for one character in the data space and store
char in the space. |
void |
charFetch(XT xt)
Fetch the character (char) stored at top (c-addr).
|
void |
charPlus(XT xt)
Add the size in address units of a character to
c-addr1 ,
giving c-addr2 . |
void |
chars(XT xt)
n2 is the size in address units of n1
characters. |
void |
charStore(XT xt)
Store the character next at top (c-addr).
|
void |
colon(XT xt)
Skip leading space delimiters.
|
void |
colonNoname(XT xt)
Stack[C]{ -- colon-sys}
Stack[S]{ -- xt}
Create an execution token
xt , enter compilation state
and start the current definition, producing colon-sys . |
void |
comma(XT xt)
Reserve one cell of data space and store
x in the cell. |
void |
comment(XT xt)
Compile:
Perform the execution semantics given below.
|
void |
constant(XT xt)
Skip leading space delimiters.
|
void |
count(XT xt)
Return the character string specification for the counted
string stored at
c-addr1 . |
void |
countedString(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
create(XT xt)
Skip leading space delimiters.
|
void |
decimal(XT xt)
Set the numeric conversion radix to ten (decimal).
|
int |
defaultDefer(XT xt) |
void |
defer(XT xt)
Stack{"
|
int |
deferDef(XT xt) |
void |
depth(XT xt)
Return the number of single-cell values contained in the
data stack.
|
void |
display(XT xt)
Display top (n) in free field format.
|
void |
displayRight(XT xt)
Display next (n1) right aligned in a field top (n2) characters
wide.
|
void |
divide(XT xt)
Divide next (n1) by top (n2), giving a single-cell quotient (n3).
|
void |
divideMod(XT xt)
Divide next (n1) by top (n2), giving the single-cell
remainder (n3) and the single-cell quotient (n4).
|
void |
DO(XT xt)
Place a (do-sys) onto the control-flow stack and append
the initialisation of a
DO -loop control parameters with
an index (top) and limit (next) to the current definition. |
int |
doAbortQuote(XT xt) |
int |
doActionOf(XT xt) |
static int |
doAgain(XT xt) |
int |
doCountedString(XT xt) |
int |
doDo(XT xt)
The runtime action of a
DO ,
set up the loop control parameters with index (top) and limit
(next) and continue execution at the next instruction. |
int |
doDoes(XT xt) |
int |
doDotQuote(XT xt) |
static int |
doElse(XT xt)
The runtime action of an
ELSE ,
continue execution at the location specified by the XT. |
int |
doEndCase(XT xt) |
static int |
doEndOf(XT xt) |
void |
does(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
int |
doExit(XT xt)
The runtime action for
EXIT ,
drop the return address off of the return stack. |
int |
doI(XT xt)
The runtime action for
I ,
return a copy of the current (inner most) loop index. |
int |
doIF(XT xt)
The runtime action of an
IF ,
if all bits of top (x) are zero, continue execution at the
location specified by the XT, otherwise continue with the next
instruction. |
int |
doIs(XT xt) |
int |
doJ(XT xt)
The runtime action for
J ,
return a copy of the next-outer loop index. |
int |
doLeave(XT xt)
The runtime action for
LEAVE ,
discard the current loop control parameters and continue
execution immediately following the innermost DO - or
?DO -loop. |
int |
doLiteral(XT xt) |
int |
doLoop(XT xt)
The runtime action for
LOOP ,
increment the loop index, if the index is equal to the limit
discard the loop parameters and continue execution immediately
following the loop, otherwise continue execution at the start
of the loop. |
int |
doOf(XT xt) |
int |
doPlusLoop(XT xt)
The runtime action for
+LOOP ,
add top (n) to the loop index, if the index did not cross the
boundary between the loop limit minus one and the loop limit,
continue execution at the beginning of the or, otherwise discard
the current loop control parameters and continue execution
immediately following the loop. |
int |
doPostpone(XT xt) |
int |
doQueryDo(XT xt)
The runtime action of a
?DO ,
if the index (top) is equal to the limit (next) continue
execution at the first instruction after the loop, otherwise
set up the loop control parameters and continue execution at
the next instruction. |
static int |
doRepeat(XT xt) |
int |
doString(XT xt) |
int |
doTick(XT xt) |
int |
doTo(XT xt) |
void |
dotQuote(XT xt)
Display a string immediately.
|
int |
doUnloop(XT xt)
The runtime action for
UNLOOP ,
discard the loop-control parameters for the current nesting
level. |
int |
doUntil(XT xt) |
int |
doWhile(XT xt) |
void |
drop(XT xt)
Remove the top value from the stack.
|
void |
dup(XT xt)
Duplicate top.
|
void |
ELSE(XT xt)
Put the location of a new unresolved forward reference (orig2)
onto the control flow stack, appending a jump to the location
specified by the resolution of the forward reference (orig2) to
the current definition, resolving the forward reference (orig1)
to the next instruction.
|
void |
emit(XT xt) |
void |
endCase(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
endOf(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
environmentQuery(XT xt)
c-addr is the address of a character string and u
is the string's character count. |
void |
equal(XT xt)
Return a flag indicating that next (x1) is bit-for-bit the
same as top (x2).
|
void |
erase(XT xt)
If
u is greater than zero, clear all bits in each of
u consecutive address units of memory beginning at
addr . |
void |
escapedString(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
evaluate(XT xt)
Interpret the string (c-addr u).
|
void |
execute(XT xt)
Remove
xt from the stack and perform the semantics
identified by it. |
void |
exit(XT xt)
Append the action to return control to the calling definition
specified by nest-sys.
|
void |
fetch(XT xt)
Return the value (x) is the value stored at top (a-addr).
|
void |
fill(XT xt)
If
u is greater than zero, store char in each
of u consecutive characters of memory beginning at
c-addr . |
void |
find(XT xt)
Find the definition named in the counted string at
c-addr . |
void |
FLOORED(XT xt)
True if floored division is the default.
|
void |
flooredMixedDivideMod(XT xt)
Divide the double-cell next (d1) by top (n1), giving the
floored quotient (n3) and the remainder (n2).
|
void |
format(XT xt)
Divide the double-cell top (ud1) by the current radix,
returning the quotient (ud2) and converting the remainder
into a character, adding it to the start of the pictured
numeric output string.
|
void |
formatEnd(XT xt)
Drop the double-cell value (xd) and make the pictured numeric
output string available as a character string (c-addr u).
|
void |
formatS(XT xt)
Convert all digits for the double-cell top (ud1) according to
the rule for
# until the quotient is zero, returning
the zero quotient (ud2). |
void |
formatStart(XT xt)
Initialise the pictured numeric output conversion process.
|
void |
here(XT xt)
addr is the data-space pointer. |
void |
hex(XT xt)
Set contents of
BASE to sixteen. |
void |
hold(XT xt)
Add the character (top) to the start of the pictured numeric
output string.
|
void |
holdLength(XT xt)
Size of the pictured numeric output string buffer, in characters.
|
void |
holds(XT xt)
Adds the string (c-addr u) to the start of the pictured
numeric output string.
|
void |
IF(XT xt)
Put the location of a new unresolved forward reference
(orig) onto the control flow stack, appending a branch if top
is zero to the current definition.
|
void |
immediate(XT xt)
Make the most recent definition an immediate word.
|
void |
invert(XT xt)
Invert all bits of top (x1), giving its logical inverse.
|
void |
is(XT xt) |
void |
key(XT xt)
Receive one character (char), a member of the
implementation-defined character set from the keyboard.
|
void |
leave(XT xt)
Place a forward reference for the
LEAVE XT on the
control-flow stack (underneath the do-sys) to be resolved by
a LOOP or +LOOP and append the action to abort
the current (innermost) DO - or ?DO -loop to the
current definition. |
void |
leftBracket(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
less(XT xt)
Return a flag indicating that next (n2) is less than top (n2).
|
void |
lineComment(XT xt)
Compile:
Perform the execution semantics given below.
|
void |
literal(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
loop(XT xt)
Resolve the destination of all unresolved occurrences of
LEAVE to continue execution at the following word,
append the action to increment the loop index and continue
execution at the start of the loop if the index is less than
the limit, or continue with the following instruction if they
are equal. |
void |
loopIndex(XT xt)
Append the action of returning a copy of the inner loop index
to the current definition.
|
void |
lShift(XT xt)
Return the logical left shift of top (u) bit-places on next
(x1).
|
void |
marker(XT xt)
Skip leading space delimiters.
|
int |
markerDef(XT xt) |
void |
max(XT xt)
Return the grater of next (n1) and top (n2).
|
void |
maxChar(XT xt)
Parse the first character of the next word, placing it on the
stack.
|
void |
maxDouble(XT xt)
Largest usable signed double number.
|
void |
maxInteger(XT xt)
Largest usable signed integer.
|
void |
maxUnsigned(XT xt)
Largest usable unsigned integer.
|
void |
maxUnsignedDouble(XT xt)
Largest usable unsigned double number.
|
void |
min(XT xt)
Return the lesser of next (n1) and top (n2).
|
void |
mixedMultiply(XT xt)
Multiply next (n) by top (n), returning the product (d).
|
void |
mod(XT xt)
Divide next (n1) by top (n2), giving the single-cell
remainder (n3).
|
void |
more(XT xt)
Return a flag indicating that next (n2) is greater than top (n2).
|
void |
move(XT xt)
If
u is greater than zero, copy the contents of
u consecutive address units at addr1 to the
u consecutive address units at addr2 . |
void |
multiply(XT xt)
Multiply next (n|u) by top (n|u), returning the product.
|
void |
negate(XT xt)
Negate top (n}, giving its arithmetic inverse (n).
|
void |
nip(XT xt)
Drop the first item below the top of stack.
|
void |
notEqual(XT xt)
Return a flag indicating that next (x1) is not bit-for-bit the
same as top (x2).
|
void |
of(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
onePlus(XT xt)
Add one to top (n|u).
|
void |
oneSubtract(XT xt)
Subtract one (1) from top (n|u}.
|
void |
or(XT xt)
Return the the bit-by-bit inclusive-or of next (x1) with
top (x2).
|
void |
outerLoopIndex(XT xt)
Append the action of returning a copy of the next-outer loop
index to the current definition.
|
void |
over(XT xt)
Place a copy of next on the top of the stack.
|
void |
pad(XT xt)
c-addr is the address of a transient region that can
be used to hold data for intermediate processing. |
void |
padLength(XT xt)
Size of the scratch area pointed to by PAD, in characters.
|
void |
parse(XT xt)
Parse
ccc delimited by the delimiter char . |
void |
parseName(XT xt)
Skip leading space delimiters.
|
void |
pick(XT xt)
Remove top (u), copy the uth element on the stack
to the top of the stack.
|
void |
plus(XT xt)
Add top (n|u) to next (n|u), returning the sum.
|
void |
plusLoop(XT xt)
Resolve the destination of all unresolved occurrences of
LEAVE to continue execution at the following word,
append the action to add (top) to the loop index and continue
execution at the start of the loop if the index does not
cross the limit boundary, or continue with the following
instruction. |
void |
plusStore(XT xt)
Add
n|u to the single-cell number at a-addr . |
void |
postpone(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
queryDo(XT xt)
Place a (do-sys) onto the control-flow stack and append
the initialisation of a
?DO -loop control parameters
with an index (top) and limit (next) to the current definition. |
void |
queryDup(XT xt)
Duplicate top if it is non-zero.
|
void |
quit(XT xt)
Empty the return stack, store zero in
SOURCE-ID if it
is present, make the user input device the input source, and
enter interpretation state. |
void |
recurse(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
refill(XT xt)
Attempt to fill the input buffer from the input source,
returning a true flag if successful.
|
void |
repeat(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
restoreInput(XT xt)
Attempt to restore the input source specification to the state
described by the stack, returning a flag indicating if the
input was not restored.
|
void |
returnFetch(XT xt)
Return a copy of the value on the top of the return stack.
|
void |
returnFrom(XT xt)
Move the top of the return stack to the data stack.
|
void |
returnSize(XT xt)
Maximum size of the return stack, in cells.
|
void |
rightBracket(XT xt)
Enter compilation state.
|
void |
roll(XT xt)
Remove top (u), rotate the items on the stack bringing the
uth item to the top.
|
void |
rot(XT xt)
Rotate the top three stack entries.
|
void |
rShift(XT xt)
Return the logical right shift of top (u) bit-places on next
(x1).
|
void |
saveInput(XT xt)
Save the current state of the input source, for later use by
RESTORE-INPUT , returning a variable number of items
with the number of item on the top of the stack. |
void |
semicolon(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
sign(XT xt)
If top (n) is negative, add a minus sign to the start of the
pictured numeric output string.
|
void |
singleToDouble(XT xt)
Convert top (n) into a double-cell number with the same
numerical value (d).
|
void |
source(XT xt)
Return a string (c-addr u) of the current input buffer.
|
void |
sourceID(XT xt)
Return an indication of the current input source, 0 for a user
input device or -1 for a string.
|
void |
stackSize(XT xt)
Maximum size of the data stack, in cells.
|
void |
state(XT xt)
a-addr is the address of a cell containing the
compilation-state flag. |
void |
store(XT xt)
Store next (x) at top (a-addr).
|
void |
string(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
stringLength(XT xt)
Maximum size of a counted string, in characters.
|
void |
subtract(XT xt)
Subtract top (n|u) from next (n|u), returning the difference.
|
void |
swap(XT xt)
Exchange the top two stack items.
|
void |
symmetricMixedDivideRemainder(XT xt)
Divide the double-cell next (d1) by top (n1), giving the
symmetric quotient (n3) and the remainder (n2).
|
void |
THEN(XT xt)
Resolve the forward reference (orig) using the location of the
next instruction.
|
void |
tick(XT xt)
Read a name from the input stream and find the name in the
dictionary, returning the corresponding XT.
|
void |
timesDivide(XT xt)
Multiply third (n1) by next (n2) producing the intermediate
double-cell product which is divided by top (n3), returning
the quotient (n4).
|
void |
timesDivideMod(XT xt)
Multiply third (n1) by next (n2) producing a double-cell
intermediate product which is then divided by top (n3), giving
the single-cell remainder (n4) and the single-cell quotient
(n5).
|
void |
to(XT xt)
Interpret:
Stack{i*x "
name delimited by a
space. |
void |
toBody(XT xt)
a-addr is the data-field address corresponding to
xt . |
void |
toIn(XT xt)
Return the address of a special variable containing the offset,
in characters, from the start of the input buffer to the start
of the parse area.
|
void |
toNumber(XT xt)
ud2 is the unsigned result of converting the characters
within the string specified by c-addr1 u1 into digits,
using the number in BASE , and adding each into
ud1 after multiplying ud1 by the number in
BASE . |
void |
toR(XT xt)
Move top (x) to the return stack.
|
void |
tuck(XT xt)
Copy top below next.
|
void |
twoDivide(XT xt)
Return the result of shifting top one bit toward the
least-significant bit, leaving the most-significant bit
unchanged.
|
void |
twoDrop(XT xt)
Drop cell pair
x1 x2 from the stack. |
void |
twoDup(XT xt)
Duplicate cell pair
x1 x2 . |
void |
twoFetch(XT xt)
Fetch the cell pair
x1 x2 stored at a-addr . |
void |
twoOver(XT xt)
Copy cell pair
x1 x2 to the top of the stack. |
void |
twoReturnFetch(XT xt)
Copy a cell pair
x1 x2 from the return stack. |
void |
twoRreturnFrom(XT xt)
Transfer cell pair
x1 x2 from the return stack. |
void |
twoStore(XT xt)
Store the cell pair
x1 x2 at a-addr , with
x2 at a-addr and x1 at the next
consecutive cell. |
void |
twoSwap(XT xt)
Exchange the top two cell pairs.
|
void |
twoTimes(XT xt)
Return the result of shifting top (x1) one bit toward the
most-significant bit, filling the vacated least-significant
bit with zero.
|
void |
twoToReturn(XT xt)
Transfer cell pair
x1 x2 to the return stack. |
void |
type(XT xt)
If top (u) is greater than zero, display the character string
specified by next (c-addr) and top (u).
|
void |
unloop(XT xt)
Append the action for discarding the loop-control parameters
of the innermost do-loop to the current definition.
|
void |
unsigedMore(XT xt)
Return a flag indicating that next (u1) is greater than top
(u2).
|
void |
unsigendDisplay(XT xt)
Display top (u) in free field format.
|
void |
unsignedDisplayRight(XT xt)
Display next (u) right aligned in a field of top (n) characters
wide.
|
void |
unsignedLess(XT xt)
Return a flag indicating that next (u1) is less than top (u2).
|
void |
unsignedMixedDivideMod(XT xt)
Divide the double-cell next (ud) by top (u1), giving the
quotient (u3) and the remainder (u2).
|
void |
unsignedMixedMultiply(XT xt)
Multiply next (u1) by top (u2), giving an unsigned double-cell
product (ud).
|
void |
UNTIL(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
unused(XT xt)
u is the amount of space remaining in the region
addressed by HERE , in address units. |
void |
value(XT xt)
Skip leading space delimiters.
|
int |
valueDef(XT xt) |
int |
valueTo(XT xt) |
void |
variable(XT xt)
Skip leading space delimiters.
|
void |
WHILE(XT xt)
Interpret:
Interpretation semantics for this word are undefined.
|
void |
within(XT xt)
Perform a comparison of a test value
n1|u1 with a
lower limit n2|u2 and an upper limit n3|u3 ,
returning true if either
(n2|u2 < n3|u3 and
(n2|u2 <= n1|u1 and
n1|u1 < n3|u3 ))
or
(n2|u2 > n3|u3 and
(n2|u2 <= n1|u1 or
n1|u1 < n3|u3 ))
is true, returning false otherwise. |
void |
word(XT xt)
Skip leading delimiters.
|
void |
xor(XT xt)
Return the bit-by-bit exclusive-or of next (x1) with top (x2).
|
void |
zeroEquals(XT xt)
Return a flag indicating if top (x) is zero.
|
void |
zeroLess(XT xt)
Return a flag indicating that top (n) is less than zero.
|
void |
zeroMore(XT xt)
return a flag indicating that top (n) is greater than zero.
|
void |
zeroNotEqual(XT xt)
Return a flag indicating if top (x) is not zero.
|
setVirtualMachine
@Stack(value=" -- n") @Environment(value="ADDRESS-UNIT-BITS") public void addressUnitBits(XT xt)
@Primitive(value="!") @Stack(value="x a-addr -- ") public void store(XT xt)
xt
- the XT of the definition.@Primitive(value="@") @Stack(value="a-addr -- x") public void fetch(XT xt)
xt
- the XT of the definition.@Primitive(value="C@") @Stack(value="c-addr -- char") public void charFetch(XT xt)
xt
- the XT of the definition.@Primitive(value="C!") @Stack(value="char c-addr -- ") public void charStore(XT xt)
xt
- the XT of the definition.@Stack(value=" -- n") @Environment(value="STACK-CELLS") public void stackSize(XT xt)
@Stack(value="x -- ") public void drop(XT xt)
xt
- the XT of the definition.@Stack(value="x -- x x") public void dup(XT xt)
xt
- the XT of the definition.@Primitive(value="?DUP") @Stack(value="x -- 0 | x x") public void queryDup(XT xt)
xt
- the XT of the definition.@Stack(value="x1 x2 -- x2 x1") public void swap(XT xt)
xt
- the XT of the definition.@Stack(value="x1 x2 -- x1 x2 x1") public void over(XT xt)
xt
- the XT of the definition.@Stack(value="x1 x2 x3 -- x2 x3 x1") public void rot(XT xt)
xt
- the XT of the definition.@Stack(value="x1 x2 -- x2") public void nip(XT xt)
xt
- the XT of the definition.@Stack(value="x1 x2 -- x2 x1 x2") public void tuck(XT xt)
xt
- the XT of the definition.@Stack(value=" -- +n") public void depth(XT xt)
xt
- the XT of the definition.@Stack(value="xu ... x1 x0 u -- xu ... x1 x0 xu") public void pick(XT xt)
u
+2 items on the stack before PICK
is executed.xt
- the XT of the definition.@Stack(value="xu xu-1 ... x0 u -- xu-1 ... x0 xu") public void roll(XT xt)
u
+2 items on the stack before ROLL
is executed.xt
- the XT of the definition.@Primitive(value="+") @Stack(value="n1|u1 n2|u2 -- n3|u3") public void plus(XT xt)
xt
- the XT of the definition.@Primitive(value="1+") @Stack(value="n1|u1 -- n2|u2") public void onePlus(XT xt)
xt
- the XT of the definition.@Primitive(value="-") @Stack(value="n1|u1 n2|u2 -- n3|u3") public void subtract(XT xt)
xt
- the XT of the definition.@Primitive(value="1-") @Stack(value="n1|u1 -- n2|u2") public void oneSubtract(XT xt)
xt
- the XT of the definition.@Stack(value="n1 -- n2") public void negate(XT xt)
xt
- the XT of the definition.@Stack(value="n -- u") public void abs(XT xt)
xt
- the XT of the definition.@Primitive(value="*") @Stack(value="n1|u1 n2|u2 -- n3|u3") public void multiply(XT xt)
xt
- the XT of the definition.@Stack(value=" -- flag") @Environment public void FLOORED(XT xt)
@Primitive(value="/") @Stack(value="n1 n2 -- n3") public void divide(XT xt)
>R S>D R> FM/MOD SWAP DROP
or the phrase >R S>D
R> SM/REM SWAP DROP}.xt
- the XT of the definition.@Primitive(value="*/") @Stack(value="n1 n2 n3 -- n4") public void timesDivide(XT xt)
>R M* R> FM/MOD SWAP DROP
or the phrase >R M* R> SM/REM SWAP DROP
.xt
- the XT of the definition.@Stack(value="n1 n2 -- n3") public void mod(XT xt)
>R S>D R> FM/MOD DROP
or the phrase >R S>D R> SM/REM DROP
.xt
- the XT of the definition.@Primitive(value="/MOD") @Stack(value="n1 n2 -- n3 n4") public void divideMod(XT xt)
>R S>D R> FM/MOD
or the phrase >R S>D R> SM/REM
.xt
- the XT of the definition.@Primitive(value="*/MOD") @Stack(value="n1 n2 n3 -- n4 n5") public void timesDivideMod(XT xt)
>R M* R> FM/MOD
or
the phrase >R M* R> SM/REM
.xt
- the XT of the definition.@Primitive(value="SM/REM") @Stack(value="d1 n1 -- n2 n3") public void symmetricMixedDivideRemainder(XT xt)
xt
- the XT of the definition.@Primitive(value="FM/MOD") @Stack(value="d1 n1 -- n2 n3") public void flooredMixedDivideMod(XT xt)
xt
- the XT of the definition.@Stack(value=" -- d") @Environment(value="MAX-D") public void maxDouble(XT xt)
@Stack(value=" -- n") @Environment(value="MAX-N") public void maxInteger(XT xt)
@Stack(value=" -- u") @Environment(value="MAX-U") public void maxUnsigned(XT xt)
@Stack(value=" -- ud") @Environment(value="MAX-UD") public void maxUnsignedDouble(XT xt)
@Primitive(value="S>D") @Stack(value="n -- d") public void singleToDouble(XT xt)
xt
- the XT of the definition.@Primitive(value="M*") @Stack(value="n1 n2 -- d") public void mixedMultiply(XT xt)
xt
- the XT of the definition.@Primitive(value="UM*") @Stack(value="u1 u2 -- ud") public void unsignedMixedMultiply(XT xt)
xt
- the XT of the definition.@Primitive(value="UM/MOD") @Stack(value="ud u1 -- u2 u3") public void unsignedMixedDivideMod(XT xt)
xt
- the XT of the definition.@Stack(value="x1 x2 -- x3") public void and(XT xt)
@Stack(value="x1 -- x2") public void invert(XT xt)
xt
- the XT of the definition.@Stack(value="x1 x2 -- x3") public void or(XT xt)
xt
- the XT of the definition.@Stack(value="x1 x2 -- x3") public void xor(XT xt)
xt
- the XT of the definition.@Primitive(value="2*") @Stack(value="x1 -- x2") public void twoTimes(XT xt)
2*
has been implemented on two's-complement
machines as a logical left-shift instruction. Multiplication
by two is an efficient side-effect on these machines. However,
shifting implies a knowledge of the significance and position
of bits in a cell. While the name implies multiplication, most
implementors have used a hardware left shift to implement
2*
.xt
- the XT of the definition.@Primitive(value="2/") @Stack(value="x1 -- x2") public void twoDivide(XT xt)
2*
. It is often implemented on two's-complement
machines with a hardware right shift that propagates the sign
bit.xt
- the XT of the definition.@Stack(value="x1 u -- x2") public void lShift(XT xt)
xt
- the XT of the definition.@Stack(value="x1 u -- x2") public void rShift(XT xt)
xt
- the XT of the definition.@Primitive(value="CELL+") @Stack(value="a-addr1 -- a-addr2") public void cellPlus(XT xt)
a-addr1
,
giving a-addr2
.
As with ALIGN
and ALIGNED
, the words
CELLS
and CELL+
were added to aid in
transportability across systems with different cell sizes.
They are intended to be used in manipulating indexes and
addresses in integral numbers of cell-widths. Example:
2VARIABLE DATA 0 100 DATA 2! DATA @ . 100 DATA CELL+ @ . 0
xt
- the XT of the definition.@Stack(value="n1 -- n2") public void cells(XT xt)
n2
is the size in address units of n1
cells.
Example:
CREATE NUMBERS 100 CELLS ALLOT
Allots space in the array NUMBERS for 100 cells of data.
xt
- the XT of the definition.@Stack(value=" -- u") @Environment(value="MAX-CHAR") public void maxChar(XT xt)
name
delimited
by a space. Append the run-time semantics given below to the
current definition.
Place char
, the value of the first character of
name
, on the stack.
Typical use:
: X ... [CHAR] <em>c</em> ... ;
@Primitive(value="CHAR") @Stack(value="\'name\' -- char") public void character(XT xt) throws java.io.IOException
name
delimited
by a space. Put the value of its first character onto the stack.
Typical use: ... CHAR A CONSTANT "A" ...
xt
- the XT of the definition.java.io.IOException
@Primitive(value="CHAR+") @Stack(value="c-addr1 -- c-addr2") public void charPlus(XT xt)
c-addr1
,
giving c-addr2
.xt
- the XT of the definition.@Primitive(value="CHARS") @Stack(value="n1 -- n2") public void chars(XT xt)
n2
is the size in address units of n1
characters.xt
- the XT of the definition.@Primitive(value="0=") @Stack(value="x -- flag") public void zeroEquals(XT xt)
xt
- the XT of the definition.@Primitive(value="0<>") @Stack(value="x -- flag") public void zeroNotEqual(XT xt)
xt
- the XT of the definition.@Primitive(value="0<") @Stack(value="n -- flag") public void zeroLess(XT xt)
xt
- the XT of the definition.@Primitive(value="0>") @Stack(value="n -- flag") public void zeroMore(XT xt)
xt
- the XT of the definition.@Primitive(value="=") @Stack(value="x1 x2 -- flag") public void equal(XT xt)
xt
- the XT of the definition.@Primitive(value="<>") @Stack(value="x1 x2 -- flag") public void notEqual(XT xt)
xt
- the XT of the definition.@Primitive(value="<") @Stack(value="n1 n2 -- flag") public void less(XT xt)
xt
- the XT of the definition.@Primitive(value=">") @Stack(value="n1 n2 -- flag") public void more(XT xt)
xt
- the XT of the definition.@Primitive(value="U<") @Stack(value="u1 u2 -- flag") public void unsignedLess(XT xt)
xt
- the XT of the definition.@Primitive(value="U>") @Stack(value="u1 u2 -- flag") public void unsigedMore(XT xt)
xt
- the XT of the definition.@Stack(value="n1 n2 -- n3") public void min(XT xt)
xt
- the XT of the definition.@Stack(value="n1 n2 -- n3") public void max(XT xt)
xt
- the XT of the definition.@Immediate @Stack(value="C: -- orig") public void IF(XT xt) throws java.lang.NoSuchMethodException
THEN
or ELSE
.
Typical use:
: X ... <em>test</em> IF ... THEN ... ;
or
: X ... <em>test</em> IF ... ELSE ... THEN ... ;
xt
- the XT of the definition.java.lang.NoSuchMethodException
- if the runtime action (doIF
) could not be found.@Stack(value="x -- ") public int doIF(XT xt)
IF
,
if all bits of top (x) are zero, continue execution at the
location specified by the XT, otherwise continue with the next
instruction.xt
- the XT of the definition@Immediate @Stack(value="C: orig1 -- orig2") public void ELSE(XT xt) throws java.lang.NoSuchMethodException
THEN
).
Resolve the forward reference (orig1) using the location
following the appended run-time semantics.xt
- the XT of the definition.java.lang.NoSuchMethodException
- if the runtime action (doElse
) could not be
found.IF(org.rigwit.forth.XT)
@Stack(value=" -- ") public static int doElse(XT xt)
ELSE
,
continue execution at the location specified by the XT.xt
- the XT of the definition@Immediate @Stack(value="C: orig -- ") public void THEN(XT xt)
xt
- the XT of the definition.IF(org.rigwit.forth.XT)
@Immediate @Stack(value="C: -- do-sys") public void DO(XT xt) throws java.lang.NoSuchMethodException
DO
-loop control parameters with
an index (top) and limit (next) to the current definition.
The semantics are incomplete until the (do-sys) is resolved by
LOOP
or +LOOP
.
Typical use:
: X ... limit first DO ... LOOP ;or
: X ... limit first DO ... step +LOOP ;
xt
- the XT of the definition.java.lang.NoSuchMethodException
- if the runtime action (doDo
) could not be
found.@Stack(value="n1.limit n2.first | n1.limit n2.first -- ; R: -- n1.limit n2.first loop-sys | u1.limit u2.limit loop-sys ") public int doDo(XT xt)
DO
,
set up the loop control parameters with index (top) and limit
(next) and continue execution at the next instruction.
An ambiguous condition exists if the limit (next) and the
index (top) are not both the same type.
Anything already on the return stack becomes unavailable until
the loop-control parameters are discarded.xt
- the XT of the definition@Primitive(value="?DO") @Immediate @Stack(value="C: -- do-sys") public void queryDo(XT xt) throws java.lang.NoSuchMethodException
?DO
-loop control parameters
with an index (top) and limit (next) to the current definition.
The semantics are incomplete until the (do-sys) is resolved by
LOOP
or +LOOP
.
It will also place a forward reference for the ?DO
XT
on the control-flow stack to be resolved by LOOP
or
+LOOP
.
Typical use:
: FACTORIAL ( +n1 -- +n2 ) 1 SWAP 1+ ?DO I * LOOP ;
xt
- the XT of the definition.java.lang.NoSuchMethodException
- if the runtime action (doQueryDo
) could not be
found.@Stack(value="n1.limit n2.first | n1.limit n2.first -- ; R: -- n1.limit n2.first loop-sys | u1.limit u2.limit loop-sys | ") public int doQueryDo(XT xt)
?DO
,
if the index (top) is equal to the limit (next) continue
execution at the first instruction after the loop, otherwise
set up the loop control parameters and continue execution at
the next instruction.
An ambiguous condition exists if the limit (next) and the
index (top) are not both the same type.
Anything already on the return stack becomes unavailable until
the loop-control parameters are discarded.xt
- the XT of the definition@Primitive(value="I") @Immediate @Stack(value=" -- ") public void loopIndex(XT xt) throws java.lang.NoSuchMethodException
xt
- the XT of the definition.java.lang.NoSuchMethodException
- if the runtime action (doI
) could not be
found.@Stack(value=" -- n|u; R: n.limit n.index | u.limit u.index -- n.limit n.index | u.limit u.index") public int doI(XT xt)
I
,
return a copy of the current (inner most) loop index.
An ambiguous condition exists if the loop control parameters
are unavailable.xt
- the XT of the definition@Primitive(value="J") @Immediate @Stack(value=" -- ") public void outerLoopIndex(XT xt) throws java.lang.NoSuchMethodException
J
may only be used with a nested DO
- or
?DO
-loop, for example, in the form:
: X ... DO ... DO ... J ... LOOP ... +LOOP ... ;
xt
- the XT of the definition.java.lang.NoSuchMethodException
- if the runtime action (doJ
) could not be
found.@Stack(value=" -- n|u; R: n1 n2 loop-sys x1 x2 loop-sys | u1 u2 loop-sys x1 x2 loop-sys -- n1 n2 loop-sys x1 x2 loop-sys | u1 u2 loop-sys x1 x2 loop-sys") public int doJ(XT xt)
J
,
return a copy of the next-outer loop index.
An ambiguous condition exists if the loop control parameters
of the next-outer loop are unavailable.xt
- the XT of the definition@Immediate @Stack(value=" -- ") public void leave(XT xt) throws java.lang.NoSuchMethodException
LEAVE
XT on the
control-flow stack (underneath the do-sys) to be resolved by
a LOOP
or +LOOP
and append the action to abort
the current (innermost) DO
- or ?DO
-loop to the
current definition.
Note that LEAVE
exists the loop immediately, so no
words following the LEAVE
within the loop will be
executed.
Typical use:
: X ... DO ... IF ... LEAVE THEN LOOP ;
xt
- the XT of the definition.java.lang.NoSuchMethodException
- if the runtime action (doLeave
) could not be
found.@Stack(value=" -- ; R: n1 n2 loop-sys | u1 u2 loop-sys -- ") public int doLeave(XT xt)
LEAVE
,
discard the current loop control parameters and continue
execution immediately following the innermost DO
- or
?DO
-loop.
An ambiguous condition exists if the control parameters are
unavailable.xt
- the XT of the definition@Immediate @Stack(value="C: x*n do-sys -- ") public void loop(XT xt) throws java.lang.NoSuchMethodException
LEAVE
to continue execution at the following word,
append the action to increment the loop index and continue
execution at the start of the loop if the index is less than
the limit, or continue with the following instruction if they
are equal.
An ambiguous condition exists if the loop control parameters
are unavailable.
Typical use:
: X ... limit first DO ... LOOP ;or
: X ... limit first ?DO ... LOOP ;
xt
- the XT of the definition.java.lang.NoSuchMethodException
- if the runtime action (doLoop
) could not be
found.@Stack(value=" -- ; R: n1 n2 loop-sys | u1 u2 loop-sys -- n1 n2 loop-sys | u1 u2 loop-sys | ") public int doLoop(XT xt)
LOOP
,
increment the loop index, if the index is equal to the limit
discard the loop parameters and continue execution immediately
following the loop, otherwise continue execution at the start
of the loop.
An ambiguous condition exists if the control parameters are
unavailable.xt
- the XT of the definition@Primitive(value="+loop") @Immediate @Stack(value="C: x*n do-sys -- ") public void plusLoop(XT xt) throws java.lang.NoSuchMethodException
LEAVE
to continue execution at the following word,
append the action to add (top) to the loop index and continue
execution at the start of the loop if the index does not
cross the limit boundary, or continue with the following
instruction.
An ambiguous condition exists if the loop control parameters
are unavailable.
Typical use:
: X ... limit first DO ... step +LOOP ;
xt
- the XT of the definition.java.lang.NoSuchMethodException
- if the runtime action (doPlusLoop
) could not
be found.@Stack(value=" n -- ; R: n1 n2 loop-sys | u1 u2 loop-sys -- n1 n2 loop-sys | u1 u2 loop-sys | ") public int doPlusLoop(XT xt)
+LOOP
,
add top (n) to the loop index, if the index did not cross the
boundary between the loop limit minus one and the loop limit,
continue execution at the beginning of the or, otherwise discard
the current loop control parameters and continue execution
immediately following the loop.
An ambiguous condition exists if the control parameters are
unavailable.xt
- the XT of the definition@Immediate @Stack(value=" do-sys1 -- do-sys2 ") public void unloop(XT xt) throws java.lang.NoSuchMethodException
UNLOOP
is required for each nesting level before
the definition may be EXIT
ed.
An ambiguous condition exists if the loop-control parameters
are unavailable.
Typical use:
: X ... limit first DO ... test IF ... UNLOOP EXIT THEN ... LOOP ... ;
UNLOOP
allows the use of EXIT
within the
context of a do-loop constructs.xt
- the XT of the definition.java.lang.NoSuchMethodException
- if the runtime action (doUnloop
) could not
be found.@Stack(value=" -- ; R: n1 n2 loop-sys | u1 u2 loop-sys -- ") public int doUnloop(XT xt)
UNLOOP
,
discard the loop-control parameters for the current nesting
level.xt
- the XT of the definition@Immediate @Stack(value=" -- ") public void exit(XT xt) throws java.lang.NoSuchMethodException
EXIT
within a do-loop, a program shall
discard the loop-control parameters by executing UNLOOP
.
Typical use:
: X ... test IF ... EXIT THEN ... ;
xt
- the XT of the definition.java.lang.NoSuchMethodException
- if the runtime action (doExit
) could not
be found.@Stack(value=" -- ; R: XT x*n -- ") public int doExit(XT xt)
EXIT
,
drop the return address off of the return stack.xt
- the XT of the definition@Immediate @Stack(value=" -- dest ") public void begin(XT xt) throws ForthException
dest
,
onto the control flow stack. Append the run-time semantics
given below to the current definition.
Runtime:
Stack{ -- }
Continue execution.
Typical use:: X ... BEGIN
... test UNTIL ;}: X ... BEGIN ... <em>test</em> WHILE ... REPEAT ;
xt
- the XT of the definition.ForthException
@Immediate @Stack(value=" dest -- ; -- ") public void again(XT xt) throws java.lang.NoSuchMethodException
dest
.
Runtime:
Stack{ -- }
Continue execution at the location specified by dest
.
If no other control flow words are used, any program code
after AGAIN
will not be executed.
Typical use: : X ... BEGIN ... AGAIN ... ;
Unless word-sequence has a way to terminate, this is an
endless loop.xt
- the XT of the definition.java.lang.NoSuchMethodException
public static int doAgain(XT xt)
@Immediate @Stack(value="dest -- ; x -- ") public void UNTIL(XT xt) throws ForthException, java.lang.NoSuchMethodException
dest
.
Runtime:
Stack{x -- }
If all bits of x
are zero, continue execution at the
location specified by dest
.
Typical use:
: X ... BEGIN ... <em>test</em> UNTIL ... ;
xt
- the XT of the definition.ForthException
java.lang.NoSuchMethodException
public int doUntil(XT xt)
@Immediate @Stack(value=" dest -- orig dest ") public void WHILE(XT xt) throws ForthException, java.lang.NoSuchMethodException
orig
onto the control flow stack, under the existing
dest
. Append the run-time semantics given below to
the current definition. The semantics are incomplete until
orig
and dest
are resolved (e.g., by
REPEAT
).
Runtime:
Stack{x -- }
If all bits of x
are zero, continue execution at the
location specified by the resolution of orig
.
Typical use:
: X ... BEGIN ... <em>test</em> WHILE ... REPEAT ... ;
xt
- the XT of the definition.ForthException
java.lang.NoSuchMethodException
public int doWhile(XT xt)
@Immediate @Stack(value=" addr.orig xt.dest -- ") public void repeat(XT xt) throws ForthException, java.lang.NoSuchMethodException
dest
.
Resolve the forward reference orig
using the location
following the appended run-time semantics.
Runtime:
Stack{ -- }
Continue execution at the location given by dest
.
Typical use:
: FACTORIAL ( +n1 -- +n2 ) DUP 2 < IF DROP 1 EXIT THEN DUP BEGIN DUP 2 > WHILE 1- SWAP OVER * SWAP REPEAT DROP ;
xt
- the XT of the definition.ForthException
java.lang.NoSuchMethodException
public static int doRepeat(XT xt)
@Stack(value=" -- n") @Environment(value="RETURN-STACK-CELLS") public void returnSize(XT xt)
@Primitive(value=">R") @Stack(value=" x -- ; R: -- x ") public void toR(XT xt)
xt
- the XT of the definition.@Primitive(value="R>") @Stack(value=" -- x ; R: x -- ") public void returnFrom(XT xt)
xt
- the XT of the definition.@Primitive(value="R@") @Stack(value=" -- x ; R: x -- x ") public void returnFetch(XT xt)
xt
- the XT of the definition.@Primitive(value="2>R") @Stack(value=" x1 x2 -- ; R: -- x1 x2") public void twoToReturn(XT xt)
x1 x2
to the return stack.
The primary advantage of 2>R
is that it puts the top
stack entry on the top of the return stack. For instance, a
double-cell number may be transferred to the return stack and
still have the most significant cell accessible on the top of
the return stack.xt
- the XT of the definition.@Primitive(value="2R>") @Stack(value=" -- x1 x2 ; R: x1 x2 -- ") public void twoRreturnFrom(XT xt)
x1 x2
from the return stack.
Note that 2R>
is not equivalent to R> R>
but
R> R> SWAP
to mirror the action of 2>R
.xt
- the XT of the definition.@Primitive(value="2R@") @Stack(value=" -- x1 x2 ; R: x1 x2 -- x1 x2 ") public void twoReturnFetch(XT xt)
x1 x2
from the return stack.xt
- the XT of the definition.@Stack(value=" \'name\' -- ; i*x -- j*x ") public void defer(XT xt) throws ForthException, java.io.IOException, java.lang.NoSuchMethodException
name
delimited
by a space. Create a definition for name
with the
execution semantics defined below.
Execute name:
Stack{i*x -- j*x}
Execute the xt
that name
is set to execute.
An ambiguous condition exists if name
has not been
set to execute an xt
.
: DEFER ( "name" -- ) xt
- the XT of the definition.ForthException
java.io.IOException
java.lang.NoSuchMethodException
public int defaultDefer(XT xt) throws ForthException, java.lang.NoSuchMethodException
ForthException
java.lang.NoSuchMethodException
public int deferDef(XT xt) throws ForthException, java.lang.Exception
ForthException
java.lang.Exception
@Immediate public void is(XT xt) throws java.io.IOException, java.lang.NoSuchMethodException
java.io.IOException
java.lang.NoSuchMethodException
public int doIs(XT xt)
@Primitive(value="ACTION-OF") @Immediate @Stack(value=" \'name\' -- xt") public void actionOf(XT xt) throws java.io.IOException, java.lang.NoSuchMethodException
name
delimited by a
space. xt
is the execution token that name
is
set to execute. An ambiguous condition exists if name
was not defined by DEFER
, or if the name
has
not been set to execute an xt
.
Compile:
Stack{"name
delimited by a
space. Append the run-time semantics given below to the
current definition. An ambiguous condition exists if
name
was not defined by DEFER
.
Runtime:
Stack{ -- xt}
xt
is the execution token that name
is set to
execute. An ambiguous condition exists if name
has
not been set to execute an xt
.
An ambiguous condition exists if POSTPONE
,
[COMPILE]
, [']
or '
is applied to
ACTION-OF
.
: ACTION-OF
STATE @ IF
POSTPONE ['] POSTPONE DEFER@
ELSE
' DEFER@
THEN
; IMMEDIATExt
- the XT of the definition.java.io.IOException
java.lang.NoSuchMethodException
public int doActionOf(XT xt)
@Immediate @Stack(value=" -- n case-sys ") public void CASE(XT xt) throws ForthException
CASE ... OF ... ENDOF ... ENDCASE
structure. Append the run-time semantics given below to the
current definition.
Runtime:
Stack{ -- }
Continue execution.
Typical use:
: X CASE test1 OF ... ENDOF testn OF ... ENDOF ( default ) ... ENDCASE ... ;
xt
- the XT of the definition.ForthException
@Immediate @Stack(value=" -- xt of-sys ; x1 x2 -- x1 ") public void of(XT xt) throws ForthException, java.lang.NoSuchMethodException
of-sys
onto the control flow stack. Append the
run-time semantics given below to the current definition.
The semantics are incomplete until resolved by a consumer
of of-sys
such as ENDOF
.
Runtime:
Stack{x1 x2 -- x1}
If the two values on the stack are not equal, discard the
top value and continue execution at the location specified
by the consumer of of-sys
, e.g., following the next
ENDOF
. Otherwise, discard both values and continue
execution in line.xt
- the XT of the definition.ForthException
java.lang.NoSuchMethodException
CASE(org.rigwit.forth.XT)
@Stack(value="x1 x2 -- x1 | ") public int doOf(XT xt)
@Immediate @Stack(value=" case-sys1 of-sys -- case-sys2 ") public void endOf(XT xt) throws ForthException, java.lang.NoSuchMethodException
OF ... ENDOF
part of the
CASE
structure. The next location for a transfer of
control resolves the reference given by of-sys
.
Append the run-time semantics given below to the current
definition.
Replace case-sys1
with case-sys2
on the
control-flow stack, to be resolved by ENDCASE
.
Runtime:
Stack{ -- }
Continue execution at the location specified by the consumer
of case-sys2
.xt
- the XT of the definition.ForthException
java.lang.NoSuchMethodException
CASE(org.rigwit.forth.XT)
public static int doEndOf(XT xt)
@Immediate @Stack(value="case-sys -- ; x -- ") public void endCase(XT xt) throws ForthException, java.lang.NoSuchMethodException
CASE ... OF ... ENDOF ... ENDCASE
structure. Use case-sys
to resolve the entire
structure.
Append the run-time semantics given below to the current
definition.
Runtime:
Stack{x -- }
Discard the case selector x
and continue execution.xt
- the XT of the definition.ForthException
java.lang.NoSuchMethodException
CASE(org.rigwit.forth.XT)
@Stack(value=" x -- ") public int doEndCase(XT xt)
@Stack(value=" \'name\' -- ; -- x ") public void value(XT xt) throws ForthException, java.io.IOException, java.lang.NoSuchMethodException
name
delimited by
a space. Create a definition for name
with the
execution semantics defined below, with an initial value equal
to x
.
name
is referred to as a "value".
Execute name:
Stack{ -- x}
Place x
on the stack. The value of x
is that
given when name
was created, until the phrase
x TO name
is executed, causing a new value of x
to be assigned to name
.
Runtime:[TO
name
]
Stack{x -- }
Assign the value x
to name
.
Typical use:
0 VALUE data : EXCHANGE ( n1 -- n2 ) data SWAP TO data ;
EXCHANGE
leaves n1
in data
and returns
the prior value n2
.xt
- the XT of the definition.ForthException
java.io.IOException
java.lang.NoSuchMethodException
@Stack(value=" -- x") public int valueDef(XT xt)
@Stack(value=" x -- ") public int valueTo(XT xt)
@Immediate @Stack(value=" i*x \'name\' -- ") public void to(XT xt) throws java.lang.Exception
name
delimited by a
space. Perform the "TO name
run-time" semantics given
in the definition for the defining word of name
.
An ambiguous condition exists if name
was not defined
by a word with "TO name
run-time" semantics.
Compile:
Stack{"name
delimited by a
space. Append the "TO name
run-time" semantics given
in the definition for the defining word of name
to the
current definition.
An ambiguous condition exists if name
was not defined
by a word with "TO name
run-time" semantics.
Runtime:
Stack{ -- }
Note:
An ambiguous condition exists if any of POSTPONE
,
[COMPILE]
, '
or [']
are applied to
TO
.
Historically, some implementations of TO
have not
explicitly parsed. Instead, they set a mode flag that is
tested by the subsequent execution of name
.
We} explicitly require that TO
must parse, so that
TO
's effect will be predictable.
Typical use: x TO
namejava.lang.Exception
public int doTo(XT xt) throws java.lang.Exception
java.lang.Exception
@Stack(value=" -- a-addr") public void base(XT xt)
xt
- the XT of the definition.@Stack(value=" -- n") @Environment(value="/HOLD") public void holdLength(XT xt)
@Primitive(value="<#") @Stack(value=" -- ") public void formatStart(XT xt) throws ForthException
<#
is executed with
a <# #>
delimited number conversion.xt
- the XT of the definition.ForthException
format(org.rigwit.forth.XT)
,
formatS(org.rigwit.forth.XT)
,
hold(org.rigwit.forth.XT)
,
holds(org.rigwit.forth.XT)
,
sign(org.rigwit.forth.XT)
,
formatEnd(org.rigwit.forth.XT)
@Primitive(value="#") @Stack(value="ud1 -- ud2") public void format(XT xt) throws ForthException
#
is executed outside
a <# #>
delimited number conversion.xt
- the XT of the definition.ForthException
- if the pictured numeric buffer is overrun.formatStart(org.rigwit.forth.XT)
@Primitive(value="#S") @Stack(value="ud1 -- ud2") public void formatS(XT xt) throws ForthException
#
until the quotient is zero, returning
the zero quotient (ud2).
An ambiguous condition exists if #S
executes outside
of a <# #>
delimited number conversion.xt
- the XT of the definition.ForthException
- if the pictured numeric buffer is overrun.@Primitive(value="#>") @Stack(value="xd -- c-addr u") public void formatEnd(XT xt)
c-addr
and u
specify the resulting character
string. A program may replace characters within the string.xt
- the XT of the definition.formatStart(org.rigwit.forth.XT)
@Stack(value="char -- ") public void hold(XT xt) throws ForthException
HOLD
executes
outside of a <# #>
delimited number conversion.xt
- the XT of the definition.ForthException
- if the pictured numeric buffer is overrun.formatStart(org.rigwit.forth.XT)
@Stack(value="c-addr u -- ") public void holds(XT xt) throws ForthException
HOLDS
executes
outside of a <# #>
delimited number conversion.xt
- the XT of the definition.ForthException
- if the pictured numeric buffer is overrun.@Stack(value="n -- ") public void sign(XT xt) throws ForthException
SIGN
executes outside
of a <# #>
delimited number conversion.xt
- the XT of the definition.ForthException
- if the pictured numeric buffer is overrun.formatStart(org.rigwit.forth.XT)
@Primitive(value=".") @Stack(value="n -- ") public void display(XT xt)
xt
- the XT of the definition.@Primitive(value=".\"") @Immediate public void dotQuote(XT xt) throws ForthException, java.io.IOException, java.lang.NoSuchMethodException
)
(right
parenthesis). .(
is an immediate word.
Typical use:
.(
ccc)
ForthException
java.io.IOException
java.lang.NoSuchMethodException
public int doDotQuote(XT xt)
@Primitive(value="CR") @Stack(value=" -- ") public void carageReturn(XT xt)
xt
- the XT of the definition.@Stack(value="x -- ") public void emit(XT xt)
@Stack(value="c-addr u -- ") public void type(XT xt)
xt
- the XT of the definition.@Primitive(value="U.") @Stack(value="u -- ") public void unsigendDisplay(XT xt)
xt
- the XT of the definition.@Primitive(value=".R") @Stack(value="n1 n2 -- ") public void displayRight(XT xt)
.R
, "R" is short for right.xt
- the XT of the definition.@Primitive(value="U.R") @Stack(value="u n -- ") public void unsignedDisplayRight(XT xt)
xt
- the XT of the definition.@Stack(value="c-addr +n1 -- +n2") public void accept(XT xt) throws java.io.IOException
+n1
is zero or greater
than 32,767. Display graphic characters as they are received.
A program that depends on the presence or absence of non-graphic
characters in the string has an environmental dependency. The
editing functions, if any, that the system performs in order to
construct the string are implementation-defined.
Input terminates when an implementation-defined line terminator
is received. When input terminates, nothing is appended to the
string, and the display is maintained in an
implementation-defined way.
+n2
is the length of the string stored at c-addr
.
Commonly, when the user is preparing an input string to be
transmitted to a program, the system allows the user to edit
that string and correct mistakes before transmitting the final
version of the string. The editing function is supplied
sometimes by the Forth system itself, and sometimes by external
system software or hardware. Thus, control characters and
functions may not be available on all systems. In the usual
case, the end of the editing process and final transmission of
the string is signified by the user pressing a
<return> or <Enter> key.xt
- the XT of the definition.java.io.IOException
- when there is a problem reading from the input stream.@Stack(value=" -- char") public void key(XT xt) throws java.io.IOException
KEY
are not displayed.
Programs that require the ability to receive control characters
have an environmental dependency.
Use of KEY
indicates that the application is processing
primitive characters. Some input devices, e.g., keyboards,
may provide more information than can be represented as a
primitive character and such an event may be received as an
implementation-specific sequence of primitive characters.
ioctl(TIOCGETP)
or an
equivalent. The only way to do this is to use the
AWT/Swing libraries and set up a keyboard listener.
This would require a separate thread running in the
background to do the IO in a ForthReader class.
For the time being we simply ignore the
characters received by KEY
are not
displayed
aspect of the standard.
A line of text is expected, and must be terminated with
the <return> or <Enter> key.
Only the first character is returned.
In effect KEY
is defined as:
: KEY ( -- char ) HERE DUP 1 ACCEPT DROP C@ ;
xt
- the XT of the definition.java.io.IOException
- when there is a problem reading from the input stream.@Primitive(value=">IN") @Stack(value=" -- a-addr") public void toIn(XT xt)
xt
- the XT of the definition.@Primitive(value="SOURCE-ID") @Stack(value=" -- 0 | -1 ") public void sourceID(XT xt)
SOURCE-ID | Input Source |
---|---|
-1 | String (via EVALUATE ) |
0 | User input device |
xt
- the XT of the definition.@Stack(value=" -- c-addr u") public void source(XT xt)
c-addr
is the address of, and u
is the number
of characters in, the input buffer. The input buffer is
read-only.
SOURCE
simplifies the process of directly accessing the
input buffer by hiding the differences between its location
for different input sources. This also gives implementors more
flexibility in their implementation of buffering mechanisms
for different input sources.xt
- the XT of the definition.@Primitive(value="save-input") @Stack(value=" -- xn ... x1 n") public void saveInput(XT xt)
RESTORE-INPUT
, returning a variable number of items
with the number of item on the top of the stack.
SAVE-INPUT
and RESTORE-INPUT
allow the same
degree of input source repositioning within a text file as is
available with BLOCK
input. SAVE-INPUT
and
RESTORE-INPUT
"hide the details" of the
operations necessary to accomplish this repositioning, and are
used the same way with all input sources.
This makes it easier for programs to reposition the input
source, because they do not have to inspect several variables
and take different action depending on the values of those
variables.
The nesting of SAVE-INPUT
and RESTORE-INPUT
is
allowed.
The return value from RESTORE-INPUT
is primarily
intended to report the case where the program attempts to
restore the position of an input source whose position cannot
be restored. The keyboard might be such an input source.
With the exception of the top most element (n), a Standard
Program may not assume any particular meaning for the
individual stack items returned by SAVE-INPUT
.xt
- the XT of the definition.@Primitive(value="restore-input") @Stack(value="xn ... x1 n -- flag") public void restoreInput(XT xt)
xt
- the XT of the definition.saveInput(org.rigwit.forth.XT)
@Stack(value=" -- flag") public void refill(XT xt) throws java.io.IOException
>IN
to zero, and
return true. Receipt of a line containing no
characters is considered successful. If there is no input
available from the current input source, return false.
When the input source is a string from EVALUATE
, return
false and perform no other action.
REFILL
is designed to behave reasonably for all
possible input sources. If the input source is coming from the
user, REFILL
could still return a false value if, for
instance, a communication channel closes so that the system
knows that no more input will be available.xt
- the XT of the definition.java.io.IOException
- when there is a problem reading from the input stream.@Primitive(value="\'") @Stack(value="\'name\' -- xt") public void tick(XT xt) throws java.io.IOException
name
is not found.
When interpreting,
' xyz EXECUTE
is equivalent to xyz
.
Typical use: ... ' name
.
xt
- the XT of the definition.java.io.IOException
- when there is a problem reading from the input stream.@Primitive(value="[\']") @Immediate @Stack(value=" \'name\' -- ; -- xt") public void bracketTick(XT xt) throws ForthException, java.io.IOException, java.lang.NoSuchMethodException
name
delimited
by a space. Find name
. Append the run-time semantics
given below to the current definition.
An ambiguous condition exists if name
is not found.
Runtime:
Stack{ -- xt}
Place name
's execution token xt
on the stack.
The execution token returned by the compiled phrase
"['] X
" is the same value returned by
"' X
" outside of compilation state.
Typical use:: X ... ['] <em>name</em> ... ;
xt
- the XT of the definition.ForthException
java.io.IOException
java.lang.NoSuchMethodException
tick(org.rigwit.forth.XT)
public int doTick(XT xt)
@Primitive(value="(") @Immediate @Stack(value="\'ccc\' -- ") public void comment(XT xt) throws java.io.IOException
)
(right parenthesis).
(
is an immediate word.
The number of characters in ccc
may be zero to the
number of characters in the parse area.
Typical use: ... ( ccc ) ...xt
- the XT of the definition.java.io.IOException
@Primitive(value="+!") @Stack(value="n | u a-addr -- ") public void plusStore(XT xt)
n|u
to the single-cell number at a-addr
.xt
- the XT of the definition.@Primitive(value=",") @Stack(value="x -- ") public void comma(XT xt)
x
in the cell.
If the data-space pointer is aligned when ,
begins
execution, it will remain aligned when ,
finishes
execution. An ambiguous condition exists if the data-space
pointer is not aligned prior to execution of ,
.
The use of ,
(comma) for compiling execution tokens is
not portable.xt
- the XT of the definition.@Primitive(value="C,") @Stack(value="char -- ") public void charComma(XT xt)
char
in the space. If the data-space pointer is
character aligned when C,
begins execution, it will
remain character aligned when C,
finishes execution.
An ambiguous condition exists if the data-space pointer is not
character-aligned prior to execution of C,
.xt
- the XT of the definition.@Primitive(value="2!") @Stack(value="x1 x2 a-addr -- ") public void twoStore(XT xt)
x1 x2
at a-addr
, with
x2
at a-addr
and x1
at the next
consecutive cell. It is equivalent to the sequence
SWAP OVER ! CELL+ !
.xt
- the XT of the definition.@Primitive(value="2@") @Stack(value="a-addr -- x1 x2") public void twoFetch(XT xt)
x1 x2
stored at a-addr
.
x2
is stored at a-addr
and x1
at the
next consecutive cell. It is equivalent to the sequence
DUP CELL+ @ SWAP @
.xt
- the XT of the definition.@Primitive(value="2DROP") @Stack(value="x1 x2 -- ") public void twoDrop(XT xt)
x1 x2
from the stack.xt
- the XT of the definition.@Primitive(value="2DUP") @Stack(value="x1 x2 -- x1 x2 x1 x2") public void twoDup(XT xt)
x1 x2
.xt
- the XT of the definition.@Primitive(value="2OVER") @Stack(value="x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2") public void twoOver(XT xt)
x1 x2
to the top of the stack.xt
- the XT of the definition.@Primitive(value="2SWAP") @Stack(value="x1 x2 x3 x4 -- x3 x4 x1 x2") public void twoSwap(XT xt)
xt
- the XT of the definition.@Stack(value="i*x -- ; R: j*x -- ") public void abort(XT xt) throws ForthException
Quit
,
which includes emptying the return stack, without displaying
a message.xt
- the XT of the definition.ForthException
- an ABORT Forth Exception@Primitive(value="ABORT\"") @Immediate @Stack(value=" \'ccc\' -- ; i*x x1 -- | i*x ; R: j*x -- | j*x") public void abortQuote(XT xt) throws ForthException, java.io.IOException, java.lang.NoSuchMethodException
" -- } Parse ccc delimited by a"
(double-quote). Append the run-time semantics given below to the current definition. Runtime: Stack{i*x x_1 -- | i*x} Stack[R]{j*x -- | j*x} Removex1
from the stack. If any bit ofx1
is not zero, display ccc and perform an implementation-defined abort sequence that includes the function ofABORT
. Typical use:: X ... test ABORT" ccc"} ... ;
xt
- the XT of the definition.ForthException
java.io.IOException
java.lang.NoSuchMethodException
public int doAbortQuote(XT xt) throws ForthException
ForthException
@Stack(value=" -- ") public void align(XT xt)
ALIGN
and
ALIGNED
may be required to build and traverse data
structures built with C,
. Implementors may define these
words as no-ops on systems for which they aren't functional.xt
- the XT of the definition.@Stack(value="addr -- a-addr") public void aligned(XT xt)
a-addr
is the first aligned address greater than or
equal to addr
.xt
- the XT of the definition.@Stack(value="n -- ") public void allot(XT xt)
n
is greater than zero, reserve n
address
units of data space. If n
is less than zero, release
|n|
address units of data space. If n
is zero,
leave the data-space pointer unchanged.
If the data-space pointer is aligned and n
is a multiple
of the size of a cell when ALLOT
begins execution, it
will remain aligned when ALLOT
finishes execution.
If the data-space pointer is character aligned and n
is
a multiple of the size of a character when ALLOT
begins
execution, it will remain character aligned when ALLOT
finishes execution.
Testing
T{ HERE 1 ALLOT -1 ALLOT HERE = -> xt
- the XT of the definition.@Stack(value="c-addr1 -- c-addr2 u") public void count(XT xt)
c-addr1
. c-addr2
is the
address of the first character after c-addr1
. u
is the contents of the character at c-addr1
, which is
the length in characters of the string at c-addr2
.xt
- the XT of the definition.@Stack(value=" -- ") public void decimal(XT xt)
xt
- the XT of the definition.@Primitive(value="ENVIRONMENT?") @Stack(value="c-addr u -- false | i*x true") public void environmentQuery(XT xt) throws java.lang.Throwable
c-addr
is the address of a character string and u
is the string's character count. u
may have a value in
the range from zero to an implementation-defined maximum which
shall not be less than 31. The character string should contain
a keyword from 3.2.6 Environmental queries or the optional word
sets to be checked for correspondence with an attribute of the
present environment. If the system treats the attribute as
unknown, the returned flag is false
; otherwise, the flag
is true
and the i*x
returned is of the type
specified in the table for the attribute queried.
In a Standard System that contains only the CoreWords word set,
effective use of ENVIRONMENT?
requires either its use
within a definition, or the use of user-supplied auxiliary
definitions. The CoreWords word set lacks both a direct method for
collecting a string in interpretation state (S"
is in
an optional word set) and also a means to test the returned
flag in interpretation state (e.g. the optional [IF]
).
xt
- the XT of the definition.java.lang.Throwable
@Stack(value="i*x c-addr u -- j*x") public void evaluate(XT xt) throws ForthException, java.io.IOException
SOURCE-ID
if it is present. Make the string
described by c-addr
and u
both the input source
and input buffer, set >IN
to zero, and interpret. When
the parse area is empty, restore the prior input source
specification. Other stack effects are due to the words
EVALUATE
d.xt
- the XT of the definition.ForthException
- caused by the text being interpreted.java.io.IOException
- should there be a difficulty reading the string.@Stack(value="i*x xt -- j*x") public void execute(XT xt) throws ForthException, java.lang.Exception
xt
from the stack and perform the semantics
identified by it. Other stack effects are due to the word
EXECUTE
d.xt
- the XT of the definition.ForthException
java.lang.Exception
@Stack(value="c-addr -- c-addr 0 | xt 1 | xt -1") public void find(XT xt)
c-addr
. If the definition is not found, return
c-addr
and zero. If the definition is found, return
its execution token xt
. If the definition is immediate,
also return one (1
), otherwise also return minus-one
(-1
). For a given string, the values returned by
FIND
while compiling may differ from those returned
while not compiling.xt
- the XT of the definition.@Stack(value=" -- addr") public void here(XT xt)
addr
is the data-space pointer.xt
- the XT of the definition.@Stack(value=" -- ") public void immediate(XT xt)
: X ... ; IMMEDIATE
xt
- the XT of the definition.@Immediate @Stack(value="x -- ; -- x") public void literal(XT xt) throws java.lang.NoSuchMethodException
x
on the stack.
Typical use:
: X ... [ x ] LITERAL ... ;xt
- the XT of the definition.java.lang.NoSuchMethodException
@Stack(value=" -- x") public int doLiteral(XT xt)
@Stack(value="c-addr u char -- ") public void fill(XT xt)
u
is greater than zero, store char
in each
of u
consecutive characters of memory beginning at
c-addr
.xt
- the XT of the definition.@Stack(value="addr u -- ") public void erase(XT xt)
u
is greater than zero, clear all bits in each of
u
consecutive address units of memory beginning at
addr
.xt
- the XT of the definition.@Stack(value="addr1 addr2 u -- ") public void move(XT xt)
u
is greater than zero, copy the contents of
u
consecutive address units at addr1
to the
u
consecutive address units at addr2
. After
MOVE
completes, the u
consecutive address units
at addr2
contain exactly what the u
consecutive
address units at addr1
contained before the move.
CMOVE
and CMOVE>
are the primary move operators
in Forth 83. They specify a behavior for moving that implies
propagation if the move is suitably invoked. In some hardware,
this specific behavior cannot be achieved using the best move
instruction. Further, CMOVE
and CMOVE>
move
characters; Forth 94 needed a move instruction capable of
dealing with address units. Thus MOVE
has been defined
and added to the CoreWords word set, and CMOVE
and
CMOVE>
have been moved to the String word set.
xt
- the XT of the definition.@Stack(value=" -- ; R: i*x -- ") public void quit(XT xt)
SOURCE-ID
if it
is present, make the user input device the input source, and
enter interpretation state. Do not display a message.
Repeat the following:
>IN
to zero, and interpret.
xt
- the XT of the definition.@Stack(value=" -- a-addr") public void state(XT xt)
a-addr
is the address of a cell containing the
compilation-state flag. STATE
is true when in
compilation state, false otherwise. The true
value in STATE
is non-zero, but is otherwise
implementation-defined. Only the following standard words
alter the value in STATE
:
:
(colon)
;
(semicolon)
ABORT
Quit
:NONAME
[
(left-bracket)
]
(right-bracket)
STATE
.
Although EVALUATE
, LOAD
, INCLUDE-FILE
and INCLUDED
are not listed as words which alter
STATE
, the text interpreted by any one of these words
could include one or more words which explicitly alter
STATE
. EVALUATE
, LOAD
,
INCLUDE-FILE
and INCLUDED
do not in themselves
alter STATE
.
STATE
does not nest with text interpreter nesting.
For example, the code sequence:
: FOO S" ]" EVALUATE ; FOOwill leave the system in compilation state. Similarly, after
LOAD
ing a block containing ]
, the system
will be in compilation state.
Note that ]
does not affect the parse area and that the
only effect that :
has on the parse area is to parse a
word. This entitles a program to use these words to set the
state with known side-effects on the parse area. For example:
: NOP : POSTPONE ; IMMEDIATE ; NOP ALIGN NOP ALIGNEDSome non-compliant systems have
]
invoke a compiler
loop in addition to setting STATE
. Such a system
would inappropriately attempt to compile the second use of
NOP
.
Also note that nothing in the Standard prevents a program from
finding the execution tokens of ]
or [
and
using these to affect STATE
. These facts suggest that
implementations of ]
will do nothing but set
STATE
and a single interpreter/compiler loop will
monitor STATE
.
xt
- the XT of the definition.@Primitive(value="[") @Immediate @Stack(value=" -- ") public void leftBracket(XT xt)
[
is an immediate word.
Typical use:xt
- the XT of the definition.@Primitive(value="]") @Stack(value=" -- ") public void rightBracket(XT xt)
xt
- the XT of the definition.@Primitive(value="buffer:") @Stack(value="u \'name\' -- ; -- a-addr ") public void bufferColon(XT xt) throws ForthException, java.io.IOException, java.lang.NoSuchMethodException
name
delimited by
a space. Create a definition for name
, with the
execution semantics defined below. Reserve u
address
units at an aligned address.
Contiguity of this region with any other region is undefined.
Execute name:
Stack{ -- a-addr}
a-addr
is the address of the space reserved by
BUFFER:
when it defined name
. The program is
responsible for initialising the contents.
BUFFER:
provides a means of defining an uninitialised
buffer. In systems that use a single memory space, this can
effectively be defined as:
: BUFFER: ( u "However, many systems profit from a separation of uninitialised and initialised data areas. Such systems can implement" -- ; -- a-addr ) CREATE ALLOT ;
BUFFER:
so that it allocates memory from a separate
uninitialised memory area.
Embedded systems can take advantage of the lack of
initialisation of the memory area while hosted systems are
permitted to ALLOCATE
a buffer.
A system may select a region of memory for performance reasons.
A detailed knowledge of the memory allocation within the system
is required to provide a version of BUFFER:
that can
take advantage of the system.
It should be noted that the memory buffer provided by
BUFFER:
is not initialised by the system and that if
the application requires it to be initialised, it is the
responsibility of the application to initialise it.xt
- the XT of the definition.ForthException
java.io.IOException
java.lang.NoSuchMethodException
@Stack(value=" -- n") @Environment(value="/PAD") public void padLength(XT xt)
@Stack(value=" -- c-addr") public void pad(XT xt)
c-addr
is the address of a transient region that can
be used to hold data for intermediate processing.
PAD
has been available as scratch storage for strings
since the earliest Forth implementations. It was brought to
our attention that many programmers are reluctant to use
PAD
, fearing incompatibilities with system uses.
PAD
is specifically intended as a programmer convenience,
however, which is why we documented the fact that no standard
words use it.xt
- the XT of the definition.@Stack(value="char \'ccc \' -- c-addr") public void word(XT xt) throws java.io.IOException
char
. An ambiguous condition exists if
the length of the parsed string is greater than the
implementation-defined length of a counted string.
c-addr
is the address of a transient region containing
the parsed word as a counted string. If the parse area was
empty or contained no characters other than the delimiter, the
resulting string has a zero length.
A program may replace characters within the string.
Typical use: char WORD ccc<char>
xt
- the XT of the definition.java.io.IOException
@Primitive(value=">NUMBER") @Stack(value="ud1 c-addr1 u1 -- ud2 c-addr2 u2") public void toNumber(XT xt)
ud2
is the unsigned result of converting the characters
within the string specified by c-addr1 u1
into digits,
using the number in BASE
, and adding each into
ud1
after multiplying ud1
by the number in
BASE
.
Conversion continues left-to-right until a character that is
not convertible, including any "+" or "-", is encountered or
the string is entirely converted.
c-addr2
is the location of the first unconverted
character or the first character past the end of the string if
the string was entirely converted. u2
is the number of
unconverted characters in the string. An ambiguous condition
exists if ud2
overflows during the conversion.xt
- the XT of the definition.@Stack(value="char \'ccc\' -- c-addr u") public void parse(XT xt) throws java.io.IOException
ccc
delimited by the delimiter char
.
c-addr
is the address (within the input buffer) and
u
is the length of the parsed string. If the parse
area was empty, the resulting string has a zero length.
Typical use:
char PARSE
ccc<char>
The traditional Forth word for parsing is WORD
.
PARSE
solves the following problems with WORD
:
WORD
always skips leading delimiters. This
behavior is appropriate for use by the text interpreter,
which looks for sequences of non-blank characters, but is
inappropriate for use by words like (
, .(
,
and ."
. Consider the following (flawed)
definition of .(
:
: .( [CHAR] ) WORD COUNT TYPE ; IMMEDIATEThis works fine when used in a line like:
.( HELLO) 5 .but consider what happens if the user enters an empty string:
.( ) 5 .The definition of
.(
shown above would treat the
)
as a leading delimiter, skip it, and continue
consuming characters until it located another )
that followed a non-)
character, or until the
parse area was empty. In the example shown, the
5 .
would be treated as part of the string to be
printed.
With PARSE
, we could write a correct definition
of .(
:
: .( [CHAR] ) PARSE TYPE ; IMMEDIATEThis definition avoids the "empty string" anomaly.
WORD
returns its result as a counted string.
This has four bad effects:
WORD
must be
copied from the input buffer into a temporary
buffer, in order to make room for the count character
that must be at the beginning of the counted string.
The copy step is inefficient, compared to
PARSE
, which leaves the string in the input
buffer and doesn't need to copy it anywhere.
WORD
must be careful not to store too many
characters into the temporary buffer, thus overwriting
something beyond the end of the buffer. This adds to
the overhead of the copy step. (WORD
may have
to scan a lot of characters before finding the
trailing delimiter.)
WORD
to 255 characters (longer
strings can easily be stored in blocks!). This
limitation does not exist for PARSE
.
WORD
. This introduces a temporal
dependency; the value returned by WORD
is
only valid for a limited duration. PARSE
has
a temporal dependency, too, related to the lifetime
of the input buffer, but that is less severe in most
cases than WORD
's temporal dependency.
WORD
with respect to skipping
leading delimiters is useful for parsing blank-delimited
names. Many system implementations include an additional
word for this purpose, similar to PARSE
with
respect to the "c-addr u
" return value, but
without an explicit delimiter argument (the delimiter set
is implicitly "white space"), and which does skip leading
delimiters. A common description for this word is:
PARSE-WORD ("If bothname" -- c-addr u} Skip leading spaces and parse
name
delimited by a space.c-addr
is the address within the input buffer andu
is the length of the selected string. If the parse area is empty, the resulting string has a zero length.
PARSE
and PARSE-WORD
are present,
the need for WORD
is largely eliminated.
xt
- the XT of the definition.java.io.IOException
@Primitive(value="parse-name") @Stack(value="\'name \' -- c-addr u") public void parseName(XT xt) throws java.io.IOException
name
delimited
by a space.
c-addr
is the address of the selected string within the
input buffer and u
is its length in characters. If the
parse area is empty or contains only white space, the resulting
string has length zero.xt
- the XT of the definition.java.io.IOException
@Stack(value=" -- n") @Environment(value="/COUNTED-STRING") public void stringLength(XT xt)
@Primitive(value="C\"") @Immediate @Stack(value=" \'ccc\' -- ; -- c-addr ") public void countedString(XT xt) throws java.io.IOException, java.lang.NoSuchMethodException
" -- } Parse ccc delimited by"
(double-quote) and append the run-time semantics given below to the current definition. Runtime: Stack{ -- c-addr} Returnc-addr
, a counted string consisting of the charactersccc
. A program shall not alter the returned string. Typical use: : X ... C" ccc" ... ; It is easy to convert counted strings to pointer/length but hard to do the opposite.C"
is the only new word that uses the "address of counted string" stack representation. It is provided as an aid to porting existing pre Forth 94 programs and systems. It is relatively difficult to implementC"
in terms of other standard words, considering its "compile string into the current definition" semantics. Users ofC"
are encouraged to migrate their application code toward the consistent use of the preferred "c-addr u
" stack representation with the alternate wordS"
. This may be accomplished by converting application words with counted string input arguments to use the preferred "c-addr u
" representation, thus eliminating the need forC"
.
xt
- the XT of the definition.java.io.IOException
java.lang.NoSuchMethodException
public int doCountedString(XT xt)
@Primitive(value="S\"") @Immediate @Stack(value=" \'ccc\' -- ; c-addr u ") public void string(XT xt) throws java.io.IOException, java.lang.NoSuchMethodException
" -- } Parseccc
delimited by"
(double-quote). Append the run-time semantics given below to the current definition. Runtime: Stack{ -- c-addr u} Returnc-addr
andu
describing a string consisting of the charactersccc
. A program shall not alter the returned string. Typical use:
: X ... S" <em>ccc</em>" ... ;
xt
- the XT of the definition.java.io.IOException
java.lang.NoSuchMethodException
public int doString(XT xt)
@Primitive(value="S\\\"") @Immediate @Stack(value=" \'ccc\' -- ; -- c-addr u") public void escapedString(XT xt) throws ForthException, java.io.IOException, java.lang.NoSuchMethodException
" -- } Parse ccc delimited by"
(double-quote), using the translation rules below. Append the run-time semantics given below to the current definition. Translation rules: Characters are processed one at a time and appended to the compiled string. If the character is a '\
' character it is processed by parsing and substituting one or more characters as follows, where the character after the backslash is case sensitive:An ambiguous condition exists if a
\a
BEL (alert, ASCII 7) \b
BS (backspace, ASCII 8) \e
ESC (escape, ASCII 27) \f
FF (form feed, ASCII 12) \l
LF (line feed, ASCII 10) \m
CR/LF pair (ASCII 13, 10) \n
newline (implementation dependent, e.g., CR/LF, CR, LF, LF/CR) \q
double-quote (ASCII 34) \r
CR (carriage return, ASCII 13) \t
HT (horizontal tab, ASCII 9) \v
VT (vertical tab, ASCII 11) \z
NUL (no character, ASCII 0) \"
double-quote & (ASCII 34)
\x
<hexdigit><hexdigit>The resulting character is the conversion of these two hexadecimal digits. An ambiguous conditions exists if \x
is not followed by two hexadecimal characters.\\
backslash itself (ASCII 92) \
is placed before any character, other than those defined in here. Runtime: Stack{ -- c-addr u} Returnc-addr
andu
describing a string consisting of the translation of the characters ccc. A program shall not alter the returned string.
xt
- the XT of the definition.ForthException
java.io.IOException
java.lang.NoSuchMethodException
@Primitive(value=":") @Stack(value="C: \'name\' -- x.name x.wordlist colon-sys") public void colon(XT xt) throws java.io.IOException, java.lang.NoSuchMethodException
name
delimited by
a space. Create a definition for name
, called a "colon
definition". Enter compilation state and start the current
definition, producing colon-sys
. Append the initiation
semantics given below to the current definition.
The execution semantics of name
will be determined by
the words compiled into the body of the definition. The current
definition shall not be findable in the dictionary until it is
ended (or until the execution of DOES>
in some systems).
Init:
Stack{i*x -- i*x}
Stack[R]{ -- nest-sys}
Save implementation-dependent information nest-sys
about the calling definition. The stack effects i*x
represent arguments to name
.
Execute name:
Stack{i*x -- j*x}
Execute the definition name
. The stack effects
i*x
and j*x
represent arguments to and
results from name
, respectively.
Typical use:
: <em>name</em> ... ;
Note that colon does not itself invoke the compiler. Colon
sets compilation state so that later words in the parse area
are compiled.xt
- the XT of the definition.java.io.IOException
java.lang.NoSuchMethodException
@Primitive(value=":NONAME") @Stack(value=" -- x.null x.wordlist colon-sys") public void colonNoname(XT xt) throws java.lang.NoSuchMethodException
xt
, enter compilation state
and start the current definition, producing colon-sys
.
Append the initiation semantics given below to the current
definition.
The execution semantics of xt
will be determined by the
words compiled into the body of the definition. This definition
can be executed later by using xt EXECUTE
.
If the control-flow stack is implemented using the data stack,
colon-sys
shall be the topmost item on the data stack.
Init:
Stack{i*x -- i*x}
Stack[R]{ -- nest-sys}
Save implementation-dependent information nest-sys
about the calling definition. The stack effects i*x
represent arguments to xt
.
Execute xt:
Stack{i*x -- j*x}
Execute the definition specified by xt
. The stack
effects i*x
and j*x
represent arguments to
and results from xt
, respectively.
:NONAME
allows a user to create an execution token
with the semantics of a colon definition without an associated
name. Previously, only :
(colon) could create an
execution token with these semantics. Thus, Forth code could
only be compiled using the syntax of :
, that is:
: NAME ... ;
:NONAME
removes this constraint and places the Forth
compiler in the hands of the programmer.
:NONAME
can be used to create application-specific
programming languages. One technique is to mix Forth code
fragments with application-specific constructs. The
application-specific constructs use :NONAME
to compile
the Forth code and store the corresponding execution tokens
in data structures.
The functionality of :NONAME
can be built on any Forth
system. For years, expert Forth programmers have exploited
intimate knowledge of their systems to generate unnamed code
fragments. Now, this function has been named and can be used
in a portable program.
For example, :NONAME
can be used to build a table of
code fragments where indexing into the table allows executing
a particular fragment. The declaration syntax of the table is:
CREATE CMD-TABLE \ table for command execution tokens 100 CELLS ALLOT : CMD ( n -- a-addr ) \ nth element address in table CELLS CMD-TABLE + ; :NONAME ... code for command 0 ... ; 0 CMD ! :NONAME ... code for command 1 ... ; 1 CMD ! ... :NONAME ... code for command 99 ... ; 99 CMD ! ... 5 CMD @ EXECUTE} ...As a further example, a defining word can be created to allow performance monitoring. In the example below, the number of multiply a word is executed is counted.
:
must first
be renamed to allow the definition of the new ;
.
: DOCOLON ( -- ) \ Modify CREATEd word to execute like a colon def DOES> ( i*x a-addr -- j*x ) 1 OVER +! \ count executions CELL+ @ EXECUTE \ execute :NONAME definition ; : OLD: : ; \ just an alias OLD: : ( "name" -- a-addr xt colon-sys ) \ begins an execution-counting colon definition CREATE HERE 0 , \ storage for execution counter 0 , \ storage for execution token DOCOLON \ set run time for CREATEd word :NONAME \ begin unnamed colon definition ;(Note the placement of
DOES>
: DOES>
must modify
the CREATE
d word and not the :NONAME
definition,
so DOES>
must execute before :NONAME
.)
OLD: ; ( a-addr xt colon-sys -- ) \ ends an execution-counting colon definition POSTPONE ; \ complete compilation of colon def SWAP CELL+ ! \ save execution token ; IMMEDIATEThe new
:
and ;
are used just like the standard
ones to define words:
... : xxx ... ; ... xxx ...Now however, these words may be "ticked" to retrieve the count (and execution token):
... ' xxx >BODY ? ...
xt
- the XT of the definition.java.lang.NoSuchMethodException
@Primitive(value=";") @Immediate @Stack(value="x.name x.wordlist colon-sys -- ; -- ") public void semicolon(XT xt)
colon-sys
. If the data-space pointer is not aligned,
reserve enough data space to align it.
Runtime:
Stack{ -- }
Stack[R]{nest-sys -- }
Return to the calling definition specified by nest-sys
.
Typical use:
: <em>name</em> ... ;
One function performed by both ;
and ;CODE
is to allow the current definition to be found in the
dictionary. If the current definition was created by
:NONAME
the current definition has no definition name
and thus cannot be found in the dictionary. If :NONAME
is implemented the Forth compiler must maintain enough
information about the current definition to allow ;
and
;CODE
to determine whether or not any action must be
taken to allow it to be found.xt
- the XT of the definition.@Stack(value=" \'name\' -- ; -- a-addr") public void create(XT xt) throws ForthException, java.io.IOException, java.lang.NoSuchMethodException
name
delimited by
a space. Create a definition for name
with the
execution semantics defined below. If the data-space pointer
is not aligned, reserve enough data space to align it. The new
data-space pointer defines name
's data field.
CREATE
does not allocate data space in name
's
data field.
Execute name:
a-addr
is the address of name
's data field.
The execution semantics of name
may be extended by
using DOES
.
The data-field address of a word defined by CREATE
is
given by the data-space pointer immediately following the
execution of CREATE
.
Reservation of data field space is typically done with
ALLOT
.
Typical use: ... CREATE SOMETHING ...xt
- the XT of the definition.ForthException
java.io.IOException
java.lang.NoSuchMethodException
@Primitive(value="DOES>") @Immediate @Stack(value="x.name x.wordlist colon-sys -- x.name x.wordlist colon-sys ; -- a-addr") public void does(XT xt) throws ForthException, java.lang.NoSuchMethodException
DOES>
is
implementation defined. Consume colon-sys1
and
produce colon-sys2
. Append the initiation semantics
given below to the current definition.
Runtime:
Stack{ -- }
Stack[R]{nest-sys1 -- }
Replace the execution semantics of the most recent definition,
referred to as name
, with the name
execution
semantics given below. Return control to the calling definition
specified by nest-sys1
. An ambiguous condition exists
if name
was not defined with CREATE
or a
user-defined word that calls CREATE
.
Init:
Stack{i*x -- i*x a-addr}
Stack[R]{ -- nest-sys2}
Save implementation-dependent information nest-sys2
about the calling definition. Place name
's data field
address on the stack. The stack effects i*x
represent
arguments to name
.
Execute name:
Stack{i*x -- j*x}
Execute the portion of the definition that begins with the
initiation semantics appended by the DOES>
which
modified name
. The stack effects i*x
and
j*x
represent arguments to and results from
name
, respectively.
Typical use:
: X
...
DOES>
...
;
Following DOES
, a Standard Program may not make any
assumptions regarding the ability to find either the name of
the definition containing the DOES>
or any previous
definition whose name may be concealed by it. DOES>
effectively ends one definition and begins another as far as
local variables and control-flow structures are concerned.
The compilation behavior makes it clear that the user is not
entitled to place DOES>
inside any control-flow
structures.xt
- the XT of the definition.ForthException
java.lang.NoSuchMethodException
public int doDoes(XT xt) throws java.lang.NoSuchMethodException
java.lang.NoSuchMethodException
@Stack(value=" \'name\' -- ; -- a-addr") public void variable(XT xt) throws ForthException, java.io.IOException, java.lang.NoSuchMethodException
name
delimited
by a space. Create a definition for name
with the
execution semantics defined below. Reserve one cell of data
space at an aligned address.
name
is referred to as a "variable".
Execute name:
a-addr
is the address of the reserved cell. A program
is responsible for initialising the contents of the reserved
cell.
Typical use: ... VARIABLE XYZ ...
xt
- the XT of the definition.ForthException
java.io.IOException
java.lang.NoSuchMethodException
@Stack(value="x \'name\' -- ; -- x") public void constant(XT xt) throws java.io.IOException, java.lang.NoSuchMethodException
name
delimited by
a space. Create a definition for name
with the execution
semantics defined below.
name
is referred to as a "constant".
Execute name:
Stack{ -- x}
Typical use:
This is equivalent to the definition:
x
on the stack.
... DECIMAL 10 CONSTANT TEN ...
: CONSTANT CREATE , DOES> @ ;
xt
- the XT of the definition.java.io.IOException
java.lang.NoSuchMethodException
@Primitive(value=">BODY") @Stack(value="xt -- a-addr") public void toBody(XT xt)
a-addr
is the data-field address corresponding to
xt
. An ambiguous condition exists if xt
is
not for a word defined via CREATE
.
a-addr
is the address that HERE
would have
returned had it been executed immediately after the execution
of the CREATE
that defined xt
.xt
- the XT of the definition.@Stack(value=" -- ") public void hex(XT xt)
BASE
to sixteen.xt
- the XT of the definition.@Stack(value="\'name\' -- ") public void marker(XT xt) throws ForthException, java.io.IOException, java.lang.NoSuchMethodException
name
delimited by
a space. Create a definition for name
with the
execution semantics defined below.
Execute name:
Restore all dictionary allocation and search order pointers to
the state they had just prior to the definition of name
.
Remove the definition of name
and all subsequent
definitions. Restoration of any structures still existing that
could refer to deleted definitions or deallocated data space is
not necessarily provided. No other contextual information such
as numeric base is affected.
As dictionary implementations have become more elaborate and in
some cases have used multiple address spaces, FORGET
has become prohibitively difficult or impossible to implement
on many Forth systems. MARKER
greatly eases the problem
by making it possible for the system to remember "landmark
information" in advance that specifically marks the spots where
the dictionary may at some future time have to be rearranged.
Testing:
{ : tmd 123 ; -> }
{ marker tmm -> }
{ : tmd 456 ; -> }
{ tmd -> 456 }
{ tmm -> }
{ tmd -> 123 }
{ : tmd 789 ; }
{ tmd -> 789 ; }
{ tmm -> }
xt
- the XT of the definition.ForthException
java.io.IOException
java.lang.NoSuchMethodException
public int markerDef(XT xt)
@Immediate @Stack(value=" -- u") public void unused(XT xt)
u
is the amount of space remaining in the region
addressed by HERE
, in address units.
Testing:
{ unused constant tu1 -> }
{ 0 , -> } / Use some memory
{ tu1 unused U< -> FALSE }xt
- the XT of the definition.@Stack(value="n1|u1 n2|u2 n3|u3 -- flag") public void within(XT xt)
n1|u1
with a
lower limit n2|u2
and an upper limit n3|u3
,
returning true if either
(n2|u2 < n3|u3
and
(n2|u2 <= n1|u1
and
n1|u1 < n3|u3
))
or
(n2|u2 > n3|u3
and
(n2|u2 <= n1|u1
or
n1|u1 < n3|u3
))
is true, returning false otherwise.
An ambiguous condition exists n1|u1
, n2|u2
,
and n3|u3
are not all the same type.
We describe WITHIN
without mentioning circular number
spaces (an undefined term) or providing the code. Here is a
number line with the overflow point ($o$) at the far right and
the underflow point ($u$) at the far left:
n2|u2 ...
n3|u3
range straddles the overflow/underflow points or it does
not. Lets examine the non-straddle case first:
n2|u2
, the ) denotes n3|u3
, and
the dots and [ are numbers WITHIN
the range.
n3|u3
is greater than n2|u2
, so the following
tests will determine if n1|u1
is WITHIN
n2|u2
and n3|u3
:
n2|u2
<= n1|u1
and n1|u1
< n3|u3
.
n3|u3
is less than n2|u2
and the following
tests will determine if n1|u1
is WITHIN
n2|u2
and n3|u3
:
n2|u2
&;t'= n1|u1
or n1|u1
< n3|u3
.
WITHIN
must work for both signed and unsigned arguments.
One obvious implementation does not work:
: WITHIN ( test low high -- flag ) >R OVER < 0 ( test flag1 ) SWAP R> < ( flag1 flag2 ) AND ;Assume two's-complement arithmetic on a 16-bit machine, and consider the following test:
33000 32000 34000 WITHIN
The above implementation returns false for that test,
even though the unsigned number 33000 is clearly within the
range {{32000 ... 34000}}.
The problem is that, in the incorrect implementation, the
signed comparison <
gives the wrong answer when
32000 is compared to 33000, because when those numbers are
treated as signed numbers, 33000 is treated as negative 32536,
while 32000 remains positive.
Replacing <
with U<
in the above
implementation makes it work with unsigned numbers, but causes
problems with certain signed number ranges; in particular, the
test:
1 -5 5 WITHIN
would give an incorrect answer. For two's-complement machines that ignore arithmetic overflow (most machines), the following implementation works in all cases:
: WITHIN ( test low high -- flag ) OVER - >R - R> U< ;
xt
- the XT of the definition.@Immediate @Stack(value="\'name\' -- ") public void postpone(XT xt) throws ForthException, java.io.IOException, java.lang.NoSuchMethodException
name
delimited by
a space. Find name
. Append the compilation semantics
of name
to the current definition. An ambiguous
condition exists if name
is not found.xt
- the XT of the definition.ForthException
java.io.IOException
java.lang.NoSuchMethodException
public int doPostpone(XT xt)
@Immediate @Stack(value=" -- ") public void recurse(XT xt)
RECURSE
appears in a definition after DOES
.
Typical use:
: X ... RECURSE ... ;
This is Forth's recursion operator. The usual example is the
coding of the factorial function.
: FACTORIAL ( +n1 -- +n2)
DUP 2 < IF DROP 1 EXIT THEN
DUP 1- RECURSE *
;
n2
is the product of n1
with all positive
integers less than itself (as a special case, zero factorial
equals one). While beloved of computer scientists, recursion
makes unusually heavy use of both stacks and should therefore
be used with caution. See alternate definition in
repeat(org.rigwit.forth.XT)
.xt
- the XT of the definition.@Primitive(value="[COMPILE]") @Immediate @Stack(value="\'name\' -- ") public void bracketCompile(XT xt) throws ForthException, java.io.IOException, java.lang.NoSuchMethodException
xt
to the execution semantics of the current
definition.
COMPILE,
is the compilation equivalent of
EXECUTE
. In many cases, it is possible to compile a
word by using POSTPONE
without resorting to the use of
COMPILE,
. However, the use of POSTPONE
requires
that the name of the word must be known at compile time,
whereas COMPILE,
allows the word to be located at any
time. It is sometime possible to use EVALUATE
to
compile a word whose name is not known until run time. This
has two possible problems:
EVALUATE
is slower than COMPILE,
because
a dictionary search is required.
EVALUATE
.
,
(comma). This usage is not portable;
it doesn't work for subroutine-threaded, native code, or
relocatable implementations. Use of COMPILE,
is
portable.
In most systems it is possible to implement COMPILE,
so
it will generate code that is optimised to the same extent as
code that is generated by the normal compilation process.
However, in some implementations there are two different
"tokens" corresponding to a particular definition name:
the normal "execution token" that is used while interpreting
or with EXECUTE
, and another "compilation token" that
is used while compiling. It is not always possible to obtain
the compilation token from the execution token. In these
implementations, COMPILE,
might not generate code that
is as efficient as normally compiled code.ForthException
java.io.IOException
java.lang.NoSuchMethodException
@Primitive(value="\\") @Immediate @Stack(value="\'ccc\' -- ") public void lineComment(XT xt) throws java.io.IOException
bs
is an immediate word.
Typical use:
5 CONSTANT THAT \ This is a comment about THAT}xt
- the XT of the definition.java.io.IOException