THIS DOCUMENT IS A WORK IN PROGRESS MG's Davex Forth is a Forth system implementing the Forth 2012 Core word set. This implementation runs under the Apple II Davex shell. It requires a version of Davex that implements the xgetln2 call, which is documented on the project page, but does not actually exist. You may contact me to get an experimental fork of Davex that does implement it. Additionally, the following are implemented: * The Exception word set. * The following words from the Core Extensions word set: .( .R U.R 2>R 2R> 2R@ :NONAME AGAIN BUFFER: C" COMPILE, DEFER DEFER! DEFER@ ERASE FALSE HEX MARKER NIP PAD PARSE PARSE-NAME PICK REFILL RESTORE-INPUT SAVE-INPUT SOURCE-ID TO TRUE TUCK U> UNUSED VALUE WITHIN \ * The following words from the Double Number word set: DABS DNEGATE D. D.R * The Facility word set. * The following words from the Programming-Tools word set: .S ? WORDS * The following words from the Programming-Tools extension word set: BYE STATE * The following words from the String word set: BLANK * Words supporting the Apple II+ProDOS+Davex environment (documented below) Implementation-defined options (Forth 2012 4.1.1): * No address alignment is required for cells or characters. * EMIT sends non-printing characters to the output device. * ACCEPT allows all editing that Davex allows, except for history. * The character set is the Apple II normal character set. Characters are stored high-bit OFF. * There are no charater set extensions. * Control characters match a space character in PARSE-NAME only. * The control-flow stack is implemented on the parameter stack as addresses to be resolved later by words that consume them. * Digits larger than 35 convert to lower-case letters. If BASE is larger than 35, number parsing becomes case-sensitive. * After input terminates, the cursor is on the beginning of the next line. If no exception occurs, after the line is executed, the system will display the sytem prompt. * When an exception occurs outside of CATCH, the system will display the exception number, will forget any current word being defined, and resume user input through QUIT. * The input line terminator is the carriage return. * The maximum size of a counted string is 255 characters. * The maximum size of a parsed string is limited by memory for PARSE and PARSE-NAME, and 34 characters for WORD. * The maximum size of a definition name is 16 characters. * ENVIRONMENT? never returns anything but false. * The user input device is the keyboard unless redirected by Davex. * The user output device is the screen unless redirected by Davex. * The dictionary starts at 256 bytes beyond the lowest memory allowed by DaveX and works its way up. * An address unit contains 8 bits. * Numbers are 16-bits with the sign (if used) in the high bit. Numbers are stored little-endian. Arithmetic is 16-bit except for mixed-precision. No 32-bit by 32-bit division is implemented. * Ranges: n: -32768..32767 +n: 0..32767 u: 0..65535 d: -2147483648..2147483647 +d: 0..2147483647 ud: 0..4294967295 * There are no read-only data space regions. * The buffer for WORD is 35 bytes and is shared with the pictured numeric output. The buffer will move with the dictionary end. * One cell is two address units (16 bits total). * One character is one address unit (8 bits total). * The keyboard terminal input buffer is 252 bytes. * The pictured numeric output string buffer is 35 bytes and shared with WORD. The buffer will move with the dictionary end. * The size of the PAD is 128 bytes. The PAD will move with the dictionary end and it usable size will shrink by one byte for each byte that UNUSED is less than 179. If PAD is used under this circumstance the behavior is undefined. * The system is not case-sensitive when finding dictionary names. * The system prompt is either '[OK]' in the compilation state, or 'OK' in the interpretation state, and is displayed after the previous input is evaluated successfully. * Division rounding is floored by default, but /MOD and M/MOD are deferred words that may be used to change the rounding of those and their derived single- and mixed-precision words, respectively. * STATE takes the value 1 when compiling a definition before any DOES>, and 2 after DOES>. * Integer overflow is truncated to the low bits, except in UM/MOD and SM/REM (and derived operations) where result overthrow results in an exception. * The current definiton may be found after DOES>. Ambiguous conditions (Forth 2012 4.1.2): General: * When a parsed name is neither a dictionary word nor a number, an exception is thrown. * When a definition name exceeds the maximum allowed length, an exception is thrown. * When addressing a region not listed in the data space, the system allows the access with the consequences being left as an exercise for the programmer. * Passing incorrect argument types results in the argument being used as if it were the expected type, possibly causing undefined behavior. * An execution token may be found for a compile-only word. Executing it via EXECUTE outside of the compilation context results in undefined behavior. * Dividing by zero throws an exception. * Data stack overflow throws an exception. Return stack overflow results in undefined behavior. * Insufficient space for loop-control variables results in undefined behavior. * Insufficient space in the dictionary results in undefined behavior. * Interpreting a word with undefined interpretation semantics throws an exception. * Modifying the contents of the input buffer may result in undefined behavior. Modifying the contents of a compiled string literal is allowed but it cannot be changed in size. The change is permanent within the lifetime of the program. See below for interpreted string literals. * Overflowing the pictured numeric string output buffer may collide with the end of the dictionary. * Overflowing a parsed string with WORD throws an exception. PARSE and PARSE-NAME effectively allow any length string to be parsed up to the end of the the line or input buffer. * Producing a number out of range results in overflow and truncation of the result *except* when mixed-precision division overflows an exception is thrown. * Data stack undeflow throws an exception. Return stack underflow results in undefined behavior. * Unexpected end of the input buffer while parsing a name returns a zero- length string. Specific: * >IN past the size of the input buffer results in termination of parsing. * RECURSE after DOES> results in recursion to the definition being compiled that contains the DOES>. * RESTORE-INPUT requires the current input source to be the same that was used during SAVE-INPUT or undefined behavior results. * Data space containing definitions may only be de-allocated by a MARKER or the behavior is undefined. * No ambiguous conditions result from alignment requirements (there are none). * The data space pointer cannot be misaligned, alignment is not required. * PICK with insufficient stack throws an exception. * Loop control parameters unavailable results in undefined behavior. * Executing IMMEDIATE affects the last definition with a name. * TO relies on >BODY, if >BODY cannot be used on the word, an exception is thrown. That being said, all words defined by CREATE, VALUE, CONSTANT, :, :NONAME, DEFER and their derivatives have a body. This means that TO may modify the first execution token within a colon definition. It can also be used to alter a (non-system) CONSTANT or the target of DEFER. * When name is not found by POSTPONE, [COMPILE], etc., an exception is thrown and the current definition being compiled is discarded. * If parameters are not of the same type in DO, the loop proceeds as if they were the same type. * POSTPONE, [COMPILE], etc. applied to TO result in TO's execution token being compiled, making the word a parsing word. * WORD is limited to 34 chars + length, which is less than the maximum length of a counted string. An exception will be thrown if the parsed word exceeds the maximum. * If u is greater than the number of bits in a cell for LSHIFT and RSHIFT, the result will be zero. * With regards to >BODY and DOES>, all secondary words have a body. DOES> will alter any secondary unless it was created with DEFER. * Pictured numeric output words used outside of <# and #>, but before any <# may write to unintended locations in memory, resulting in undefined behavior. It is generally safe to use them immediately after the #>, but the c-addr,u pair returned by #> will no longer be valid. * Accessing an unassigned deferred word throws an exception. * Attempting to assign an xt to a word not defined by DEFER throws an exception, when using DEFER! and derivatives. * POSTPONE, [COMPILE], etc. used to resolve a deferred word results in undefined behavior unless the deferred word is declared IMMEDIATE. * S\" is not implemented, so \x not followed by two hexadecimal digits is not applicable. * Similarly, a \ before any character not defined for S\" is not applicable. Other system documentation (Forth 2012 4.1.3) * No non-standard words use PAD. * Terminal facilities are the same as those provided by Davex. * Program space available is about 1.5K. * The return stack is 128 cells, and is implemented in the 6502 stack. Some cells are used by the host system software. * The data stack is 128 cells. The data stack is split, the low unit and high unit of any cell on the stack are not adjacent in memory. * The system dictionary space is approximately 8K. Non-standard words included: COLD ( x1..xn -- ): Restart the interpreter, resetting the dictionary. RDROP ( r: x -- ): drop the top of the return stack -ROT: rotate the opposite direction as ROT LAST: return the address of the last named dictionary entry S/REM: explicit towards-zero 16-bit division. F/MOD: explicit floored 16-bit division. M/MOD: mixed-precision division defaulting to floored behavior. Used for calculations by other system words, may be changed to towards-zero division using ' SM/REM ' M/MOD DEFER! XKEY ( c1 -- c2 ): use Davex to read a key with c1 as the character under the cursor. MAXLEN ( -- u ): return maximum size that can be requested via ACCEPT. X3U. ( d -- ): print an unsigned integer of up to 24 bits, in base 10, via Davex. MESSAGE ( n -- ): prints "Msg #" followed by n. Can be replaced with something more verbose using DEFER! ABORT!: like ABORT but an IMMEDIATE word. 0SP: empty the parameter stack CATBUFF: return Davex CATBUFF address. FBUFF, FBUFF2, FBUFF3: return the address of the respected Davex buffer. Each is 512 bytes. .FTYPE (u -- ): Use Davex to print ProDOS file type. .ACCESS (u -- ): use Davex to print ProDOS access bits. .SD (u -- ): use Davex to print ProDOS slot and drive. CSTYPE: use Davex to print a counted string. CS+CS ( c-addr1 c-addr2 -- ): append counted string c-addr2 to c-addr1. CS+ ( c-addr char -- ): append character char to counted string c-addr CS/- ( c-addr -- ): remove ProDOS last path component from counted string CS+/ ( c-addr -- ): append a / to counted string c-addr, but only if it does not already end with one. CSMOVE ( c-addr1 c-addr2 ): copy counted string c-addr1 to c-addr2. PLACE ( c-addr1 u c-addr2 ): place string described by c-addr,u as a counted string at c-addr2 BUILD_LOCAL (c-addr -- c-addr'): call Davex xbuild_local REDIRECT? ( -- f ): Return Davex input or output are redirected, b0=1 if input b1=1 if output. +REDIRECT, -REDIRECT: affect DaveX I/O redirection. U% (u1 u2 -- u): use Davex to calculate the percentage of u1 that u2 is. 3U% (d1 d2 -- u): use Davex to calculate the percentage of d1 that d2 is, up to 24-bit. Y/N ( -- f ): use Davex to ask "? (y/n)" returning true if Y was pressed. Y/N2 ( u -- f ): u is either 'y' or 'n'. Perform as Y/N above, but use u as the default if space or return are pressed. BELL: sound the Davex bell as configured by the user. .DATE ( u -- ): use Davex to print a ProDOS date word. .TIME ( u -- ): use Davex to print a ProDOS time word. .P8_ERR ( u -- ): use Davex to print a ProDOS error message.