Forth Inspired Command Language | |
Author: John Sadler (john_sadler@alum.mit.edu) | |
Created: 19 July 1997 | |
Revision 2.02: 10 October 1998 |
What's new in version 2.02New words
|
What's new in version 2.01
|
What's new in version 2.0
|
Local VariablesFicl includes support for LOCALS and LOCALS EXT words (all three of them!). I've implemented both of the local variable syntaxes suggested in DPANS Appendix A.13. Examples: (By the way, Ficl implements -ROT as : -rot 2 -roll ; )
: -rot ( a b c -- c a b ) locals| c b a | c a b ; \ Using LOCAL END-LOCAL : -rot ( a b c -- c a b ) local c local b local a end-locals c a b ; The default maximum number of local variables is 16. It's controlled by FICL_MAX_LOCALS in sysdep.h. Ficl 2.02 includes by default an implementation of the Johns Hopkins local syntax (as best I can determine it from examples on the web). This syntax lets you declare local variables that look very much like a stack comment. Variables in the declaration appear in the "correct" order for a stack comment. Everything after the -- is treated as a comment. In addition, you can insert a | before the -- to declare one or more zero-initialized locals. Example: :tuck0 { a b c | d -- 0 a b c }The | and -- delimiters can appear at most once, and must appear in the order shown in the example to work correctly. The local declaration ends at the first occurrence of }. The declaration must all be on one line as presently implemented. Ficl 2.01 added yet another local syntax that models a stack comment. This one is not compiled in the release, but you can add it by editing softwords/softcore.bat to include the file ficllocal.fr. In this case, parameters are re-ordered so that the rightmost initialized param comes from the top of the stack. The syntax is:
{{ a b c }} c a b ; : tuck0 ( a b c -- 0 a b c ) {{ a b c -- d }} d a b c ; Search OrderFicl implements many of the search order words in terms of two primitives called >SEARCH and SEARCH>. As their names suggest (assuming you're familiar with Forth), they push and pop the search order stack. See the list of Ficl extras for details.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 ABORT happens. This includes stack underflows and overflows. QUIT does not affect the search order. The minimum search order (set by ONLY) is equivalent to FORTH-WORDLIST 1 SET-ORDER 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). Soft WordsMany 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 ficl/softwords. 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 softcore.bat to change the list of files that contribute to softcore.c. |
Objects in ficlFicl 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 (below) 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.Design goals of Ficl OO syntaxFicl'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.
|
Ficl Object ModelAll classes in Ficl are derived from the common base class OBJECT. All classes are instances of METACLASS. This means that classes are objects, too. METACLASS implements the methods for messages sent to classes. Class methods create instances and subclasses, and give information about the class. Classes have exactly three elements:
Note for the curious: METACLASS 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 METACLASS
as an instance of itself.
|
Tutorial (finally!)Since this is a tutorial, I'm assuming you're following along by typing the examples into ficlWin, the Win32 version of Ficl (or some other build that includes the OO part of softcore.c). I also assume that you're familiar with Forth. If not, please see one of the references, below. Ficl's OOP words are in vocabulary OOP. To put OOP in the search order and make it the compilation wordlist from the default search order (as set by ONLY), type:
4 chars: m_chars : init ( inst class -- ) locals| class inst | 0 inst class --> m_cell1 ! inst class --> m_chars 4 0 fill ." initializing an instance of c_foo at " inst x. cr ; end-class The init method is special for Ficl objects: whenever you create
an initialized instance using new or new-array,
Ficl calls the class's init method for you on that instance. The
default init method supplied by class object clears the
instance, so we didn't really need to override it in this case (see the
source code in ficl/softwords/oo.fr).
foo-instance --> pedigree
or foo-instance --> class --> see init
metaclass => instance --> init ; metaclass --> see new Notice that the early-binding operator requires a class at compile time. For this reason, classes are IMMEDIATE, 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. 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 ref from this class,
supplying the address of the structure. After that, the ref instance behaves
as a Ficl object, but its instance variables take on the values in the
existing structure. Example (from ficlclass.fr):
cell: .parent cell: .size cell: .hash : push drop >search ;
: named-wid ( "name" -- )
wordlist postpone c-wordlist --> ref ;
my-wordlist --> set-current order Ficl can make arrays of instances, and aggregate arrays into class descripions. The class methods array and new-array create uninitialized and initialized arrays, respectively, of a class. In order to initialize an array, the class must define a reasonable init method. New-array invokes it on each member of the array in sequence from lowest to highest. Array instances and array members use the object methods index, next, and prev to navigate. Aggregate a member array of objects using array:. The objects are not automatically initialized in this case - your class initializer has to call array-init explicitly if you want this behavior. For further examples of OOP in Ficl, please see the source file ficl/softwords/ficlclass.fr. This file wraps several Ficl internal data structures in objects and gives use examples. |
object base-class Methods GlossaryThese are methods that are defined for all instances by the base class. The methods include default initialization, array manipulations, aliases of class methods, upcasting, and programming tools.
Convert an object signature into the signature of the previous object in the array. No check for bounds underflow. |
ANS Forth System
Providing names from the Core Extensions word set Providing the Locals word set Providing the Locals Extensions word set Providing the Programming-Tools word set Providing names from the Programming-Tools Extensions word set Providing the Search-Order word set Providing the Search-Order Extensions word set Implementation-defined OptionsThe 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.
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 ALIGN and ALIGNED to align on 4 byte boundaries. To align on 2n byte boundaries, set FICL_ALIGN to n. Depends on target system, C runtime library, and your implementation of ficlTextOut(). 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. Depends on target system and implementation of ficlTextOut() Ficl characters are one byte each. There are no alignment requirements. No special processing is performed on characters beyond case-folding. Therefore, extended characters will not match their unaccented counterparts. Ficl uses the Standard C function isspace() to distinguish space characters. The rest is up to your library vendor. Uses the data stack The maximum supported value of BASE 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, however, other than possibly unexpected behavior. Target system dependent Does ABORT Target system dependent (implementation of outer loop that calls ficlExec) 255 Limited by available memory and the maximum unsigned value that can fit in a CELL (232-1). Ficl stores the first 31 characters of a definition name. Same as maximum definition name length None supported. This is up to the target system None supported. This is up to the target system Target system dependent. Ficl generally supports processors that can address 8 bit quantities, but there is no dependency that I'm aware of. 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. Assuming a 32 bit implementation, range for signed single-cell values is -231..231-1. Range for unsigned single cell values is 0..232-1. Range for signed double-cell values is -263..263-1. Range for unsigned single cell values is 0..264-1. None Default is 255. Depends on the setting of nPAD in ficl.h. System dependent, generally four. System dependent, generally one. This buffer is supplied by the host program. Ficl imposes no practical limit. Default is 255 characters. Depends on the setting of nPAD in ficl.h. Not presently supported Ficl is not case sensitive "ok>" Symmetric One (no others) System dependent. Ficl makes no special checks for overflow. No. Definitions are unsmudged after ; only, and only then if no control structure matching problems have been detected. Ambiguous ConditionsA 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.The following general ambiguous conditions could occur because of a combination of factors:
Ficl does ABORT and prints the name followed by " not found". 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. No problem: all addresses in ficl are absolute. You can reach any 32 bit address in Ficl's address space. Ficl makes no check for argument type compatibility. Effects of a mismatch vary widely depending on the specific problem and operands. Ficl returns a valid token, but the result of executing that token while interpreting may be undesirable. Results are target procesor dependent. Generally, Ficl makes no check for divide-by-zero. The target processor will probably throw an exception. With FICL_ROBUST (sysdep.h) set >= 2, most parameter stack operations are checked for underflow and overflow. Ficl does not check the return stack. No check - Evil results. Ficl generates an error message if the dictionary is too full to create a definition header. It checks ALLOT as well, but it is possible to make an unchecked allocation request that overflows the dictionary. 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 EXECUTE, though. 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. 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. 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 SLITERAL, you need to have enough room for the string, otherwise bad things may happen. This is not usually a problem. Value will be truncated 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. Ficl returns for a new input buffer until a non-empty one is supplied.
Bad Things occur - unpredictable bacause the input buffer is supplied by the host program's outer loop. It finds the address of the definition before DOES> Not implemented 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. Target processor dependent. Consequences include: none (Intel), address error exception (68K). See above on data space read/write alignment Ficl detects a stack underflow and reports it, executing ABORT, as long as FICL_ROBUST is two or larger. 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. No problem. Ficl's version of TO works correctly with VALUEs, CONSTANTs and VARIABLEs. Ficl prints an error message and does ABORT No check. Results vary depending on the specific problem. The word is postponed correctly. 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.) 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. 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) Don't. CREATE reserves a field in words it builds for DOES> to fill in. If you use DOES> on a word not made by CREATE, 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. Locals Implementation-defined options
Default is 16. Change by redefining FICL_MAX_LOCALS, defined in sysdep.h Locals Ambiguous conditions
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. See the CORE ambiguous conditions, above (no change) Programming Tools Implementation-defined options
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. Search Order Implementation-defined options
Defaults to 16. Can be changed by redefining FICL_DEFAULT_VOCS, declared in sysdep.h Equivalent to FORTH-WORDLIST 1 SET-ORDER Search Order Ambiguous conditions
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 new compile wordlist. Ficl prints an error message if the search order underflows, and resets the order to its default state. Ficl prints an error message if the search order overflows, and resets the order to its default state. |