I'm interesting in testing some of the limits of Gforth and would like to have it execute arbitrary code that I "hand compile" into allocated memory. Here is my attempt.
100 cells allocate throw constant &mem
\ store at &mem: docol: . EXIT
docol: &mem !
comp' . &mem 1 cells + ! drop \ drop "execution token"
comp' EXIT &mem 2 cells + ! drop
42 \ something to print
&mem execute
Unfortunately this fails with:
in file included from *OS command line*:-1
notes/execute.fs:8: Invalid memory address
&mem >>>execute<<<
Backtrace:
$7EFC61175B28 execute
I have to use
comp'
instead of'
, because it doesn't work for getting the xt ofEXIT
.
I would have thought this should work, unless Gforth doesn't operate in any way like JonesForth did where docol:
starts executing the xt's next to it.
Is this possible in either Gforth or ANS forth in general?
You can execute an arbitrary list of xt, but you have to use your own word to execute this list, by applying execute
to each xt from the list.
By the current standard, a standard program cannot compile arbitrary code into allocated memory. The program may only compile into the code space of the dictionary, and in the frame of the current definition (i.e., that is not yet completed). Compilation can be performed via compile, ( xt -- )
or postpone ( i*x "name" -- j*x )
words. Also the words literal
, 2literal
, sliteral
, fliteral
(or their counterparts lit,
, 2lit,
, slit,
, flit,
) can be used to compile literals.
In Gforth you can also compile into another dictionary ("section"), that can be allocated using word extra-section ( size "name" -- )
.
10000 extra-section execute-in-my-section
\ execute-in-my-section ( i*x xt -- j*x )
unused cr . \ free space in the default dictionary
[:
unused cr . \ free space in the current section
:noname
postpone .
postpone ;
( xt-new )
unused cr . \ free space after compile the new definition
;] execute-in-my-section ( xt-new )
\ test
123 swap execute
See also section.fs source, and Sections paper by Anton Ertl, 2016.