PFE - Portable Forth Environment - pfe Forth Wordsets

  PFE 0.33.71 Homepage SourceForge Download Documentation -Overview -The PFE Manual old manual / (book) -ChangeLog -Authors -License (LGPL) -Wordsets / (book) -Functions .. (book) -Dp of ANS Forth -The 4thTutor -Forthprimer.pdf - Old Wordsets - Old Words List Forth Links * Forth Repository * Taygeta Compilation * TinyBoot FirmWare * FiCL, Free Forth * Research Vienna * Research Bournemouth * zForth WebRing Other Links * Tektronix/MPT * Forth Org. (FIG) * Forth Inc. * MPE Ltd. Forths * SF Win32Forth * PD Win32Forth * Neil Bawd generated (C) Guido U. Draheim guidod@gmx.de | ## Useful kernel extensions `_like:COMPILE,``` => `"EXTENSIONS"` (no description) primitive code = [p4_to_compile] `($``( [word] -- cs-token )``compile-only` => `"EXTENSIONS"` takes the execution token of the following word and saves it on the compile-stack. The correspondig closing `)` will then feed it into `>COMPILE` - so this pair of word provides you with a prefix-operation syntax that you may have been seen in lisp-like languages.
          ($ IF ($ 0= A1 @ )) ($ THEN ." hello " )
  Note that an opening simple `(` paren is a comment. immediate code = [p4_prefix_begin] `)``( cs-token -- )``` => `"EXTENSIONS"` takes the execution-token from `($` and compiles it using `>COMPILE` immediate code = [p4_prefix_end] `PFE-PRINTF``( args ... format$ -- )``` => `"EXTENSIONS"` uses `SPRINTF` to print to a temporary 256-char buffer and prints it to stdout afterwards. See the example at `SPRINTF` of what it does internally. primitive code = [p4_printf] `PFE-SPRINTF``( args ... format$ dest$ -- len-dest )``` => `"EXTENSIONS"` just like the standard sprintf() function in C, but the format is a counted string and accepts %#s to be the format-symbol for a forth-counted string. The result is a zeroterminated string at dest$ having a length being returned. To create a forth-counted string, you could use:
          variable A 256 ALLOT
          15 " example" " the %#s value is %i" A 1+ SPRINTF A C!
          A COUNT TYPE
  primitive code = [p4_sprintf] `LOADF``( "filename" -- )``` => `"EXTENSIONS"` loads a file just like `INCLUDE` but does also put a `MARKER` in the `LOADED` dictionary that you can do a `FORGET` on to kill everything being loaded from that file. primitive code = [p4_loadf] `DOER``( word -- )``` => `"EXTENSIONS"` In PFE it is a synonym to `DEFER` which a semistandard word. Unlike `DEFER`, the `DOER`-vector was set with an a small piece of code between `MAKE` and `;AND`. The "DOER"-word should be replaced with `DEFER` `IS`, which is easy since the `DEFER` and `DOER` point to the same internal runtime. primitive code = [p4_defer] `MAKE``( [word] -- )``... ;AND` => `"EXTENSIONS"` make a seperated piece of code between `MAKE` and `;AND` and on execution of the `MAKE` the named word is twisted to point to this piece of code. The word is usually a `DOER` but the current implementation works on `DEFER` just as well, just as it does on other words who expect to find an execution-token in its PFA. You could even create a colon-word that starts with `NOOP` and can then make that colon-word be prefixed with the execution of the code piece. This `MAKE` does even work on `LOCALS|` and `VAR` but it is uncertain what that is good for. compiling word = [p4_make] `;AND``( -- )``` => `"EXTENSIONS"` For the code piece between `MAKE` and `;AND` , this word will do just an `EXIT` . For the code outside of the `MAKE` construct a branch-around must be resolved then. compiling word = [p4_semicolon_and] `[NOT]``( a -- a' )``` => `"EXTENSIONS"` executes `0=` but this word is immediate so that it does affect the cs-stack while compiling rather than compiling anything. This is useful just before words like `[IF]` to provide semantics of an `[IFNOT]`. It is most useful in conjunction with "=> [DEFINED] word" as it the sequence "`[DEFINED] word [NOT] [IF]`" can simulate "`[IFNOTDEF] word`" immediate code = [p4_bracket_not] `+FIELD:``( offset "name" -- offset )``` => `"EXTENSIONS"` created a new name with an `OFFSET-RT` runtime using the given offset. Leave the offset-value untouched, so it can be modified with words like `CHAR+` and `CELL+` and `SFLOAT+` ; This word is the simplest way to declared structure access words in forth - the two `STRUCT` modules contain a more elaborate series of words. Use this one like:
        0                        ( a fresh definition is started )
        +FIELD: zapp.a+ CHAR+     ( zero offset from the base of the struct )
        +FIELD: zapp.b+ CELL+     ( no alignment, starts off at 1 from base )
        +FIELD: zapp+   DROP      ( store size of complete zap structure )

        0 zapp+                  ( extend the zap structure )
        +FIELD: zappx.c+ CELL+    ( a new field )
        +FIELD: zappx+   DROP     ( and save it again )

        CREATE zapp1  0 zapp+ ALLOT ( a way to allocate a strucutre )

        zapp2 zapp.b+ @         ( read a value from the field )
        16 zapp2 zapp.b+ !      ( store a value in there )
  this form is not the traditional form used in forth, it is however quite simple. Use the simplefield declaration with `/FIELD` to be compatible with traditional styles that build on top of sizeof constants in forth (which are not part of the ANS Forth standard). primitive code = [p4_plus_field] `/FIELD``( offset size "name" -- offset+size )``` => `"EXTENSIONS"` created a new `+FIELD` name with an `OFFSET-RT` of offset. Then add the size value to the offset so that the next `/FIELD` declaration will start at the end of the field currently declared. This word is the simplest way to declared structure access words in forth - the two `STRUCT` modules contain a more elaborate series of words. This one is used like:
        0                        ( a fresh definition is started )
        /CHAR /FIELD ->zapp.a    ( zero offset from the base of the struct )
        /CELL /FIELD ->zapp.b    ( no alignment, starts off at 1 from base )
        CONSTANT /zapp           ( store size of complete zap structure )

        /zapp                    ( extend the zap structure )
        /CELL /FIELD ->zappx.c   ( a new field )
        CONSTANT /zappx          ( and save it again )

        CREATE zapp1 /zapp ALLOT ( a way to allocate a strucutre )
        /zapp BUFFER: zapp2      ( another way to do it, semi-standard )

        zapp2 ->zapp.b @         ( read a value from the field )
        16 zapp2 ->zapp.b !      ( store a value in there )
  compare also with `/CHAR` `/WCHAR` `/CELL` `/DCELL` and use `+FIELD` as the lowlevel word, can simulate as
        : /FIELD SWAP +FIELD + ;
  primitive code = [p4_slash_field] `REPLACE-IN``( to-xt from-xt n "name" -- )``` => `"EXTENSIONS"` will handle the body of the named word as a sequence of cells (or tokens) and replaces the n'th occurences of from-xt into to-xt. A negative value will change all occurences. A zero value will not change any. primitive code = [p4_replace_in] `(LOADF-LOCATE)``( xt -- nfa )``` => `"EXTENSIONS"` the implementation of `LOADF-LOCATE` primitive code = [p4_paren_loadf_locate] `LOADF-LOCATE``( "name" -- )``` => `"EXTENSIONS"` look for the filename created by `LOADF` that had been defining the given name. `LOADF` has created a marker that is above the `INCLUDED` file and that marker has a body-value just below the `INCLUDED` file. Hence the symbol was defined during `LOADF` execution of that file.
        : LOADF-LOCATE ?EXEC POSTPONE ' (LOADF-LOCATE) .NAME ;
  primitive code = [p4_loadf_locate] `X"``( "hex-q" -- bstring )``` => `"EXTENSIONS"` places a counted string on stack containing bytes specified by hex-string - the hex string may contain spaces which will delimit the bytes
        example:
           X" 41 42 4344" COUNT TYPE ( shows ABCD )
  compiling word = [p4_x_quote] `EVALUATE-WITH``( i*x addr len xt[i*x--j*x] -- j*x )``` => `"EXTENSIONS"` added to be visible on the forth command line on request by MLG, he has explained the usage before a lot, you can get an idea from:
           : EVALUATE ['] INTERPRET EVALUATE-WITH ;
  The word is used internally in PFE for the loadlist evaluation of the binary modules: where previously each loadercode had its own CREATE-execution we do now call the original forthish CREATE-word like, so bootstrapping a `VARIABLE` will now call VARIABLE itself and of course we need to set up the TIB-area to point to the name of the variable that shall be created in the forth dictionary:
        : LOAD-WORD ( arg-value str-ptr str-len loader-code -- )
             CASE
               #LOAD-VARIABLE OF ['] VARIABLE EVALUATE-WITH ENDOF
               ....
             ENDCASE
             CLEARSTACK
        ;
  primitive code = [p4_evaluate_with] `[POSSIBLY]``( [name] -- ?? )``` => `"EXTENSIONS"` check if the name exists, and execute it immediatly if found. Derived from POSSIBLY as seen in other forth systems.
        : [POSSIBLY] (') ?DUP IF EXECUTE THEN ; IMMEDIATE
  immediate code = [p4_bracket_possibly] `[VOCABULARY]``( "name" -- )``` => `"EXTENSIONS"` create an immediate vocabulary. Provides for basic modularization.
        : [VOCABULARY] VOCABULARY IMMEDIATE ;
  primitive code = [p4_bracket_vocabulary] `[DEF]``( -- )``` => `"EXTENSIONS"` immediatly set topmost `CONTEXT` voc to `CURRENT` compilation voc.
        : DEF' CURRENT @ CONTEXT ! ; IMMEDIATE
  note that in PFE most basic vocabularies are immediate, so that you can use a sequence of
        FORTH ALSO  DEFINITIONS
        [DEF] : GET-FIND-3  [ANS] ['] FIND  [FIG] ['] FIND  [DEF] ['] FIND ;
  where the first wordlist to be searched via the search order are [ANS] and [FIG] and FORTH (in this order) and which may or may not yield different flavours of the FIND routine (i.e. different XTs) immediate code = [p4_bracket_def] `CONTEXT?``( -- number )``` => `"EXTENSIONS"` GET-CONTEXT and count how many times it is in the order but the CONTEXT variable itself. The returned number is therefore minus one the occurences in the complete search-order. usage:
          ALSO EXTENSIONS CONTEXT? [IF] PREVIOUS [THEN]
          ALSO DEF' DEFAULT-ORDER
        : CONTEXT?
          0 LVALUE _count
          GET-ORDER 1- SWAP  LVALUE _context
          0 ?DO _context = IF 1 +TO _count THEN LOOP
          _count
        ;
  primitive code = [p4_context_Q] `CASE-SENSITIVE-VOC``( -- )``` => `"EXTENSIONS"` accesses `CONTEXT` which is generally the last named `VOCABULARY` . sets a flag in the vocabulary-definition so that words are matched case-sensitive.
        example:
           VOCABULARY MY-VOC  MY-VOC CASE-SENSITIVE-VOC
  OBSOLETE! use `DEFS-ARE-CASE-SENSITIVE` primitive code = [p4_case_sensitive_voc] `DEFS-ARE-CASE-SENSITIVE``( -- )``` => `"EXTENSIONS"` accesses `CURRENT` which is generally the last wordlist that the `DEFINITIONS` shall go in. sets there a flag in the vocabulary-definition so that words are matched case-sensitive.
        example:
           VOCABULARY MY-VOC  MY-VOC DEFINITIONS DEFS-ARE-CASE-SENSITIVE
  primitive code = [p4_defs_are_case_sensitive] `DEFS-ARE-SEARCHED-ALSO``( -- )``` => `"EXTENSIONS"` binds `CONTEXT` with `CURRENT`. If the `CURRENT` `VOCABULARY` is in the search-order (later), then the `CONTEXT` vocabulary will be searched also. If the result of this word could lead into a recursive lookup with `FIND` it will throw `CURRENT_DELETED` and leave the `CURRENT` `VOCABULARY` unaltered.
        example:
MY-VOC DEFINITIONS MY-VOC-PRIVATE DEFS-ARE-SEARCHED-ALSO primitive code = [p4_defs_are_searched_also]