diff options
author | Pedro F. Giffuni <pfg@FreeBSD.org> | 2015-05-12 03:27:06 +0000 |
---|---|---|
committer | Pedro F. Giffuni <pfg@FreeBSD.org> | 2015-05-12 03:27:06 +0000 |
commit | f4e75c6395310fa4b119d3eaa9a4a9f8913df200 (patch) | |
tree | 2b015c205d81fa2431f0c36d7d9e903088a56d1c /doc/source | |
parent | be98e1ae3decabdd852fbe6496166aaa9acfbf9e (diff) |
Notes
Diffstat (limited to 'doc/source')
-rw-r--r-- | doc/source/api.ht | 250 | ||||
-rw-r--r-- | doc/source/debugger.ht | 157 | ||||
-rw-r--r-- | doc/source/dpans.ht | 589 | ||||
-rw-r--r-- | doc/source/ficl.ht | 1257 | ||||
-rw-r--r-- | doc/source/generate.py | 244 | ||||
-rw-r--r-- | doc/source/index.ht | 244 | ||||
-rw-r--r-- | doc/source/license.ht | 47 | ||||
-rw-r--r-- | doc/source/links.ht | 156 | ||||
-rw-r--r-- | doc/source/locals.ht | 133 | ||||
-rw-r--r-- | doc/source/oop.ht | 1224 | ||||
-rw-r--r-- | doc/source/parsesteps.ht | 234 | ||||
-rw-r--r-- | doc/source/releases.ht | 1003 | ||||
-rw-r--r-- | doc/source/upgrading.ht | 349 |
13 files changed, 5887 insertions, 0 deletions
diff --git a/doc/source/api.ht b/doc/source/api.ht new file mode 100644 index 000000000000..599ba9e16b14 --- /dev/null +++ b/doc/source/api.ht @@ -0,0 +1,250 @@ +<? +ficlPageHeader("ficl api") + +ficlAddToNavBarAs("API") + + +def entrypoint(prototype): + print "<p><dt>\n" + "<code>" + prototype + "</code>\n<dd>\n" +?> + + + +<? ficlHeader1("Quick Ficl Programming Concepts Overview") ?> + + +A Ficl <i>dictionary</i> is equivalent to the FORTH "dictionary"; it is where words are stored. +A single dictionary has a single <code>HERE</code> pointer. +<p> + +A Ficl <i>system information</i> structure is used to change default values used +in initializing a Ficl <i>system</i>. +<p> + +A Ficl <i>system</i> contains a single <i>dictionary</i>, and one or more <i>virtual machines</i>. +<p> + +A Ficl <i>stack</i> is equivalent to a FORTH "stack". Ficl has three stacks: +<ul> + +<li> +The <i>data</i> stack, where integer arguments are stored. + +<li> +The <i>return</i> stack, where locals and return addresses for subroutine returns are stored. + +<li> +The <i>float</i> stack, where floating-point arguments are stored. (This stack +is only enabled when <code>FICL_WANT_FLOAT</code> is nonzero.) +</ul> + +<p> + +A Ficl <i>virtual machine</i> (or <i>vm</i>) represents a single running instance of the Ficl interpreter. +All virtual machines in a single Ficl system see the same dictionary. +<p> + +<? ficlHeader2("Quick Ficl Programming Tutorial") ?> + +Though Ficl's API offers a great deal of flexibility, most programs +incorporating Ficl simply use it as follows: + +<ol> + +<li> +Create a single <code>ficlSystem</code> using <code>ficlSystemCreate(NULL)</code>. + +<li> +Add native functions as necessary with <code>ficlDictionarySetPrimitive()</code>. + +<li> +Add constants as necessary with <code>ficlDictionarySetConstant()</code>. + +<li> +Create one (or more) virtual machine(s) with <code>ficlSystemCreateVm()</code>. + +<li> +Add one or more scripted functions with <code>ficlVmEvaluate()</code>. + +<li> +Execute code in a Ficl virtual machine, usually with <code>ficlVmEvaluate()</code>, +but perhaps with <code>ficlVmExecuteXT()</code>. + +<li> +At shutdown, call <code>ficlSystemDestroy()</code> on the single Ficl system. + +</ol> + + +<? ficlHeader1("Ficl Application Programming Interface") ?> + +The following is a partial listing of functions that interface your +system or program to Ficl. For a complete listing, see <code>ficl.h</code> +(which is heavily commented). For a simple example, see <code>main.c</code>. +<p> + +Note that as of Ficl 4, the API is internally consistent. +<i>Every</i> external entry point starts with the word +<code>ficl</code>, and the word after that also corresponds +with the first argument. For instance, a word that operates +on a <code>ficlSystem *</code> will be called <code>ficlSystem<i>Something</i>()</code>. + + + + +<dl> + +<? entrypoint("void ficlSystemInformationInitialize(ficlSystemInformation *fsi)") ?> + +Resets a <code>ficlSystemInformation</code> structure to all zeros. +(Actually implemented as a macro.) Use this to initialize a <code>ficlSystemInformation</code> +structure before initializing its members and passing it +into <code>ficlSystemCreate()</code> (below). + +<? entrypoint("ficlSystem *ficlSystemCreate(ficlSystemInformation *fsi)") ?> + +Initializes Ficl's shared system data structures, and creates the +dictionary allocating the specified number of cells from the heap +(by a call to <code>ficlMalloc()</code>). If you pass in a <code>NULL</code> +pointer, you will recieve a <code>ficlSystem</code> using the default +sizes for the dictionary and stacks. + + +<? entrypoint("void ficlSystemDestroy(ficlSystem *system)") ?> + +Reclaims memory allocated for the Ficl system including all +dictionaries and all virtual machines created by +<code>ficlSystemCreateVm()</code>. Note that this will <i>not</i> +automatically free memory allocated by the FORTH memory allocation +words (<code>ALLOCATE</code> and <code>RESIZE</code>). + +<? entrypoint("ficlWord *ficlDictionarySetPrimitive(ficlDictionary *dictionary, char *name, ficlCode code, ficlUnsigned8 flags)") ?> + +Adds a new word to the dictionary with the given +name, code pointer, and flags. To add +<p> + +The <code>flags</code> parameter is a bitfield. The valid +flags are:<ul> + +<li> +FICL_WORD_IMMEDIATE +<li> +FICL_WORD_COMPILE_ONLY +<li> +FICL_WORD_SMUDGED +<li> +FICL_WORD_OBJECT +<li> +FICL_WORD_INSTRUCTION + +</ul> + +For more information on these flags, see <code>ficl.h</code>. + + +<? entrypoint("ficlVm *ficlSystemCreateVm(ficlSystem *system)") ?> + +Creates a new virtual machine in the specified system. + + +<? entrypoint("int ficlVmEvaluate(ficlVm *vm, char *text)") ?> + + the specified C string (zero-terminated) to the given +virtual machine for evaluation. Returns various exception codes (VM_XXXX +in ficl.h) to indicate the reason for returning. Normal exit +condition is VM_OUTOFTEXT, indicating that the VM consumed the string +successfully and is back for more. Calls to <code>ficlVmEvaluate()</code> +can be nested, and +the function itself is re-entrant, but note that a VM is +static, so you have to take reasonable precautions (for example, use one +VM per thread in a multithreaded system if you want multiple threads to +be able to execute commands). + + +<? entrypoint("int ficlVmExecuteXT(ficlVm *vm, ficlWord *pFW)") ?> + +Same as ficlExec, but takes a pointer to a ficlWord instead of a +string. Executes the word and returns after it has finished. If +executing the word results in an exception, this function will +re-throw the same code if it is nested under another ficlExec family +function, or return the exception code directly if not. This function +is useful if you need to execute the same word repeatedly—you +save the dictionary search and outer interpreter overhead. + +<? entrypoint("void ficlFreeVM(ficlVm *vm)") ?> + +Removes the VM in question from the system VM list and deletes +the memory allocated to it. This is an optional call, since +ficlTermSystem will do this cleanup for you. This function is +handy if you're going to do a lot of dynamic creation of VMs. + +<? entrypoint("ficlVm *ficlNewVM(ficlSystem *system)") ?> + +Create, initialize, and return a VM from the heap using +ficlMalloc. Links the VM into the system VM list for later reclamation +by ficlTermSystem. + +<? entrypoint("ficlWord *ficlSystemLookup(ficlSystem *system, char *name)") ?> + +Returns the address of the specified word in the main dictionary. +If no such word is found, it returns <code>NULL</code>. +The address is also a valid execution token, and can be used in a call to <code>ficlVmExecuteXT()</code>. + +<? entrypoint("ficlDictionary *ficlSystemGetDictionary(ficlSystem *system)<br>ficlDictionary *ficlVmGetDictionary(ficlVm *system)") ?> + +Returns a pointer to the main system dictionary. + + +<? entrypoint("ficlDictionary *ficlSystemGetEnvironment(ficlSystem *system)") ?> + +Returns a pointer to the environment dictionary. This dictionary +stores information that describes this implementation as required by the +Standard. + + + + +<? entrypoint("ficlDictionary *ficlSystemGetLocals(ficlSystem *system)") ?> + +Returns a pointer to the locals dictionary. This function is +defined only if <code>FICL_WANT_LOCALS</code> is non-zero (see <code>ficl.h</code>). +The locals dictionary is the symbol table for +<a href="locals.html">local variables</a>. + + +</dl> + + +<? ficlHeader1("Ficl Compile-Time Constants") ?> + +There are a lot of preprocessor constants you can set at compile-time +to modify Ficl's runtime behavior. Some are required, such as telling +Ficl whether or not the local platform supports double-width integers +(<code>FICL_PLATFORM_HAS_2INTEGER</code>); +some are optional, such as telling Ficl whether or not to use the +extended set of "prefixes" (<code>FICL_WANT_EXTENDED_PREFIXES</code>). +<p> + +The best way to find out more about these constants is to read <code>ficl.h</code> +yourself. The settings that turn on or off Ficl modules all start with +<code>FICL_WANT</code>. The settings relating to functionality available +on the current platform all start with <code>FICL_PLATFORM</code>. +<p> + + + +<? ficlHeader2("<code>ficllocal.h</code>") ?> + +One more note about constants. Ficl now ships with a standard place for +you to tweak the Ficl compile-time preprocessor constants. +It's a file called <code>ficllocal.h</code>, and we guarantee that it +will always ship empty (or with only comments). We suggest that you +put all your local changes there, rather than editing <code>ficl.h</code> +or editing the makefile. That should make it much easier to integrate +future Ficl releases into your product—all you need do is preserve +your tweaked copy of <code>ficllocal.h</code> and replace the rest. + + + +<? ficlPageFooter() ?> diff --git a/doc/source/debugger.ht b/doc/source/debugger.ht new file mode 100644 index 000000000000..e2187f9b2670 --- /dev/null +++ b/doc/source/debugger.ht @@ -0,0 +1,157 @@ +<? +ficlPageHeader("ficl debugger") + +ficlAddToNavBarAs("Debugger") + +?> + +<p>Ficl includes a simple step debugger for colon definitions +and <code>DOES></code> words. + + +<? ficlHeader1("Using The Ficl Debugger") ?> + + +To debug a word, set up the stack with any parameters the word requires, +then execute: +<pre><b>DEBUG <i>your-word-name-here</i></b></pre> +<p> + +If the word is unnamed, or all you have is an execution token, +you can instead use <code>DEBUG-XT</code></b> +<p> + +The debugger invokes <tt>SEE</tt> on the word which prints a crude source +listing. It then stops at the first instruction of the definition. There are +six (case insensitive) commands you can use from here onwards: + +<dl> + +<dt> +<b>I</b> (step <b>I</b>n) +<dd>If the next instruction is a colon defintion or does> word, steps into +that word's code. If the word is a primitive, simply executes the word. + +<dt> +<b>O</b> (step <b>O</b>ver) +<dd> +Executes the next instruction in its entirety. + +<dt> +<b>G</b> (<b>G</b>o) +<dd> +Run the word to completion and exit the debugger. + +<dt> +<b>L</b> (<b>L</b>ist) +<dd> +Lists the source code of the word presently being stepped. + +<dt> +<b>Q</b> (<b>Q</b>uit) +<dd> +Abort the word and exit the debugger, clearing the stacks. + +<dt> +<b>X</b> (e<b>X</b>ecute) +<dd> +Interpret the remainder of the line as Ficl words. Any change +they make to the stacks will be preserved when the debugged word +continues execution. +Any errors will abort the debug session and reset the VM. Usage example: +<pre> +X DROP 3 \ change top argument on stack to 3 +</pre> + +</dl> + + +Any other character will prints a list of available debugger commands. + + +<? ficlHeader2("The <code>ON-STEP</code> Event") ?> + +If there is a defined word named <code>ON-STEP</code> when the debugger starts, that +word will be executed before every step. Its intended use is to display the stacks +and any other VM state you find interesting. The default <code>ON-STEP</code> is: +<p> + +<pre> +: ON-STEP ." S: " .S-SIMPLE CR ; +</pre> + +If you redefine <code>ON-STEP</code>, we recommend you ensure the word has no +side-effects (for instance, adding or removing values from any stack). + + + +<? ficlHeader3("Other Useful Words For Debugging And <code>ON-STEP</code>") ?> + +<dl> + +<dt> +<code>.ENV ( -- )</code> +<dd> +Prints all environment settings non-destructively. + +<dt> +<code>.S ( -- )</code> +<dd> +Prints the parameter stack non-destructively in a verbose format. + +<dt> +<code>.S-SIMPLE ( -- )</code> +<dd> +Prints the parameter stack non-destructively in a simple single-line format. + +<dt> +<code>F.S ( -- )</code> +<dd> +Prints the float stack non-destructively (only available if <code>FICL_WANT_FLOAT</code> is enabled). + +<dt> +<code>R.S ( -- )</code> +<dd> +Prints a represention of the state of the return stack non-destructively. + + + +</dl> + +<? ficlHeader1("Debugger Internals") ?> + +<p> +The debugger words are mostly located in source file <code>tools.c</code>. There are +supporting words (<code>DEBUG</code> and <code>ON-STEP</code>) in <code>softcore.fr</code> as well. +There are two main words that make the debugger go: <code>debug-xt</code> and <code>step-break</code>. +<code>debug-xt</code> takes the execution token of a word to debug (as returned by <code>'</code> for example) , +checks to see if it is debuggable (not a primitive), sets a breakpoint at its +first instruction, and runs <code>see</code> on it. To set a breakpoint, +<code>debug-xt</code> +replaces the instruction at the breakpoint with the execution token of <code>step-break</code>, and +stores the original instruction and its address in a static breakpoint +record. To clear the breakpoint, <code>step-break</code> simply replaces the original +instruction and adjusts the target virtual machine's instruction pointer +to run it. + +<p> + +<code>step-break</code> is responsible for processing debugger commands and setting +breakpoints at subsequent instructions. + + +<? ficlHeader1("Future Enhancements") ?> + +<dl> + +<li> +The debugger needs to exit automatically when it encounters the end of the word +it was asked to debug. (Perhaps this could be a special kind of breakpoint?) + +<li>Add user-set breakpoints. + +<li>Add "step out" command. +</dl> + + +<? ficlPageFooter() ?> diff --git a/doc/source/dpans.ht b/doc/source/dpans.ht new file mode 100644 index 000000000000..cfd957e269a6 --- /dev/null +++ b/doc/source/dpans.ht @@ -0,0 +1,589 @@ +<? +ficlPageHeader("ficl standards compliance") + +ficlHeader1("ANS Required Information") + +ficlAddToNavBarAs("ANS") + +?> + + +The following documentation is necessary to comply for Ficl +to comply with the DPANS94 standard. It describes what areas +of the standard Ficl implements, what areas it does not, and +how it behaves in areas undefined by the standard. + +<blockquote> + +<? ficlHeader2("ANS Forth System") ?> + +<b> + +Providing names from the Core Extensions word set +<br> + +Providing names from the Double-Number word set +<br> + +Providing the Exception word set +<br> + +Providing the Exception Extensions word set +<br> + +Providing the File-Access word set +<br> + +Providing the File-Access Extensions word set +<br> + +Providing names from the Floating-Point word set +<br> + +Providing the Locals word set +<br> + +Providing the Locals Extensions word set +<br> + +Providing the Memory Allocation word set +<br> + +Providing the Programming-Tools word set +<br> + +Providing names from the Programming-Tools Extensions word set +<br> + +Providing the Search-Order word set +<br> + +Providing the Search-Order Extensions word set +<br> + +Providing names from the String Extensions word set +<br> + +</b> + + +<? +def entry(heading): + print "<dt><b>\n" + heading + "\n</b><dd>\n" + +?> + + +<? ficlHeader2("Implementation-defined Options") ?> + +The implementation-defined items in the following list represent +characteristics and choices left to the discretion of the implementor, +provided that the requirements of the Standard are met. A system shall +document the values for, or behaviors of, each item. + +<dl> + +<? entry("aligned address requirements (3.1.3.3 Addresses)") ?> + +System dependent. You can change the default address alignment by +defining <code>FICL_ALIGN</code> on your compiler's command line, +or in <code>platform.h</code>. +The default value is set to 2 in <code>ficl.h</code>. +This causes dictionary entries and <code>ALIGN</code> and +<code>ALIGNED</code> to align on 4 byte +boundaries. To align on 2<b><sup>n</sup></b> byte boundaries, +set <code>FICL_ALIGN</code> to <b>n</b>. + + +<? entry("behavior of 6.1.1320 EMIT for non-graphic characters") ?> + +Depends on target system, C runtime library, and your +implementation of <code>ficlTextOut()</code>. + + +<? entry("character editing of 6.1.0695 ACCEPT and 6.2.1390 EXPECT") ?> + +None implemented in the versions supplied in <code>primitives.c</code>. +Because <code>ficlEvaluate()</code> is supplied a text buffer +externally, it's up to your system to define how that buffer will +be obtained. + + +<? entry("character set (3.1.2 Character types, 6.1.1320 EMIT, 6.1.1750 KEY)") ?> + +Depends on target system and implementation of <code>ficlTextOut()</code>. + + +<? entry("character-aligned address requirements (3.1.3.3 Addresses)") ?> + +Ficl characters are one byte each. There are no alignment requirements. + + +<? entry("character-set-extensions matching characteristics (3.4.2 Finding definition names)") ?> + +No special processing is performed on characters beyond case-folding. Therefore, +extended characters will not match their unaccented counterparts. + + +<? entry("conditions under which control characters match a space delimiter (3.4.1.1 Delimiters)") ?> + +Ficl uses the Standard C function <code>isspace()</code> to distinguish space characters. + + +<? entry("format of the control-flow stack (3.2.3.2 Control-flow stack)") ?> + +Uses the data stack. + + +<? entry("conversion of digits larger than thirty-five (3.2.1.2 Digit conversion)") ?> + +The maximum supported value of <code>BASE</code> is 36. +Ficl will fail via assertion in function <code>ltoa()</code> of <code>utility.c</code> +if the base is found to be larger than 36 or smaller than 2. There will be no effect +if <code>NDEBUG</code> is defined, however, other than possibly unexpected behavior. + + +<? entry("display after input terminates in 6.1.0695 ACCEPT and 6.2.1390 EXPECT") ?> + +Target system dependent. + + +<? entry("exception abort sequence (as in 6.1.0680 ABORT\")") ?> + +Calls <tt>ABORT</tt> to exit. + + +<? entry("input line terminator (3.2.4.1 User input device)") ?> + +Target system dependent (implementation of outer loop that calls <code>ficlEvaluate()</code>). + + +<? entry("maximum size of a counted string, in characters (3.1.3.4 Counted strings, 6.1.2450 WORD)") ?> + +Counted strings are limited to 255 characters. + + +<? entry("maximum size of a parsed string (3.4.1 Parsing)") ?> + +Limited by available memory and the maximum unsigned value that can fit in a cell (2<sup>32</sup>-1). + + +<? entry("maximum size of a definition name, in characters (3.3.1.2 Definition names)") ?> + +Ficl stores the first 31 characters of a definition name. + + +<? entry("maximum string length for 6.1.1345 ENVIRONMENT?, in characters") ?> + +Same as maximum definition name length. + + +<? entry("method of selecting 3.2.4.1 User input device") ?> + +None supported. This is up to the target system. + + +<? entry("method of selecting 3.2.4.2 User output device") ?> + +None supported. This is up to the target system. + + +<? entry("methods of dictionary compilation (3.3 The Forth dictionary)") ?> + +Okay, we don't know what this means. If you understand what they're asking for here, +please call the home office. + + +<? entry("number of bits in one address unit (3.1.3.3 Addresses)") ?> + +Target system dependent, either 32 or 64 bits. + + +<? entry("number representation and arithmetic (3.2.1.1 Internal number representation)") ?> + +System dependent. Ficl represents a CELL internally as a union that can hold a <code>ficlInteger32</code> +(a signed 32 bit scalar value), a <code>ficlUnsigned32</code> (32 bits unsigned), +and an untyped pointer. No specific byte ordering is assumed. + + +<? entry("ranges for n, +n, u, d, +d, and ud (3.1.3 Single-cell types, 3.1.4 Cell-pair types)") ?> + +System dependent. +Assuming a 32 bit implementation, range for signed single-cell values is [-2<sup>31</sup>, 2<sup>31</sup>-1]. +Range for unsigned single cell values is [0, 2<sup>32</sup>-1]. +Range for signed double-cell values is [-2<sup>63</sup>, 2<sup>63</sup>-1]. +Range for unsigned double cell values is [0, 2<sup>64</sup>-1]. + + +<? entry("read-only data-space regions (3.3.3 Data space)") ?> + +None. + + +<? entry("size of buffer at 6.1.2450 WORD (3.3.3.6 Other transient regions)") ?> + +Default is 255. Depends on the setting of <code>FICL_PAD_SIZE</code> in <code>ficl.h</code>. + + +<? entry("size of one cell in address units (3.1.3 Single-cell types)") ?> + +System dependent, generally 4. + + +<? entry("size of one character in address units (3.1.2 Character types)") ?> + +System dependent, generally 1. + + +<? entry("size of the keyboard terminal input buffer (3.3.3.5 Input buffers)") ?> + +This buffer is supplied by the host program. Ficl imposes no practical limit. + + +<? entry("size of the pictured numeric output string buffer (3.3.3.6 Other transient regions)") ?> + +Default is 255. Depends on the setting of <code>FICL_PAD_SIZE</code> in <code>ficl.h</code>. + + +<? entry("size of the scratch area whose address is returned by 6.2.2000 PAD (3.3.3.6 Other transient regions)") ?> + +Default is 255. Depends on the setting of <code>FICL_PAD_SIZE</code> in <code>ficl.h</code>. + + +<? entry("system case-sensitivity characteristics (3.4.2 Finding definition names)") ?> + +The Ficl dictionary is not case-sensitive. + + +<? entry("system prompt (3.4 The Forth text interpreter, 6.1.2050 QUIT)") ?> + +<code>ok></code> + + +<? entry("type of division rounding (3.2.2.1 Integer division, 6.1.0100 */, 6.1.0110 */MOD, 6.1.0230 /, 6.1.0240 /MOD, 6.1.1890 MOD)") ?> + +Symmetric. + + +<? entry("values of 6.1.2250 STATE when true") ?> + +1. + + +<? entry("values returned after arithmetic overflow (3.2.2.2 Other integer operations)") ?> + +System dependent. Ficl makes no special checks for overflow. + + +<? entry("whether the current definition can be found after 6.1.1250 DOES> (6.1.0450 :)") ?> +No. Definitions are unsmudged after ; only, and only then if no control structure matching problems have been detected. + +</dl> + + +<? ficlHeader2("Ambiguous Conditions") ?> + +<dl> + +<? entry("a name is neither a valid definition name nor a valid number during text interpretation (3.4 The Forth text interpreter)") ?> + +Ficl calls <code>ABORT</code> then prints the name followed by <code>not found</code>. + + +<? entry("a definition name exceeded the maximum length allowed (3.3.1.2 Definition names)") ?> + +Ficl stores the first 31 characters of the definition name, and uses all characters of the name +in computing its hash code. The actual length of the name, up to 255 characters, is stored in +the definition's length field. + + +<? entry("addressing a region not listed in 3.3.3 Data Space") ?> + +No problem: all addresses in Ficl are absolute. You can reach any 32 bit address in Ficl's address space. + + +<? entry("argument type incompatible with specified input parameter, e.g., passing a flag to a word expecting an n (3.1 Data types)") ?> + +Ficl makes no check for argument type compatibility. Effects of a mismatch vary widely depending on the specific problem and operands. + + +<? entry("attempting to obtain the execution token, (e.g., with 6.1.0070 ', 6.1.1550 FIND, etc.) of a definition with undefined interpretation semantics") ?> + +Ficl returns a valid token, but the result of executing that token while interpreting may be undesirable. + + +<? entry("dividing by zero (6.1.0100 */, 6.1.0110 */MOD, 6.1.0230 /, 6.1.0240 /MOD, 6.1.1561 FM/MOD, 6.1.1890 MOD, 6.1.2214 SM/REM, 6.1.2370 UM/MOD, 8.6.1.1820 M*/)") ?> + +Results are target procesor dependent. Generally, Ficl makes no check for divide-by-zero. The target processor will probably throw an exception. + + +<? entry("insufficient data-stack space or return-stack space (stack overflow)") ?> + +With <code>FICL_ROBUST</code> (defined in <code>ficl.h</code>) set to a value of 2 or greater, +most data, float, and return stack operations are checked for underflow and overflow. + + +<? entry("insufficient space for loop-control parameters") ?> + +This is not checked, and bad things will happen. + + +<? entry("insufficient space in the dictionary") ?> + +Ficl generates an error message if the dictionary is too full to create +a definition header. It checks <code>ALLOT</code> as well, but it is possible +to make an unchecked allocation request that will overflow the dictionary. + + +<? entry("interpreting a word with undefined interpretation semantics") ?> + +Ficl protects all ANS Forth words with undefined interpretation semantics from being executed while in interpret state. +It is possible to defeat this protection using ' (tick) and <code>EXECUTE</code> though. + + +<? entry("modifying the contents of the input buffer or a string literal (3.3.3.4 Text-literal regions, 3.3.3.5 Input buffers)") ?> + +Varies depending on the nature of the buffer. The input buffer is supplied by ficl's host function, and may reside +in read-only memory. If so, writing the input buffer can ganerate an exception. +String literals are stored in the dictionary, and are writable. + + +<? entry("overflow of a pictured numeric output string") ?> + +In the unlikely event you are able to construct a pictured numeric string of more +than <code>FICL_PAD_LENGTH</code> characters, the system will be corrupted unpredictably. +The buffer area that holds pictured numeric output is at the end of the virtual machine. +Whatever is mapped after the offending VM in memory will be trashed, along with the heap +structures that contain it. + + +<? entry("parsed string overflow") ?> + +Ficl does not copy parsed strings unless asked to. Ordinarily, a string parsed from the input buffer during +normal interpretation is left in-place, so there is no possibility of overflow. +If you ask to parse a string into the dictionary, as in <code>SLITERAL</code>, you need to have enough +room for the string, otherwise bad things may happen. This is usually not a problem. + + +<? entry("producing a result out of range, e.g., multiplication (using *) results in a value too big to be represented by a single-cell integer (6.1.0090 *, 6.1.0100 */, 6.1.0110 */MOD, 6.1.0570, >NUMBER, 6.1.1561 FM/MOD, 6.1.2214 SM/REM, 6.1.2370 UM/MOD, 6.2.0970 CONVERT, 8.6.1.1820 M*/)") ?> + +Value will be truncated. + + +<? entry("reading from an empty data stack or return stack (stack underflow)") ?> + +Most stack underflows are detected and prevented if <code>FICL_ROBUST</code> (defined in <code>sysdep.h</code>) is set to 2 or greater. +Otherwise, the stack pointer and size are likely to be trashed. + + +<? entry("unexpected end of input buffer, resulting in an attempt to use a zero-length string as a name") ?> + +Ficl returns for a new input buffer until a non-empty one is supplied. + + +</dl> + + +The following specific ambiguous conditions are noted in the glossary entries of the relevant words: + +<dl> + +<? entry(">IN greater than size of input buffer (3.4.1 Parsing)") ?> + +Memory corruption will occur—the exact behavior is unpredictable +because the input buffer is supplied by the host program's outer loop. + + +<? entry("6.1.2120 RECURSE appears after 6.1.1250 DOES>") ?> + +It finds the address of the definition before <code>DOES></code> + + +<? entry("argument input source different than current input source for 6.2.2148 RESTORE-INPUT") ?> + +Not implemented. + + +<? entry("data space containing definitions is de-allocated (3.3.3.2 Contiguous regions)") ?> + +This is okay until the cells are overwritten with something else. +The dictionary maintains a hash table, and the table must be updated +in order to de-allocate words without corruption. + + +<? entry("data space read/write with incorrect alignment (3.3.3.1 Address alignment)") ?> + +Target processor dependent. Consequences include: none (Intel), address error exception (68K). + + +<? entry("data-space pointer not properly aligned (6.1.0150 ,, 6.1.0860 C,)") ?> + +See above on data space read/write alignment. + +<? entry("less than u+2 stack items (6.2.2030 PICK, 6.2.2150 ROLL)") ?> + +If <code>FICL_ROBUST</code> is two or larger, Ficl will detect a stack underflow, report it, and execute <code>ABORT</code> to +exit execution. Otherwise the error will not be detected, and memory corruption will occur. + + +<? entry("loop-control parameters not available ( 6.1.0140 +LOOP, 6.1.1680 I, 6.1.1730 J, 6.1.1760 LEAVE, 6.1.1800 LOOP, 6.1.2380 UNLOOP)") ?> + +Loop initiation words are responsible for checking the stack and guaranteeing that the control parameters are pushed. +Any underflows will be detected early if <code>FICL_ROBUST</code> is set to 2 or greater. +Note however that Ficl only checks for return stack underflows at the end of each line of text. + +<? entry("most recent definition does not have a name (6.1.1710 IMMEDIATE)") ?> + +No problem. + + +<? entry("name not defined by 6.2.2405 VALUE used by 6.2.2295 TO") ?> + +Ficl's version of <code>TO</code> works correctly with words defined with: +<ul> + +<li> <code>VALUE</code> +<li> <code>2VALUE</code> +<li> <code>FVALUE</code> +<li> <code>F2VALUE</code> +<li> <code>CONSTANT</code> +<li> <code>FCONSTANT</code> +<li> <code>2CONSTANT</code> +<li> <code>F2CONSTANT</code> +<li> <code>VARIABLE</code> +<li> <code>2VARIABLE</code> +</ul> +as well as with all "local" variables. + +<? entry("name not found (6.1.0070 ', 6.1.2033 POSTPONE, 6.1.2510 ['], 6.2.2530 [COMPILE])") ?> + +Ficl prints an error message and executes <code>ABORT</code> + +<? entry("parameters are not of the same type (6.1.1240 DO, 6.2.0620 ?DO, 6.2.2440 WITHIN)") ?> + +Not detected. Results vary depending on the specific problem. + + +<? entry("6.1.2033 POSTPONE or 6.2.2530 [COMPILE] applied to 6.2.2295 TO") ?> + +The word is postponed correctly. + + +<? entry("string longer than a counted string returned by 6.1.2450 WORD") ?> + +Ficl stores the first <code>FICL_COUNTED_STRING_MAX</code> - 1 characters in the +destination buffer. +(The extra character is the trailing space required by the standard. Yuck.) + +<? entry("u greater than or equal to the number of bits in a cell (6.1.1805 LSHIFT, 6.1.2162 RSHIFT)") ?> + +Depends on target process or and C runtime library implementations of the << and >> operators +on unsigned values. For I386, the processor appears to shift modulo the number of bits in a cell. + +<? entry("word not defined via 6.1.1000 CREATE (6.1.0550 >BODY, 6.1.1250 DOES>)") ?> + +<? entry("words improperly used outside 6.1.0490 <# and 6.1.0040 #> (6.1.0030 #, 6.1.0050 #S, 6.1.1670 HOLD, 6.1.2210 SIGN)") ?> + +Undefined. <code>CREATE</code> reserves a field in words it builds for <code>DOES></code> to fill in. +If you use <code>DOES></code> on a word not made by <code>CREATE</code> it will overwrite the first +cell of its parameter area. That's probably not what you want. Likewise, pictured numeric words +assume that there is a string under construction in the VM's scratch buffer. If that's not the case, +results may be unpleasant. + + +</dl> + +<? ficlHeader2("Locals Implementation-Defined Options") ?> + +<dl> + +<? entry("maximum number of locals in a definition (13.3.3 Processing locals, 13.6.2.1795 LOCALS|)") ?> + +Default is 64—unused locals are cheap. Change by redefining <code>FICL_MAX_LOCALS</code> (defined in <code>ficl.h</code>). + +</dl> + + +<? ficlHeader2("Locals Ambiguous conditions") ?> + +<dl> + +<? entry("executing a named local while in interpretation state (13.6.1.0086 (LOCAL))") ?> + +Locals can be found in interpretation state while in the context of a definition under +construction. Under these circumstances, locals behave correctly. Locals are not visible +at all outside the scope of a definition. + +<? entry("name not defined by VALUE or LOCAL (13.6.1.2295 TO)") ?> + +See the CORE ambiguous conditions, above (no change). + +</dl> + + +<? ficlHeader2("Programming Tools Implementation-Defined Options") ?> + + +<dl> + +<? entry("source and format of display by 15.6.1.2194 SEE") ?> + +<code>SEE</code> de-compiles definitions from the dictionary. Ficl words are stored as a combination +of things: +<ol> + +<li>bytecodes (identified as "instructions"), +<li>addresses of native Ficl functions, and +<li>arguments to both of the above. + +</ol> +Colon definitions are decompiled. Branching instructions indicate their destination, +but target labels are not reconstructed. +Literals and string literals are so noted, and their contents displayed. + +</dl> + + +<? ficlHeader2("Search Order Implementation-Defined Options") ?> + + +<dl> + +<? entry("maximum number of word lists in the search order (16.3.3 Finding definition names, 16.6.1.2197 SET-ORDER)") ?> + +Defaults to 16. Can be changed by redefining <code>FICL_MAX_WORDLISTS</code> (declared in <code>ficl.h</code>). + + +<? entry("minimum search order (16.6.1.2197 SET-ORDER, 16.6.2.1965 ONLY)") ?> + +Equivalent to <code>FORTH-WORDLIST 1 SET-ORDER</code> + +</dl> + + + +<? ficlHeader2("Search Order Ambiguous Conditions") ?> + + +<dl> +<? entry("changing the compilation word list (16.3.3 Finding definition names)") ?> + +Ficl stores a link to the current definition independently of the compile wordlist while +it is being defined, and links it into the compile wordlist only after the definition completes +successfully. Changing the compile wordlist mid-definition will cause the definition to link +into the <i>new</i> compile wordlist. + + +<? entry("search order empty (16.6.2.2037 PREVIOUS)") ?> + +Ficl prints an error message if the search order underflows, and resets the order to its default state. + + +<? entry("too many word lists in search order (16.6.2.0715 ALSO)") ?> + +Ficl prints an error message if the search order overflows, and resets the order to its default state. + +</dl> + + +<? ficlPageFooter() ?> diff --git a/doc/source/ficl.ht b/doc/source/ficl.ht new file mode 100644 index 000000000000..faa49e7a7cff --- /dev/null +++ b/doc/source/ficl.ht @@ -0,0 +1,1257 @@ +<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en"> + +<html> +<head> + <meta name="Author" content="john sadler"> + <meta name="Description" content="Ficl - embedded scripting with object oriented programming"> + <meta name="Keywords" content="scripting prototyping tcl OOP Forth interpreter C"> + <link rel="SHORTCUT ICON" href="favicon.ico"> + <title>Ficl - Embedded Scripting</title> +</head> + +<body> + +<h1>Ficl Documentation</h1> + +<script language="javascript" src="ficlheader.js" type="text/javascript"> +</script> + +<h1><a name="whatis">What is Ficl?</a></h1> +Ficl is a complete programming language interpreter designed to be +embedded into other systems (including firmware based ones) as a +command, macro, and development prototype language. Unlike other +scripting interpreters, Ficl: + +<ul> + +<li> +typically takes under 2 hours to port to a new system—much +less if the target operating system is one of several already supported +(Win32, Linux, FreeBSD, RiscOS, and more) + +<li> +has a small memory footprint: a fully featured Win32 console +version takes less than 100K of memory, and a minimal version is less +than half that + +<li> +is relatively quick thanks to its "switch-threaded" virtual +machine design and just in time compiling + +<li> +is a complete and powerful programming language + +<li> +is interactive + +<li> +has object oriented programming features that can be used to wrap +data structures or classes of the host system without altering them—even +if the host is mainly written in a non-OO language + +</ul> + +<p> + +Ficl syntax is based on ANS Forth and the code is ANSI C. See +below for examples of <a href="#includesficl">software and products +that include ficl</a>. Ficl stands for "Forth inspired command language". + + +<h3>Ficl Versus Other Forth Interpreters</h3> + +Where most Forths view themselves as the center of the system and +expect the rest of the system to be coded in Forth, Ficl acts as a +component of the system. It is easy to export code written in C or +ASM to Ficl in the style of TCL, or to invoke Ficl code from a compiled +module. This allows you to do incremental development in a way that +combines the best features of threaded languages (rapid +development, quick code/test/debug cycle, reasonably fast) with the best +features of C (everyone knows it, easier to support large blocks of +code, efficient, type checking). In addition, Ficl provides a simple +and powerful object model that can act as an object oriented <i>adapter</i> +for code written in C (or asm, Forth, C++...). + + +<h3>Ficl Design Goals</h3> +<ul> + +<li> +Target 32- and 64-bit processors + +<li> +Scripting, prototyping, and extension language for systems +written also in C + +<li> +Supportable—code is as transparent as I can make it + +<li> +Interface to functions written in C + +<li> +Conformant to the 1994 ANSI Standard for Forth (DPANS94) + +<li> +Minimize porting effort—require an ANSI C runtime environment +and minimal glue code + +<li> +Provide object oriented extensions + +</ul> + +<hr> + +<h2><a name="download">Download</a></h2> + +<ul> + +<li> <b><a href="http://sourceforge.net/project/showfiles.php?group_id=24441">Download Ficl (latest release)</a></b> + +</ul> + +<h2><a name="links">More information on Ficl and Forth</a></h2> + +<ul> + +<li> +<a href="http://ficl.sourceforge.net">Web home of Ficl</a> + +<li> +<a href="http://ficl.sourceforge.net/pdf/Forth_Primer.pdf"> +An excellent Forth Primer by Hans Bezemer +</a> + +<li> +<a href="ficlddj.pdf"> +Manuscript of Ficl article for January 1999 Dr. Dobb's Journal +</a> + +<li> +<a href="jwsforml.pdf"> +1998 FORML Conference paper—OO Programming in Ficl +</a> + +<li> +<a href="http://www.taygeta.com/forth_intro/stackflo.html"> +An Introduction to Forth using Stack Flow +</a> +(start here if you're new to Forth) + +<li> +<a href="http://www.softsynth.com/pforth/pf_tut.htm"> +Phil Burk's Forth Tutorial +</a> + +<li> +<a href="http://www.complang.tuwien.ac.at/forth/threaded-code.html"> +Anton Ertl's description of Threaded Code +</a> +(Ficl now uses what he calls "switch threading") + +<li> +<a href="http://ficl.sourceforge.net/dpans/dpans.htm"> +Draft Proposed American National Standard for Forth +</a> +(quite readable, actually) + +<li> +<a href="http://www.taygeta.com/forthlit.html"> +Forth literature index on Taygeta +</a> + +<li> +<a href="http://www.forth.org"> +Forth Interest Group +</a> + +</ul> + +<h2><a name="includesficl">Some software that uses Ficl</a></h2> + +<ul> +<li> +The <a href="http://www.freebsd.org/">FreeBSD</a> boot loader +(Daniel Sobral, Jordan Hubbard) + +<li> +<a href="http://www.chipcenter.com/networking/images/prod/prod158a.pdf"> +SwitchCore +</a> +Gigabit Ethernet switches (Örjan Gustavsson ) + +<li> +<a href="http://debuffer.sourceforge.net/"> +Palm Pilot Debuffer +</a> +(Eric Sessoms) Also see ficlx, a C++ interface to ficl, on the same site + +<li> +<a href="http://www.swcp.com/%7Ejchavez/osmond.html"> +Osmond PC Board Layout tool +</a> + +<li> +<a href="http://www.netcomsystems.com"> +NetCom Systems +</a> +ML7710 + +<li> +<a href="http://www.parview.com/ds/homepage.html"> +ParView +</a> +GPS system + +<li> +<a href="http://www.thekompany.com/products/powerplant/software/Languages/Embedded.php3"> +PowerPlant Software +</a> +Development Environment for Linux + +<li> +<a href="http://www.vyyo.com/products/architecture_v3000.html"> +Vyyo V3000 Broadband Wireless Hub +</a> + +<li> +<a href="mailto:john_sadler@alum.mit.edu"> +<i>Your Product Name Here!!!</i> +</a> + +</ul> + + +<hr> +<h2><a name="lawyerbait">License And Disclaimer</a></h2> + +Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) +<br> +All rights reserved. +<p> + +<b> +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +<ol> + +<li> +Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +<li> +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +</ol> + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +</b> +<p> + +I am interested in hearing from anyone who uses Ficl. If you have a +problem, a success story, a defect, an enhancement request, or if +you would like to contribute to the ficl release, please +<a href="mailto:john_sadler@alum.mit.edu">send me email</a>. +<p> + + +<h2><a name="features">Ficl Features</a></h2> + +<ul> + +<li> +Simple to integrate into existing systems: the sample +implementation requires three Ficl function calls (see the example +program in <b>main.c</b>). + +<li> +Written in ANSI C for portability. + +<li> +Standard: Implements the ANS Forth CORE word set, part of the +CORE EXT word set, SEARCH and SEARCH EXT, TOOLS and part of TOOLS EXT, +LOCAL and LOCAL EXT, EXCEPTION, MEMORY, and various extras. + +<li> +Extensible: you can export code written in Forth, C, or ASM in a +straightforward way. Ficl provides open facilities for extending the +language in an application specific way. You can even add new +control structures (not surprising if you're familiar with Forth) + +<li> +Ficl and C/C++ can interact in two ways: Ficl can wrap C code, +and C functions can invoke Ficl code. + +<li> +Ficl code is thread safe and re-entrant: your program can have one or more +Ficl "systems", and each "system" can have one or Ficl virtual machines. +Each Ficl virtual machine has an otherwise complete state, and each can +be bound to a separate I/O channel (or none at all). +An optional function called ficlLockDictionary() can control +exclusive dictionary access. This function is stubbed out by +default (See FICL_MULTITHREAD in sysdep.h). As long as there is only +one "session" that can compile words into the dictionary, you do not +need exclusive dictionary access for multithreading. +<b>Note</b>: +while the code is re-entrant, there are still restrictions on how you +can use it safely in a multithreaded system. Specifically, the VM +itself maintains state, so you generally need a VM per thread in a +multithreaded system. If interrupt service routines make calls into Ficl +code that alters VM state, then these generally need their +own VM as well. Alternatively, you could provide a mutual exclusion +mechanism to serialize access to a VM from multiple threads. + +<li> +ROMable: Ficl is designed to work in RAM based and ROM code / RAM +data environments. It does require somewhat more memory than a pure ROM +implementation because it builds its system dictionary in RAM +at startup time. + +<li> +Written in ANSI C to be as simple as I can make it to understand, +support, debug, and port. Compiles without complaint at <code>/Az /W4</code> (require +ANSI C, max. warnings) under Microsoft Visual C++, and <code>-ansi</code> +under GCC. Ports to several other toolchains and operating systems +(notably FreeBSD and Linux flavors) exist. + +<li> Does full 32 bit math (but you need to implement two mixed +precision math primitives (see sysdep.c)) </li> + +</ul> + +<hr> + +<h2><a name="porting">Porting Ficl</a></h2> + +To install Ficl on your target system, you need an ANSI C compiler and +its runtime library. Inspect the system dependent macros and functions +in <b>sysdep.h</tt> and <tt>sysdep.c</tt> and edit them to suit +your system. For example, <tt>INT16</tt> is a <tt>short</tt> on some +compilers and an <tt>int</tt> on others. Check the default <tt>CELL</tt> +alignment controlled by <tt> FICL_ALIGN</tt>. If necessary, add new +definitions of <tt>ficlMalloc, ficlFree, ficlRealloc</tt>, and <tt>ficlTextOut</tt> +to work with your operating system. Finally, use <tt>testmain.c</tt> as +a guide to installing the ficl system and one or more virtual machines +into your code. You do not need to include <tt>testmain.c</tt> in your +build. +<p> +Note: ficlLockDictionary can be left unimplemented in most +multithreaded implementations - it's only necessary if you expect to +have more than one thread modifying the dictionary at the same +time. If you do decide to implement it, make sure calls to +ficlLockDictionary can nest properly (see the comments in sysdep.h). You +need to keep count of nested locks and unlocks and do the right +thing. +<p> + +Feel free to stub out the double precision math functions (which are +presently implemented as inline assembly because it's so easy on many 32 +bit processors) with kludge code that only goes to 32 bit +precision. In most applications, you won't notice the difference. If +you're doing a lot of number crunching, consider implementing them +correctly. + + +<h3>Build Controls</h3> + +The file sysdep.h contains default values for build controls. Most of +these are written such that if you define them on the compiler command +line, the defaults are overridden. I suggest you take the defaults +on everything below the "build controls" section until you're confident +of your port. Beware of declaring too small a dictionary, for example. +You need about 3200 cells for a full system, about 2000 if you +strip out most of the "soft" words. + +<h3>Softcore</h3> +Many words from all the supported wordsets are written in Forth, and +stored as a big string that Ficl compiles when it starts. The sources +for all of these words are in directory <b>softcore</b>. There is a +.bat file (softcore.bat) and a PERL 5 script (softcore.pl) that convert +Forth files into the file softcore.c, so softcore.c is really dependent +on the Forth sources. This is not reflected in the Visual C++ project +database. For the time being, it's a manual step. You can edit +<b>make.bat</b> to change the list of files that contribute to +<b>softcore.c</b>. + +<h3>To-Do List (target system dependent words)</h3> + +<ul> + +<li> +Unimplemented system dependent <tt>CORE</tt> word: <tt>KEY</tt> +(implement this yourself if you need it) + +<li> +Kludged <tt>CORE</tt> word: <tt>ACCEPT</tt> (implement this +better if you need to) + +</ul> + +<h2><a name="api">Application Programming Interface</a></h2> + +The following is a partial listing of functions that interface your +system or program to Ficl. For a complete listing, see <b>ficl.h</b> +(which is heavily commented). For examples, see <b>main.c</b> and the +FiclWin sources (<a href="#download">below</a>). + +<dl> + <dt> <b>FICL_SYSTEM *ficlInitSystem(int nDictCells)</b> </dt> + <dd> Initializes Ficl's shared system data structures, and creates the +dictionary allocating the specified number of CELLs from the heap (by a +call to ficlMalloc) </dd> + <dt> <b>void ficlTermSystem(FICL_SYSTEM *pSys)</b> </dt> + <dd> Reclaims memory allocated for the ficl system including all +dictionaries and all virtual machines created by vmCreate. Any uses of +the memory allocation words (allocate and resize) are your +problem. </dd> + <dt> <b>int ficlBuild(FICL_SYSTEM *pSys, char *name, FICL_CODE code, +char flags)</b> </dt> + <dd> Create a primitive word in ficl's main dictionary with the given +name, code pointer, and properties (immediate, compile only, etc) as +described by the flags (see ficl.h for flag descriptions of +the form FW_XXXX) </dd> + <dt> <b>int ficlExec(FICL_VM *pVM, char *text)</b> </dt> + <dd> Feed the specified C string ('\0' terminated) to the given +virtual machine for evaluation. Returns various exception codes (VM_XXXX +in ficl.h) to indicate the reason for returning. Normal exit +condition is VM_OUTOFTEXT, indicating that the VM consumed the string +successfully and is back for more. ficlExec calls can be nested, and +the function itself is re-entrant, but note that a VM is +static, so you have to take reasonable precautions (for example, use one +VM per thread in a multithreaded system if you want multiple threads to +be able to execute commands). </dd> + <dt> <b>int ficlExecC(FICL_VM *pVM, char *text, int nChars)</b> </dt> + <dd> Same as ficlExec, but takes a count indicating the length of the +supplied string. Setting nChars to -1 is equivalent to ficlExec (expects +'\0' termination). </dd> + <dt> <b>int ficlExecXT(FICL_VM *pVM, FICL_WORD *pFW)</b> </dt> + <dd> Same as ficlExec, but takes a pointer to a FICL_WORD instead of a +string. Executes the word and returns after it has finished. If +executing the word results in an exception, this function will +re-throw the same code if it is nested under another ficlExec family +function, or return the exception code directly if not. This function +is useful if you need to execute the same word repeatedly - +you save the dictionary search and outer interpreter overhead. </dd> + <dt> <b>void ficlFreeVM(FICL_VM *pVM)</b> </dt> + <dd> Removes the VM in question from the system VM list and deletes +the memory allocated to it. This is an optional call, since +ficlTermSystem will do this cleanup for you. This function is +handy if you're going to do a lot of dynamic creation of VMs. </dd> + <dt> <b>FICL_VM *ficlNewVM(FICL_SYSTEM *pSys)</b> </dt> + <dd> Create, initialize, and return a VM from the heap using +ficlMalloc. Links the VM into the system VM list for later reclamation +by ficlTermSystem. </dd> + <dt> <b>FICL_WORD *ficlLookup(FICL_SYSTEM *pSys, char *name)</b> </dt> + <dd> Returns the address (also known as an XT in this case) of the +specified word in the main dictionary. If not found, returns NULL. The +address can be used in a call to ficlExecXT. </dd> + <dt> <b>FICL_DICT *ficlGetDict(FICL_SYSTEM *pSys)</b> </dt> + <dd> Returns a pointer to the main system dictionary, or NULL if the +system is uninitialized. </dd> + <dt> <b>FICL_DICT *ficlGetEnv(FICL_SYSTEM *pSys)</b> </dt> + <dd> Returns a pointer to the environment dictionary. This dictionary +stores information that describes this implementation as required by the +Standard. </dd> + <dt> <b>void ficlSetEnv(FICL_SYSTEM *pSys, char *name, UNS32 value)</b> </dt> + <dd> Enters a new constant into the environment dictionary, with the +specified name and value. </dd> + <dt> <b>void ficlSetEnvD(FICL_SYSTEM *pSys, char *name, UNS32 hi, +UNS32 lo)</b> </dt> + <dd> Enters a new double-cell constant into the environment dictionary +with the specified name and value. </dd> + <dt> <b>FICL_DICT *ficlGetLoc(FICL_SYSTEM *pSys)</b> </dt> + <dd> Returns a pointer to the locals dictionary. This function is +defined only if FICL_WANT_LOCALS is #defined as non-zero (see sysdep.h). +The locals dictionary is the symbol table for <a href="ficl_loc.html">local +variables</a>. </dd> + <dt> <b>void ficlCompileCore(FICL_SYSTEM *pSys)</b> </dt> + <dd> Defined in words.c, this function builds ficl's primitives. + </dd> + <dt> <b>void ficlCompileSoftCore(FICL_SYSTEM *pSys)</b> </dt> + <dd> Defined in softcore.c, this function builds ANS required words +and ficl extras by evaluating a text string (think of it as a memory +mapped file ;-) ). The string itself is built from files in +the softwords directory by PERL script softcore.pl. </dd> +</dl> +<hr> +<table border="0" cellspacing="5" cols="2"> + <tbody> + <tr> + <td colspan="2"> + <h2> <a name="manifest"></a>Ficl Source Files </h2> + </td> + </tr> + <tr> + <td> <b>ficl.h</b> </td> + <td> Declares most public functions and all data structures. +Includes sysdep.h and math.h </td> + </tr> + <tr> + <td> <b>sysdep.h</b> </td> + <td> Declares system dependent functions and contains build +control macros. Edit this file to port to another system. </td> + </tr> + <tr> + <td> <b>math.h</b> </td> + <td> Declares functions for 64 bit math </td> + </tr> + <tr> + <td> <b>dict.c</b> </td> + <td> Dictionary </td> + </tr> + <tr> + <td> <b>ficl.c</b> </td> + <td> System initialization, termination, and ficlExec </td> + </tr> + <tr> + <td> <b>float.c</b> </td> + <td> Adds precompiled definitions from the optional FLOAT word +set. Most of the file is conditioned on FICL_WANT_FLOAT </td> + </tr> + <tr> + <td> <b>math64.c</b> </td> + <td> Implementation of 64 bit math words (except the two unsigned +primitives declared in sysdep.h and implemented in sysdep.c) </td> + </tr> + <tr> + <td> <b>prefix.c</b> </td> + <td> The optional prefix parse step (conditioned on +FICL_EXTENDED_PREFIX). This parse step handles numeric constructs like +0xa100, for example. See the release notes for more on parse steps. </td> + </tr> + <tr> + <td> <b>search.c</b> </td> + <td> Contains C implementations of several of the SEARCH and +SEARCH EXT words </td> + </tr> + <tr> + <td> <b>softcore.c</b> </td> + <td> Contains all of the "soft" words - those written in Forth and +compiled by Ficl at startup time. Sources for these words are in the +softwords directory. The files softwords/softcore.bat and +softwords/softcore.pl generate softcore.c from the .fr sources. </td> + </tr> + <tr> + <td> <b>softwords/</b> </td> + <td> Directory contains sources and translation scripts for the +words defined in softcore.c. Softcore.c depends on most of the files in +this directory. See softcore.bat for the actual list of +files that contribute to softcore.c. This is where you'll find source +code for the object oriented extensions. PERL script softcore.pl +converts the .fr files into softcore.c. </td> + </tr> + <tr> + <td> <b>stack.c</b> </td> + <td> Stack methods </td> + </tr> + <tr> + <td> <b>sysdep.c</b> </td> + <td> Implementation of system dependent functions declared in +sysdep.h </td> + </tr> + <tr> + <td> <b>testmain.c</b> </td> + <td> The main() function for unix/linux/win32 console applications +- use this as an example to integrate ficl into your system. Also +contains some definitions for testing - also useful in +unix/linux/win32 land. </td> + </tr> + <tr> + <td> <b>tools.c</b> </td> + <td> Contains C implementations of TOOLS and TOOLS EXT words, the +debugger, and debugger support words. </td> + </tr> + <tr> + <td> <b>vm.c</b> </td> + <td> Virtual Machine methods </td> + </tr> + <tr> + <td> <b>win32.c & unix.c</b> </td> + <td> Platform extensions words loaded in ficl.c by +ficlCompilePlatform() - conditioned on FICL_WANT_PLATFORM </td> + </tr> + <tr> + <td> <b>words.c</b> </td> + <td> Exports ficlCompileCore(), the run-time dictionary builder, +and contains most precompiled CORE and CORE-EXT words. </td> + </tr> + </tbody> +</table> +<hr> +<h2> <a name="extras"></a>Ficl extras </h2> +<h3> <a name="exnumber"></a>Number syntax </h3> +You can precede a number with "0x", as in C, and it will be interpreted +as a hex value regardless of the value of <code>BASE</code>. Likewise, +numbers prefixed with "0d" will be interpreted as decimal values. +Example: +<pre>ok> decimal 123 . cr<br>123<br>ok> 0x123 . cr<br>291<br>ok> 0x123 x. cr<br>123<br></pre> +Note: ficl2.05 and later - this behavior is controlled by the <a + href="ficl_parse.html">prefix parser</a> defined in <code>prefix.c</code>. +You can add other prefixes by defining handlers for them in ficl +or C. +<h3> <a name="exsearch"></a> The <code>SEARCH</code> wordset and Ficl +extensions </h3> +<p> Ficl implements many of the search order words in terms of two +primitives called <code><a href="#tosearch">>SEARCH</a></code> and <code><a + href="#searchfrom">SEARCH></a></code>. As their names +suggest (assuming you're familiar with Forth), they push and pop the +search order stack. </p> +<p> The standard does not appear to specify any conditions under which +the search order is reset to a sane state. Ficl resets the search order +to its default state whenever <tt>ABORT</tt> happens. This includes +stack underflows and overflows. <tt>QUIT</tt> does not affect the search +order. The minimum search order (set by <tt>ONLY</tt>) is equivalent +to </p> +<pre>FORTH-WORDLIST 1 SET-ORDER<br></pre> +<p> There is a default maximum of 16 wordlists in the search order. This +can be changed by redefining FICL_DEFAULT_VOCS (declared in sysdep.h). </p> +<p> <b>Note</b>: Ficl resets the search order whenever it does <tt>ABORT</tt>. +If you don't like this behavior, just comment out the +dictResetSearchOrder() lines in ficlExec(). </p> +<dl> + <dt> <a name="tosearch"></a><code>>search ( wid -- )</code> </dt> + <dd> Push <tt>wid</tt> onto the search order. Many of the other search +order words are written in terms of the <tt>SEARCH></tt> and <tt>>SEARCH</tt> +primitives. This word can be defined in ANS Forth as follows </dd> + <dd> <tt>: >search >r get-order 1+ r> swap +set-order ;</tt> </dd> + <dt> <a name="searchfrom"></a><tt>search> ( -- wid )</tt> </dt> + <dd> Pop <tt>wid</tt> off the search order (can be coded in ANS Forth +as <tt>: search> get-order nip 1- set-order ;</tt> ) </dd> + <dt> <a name="ficlsetcurrent"></a><tt>ficl-set-current ( +wid -- old-wid )</tt> </dt> + <dd> Set wid as compile wordlist, leaving the previous compile +wordlist on the stack </dd> + <dt> <a name="ficlvocabulary"></a><tt>ficl-vocabulary ( +nBins "name" -- )</tt> </dt> + <dd> Creates a <tt>ficl-wordlist</tt> with the specified number of +hash table bins, binds it to the name, and associates the semantics of <tt>vocabulary</tt> +with it (replaces the top wid in the search order list with +its own wid when executed) </dd> + <dt> <a name="ficlwordlist"></a><tt>ficl-wordlist ( nBins +-- wid )</tt> </dt> + <dd> Creates a wordlist with the specified number of hash table bins, +and leaves the address of the wordlist on the stack. A <tt>ficl-wordlist</tt> +behaves exactly as a regular wordlist, but it may search +faster depending on the number of bins chosen and the number of words it +contains at search time. As implemented in ficl, a wordlist is single +threaded by default. <tt> ficl-named-wordlist</tt> takes a name for the +wordlist and creates a word that pushes the <tt>wid</tt>. This is by +contrast to <tt>VOCABULARY</tt>, which also has a name, but replaces +the top of the search order with its <tt>wid</tt>. </dd> + <dt> <a name="ficlforgetwid"></a><tt>forget-wid ( wid -- )</tt> </dt> + <dd> Iterates through the specified wordlist and unlinks all +definitions whose xt addresses are greater than or equal to the value of <tt>HERE</tt>, +the dictionary fill pointer. </dd> + <dt> <a name="ficlhide"></a><tt>hide ( -- current-wid-was +)</tt> </dt> + <dd> Push the <tt>hidden</tt> wordlist onto the search order, and set +it as the current compile wordlist (unsing <tt>ficl-set-current</tt>). +Leaves the previous compile wordlist ID. I use this word to +hide implementation factor words that have low reuse potential so that +they don't clutter the default wordlist. To undo the effect of hide, +execute <b><tt>previous set-current</tt></b> </dd> + <dt> <a name="ficlhidden"></a><tt>hidden ( -- wid )</tt> </dt> + <dd> Wordlist for storing implementation factors of ficl provided +words. To see what's in there, try: <b><tt>hide words previous +set-current</tt></b> </dd> + <dt> <a name="wid-get-name"></a><tt>wid-get-name ( wid -- +c-addr u )</tt> </dt> + <dd> Ficl wordlists (2.05 and later) have a name property that can be +assigned. This is used by <tt>ORDER</tt> to list the names of wordlists +in the search order. </dd> + <dt> <a name="wid-set-name"></a><tt>wid-set-name ( c-addr +wid -- )</tt> </dt> + <dd> Ficl wordlists (2.05 and later) have a name property that can be +assigned. This is used by <tt>ORDER</tt> to list the names of wordlists +in the search order. The name is assumed to be a \0 terminated +string (C style), which conveniently is how Ficl stores word +names. See softwords/softcore.fr definition of <tt>brand-wordlist</tt> </dd> + <dt> <a name="wid-set-super"></a><tt>wid-set-super ( wid +-- )</tt> </dt> + <dd> Ficl wordlists have a parent wordlist pointer that is not +specified in standard Forth. Ficl initializes this pointer to NULL +whenever it creates a wordlist, so it ordinarily has no effect. +This word sets the parent pointer to the wordlist specified on the top +of the stack. Ficl's implementation of <tt>SEARCH-WORDLIST</tt> will +chain backward through the parent link of the wordlist when +searching. This simplifies Ficl's object model in that the search order +does not need to reflect an object's class hierarchy when searching for +a method. It is possible to implement Ficl object syntax in +strict ANS Forth, but method finders need to manipulate the search order +explicitly. </dd> +</dl> +<h3> <a name="exuser"></a>User variables </h3> +<dl> + <dt> <tt>user ( -- ) name</tt> </dt> + <dd> Create a user variable with the given name. User variables are +virtual machine local. Each VM allocates a fixed amount of storage for +them. You can change the maximum number of user variables +allowed by defining FICL_USER_CELLS on your compiiler's command line. +Default is 16 user cells. User variables behave like <tt>VARIABLE</tt>s +in all other respects (you use @ and ! on them, for example). +Example: </dd> + <dd> + <dl> + <dd> <tt>user current-class</tt> </dd> + <dd> <tt>0 current-class !</tt> </dd> + </dl> + </dd> +</dl> +<h3> <a name="exmisc"></a>Miscellaneous </h3> +<dl> + <dt> <tt>-roll ( xu xu-1 ... x0 u -- x0 xu-1 ... x1 +) </tt> </dt> + <dd> Rotate u+1 items on top of the stack after removing u. Rotation +is in the opposite sense to <tt>ROLL</tt> </dd> +</dl> +<dl> + <dt> <a name="minusrot"></a><tt>-rot ( a b c -- c a b )</tt> </dt> + <dd> Rotate the top three stack entries, moving the top of stack to +third place. I like to think of this as <tt>1<sup>1</sup>/<sub>2</sub>swap</tt> +because it's good for tucking a single cell value behind a +cell-pair (like an object). </dd> +</dl> +<dl> + <dt> <tt>.env ( -- )</tt> </dt> + <dd> List all environment variables of the system </dd> + <dt> <tt>.hash ( -- )</tt> </dt> + <dd> List hash table performance statistics of the wordlist that's +first in the search order </dd> + <dt> <tt>.ver ( -- )</tt> </dt> + <dd> Display ficl version ID </dd> + <dt> <tt>>name ( xt -- c-addr u )</tt> </dt> + <dd> Convert a word's execution token into the address and length of +its name </dd> + <dt> <tt>body> ( a-addr -- xt )</tt> </dt> + <dd> Reverses the effect of <tt>CORE</tt> word <tt>>body</tt> +(converts a parameter field address to an execution token) </dd> + <dt> <tt>compile-only</tt> </dt> + <dd> Mark the most recently defined word as being executable only +while in compile state. Many <tt>immediate</tt> words have this +property. </dd> + <dt> <tt>empty ( -- )</tt> </dt> + <dd> Empty the parameter stack </dd> + <dt> <tt>endif</tt> </dt> + <dd> Synonym for <tt>THEN</tt> </dd> + <dt> <a name="last-word"></a><tt>last-word ( -- xt )</tt> </dt> + <dd> Pushes the xt address of the most recently defined word. This +applies to colon definitions, constants, variables, and words that use <tt>create</tt>. +You can print the name of the most recently defined word +with </dd> + <dd> <b><tt>last-word >name type</tt> </b> </dd> + <dt> <tt>parse-word ( <spaces>name -- c-addr u )</tt> </dt> + <dd> Skip leading spaces and parse name delimited by a space. c-addr +is the address within the input buffer and u is the length of the +selected string. If the parse area is empty, the resulting +string has a zero length. (From the Standard) </dd> + <dt> <a name="qfetch"></a><tt>q@ ( addr -- x )</tt> </dt> + <dd> Fetch a 32 bit quantity from the specified address </dd> + <dt> <a name="qbang"></a><tt>q! ( x addr -- )</tt> </dt> + <dd> Store a 32 bit quantity to the specified address </dd> + <dt> <tt>w@ ( addr -- x )</tt> </dt> + <dd> Fetch a 16 bit quantity from the specified address </dd> + <dt> <tt>w! ( x addr -- )</tt> </dt> + <dd> Store a 16 bit quantity to the specified address (the low 16 bits +of the given value) </dd> + <dt> <a name="xdot"></a><tt>x. ( x -- )</tt> </dt> + <dd> Pop and display the value in hex format, regardless of the +current value of <tt>BASE</tt> </dd> +</dl> +<h3> <a name="exficlwin"></a>Extra words defined in testmain.c (Win32 +and POSIX versions) </h3> +<dl> + <dt> <tt>break ( -- )</tt> </dt> + <dd> Does nothing - just a handy place to set a debugger breakpoint </dd> + <dt> <tt>cd ( +"directory-name<newline>" -- )</tt> </dt> + <dd> Executes the Win32 chdir() function, changing the program's +logged directory. </dd> + <dt> <a name="clock"></a><tt>clock ( -- now )</tt> </dt> + <dd> Wrapper for the ANSI C clock() function. Returns the number of +clock ticks elapsed since process start. </dd> + <dt> <a name="clockspersec"></a><tt>clocks/sec ( -- +clocks_per_sec )</tt> </dt> + <dd> Pushes the number of ticks in a second as returned by <tt>clock</tt> </dd> + <dt> <a name="ficlload"></a><tt>load ( +"filename<newline>" -- )</tt> </dt> + <dd> Opens the Forth source file specified and loads it one line at a +time, like <tt>INCLUDED (FILE)</tt> </dd> + <dt> <tt>pwd ( -- )</tt> </dt> + <dd> Prints the current working directory as set by <tt>cd</tt> </dd> + <dt> <tt>system ( "command<newline>" -- )</tt> </dt> + <dd> Issues a command to a shell; implemented with the Win32 system() +call. </dd> + <dt> <tt>spewhash ( "filename<newline>" -- )</tt> </dt> + <dd> Dumps all threads of the current compilation wordlist to the +specified text file. This was useful when I thought there might be some +point in attempting to optimize the hash function. I no longer +harbor those illusions. </dd> +</dl> +<h3> Words defined in FiclWin only </h3> +<dl> + <dt> <tt>!oreg ( c -- )</tt> </dt> + <dd> Set the value of the simulated LED register as specified (0..255) + </dd> + <dt> <tt>@ireg ( -- c )</tt> </dt> + <dd> Gets the value of the simulated switch block (0..255) </dd> + <dt> <tt>!dac ( c -- )</tt> </dt> + <dd> Sets the value of the bargraph control as specified. Valid values +range from 0..255 </dd> + <dt> <tt>@adc ( -- c )</tt> </dt> + <dd> Fetches the current position of the slider control. Range is +0..255 </dd> + <dt> <tt>status" ( "ccc<quote>" -- )</tt> </dt> + <dd> Set the mainframe window's status line to the text specified, up +to the first trailing quote character. </dd> + <dt> <a name="ficlms"></a><tt><a + href="http://www.taygeta.com/forth/dpans10.htm#10.6.2.1905">ms</a> +( u -- )</tt> </dt> + <dd> Causes the running virtual machine to sleep() for the number of +milliseconds specified by the top-of-stack value. </dd> +</dl> +<hr> +<h2> <a name="ansinfo"></a>ANS Required Information </h2> +<b>ANS Forth System</b><br> +<b>Providing names from the Core Extensions word set </b><br> +<b>Providing the Exception word set</b><br> +<b>Providing names from the Exception Extensions word set</b><br> +<b>Providing the Locals word set </b><br> +<b>Providing the Locals Extensions word set </b><br> +<b>Providing the Memory Allocation word set</b><br> +<b>Providing the Programming-Tools word set</b><br> +<b>Providing names from the Programming-Tools Extensions word set</b><br> +<b>Providing the Search-Order word set</b><br> +<b>Providing the Search-Order Extensions word set</b> +<h3> Implementation-defined Options </h3> +The implementation-defined items in the following list represent +characteristics and choices left to the discretion of the implementor, +provided that the requirements of the Standard are met. A system +shall document the values for, or behaviors of, each item. +<ul> + <li> <b>aligned address requirements (3.1.3.3 Addresses);</b> </li> + <li> <br> + <font color="#000000">System dependent. You can change the default +address alignment by defining FICL_ALIGN on your compiler's command +line. The default value is set to 2 in sysdep.h. This causes +dictionary entries and <tt>ALIGN</tt> and <tt>ALIGNED</tt> to align on 4 +byte boundaries. To align on <b>2<sup>n</sup></b> byte boundaries, set +FICL_ALIGN to <b>n</b>. </font> </li> + <li> <b>behavior of 6.1.1320 EMIT for non-graphic characters</b>; </li> + <li> <br> + <font color="#000000">Depends on target system, C runtime library, +and your implementation of ficlTextOut().</font> </li> + <li> <b>character editing of 6.1.0695 ACCEPT and 6.2.1390 EXPECT</b>; </li> + <li> <br> + <font color="#000000">None implemented in the versions supplied in +words.c. Because ficlExec() is supplied a text buffer externally, it's +up to your system to define how that buffer will be obtained.</font> </li> + <li> <b>character set (3.1.2 Character types, 6.1.1320 EMIT, 6.1.1750 +KEY)</b>; </li> + <li> <br> + <font color="#000000">Depends on target system and implementation +of ficlTextOut()</font> </li> + <li> <b>character-aligned address requirements (3.1.3.3 Addresses)</b>; </li> + <li> <br> + <font color="#000000">Ficl characters are one byte each. There are +no alignment requirements.</font> </li> + <li> <b>character-set-extensions matching characteristics (3.4.2 +Finding definition n<font color="#000000">ames)</font></b><font + color="#000000">; </font> </li> + <li> <br> + <font color="#000000">No special processing is performed on +characters beyond case-folding. Therefore, extended characters will not +match their unaccented counterparts.</font> </li> + <li> <b>conditions under which control characters match a space +delimiter (3.4.1.1 Delimiters)</b>;<font color="#ff6666"> </font> </li> + <li> <br> + <font color="#000000">Ficl uses the Standard C function isspace() +to distinguish space characters. The rest is up to your library vendor.</font> </li> + <li> <b>format of the control-flow stack (3.2.3.2 Control-flow stack)</b>; </li> + <li> <br> + <font color="#000000">Uses the data stack</font> </li> + <li> <b>conversion of digits larger than thirty-five (3.2.1.2 Digit +conversion)</b>; </li> + <li> <br> + <font color="#000000">The maximum supported value of <tt>BASE</tt> +is 36. Ficl will assertion fail in function ltoa of vm.c if the base is +found to be larger than 36 or smaller than 2. There will be no +effect if NDEBUG is defined</font>, however, other than possibly +unexpected behavior. </li> + <li> <b>display after input terminates in 6.1.0695 ACCEPT and +6.2.1390 EXPECT</b>; </li> + <li> <br> + <font color="#000000">Target system dependent</font> </li> + <li> <b>exception abort sequence (as in 6.1.0680 ABORT")</b>; </li> + <li> <br> + <font color="#000000">Does <tt>ABORT</tt></font> </li> + <li> <b>input line terminator (3.2.4.1 User input device)</b>;<font + color="#ff0000"> </font> </li> + <li> <br> + <font color="#000000">Target system dependent (implementation of +outer loop that calls ficlExec)</font> </li> + <li> <b>maximum size of a counted string, in characters (3.1.3.4 +Counted strings, 6.1.2450 WORD)</b>; </li> + <li> <br> + <font color="#000000">255</font> </li> + <li> <b>maximum size of a parsed string (3.4.1 Parsing)</b>; </li> + <li> <br> +Limited by available memory and the maximum unsigned value that can fit +in a CELL (2<sup>32</sup>-1). </li> + <li> <b>maximum size of a definition name, in characters (3.3.1.2 +Definition names)</b>; </li> + <li> <br> + <font color="#000000">Ficl stores the first 31 characters of a +definition name.</font> </li> + <li> <b>maximum string length for 6.1.1345 ENVIRONMENT?, in characters</b>; </li> + <li> <br> + <font color="#000000">Same as maximum definition name length</font> </li> + <li> <b>method of selecting 3.2.4.1 User input device</b>; </li> + <li> <br> +None supported. This is up to the target system </li> + <li> <b>method of selecting 3.2.4.2 User output device</b>; </li> + <li> <br> +None supported. This is up to the target system </li> + <li> <b>methods of dictionary compilation (3.3 The Forth dictionary)</b>; </li> + <li> <b>number of bits in one address unit (3.1.3.3 Addresses)</b>; </li> + <li> <br> + <font color="#000000">Target system dependent. Ficl generally +supports processors that can address 8 bit quantities, but there is no +dependency that I'm aware of.</font> </li> + <li> <b>number representation and arithmetic (3.2.1.1 Internal number +representation)</b>; </li> + <li> <br> +System dependent. Ficl represents a CELL internally as a union that can +hold INT32 (a signed 32 bit scalar value), UNS32 (32 bits unsigned), and +an untyped pointer. No specific byte ordering is +assumed. </li> + <li> <b>ranges for n, +n, u, d, +d, and ud (3.1.3 Single-cell types, +3.1.4 Cell-pair types)</b>; </li> + <li> <br> +Assuming a 32 bit implementation, range for signed single-cell values +is -2<sup>31</sup>..2<sup>31</sup>-1. Range for unsigned single cell +values is 0..2<sup>32</sup>-1. Range for signed double-cell +values is -2<sup>63</sup>..2<sup>63</sup>-1. Range for unsigned single +cell values is 0..2<sup>64</sup>-1. </li> + <li> <b>read-only data-space regions (3.3.3 Data space)</b>; </li> + <li> <br> +None </li> + <li> <b>size of buffer at 6.1.2450 WORD (3.3.3.6 Other transient +regions)</b>; </li> + <li> <br> +Default is 255. Depends on the setting of nPAD in ficl.h. </li> + <li> <b>size of one cell in address units (3.1.3 Single-cell types)</b>; </li> + <li> <br> + <font color="#000000">System dependent, generally four.</font> </li> + <li> <b>size of one character in address units (3.1.2 Character types)</b>; </li> + <li> <br> + <font color="#000000">System dependent, generally one.</font> </li> + <li> <b>size of the keyboard terminal input buffer (3.3.3.5 Input +buffers)</b>; </li> + <li> <br> + <font color="#000000">This buffer is supplied by the host program. +Ficl imposes no practical limit.</font> </li> + <li> <b>size of the pictured numeric output string buffer (3.3.3.6 +Other transient regions)</b>; </li> + <li> <br> +Default is 255 characters. Depends on the setting of nPAD in +ficl.h. </li> + <li> <b>size of the scratch area whose address is returned by +6.2.2000 PAD (3.3.3.6 Other transient regions)</b>; </li> + <li> <br> +Not presently supported </li> + <li> <b>system case-sensitivity characteristics (3.4.2 Finding +definition names)</b>; </li> + <li> <br> + <font color="#000000">Ficl is not case sensitive</font> </li> + <li> <b>system prompt (3.4 The Forth text interpreter, 6.1.2050 QUIT)</b>; </li> + <li> <br> + <font color="#000000">"ok>"</font> </li> + <li> <b>type of division rounding (3.2.2.1 Integer division, 6.1.0100 +*/, 6.1.0110 */MOD, 6.1.0230 /, 6.1.0240 /MOD, 6.1.1890 MOD)</b>; </li> + <li> <br> + <font color="#000000">Symmetric</font> </li> + <li> <b>values of 6.1.2250 STATE when true</b>; </li> + <li> <br> + <font color="#000000">One (no others)</font> </li> + <li> <b>values returned after arithmetic overflow (3.2.2.2 Other +integer operations)</b>; </li> + <li> <br> +System dependent. Ficl makes no special checks for overflow. </li> + <li> <b>whether the current definition can be found after 6.1.1250 +DOES> (6.1.0450 :)</b>. </li> + <li> <br> + <font color="#000000">No. Definitions are unsmudged after ; only, +and only then if no control structure matching problems have been +detected.</font> </li> +</ul> +<h3> Ambiguous Conditions </h3> +A system shall document the system action taken upon each of the +general or specific ambiguous conditions identified in this Standard. +See 3.4.4 Possible actions on an ambiguous condition. +<p> The following general ambiguous conditions could occur because of a +combination of factors: </p> +<ul> + <li> <b>a name is neither a valid definition name nor a valid number +during text interpretation (3.4 The Forth text interpreter)</b>; </li> + <li> <br> + <font color="#000000">Ficl does <tt>ABORT</tt> and prints the name +followed by " not found".</font> </li> + <li> <b>a definition name exceeded the maximum length allowed +(3.3.1.2 Definition names)</b>; </li> + <li> <br> + <font color="#000000">Ficl stores the first 31 characters of the +definition name, and uses all characters of the name in computing its +hash code. The actual length of the name, up to 255 +characters, is stored in the definition's length field.</font> </li> + <li> <b>addressing a region not listed in 3.3.3 Data Space</b>; + </li> + <li> <br> + <font color="#000000">No problem: all addresses in ficl are +absolute. You can reach any 32 bit address in Ficl's address space.</font> </li> + <li> <b>argument type incompatible with specified input parameter, +e.g., passing a flag to a word expecting an n (3.1 Data types)</b>; </li> + <li> <br> + <font color="#000000">Ficl makes no check for argument type +compatibility. Effects of a mismatch vary widely depending on the +specific problem and operands.</font> </li> + <li> <b>attempting to obtain the execution token, (e.g., with +6.1.0070 ', 6.1.1550 FIND, etc.) of a definition with undefined +interpretation semantics</b>; </li> + <li> <br> + <font color="#000000">Ficl returns a valid token, but the result of +executing that token while interpreting may be undesirable.</font> </li> + <li> <b>dividing by zero (6.1.0100 */, 6.1.0110 */MOD, 6.1.0230 /, +6.1.0240 /MOD, 6.1.1561 FM/MOD, 6.1.1890 MOD, 6.1.2214 SM/REM, 6.1.2370 +UM/MOD, 8.6.1.1820 M*/)</b>; </li> + <li> <br> + <font color="#000000">Results are target procesor dependent. +Generally, Ficl makes no check for divide-by-zero. The target processor +will probably throw an exception.</font> </li> + <li> <b>insufficient data-stack space or return-stack space (stack +overflow)</b>; </li> + <li> <br> + <font color="#000000">With FICL_ROBUST (sysdep.h) set >= 2, most +parameter stack operations are checked for underflow and overflow. Ficl +does not check the return stack.</font> </li> + <li> <b>insufficient space for loop-control parameters</b>; </li> + <li> <br> + <font color="#000000">No check - Evil results.</font> </li> + <li> <b>insufficient space in the dictionary</b>; </li> + <li> <br> + <font color="#000000">Ficl generates an error message if the +dictionary is too full to create a definition header. It checks <tt>ALLOT</tt> +as well, but it is possible to make an unchecked allocation +request that overflows the dictionary.</font> </li> + <li> <b>interpreting a word with undefined interpretation semantics</b>; </li> + <li> <br> + <font color="#000000">Ficl protects all ANS Forth words with +undefined interpretation semantics from being executed while in +interpret state. It is possible to defeat this protection using +' (tick) and <tt>EXECUTE</tt>, though.</font> </li> + <li> <b>modifying the contents of the input buffer or a string +literal (3.3.3.4 Text-literal regions, 3.3.3.5 Input buffers)</b>; </li> + <li> <br> + <font color="#000000">Varies depending on the nature of the buffer. +The input buffer is supplied by ficl's host function, and may reside in +read-only memory. If so, writing the input buffer can ganerate +an exception. String literals are stored in the dictionary, and are +writable.</font> </li> + <li> <b>overflow of a pictured numeric output string</b>; </li> + <li> <br> +In the unlikely event you are able to construct a pictured numeric +string of more than 255 characters, the system will be corrupted +unpredictably. The buffer area that holds pictured numeric +output is at the end of the virtual machine. Whatever is mapped after +the offending VM in memory will be trashed, along with the heap +structures that contain it. </li> + <li> <b>parsed string overflow</b>; </li> + <li> <br> +Ficl does not copy parsed strings unless asked to. Ordinarily, a string +parsed from the input buffer during normal interpretation is left +in-place, so there is no possibility of overflow. If you ask +to parse a string into the dictionary, as in <tt>SLITERAL</tt>, you +need to have enough room for the string, otherwise bad things may +happen. This is not usually a problem. </li> + <li> <b>producing a result out of range, e.g., multiplication (using +*) results in a value too big to be represented by a single-cell integer +(6.1.0090 *, 6.1.0100 */, 6.1.0110 */MOD, 6.1.0570 +>NUMBER, 6.1.1561 FM/MOD, 6.1.2214 SM/REM, 6.1.2370 UM/MOD, 6.2.0970 +CONVERT, 8.6.1.1820 M*/)</b>; </li> + <li> <br> + <font color="#000000">Value will be truncated</font> </li> + <li> <b>reading from an empty data stack or return stack (stack +underflow)</b>; </li> + <li> <br> + <font color="#000000">Most stack underflows are detected and +prevented if FICL_ROBUST (sysdep.h) is set to 2 or greater. Otherwise, +the stack pointer and size are likely to be trashed.</font> </li> + <li> <b>unexpected end of input buffer, resulting in an attempt to +use a zero-length string as a name</b>; </li> + <li> <br> + <font color="#000000">Ficl returns for a new input buffer until a +non-empty one is supplied.</font> </li> +</ul> +The following specific ambiguous conditions are noted in the glossary +entries of the relevant words: +<ul> + <li> <b>>IN greater than size of input buffer (3.4.1 Parsing)</b> </li> + <li> <br> +Bad Things occur - unpredictable bacause the input buffer is supplied +by the host program's outer loop. </li> + <li> <b>6.1.2120 RECURSE appears after 6.1.1250 DOES></b> </li> + <li> <br> +It finds the address of the definition before <tt>DOES></tt> </li> + <li> <b>argument input source different than current input source for +6.2.2148 RESTORE-INPUT</b> </li> + <li> <br> +Not implemented </li> + <li> <b>data space containing definitions is de-allocated (3.3.3.2 +Contiguous regions)</b> </li> + <li> <br> +This is OK until the cells are overwritten with something else. The +dictionary maintains a hash table, and the table must be updated in +order to de-allocate words without corruption. </li> + <li> <b>data space read/write with incorrect alignment (3.3.3.1 +Address alignment)</b> </li> + <li> <br> +Target processor dependent. Consequences include: none (Intel), address +error exception (68K). </li> + <li> <b>data-space pointer not properly aligned (6.1.0150 ,, 6.1.0860 +C,)</b> </li> + <li> <br> +See above on data space read/write alignment </li> + <li> <b>less than u+2 stack items (6.2.2030 PICK, 6.2.2150 ROLL)</b> </li> + <li> <br> +Ficl detects a stack underflow and reports it, executing <tt>ABORT,</tt> +as long as FICL_ROBUST is two or larger. </li> + <li> <b>loop-control parameters not available ( 6.1.0140 +LOOP, +6.1.1680 I, 6.1.1730 J, 6.1.1760 LEAVE, 6.1.1800 LOOP, 6.1.2380 UNLOOP)</b> </li> + <li> <br> +Loop initiation words are responsible for checking the stack and +guaranteeing that the control parameters are pushed. Any underflows will +be detected early if FICL_ROBUST is set to two or greater. +Note however that Ficl only checks for return stack underflows at the +end of each line of text. </li> + <li> <b>most recent definition does not have a name (6.1.1710 +IMMEDIATE)</b> </li> + <li> <br> +No problem. </li> + <li> <b>name not defined by 6.2.2405 VALUE used by 6.2.2295 TO</b> </li> + <li> <br> +Ficl's version of <tt>TO</tt> works correctly with <tt>VALUE</tt>s, <tt>CONSTANT</tt>s +and <tt>VARIABLE</tt>s. </li> + <li> <b>name not found (6.1.0070 ', 6.1.2033 POSTPONE, 6.1.2510 ['], +6.2.2530 [COMPILE])</b> </li> + <li> <br> +Ficl prints an error message and does <tt>ABORT</tt> </li> + <li> <b>parameters are not of the same type (6.1.1240 DO, 6.2.0620 +?DO, 6.2.2440 WITHIN)</b> </li> + <li> <br> +No check. Results vary depending on the specific problem. </li> + <li> <b>6.1.2033 POSTPONE or 6.2.2530 [COMPILE] applied to 6.2.2295 TO</b> </li> + <li> <br> +The word is postponed correctly. </li> + <li> <b>string longer than a counted string returned by 6.1.2450 WORD</b> </li> + <li> <br> +Ficl stores the first FICL_STRING_MAX-1 chars in the destination +buffer. (The extra character is the trailing space required by the +standard. Yuck.) </li> + <li> <b>u greater than or equal to the number of bits in a cell +(6.1.1805 LSHIFT, 6.1.2162 RSHIFT)</b> </li> + <li> <br> +Depends on target process or and C runtime library implementations of +the << and >> operators on unsigned values. For I386, the +processor appears to shift modulo the number of bits in a +cell. </li> + <li> <b>word not defined via 6.1.1000 CREATE (6.1.0550 >BODY, +6.1.1250 DOES>)</b> </li> + <li> <br> + <b>words improperly used outside 6.1.0490 <# and 6.1.0040 #> +(6.1.0030 #, 6.1.0050 #S, 6.1.1670 HOLD, 6.1.2210 SIGN)</b><br> +Don't. <tt>CREATE</tt> reserves a field in words it builds for <tt>DOES></tt>to +fill in. If you use <tt>DOES></tt> on a word not made by <tt>CREATE</tt>, +it will overwrite the first cell of its parameter area. +That's probably not what you want. Likewise, pictured numeric words +assume that there is a string under construction in the VM's scratch +buffer. If that's not the case, results may be unpleasant. </li> +</ul> +<h3> Locals Implementation-defined options </h3> +<ul> + <li> <b>maximum number of locals in a definition (13.3.3 Processing +locals, 13.6.2.1795 LOCALS|)</b> </li> + <li> <br> +Default is 16. Change by redefining FICL_MAX_LOCALS, defined in +sysdep.h </li> +</ul> +<h3> Locals Ambiguous conditions </h3> +<ul> + <li> <b>executing a named local while in interpretation state +(13.6.1.0086 (LOCAL))</b> </li> + <li> <br> +Locals can be found in interpretation state while in the context of a +definition under construction. Under these circumstances, locals behave +correctly. Locals are not visible at all outside the scope of +a definition. </li> + <li> <b>name not defined by VALUE or LOCAL (13.6.1.2295 TO)</b> </li> + <li> <br> +See the CORE ambiguous conditions, above (no change) </li> +</ul> +<h3> Programming Tools Implementation-defined options </h3> +<ul> + <li> <b>source and format of display by 15.6.1.2194 SEE</b> </li> + <li> <br> +SEE de-compiles definitions from the dictionary. Because Ficl words are +threaded by their header addresses, it is very straightforward to print +the name and other characteristics of words in a definition. +Primitives are so noted. Colon definitions are decompiled, but branch +target labels are not reconstructed. Literals and string literals are so +noted, and their contents displayed. </li> +</ul> +<h3> Search Order Implementation-defined options </h3> +<ul> + <li> <b>maximum number of word lists in the search order (16.3.3 +Finding definition names, 16.6.1.2197 SET-ORDER)</b> </li> + <li> <br> +Defaults to 16. Can be changed by redefining FICL_DEFAULT_VOCS, +declared in sysdep.h </li> + <li> <b>minimum search order (16.6.1.2197 SET-ORDER, 16.6.2.1965 ONLY)</b> </li> + <li> <br> +Equivalent to <tt>FORTH-WORDLIST 1 SET-ORDER</tt> </li> +</ul> +<h3> Search Order Ambiguous conditions </h3> +<ul> + <li> <b>changing the compilation word list (16.3.3 Finding definition +names)</b> </li> + <li> <br> +Ficl stores a link to the current definition independently of the +compile wordlist while it is being defined, and links it into the +compile wordlist only after the definition completes +successfully. Changing the compile wordlist mid-definition will cause +the definition to link into the <i>new</i> compile wordlist. </li> + <li> <b>search order empty (16.6.2.2037 PREVIOUS)</b> </li> + <li> <br> +Ficl prints an error message if the search order underflows, and resets +the order to its default state. </li> + <li> <b>too many word lists in search order (16.6.2.0715 ALSO)</b> </li> + <li> <br> +Ficl prints an error message if the search order overflows, and resets +the order to its default state. </li> +</ul> +</div> +</body> +</html> diff --git a/doc/source/generate.py b/doc/source/generate.py new file mode 100644 index 000000000000..36a4406320ad --- /dev/null +++ b/doc/source/generate.py @@ -0,0 +1,244 @@ +import cStringIO +import os +import re +import shutil +import string +import sys + + +outputStart = None +navBarEntries = {} + + + +def ficlLinkEntry(file, title): + print("<a href=" + file + ".html><font color=white>" + title + "</font></a><p>\n") + + + +currentNavBarName = None + +def ficlAddToNavBarAs(name): + global currentNavBarName + currentNavBarName = name + + +def ficlPageHeader(heading): + outputStart.write("""<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +<META name='Description' content='Ficl - embedded scripting with object oriented programming'> +<META name='Keywords' content='scripting prototyping tcl OOP Forth interpreter C'> +<LINK rel='SHORTCUT ICON' href='ficl.ico'> +<TITLE>""" + heading + """</TITLE> +<style>\n +blockquote { margin-left: 1em }\n +</style>\n +</HEAD> +<BODY> + +<table border=0 cellspacing=0 width=100%%><tr>\n + +<td width=112 bgcolor=#004968 colspan=3> +<img src=graphics/ficl.4.96.jpg height=96 width=96> +</td> + +<td bgcolor=#004968> +<font face=arial,helvetica color=white size=7><b><i> +""" + heading + """ +</i></b></font> +</td></tr> + +\n<tr> +<td bgcolor=#004968 width=10></td> +<td bgcolor=#004968 valign=top> +<br><p> +<a href=index.html><font face=arial,helvetica color=white><b>Index</b></font></a><p> +""") + + print("</td><td bgcolor=#004968 width=5></td><td valign=top><blockquote><p>\n") + + + +def ficlPageFooter(): + print("\n</blockquote><p></td></tr></table></body></html>\n") + + + +sizeArray = [7, 5, 4, 3, 2] +indentLevel = 0 +sections = None + +def ficlHeader(level, color, bgcolor, heading): + global sizeArray + size = str(sizeArray[level]) + + global indentLevel + global sections + while (indentLevel < level): + indentLevel += 1 +# sys.stderr.write("adding 1 to indentLevel, it's now " + str(indentLevel) + "\n\n") + sections.append([]) + while (indentLevel > level): + indentLevel -= 1 + subheadings = sections.pop() +# sys.stderr.write("indentLevel is " + str(indentLevel) + ", subheadings is " + str(subheadings) + ", len(sections) is " + str(len(sections)) + ", sections is " + str(sections) + "\n\n") + sections[indentLevel - 1][-1][1] = subheadings + entry = [heading, [] ] +# sys.stderr.write("indentLevel is " + str(indentLevel) + ", len(sections) is " + str(len(sections)) + ", sections is " + str(sections) + "\n\n") +# sys.stderr.flush() + sections[indentLevel - 1].append(entry) + + print(""" +<p> +</blockquote><table border=0 bgcolor=""" + bgcolor + """ width=100%><tr> + +<td width=1em></td> +<td> +<font face=arial,helvetica color=""" + color + " size=" + size + "><b><i>") + print("<a name='" + collapse(heading) + "'>") + print(heading) + print("</a></i></b></font></td></tr></table><p><blockquote>\n") + + +def ficlHeader1(heading): + ficlHeader(1, "#004968", "#a0a0a0", heading) + +def ficlHeader2(heading): + ficlHeader(2, "#004968", "#b8b8b8", heading) + +def ficlHeader3(heading): + ficlHeader(3, "#004968", "#d0d0d0", heading) + +def ficlHeader4(heading): + ficlHeader(4, "#004968", "#e8e8e8", heading) + + +def collapse(s): + return string.join(s.split(), "").replace("'", "").replace("&", "").replace('"', "").replace('<', "").replace('>', "").replace('.', "").replace('?', "") + +def dump(f, sections): + for section in sections: + sys.stderr.write("sections is " + str(section) + "\n") + name = section[0] + f.write("<li><a href=#" + collapse(name) + "><font color=white>" + name + "</font></a>\n") + if len(section[1]) != 0: + f.write("<ul>\n") + dump(f, section[1]) + f.write("</ul>\n") + +def process(inputfilename, outputfilename): + print "generating " + inputfilename + global indentLevel + indentLevel = 0 + global sections + sections = [] + global currentNavBarName + + input = open(inputfilename, "r") + data = input.read().replace("\r", "") + input.close() + chunks = data.split("<?") + + output = cStringIO.StringIO() + + global outputStart + outputStart = cStringIO.StringIO() + + stdout = sys.stdout + + fauxGlobals = { } + fauxGlobals.update(globals()) + fauxGlobals['__name__'] = '__ficlDocs__' + fauxGlobals['__doc__'] = inputfilename + fauxGlobals['outputStart'] = outputStart + + sys.stdout = output + if (chunks[0] != None): + output.write(chunks[0]) + for chunk in chunks[1:]: + (code, verbatim) = chunk.split("?>") + code = code.lstrip() + if (code[0] == "="): + execution = "eval" + code = code[1:].lstrip() + else: + execution = "exec" + compiled = compile(code, "[unknown]", execution) + if (execution == "eval"): + output.write(str(eval(compiled))) + else: + exec compiled + output.write(verbatim) + + sys.stdout = stdout + + + f = open(outputfilename, "w") + f.write(outputStart.getvalue()) + f.write("<p><br>\n") + keys = navBarEntries.keys() + keys.sort() + for name in keys: + filename = navBarEntries[name] + f.write("<a href=" + filename + ">") + name = name.replace(" ", " ") + f.write("<font face=arial,helvetica color=white><b>" + name + "</b></font>") + f.write("</a><br>\n") +# This doesn't look as pretty as I wanted, so I'm turning it off. --lch +# if (name == currentNavBarName) and (len(sections) > 0): +# f.write("<ul>\n") +# dump(f, sections[0]) +# f.write("</ul>\n") + + f.write(output.getvalue()) + f.close() + + + +## +## First, find all the documents in the current directory, +## and look for their navBar entry. +## + +for filename in os.listdir("."): + if filename[-3:] == ".ht": + file = open(filename, "rb") + for line in file.readlines(): + navBar = "ficlAddToNavBarAs(\"" + if line.strip().startswith(navBar): + (a, name, b) = line.split('"') + navBarEntries[name] = filename + "ml" + break + file.close() + +navBarEntries["Download"] = "http://sourceforge.net/project/showfiles.php?group_id=24441" + +ignored = re.compile("^((.*\.pyc?)|(.*\.zip)|\.|(\.\.))$") + +## +## Second, build the doc tree (in ..), processing as necessary. +## +def visit(unused, directory, names): + for file in names: + if ignored.search(file): + continue + input = directory + "/" + file + output = "../" + input + if input[-3:].lower() == ".ht": + process(input, output + "ml") + elif os.path.isdir(input): + if not os.path.isdir(output): + os.mkdir(output) + else: + try: + shutil.copy2(input, output) + except IOError: + ## Ignore file-copy errors. It's probably + ## a read-only file that doesn't change. + ## Lazy, I know. --lch + None + +os.path.walk(".", visit, None) + + diff --git a/doc/source/index.ht b/doc/source/index.ht new file mode 100644 index 000000000000..1c66a2ed992d --- /dev/null +++ b/doc/source/index.ht @@ -0,0 +1,244 @@ +<? +ficlPageHeader("ficl") + +def feature(preamble, keyfeature, postscript = ""): + print "<p><dt>\n" + preamble + " <b><i>" + keyfeature + "</i></b> " + postscript + "\n<dd>\n" + +?> + + +<? ficlHeader1("What is Ficl?") ?> + + +Ficl is a programming language interpreter designed to be embedded +into other systems as a command, macro, and development prototyping +language. +<p> + +Ficl is an acronym for "Forth Inspired Command Language". + + +<? ficlHeader1("Ficl Features") ?> + +<dl> + + +<? feature("Ficl is", "easy to port.") ?> + +<ul> + +<li> +It typically takes under 2 hours to port to a new platform. + +<li> +Ficl is written in strict ANSI C. + +<li> +Ficl can run natively on 32- and 64-bit processors. + +</ul> + + + +<? feature("Ficl has a", "small memory footprint.") ?> + +A fully featured Win32 console version takes less than 100K +of memory, and a minimal version is less +than half that. + + + +<? feature("Ficl is ", "easy to integrate", "into your program.") ?> + +Where most Forths view themselves as the center of the system and +expect the rest of the system to be coded in Forth, Ficl acts as a +component of your program. It is easy to export code written in C or +ASM to Ficl (in the style of TCL), or to invoke Ficl code from a +compiled module. + + + +<? feature("Ficl is", "fast.") ?> + +Thanks to its +<a href=http://www.complang.tuwien.ac.at/forth/threaded-code.html#switch-threading>"switch-threaded"</a> +virtual machine design, Ficl 4 is faster than ever—about 3x the speed of Ficl 3. +Ficl also features blindingly fast "just in time" compiling, removing the "compile" step from +the usual compile-debug-edit iterative debugging cycle. + + + +<? feature("Ficl is a", "complete and powerful programming language.") ?> + +Ficl is an implementation of the FORTH language, a language providing +a wide range of standard programming language features: +<ul> + +<li> +Integer and floating-point numbers, with a rich set of operators. + +<li> +Arrays. + +<li> +File I/O. + +<li> +Flow control (<code>if/then/else</code> and many looping structures). + +<li> +Subroutines with named arguments. + +<li> +Language extensibility. + +<li> +Powerful code pre-processing features. + +</ul> + + + +<? feature("Ficl is ", "standards-compliant.") ?> + +Ficl conforms to the 1994 ANSI Standard for FORTH (DPANS94). +See <a href=dpans.html>ANS Required Information</a> for +more detail. + + +<? feature("Ficl is", "extensible.") ?> + +Ficl is extensible both at compile-time and at run-time. +You can add new script functions, new native functions, +even new control structures. + + + + +<? feature("Ficl adds ", "object oriented programming features.") ?> + +Ficl's flexible OOP library can be used to wrap +data structures or classes of the host system without altering them. +(And remember how we said Ficl was extensible? Ficl's object-oriented +programming extensions are written in Ficl.) + + + +<? feature("Ficl is", "interactive.") ?> + +Ficl can be used interactively, like most other FORTHs, Python, +and Smalltalk. You can inspect data, run commands, or even +define new commands, all on a running Ficl VM. +Ficl also has a built-in script debugger that allows you to +step through Ficl code as it is executed. + + +<? feature("Ficl is", "ROMable.") ?> + +Ficl is designed to work in RAM based and ROM code / RAM +data environments. + + + +<? feature("Ficl is", "safe for multithreaded programs.") ?> + +Ficl is reentrant and thread-safe. After initialization, +it does not write to any global data. + + +<? feature("Ficl is ", "open-source and free.") ?> + +The <a href=license.html>Ficl licence</a> is a BSD-style +license, requiring only that you document that you are +using Ficl. There are no licensing costs for using Ficl. + + +</dl> + + +<a name=whatsnew> +<? ficlHeader1("What's New In Ficl 4.0?") ?> +</a> + +Ficl 4.0 is a major change for Ficl. Ficl 4.0 is <i>smaller</i>, +<i>faster</i>, <i>more powerful</i>, and <i>easier to use</i> +than ever before. (Or your money back!) +<p> + +Ficl 4.0 features a major engine rewrite. Previous versions +of Ficl stored compiled words as an array of pointers to data +structure; Ficl 4.0 adds "instructions", and changes over to +mostly using a "switch-threaded" model. The result? Ficl 4.0 +is approximately <i>three times</i> as fast as Ficl 3.03. +<p> + +Ficl 4.0 also adds the ability to store the "softcore" words +as LZ77 compressed text. Decompression is so quick as to be +nearly unmeasurable (0.00384 seconds on a 750MHz AMD Duron-based +machine). And even with the runtime decompressor, the resulting +Ficl executable is over 13k smaller! +<p> + +Another new feature: Ficl 4.0 can take advantage of native +support for double-word math. If your platform supports it, +set the preprocessor symbol <code>FICL_HAVE_NATIVE_2INTEGER</code> +to 1, and create <code>typedefs</code> for <code>ficl2Integer</code> +and <code>ficl2Unsigned</code>. +<p> + +Ficl 4.0 also features a retooled API, and a redesigned directory +tree. The API is now far more consistent. But for those of you +who are upgrading from Ficl 3.03 or before, you can enable API +backwards compatibility by turning on the compile-time flag +<code>FICL_WANT_COMPATIBILITY</code>. +<p> + +Ficl 4.0 also extends support every kind of local and +global value imaginable. Every values can individually +be local or global, single-cell or double-cell, and +integer or floating-point. +And <code>TO</code> <i>always</i> does the right thing. +<p> + +If you're using Ficl under Windows, you'll be happy +to know that there's a brand-new build process. +The Ficl build process now builds Ficl as +<ul> + +<li> +a static library (.LIB), + +<li> +a dynamic library (.DLL, with a .LIB import library), and + +<li> +a standalone executable (.EXE). + +</ul> + +Furthermore, each of these targets can be built in +Debug or Release, Singlethreaded or Multithreaded, +and optionally using the DLL version of the C runtime +library for Multithreaded builds. (And, plus, the +<code>/objects/common</code> nonsense is gone!) +<p> + + +Finally, Ficl 4.0 adds a <code>contrib</code> +directory, a repository for user-contributed code that isn't +part of the standard Ficl release. The only package there +right now is <b>XClasses</b>, a Python-based IDL that generates +the definition files for C++-based classes, the equivalent Ficl +classes, and code to allow the Ficl classes to call the C++ methods. +Using <b>XClasses</b> you can write your class once, and use it +immediately from both C++ and Ficl. + + +<? ficlHeader1("Getting Ficl") ?> + +You can download Ficl from the +<a href=http://sourceforge.net/project/showfiles.php?group_id=24441> +Ficl download page at Sourceforge</a>. + + +<? ficlPageFooter() ?> diff --git a/doc/source/license.ht b/doc/source/license.ht new file mode 100644 index 000000000000..50b92b5f1432 --- /dev/null +++ b/doc/source/license.ht @@ -0,0 +1,47 @@ +<? +ficlPageHeader("ficl licensing") + +ficlAddToNavBarAs("Licensing") + +ficlHeader1("Ficl License And Disclaimer") + +?> + +<font size=+1> +Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) +<br> +All rights reserved. +</font> +<p> + +<b> +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +<ol> + +<li> +Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +<li> +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +</ol> + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +</b> + +<? ficlPageFooter() ?> diff --git a/doc/source/links.ht b/doc/source/links.ht new file mode 100644 index 000000000000..743b222c3fa3 --- /dev/null +++ b/doc/source/links.ht @@ -0,0 +1,156 @@ +<? +ficlPageHeader("ficl links") + +ficlAddToNavBarAs("Links") + +def linkto(href): + print "<p><dt>\n<a href=\"" + href + "\">" + href + "</a>\n<dd>\n" + +?> + +<? ficlHeader1("Official Ficl Pages") ?> + +<dl> + +<? linkto("http://ficl.sourceforge.net") ?> +The official web home of Ficl. + +<? linkto("http://sourceforge.net/project/showfiles.php?group_id=24441") ?> +The Ficl download page. + + +</dl> + + + +<? ficlHeader1("Forth Primers And Tutorials") ?> + +<dl> + +<? linkto("http://www.phys.virginia.edu/classes/551.jvn.fall01/primer.htm") ?> +An excellent Forth primer, by Julian Nobel. + +<? linkto("http://ficl.sourceforge.net/pdf/Forth_Primer.pdf") ?> +Another excellent Forth primer, by Hans Bezemer. + +<? linkto("http://www.taygeta.com/forth_intro/stackflo.html") ?> +<i>An Introduction To Forth Using Stack Flow</i> by Gordon Charton. +Mr. Charton's stack-flow diagrams make it easy to understand how +to manipulate the FORTH stacks. + +<? linkto("http://www.softsynth.com/pforth/pf_tut.htm") ?> +Phil Burk's Forth Tutorial. + +</dl> + + + +<? ficlHeader1("Technical Articles On Ficl And Forth") ?> + +<dl> + +<? linkto("articles/ficlddj.pdf") ?> +Manuscript of John Sadler's article on Ficl for January 1999 <a href=http://www.ddj.com>Dr. Dobb's Journal</a>. + +<? linkto("articles/jwsforml.pdf") ?> +1998 FORML Conference paper: <i>OO Programming in Ficl,</i> written and presented by John Sadler. + + +<? linkto("http://www.complang.tuwien.ac.at/forth/threaded-code.html") ?> +Anton Ertl's description of threaded code techniques. (The FORTH-related definition +of "threaded code" is different from—and predates—the common modern +usage dealing with light-weight processes.) Ficl 4 uses what Ertl calls +"switch threading". + +<? linkto("http://ficl.sourceforge.net/dpans/dpans.htm") ?> +1994 Draft Proposed American National Standard for Forth. +And surprisingly readable, as language standards go. + +<? linkto("http://www.taygeta.com/forthlit.html") ?> +Forth literature index on Taygeta, a web clearinghouse of Forth links. + +</dl> + +<? ficlHeader1("Other Forth Sites Of Interest") ?> + +<dl> + +<? linkto("http://www.forth.org") ?> +The Forth Interest Group. + +<? linkto("http://www.forth.com") ?> +FORTH, Incorporated. Thirty years old and going strong. +You might be surprised to learn that they wrote software for +the <a href=http://www.forth.com/Content/Stories/FedEx.htm>FedEx</a> +"SuperTracker" bar code scanners / package trackers. + +</dl> + +<table width=100% bgcolor=#e0e0e0><tr><td width=160> +<A href="http://t.webring.com/hub?sid=&ring=forth&list"><IMG src="graphics/4ring.gif" width="155" height="140" border="0" alt="Forth Webring Logo"></A> +</td><td> +<? ficlHeader1("The Forth Web Ring") ?> +<A href="http://t.webring.com/hub?sid=&ring=forth&id=47&prev5">Previous 5 Sites</A><BR> +<A href="http://t.webring.com/hub?sid=&ring=forth&id=47&prev">Previous</A><BR> +<A href="http://t.webring.com/hub?sid=&ring=forth&id=47&next">Next</A><BR> +<A href="http://t.webring.com/hub?sid=&ring=forth&id=47&next5">Next 5 Sites</A><BR> +<A href="http://t.webring.com/hub?sid=&ring=forth&random">Random Site</A><BR> +<A href="http://t.webring.com/hub?sid=&ring=forth&list">List Sites</A></FONT> +</td></tr></table> + + + +<? ficlHeader1("Some Software That Uses Ficl") ?> + +<ul> +<li> +The <a href="http://www.freebsd.org/">FreeBSD</a> boot loader +(Daniel Sobral, Jordan Hubbard) + +<li> +<a href="http://www.chipcenter.com/networking/images/prod/prod158a.pdf"> +SwitchCore +</a> +Gigabit Ethernet switches (Örjan Gustavsson ) + +<li> +<a href="http://debuffer.sourceforge.net/"> +Palm Pilot Debuffer +</a> +(Eric Sessoms) +Also see <a href=http://sonic-weasel.org/eric/ficlx/>FiclX</a>, a C++ interface to Ficl. + +<li> +<a href="http://www.swcp.com/%7Ejchavez/osmond.html"> +Osmond PC Board Layout tool +</a> + +<li> +<a href="http://www.netcomsystems.com"> +NetCom Systems +</a> +ML7710 + +<li> +<a href="http://www.parview.com/ds/homepage.html"> +ParView +</a> +GPS system + +<li> +<a href="http://www.thekompany.com/products/powerplant/software/Languages/Embedded.php3"> +PowerPlant Software +</a> +Development Environment for Linux + +<li> +<a href="http://www.vyyo.com/products/architecture_v3000.html"> +Vyyo V3000 Broadband Wireless Hub +</a> + +</ul> + +(Contact us if you'd like your name and product listed here.) + + +<? ficlPageFooter() ?> diff --git a/doc/source/locals.ht b/doc/source/locals.ht new file mode 100644 index 000000000000..e75ac82c4908 --- /dev/null +++ b/doc/source/locals.ht @@ -0,0 +1,133 @@ +<? + +ficlPageHeader("local variables in Ficl") + +ficlAddToNavBarAs("Locals") + +def entry(definition, description): + print "<tr><td bgcolor=#e0e0e0>\n<b>" + definition + "</b>\n</td><td bgcolor=#f0f0f0>\n" + description + "\n</td></tr>\n" + +?> + + +<? ficlHeader1("An Overview And A History") ?> + + + +Named, locally scoped variables came late to Forth. Purists feel that experienced +Forth programmers can (and should) write supportable code using only anonymous +stack variables and good factoring, and they complain that novices use +global variables too frequently. But local variables cost little in terms of +code size and execution speed, and are very convenient for OO programming +(where stack effects are more complex). +<p> + +Ficl provides excellent support +for local variables, and the purists be damned—we use 'em all the time. +<p> + +Local variables can only be declared inside a definition, +and are only visible in that definition. Please refer to +<a href="http://ficl.sourceforge.net/dpans/dpans13.htm"> +the ANS standard for FORTH +</a> for more general information on local variables. + + +<? ficlHeader1("John-Hopkins Forth Argument Syntax") ?> + +ANS Forth does not specify a complete local variable facility. +Instead, it defines a foundation upon which to build one. Ficl comes with +an adaptation of the Johns-Hopkins local variable syntax, as developed by John +Hayes et al. However, Ficl extends this syntax with support for double-cell and +floating-point numbers. + +<p> + +Here's the basic syntax of a JH-local variable declaration: +<blockquote><code> +<b>{</b> <i>arguments</i> +<b>|</b> <i>locals</i> +<b>--</b> <i>ignored</i> +<b>}</b> +</code></blockquote> +(For experienced FORTH programmers: the declaration is designed to look like a stack comment, +but it uses curly braces instead of parentheses.) Each section must list zero or more +legal Ficl word names; comments and preprocessing are not allowed here. +Here's what each section denotes: + +<ul> + +<li> +The <i>arguments</i> section lists local variables which are initialized from the stack when the word executes. +Each argument is set to the top value of the stack, starting at the rightmost argument name and moving left. +You can have zero or more arguments. +<p> + +<li> +The <i>locals</i> section lists local variables which are set to zero when the word executes. +You can have zero or more locals. +<p> + +<li> +Any characters between <code>--</code> and <code>}</code> are treated as a comment, and ignored. + +</ul> + +(The <code>|</code> and <code>--</code> sections are optional, +but they must appear in the order shown if they appear at all.) +<p> + + +<? ficlHeader2("Argument Types") ?> + +Every time you specify a local variable (in either the <i>arguments</i> or the <i>locals</i> section), +you can also specify the <i>type</i> of the local variable. By default, a local variable +is a single-cell integer; you can specify that the local be a double-cell integer, and/or a +floating-point number. +<p> + +To specify the type of a local, specify one or more of the following single-character specifiers, +followed by a colon (<code>:</code>). + +<table> + +<? entry("1", "single-cell") ?> + +<? entry("2", "double-cell") ?> + +<? entry("d", "double-cell") ?> + +<? entry("f", "floating-point (use floating stack)") ?> + +<? entry("i", "integer (use data stack)") ?> + +<? entry("s", "single-cell") ?> + +</table> + +For instance, the argument <code>f2:foo</code> would specify a double-width floating-point +number. +<p> + +The type specifiers are read right-to left, and when two specifiers conflict, the rightmost +one takes priority. So <code>2is1f2:foo</code> would still specifiy a double-width floating-point +number. +<p> + +Note that this syntax <i>only works</i> for Ficl's JH-locals. Locals +defined in some other way (say, with the FORTH standard word <code>LOCALS|</code>) +will ignore this syntax, and the entire string will be used as the name of +the local (type and all). + +<? ficlHeader2("A Simple Example") ?> + +<pre> +: DEMONSTRATE-JH-LOCALS { c b a f:float -- a+b f:float*2 } + a b + + 2.0e float f* + ; +</pre> + +<? +ficlPageFooter() +?>
\ No newline at end of file diff --git a/doc/source/oop.ht b/doc/source/oop.ht new file mode 100644 index 000000000000..c928eb0795b3 --- /dev/null +++ b/doc/source/oop.ht @@ -0,0 +1,1224 @@ +<? + +ficlPageHeader("ficl oop") + +ficlAddToNavBarAs("OOP In Ficl") + +def glossaryEntry(name, description): + print "<dt><code>" + name + " <i>" + description + "</i></code><dd>\n" + +?> + +<? ficlHeader1("Ficl Object Oriented Programming") ?> + + +Ficl's object extensions provide the traditional OO benefits of associating +data with the code that manipulates it, and reuse through single inheritance. +Ficl also has some unusual capabilities that support interoperation with +systems written in C. +<p> + +Some design points of Ficl's OOP system: + +<ul> + +<li> +Ficl objects are normally late bound for safety (late binding guarantees +that the appropriate method will always be invoked for a particular object). +Early binding is also available, provided you know the object's class at +compile-time. + +<li> +Ficl OOP supports single inheritance, aggregation, and arrays of objects. + +<li> +Classes have independent name spaces for their methods: methods are only +visible in the context of a class or object. Methods can be overridden +or added in subclasses; there is no fixed limit on the number of methods +of a class or subclass. + +<li> +Ficl OOP syntax is regular and unified over classes and objects. In ficl, +all classes are objects. Class methods include the ability to subclass +and instantiate. + +<li> +Ficl can adapt legacy data structures with object wrappers. You can model +a structure in a Ficl class, and create an instance that refers to an address +in memory that holds an instance of the structure. The <i>ref object</i> +can then manipulate the structure directly. This lets you wrap data structures +written and instantiated in C. + +</ul> + +<? ficlHeader2("Object-Oriented Programming concepts") ?> + +If you're not familiar with object-oriented programming, you +can click <a href="http://whatis.techtarget.com/definition/0,289893,sid9_gci212681,00.html">here</a> +or <a href="http://www.softwaredesign.com/objects.html">here</a> for +a general-purpose overview. +Or click <a href="articles/oo_in_c.html#review">here</a> for a short review of object-oriented ideas, +terms, and implementations in C. + +<? ficlHeader2("Acknowledgements") ?> + +Ficl is not the first Forth to include Object Oriented extensions. Ficl's +OO syntax owes a debt to the work of John Hayes and Dick Pountain, among +others. OO Ficl is different from other OO Forths in a few ways, though +(some things never change). First, unlike several implementations, the +syntax is documented (<a href="#ootutorial">below</a>) beyond the source +code. In Ficl's spirit of working with C code, the OO syntax provides means +to adapt existing data structures. I've tried to make Ficl's OO model simple +and safe by unifying classes and objects, providing late binding by default, +and separating namespaces so that methods and regular Forth words are not +easily confused. + + +<? ficlHeader2("Ficl Object Model") ?> + +All classes in Ficl are derived from the common base class +<code><a href="#objectgloss">OBJECT</a></code> +as shown in the <a href="#figure1">figure</a> below. All classes are instances +of <code><a href="#glossclass">METACLASS</a></code>. This means that classes +are objects, too. <code>METACLASS</code> implements the methods for messages +sent to classes. Class methods create instances and subclasses, and give +information about the class. Each class is represented by a data stucture +of three elements: + +<ol> + +<li> +The address (named <code>.CLASS</code> ) of a parent class, or zero if it's +a base class (only <code>OBJECT</code> and <code>METACLASS</code> have this property). + +<li> +The size (named <code>.SIZE</code> ) in address units of an instance of the +class. + +<li> +A wordlist ID (named <code>.WID</code> ) for the methods of the class. + +</ol> + +In the figure below, <code>METACLASS</code> and <code>OBJECT</code> are real system-supplied +classes. The others are contrived to illustrate the relationships among +derived classes, instances, and the two system base classes. The dashed +line with an arrow at the end indicates that the object/class at the arrow +end is an instance of the class at the other end. The vertical line with +a triangle denotes inheritance. +<p> + +Note for the curious: <code>METACLASS</code> behaves like a class—it responds +to class messages and has the same properties as any other class. If you +want to twist your brain in knots, you can think of <code>METACLASS</code> +as an instance of itself. +<p> + + +<a NAME="figure1"></a><img SRC="graphics/ficl_oop.jpg" VSPACE=10 height=442 width=652> +<br> + +<? ficlHeader2("Ficl Object-Oriented Syntax Tutorial") ?> +<a NAME="ootutorial"></a> + +It's helpful to have some familiarity with Forth and the customary Forth +stack notation to understand this tutorial. To get started, take a look +at this <a href="http://www.taygeta.com/forth_intro/stackflo.html">web-based +Forth tutorial</a>. If you're comfortable with both OO and Forth, you can +<a href="#ootutorial-finally">jump ahead</a>. +<p> + +A Ficl <a href="oo_in_c.html#object-def">object</a> associates a <a href="oo_in_c.html#class-def">class</a> +with an <a href="oo_in_c.html#instance-def">instance</a> (the storage for +one set of instance variables). This is done explicitly on Ficl's stack, +in that any Ficl object is represented by a cell pair: +<blockquote><code>( INSTANCE-address CLASS-address )</code></blockquote> + +The <code>INSTANCE-address</code> is the address of the object's storage, and the <code>CLASS-address</code> +is the address of its class. Whenever a named Ficl object executes (e.g. +when you type its name and press enter at the Ficl prompt), it leaves this +"signature". All methods by convention expect a class and instance on the +stack when they execute, too. In many other OO languages, including C++, +instances contain information about their classes (a <a href="http://www.mvps.org/vbvision/vtable.htm">vtable</a> +pointer, for example). By making this pairing explicit rather than implicit, +Ficl can be OO about chunks of data that don't realize that they are objects, +without sacrificing any robustness for native objects. That means that +you can use Ficl to write object wrappers for data structures created in +C or assembly language, as long as you can determine how they're laid out +in memory. +<p> + +Whenever you create an object in Ficl, you specify its class. +After that, the object always pushes its class and the address of its +<a href="http://www.aware.com/Glossary/main.htm#P">payload</a> +(instance variable space) when invoked by name. +<p> + +Classes are special kinds of objects that store the methods of their +instances, the size of an instance's payload, and a parent class pointer. +Classes themselves are instances of a special base class called <code>METACLASS</code>, +and all classes inherit from class <code>OBJECT</code>. This is confusing at +first, but it means that Ficl has a very simple syntax for constructing +and using objects. Class methods include subclassing (<code>SUB</code>), creating +initialized and uninitialized instances (<code>NEW</code> and <code>INSTANCE</code>), +and creating reference instances (<code>REF</code>), described later. Classes +also have methods for disassembling their methods (<code>SEE</code>), identifying +themselves (<code>ID</code>), and listing their pedigree (<code>PEDIGREE</code>). +All objects inherit (from <code>OBJECT</code>) methods for initializing instances +and arrays of instances, for performing array operations, and for getting +information about themselves. + +<? ficlHeader3("Methods And Messages") ?> + +Methods are the functions that objects execute in response to messages. +A message is a request to an object for a behavior that the object supports. +When it receives a message, the target object looks up a method that performs +the behavior for its class, and executes it. Any specific message may be +bound to different methods in different objects, according to class. This +separation of messages and methods allows objects to behave <a href="http://www.whatis.com/polymorp.htm">polymorphically</a>. +(In Ficl, methods are words defined in the context of a class, and messages +are the names of those words.) Ficl classes associate messages with methods +for their instances (a fancy way of saying that each class owns a wordlist). +Ficl provides a late-binding operator <code>--></code> that sends messages +to objects at run-time, and an early-binding operator <code>=></code> +that compiles a specific class's method. These operators are the only supported +way to invoke methods. Regular Forth words are not visible to the method-binding +operators, so there's no chance of confusing a message with a regular +word of the same name. + +<a NAME="ootutorial-finally"></a> + +<? ficlHeader2("Tutorial") ?> + +(Finally!) +<p> + +This is a tutorial. It works best if you follow along by pasting the examples +into <b>ficlWin</b>, the Win32 version of Ficl included with the release sources +(or some other build that includes the OO part of <code>softcore.c</code>). If you're +not familiar with Forth, please see one of these <a href="#links">references</a>. +Ficl's OOP words are in vocabulary <code>OOP</code>. To put <code>OOP</code> in +the search order and make it the compilation wordlist, type: +<pre> +ONLY +ALSO OOP DEFINITIONS +</pre> + +<b>Note for beginners:</b> To see the effect of the commands above, type +<code>ORDER</code> +after each line. You can repeat the sequence above if you like. +<p> + +To start, we'll work with the two base classes <code>OBJECT</code> and <code>METACLASS</code>. +Try this: +<pre> +METACLASS --> METHODS +</pre> + +The line above contains three words. The first is the name of a class, +so it pushes its signature on the stack. Since all classes are instances +of <code>METACLASS</code>, <code>METACLASS</code> behaves as if it is an instance +of itself (this is the only class with this property). It pushes the same +address twice: once for the class and once for the payload, since they +are the same. The next word finds a method in the context of a class and +executes it. In this case, the name of the method is <code>METHODS</code>. +Its job is to list all the methods that a class knows. What you get when +you execute this line is a list of all the class methods Ficl provides. +<pre> +OBJECT --> SUB C-LED +</pre> +Causes the base-class <code>OBJECT</code> to derive from itself a new class +called <code>C-LED</code>. Now we'll add some instance variables and methods to the new class. +<p> + +<b>Note:</b> I like to prefix the names of classes with <code>c-</code> and the +names of member variables with a period, but this is just a convention. +If you don't like it, pick your own. +<pre> +C-BYTE OBJ: .STATE +: INIT { 2:THIS -- } + THIS --> SUPER --> INIT + ." Initializing an instance of " + THIS --> CLASS --> ID TYPE CR ; +: ON { LED# 2:THIS -- } + THIS --> .STATE --> GET + 1 LED# LSHIFT OR DUP !OREG + THIS --> .STATE --> SET ; +: OFF { LED# 2:THIS -- } + THIS --> .STATE --> GET + 1 LED# LSHIFT INVERT AND DUP !OREG + THIS --> .STATE --> SET&NBSP; ; +END-CLASS +</pre> +The first line adds an instance variable called <code>.STATE</code> to the +class. This particular instance variable is an object—it will be an instance +of <code>C-BYTE</code>, one of Ficl's stock classes (the source for which can be found +in the distribution in <code>softcore/classes.fr</code>). +<p> + +Next we've defined a method called <code>INIT</code>. This line also declares +a <a href="locals.html">local variable</a> called <code>THIS</code> +(the 2 in front tells Ficl that this is a double-cell local). All methods +by convention expect the address of the class and instance on top of the +stack when called. The next three lines define the behavior of <code>INIT</code> when it's called. +It first calls its superclass's version of <code>INIT</code> (which in this +case is "<code>OBJECT => INIT</code>"—this default implementation clears all +instance variables). The rest displays some text and causes the instance +to print its class name (<code>THIS --> CLASS --> ID</code>). +<p> + +The <code>INIT</code>> method is special for Ficl objects: whenever +you create an initialized instance using <code>NEW</code> or <code>NEW-ARRAY</code>, +Ficl calls the class's <code>INIT</code> method for you on that instance. The +default <code>INIT</code> method supplied by <code>OBJECT</code> clears the instance, +so we didn't really need to override it in this case (see the source code +in <code>softcore/oo.fr</code>). +<p> + +The <code>ON</code> and <code>OFF</code> methods defined above hide the details +of turning LEDs on and off. The interface to FiclWin's simulated hardware +is handled by <code>!OREG</code>. The class keeps the LED state in a shadow +variable (<code>.STATE</code>) so that <code>ON</code> and <code>OFF</code> can work +in terms of LED number rather than a bitmask. +<p> + +Now make an instance of the new class: +<pre> +C-LED --> NEW LED +</pre> + +And try a few things... +<pre> +LED --> METHODS +LED --> PEDIGREE +1 LED --> ON +1 LED --> OFF +</pre> + +Or you could type this with the same effect: +<pre> +LED 2DUP --> METHODS --> PEDIGREE +</pre> + +Notice (from the output of <code>METHODS</code>) that we've overridden the +<code>INIT</code> method supplied by object, and added two more methods for the member +variables. If you type <code>WORDS</code>, you'll see that these methods are +not visible outside the context of the class that contains them. The method +finder <code>--></code> uses the class to look up methods. You can use +this word in a definition, as we did in <code>INIT</code>, and it performs +late binding, meaning that the mapping from message (method name) to method +(the code) is deferred until run-time. To see this, you can decompile the +init method like this: +<pre> +C-LED --> SEE INIT +</pre> + +or +<pre> +LED --> CLASS --> SEE INIT +</pre> + +<? ficlHeader2("Early Binding") ?> + +Ficl also provides early binding if you ask for it. Early binding is not +as safe as late binding, but it produces code that is more compact and +efficient because it compiles method addresses rather then their names. +In the preferred uses of early binding, the class is assumed to be the +one you're defining. This kind of early binding can only be used inside +a class definition. Early bound methods still expect to find a class and +instance cell-pair on top of the stack when they run. +<p> + +Here's an example that illustrates a potential problem: +<pre> +OBJECT --> SUB C1 +: M1 { 2:THIS -- } ." C1'S M1" CR ; +: M2 { 2:THIS -- } ." Running " THIS MY=> M1 ; ( early ) +: M3 { 2:THIS -- } ." Running " THIS --> M1 ( late ) +END-CLASS +C1 --> SUB C2 +: M1 { 2:THIS -- } ." C2'S M1" CR ; +END-CLASS +C2 --> NEW I2 +I2 --> M1 ( runs the M1 defined in C2 ) +I2 --> M2 ( Is this what you wanted? ) +I2 --> M3 { runs the overridden M1) +</pre> + +Even though we overrode method <code>M1</code> in class <code>C2</code>, the definition of <code>M2</code> with +early binding forced the use of <code>M1</code> as defined in <code>C1</code>. If that's what you +want, great, but more often you'll want the flexibility of overriding parent +class behaviors appropriately. + +<ol> + +<li> +<code>MY=></code> binds early to a method in the class being defined, +as in the example above. + +<li> +<code>MY=[ ]</code> binds a sequence of methods in the current class. +Useful when the class has object members. Lines like +<code>THIS --> STATE --> SET</code> in the definition of <code>C-LED</code> above can be replaced with +<code>THIS MY=[ STATE SET ]</code> to use early binding. + +<li> +<code>=></code> (dangerous) pops a class off the stack and compiles +the method in that class. Since you have to specify the class explicitly, +there is a real danger that this will be out of sync with the class you +really wanted. I recommend you use <code>MY=></code> or <code>MY=[ ]</code> instead. + +</ol> + +Early binding using <code>=></code> is dangerous because it partially +defeats the data-to-code matching mechanism object oriented languages were +created to provide, but it does increase run-time speed by binding the +method at compile time. In many cases, such as the <code>INIT</code> method, +you can be reasonably certain of the class of thing you're working on. +This is also true when invoking class methods, since all classes are instances +of <code>METACLASS</code>. Here's an example from the definition of <code>METACLASS</code> +in oo.fr (don't paste this into ficlWin—it's already there): +<pre> +: NEW \ ( class metaclass "name" -- ) + METACLASS => INSTANCE --> INIT ; +</pre> + +Try this: +<pre> +METACLASS --> SEE NEW +</pre> + +Decompiling the method with <code>SEE</code> shows the difference between the +two strategies. The early bound method is compiled inline, while the late-binding +operator compiles the method name and code to find and execute it in the +context of whatever class is supplied on the stack at run-time. +<p> + +Notice that the primitive early-binding operator <code>=></code> requires +a class at compile time. For this reason, classes are <code>IMMEDIATE</code>, +meaning that they push their signature at compile time or run time. I'd +recommend that you avoid early binding until you're very comfortable with +Forth, object-oriented programming, and Ficl's OOP syntax. + +<? ficlHeader2("More About Instance Variables") ?> + +<i>Untyped</i> instance variable methods (created by <code>CELL: CELLS: CHAR:</code> +and <code>CHARS:</code>) just push the address of the corresponding instance +variable when invoked on an instance of the class. It's up to you to remember +the size of the instance variable and manipulate it with the usual Forth +words for fetching and storing. +<p> + +As advertised earlier, Ficl provides ways to objectify existing data +structures without changing them. Instead, you can create a Ficl class +that models the structure, and instantiate a <i>ref</i> from this class, +supplying the address of the structure. After that, the <i>ref instance</i> +behaves as a Ficl object, but its instance variables take on the values +in the existing structure. Example (from <code>softcore/ficlclass.fr</code>): +<pre> +OBJECT SUBCLASS C-WORDLIST + C-WORDLIST REF: .PARENT + C-PTR OBJ: .NAME + C-CELL OBJ: .SIZE + C-WORD REF: .HASH ( first entry in hash table ) + + : ? + --> GET-NAME ." ficl wordlist " TYPE CR ; + : PUSH DROP >SEARCH ; + : POP 2DROP PREVIOUS ; + : SET-CURRENT DROP SET-CURRENT ; + : GET-NAME DROP WID-GET-NAME ; + : WORDS { 2:THIS -- } + THIS MY=[ .SIZE GET ] 0 DO + I THIS MY=[ .HASH INDEX ] ( 2list-head ) + BEGIN + 2DUP --> GET-NAME TYPE SPACE + --> NEXT OVER + 0= UNTIL 2DROP CR + LOOP + ; +END-CLASS +</pre> + +In this case, <code>C-WORDLIST</code> describes Ficl's wordlist structure; +<code>NAMED-WID</code> creates a wordlist and binds it to a ref instance of +<code>C-WORDLIST</code>. +The fancy footwork with <code>POSTPONE</code> and early binding is required +because classes are immediate. An equivalent way to define <code>NAMED-WID</code> with +late binding is: +<pre> +: NAMED-WID ( c-address u -- ) + WORDLIST POSTPONE C-WORDLIST --> REF + ; +</pre> + +To do the same thing at run-time (and call it <code>MY-WORDLIST</code>): + +<pre>wordlist c-wordlist --> ref my-wordlist</pre> + +Now you can deal with the wordlist through the ref instance: +<pre> +MY-WORDLIST --> PUSH +MY-WORDLIST --> SET-CURRENT +ORDER +</pre> + +Ficl can also model linked lists and other structures that contain pointers +to structures of the same or different types. The class constructor word +<a href="#exampleref:"><code>REF:</code></a> +makes an aggregate reference to a particular class. See the <a href="#glossinstance">instance +variable glossary</a> for an <a href="#exampleref:">example</a>. +<p> + +Ficl can make arrays of instances, and aggregate arrays into class descripions. +The <a href="#glossclass">class methods</a> <code>ARRAY</code> and <code>NEW-ARRAY</code> +create uninitialized and initialized arrays, respectively, of a class. +In order to initialize an array, the class must define (or inherit) a reasonable +<code>INIT</code> method. <code>NEW-ARRAY</code> invokes it on each member of the array +in sequence from lowest to highest. Array instances and array members use +the object methods <code>INDEX</CODE>, <CODE>NEXT</CODE>, and <CODE>PREV</code> +to navigate. Aggregate a member array of objects using <a href="#arraycolon"><code>ARRAY:</code></a>. +The objects are not automatically initialized in this case—your class +initializer has to call <code>ARRAY-INIT</code> explicitly if you want +this behavior. +<p> + +For further examples of OOP in Ficl, please see the source file <code>softcore/ficlclass.fr</code>. +This file wraps several Ficl internal data structures in objects and gives +use examples. + + +<? ficlHeader1("Ficl String Classes") ?> +<a NAME="cstring"></a> + +<code>C-STRING</code> is a reasonably useful dynamic string class. +Source code for the class is located in <code>softcore/string.fr</code>. +Features: +dynamic creation and resizing; deletion, char cout, concatenation, output, +comparison; creation from quoted string constant (<code>S"</code>). +<p> +Examples of use: +<pre> +C-STRING --> NEW HOMER +S" In this house, " HOMER --> SET +S" we obey the laws of thermodynamics!" HOMER --> CAT +HOMER --> TYPE +</pre> + + +<? ficlHeader2("OOP Glossary") ?> + +<a NAME="oopgloss"></a> + +<b>Note:</b> With the exception of the binding operators (the first two definitions +here), all of the words in this section are internal factors that you don't +need to worry about. These words provide method binding for all classes +and instances. Also described are supporting words and execution factors. +All are defined in <code>softcore/oo.fr</code>. + +<dl> + +<? glossaryEntry("-->", "( instance class \"method-name\" -- xn )") ?> + +Late binding: looks up and executes the given method in the context of +the class on top of the stack. + +<? glossaryEntry("C->", "( instance class \"method-name\" -- xn exc )") ?> + +Late binding with <code>CATCH</code>: looks up and <code>CATCH</code>es the given +method in the context of the class on top of the stack, pushes zero or +exception code upon return. + +<? glossaryEntry("MY=>", "compilation: ( \"method-name\" -- ) execution: ( instance class -- xn )") ?> + +Early binding: compiles code to execute the method of the class being defined. +Only visible and valid in the scope of a <code>--> SUB</CODE> .. <CODE>END-CLASS</code> +class definition. + +<? glossaryEntry("MY=[", "compilation: ( \"obj1 obj2 .. method ]\" -- ) execution: ( instance class -- xn )") ?> + +Early binding: compiles code to execute a chain of methods of the class +being defined. Only visible and valid in the scope of a <code>--> SUB</CODE> +.. <CODE>END-CLASS</code> class definition. + +<? glossaryEntry("=>", "compilation: ( class metaclass \"method-name\" -- ) execution: ( instance class -- xn )") ?> + +Early binding: compiles code to execute the method of the class specified +at compile time. + +<? glossaryEntry("do-do-instance", "") ?> + +When executed, causes the instance to push its <code>( INSTANCE CLASS )</code> stack +signature. Implementation factor of <code>METACLASS --> SUB</code></b> . +Compiles <code>.DO-INSTANCE</code> in the context of a class; <code>.DO-INSTANCE</code> +implements the <code>DOES></code> part of a named instance. + +<? glossaryEntry("exec-method", "( instance class c-address u -- xn )") ?> + +Given the address and length of a method name on the stack, finds +the method in the context of the specified class and invokes it. Upon entry +to the method, the instance and class are on top of the stack, as usual. +If unable to find the method, prints an error message and aborts. + +<? glossaryEntry("find-method-xt", "( class \"method-name\" -- class xt )") ?> + +Attempts to map the message to a method in the specified class. If successful, +leaves the class and the execution token of the method on the stack. Otherwise +prints an error message and aborts. + +<? glossaryEntry("lookup-method", "( class c-address u -- class xt )") ?> + +Given the address and length of a method name on the stack, finds +the method in the context of the specified class. If unable to find the +method, prints an error message and aborts. + +<? glossaryEntry("parse-method", "compilation: ( \"method-name\" -- ) execution: ( -- c-address u )") ?> + +Parse <code>"method-name"</code> from the input stream and compile code to push its length +and address when the enclosing definition runs. +</dl> + +<? ficlHeader3("Instance Variable Glossary") ?> +<a NAME="glossinstance"></a> + +<b>Note:</b>: These words are only visible when creating a subclass! To +create a subclass, use the <code>SUB</code> method on <code>OBJECT</code> or any +class derived from it (<i>not</i> <code>METACLASS</code>). Source code for +Ficl OOP is in <code>softcore/oo.fr</code>. +<p> + +Instance variable words do two things: they create methods that do +san action appropriate for the type of instance variable they represent, +and they reserve space in the class template for the instance variable. +We'll use the term <i>instance variable</i> to refer both to the method +that gives access to a particular field of an object, and to the field +itself. Rather than give esentially the same example over and over, here's +one example that shows several of the instance variable construction words +in use: + +<pre> +OBJECT SUBCLASS C-EXAMPLE + CELL: .CELL0 + C-4BYTE OBJ: .NCELLS + 4 C-4BYTE ARRAY: .QUAD + CHAR: .LENGTH + 79 CHARS: .NAME +END-CLASS +</pre> + +This class only defines instance variables, and it inherits some methods +from <code>OBJECT</code>. Each untyped instance variable (<code>.CELL0</code>, <code>.LENGTH</code>, +<code>.NAME</code>) pushes its address when executed. Each object instance variable +pushes the address and class of the aggregate object. Similar to C, an +array instance variable leaves its base address (and its class) when executed. +The word <code>SUBCLASS</code> is shorthand for <code>--> sub</code> . + +<dl> + +<? glossaryEntry("CELL:", "compilation: ( offset \"name\" -- offset ) execution: ( -- cell-address )") ?> + +Create an untyped instance variable one cell wide. The instance variable +leaves its payload's address when executed. + +<? glossaryEntry("CELLS:", "compilation: ( offset nCells \"name\" -- offset' ) execution: ( -- cell-address )") ?> + +Create an untyped instance variable <code>nCells</code> cells wide. + +<? glossaryEntry("CHAR:", "compilation: ( offset \"name\" -- offset' ) execution: ( -- cell-address )") ?> + +Create an untyped member variable one character wide. + +<? glossaryEntry("CHARS:", "compilation: ( offset nChars \"name\" -- offset' ) execution: ( -- cell-address )") ?> + +Create an untyped member variable <code>nChars</code> characters wide. + +<? glossaryEntry("OBJ:", "compilation: ( offset class metaclass \"name\" -- offset' ) execution: ( -- instance class )") ?> + +Aggregate an uninitialized instance of <code>CLASS</code> as a member variable +of the class under construction. + +<? glossaryEntry("ARRAY:", "compilation: ( offset nObjects class metaclass \"name\" -- offset' ) execution: ( -- instance class )") ?> +<a NAME="arraycolon"></a> + +Aggregate an uninitialized array of instances of the class specified as +a member variable of the class under construction. + +<? glossaryEntry("EXAMPLEREF:", "compilation: ( offset class metaclass \"name\" -- offset' ) execution: ( -- ref-instance ref-class )") ?> + +Aggregate a reference to a class instance. There is no way to set the value +of an aggregated ref—it's meant as a way to manipulate existing data +structures with a Ficl OO model. For example, if your system contains a +linked list of 4 byte quantities, you can make a class that represents +a list element like this: + +<pre> +OBJECT SUBCLASS C-4LIST + C-4LIST REF: .LINK + C-4BYTE OBJ: .PAYLOAD +END-CLASS + +ADDRESS-OF-EXISTING-LIST C-4LIST --> REF MYLIST +</pre> + +<dd> +The last line binds the existing structure to an instance of the class +we just created. The link method pushes the link value and the class <code>C_4LIST</code>, +so that the link looks like an object to Ficl and like a struct to C (it +doesn't carry any extra baggage for the object model—the Ficl methods +alone take care of storing the class information). +<p> + +<b>Note:</b> Since a <code>REF:</code> aggregate can only support one class, it's good for +modeling static structures, but not appropriate for polymorphism. If you +want polymorphism, aggregate a <code>C_REF</code> (see <code>softcore/classes.fr</code> for source) +into your class—it has methods to set and get an object. +<p> + +By the way, it is also possible to construct a pair of classes that contain +aggregate pointers to each other. Here's an example: + +<pre> +OBJECT SUBCLASS AKBAR + SUSPEND-CLASS \ put akbar on hold while we define jeff + +OBJECT SUBCLASS JEFF + AKBAR REF: .SIGNIFICANT-OTHER + ( <i>... your additional methods here ...</i> ) +END-CLASS \ done with jeff + +AKBAR --> RESUME-CLASS \ resume defining akbar + JEFF REF: .SIGNIFICANT-OTHER + ( <i>... your additional methods here ...</i> ) +END-CLASS \ done with akbar +</pre> + +</dl> + +<a NAME="glossclass"></a> +<? ficlHeader1("Class Methods Glossary") ?> + +These words are methods of <code>METACLASS</code>. They define the manipulations +that can be performed on classes. Methods include various kinds of instantiation, +programming tools, and access to member variables of classes. Source is +in <code>softcore/oo.fr</code>. + +<dl> + +<? glossaryEntry("INSTANCE", "( class metaclass \"name\" -- instance class )") ?> + +Create an uninitialized instance of the class, giving it the name specified. +The method leaves the instance's signature on the stack (handy if you +want to initialize). Example: + +<pre> +C_REF --> INSTANCE UNINIT-REF 2DROP +</pre> + +<? glossaryEntry("NEW", "( class metaclass \"name\" -- )") ?> + +Create an initialized instance of class, giving it the name specified. +This method calls <code>INIT</code> to perform initialization. + +<? glossaryEntry("ARRAY", "( nObjects class metaclass \"name\" -- nObjects instance class )") ?> + +Create an array of <code>nObjects</code> instances of the specified class. +Instances are not initialized. Example: + +<pre> +10 C_4BYTE --> ARRAY 40-RAW-BYTES 2DROP DROP +</pre> + + +<? glossaryEntry("NEW-ARRAY", "( nObjects class metaclass \"name\" -- )") ?> + +Creates an initialized array of <code>nObjects</code> instances of the class. +Same syntax as <code>ARRAY</code>. + +<a NAME="alloc"></a> +<? glossaryEntry("ALLOC", "( class metaclass -- instance class )") ?> + +Creates an anonymous instance of <code>CLASS</code> from the heap (using a call +to <code>ficlMalloc()</code> to get the memory). Leaves the payload and class addresses +on the stack. Usage example: + +<pre> +C-REF --> ALLOC 2CONSTANT INSTANCE-OF-REF +</pre> +<p> + +Creates a double-cell constant that pushes the payload and class address +of a heap instance of <code>C-REF</code>. + +<a NAME="allocarray"></a> +<? glossaryEntry("ALLOC-ARRAY", "( nObjects class metaclass -- instance class )") ?> + +Same as <code>NEW-ARRAY</code>, but creates anonymous instances from the heap using +a call to <code>ficlMalloc()</code>. Each instance is initialized using the class's +<code>INIT</code> method. + +<a NAME="allot"></a> +<? glossaryEntry("ALLOT", "( class metaclass -- instance class )") ?> + +Creates an anonymous instance of <code>CLASS</code> from the dictionary. Leaves +the payload and class addresses on the stack. Usage example: + +<pre> +C-REF --> ALLOT 2CONSTANT INSTANCE-OF-REF +</pre> + +<p> + +Creates a double-cell constant that pushes the payload and class address +of a heap instance of <code>C-REF</code>. + +<a NAME="allotarray"></a> +<? glossaryEntry("ALLOT-ARRAY", "( nObjects class metaclass -- instance class )") ?> + +Same as <code>NEW-ARRAY</code>, but creates anonymous instances from the dictionary. +Each instance is initialized using the class's <code>INIT</code> method. + +<? glossaryEntry("REF", "( instance-address class metaclass \"name\" -- )") ?> + +Make a ref instance of the class that points to the supplied instance address. +No new instance space is allotted. Instead, the instance refers to the +address supplied on the stack forever afterward. For wrapping existing +structures. + + +<? glossaryEntry("SUB", "( class metaclass -- old-wid address[size] size )") ?> + +Derive a subclass. You can add or override methods, and add instance variables. +Alias: <code>SUBCLASS</code>. Examples: +<p> + +<pre> +C_4BYTE --> SUB C_SPECIAL4BYTE + ( <i>... your new methods and instance variables here ...</i> ) +END-CLASS +</pre> + +or + +<pre> +C_4BYTE SUBCLASS C_SPECIAL4BYTE + ( <i>... your new methods and instance variables here ...</i> ) +END-CLASS +</pre> + +<? glossaryEntry(".SIZE", "( class metaclass -- instance-size )") ?> + +Returns address of the class's instance size field, in address units. This +is a metaclass member variable. + +<? glossaryEntry(".SUPER", "( class metaclass -- superclass )") ?> + +Returns address of the class's superclass field. This is a metaclass member +variable. + +<? glossaryEntry(".WID", "( class metaclass -- wid )") ?> + +Returns the address of the class's wordlist ID field. This is a metaclass +member variable. + +<? glossaryEntry("GET-SIZE", "( -- instance-size )") ?> + +Returns the size of an instance of the class in address units. Imeplemented +as follows: + +<pre> +: GET-SIZE METACLASS => .SIZE @ ; +</pre> + +<? glossaryEntry("GET-WID", "( -- wid )") ?> + +Returns the wordlist ID of the class. Implemented as: + +<pre> +: GET-WID METACLASS => .WID @ ; +</pre> + +<? glossaryEntry("GET-SUPER", "( -- superclass )") ?> + +Returns the class's superclass. Implemented as + +<pre> +: GET-SUPER METACLASS => .super @ ; +</pre> + + +<? glossaryEntry("ID", "( class metaclass -- c-address u )") ?> + +Returns the address and length of a string that names the class. + + +<? glossaryEntry("METHODS", "( class metaclass -- )") ?> + +Lists methods of the class and all its superclasses. + + +<? glossaryEntry("OFFSET-OF", "( class metaclass \"name\" -- offset )") ?> + +Pushes the offset from the instance base address of the named member variable. +If the name is not that of an instance variable method, you get garbage. +There is presently no way to detect this error. Example: + +<pre> +metaclass --> offset-of .wid +</pre> + + +<? glossaryEntry("PEDIGREE", "( class metaclass -- )") ?> + + +Lists the pedigree of the class (inheritance trail). + +<? glossaryEntry("SEE", "( class metaclass \"name\" -- )") ?> + +Decompiles the specified method—obect version of <code>SEE</code>, from the +<code>TOOLS</code> wordset. + +</dl> + +<? ficlHeader1("<code>OBJECT</code> Base-Class Methods Glossary") ?> +<a NAME="objectgloss"></a> + +These are methods that are defined for all instances by the base class +<code>OBJECT</code>. +The methods include default initialization, array manipulations, aliases +of class methods, upcasting, and programming tools. + +<dl> + +<? glossaryEntry("INIT", "( instance class -- )") ?> + +Default initializer, called automatically for all instances created with +<code>NEW</code> +or <code>NEW-ARRAY</code>. Zero-fills the instance. You do not normally need +to invoke <code>INIT</code> explicitly. + +<? glossaryEntry("ARRAYINIT", "( nObjects instance class -- )") ?> + +Applies <code>INIT</code> to an array of objects created by <code>NEW-ARRAY</code>. +Note that <code>ARRAY:</code> does not cause aggregate arrays to be initialized +automatically. You do not normally need to invoke <code>ARRAY-INIT</code> explicitly. + +<? glossaryEntry("FREE", "( instance class -- )") ?> + +Releases memory used by an instance previously created with <code>ALLOC</code> +or <code>ALLOC-ARRAY</code>. <b>Note:</b> This method is not presently protected +against accidentally deleting something from the dictionary. If you do +this, Bad Things are likely to happen. Be careful for the moment to apply +free only to instances created with <code>ALLOC</code> or <code>ALLOC-ARRAY</code>. + +<? glossaryEntry("CLASS", "( instance class -- class metaclass )") ?> + +Convert an object signature into that of its class. Useful for calling +class methods that have no object aliases. + +<? glossaryEntry("SUPER", "( instance class -- instance superclass )") ?> + +Upcast an object to its parent class. The parent class of <code>OBJECT</code> +is zero. Useful for invoking an overridden parent class method. + +<? glossaryEntry("PEDIGREE", "( instance class -- )") ?> + +Display an object's pedigree—its chain of inheritance. This is an alias +for the corresponding class method. + +<? glossaryEntry("SIZE", "( instance class -- instance-size )") ?> + +Returns the size, in address units, of one instance. Does not know about +arrays! This is an alias for the class method <code>GET-SIZE</code>. + +<? glossaryEntry("METHODS", "( instance class -- )") ?> + +Class method alias. Displays the list of methods of the class and all superclasses +of the instance. + +<? glossaryEntry("INDEX", "( n instance class -- instance[n] class )") ?> + +Convert array-of-objects base signature into signature for array element +n. No check for bounds overflow. Index is zero-based, like C, so + +<pre> +0 MY-OBJ --> INDEX +</pre> + +is equivalent to + +<pre> +MY-OBJ +</pre> + +Check out the <a href="#minusrot">description of <code>-ROT</code></a> for +help in dealing with indices on the stack. + +<? glossaryEntry("NEXT", "( instance[n] class -- instance[n+1] )") ?> + +Convert an array-object signature into the signature of the next +object in the array. No check for bounds overflow. + +<? glossaryEntry("PREV", "( instance[n] class -- instance[n-1] class )") ?> + +Convert an object signature into the signature of the previous object +in the array. No check for bounds underflow. + +</dl> + + +<? ficlHeader2("Supplied Classes") ?> +<a NAME="stockclasses"></a> + +For more information on theses classes, see <code>softcore/classes.fr</code>. + +<dl> + +<? glossaryEntry("METACLASS", "") ?> + +Describes all classes of Ficl. Contains class methods. Should never be +directly instantiated or subclassed. Defined in <code>softcore/oo.fr</code>. Methods described +above. + +<? glossaryEntry("OBJECT", "") ?> + +Mother of all Ficl objects. Defines default initialization and array indexing +methods. Defined in <code>softcore/oo.fr</code>. Methods described above. + +<? glossaryEntry("C-REF", "") ?> + +Holds the signature of another object. Aggregate one of these into a data +structure or container class to get polymorphic behavior. Methods and members: + +<dl> + +<? glossaryEntry("GET", "( instance class -- ref-instance ref-class )") ?> +Push the referenced object value on the stack. + +<? glossaryEntry("SET", "( ref-instance ref-class instance class -- )") ?> +Set the referenced object being held. + +<? glossaryEntry(".INSTANCE", "( instance class -- a-address )") ?> +Cell member that holds the instance. + +<? glossaryEntry(".CLASS", "( instance class -- a-address )") ?> +Cell member that holds the class. + +</dl> + +<? glossaryEntry("C-BYTE", "") ?> + +Primitive class derived from <code>OBJECT</code>, with a 1-byte payload. <code>SET</code> +and <code>GET</code> methods perform correct width fetch and store. Methods and members: + +<dl> + +<? glossaryEntry("GET", "( instance class -- byte )") ?> +Push the object's value on the stack. + +<? glossaryEntry("SET", "( byte instance class -- )") ?> +Set the object's value from the stack. + +<? glossaryEntry(".PAYLOAD", "( instance class -- address )") ?> +Member holds instance's value. + +</dl> + +<? glossaryEntry("C-2BYTE", "") ?> + +Primitive class derived from <code>OBJECT</code>, with a 2-byte payload. <code>SET</code> +and <code>GET</code> methods perform correct width fetch and store. Methods and members: + +<dl> + +<? glossaryEntry("GET", "( instance class -- 2byte )") ?> +Push the object's value on the stack. + +<? glossaryEntry("SET", "( 2byte instance class -- )") ?> +Set the object's value from the stack. + +<? glossaryEntry(".PAYLOAD", "( instance class -- address )") ?> +Member holds instance's value. + +</dl> + +<? glossaryEntry("C-4BYTE", "") ?> +Primitive class derived from <code>object</code>, with a 4-byte payload. <code>SET</code> +and <code>GET</code> methods perform correct width fetch and store. Methods and members: + +<dl> + +<? glossaryEntry("GET", "( instance class -- 4byte )") ?> +Push the object's value on the stack. + +<? glossaryEntry("SET", "( 4byte instance class -- )") ?> +Set the object's value from the stack. + +<? glossaryEntry(".PAYLOAD", "( instance class -- address )") ?> +Member holds instance's value. + +</dl> + +<? glossaryEntry("C-CELL", "") ?> + +Primitive class derived from <code>OBJECT</code>, with a cell payload (equivalent +to <code>C-4BYTE</code> on 32 bit platforms, 64 bits wide on Alpha and other +64-bit platforms). <code>SET</code> +and <code>GET</code> methods perform correct width fetch and store. Methods and members: + +<dl> + +<? glossaryEntry("GET", "( instance class -- 4byte )") ?> +Push the object's value on the stack. + +<? glossaryEntry("SET", "( 4byte instance class -- )") ?> +Set the object's value from the stack. + +<? glossaryEntry(".PAYLOAD", "( instance class -- address )") ?> +Member holds instance's value. + +</dl> + +<? glossaryEntry("C-PTR", "") ?> + +Base class derived from <code>OBJECT</code> for pointers to non-object types. +This class is not complete by itself: several methods depend on a derived +class definition of <code>@SIZE</code>. Methods and members: + +<dl> + +<? glossaryEntry(".ADDR", "( instance class -- a-address )") ?> +Member variable, holds the pointer address. + +<? glossaryEntry("GET-PTR", "( instance class -- pointer )") ?> +Pushes the pointer address. + +<? glossaryEntry("SET-PTR", "( pointer instance class -- )") ?> +Sets the pointer address. + +<? glossaryEntry("INC-PTR", "( instance class -- )") ?> +Adds <code>@SIZE</code> to the pointer address. + +<? glossaryEntry("DEC-PTR", "( instance class -- )") ?> +Subtracts <code>@SIZE</code> to the pointer address. + +<? glossaryEntry("INDEX-PTR", "( i instance class -- )") ?> +Adds <code>i * @SIZE</code> to the pointer address. + +</dl> + +<? glossaryEntry("C-BYTEPTR", "") ?> + +Pointer to byte derived from <code>C-PTR</code>. Methods and members: + +<dl> + +<? glossaryEntry("@SIZE", "( instance class -- size )") ?> +Push size of the pointed-to object. + +<? glossaryEntry("GET", "( instance class -- byte )") ?> +Pushes the pointer's referent byte. + +<? glossaryEntry("SET", "( byte instance class -- )") ?> +Stores <code>byte</code> at the pointer address. + +</dl> + + + +<? glossaryEntry("C-2BYTEPTR", "") ?> + +Pointer to 2byte derived from <code>C-PTR</code>. Methods and members: + +<dl> + +<? glossaryEntry("@SIZE", "( instance class -- size )") ?> +Push size of the pointed-to object. + +<? glossaryEntry("GET", "( instance class -- 2byte )") ?> +Pushes the pointer's referent 2byte. + +<? glossaryEntry("SET", "( 2byte instance class -- )") ?> +Stores <code>2byte</code> at the pointer address. + +</dl> + + + +<? glossaryEntry("C-4BYTEPTR", "") ?> + +Pointer to 4byte derived from <code>C-PTR</code>. Methods and members: + +<dl> + +<? glossaryEntry("@SIZE", "( instance class -- size )") ?> +Push size of the pointed-to object. + +<? glossaryEntry("GET", "( instance class -- 4byte )") ?> +Pushes the pointer's referent 4byte. + +<? glossaryEntry("SET", "( 4byte instance class -- )") ?> +Stores <code>4byte</code> at the pointer address. + +</dl> + + +<? glossaryEntry("C-CELLPTR", "") ?> + +Pointer to cell derived from <code>C-PTR</code>. Methods and members: + +<dl> + +<? glossaryEntry("@SIZE", "( instance class -- size )") ?> +Push size of the pointed-to object. + +<? glossaryEntry("GET", "( instance class -- cell )") ?> +Pushes the pointer's referent cell. + +<? glossaryEntry("SET", "( cell instance class -- )") ?> +Stores <code>cell</code> at the pointer address. + +</dl> + + + +<? glossaryEntry("C-STRING", "") ?> + +Dynamically allocated string, similar to MFC's <code>CString</code>. +For more information, see <code>softcore/string.fr</code>. +Partial list of methods and members: + +<dl> + +<? glossaryEntry("GET", "( instance class -- c-address u )") ?> +Pushes the string buffer's contents as a <code>C-ADDR U</code> style string. + +<? glossaryEntry("SET", "( c-address u instance class -- )") ?> +Sets the string buffer's contents to a new value. + +<? glossaryEntry("CAT", "( c-address u instance class -- )") ?> +Concatenates a string to the string buffer's contents. + +<? glossaryEntry("COMPARE", "( c-address u instance class -- result )") ?> +Lexical compiration of a string to the string buffer's contents. +Return value is the same as the FORTH function <code>COMPARE</code>. + +<? glossaryEntry("TYPE", "( instance class -- )") ?> +Prints the contents of the string buffer to the output stream. + +<? glossaryEntry("HASHCODE", "( instance class -- i )") ?> +Returns a computed hash based on the contents of the string buffer. + +<? glossaryEntry("FREE", "( instance class -- )") ?> +Releases the internal buffer. + +</dl> + + +<? glossaryEntry("C-HASHSTRING", "") ?> + +Subclass of <code>C-STRING</code>, which adds a member variable to store a hashcode. +For more information, see <code>softcore/string.fr</code>. + +</dl> + +<? ficlPageFooter() ?> diff --git a/doc/source/parsesteps.ht b/doc/source/parsesteps.ht new file mode 100644 index 000000000000..ad083dce9d7a --- /dev/null +++ b/doc/source/parsesteps.ht @@ -0,0 +1,234 @@ +<? +ficlPageHeader("ficl parse steps") + +ficlAddToNavBarAs("Parse Steps") + +def entry(definition): + print "<dt>\n<code>" + definition + "</code>\n<dd>\n" + +?> + + +<? ficlHeader1("Parse Steps") ?> + +Unlike every other FORTH we know of, Ficl features an <i>extensible +parser chain</i>. The Ficl parser is not a monolithic function; instead, +it is comprised of a simple tokenizer and a series of <i>parse steps</i>. +A parse step is a step in the parser chain that handles a particular kind +of token, acting on the token as appropriate. Example parse steps, in +terms of traditional FORTH lore, would be the "number runner" and the +"colon compiler". +<p> + +The Ficl parser works like this: +<ol> + +<li> +Read in a new <i>token</i> (string of text with no internal whitespace). + +<li> +For each parse step in the chain, call the parse step, passing in the token. +If the parse step returns <code>FICL_TRUE</code>, that parse step must have +handled the token appropriately; move on to the next token. + +<li> +If the parser tries all the parse steps and none of them return +<code>FICL_TRUE</code>, the token is illegal—print an error +and reset the virtual machine. + +</ol> + +Parse steps can be written as native functions, or as Ficl script functions. +New parse steps can be appended to the chain at any time. + + +<? ficlHeader2("The Default Ficl Parse Chain") ?> + +These is the default Ficl parser chain, shown in order. + +<dl> + +<? entry("?word") ?> + +If compiling and local variable support is enabled, attempt to find the token in the local +variable dictionary. If found, execute the token's compilation semantics and return <code>FICL_TRUE</code>. +<p> + +Attempt to find the token in the system dictionary. If found, execute the token's semantics +(may be different when compiling than when interpreting) and return <code>FICL_TRUE</code>. + +<? entry("?prefix") ?> +This parse step is only active if prefix support is enabled, setting <code>FICL_WANT_PREFIX</code> +in <code>ficl.h</code> to a non-zero value. +Attempt to match the beginning of the token to the list of known prefixes. If there's a match, +execute the associated prefix method and return <code>FICL_TRUE</code>. + +<? entry("?number") ?> +Attempt to convert the token to a number in the present <code>BASE</code>. If successful, push the +value onto the stack if interpreting, otherwise compile it, then return <code>FICL_TRUE</code>. + +<? entry("?float") ?> +This parse step is only active if floating-point number support is enabled, +setting <code>FICL_WANT_FLOAT</code> in <code>ficl.h</code> to a non-zero value. +Attempt to convert the token to a floating-point number. If successful, push the +value onto the floating-point stack if interpreting, otherwise compile it, +then return <code>FICL_TRUE</code>. + +</dl> + + + +<? ficlHeader2("Adding A Parse Step From Within Ficl") ?> +<a name=ficlparsestep></a> + +You can add a parse step in two ways. The first is to write a Ficl word that +has the correct stack signature for a parse step: +<pre> +<i>MY-PARSE-STEP</i> ( c-addr u -- x*i flag ) +</pre> +where <code>c-addr u</code> are the address and length of the incoming token, +and <code>flag</code> is <code>FICL_TRUE</code> if the parse step processed +the token and <code>FICL_FALSE</code> otherwise. +<p> + +Install the parse step using <code>add-parse-step</code>. +A trivial example: +<pre> +: ?silly ( c-addr u -- flag ) + ." Oh no! Not another " type cr true ; +' ?silly add-parse-step +parse-order +</pre> + +<? ficlHeader2("Adding A Native Parse Step") ?> + +The other way to add a parse step is to write it in C and add it into the +parse chain with the following function: + +<pre> +void ficlSystemAddPrimitiveParseStep(ficlSystem *system, char *name, ficlParseStep step); +</pre> + +<code>name</code> is the display name of the parse step in the parse chain +(as displayed by the Ficl word <code>PARSE-ORDER</code>). <code>step</code> +is a pointer to the code for the parse step itself, +and must match the following declaration: +<pre> +typedef int (*ficlParseStep)(ficlVm *vm, ficlString s); +</pre> +<p> + +When a native parse step is run, <code>si</code> points to the incoming token. +The parse step must return <code>FICL_TRUE</code> if it succeeds in handling the +token, and <code>FICL_FALSE</code> otherwise. +See <code>ficlVmParseNumber()</code> in <code>system.c</code> for an example. + + +<? ficlHeader1("Prefixes") ?> + +What's a prefix, anyway? A prefix (contributed by Larry Hastings) is a token that's +recognized as the beginning of another token. Its presence modifies the semantics of +the rest of the token. An example is <code>0x</code>, which causes digits following +it to be converted to hex regardless of the current value of <code>BASE</code>. +<p> + +Caveat: Prefixes are matched in sequence, so the more of them there are, +the slower the interpreter gets. On the other hand, because the prefix +parse step occurs immediately after the dictionary lookup step, if you +have a prefix for a particular purpose, using it may save time since it +stops the parse process. Also, the Ficl interpreter is wonderfully fast, +and most interpretation only happens once, so it's likely you won't notice +any change in interpreter speed even if you make heavy use of prefixes. +<p> + +Each prefix is a Ficl word stored in a special wordlist called <code><PREFIXES></code>. When the +prefix parse step (<code>?prefix</code>, implemented in C as <code>ficlVmParsePrefix()</code>) is +executed, it searches each word in <code><PREFIXES></code> in turn, comparing it with the +initial characters of the incoming token. If a prefix matches, the parse step returns the remainder +of the token to the input stream and executes the code associated with the prefix. This code can be +anything you like, but it would typically do something with the remainder of the token. If the prefix +code does not consume the rest of the token, it will go through the parse process again (which may +be what you want). +<p> + +Prefixes are defined in <code>prefix.c</code> and in <code>softcore/prefix.fr</code>. +The best way to add prefixes is by defining them in your own code, bracketed with the special +words <code>START-PREFIXES</code> and <code>END-PREFIXES</code>. For example, the following +code would make <code>.(</code> a prefix. + +<pre> +start-prefixes +: .( .( ; +end-prefixes +</pre> +<p> + +The compile-time constant <code>FICL_EXTENDED_PREFIX</code> controls the inclusion of +several additional prefixes. This is turned off in the default build, since several +of these prefixes alter standard behavior, but you might like them. + + +<? ficlHeader1("Notes") ?> + +<ul> + +<li> +Prefixes and parser extensions are non-standard. However, with the exception of +prefix support, Ficl's default parse order follows the standard. +Inserting parse steps in some other order will almost certainly break standard behavior. +<p> + +<li> +The number of parse steps that can be added to the system is limited by the value of +<code>FICL_MAX_PARSE_STEPS</code> (defined in <code>sysdep.h</code>). The default +maximum number is 8. +<p> + +<li> +The compile-time constant <code>FICL_EXTENDED_PREFIX</code> controls the inclusion of +several additional prefixes. This is turned off in the default build, since several +of these prefixes alter standard behavior, but you might like them. +<p> + + +</ul> + +<? ficlHeader1("Parser Glossary") ?> + +<dl> + +<? entry("PARSE-ORDER ( -- )") ?> + +Prints the list of parse steps, in the order in which they are called. + +<? entry("ADD-PARSE-STEP ( xt -- )") ?> + +Appends a parse step to the parse chain. <code>xt</code> is the address +(execution token) of a Ficl word to use as the parse step. The word must be a +legal Ficl parse step (<a href=#ficlparsestep>see above</a>). + +<? entry("SHOW-PREFIXES ( -- )") ?> + +Prints the list of all prefixes. Each prefix is a Ficl word that is executed if its name +is found at the beginning of a token. + +<? entry("START-PREFIXES ( -- )") ?> + +Declares the beginning of a series of prefix definitions. +Should be followed, eventually, by <code>END-PREFIXES</code>. +(All <code>START-PREFIXES</code> does is tell the Ficl virtual machine +to compile into the <code><PREFIXES></code> wordlist.) + +<? entry("END-PREFIXES ( -- )") ?> + +Declares the end of a series of prefix definitions. +Should only be used after calling <code>START-PREFIXES</code>. +(All <code>END-PREFIXES</code> does is tell the Ficl virtual machine +to switch back to the wordlist that was in use before <code>START-PREFIXES</code> was called.) + +</dl> + + +<? +ficlPageFooter() +?>
\ No newline at end of file diff --git a/doc/source/releases.ht b/doc/source/releases.ht new file mode 100644 index 000000000000..a594bb8e02f9 --- /dev/null +++ b/doc/source/releases.ht @@ -0,0 +1,1003 @@ +<? +ficlPageHeader("ficl release history") + +ficlAddToNavBarAs("Release History") + +def ficlVersion(s): + ficlHeader1(s) + +?> + +<? ficlVersion("Version 4.0.31") ?> +<ul> + +<li> +First official release of new engine as Ficl 4! Hooray! + +<li> +<code>ficlDictionarySee()</code> now takes a <code>ficlCallback</code>, +so it knows where to print to. This is because <b>ficlWin</b> only +sets a per-VM callback, which <i>should</i> work. + +<li> +<code>ficlSystemCreate()</code> now passes in the system correctly +into the dictionaries it creates, which lets dictionaries know what +system they're a part of. + +<li> +ficlCompatibility: Forgot to add the <code>errorTextOut</code> to the +<code>ficl_system</code> structure (though I'd remembered to add it to +the <code>ficl_vm</code> structure). This caused the <code>ficl_system</code> +members after <code>textOut</code> to not line up with their equivalent +<code>ficlSystem</code> members, which did bad things. (The bad thing +in particular was calling <code>ficlDictionaryResetSearchOrder()</code> +resulted in diddling the <code>vm->link</code> member, which strangely +enough resulted in double-freeing the stacks.) + +<li> +Added <code>ficlStackWalk()</code>, which walks a stack from top +to bottom and calls your specified callback with each successive +element. Cleaned up stack-printing functions as a result. + +<li> +Changed <code>MULTICALL</code> so you can explicitly specify the vtable. + +<li> +Changed XClasses so it explicitly specifies the vtable for +non-virtual classes. This means you can now call a virtual +method when you've <code>SUPER</code>ed an object and you'll +get the method you wanted. + +<li> +XClasses improvement: when removing a thunked method, remove +the thunk variable too. Added <code>xClass.removeMember()</code> +to support this. + +<li> +XClasses now generates runtime stack-check code (<code>_DEBUG</code> +only) for functions thunked from C to Ficl. + +<li> +<code>FICL_WANT_PLATFORM</code> is now <code>0</code> by default. +It is now set to <code>1</code> in the appropriate <code>ficlplatform/*.h</code>. + +<li> +<code>softcore/win32.fr ENVIRONMENT? COMPARE<code> needed to be case-insensitive. + +<li> +Whoops! Setting <code>FICL_PLATFORM_2INTEGER</code> to 0 +didn't compile. It now does, and works fine, as proved by +the <code>ansi</code> platform. + +<li> +Another whoops: contrib/xclasses/xclasses.py assumed that <code>"</code> (a prefix +version of <code>S"</code>) defined. Switched to <code>S"</code>, which is safer. + +</ul> + +<? ficlVersion("Version 4.0.30") ?> + +<ul> + +<li> +Cleaned up some <code>FICL_</code> definitions. Now all <code>FICL_HAVE_*</code> constants +(and some other odds and ends) have been moved to <code>FICL_PLATFORM_</code>. + +<li> +Whoops! Setting <code>FICL_PLATFORM_2INTEGER</code> to 0 didn't +compile. It now does, and works fine, as proved by +the <code>"ansi"</code> platform. + +<li> +Another whoops: <code>contrib/xclasses/xclasses.py</code> assumed that <code>"</code> (a prefix +version of <code>S"</code>) defined. Switched to <code>S"</code>, which is safer. + +<li> +Added <code>ficlDictionarySetConstantString()</code>. 'Cause I needed it for: + +<li> +Removed the <code>"WIN32"</code> <code>ENVIRONMENT?</code> setting, and added <code>"FICL_PLATFORM_OS"</code> +and <code>"FICL_PLATFORM_ARCHITECTURE"</code> in its place. These are both <i>strings</i>. +Updated <code>softcore/win32.fr</code> to match. + +<li> +Compatibility: improved <code>ficlTextOut()</code> behavior. It makes life slightly +less convenient for some users, but should be an improvement overall. +The change: <code>ficlTextOut()</code> is now a compatibility-layer function that +calls straight through to <code>vmTextOut()</code>. Lots of old code calls <code>ficlTextOut()</code> +(naughty!). It's now explicit that you must set the <code>textOut</code> function +by hand if you use a custom one... which is a good habit to get in to anyway. + +<li> +Improved the documentation regarding upgrading, <code>ficllocals.h</code>, and compile-time +constants. + +<li> +Fixed <code>doc/source/generate.py</code> so it gracefully fails to copy over read-only +files. + +<li> +Got rid of every <code>#ifdef</code> in the sources. We now consistently use <code>#if defined()</code> +everywhere. Similarly, got rid of all platform-switched <code>#if</code> code (except for the +compatibility layer, sigh). + +</ul> + +<? ficlVersion("Version 4.0.29") ?> + +<ul> + +<li> +Documentation totally reworked and updated. + +<li> +<code>oldnames</code> renamed to <code>compatibility</code>. +And improved, so that now Ficl 4 is basically a drop-in +replacement for Ficl 3. + +</ul> + +<? ficlVersion("Version 4.0.28") ?> + +<ul> + +<li> +Did backwards-compatibility testing. Ficl now drops in, more or less, +with all the old Ficl-3.03-using projects I had handy. + +<li> +Got Ficl compiling and running fine on Linux. + +<li> +Weaned LZ77 code from needing htonl()/ntohl(). + +<li> +Moved all the primitives defined in "testmain.c" to their own file, +"extras.c", and gave it its own global entry point. + +<li> +Renamed "testmain.c" to just plain "main.c". + +<li> +Renamed "softwords" directory to "softcore". More symmetrical. + +<li> +Renamed "softcore\softcore.bat" to "make.bat". Added support for "CLEAN". + +</ul> + +<? ficlVersion("Version 4.0.27") ?> +<ul> + +<li> +Added runtime jump-to-jump peephole optimization in the new +switch-threaded VM. + +<li> +Fixed <code>INCLUDE-FILE</code> so it rethrows an exception in the +subordinate evaluation. + +<li> +Added a separate <code>errorOut</code> function to +<code>ficlCallback()</code>, +so under Windows you can have a jolly popup window to +rub your nose in your failings. + +</ul> + +<? ficlVersion("Version 4.0.26") ?> +<ul> + +<li> +Namespace policing complete. There are now <i>no</i> external symbols +which do not start with the word <code>ficl</code>. + +<li> +Removed <code>ficlVmExec()</code>, renamed <code>ficlVmExecC()</code> to +<code>ficlVmExecuteString()</code>, changed it to take a <code>ficlString()</code>. +This is deliberate subterfuge on my part; I suspect most +people who currently call <code>ficlVmExec() / ficlVmExecC()</code> +should be calling <code>ficlVmEvaluate()</code>. +</ul> + +<? ficlVersion("Version 4.0.25") ?> +<ul> + +<li> +First pass at support for "oldnames", and namespace policing. + +</ul> + +<? ficlVersion("Version 4.0.23") ?> +First alpha release of Ficl 4.0 rewrite. Coded, for better +or for worse, by Larry Hastings. +Ficl is <i>smaller</i>, <i>faster</i>, <i>more powerful</i>, +and <i>easier to use</i> than ever before. (Or your money back!) +<ul> +<li> +Rewrote Ficl's virtual machine; Ficl now runs nearly 3x faster out-of-the-box. +The new virtual machine is of the "big switch statement" variety. + +<li> +Renamed most (probably all) external Ficl functions and data structures. +They now make sense and are (gasp!) consistent. + +<li> +Retooled double-cell number support to take advantage of platforms +which natively support double-cell-sized integers. (Like most modern +32-bit platforms.) + +<li> +Locals and VALUEs are now totally orthogonal; they can be single- or +double-cell, and use the float or data stack. TO automatically supports all variants. + +<li> +The "softcore" words can now be stored compressed, with a (current) +savings of 11k. Decompression is nigh-instantaneous. You can choose +whether or not you want softcore stored compressed at compile-time. + +<li> +Reworked Win32 build process. Ficl now builds out-of-the-box on Win32 +as a static library, as a DLL, and as a command-line program, +in each of the six possible runtime variants (Debug,Release x Singlethreaded, +Multithreaded,Multithreaded DLL). + +<li> +There's very likely other wonderful things that I've long forgotten +about. If you notice them, feel free to remind me :) + +</ul> + +<? ficlVersion("Version 3.03") ?> +<ul> +<li> +Bugfix for floating-point numbers. Floats in compiled code were simply broken. + +<li> +New words: <code>random</code> and <code>seed-random</code> + +<li> +Bugfix: <code>included</code> never closed its file. + +<li> +Bugfix: <code>include</code> was not <code>IMMEDIATE</code>. + +<li> +Un-hid the OO words <code>parse-method</code>, <code>lookup-method</code>, and <code>find-method-xt</code>, as there are perfectly legitimate reasons why you might want to use them. + +<li> +Changed the prefix version of <code>.(</code> to be <code>IMMEDIATE</code> too. + +<li> +Fixed comment in Python softcore builder. + +<li> +Put the <b>doc</b> directory back in to the distribution. (It was missing from 3.02... where'd it go?) + +</ul> + + + +<? ficlVersion("Version 3.02") ?> +<ul> +<li> +Added support for <code>nEnvCells</code> (number of environment cells) to <code>FICL_SYSTEM_INFO</code>. + +<li> +Consolidated <code>context</code> and <code>pExtend</code> pointers of <code>FICL_SYSTEM</code>—VM's <code>pExtend</code> pointer is initialized from the copy in <code>FICL_SYSTEM</code> upon VM creation. + +<li> +Added <code>ficl-robust</code> environment variable. + +<li> +Added <code>FW_ISOBJECT</code> word type. + +<li> +Bugfix: <code>environment?</code> was ignoring the length of the supplied string. + +<li> +Portability cleanup in fileaccess.c. + +<li> +Bugfix in <code>ficlParsePrefix</code>: if the prefix dictionary isn't in the wordlist, the word being examined cannot be a prefix, so return failure. + +<li> +<code>SEE</code> improvements: <code>SEE</code> (and consequently <code>DEBUG</code>) have improved source listings with instruction offsets. + +<li> +It's turned off with the preprocessor, but we have the beginnings of a switch-threaded implementation of the inner loop. + +<li> +Added <code>objectify</code> and <code>?object</code> for use by OO infrastructure. + +<li> +<code>my=[</code> detects object members (using <code>?object</code>) and assumes all other members leave class unchanged. + +<li> +Removed <code>MEMORY-EXT</code> environment variable (there is no such wordset). + +<li> +Ficlwin changes: +<ul> +<li> +Ficlwin character handling is more robust + +<li> +Ficlwin uses multi-system constructs (see ficlthread.c) + +</ul> + +<li> +Documentation changes: +<ul> +<li> +Corrected various bugs in docs. + +<li> +Added ficl-ized version of JV Noble's Forth Primer + +<li> +Ficl OO tutorial expanded and revised. Thanks to David McNab for his demo and suggestions. + +</ul> + + +</ul> + +<? ficlVersion("Version 3.01") ?> +<ul> +<li> +Major contributionss by Larry Hastings (larry@hastings.org): +<ul> +<li> +FILE wordset (fileaccess.c) + +<li> +ficlEvaluate wrapper for ficlExec + +<li> +ficlInitSystemEx makes it possible to bind selectable properties to VMs at create time + +<li> +Python version of softcore builder ficl/softwords/softcore.py + +</ul> + +<li> +Environment contains ficl-version (double) + +<li> +?number handles trailing decimal point per DOUBLE wordset spec + +<li> +Fixed broken .env (thanks to Leonid Rosin for spotting this goof) + +<li> +Fixed broken floating point words that depended on evaluation order of stack pops. + +<li> +env-constant + +<li> +env-2constant + +<li> +dictHashSummary is now commented out unless FICL_WANT_FLOAT (thanks to Leonid Rosin again) + +<li> +Thanks to David McNab for pointing out that .( should be IMMEDIATE. Now it is. + +</ul> + +<? ficlVersion("Version 3.00a") ?> + +<ul> +<li> +Fixed broken oo.fr by commenting out vcall stuff using FICL_WANT_VCALL. Vcall is still broken. + +</ul> + +<? ficlVersion("Version 3.00") ?> + +<ul> +<li> +Added pSys parameter to most ficlXXXX functions for multiple system support. Affected functions: +<ul> +<li>dictLookupLoc renamed to ficlLookupLoc after addition of pSys param +<li>ficlInitSystem returns a FICL_SYSTEM* +<li>ficlTermSystem +<li>ficlNewVM +<li>ficlLookup +<li>ficlGetDict +<li>ficlGetEnv +<li>ficlSetEnv +<li>ficlSetEnvD +<li>ficlGetLoc +<li>ficlBuild +</ul> + + +<li>Fixed off-by-one bug in ficlParsePrefix +<li>Ficl parse-steps now work correctly - mods to interpret() +<li>Made tools.c:isAFiclWord more selective +<li>Tweaked makefiles and code to make gcc happy under linux +<li>Vetted all instances of LVALUEtoCELL to make sure they're working on CELL sized operands +(for 64 bit compatibility) +</ul> + +<? ficlVersion("Version 2.06") ?> +<ul> +<li>Debugger changes: +<ul> +<li>New debugger command "x" to execute the rest of the command line as ficl +<li>New debugger command "l" lists the source of the innermost word being debugged +<li>If you attempt to debug a primitive, it gets executed rather than doing nothing +<li><code>R.S</code> displays the stack contents symbolically +<li>Debugger now operates correctly under ficlwin, although ficlwin's key handling leaves a lot to be desired. +<li><code>SEE</code> listing enhanced for use with the debugger +</ul> +<li>Added Guy Carver's changes to oo.fr for VTABLE support +<li><code>float.c</code> words f> and >f to move floats to and from the param stack, analogous to >r and r> +<li><code>LOOKUP</code> - Surrogate precompiled parse step for ficlParseWord (this step is hard + coded in <code>INTERPRET</code>) +<li>License text at top of source files changed from LGPL to BSD by request +<li>Win32 console version now handles exceptions more gracefully rather than crashing - uses win32 +structured exception handling. +<li>Fixed BASE bug from 2.05 (was returning the value rather than the address) +<li>Fixed ALLOT bug - feeds address units to dictCheck, which expects Cells. Changed dictCheck +to expect AU. +<li>Float stack display word renamed to f.s from .f to be consistent with r.s and .s +</ul> + +<? ficlVersion("Version 2.05") ?> +<h3>General</h3> + +<ul> +<li>HTML documentation extensively revised +<li>Incorporated Alpha (64 bit) patches from the freeBSD team. +<li>Split SEARCH and SEARCH EXT words from words.c to search.c +<li><a href="ficl_loc.html">2LOCALS</a> defined in <a href="ficl_loc.html#jhlocal">Johns Hopkins local syntax</a> now lose the first '2:' in their names. +<li>Simple step <a href="ficl_debug.html">debugger</a> (see tools.c) +<li>The text interpreter is now extensible - this is accomplished through the use +of <code>ficlAddParseStep()</code>. <code>FICL_MAX_PARSE_STEPS</code> limits the number of parse steps +(default: 8). You can write a precompiled parse step (see <code>ficlParseNumber</code>) and +append it to the chain, or you can write one in ficl and use <code>ADD-PARSE-STEP</code> +to append it. Default parse steps are initialized in <code>ficlInitSystem</code>. You can list +the parse steps with <code>parse-order ( -- )</code>. +<li>There is now a FICL_SYSTEM structure. This is a transitional release - version 3.0 +will alter several API prototypes to take this as a parameter, allowing multiple +systems per process (and therefore multiple dictionaries). For those who use ficl +under a virtual memory O/S like Linux or Win NT, you can just create multiple ficl +processes (not threads) instead and save youself the wait. +<li>Fixes for improved command line operation in testmain.c (Larry Hastings) +<li>Numerous extensions to OO facility, including a new allot methods, ability +to catch method invocations (thanks to Daniel Sobral again) +<li>Incorporated Alpha (64 bit) patches contributed by Daniel Sobral and the freeBSD team +Ficl is now 64 bit friendly! UNS32 is now FICL_UNS. +<li>Split SEARCH and SEARCH EXT words from words.c to search.c +<li>ABORT" now complies with the ANS (-2 THROWs) +<li>Floating point support contributed by Guy Carver (Enable FICL_WANT_FLOAT in sysdep.h). +<li>Win32 vtable model for objects (Guy Carver) +<li>Win32 dll load/call suport (Larry Hastings) +<li>Prefix support (Larry Hastings) (prefix.c prefix.fr FICL_EXTENDED_PREFIX) makes it +easy to extend the parser to recignize prefixes like 0x and act on them. Use show-prefixes +to see what's defined. +<li>Cleaned up initialization sequence so that it's all in ficlInitSystem, and so that +a VM can be created successfully before the dictionary is created +</ul> + +<h3> +Bug fixes</h3> + +<ul> +<li> +<a href="http://www.taygeta.com/forth/dpans9.htm#9.6.2.0680">ABORT"</a> +now works correctly (I promise!) + +<li> +<a href="http://www.taygeta.com/forth/dpans6.htm#6.2.2125">REFILL</a> works +better + +<li> +<a href="http://www.taygeta.com/forth/dpans6.htm#6.1.0710">ALLOT</a>'s +use of dictCheck corrected (finally) +</ul> + +<h3> +New words</h3> + +<ul> +<li> +<a href="http://www.taygeta.com/forth/dpans6.htm#6.2.0415">2r@</a> <a href="http://www.taygeta.com/forth/dpans6.htm#6.2.0410">2r></a> <a href="http://www.taygeta.com/forth/dpans6.htm#6.2.0340">2>r</a> +(CORE EXT) + +<li> +<a href="http://www.taygeta.com/forth/dpans8.htm#8.6.1.0440">2VARIABLE</a> +(DOUBLE) + +<li> +<a href="http://www.taygeta.com/forth/dpans16.htm#16.6.2.1985">ORDER</a> +now lists wordlists by name + +<li> +<a href="http://www.taygeta.com/forth/dpans15.htm#15.6.1.0220">.S</a> now +displays all stack entries on one line, like a stack comment + +<li> +<a href="ficl.html#wid-get-name"><tt>wid-get-name</tt> </a> +given a wid, returns the address and count of its name. If no name, count +is 0 + +<li> +<tt><a href="ficl.html#wid-set-name">wid-set-name</a></tt> +set optional wid name pointer to the \0 terminated string address specified. + +<li> +<tt><a href="ficl.html#ficlwordlist">ficl-named-wordlist</a></tt> creates +a ficl-wordlist and names it. This is now used in <tt>vocabulary</tt> and +<tt><a href="ficl.html#ficlvocabulary">ficl-vocabulary</a></tt> + +<li> +<tt><a href="ficl.html#last-word">last-word</a></tt> returns the +xt of the word being defined or most recently defined. + +<li> +<tt><a href="ficl.html#qfetch">q@</a></tt> and <tt><a href="ficl.html#qbang">q!</a></tt> +operate on quadbyte quantities for 64 bit friendliness +</ul> + +<h3> +New OO stuff</h3> + +<ul> +<li> +<tt>ALLOT (class method)</tt> + +<li> +<tt>ALLOT-ARRAY (class method)</tt> + +<li> +<tt>METHOD</tt> define method names globally + +<li> +<tt>MY=></tt> early bind a method call to "this" class + +<li> +<tt>MY=[ ]</tt> early bind a string of method calls to "this" class and +obj members + +<li> +<tt>C-></tt> late bind method invocation with CATCH + +<li> +Metaclass method <tt>resume-class</tt> and instance word <tt>suspend-class</tt> +create mutually referring classes. Example in string.fr + +<li> +Early binding words are now in the instance-vars wordlist, not visible +unless defining a class. + +<li>Support for refs to classes with VTABLE methods (contributed by Guy Carver). Guy writes: +<p> +My next favorite change is a set of VCALL words that allow me +to call C++ class virtual methods from my forth classes. This +is accomplished by interfacing with the VTABLE of the class. The +class instance currently must be created on the C++ side. +C++ places methods in the VTABLE in order of declaration in the +header file. To use this in FICL one only needs to ensure +that the VCALL: declerations occur in the same order. I use this +quite a bit to interface with the C++ classes. When I need access +to a method I make sure it is virtual (Even if it ultimately will +not be). I use Visual C++ 6.0 and have not tested this under +any other compiler but I believe VTABLE implementation is standard. +</p><p> +Here is an example of how to use VCALL: +</p> +<b>C++ class declaration</b> +<pre> +class myclass +{ +public: + myclass(); + virtual ~myclass(); + virtual void Test( int iParam1 ); + virtual int Test( int iParam1, char cParam2 ); + virtual float Test(); +}; +</pre> +<b>ficl class declaration</b> +<pre> +object subclass myfclass hasvtable \ hasvtable adds 4 to the offset to + \ accommodate for the VTABLE pointer. +0 VCALL: Destructor() \ VCALL: ( ParamCount -<MethodName>- ) +1 VCALL: Test(int) \ Test takes 1 int parameter. +2 VCALLR: iTest(int,char) \ iTest takes 2 parameters and returns an int. +0 VCALLF: fTest() \ fTest takes no parameters and returns a float. +end-class + +MyCAddress \ Primitive to return a pointer to a "myclass" instance. +myfclass -> ref dude \ This makes the MyCAddress pointer a myfclass + \ instance with the name "dude". +1234 dude -> Test(int) \ Calls the virtual method Test. +1234 1 dude -> iTest(int,char) . \ Calls iTest and emits the returned int. +dude -> fTest() f. \ Calls fTest and emits the returned float. +</pre> + +</ul> + +<? ficlVersion("Version 2.04") ?> + +<h3>ficlwin</h3> + +<ul> +<li> +Catches exceptions thrown by VM in ficlThread (0 @ for example) rather +than passing them off to the OS. +</ul> + +<h3> +ficl bugs vanquished</h3> + +<ul> +<li> +Fixed leading delimiter bugs in s" ." .( and ( (reported by Reuben Thomas) + +<li> +Makefile tabs restored (thanks to Michael Somos) + +<li> +ABORT" now throws -2 per the DPANS (thanks to Daniel Sobral for sharp eyes +again) + +<li> +ficlExec does not print the prompt string unless (source-id == 0) + +<li> +Various fixes contributed by the FreeBSD team. +</ul> + +<h3> +ficl enhancements</h3> + +<ul> +<li> +Words.c: modified ficlCatch to use vmExecute and vmInnerLoop (request of +Daniel Sobral) Added vmPop and vmPush functions (by request of Lars Krueger +) in vm.c These are shortcuts to the param stack. (Use LVALUEtoCELL to +get things into CELL form) + +<li> +Added function vmGetStringEx with a flag to specify whether or not to skip +lead delimiters + +<li> +Added non-std word: number? + +<li> +Added CORE EXT word AGAIN (by request of Reuben Thomas) + +<li> +Added double cell local (2local) support + +<li> +Augmented Johns Hopkins local syntax so that locals whose names begin with +char 2 are treated as 2locals (OK - it's goofy, but handy for OOP) + +<li> +C-string class revised and enhanced - now dynamically sized + +<li> +C-hashstring class derived from c-string computes hashcode too. +</ul> + + +<? ficlVersion("Version 2.03") ?> + +This is the first version of Ficl that includes contributed code. Thanks +especially to Daniel Sobral, Michael Gauland for contributions and bug +finding. +<p> +New words: +<ul> +<li> +<tt><a href="#clock">clock</a> +(FICL)</tt> + +<li> +<tt><a href="#clockspersec">clocks/sec</a> +(FICL)</tt> + +<li> +<tt><a href="http://www.taygeta.com/forth/dpans8.htm#8.6.1.1230">dnegate</a> +(DOUBLE)</tt> + +<li> +<tt><a href="http://www.taygeta.com/forth/dpans10.htm#10.6.2.1905">ms</a> +(FACILITY EXT - replaces MSEC <i>ficlWin only</i>)</tt> + +<li> +<tt><a href="http://www.taygeta.com/forth/dpans9.htm#9.6.1.2275">throw</a> +(EXCEPTION)</tt> + +<li> +<tt><a href="http://www.taygeta.com/forth/dpans9.htm#9.6.1.0875">catch</a> +(EXCEPTION)</tt> + +<li> +<tt><a href="http://www.taygeta.com/forth/dpans14.htm#14.6.1.0707">allocate</a> +(MEMORY)</tt> + +<li> +<tt><a href="http://www.taygeta.com/forth/dpans14.htm#14.6.1.1605">free</a> +(MEMORY)</tt> + +<li> +<tt><a href="http://www.taygeta.com/forth/dpans14.htm#14.6.1.2145">resize</a> +(MEMORY)</tt> + +<li> +<tt><a href="http://www.taygeta.com/forth/dpans6.htm#6.2.2440">within</a> +(CORE EXT)</tt> + +<li> +<tt><a href="#alloc">alloc</a> +(class method)</tt> + +<li> +<tt><a href="#allocarray">alloc-array</a> +(class method)</tt> + +<li> +<tt><a href="#oofree">free</a> +(class method)</tt> +</ul> + +Bugs Fixed: +<ul> +<li> +Bug fix in isNumber(): used to treat chars between 'Z' and 'a' as valid +in base 10... (harmless, but weird) + +<li> +ficlExec pushes the <i>ip</i> and <tt>interpret</tt>s at the right times +so that nested calls to ficlExec behave the way you'd expect them to. + +<li> +<tt>evaluate</tt> respects count parameter, and also passes exceptional +return conditions back out to the calling instance of ficlExec. + +<li> +VM_QUIT now clears the locals dictionary in ficlExec. +</ul> +Ficlwin Enhancements +<ul> +<li> +File Menu: recent file list and Open now load files. + +<li> +Text ouput function is now faster through use of string caching. Cache +flushes at the end of each line and each time ficlExec returns. + +<li> +Edit/paste now behaves more reasonably for text. File/open loads the specified +file. + +<li> +Registry entries specify dictionary and stack sizes, default window placement, +and whether or not to create a splitter for multiple VMs. See HKEY_CURRENT_USER/Software/CodeLab/ficlwin/Settings +</ul> +Ficl Enhancements +<ul> +<li> +This version includes changes to make it <b>64 bit friendly</b>. This unfortunately +meant that I had to tweak some core data types and structures. I've tried +to make this transparent to 32 bit code, but a couple of things got renamed. +INT64 is now DPINT. UNS64 is now DPUNS. FICL_INT and FICL_UNS are synonyms +for INT32 and UNS32 in 32 bit versions, but a are obsolescent. Please use +the new data types instead. Typed stack operations on INT32 and UNS32 have +been renamed because they operate on CELL scalar types, which are 64 bits +wide on 64 bit systems. Added BITS_PER_CELL, which has legal values of +32 or 64. Default is 32. + +<li> +ficl.c: Added ficlExecXT() - executes an xt completely before returning, +passing back any exception codes generated in the process. Normal exit +code is VM_INNEREXIT. + +<li> +ficl.c: Added ficlExecC() to operate on counted strings as opposed to zero +terminated ones. + +<li> +ficlExec pushes ip and executes interpret at the right times so that nested +calls to ficlExec behave the way you'd expect them to. + +<li> +ficlSetStackSize() allows specification of stack size at run-time (affects +subsequent invocations of ficlNewVM()). + +<li> +vm.c: vmThrow() checks for (pVM->pState != NULL) before longjmping it. +vmCreate nulls this pointer initially. + +<li> +EXCEPTION wordset contributed by Daniel Sobral of FreeBSD + +<li> +MEMORY-ALLOC wordset contributed by Daniel Sobral, too. Added class methods +<tt>alloc</tt> +and <tt>alloc-array</tt> in softwords/oo.fr to allocate objects from the +heap. + +<li> +Control structure match check upgraded (thanks to Daniel Sobral for this +suggestion). Control structure mismatches are now errors, not warnings, +since the check accepts all syntactally legal constructs. + +<li> +Added vmInnerLoop() to vm.h. This function/macro factors the inner +interpreter out of ficlExec so it can be used in other places. Function/macro +behavior is conditioned on INLINE_INNER_LOOP in sysdep.h. Default: 1 unless +_DEBUG is set. In part, this is because VC++ 5 goes apoplectic when trying +to compile it as a function. See + +<br>comments in vm.c +<li> +EVALUATE respects the count parameter, and also passes exceptional return +conditions back out to the calling instance of ficlExec. + +<li> +VM_QUIT clears locals dictionary in ficlExec() + +<li> +Added Michael Gauland's ficlLongMul and ficlLongDiv and support routines +to math64.c and .h. These routines are coded in C, and are compiled only +if PORTABLE_LONGMULDIV == 1 (default is 0). + +<li> +Added definition of ficlRealloc to sysdep.c (needed for memory allocation +wordset). If your target OS supports realloc(), you'll probably want to +redefine ficlRealloc in those terms. The default version does ficlFree +followed by ficlMalloc. + +<li> +testmain.c: Changed gets() in testmain to fgets() to appease the security +gods. + +<li> +testmain: <tt>msec</tt> renamed to <tt><a href="#ficlms">ms</a></tt> in +line with the ANS + +<li> +softcore.pl now removes comments & spaces at the start and end of lines. +As a result: sizeof (softWords) == 7663 bytes (used to be 20000) +and consumes 11384 bytes of dictionary when compiled + +<li> +Deleted license paste-o in readme.txt (oops). +</ul> + + +<? ficlVersion("Version 2.02") ?> + +New words: +<ul> +<li> +<tt><a href="http://www.taygeta.com/forth/dpans6.htm#6.2.1850">marker</a> +(CORE EXT)</tt> + +<li> +<tt><a href="http://www.taygeta.com/forth/dpans15.htm#15.6.2.1580">forget</a> +(TOOLS EXT)</tt> + +<li> +<tt><a href="#ficlforgetwid">forget-wid</a> +(FICL)</tt> + +<li> +<tt><a href="#ficlwordlist">ficl-wordlist</a> (FICL)</tt> + +<li> +<tt><a href="#ficlvocabulary">ficl-vocabulary</a> (FICL)</tt> + +<li> +<tt><a href="#ficlhide">hide</a> +(FICL)</tt> + +<li> +<tt><a href="#ficlhidden">hidden</a> +(FICL)</tt> + +<li> +<a href="#jhlocal">Johns Hopkins local variable syntax</a> (as best I can +determine) +</ul> +Bugs Fixed +<ul> +<li> +<tt>forget</tt> now adjusts the dictionary pointer to remove the name of +the word being forgotten (name chars come before the word header in ficl's +dictionary) + +<li> +<tt>:noname</tt> used to push the colon control marker and its execution +token in the wrong order + +<li> +<tt>source-id</tt> now behaves correctly when loading a file. + +<li> +<tt>refill</tt> returns zero at EOF (Win32 load). Win32 <tt><a href="#ficlload">load</a></tt> +command continues to be misnamed. Really ought to be called <tt>included</tt>, +but does not exactly conform to that spec either (because <tt>included</tt> +expects a string signature on the stack, while Ficl's <tt><a href="#ficlload">load</a></tt> +expects a filename upon invocation). The "real" <tt>LOAD</tt> is a <tt>BLOCK</tt> +word. +</ul> +Enhancements (IMHO) +<ul> +<li> +dictUnsmudge no longer links anonymous definitions into the dictionary + +<li> +<tt>oop</tt> is no longer the default compile wordlist at startup, nor +is it in the search order. Execute <b><tt>also oop definitions</tt></b> +to use Ficl OOP. + +<li> +Revised oo.fr extensively to make more use of early binding + +<li> +Added <tt>meta</tt> - a constant that pushes the address of metaclass. +See oo.fr for examples of use. + +<li> +Added classes: <tt>c-ptr c-bytePtr c-2bytePtr c-cellPtr +</tt>These +classes model pointers to non-object data, but each knows the size of its +referent. +</ul> + + +<? ficlVersion("Version 2.01") ?> + +<ul> +<li> +Bug fix: <tt>(local)</tt> used to leave a value on the stack between the +first and last locals declared. This value is now stored in a static. + +<li> +Added new local syntax with parameter re-ordering. <a href="#newlocal">See +description below</a>. (No longer compiled in version 2.02, in favor of +the Johns Hopkins syntax) +</ul> + + +<? ficlVersion("Version 2.0") ?> + +<ul> +<li> +New ANS Forth words: <tt>TOOLS</tt> and part of <tt>TOOLS EXT, SEARCH</tt> +and <tt>SEARCH EXT, LOCALS</tt> and <tt>LOCALS EXT</tt> word sets, additional +words from <tt>CORE EXT, DOUBLE</tt>, and <tt>STRING</tt>. (See the function +ficlCompileCore in words.c for an alphabetical list by word set). + +<li> +Simple <tt>USER</tt> variable support - a user variable is a virtual machine +instance variable. User variables behave as <tt>VARIABLE</tt>s in all other +respects. + +<li> +Object oriented syntax extensions (see below) + +<li> +Optional stack underflow and overflow checking in many CORE words (enabled +when FICL_ROBUST >= 2) + +<li> +Various bug fixes +</ul> + + + +<? ficlPageFooter() ?> diff --git a/doc/source/upgrading.ht b/doc/source/upgrading.ht new file mode 100644 index 000000000000..9d9b5f26a022 --- /dev/null +++ b/doc/source/upgrading.ht @@ -0,0 +1,349 @@ +<? + +ficlPageHeader("upgrading ficl") + +ficlAddToNavBarAs("Upgrading To 4.0") + +def startoldvsnew(extra = None): + print "<table width=100%><tr>\n" + print "<td bgcolor=#d0d0f0><b>old name</b></td>\n" + print "<td bgcolor=#e0e0ff><b>new name</td>\n" + if extra != None: + print "<td bgcolor=#d0d0f0><b>" + extra + "</td>\n" + print "</tr>\n" + +def oldvsnew(old, new, extra = None): + print "<tr>\n" + print "<td bgcolor=#e0e0e0><code>" + old + "</code></td>\n" + print "<td bgcolor=#f0f0f0><code>" + new + "</code></td>\n" + if extra != None: + print "<td bgcolor=#e0e0e0><code>" + extra + "</code></td>\n" + print"</tr>\n\n" + + +def endoldvsnew(): + print "</table><p>\n" + +?> + +Ficl 4.0 is smaller, faster, and more capable than any previous +version. For more information on why Ficl 4.0 is so gosh-darned +swell, see the <a href=index.html#WhatsNewInFicl4.0>What's New In Ficl 4.0?</a> +section of the overview. +<p> + + +Since the Ficl API has changed so dramatically, you can't just drop +the new Ficl source. You have two basic choices: +<a href=#compatibility>use the <code>FICL_WANT_COMPATIBILITY</code> support</a>, and +<a href=#newapi>switching to the new API</a>. +<p> + +Note that using <i>either</i> of these choices <i>requires</i> +that you recompile your application. You cannot build Ficl 4 into +a shared library or DLL and use it with an application expecting +Ficl 3.0. Stated another way: Ficl 4 is <i>source</i> compatible +but not <i>binary</i> compatible with Ficl 3. + + +<a name=oldnames> +<? ficlHeader1("Using <code>FICL_WANT_COMPATIBILITY</code>") ?> +</a> + + +If you want to get Ficl 4.0 up and running in your project as quickly +as possible, <code>FICL_WANT_COMPATIBILITY</code> is what you'll want to use. +There are two easy steps, one of which you might be able to skip: +<p> + +<ol> + +<li> +Set the C preprocessor constant <code>FICL_WANT_COMPATIBILITY</code> to 1. +The best way is by adding the following line to <code>ficllocal.h</code>: +<pre> + #define FICL_WANT_COMPATIBILITY (1) +</pre> + + +<li> + +<i>If</i> you use a custom <code>ficlTextOut()</code> function, you'll +have to rename it, and explicitly specify it to Ficl. Renaming it is +necessary, because the Ficl compatibility layer also provides one for +code that called <code>ficlTextOut()</code> directly (instead of calling +<code>vmTextOut()</code> as it should have). +We recommend renaming your function to <code>ficlTextOutLocal()</code>, as +we have have provided a prototype for this function for you in <code>ficlcompatibility.h</code>. +This will save you the trouble of defining your own prototype, ensuring you get +correct name decoration / linkage, etc. + +<p> + +There are two methods you can use to specify your <code>ficlTextOut()</code> +function: +<ol> + +<li> +Specify it in the <code>FICL_INIT_INFO</code> structure passed in to +<code>ficlInitSystem()</code>. This is the preferred method, as it ensures +you will see the results of Ficl's initialization code, and it will be +automatically passed in to every newly created VM. + +<li> +Set it explicitly in every VM by calling <code>vmSetTextOut()</code> and +passing it in. + +</ol> +<p> + +<b>Note:</b> Any other method, such as setting it by hand in the +<code>FICL_SYSTEM</code> or <code>FICL_VM</code> structures, +will <b>not</b> work. There is a special compatibility layer for old-style +<code>OUTFUNC</code> functions, but it is only invoked properly when you +use one of the two methods mentioned above. + + +</ol> + +<p> + +This <i>should</i> be sufficient for you to recompile-and-go +with Ficl 4. If it's not, please let us know, preferably including a +suggested solution to the problem. + + +<a name=newapi> +<? ficlHeader1("Using The New API") ?> +</a> + +Since most (all?) of the external symbols have changed names since the 3.0 series, +here is a quick guide to get you started on renaming everything. This is by no +means an exhaustive list; this is meant to guide you towards figuring out what +the new name <i>should</i> be. (After all, part of the point of this massive +renaming was to make all the external symbols consistent.) +<p> + + + + +<? ficlHeader2("Types") ?> + +Every external type has been renamed. They all begin with the +word <code>ficl</code>, and they use mixed case (instead of all upper-case, +which is now reserved for macros). Also, the confusingly-named +string objects have been renamed: +<code>FICL_STRING</code> is now <code>ficlCountedString</code>, as it +represents a "counted string" in the language, and +the more commonly-used <code>STRINGINFO</code> is now simply +<code>ficlString</code>. + +<? + +startoldvsnew() + +oldvsnew("FICL_SYSTEM", "ficlSystem") +oldvsnew("FICL_VM", "ficlVm") +oldvsnew("FICL_SYSTEM_INFO", "ficlSystemInformation") +oldvsnew("FICL_WORD", "ficlWord") +oldvsnew("IPTYPE", "ficlIp") +oldvsnew("FICL_CODE", "ficlPrimitive") +oldvsnew("OUTFUNC", "ficlOutputFunction") +oldvsnew("FICL_DICTIONARY", "ficlDictionary") +oldvsnew("FICL_STACK", "ficlStack") +oldvsnew("STRINGINFO", "ficlString") +oldvsnew("FICL_STRING", "ficlCountedString") + +endoldvsnew() + +?> + +<? ficlHeader2("Structure Members") ?> + +In addition, many structure names have changed. To help ease the heartache, +we've also added some accessor macros. So, in case they change in the future, +your code might still compile (hooray!). +<? + +startoldvsnew("accessor") + +oldvsnew("pExtend", "context", "ficlVmGetContext(), ficlSystemGetContext()") +oldvsnew("pStack", "dataStack", "ficlVmGetDataStack()") +oldvsnew("fStack", "floatStack", "ficlVmGetFloatStack()") +oldvsnew("rStack", "returnStack", "ficlVmGetReturnStack()") + +endoldvsnew() + +?> + +<? ficlHeader2("Callback Functions") ?> + +Text output callbacks have changed in two major ways: + +<ul> + +<li> +They no longer take a VM pointer; they now take a <code>ficlCallback</code> structure. +This allows output to be printed before a VM is defined, or in circumstances where a +VM may not be defined (such as an assertion failure in a <code>ficlSystem...()</code> function). + +<li> +They no longer take a flag indicating whether or not to add a "newline". +Instead, the function must output a newline whenever it encounters +a <code>\n</code> character in the text. + +</ul> + +If you don't want to rewrite your output function yet, you can +"thunk" the new-style call to the old-style. Just pass in <code>ficlOldnamesCallbackTextOut</code> +as the name of the output function for the system and VM, and then set +the <code>thunkedTextout</code> member of the <code>ficlSystem</code> +or <code>ficlVm</code> to your old-style text output function. + + +<? ficlHeader2("Renamed Macros") ?> + +<? + +startoldvsnew() + +oldvsnew("PUSHPTR(p)", "ficlStackPushPointer(vm->dataStack, p)") +oldvsnew("POPUNS()", "ficlStackPopUnsigned(vm->dataStack)") +oldvsnew("GETTOP()", "ficlStackGetTop(vm->dataStack)") + +oldvsnew("FW_IMMEDIATE", "FICL_WORD_IMMEDIATE") +oldvsnew("FW_COMPILE", "FICL_WORD_COMPILE_ONLY") + +oldvsnew("VM_INNEREXIT", "FICL_VM_STATUS_INNER_EXIT") +oldvsnew("VM_OUTOFTEXT", "FICL_VM_STATUS_OUT_OF_TEXT") +oldvsnew("VM_RESTART", "FICL_VM_RESTART") + + +endoldvsnew() + +?> + +<? ficlHeader2("<code>ficllocal.h</code>") ?> + +One more note about macros. Ficl now ships with a standard place for +you to tweak the Ficl compile-time preprocessor switches such as +<code>FICL_WANT_COMPATIBILITY</code> and <code>FICL_WANT_FLOAT</code>. +It's a file called <code>ficllocal.h</code>, and we guarantee that it +will always ship empty (or with only comments). We suggest that you +put all your local changes there, rather than editing <code>ficl.h</code> +or editing the makefile. That should make it much easier to integrate +future Ficl releases into your product—all you need do is preserve +your tweaked copy of <code>ficllocal.h</code> and replace the rest. + + +<? ficlHeader2("Renamed Functions") ?> + +Every function that deals primarily with a particular structure +is now named after that structure. For instance, any function +that takes a <code>ficlSystem</code> as its first argument is +named <code>ficlSystem<i>Something</i>()</code>. Any function +that takes a <code>ficlVm</code> as its first argument is +named <code>ficlVm<i>Something</i>()</code>. And so on. +<p> + +Also, functions that create a new object are always +called <code>Create</code> (not <code>Alloc</code>, <code>Allot</code>, <code>Init</code>, or <code>New</code>). +Functions that create a new object are always +called <code>Destroy</code> (not <code>Free</code>, <code>Term</code>, or <code>Delete</code>). +<p> + + +<? + +startoldvsnew() + +oldvsnew("ficlInitSystem()", "ficlSystemCreate()") +oldvsnew("ficlTermSystem()", "ficlSystemDestroy()") +oldvsnew("ficlNewVM()", "ficlSystemCreateVm()") +oldvsnew("ficlFreeVM()", "ficlVmDestroy()") +oldvsnew("dictCreate()", "ficlDictionaryCreate()") +oldvsnew("dictDelete()", "ficlDictionaryDestroy()") + +endoldvsnew() + +?> +<p> + +All functions exported by Ficl now start with the word <code>ficl</code>. +This is a <i>feature</i>, as it means the Ficl project will no longer +pollute your namespace. + +<? + +startoldvsnew() + +oldvsnew("PUSHPTR(p)", "ficlStackPushPointer(vm->dataStack, p)") +oldvsnew("POPUNS()", "ficlStackPopUnsigned(vm->dataStack)") +oldvsnew("GETTOP()", "ficlStackGetTop(vm->dataStack)") +oldvsnew("ltoa()", "ficlLtoa()") +oldvsnew("strincmp()", "ficlStrincomp()") + +endoldvsnew() + +?> + + + +<? ficlHeader2("Removed Functions") ?> + +A few entry points have simply been removed. +For instance, functions specifically managing a system's <code>ENVIRONMENT</code> +settings have been removed, in favor of managing the system's +<code>environment</code> dictionary directly: +<? + +startoldvsnew() + +oldvsnew("ficlSystemSetEnvironment(system)", "ficlDictionarySetConstant(ficlSystemGetEnvironment(system), ...)") +oldvsnew("ficlSystemSet2Environment(system)", "ficlDictionarySet2Constant(ficlSystemGetEnvironment(system), ...)") + +endoldvsnew() + +?> + + +In a similar vein, <code>ficlSystemBuild()</code> has been removed in favor +of using <code>ficlDictionarySetPrimitive()</code> directly: + +<? +startoldvsnew() +oldvsnew("ficlSystemBuild(system, ...)", "ficlDictionarySetPrimitive(ficlSystemGetDictionary(system), ...)") +endoldvsnew() +?> + +Finally, there is no <i>exact</i> replacement for <code>ficlExec()</code>. 99% of the code +that called <code>ficlExec()</code> never bothered to manage <code>SOURCE-ID</code> properly. +If you were calling <code>ficlExec()</code>, and you weren't changing <code>SOURCE-ID</code> +(or <code>vm->sourceId</code>) to match, you should replace those calls with <code>ficlVmEvaluate()</code>, +which will manage <code>SOURCE-ID</code> for you. +<p> + +There <i>is</i> a function that takes the place of <code>ficlExec()</code> which doesn't change +<code>SOURCE-ID</code>: <code>ficlVmExecuteString()</code>. However, instead of taking a +straight C string (a <code>char *</code>), it takes a <code>ficlString *</code> as its +code argument. (This is to discourage its use.) + + +<? +ficlHeader1("Internal Changes") +?> + +<b>Note:</b> none of these changes should affect you. If they do, there's probably +a problem somewhere. Either Ficl's API doesn't abstract away something enough, or +you are approaching a problem the wrong way. Food for thought. +<p> + +There's only one internal change worth noting here. +The top value on a Ficl stack used to be at (to use the modern structure names) +<code>stack->top[-1]</code>. It is now at <code>stack->top[0]</code>. +In other words, the "stack top" pointer used to point <i>past</i> the top +element; it now points <i>at</i> the top element. (Pointing <i>at</i> the +top element is not only less confusing, it is also faster.) + +</body> +</html> |