1. About this document
This document contains the whole documentation of the QL Broauhabouha Forth system (last version, from 1994-05).
The original documentation consisted of three text files. They have been combined into one document and converted to Asciidoctor[1] format, in order to make the manual easier to use and preserve it for the future[2].
The contents have not been modified, except:
-
Fixed some typos found during the edition.
-
Did some little layout changes, required by the new format.
-
Changed the "kB" unit to "KiB"; and "F79" to "Forth 79".
-
Added some footnotes, in order to provide updated information.
-
Added some missing stack comments.
-
Added automatic section numbering and table of contents.
-
Renamed the subsection "Stack handling" to "Data stack handling" and moved it before "Return stack handling".
2. Terms of distribution
BBS Sysops!
Runtime information is only preserved by QDOS archivers!
Do not re-archive the executable on a different operating system than QDOS! The archive contains OS header information needed for execution.
Distribution is welcome, but only allowed with all original text files being at least part of what is distributed, and the executable file remains the original one.
3. Terms of usage
Brouhabouha Forth for Sinclair QL operating system QDOS comes along with permission granted for free use in noncommercial environments. That is, no profit is made intentionally by its use. Elsewise contact with the author at one of the below given addresses for special license terms is mandatory.
This is a forth interpreter and compiler mainly as described by ANS draft proposal dpANS-6 from June 1993. That paper should be the best description as well for this forth system[3].
No expectations may be made other than for occupying some memory and perhaps stealing some CPU time.
All rights reserved @ Ewald Pfau, 1991-1994.
Comments and reports are welcome.
EMail[4]:
2:316/9.0@fidonet
ehp at ist dot tu-graz dot ac dot at
Surface Mail:
Hoenigtal 145 - 8301 Lassnitzhoehe - Austria/Europe
There also exists a similar version for IBM/DOS machines and a reduced version for 8051 micro controller. Developping tools exist for implementation of versions running on different controllers and platforms.
Thanks to QL community: To Jan Bredenbeek for helping to keep things together via EMail, to Franz Herrmann for his port of LHarc Archiver, to Jonathan Hudson for his "Ibmdisk" tool.
Thanks to Forth community: To Johannes Teich for providing news and putting questions.
4. For novice users
Only some few hints, no tutorial:
-
There is no other delimiter in forth interpreter than white space or end of line (end of block, end of file). Exceptions only if characters are scanned for, as with '"' (double-quotes) or ')' (right paren). So
(
(left paren) is a Forth word as all that other stuff and as well delimited by a blank (but it will scan for a right paren which by that action does not need a delimiter). -
The easiest way to leave the system is to say
BYE
. -
The easiest way to look around is to use the tools provided:
WORDS
,.S
,SEE <name>
,DUMP
. While interpreting, strings may be input withS" <string>"
— after that, parameters of a string, address and length, are waiting on the stack to be dealt with, as consumed byTYPE
or byR/W OPEN-FILE
or doubled by2DUP
and so on;.S
will show at any time what is on the stack. -
Most words are built with defining word
:
(colon), followed by a new_name, a sample of actions, and the definition ended by;
(semicolon). Words built that way, colon definitions, "secondaries", may be "seen" bySEE <new_name>
. Other defining words areCONSTANT
,VARIABLE
,VALUE
,CREATE
. By help ofDOES>
, as well defining words may be defined, mainly to inherit the same runtime code to different data structures composed withCREATE
andALLOT
. Since this is an easy way, there are no predefined arrays. The data representation of any definition is the execution token (formerly called "cfa", "code field address"), which may be found by' <name>
("tick" of name) and consumed byEXECUTE
or byCATCH
. -
Words starting with a dot by convention are words which will show something. A dot by its own will print a number. Numbers are input by typing them in, so they are on the stack. For the interpreter, numbers containing a dot somewhere between the digits are interpreted to be double-cell numbers, the high value being top of stack. Numbers being put in with a leading '$', '&' or '%' are taken to be composed of hex digits, decimal or binary, independant of what is the momentary valid base held in variable
BASE
. -
Leo Brodie’s book Thinking Forth has been published again[5].
5. Some differences to Forth 79 and Forth 83
-
Only data memory may be regarded as being addressable!
-
A
DOES>
-clause only is a valid runtime for definitions which have been created by direct or indirect use ofCREATE
. From a word generated by a (child of)CREATE
the address of associated data memory may be calculated by applying>BODY
to the execution token of that word. The amount of needed data space should have been reserved by use ofALLOT
or,
("comma") orC,
("C-comma"). Proper use ofALIGN
must be taken care of, if memory shall be addressable as storage area for cells. -
To control recovery from ambiguos situations, execution tokens may be executed by being consumed as a parameter of
CATCH
. By this, a frame is initialized for stack and return stack, which will be discarded if aTHROW
is executed by a called instance, with a parameter other than zero. This parameter will then be returned byCATCH
. Elsewise, a zero is consumed byTHROW
, andCATCH
returns zero, so the frame has been worked thru step by step. IfCATCH
returns a non-zero value, so an ambiguos situation is given, which may be dealt with as the special situation dictates. This non-zero parameter may be handed over then to anotherTHROW
following the special action taken in this case. By each of the interpreting loops,EVALUATE
,LOAD
,INCLUDE-FILE
,QUIT
, such a frame is established, which will be discarded as a last instance for recovery, which will yield into the action ofQUIT
. So ambiguos situations may be "thrown" in any case, and control is given back to the interpreting loop then. If interpreting is done from operating system commandline, so control is given back to the operating system, to ensure a workable condition if interpreting is done in unattended situations. As well, if the returnstack frame is out of bounds, aBYE
is executed. Throw-values in the range -4095…0 are reserved for system own use. -
Instead of vocabularies, switchable by names, now there are wordlists, switchable by parameters.
WORDLIST
will install a new wordlist and return a wordlist identifier ("wid"). This parameter is consumed bySET-CURRENT
to switch the compiling wordlist.GET-CURRENT
returns the identifier of the active compiling wordlist.GET-ORDER
will return a set of parameters, the count being on top of stack.SET-ORDER
will switch the active search-order, consuming a set of parameters with its count on top of stack, the identifier of the first searched wordlist being next on stack.FIND
will search in the active search-order.SEARCH-WORDLIST
only will search in one wordlist, given as parameter.FIND
will consume the address of a counted string, and if the name contained in that string is not found, it will return that address and zero as top of stack.SEARCH-WORDLIST
will consume the parameters of a string as address and length plus a wordlist identifier, and if not found, only will return zero. If the searched string could be found to be the name of a definition in the wordlists which had been scanned, so the execution token of that definition is returned, and a flag, being greater than zero, if that word is immediate, elsewise a flag being less than zero. This is the only way, the immediacy of a definition may be determined. -
To inherit a compiling action to the runtime of a definition, instead of formerly used
COMPILE <name>
and[COMPILE] <name>
now the "immediacy smart"POSTPONE <name>
is provided, as well asCOMPILE,
("compile-comma"). ByPOSTPONE
, "name" will be compiled by itself if it is immediate, so it will be executed at runtime instead of being executed at compile time, elsewise "name" will be compiled at runtime.COMPILE,
takes an execution token as parameter and appends it at runtime to the definition of which the compilation is being in progress. -
There are four defined input streams now. This is for strings in memory, via
EVALUATE
(given parameters for that string), for files containing text lines — viaINCLUDE-FILE
(given a file handle) orINCLUDED
(given parameters for the string of a file name) —, for block files viaTHRU
orLOAD
(given two block numbers or one; and for this implementation:LOAD-FILE
given a block number and a file handle), and console, viaQUIT
(no parameters; state of the machine is reset to interpreting, debugging is switched off, returnstack and catch-frames are reset). -
SAVE-INPUT
will return a set of parameters with the count being on top of stack, being an internal description of the momentary position valid for the interpreter. ByRESTORE-INPUT
it will be tried to set the position valid for the interpreter to the position as described by the given set of parameters, which should come from an earlier execution ofSAVE-INPUT
; will return a true flag if this was possible, a false flag otherwise. No switching across different input streams or files should be done this way (even if this implementation is capable of it). -
SOURCE
will return the parameters of the whole string which for the moment is the input for the interpreter, consisting of one line for console or ASCII file, or one block for block files, or the string given toEVALUATE
. Within the input string, the valid position being interpreted next may be set by reading the value held in variable>IN
and writing it back again. An offset obtained from scanning in that string may be added or subtracted. The rest of the string which waits for being interpreted may be calculated by:SOURCE >IN @ /STRING
. This will leave a length of zero if the input stream is empty for this line or block. -
The rest of this string is discarded by
REFILL
— and by that, from the input stream the next line or block is tried to be obtained. A flag is returned, zero in case the input stream had been a string in memory forEVALUATE
or an end of file has been reached. -
A counted string being returned by
WORD
does no more depend on being delimited by a blank (or zero in Forth 79). A delimiting blank will be appended anyway after the isolated string has been moved to the position in memory returned byHERE
. The former number conversion, which needed that delimiting blank has been changed in being built upon the behaviour of>NUMBER
— which takes as parameters a double cell accumulation value and the parameters of a string, these values being updated and returned. If the string is empty afterwards, so its length is found as the length parameter being zero, so no delimiter is needed. -
Formerly used immediate word
ASCII
, to obtain a character from the input stream, has been replaced by non-immediateCHAR
and immediate[CHAR]
.EXPECT
— to obtain a string as typed in from keyboard — has been replaced byACCEPT
; instead of the resulting length of the input string being held in variableSPAN
now the result is returned on stack. Instead of fomerly usedFORGET <name>
— after having made allocations -, now markers should be set usingMARKER <name>
, before making allocations. Execution of<name>
then will have the same effect as now obsoleteFORGET <name>
.
6. Implementation characteristics and special behaviour
By use of ADJUST-SIZES
and SAVE-FILE
(described somewhere else
in one of these texts), the sizes of RAM, which the executable
claims from QDOS, may be set to individual needs. This is set to
be 192 KiB in this distributed version.
For File Wordset words RENAME-FILE
and RESIZE-FILE,
the QDOS
extension traps provided by TK2 should be workable (Trap 3,
functions $4A and $4B). No other extensions are required except
provision for enough memory, that is at least a 256 KiB expansion
card on original QL.
Floating Point wordset is missing.
Only two internal throw codes are implemented, these are -2 for
ABORT"
and -1 for ABORT
. -254 THROW
will give the behaviour of
BYE
(this may change in future versions).
Environmental queries with ENVIRONMENT?
only will deliver a
dummy argument of zero.
The executable will claim 192 KiB from the operating system at
startup. This is 112 KiB for code, 48 KiB for headers and 32 KiB
for data[6]. With the block
editor loaded as-is, for free use remain about 42 KiB for
code, 22 KiB for headers, 19 KiB for data. After execution of
marker NOEDIT
, this increases to 59 KiB, 27 Kb, 23 KiB, with
no editor. This may be adjusted to individual needs by use of
ADJUST-SIZES
and SAVE-FILE
for next start-up of saved
executable.
QDOS channel IDs are held in an internal table keeping a maximum of 32 values. Forth I/O-handle parameters for I/O-access are offsets into this table. Positions in this table having become free are re-used.
Memory in data area is addressable as cells only with aligned addresses.
EMIT
of non-graphical characters is handled by QDOS. It will
print a filled rectangular.
Editing of keyboard input via ACCEPT
is done via QDOS trap
IO.FLINE, so commandline history will be functionable if
implemented, and deleting, cursor positioning, and inserting of
characters is working. IO.FLINE is started as a secondary job
from QDOS. Forth job is named "ZQF" in QDOS job table. Secondary
job is named "ZQF/con_".
After the given string length for ACCEPT
has been input, or the
ENTER key is pressed, the call is terminated. The code for the
ENTER key is the code for LF.
KEY will act upon character input in the range of character
codes 0…255. Keypresses giving other values are discarded if
waiting or scanning for input with KEY
or KEY?
. The set of
all keycodes may be obtained by use of EKEY
or scanned for by
use of EKEY?
.
A character storage cell has the width of one address unit. At
any time the machine may be regarded as character aligned. The
only memory operator acting upon address units is MOVE
. All
other memory operators will act upon character or cell units.
No provision is made to store definition names containing
characters which are not printable characters, via keyboard or
ASCII file input. If such names have been defined, using input
from block files or via EVALUATE
, so the corresponding execution
tokens may be found as well the same way.
If the input stream is switched to an ASCII file and interpreting is
done via INCLUDE-FILE
or INCLUDED
, so characters with codes smaller
than 32 are treated as white space, except for the codes for CR and
LF, which are taken as EOL markers. End of line is reached with CR,
LF, or the sequence CR LF.
While compiling, control flow stack for compiling of conditionals is
the parameter stack. Non-immediate words CS-PICK
and CS-ROLL
will copy
or exchange control flow values.
A value of greater than 36 kept in variable BASE
will give an
undefined behaviour for digit conversion. A value of up to 36 will
provide conversion to digits 0…9,A…Z. DECIMAL
will reset
conversion to digits 0…9.
Compilation of an ABORT" <text>"
sequence will be compiled as a
sequence starting with a conditional branch and an inline
string containing <text>.
Maximum sizes are: 255 characters for counted strings, 30 for
definition names and the output of WORD
. Parsed strings may be
as long as the input field where they are taken from. If 'S"' is
executed while interpreting, so the parsed string is kept in a
circular buffer, and at least the two last input strings are
available, each with a maximum size of 255 characters.
User input and output devices are opened at start of program. The first input device is the commandline as given to QDOS as parameter with program call. This line is evaluated. After that, all further input is taken via QDOS call IO.FLINE. User output device is a console window set to no border, CSIZE 0,0, INK 7, PAPER 0 at position 0, 0, sized 512 * 256 with cursor switched on and the window cleared. First IO.FLINE and output window are set up, then the commandline is evaluated, then the banner is shown. This behaviour may change or as well be made configurable in future versions.
The accessible dictionary space is data space only, this is separate from code space and name space.
One address unit is 8 bits wide.
Numbers are stored in cells sized 4 address units, in two’s complement representation for signed values.
Single cell signed numbers may take values from -2^31 to 2^31-1. Single cell unsigned numbers may take values from 0 to 2^32-1. Positive single cell numbers may take values from 0 to 2^31-1.
Double cell signed numbers may take values from -2^63 to 2^63-1. Double cell unsigned numbers may take values from 0 to 2^64-1. Positive double cell numbers may take values from 0 to 2^63-1.
Data space of dictionnary is contiguos. Stack and return stack
are kept inside this area and should be regarded as
non-addressable — positions may change with heap allocations.
Strings returned by S"
, C"
, WORD
, PARSE
, SOURCE
should be
regarded as read-only and be copied before they are written to.
Buffer for WORD
is shared with buffer for pictured number
conversion and kept at the address returned by HERE
. WORD
will
not return a string with a size greater than 31 characters.
Storage area for one cell is sized 4 address units. Storage area for one character is sized 1 address unit.
Keyboard input terminal buffer is sized 128 characters.
Storage area for pictured numeric output string is sized 64 characters, 32 of which are shared with the buffer for WORD.
The size of the scratch area, starting at the address returned
by PAD
, is all unused data memory. So PAD UNUSED
will give a
maximum temporary storage area.
Finding definition names internally is done by uppercasing the
result of WORD
from keyboard input and uppercasing the names
searched for. Names of new definitions are stored uppercase.
This case independent behaviour may be switched off by writing 0
to variable CAPS
. After that, names of new definitions are
stored as given and finding is done case dependant with input as
given.
The system prompt, after a line from keyboard has been successfully interpreted, is "ok" followed by as many dots, but not more than 32, as are items on the stack. If state of machine is the compiling state, instead of "ok" "]" is output. Cursor is set to a new line then.
Operators ,
/
, MOD
, /MOD
, /
, and */MOD
are not
provided and have to be defined using the preferred method of
rounding characteristics, given either by SM/REM
, symmetrical,
or FM/MOD
, towards negative infinite.
Definitions by using SM/REM
are:
: /MOD ( n1 n2 n3 -- n4 n5) over 0< swap sm/rem ; : / ( n1 n2 -- n3) /mod swap drop ; : MOD ( n1 n2 -- n3) /mod drop ; : * ( n1 n2 -- n3) m* drop ; : */MOD ( n1 n2 n3 -- n4 n5) >R m* R> sm/rem ; : */ ( n1 n2 n3 -- n4) */mod swap drop ; : /MOD ( n1 n2 -- n3 n4) over 0< swap sm/rem ;
In compiling state, variable STATE
contains -1, else 0.
Arithmetic overflow or underflow will give results modulo 2^32, the operators seen as unsigned numbers. Division by zero will give results of 0 for quotient and remainder.
While compiling a runtime part of a definition in a
DOES>
-clause, the name of the defining word of which the
compilation is in progress, will not be found. It is revealed
only after finishing the definition with ;
(semicolon).
No system words will use the scratch area starting at PAD
.
Return stack size is 256 cells. Parameter stack size is all of
unused memory growing downwards, if not used as scratch area
starting at PAD
, growing upwards. By UNUSED
, a stack size
of 256 cells is taken into account.
7. Words and tools not covered by the ANS Forth paper
7.1. Words available in Forth wordlist
U<=> ( u1 u2 -- -1/0/1)
Compare unsigned two values given, return 0 if both are the same, -1 if the value next on stack is smaller than the value on top of stack, 1 otherwise.
CASE? ( n1 n2 -- n1 0 // -1)
Compare two values given, return -1 if both are the same, elsewise leave the value next on stack and zero on top of stack.
UMIN ( u1 u2 -- u3)
Leave unsigned the smaller one from two values given.
UMAX ( u1 u2 -- u3)
Leave unsigned the bigger one from two values given.
$CRC16+ ( n0 a n -- n1)
Apply a cyclic redundancy check calculation to the string in memory given by its parameters, address and length, starting with the accumulating value given as the next but one value on stack, returning the accumulated value.
CREATE-JOB ( #code #data -- a job-id err#) PJOB ( priority job-id -- err#) AJOB ( priority 0/-1 job-id -- err#) SUSJOB ( #ticks job-id -- err#) RELJOB ( job-id -- err#)
F#@ ( id -- channel#)
Lookup the OS specific channel number of the handle number
as it has been returned by OPEN-FILE
or by CREATE-FILE
.
IN-CHANNEL ( -- a)
Variable, containing the handle number used for input from keyboard.
CRT-CHANNEL ( -- a)
Variable, containing the handle number used for output to console.
CSIZE ( n1 n2 --) PAPER ( n --) INK ( n --) CURS-ON ( --)
DEL ( --)
Destructive backspace is output on console window if cursor is not already in first column.
SKIP ( a n char -- a+ n-) SCAN ( a n char -- a+ n-)
CAPS ( -- a)
Address of a variable in which -1 is kept if some system words
shall act case independant. These are FIND
and SEARCH-WORDLIST
for the interpreter as well as COMPARE
and SEARCH
for string
words. Writing 0 to CAPS
will switch to case dependant
behaviour.
CAPITAL ( char -- char)
A given character is returned uppercased.
STACK| ( ix..iy -- ix..iy // "abcd...|xyz...|")
Rearrange the order of values on stack, taking each letter of a first series of letters up to a first pipe sign '|', to be one item on stack in the order as is, the last letter representing the value on top of stack, and rearrange, or as well duplicate or drop, following the series of letters up to a trailing pipe sign.
USE ( -- // "name")
To the block file system, file <name> is assigned to. This file
is opened and the file handle is stored in variable BLOCK-FID
.
If a block file already has been open with it’s file handle
stored in BLOCK-FID
, it is closed after the new file could be
opened.
If on the same drive the medium is to be changed, and a file is
open on the first medium, so this file should be closed by:
BLOCK-FID @ CLOSE-FILE THROW 0 BLOCK-FID !
.
LOAD-FILE ( n hdl --)
A file represented by a file handle is regarded to be a block
file, the value stored in BLOCK-FID
is saved, the block number
given is loaded as with LOAD
, and BLOCK-FID
restored afterwards.
SAVE-FILE ( a n -- err#)
An image of the momentary running executable is saved as a file the name of which given by its parameters, address and length. A nonzero value is returned if operation failed.
GET-SIZES ( -- #code #data #hdrs)
Three values are returned on stack reflecting the amount of memory sizes the executable would claim from the operating system at next startup. These are for maximum size of code, of data, and, as top of stack, of headers.
ADJUST-SIZES ( #code #data #hdrs --)
Three values are taken from stack to be the sizes of memory
which will be claimed from operating system more than
momentarily needed, at next start-up of the momentary running
executable, if it is saved after adjusting sizes by SAVE-FILE
.
The values are for additional size of code, of data and of
headers area, the last one being expected as top of stack. All
parameters being zero will leave an unexpandable execution image
which will claim about 100 KiB if editor is loaded, about 80 KiB
without. Data memory already reserved by ALLOCATE
is not
included and should be added to the parameter for the amount of
the size of data area. For use of directory access words
OPEN-DIR
, READ-DIR
, CLOSE-DIR
, an amount of 100 address units
should be reserved for each instance this will be made use of.
Caution! Parameters for an image exceeding available RAM will leave a non-executable image!
.MEM ( --)
Some values are displayed to reflect the current state of the system, remaining sizes of memory areas, identifiers of wordlists, tasks and heap memory areas.
TICKS ( -- n)
A value is returned which is incremented once in a second.
TICKS>T&D ( n -- ss mm hh dd mm yy)
Calculate the values for time and date from the value as given
by TICKS
.
.DATE ( --)
The current date is output to the console as given by the OS.
.TIME ( --)
The current time is output to the console as given by the OS.
AVAILABLE ( -- u)
Maximum size which may be reserved on the heap by ALLOCATE
is
returned.
ERRORLEVEL ( -- a)
7.2. Words available in Assembler wordlist (if assembler loaded or not)
>CODES ( -- a)
Variable, holds address of a table, in which the execution
tokens are kept for all assembler memory and dictionnary
accesses. As a default, assembler code is generated in code
area. This may be changed by providing a new table containing
execution tokens for the actions of C@
, @
, C!
, !
,
HERE
, ALLOT
, ALIGN
, C,
("C-comma") and ,
("comma").
7.3. Words available in Editor wordlist (if editor loaded or not)
B/BLK ( -- 1024)
Return size of one block of a block file.
BLK-UM* ( u -- d)
Multiply a given value with B/BLK
, returning a double cell
product.
BLK/MOD ( d -- mod div)
Divide a double cell number by B/BLK
, returning modulo and
quotient.
-SKIP ( a0 n char -- a0 n-)
-SCAN ( a0 n char -- a0 n-)
WSCAN ( a n1 n2 -- a+ n-)
In an array of cells represented by address of first cell and count of cells, a value is scanned for which is given as top of stack. If this value could be found, so the parameters of the rest of the array is returned, starting at the address at which the searched value is stored in and the numbers of cells remaining, including the found position. Elsewise zero is returned as top of stack and the first address behind the array.
?ESC ( -- 1 /key:esc , -1 /cr , 0 , /space = wait)
Keyboard is scanned for a keypress. Enter key will return -1, ESC key will return 1, else 0. If space key has been pressed, a second press of space key is waited for. Other keypresses are skipped.
TAB+ ( n --)
Cursor is positioned to next tab stop for a field width given as parameter. If this field does not fit into the rest of the line, a new line is started.
7.4. Debugging
XDUMP ( 'a n --)
Show a dump of code memory not addressable with data memory words.
'SEE ( cfa --)
Apply the function of SEE
on the execution token given instead
of the name of a definition.
DEBUG ( -- /"name")
Debugger is initialized to be called each time, the given <name> will be executed next, if it is a secondary forth definition. Exception handling and QUIT will disable the debugger. Debugger is set to single step mode, so after each step, the Enter key has to be pressed. Instead a line may be given to the interpreter while debugging in single step mode. After execution of this line, the prompt will be the forth prompt with the leading string "debug: ". Next step will be executed if Enter is pressed with an empty commandline. Debugging keys input is taken from keyboard even if input source is a file. Some words used by the debugger itself cannot be debugged, elsewise restrictions for interpreter use while debugging are minimal. With shared code of tasks, only the same instance of code will be debugged, the debugger itself is working in.
'DEBUG ( cfa --)
Apply the function of DEBUG
on the execution token given instead
of the name of a definition.
FT ( --)
Debugging mode is switched to "Fast Trace". This may be done at any time after the debugger has been initialized. If Enter key is pressed, so mode is switched to single step mode. If space key is pressed, so output is halted until another pressing of the space key.
NODEBUG ( --)
While in single step debugging mode, debugger is switched off and execution continuos without debugger.
7.5. Internal Tasking
SELF ( -- a)
Within a task, its own task identifier "tcb" is given.
PAUSE ( --)
Essentially a nope, if tasker is switched off, elsewise a hook,
which enables next active task to continue execution until this
one by itself executes a PAUSE
. Each system word performing I/O
ends with the action of PAUSE
.
TASKER-ON ( --)
Behaviour of PAUSE
is switched to be a hook into next task in
the circular list of current active tasks.
TASKER-OFF ( --)
Behaviour of PAUSE
is switched to be a NOPE
. May be executed
within tasks instead of semaphores to protect access to open
files if used in conjunction with TASKER-ON
— the interpreter is
switched off also this way, if it is not the current task from
where this is executed.
WAKE ( tcb --)
A task is put into the circular list of current active tasks.
SLEEP ( tcb --)
A task is taken out from the circular list of current active
tasks. If code of a task is placed in the memory area for which
a marker has been defined, so the action of SLEEP
is performed
for this task, if that marker is executed and the task is
active. If a task is not an endless loop, so it will stop by
performing the action of SLEEP
, and re-initialize itself after
finishing, for being restartable again by WAKE
.
RUNS ( tcb -- /"name")
To an existing and "sleeping" task, a new action is assigned to, given by <name>.
TASK: ( Execution: -- tcb) ( Compilation: #R #S -- /"name")
Start of definition of a task <name>. Parameters are to be given
for sizes of task own return stack and parameter stack, in
address units, should be at least 64 for each of them. HERE
and
PAD
called from within a task will give addresses inside the
task. If scratch pad area shall be used inside the task, its
size should be taken into account of the size for the parameter
stack.
7.6. Directory access
OPEN-DIR ( a n method -- dir-id err#)
Given a string in data memory by its parameters, and the value for a method (which will be ignored), an access will be tried to be opened to a directory on the drive of which the name is contained in the string. An internal identification value and 0 as top of stack will be returned if the operation succeeded, elsewise a value different from 0 as top of stack and a descardable value at next position on stack.
NEXT-DIR ( dir-id -- dir-a err#)
Given a directory identification as returned by OPEN-DIR
, the
next entry from the directory on the associated drive is read
and the address of a specfic storage area is returned together
with 0 if the operation succeeded, elsewise a non-zero value and
a discardable value at next position on stack.
CLOSE-DIR ( dir-id -- err#)
Given a directory identification as returned by OPEN-DIR
, all
other access to the directory on the associated drive by help of
this value is discarded. Temporarilly allocated heap storage area
is set free again.
>FATTR ( dir-a -- a2)
In the specific storage area as given by READ-DIR
the address
of a character field is calculated, from which a value may be
read (by C@
) which should reflect the attribute which the OS
stored as associated with the file of which the directory entry
just has been read.
>FTIME&DATE ( dir-a -- ss mm hh dd mm yy)
From the specific storage area as given by READ-DIR
, six
values for time and date are calculated which are associated
with the file to which the just read directory entry belongs to.
The values are returned the same way as with forth facility word
TIME&DATE
, with the values for seconds, minutes, hour, day,
month, year on stack, the value for the year of the date being
on top of the stack.
>FSIZE ( dir-a -- a2)
In the specific storage area as given by READ-DIR
, the address
of a double-cell field is calculated, in which the size of the
file may be read (by 2@
) of which the directory entry just has
been read. After an OPEN-DIR
but before a READ-DIR
this will
give the amount of free memory available on the medium.
>FNAME ( dir-a -- a2)
In the specific storage area as given by READ-DIR
, the address
of a counted string is calculated, which holds the name of the
file of which the directory entry just has been read. A counted
string may be converted to the parameters of a string with
address and length by applying COUNT
to the address of a counted
string as parameter. After an OPEN-DIR
but before a READ-DIR
this will give the name the medium has been given when it was
formatted.
DIR ( -- //"name")
The directory on a drive is shown of which <name> is given, with names of files, sizes, and asterisks if they are executables.
HEADER-READ ( id -- dir-a err#)
QDOS Header information of an open file is read into an area starting at "dir-a". Tools for queries from directory entries may be applied; information for file-size is mapped as a double-cell value.
HEADER-WRITE ( id -- err#)
QDOS Header information of an open file is written back using
"dir-a" as obtained by HEADER-READ
. If header information for
data allocation is to be changed, the adequate value should be
written as a single cell value into offset 6 of "dir-a" with
!
. If header information for file access is to be changed, the
adequate value (1 for an executable, 0 for a data file) should
be written into offset 5 of "dir-a" as a character value with
C!
.
8. The block File Editor
Before editing, first a block file has to be assigned to be the
default block file for the interpreter, using USE <name>
.
If while editing more files have been opened, so the last one edited will be the one which is assigned to be the default block file after leaving the editor.
By invoking the editor, an "ID" is asked for, holding two characters; this will be put into the top line of each changed block while editing, if this line was not empty. The ID is put together with current date in the form "ddmmmyyid" right justified. If the ID query is skipped by only hitting the enter-key, so no ID’s will be written. If an ID is active, the query is skipped.
Pushed lines and find-strings are preserved if the editor is left and entered again. By entering the editor, state of the debugger and values on the stack remain untouched except for the case of read/write/open failures.
Cut&Paste between files may be done either by Push&Pop for lines, or by setting markers as "from" and "up to" for blocks, then switching to target file, then "copy marked blocks" and "delete marked blocks". There should be no restriction on size of copied areas other than dictated by the medium. Files will be resized, cut (if TK2 is workable) or enlargened as necessary.
The functions for insertion of one block or deletion of current block only work if dummy markers are set. Deletion of current block will leave the last block of the file empty. Insertion first will use an empty last block, before enlargening the file.
By using a block file with a size smaller than 1024 bytes, that is less than one full block, this block probably is filled with 0’s instead of with blanks — following the default behaviour of the block cache system of the interpreter. These lines should be deleted and the file should be flushed then, so the size is reset to be 1024 bytes. Insertion of one block after that only will work then, if this "block 0" is not left empty (that is: at least a backslash as first character in first line may be written). Block 0 never will be taken as input for the interpreter, it is always a comment block. Block 1 for usual is the block containing loading instructions for random access into the file.
ED ( --)
Start editing with the block of which the number is held in
variable SCR
. By default this is 1, at start-up this is 0,
elsewise the number of the last block edited.
EDIT ( blk --)
Start editing with the block of which the number is given as a parameter.
ID-OFF ( --)
Cancel a previously put-in ID.
ALL-FLUSH ( --)
Flush all files open for the editor from within the interpreter.
ALL-CLOSE ( --)
Close all files open for the editor except the one last edited, which is the default block file for the interpreter.
8.1. Keys
The following keys are assigned to: (A=ALT, S=Shift, ^=CTRL)
jump: left right column A-left A-right start/end of line S-left S-right word up down row S-up S-down top/bottom of screen Tab S-Tab +/- 8 columns Enter next line, 1st column
^left ^right delete ^H delete ^Q toggle mode for insert/overwrite
^N insert ^Y delete ^Z delete ^O clear-EOL ^S split ^M join if next line fits F3 push (buffer may hold 32 lines) F4 push© F5 pop if line fits
^up page back ^down page ahead A-up page back A-down page ahead S-A-up 1st screen of file S-A-down last screen of file S-F5 "shadow" screen — toggle half of file-size back/ahead ^U undo if updated ^D delete current screen if marker set (ignore marker) ^T insert one screen if marker set (ignore marker)
F2 S-F2 input & find ahead / backwards ^L ^K find next / previous ( not implemented, but reserved keys: ) ( ^R ^E find&replace next / previous)
F1 goto A-F1 set A-F2 reset A-F3 copy marked blocks A-F4 delete marked blocks
^F3 open ^F4 close S-F3 swap S-F4 roll ^F flush all open files ^B make a backup
ESC modified & flushed ^X unmodified if updated
9. Table of optimizing compiler actions
exe-An & exe-B ==> exe-Cn
A[ exe-A1 exe-A2 exe-A3 ... ] B= ............................. exe-B C[ exe-C1 exe-C2 exe-C3 ... ]
A[ R> SWAP ROT 2DROP ] B= .......................... DROP C[ RDROP NIP ROTDROP 3DROP ] A[ 2R> 2R>/SWAP R>/RDROP RDROP/R> 2R@ ] B= ................................................. DROP C[ RDROP/R> R>/RDROP 2RDROP 2RDROP 2R@/DROP ] A[ NIP DROP 2R> 2R>/SWAP 2R@ ] B= .......................................... NIP C[ NIPNIP DROPNIP R>/RDROP RDROP/R> R@ ] A[ ROT OVER 2DUP R> 0 2R>/SWAP ] B= ........................................................... SWAP C[ ROTSWAP OVERSWAP 2DUP/SWAP R>/SWAP 0/SWAP 2R> ] A[ ROT SWAP DUP ] B= ......................... ROT C[ ROTROT SWAPROT DUPROT ] A[ DROP 2DROP 2SWAP R> 2R> 2R>/SWAP ] B= ................................................. 2DROP C[ 3DROP 4DROP 2NIP R>/2DROP 2RDROP 2RDROP ] A[ 2R> ] B= ........... 2SWAP C[ 2R>/2SWAP ] A[ 2SWAP 2OVER ] B= .............. 2OVER C[ 2TUCK 4DUP ] A[ 2ROT ] B= ....... 2ROT C[ -2ROT ] A[ DUP SWAP >R SWAP/>R ] B= .................................... >R C[ DUP/>R SWAP/>R SWAP/2>R 2>R ] A[ >R ] B= ........ R@ C[ DUP/>R ] A[ R> DROP ] B= ................... R> C[ 2R>/SWAP DROP/R> ] A[ 2DUP 2SWAP ] B= ..................... 2>R C[ 2DUP/2>R 2SWAP/2>R ] A[ DUP ] B= ....... @ C[ DUP/@ ] A[ 2DUP ] B= ......... C! C[ 2DUP/C! ] A[ SWAP OVER TUCK DUPROT 2DUP ] B= ......................................... ! C[ SWAP/! OVER/! TUCK/! DUPROT/! 2DUP/! ] A[ OVER TUCK 2DUP CELLS @ ] B= ..................................... + C[ OVER/+ TUCK/+ 2DUP/+ CELLS/+ @/+ ] A[ OVER TUCK 2DUP 2DUP/SWAP CELLS @ ] B= ................................................... - C[ OVER/- TUCK/- 2DUP/- 2DUP/SWAP/- CELLS/- @/- ] A[ 2SWAP ] B= .......... D- C[ 2SWAP/D- ] A[ 0< 0> = <> < > U< U> ] B= ..................................... 0= C[ 0>= 0=< <> = >= =< U>= U=< ] A[ 2DUP/= 2DUP/<> 2DUP/- 2DUP/< 2DUP/> 2DUP/U< 2DUP/U> ] B= ............................................................... 0= C[ 2DUP/<> 2DUP/= 2DUP/= 2DUP/>= 2DUP/=< 2DUP/U>= 2DUP/U=< ] A[ D0= D0< D= D< DU< ] B= ......................... 0= C[ D0<> D0>= D<> D>= DU>= ] A[ 1 ] B= .......... /STRING C[ 1/STRING ] A[ 0 BL ] B= .............. FILL C[ ERASE BLANK ] A[ @ ] B= ......... EXECUTE C[ PERFORM ] A[ DROP 1 0 -1 FALSE TRUE ] B= ................................................. EXIT C[ DROP/EXIT 1&EXIT 0&EXIT -1&EXIT 0&EXIT -1&EXIT ]
exe-A & exe-Bn ==> exe-Cn
A= exe-A B[ exe-B1 exe-B2 exe-B3 ... ] C[ exe-C1 exe-C2 exe-C3 ... ]
A= DROP B[ SWAP DUP 0 ] C[ DROP/SWAP DROP/DUP DROP/0 ] A= SWAP B[ < > U< U> - OVER MOVE ] C[ > < U> U< SWAP/- TUCK SWAP/MOVE ] A= 2DUP B[ = <> - < > ] C[ 2DUP/= 2DUP/<> 2DUP/- 2DUP/< 2DUP/> ] A= 2DUP B[ U< U> AND OR XOR ] C[ 2DUP/U< 2DUP/U> 2DUP/AND 2DUP/OR 2DUP/XOR ] A= 2DUP/SWAP B[ < > U< U> - ] C[ 2DUP/> 2DUP/< 2DUP/U> 2DUP/U< 2DUP/SWAP/- ]
XBRA[ IF WHILE UNTIL ]
rel-exe rel-exe & XBRA & 0= ==> rel/0BRA & XBRA ==> rel/?BRA
rel-exe rel/0BRA rel/?BRA PAUSE PAUSE/0BRA PAUSE/?BRA 0< 0</0BRA 0</?BRA 0> 0>/0BRA 0>/?BRA = =/0BRA =/?BRA <> <>/0BRA <>/?BRA < </0BRA </?BRA > >/0BRA >/?BRA U< U</0BRA U</?BRA U> U>/0BRA U>/?BRA WITHIN WITHIN/0BRA WITHIN/?BRA - <>/0BRA <>/?BRA AND AND/0BRA AND/?BRA OR OR/0BRA OR/?BRA XOR XOR/0BRA XOR/?BRA ?DUP ?DUP/0BRA ?DUP/?BRA DUP DUP/0BRA DUP/?BRA SWAP SWAP/0BRA SWAP/?BRA CASE? CASE?/0BRA 2DUP/= 2DUP/=/0BRA 2DUP/=/?BRA 2DUP/<> 2DUP/<>/0BRA 2DUP/<>/?BRA 2DUP/- 2DUP/<>/0BRA 2DUP/<>/?BRA 2DUP/< 2DUP/</0BRA 2DUP/</?BRA 2DUP/> 2DUP/>/0BRA 2DUP/>/?BRA 2DUP/>= 2DUP/</?BRA 2DUP/</0BRA 2DUP/=< 2DUP/>/?BRA 2DUP/>/0BRA 2DUP/U< 2DUP/U</0BRA 2DUP/U</?BRA 2DUP/U> 2DUP/U>/0BRA 2DUP/U>/?BRA 2DUP/U>= 2DUP/U</?BRA 2DUP/U</0BRA 2DUP/U=< 2DUP/U>/?BRA 2DUP/U>/0BRA 2DUP/AND 2DUP/AND/0BRA 2DUP/AND/?BRA 2DUP/OR 2DUP/OR/0BRA 2DUP/OR/?BRA 2DUP/XOR 2DUP/XOR/0BRA 2DUP/XOR/?BRA D0= D0=/0BRA D0=/?BRA D0< D0</0BRA D0</?BRA D= D=/0BRA D=/?BRA D< D</0BRA D</?BRA DU< DU</0BRA DU</?BRA
rel-exe rel-exe & XBRA & 0= ==> rel/?BRA & XBRA ==> rel/0BRA
rel-exe rel/?BRA rel/0BRA 0>= 0</?BRA 0</0BRA 0=< 0>/?BRA 0>/0BRA >= </?BRA </0BRA =< >/?BRA >/0BRA U>= U</?BRA U</0BRA U=< U>/?BRA U>/0BRA D0<> D0=/?BRA D0=/0BRA D0>= D0</?BRA D0</0BRA D<> D=/?BRA D=/0BRA D>= D</?BRA D</0BRA DU>= DU</?BRA DU</0BRA
exe-An & exe-Bn ==> exe-Cn
A[ exe-A1 exe-A2 exe-A3 ... ] B[ exe-B1 exe-B2 exe-B3 ... ] C[ exe-C1 exe-C2 exe-C3 ... ]
BRA[ AHEAD ELSE AGAIN REPEAT LEAVE ]
A[ PAUSE PAUSE PAUSE 0 0 ] B[ BRA LOOP +LOOP DO ?DO ] C[ PAUSE/BRA PAUSE/LOOP PAUSE/+LOOP 0DO ?0DO ]
10. Table of Forth words
10.1. Data stack handling
10.1.1. CORE
DROP ( n --) DUP ( n -- n n) SWAP ( n1 n2 -- n2 n1) OVER ( n1 n2 -- n1 n2 n1) ROT ( n1 n2 n3 -- n2 n3 n1) ?DUP ( 0 -- 0 // n -- n n) 2DROP ( n1 n2 --) 2DUP ( n1 n2 -- n1 n2 n1 n2) 2SWAP ( n1 n2 n3 n4 -- n3 n4 n1 n2) 2OVER ( n1 n2 n3 n4 -- n1 n2 n3 n4 n1 n2) DEPTH ( ix -- ix n)
10.1.2. EXT
NIP ( n1 n2 -- n2) TUCK ( n1 n2 -- n2 n1 n2) PICK ( nx .. np .. n0 p -- nx .. np .. n0 np) ROLL ( nx .. np .. n0 p -- nx .. np-1 .. n0 np)
10.2. Return stack handling
10.2.1. CORE
EXIT ( -- R: i --) EXECUTE ( cfa -- R: -- i) >R ( n -- R: -- n) R> ( -- n R: n --) R@ ( -- n R: n -- n)
10.2.2. EXT
2>R ( n1 n2 -- R: n1 n2) 2R> ( -- n1 n2 R: n1 n2) 2R@ ( -- n1 n2 /R: n1 n2 -- n1 n2)
10.2.3. DOUBLE EXT
2ROT ( n1 n2 n3 n4 n5 n6 -- n3 n4 n5 n6 n1 n2)
10.3. Arithmetic calculation
10.3.1. CORE
= ( n1 n2 -- f) U< ( n1 n2 -- f) < ( n1 n2 -- f) > ( n1 n2 -- f) 0= ( n -- f) 0< ( n -- f) AND ( n1 n2 -- n3) OR ( n1 n2 -- n3) XOR ( n1 n2 -- n3) INVERT ( n1 -- n2) LSHIFT ( n1 n2 -- n3) RSHIFT ( n1 n2 -- n3) + ( n1 n2 -- n3) - ( n1 n2 -- n3) NEGATE ( n -- n) ABS ( n1 -- n2) MIN ( n1 n2 -- n3) MAX ( n1 n2 -- n3)
10.3.2. EXT
<> ( n1 n2 -- f) U> ( n1 n2 -- f) 0<> ( n -- f) 0> ( n -- f) WITHIN ( n1 n2 n3 -- f)
10.3.3. DOUBLE
D= ( d1 d2 -- f) D+ ( d1 d2 -- d3) DNEGATE ( d1 -- d2) DABS ( d1 -- d2) D< ( d1 d2 -- f) D0= ( d1 -- f) D0< ( d1 -- f) DMIN ( d1 d2 -- d3) DMAX ( d1 d2 -- d3) M+ ( d1 n -- d2) D- ( d1 d2 -- d3)
10.3.4. EXT
DU< ( d1 d2 -- f)
10.4. Arithmetic constants
10.4.1. CORE
ALIGNED ( a -- a) 1+ ( n -- n+1) 1- ( n -- n-1) 2* ( n -- n*2) 2/ ( n -- n/2) CELL+ ( a -- a+) CELLS ( n -- n+) CHAR+ ( a -- a+) CHARS ( n -- n+) S>D ( n -- d) >BODY ( cfa -- a2)
10.4.2. EXT
TRUE ( -- -1) FALSE ( -- 0)
10.4.3. DOUBLE
D>S ( d -- n) D2* ( d1 -- d2) D2/ ( d1 -- d2)
10.4.4. STRING
/STRING ( a1 u1 n1 -- a1+ u1-)
10.5. Memory access
10.5.1. CORE
C@ ( a -- b) C! ( b a --) @ ( a -- n) ! ( n a --) 2@ ( a -- d) 2! ( d a --) +! ( n a -) MOVE ( a1 a2 n --) FILL ( a n b --) COUNT ( a$ -- a+1 n)
10.5.2. EXT
ERASE ( a n --)
10.5.3. STRING
CMOVE ( a1 a2 n --) CMOVE> ( a1 a2 n --) BLANK ( a n --) -TRAILING ( a1 n1 -- a1 n2) COMPARE ( a1 n1 a2 n2 -- -1/0/1) SEARCH ( a1 n1 a2 n2 -- a3 n3 f)
10.6. Enhanced arithmetics
10.6.1. CORE
UM/MOD ( d n1 -- u2/rem u3/div) FM/MOD ( d n1 -- n2 n3) SM/REM ( d n1 -- n2 n3) UM* ( u1 u2 -- ud) M* ( n1 n2 -- d) \ missing /MOD ( n1 n2 -- n3 n4) / ( n1 n2 -- n3) MOD ( n1 n2 -- n3) * ( n1 n2 -- n3) */MOD ( n1 n2 n3 -- n4 n5) */ ( n1 n2 n3 -- n4)
10.6.2. DOUBLE
M*/ ( d1 n1 n2 -- d2)
10.7. System values
10.7.1. CORE
BL ( -- 32) >IN ( -- a) SOURCE ( -- a n) STATE ( -- a) BASE ( -- a)
10.7.2. SEARCH
FORTH-WORDLIST ( -- wid)
10.7.3. BLOCK
BLK ( -- a)
10.7.4. BLOCK EXT
SCR ( -- a)
10.7.5. FILE
BLOCK-FID ( -- a) SOURCE-ID ( -- n)
10.8. Value access
10.8.1. CORE
HERE ( -- a) ALLOT ( n --) ALIGN ( --) C, ( b --) , ( n --)
10.8.2. EXT
PAD ( -- a) COMPILE, ( cfa --) UNUSED ( -- u) ENVIRONMENT? ( -- 0)
10.9. Number conversion
10.9.1. CORE
DECIMAL ( --) >NUMBER ( d a n -- d a+ n-) <# ( --) HOLD ( b --) SIGN ( n --) # ( d1 -- d2) #S ( d1 -- d2) #> ( d -- a n)
10.9.2. EXT
HEX ( --)
10.10. Output
10.10.1. CORE
TYPE ( a n --) EMIT ( b --) SPACE ( --) SPACES ( n --) CR ( --) . ( n --) U. ( n --)
10.10.2. EXT
.( ( --) .R ( n1 n2 --) U.R ( n1 n2 --)
10.10.3. DOUBLE
D. ( d --) D.R ( d n --)
10.10.4. FACILITY EXT
EMIT? ( -- f) PAGE ( --) AT-XY ( n1 n2 --)
10.11. Search order
10.11.1. CORE
FIND ( $a -- a 0 , cfa -2/-1/1/2)
10.11.2. SEARCH
SEARCH-WORDLIST ( a n wid -- 0 , cfa -2/-1/1/2) GET-ORDER ( -- widn..wid1 n) SET-ORDER ( widn..wid1 n --) GET-CURRENT ( -- wid) SET-CURRENT ( wid --) DEFINITIONS ( --)
10.11.3. EXT
ALSO ( --) PREVIOUS ( --) FORTH ( --) ONLY ( --)
10.11.4. TOOLS EXT
ASSEMBLER ( --) EDITOR ( --)
10.12. Input & parsing
10.12.1. CORE and FILE
KEY ( -- b) ACCEPT ( a n1 -- n2) WORD ( b -- a$) CHAR ( -- b) ' ( -- cfa) ( ( --) S" ( -- a n) \ ( --) PARSE ( b -- a n) RESTORE-INPUT ( nx ... n1 x -- f) SAVE-INPUT ( -- nx ... n1 x) REFILL ( -- f)
10.12.2. FACILITY EXT
KEY? ( -- f) EKEY? ( -- f) EKEY ( -- b)
10.12.3. TOOLS EXT
[THEN] ( n --) [ELSE] ( n -- n) [IF] ( f -- n)
10.13. Error handling
10.13.1. ERROR
CATCH ( cfa -- 0 / #-throw) THROW ( # --)
10.14. Blocks handling
10.14.1. BLOCK
BUFFER ( n -- a) BLOCK ( n -- a) UPDATE ( --) SAVE-BUFFERS ( --) FLUSH ( --)
10.14.2. BLOCK EXT
EMPTY-BUFFERS ( --) LIST ( n --)
10.15. File handling
10.15.1. FILE
R/W ( -- n) R/O ( -- n) FILE-POSITION ( hdl -- d err#) REPOSITION-FILE ( d hdl -- err#) FILE-SIZE ( hdl -- d err#) RESIZE-FILE ( d hdl -- err#) CLOSE-FILE ( hdl -- err#) OPEN-FILE ( a n1 n2 -- hdl err#) CREATE-FILE ( a n1 n2 -- hdl err#) DELETE-FILE ( a n - err#) READ-FILE ( a n1 hdl -- n2 err#) WRITE-FILE ( a n hdl -- err#) READ-LINE ( a n hdl -- n f err#) WRITE-LINE ( a n hdl -- err#)
10.15.2. EXT
FLUSH-FILE ( hdl -- err#) RENAME-FILE ( a1 n1 a2 n2 -- err#) FILE-STATUS ( a1 n1 -- n2 err#)
10.16. Loop engine
10.16.1. CORE
QUIT ( -- /R: ix -- iy) ABORT ( ix -- iy /R: ix -- iy) EVALUATE ( a n --)
10.16.2. BLOCK EXT
THRU ( u1 u2 --) LOAD ( n --)
10.16.3. FILE
INCLUDE-FILE ( hdl --) INCLUDED ( a n --)
10.17. Code compiler
10.17.1. CORE
] ( --) [ ( --) : ( -- /R: -- i /C: -- /"name") DOES> ( /Runtime: -- a /R: i -- ) ( /Generation: -- /R: i -- ) / /Compile: -- /R: -- i) ; ( -- /R: i -- /C: --) RECURSE ( --) IMMEDIATE ( --) LITERAL ( -- n /C: n --) [CHAR] ( -- n /C: -- /"name") ['] ( -- n /C: -- /"name") POSTPONE ( -- /C: -- /"name") S" ( /Interpret: -- a n) ( /Runtime: -- a n) ( /Compile: -- /"string") ." ( -- /C: -- /"string") ABORT" ( -- /C: -- /"string")
10.17.2. EXT
:NONAME ( -- /R: -- i /C: -- cfa) C" ( -- $a /C: -- /"string")
10.17.3. DOUBLE
2LITERAL ( -- d /C: d --)
10.17.4. TOOLS EXT
CODE ( -- n /"name")
10.17.5. LOCAL
(LOCAL) ( /C: a n/0 --) LOCAL| ( /C: -- /"name name ... |") TO ( n -- /C: -- /"name")
10.18. Flow of control
10.18.1. CORE
IF ( f -- /C: -- a) THEN ( -- /C: a --) ELSE ( -- /C: a1 -- a2) BEGIN ( -- /C: -- a) UNTIL ( f -- /C: a --) WHILE ( f -- /C: a1 -- a2 a1) REPEAT ( -- /C: a1 a2 --) DO ( n2 n1 -- /R: ix/nodo -- iy/do /C: -- a) LOOP ( -- /R: iy/do -- [iy/do]|[ix/nodo] /C: a --) +LOOP ( n -- /R: iy/do -- [iy/do]|[ix/nodo] /C: a --) I ( -- n /R: iy/do -- iy/do) UNLOOP ( -- /R: iy/do -- ix/nodo) LEAVE ( -- /R: iy/do -- ix/nodo)
10.18.2. EXT
AGAIN ( -- /C: a --) ?DO ( n2 n1 -- /R: ix/nodo -- [ix/nodo]|[iy/do] /C: -- a) J ( -- n /R: ix/dodo -- ix/dodo)
10.18.3. TOOLS EXT
AHEAD ( -- /C: -- a) CS-PICK ( ax..a1 x -- ax..a1 ax) CS-ROLL ( ax ax-1..a1 x -- ax-1..a1 ax)
10.19. Data compiler
10.19.1. CORE
CREATE ( -- /"name" /Run: -- a) CONSTANT ( n -- /"name" /Run: -- n) VARIABLE ( -- /"name" /Run: -- a)
10.19.2. EXT
VALUE ( n -- /"name" /Run: -- n) TO ( n -- /"name" /C: -- /"name") MARKER ( -- /"name")
10.19.3. DOUBLE
2CONSTANT ( d -- /"name" /Run: -- d) 2VARIABLE ( -- /"name" /Run: -- a)
10.19.4. SEARCH
WORDLIST ( -- wid)
10.20. Tools
10.20.1. TOOLS EXT
DUMP ( a n --) ? ( a --) .S ( --) WORDS ( -- /"char") SEE ( -- /"name") BYE ( --)
10.20.2. SEARCH EXT
ORDER ( --)
10.20.3. FACILITY EXT
MS ( n --) TIME&DATE ( -- n1 n2 n3 n4 n5 n6)
10.20.4. MEMORY
ALLOCATE ( n -- a err#) FREE ( a -- err#) RESIZE ( a n -- a err#)