6.19 Environmental Queries

Forth-94 introduced the idea of “environmental queries” as a way for a program running on a system to determine certain characteristics of the system. The Standard specifies a number of strings that might be recognised by a system, and a way of querying them:

environment? ( c-addr u – false / ... true  ) core “environment-query”

c-addr, u specify a counted string. If the string is not recognised, return a false flag. Otherwise return a true flag and some (string-specific) information about the queried string.

Note that, whilst the documentation for (e.g.) ADDRESS-UNIT-BITS shows it returning one cell on the stack, querying it using environment? will return an additional item; the true flag that shows that the string was recognised; so for querying ADDRESS-UNIT-BITS the stack effect of environment? is ( c-addr u -- n true ).

Several environmental queries deal with the system’s limits:

ADDRESS-UNIT-BITS ( – n  ) environment “ADDRESS-UNIT-BITS”

Size of one address unit, in bits.

MAX-CHAR ( – u  ) environment “MAX-CHAR”

Maximum value of any character in the character set

/COUNTED-STRING ( – n  ) environment “slash-counted-string”

Maximum size of a counted string, in characters.

/HOLD ( – n  ) environment “slash-hold”

Size of the pictured numeric string output buffer, in characters.

/PAD ( – n  ) environment “slash-pad”

Size of the scratch area pointed to by PAD, in characters.

CORE ( – f  ) environment “CORE”

True if the complete core word set is present. Always true for Gforth.

CORE-EXT ( – f  ) environment “CORE-EXT”

True if the complete core extension word set is present. Always true for Gforth.

FLOORED ( – f  ) environment “FLOORED”

True if / etc. perform floored division

MAX-N ( – n  ) environment “MAX-N”

Largest usable signed integer.

MAX-U ( – u  ) environment “MAX-U”

Largest usable unsigned integer.

MAX-D ( – d  ) environment “MAX-D”

Largest usable signed double.

MAX-UD ( – ud  ) environment “MAX-UD”

Largest usable unsigned double.

return-stack-cells ( – n  ) environment “return-stack-cells”

Maximum size of the return stack, in cells.

stack-cells ( – n  ) environment “stack-cells”

Maximum size of the data stack, in cells.

floating-stack ( – n  ) environment “floating-stack”

n is non-zero, showing that Gforth maintains a separate floating-point stack of depth n.

#locals ( – n  ) environment “number-locals”

The maximum number of locals in a definition

wordlists ( – n  ) environment “wordlists”

the maximum number of wordlists usable in the search order

max-float ( – r  ) environment “max-float”

The largest usable floating-point number (implemented as largest finite number in Gforth)

XCHAR-ENCODING ( – addr u  ) environment “XCHAR-ENCODING”

Returns a printable ASCII string that reperesents the encoding, and use the preferred MIME name (if any) or the name in http://www.iana.org/assignments/character-sets like “ISO-LATIN-1” or “UTF-8”, with the exception of “ASCII”, where we prefer the alias “ASCII”.

MAX-XCHAR ( – xchar  ) environment “MAX-XCHAR”

Maximal value for xchar. This depends on the encoding.

XCHAR-MAXMEM ( – u  ) environment “XCHAR-MAXMEM”

Maximal memory consumed by an xchar in address units

Several environemtal queries are there for determining the presence of the Forth-94 version of a wordset; they all have the stack effect ( -- f ) if the string is present (so the environment? stack effect for these queries is ( c-addr u -- false / f true ).

block block-ext double double-ext exception exception-ext facility facility-ext file file-ext floating floating-ext locals locals-ext memory-alloc memory-alloc-ext tools tools-ext search-order search-order-ext string string-ext

These wordset queries were rarely used and implemented, so Forth-2012 did not introduce a way to query for the Forth-2012 variants of the wordsets. Instead, the idea is that you use [defined] (see Interpreter Directives) instead.

Forth-200x (a group that works on the next standard; the documents that they produce are also called Forth-200x) defines extension queries for the extension proposals once they finish changing (CfV stage), so programs using these proposals can check whether a system has them, and maybe load the reference implementation (if one exists). If environment? finds such a query, then the corresponding proposal on www.forth200x.org is implemented on the system (but the absence tells you nothing, as usual with environment?). These queries have the stack effect ( -- ), which means that for them environment? has the stack effect ( c-addr u -- false / true ), which is more convenient than that of wordset queries. A number of these proposals have been incorporated into Forth-2012. The extension queries are also not particularly popular among Forth system implementors, so going for [defined] may be the better approach. Anyway, Gforth implements the following extension queries:

X:2value X:buffer X:deferred X:defined X:ekeys X:escaped-strings X:extension-query X:fp-stack X:ftrunc X:fvalue X:locals X:n-to-r X:number-prefixes X:parse-name X:required X:s-escape-quote X:s-to-f X:structures X:synonym X:text-substitution X:throw-iors X:traverse-wordlist X:xchar

In addition, Gforth implements the following Gforth-specific queries:

gforth ( – c-addr u  ) gforth-environment “gforth”

Counted string representing a version string for this version of Gforth (for versions>0.3.0). The version strings of the various versions are guaranteed to be ordered lexicographically.

os-class ( – c-addr u  ) gforth-environment “os-class”

Counted string representing a description of the host operating system.

os-type ( – c-addr u  ) gforth-environment “os-type”

Counted string equal to "$host_os"

The Standard requires that the header space used for environmental queries be distinct from the header space used for definitions.

Typically, a Forth system supports environmental queries by creating a set of definitions in a wordlist that is only used for environmental queries; that is what Gforth does. There is no Standard way of adding definitions to the set of recognised environmental queries, but in Gforth and other systems that use the wordlist mechanism, the wordlist used to honour environmental queries can be manipulated just like any other word list.

environment-wordlist ( – wid  ) gforth-0.2 “environment-wordlist”

wid identifies the word list that is searched by environmental queries (present in SwiftForth and VFX).

environment ( ) gforth-0.6 “environment”

A vocabulary for environment-wordlist (present in Win32Forth and VFX).

Here are some examples of using environmental queries:

s" address-unit-bits" environment? 0=
[IF]
     cr .( environmental attribute address-units-bits unknown... ) cr
[ELSE]
     drop \ ensure balanced stack effect
[THEN]

\ this might occur in the prelude of a standard program that uses THROW
s" exception" environment? [IF]
   0= [IF]
      : throw abort" exception thrown" ;
   [THEN]
[ELSE] \ we don't know, so make sure
   : throw abort" exception thrown" ;
[THEN]

s" gforth" environment? [IF] .( Gforth version ) TYPE
                        [ELSE] .( Not Gforth..) [THEN]

\ a program using v*
s" gforth" environment? [IF]
  s" 0.5.0" compare 0< [IF] \ v* is a primitive since 0.5.0
   : v* ( f_addr1 nstride1 f_addr2 nstride2 ucount -- r )
     >r swap 2swap swap 0e r> 0 ?DO
       dup f@ over + 2swap dup f@ f* f+ over + 2swap
     LOOP
     2drop 2drop ; 
  [THEN]
[ELSE] \ 
  : v* ( f_addr1 nstride1 f_addr2 nstride2 ucount -- r )
  ...
[THEN]

Here is an example of adding a definition to the environment word list:

get-current environment-wordlist set-current
true constant block
true constant block-ext
set-current

You can see what definitions are in the environment word list like this:

environment-wordlist wordlist-words