Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.forth > #21356
| From | mhx@iae.nl (Marcel Hendrix) |
|---|---|
| Subject | Re: Anonymous code/data/create-does |
| Newsgroups | comp.lang.forth |
| Message-ID | <02591300998434@frunobulax.edu> (permalink) |
| Date | 2013-04-03 22:44 +0200 |
| References | <93571201998434@frunobulax.edu> |
| Organization | Wanadoo |
The old [: ... ;] could not have locals, but knew ho to access the locals of the
host definition. As this seems to be quite useful, a second variant was added:
<: ... :>. Such blocks support having locals and also support EXIT. However,
a <: .. :> block can not access outer locals.
The ^{ .. }^ word was a mistake. The new ^, word ( does-xt -- child-xt )
creates an anonymous child and returns it xt. The data for the child is
supposed to be at HERE. When putting both [: ... ;], ^, and (e.g.) ","
inside a definer-word, children can be dynamically created. Such children
inherit the anonymous code and have a data field (at HERE) that can be
initialized from the data passed to the definer word (e.g. with ",").
With indirection, a single data area can have any number of anonymous
code blocks attached.
It is now possible to "freeze" any amount of environmental data of the
host word when a child is created. This is under programmer control (not
done automatically, and used memory is not garbage collected).
The code has not grown in size. SELF is removed.
I found factors of the anonymous blocks hidden in the iForth sources.
Apparently the concept was just waiting for vocalization.
-marcel
-- ----------
(*
* LANGUAGE : ANS Forth with extensions
* PROJECT : Forth Environments
* DESCRIPTION : Primitive form of anonymous words
* CATEGORY : Experiment
* AUTHOR : Marcel Hendrix
* LAST CHANGE : Wednesday, April 03, 2013, 19:27, Marcel Hendrix; added locals and EXIT
* LAST CHANGE : Monday, April 01, 2013, 17:07, Marcel Hendrix
*)
NEEDS -miscutil
REVISION -anons "--- Anonymous words Version 0.02 ---"
PRIVATES
DOC
(*
CALL here
[ here TO dict ]
>R
...code...
R> ret
here:
LOCALs in a definition that builds anonymous words can be a problem when you compile
a reference to a local before *all* locals are defined.
An anonymous code block can have its own locals, and it can access outer locals.
-- An anonymous code block
: test1
0 LOCAL xt
[: + 2+ 3 AND ;] TO xt
#11 #12 xt EXECUTE . ;
-- An anonymous CREATE DOES> structure
: test-createdoes ( val -- xt2 )
[: DUP @ 1 ROT +! ;] ( val xt1 -- ) \ define code (does>)
^, ( val xt2 -- ) SWAP , ; \ create new var, initialize, leave xt of object
1 test-createdoes CONSTANT counter
counter EXECUTE . ( 1)
counter EXECUTE . ( 2)
*)
ENDDOC
0 VALUE dict PRIVATE : MYSELF ( -- ) dict 5 + POSTPONE LITERAL POSTPONE EXECUTE ; IMMEDIATE
ALSO ASSEMBLER
: <: ([:) -OPT AHEAD, OVER TO dict POSTPONE >R -OPT ; IMMEDIATE ( own locals )
: [: -OPT AHEAD, OVER TO dict POSTPONE >R -OPT ; IMMEDIATE ( reuse outer locals )
: ;> POSTPONE R> -OPT (;]) $C3 ( ret) C, ENDIF, $E8 ( call) dict C! ; IMMEDIATE \ modify jump to call
: ;] POSTPONE R> -OPT $C3 ( ret) C, ENDIF, $E8 ( call) dict C! ; IMMEDIATE
: ^, ( xt-does -- xt-child )
HERE SWAP POSTPONE >R -OPT $90909090 32B, $90 C, ( 5 nops) ALIGN -5 ALLOT
$E8 ( call) C, 9 + ( skip >R) HERE 4 + - 32B, ( rel call of does> code) ;
PREVIOUS
NESTING @ 1 =
[IF] -- Examples
-- "1"
: test [: + 2+ 3 AND ;] #11 #12 ROT EXECUTE . ;
-- 11 12 test1 gives "a = 11 b = 12 result = 25"
-- Here we want access to outer locals.
: test1 ( a b -- )
LOCALS| b a |
CR ." a = " a . ." b = " b .
[: a b + 2+ ." result = " . ;] EXECUTE ;
-- 11 12 test2
-- a = 11 b = 12 xt = $01406F80
-- first : result = 134
-- second : result = 245 ok
-- Here we want access to outer locals.
: test2 ( a b -- )
0 LOCALS| xt b a |
." a = " a . ." b = " b .
[: a b + ( offs) + ." result = " . ;] TO xt
." xt = " xt H.
CR ." first : " #111 xt EXECUTE
CR ." second : " #222 xt EXECUTE ;
-- Does work; there is code between the local setups, but we don't compile references then.
: test3 PI FLOCAL p
[: F+ F+ ;]
[: F- F- ;]
[: F* F* ;] LOCALS| xt* xt- xt+ |
11e 2e 3e xt+ EXECUTE F.
11e 2e 3e xt- EXECUTE F.
11e 2e 3e xt* EXECUTE F.
p F. ;
: test-recursion ( flag -- )
#10 SWAP
IF [: ( n1 -- n2 ) DUP 1 > IF DUP 1- MYSELF SWAP 2- MYSELF + ENDIF ;] \ fib
ELSE [: ( n1 -- n2 ) DUP IF DUP 1- MYSELF SWAP * ELSE 1+ ENDIF ;] \ fac
ENDIF EXECUTE . ;
-- Does not work; setup locals *before* referencing them (ANS :-)
: test4a pi FLOCAL p
[: F+ F+ p F+ ;]
[: F- F- p F- ;]
[: F* F* p F* ;] LOCALS| xt* xt- xt+ |
11e 2e 3e xt+ EXECUTE F.
11e 2e 3e xt- EXECUTE F.
11e 2e 3e xt* EXECUTE F. ;
-- Correct usage, this works.
: test4b pi FLOCAL p
0 0 0 LOCALS| xt* xt- xt+ |
[: F+ F+ p F+ ;] TO xt+
[: F- F- p F- ;] TO xt-
[: F* F* p F* ;] TO xt*
11e 2e 3e xt+ EXECUTE F.
11e 2e 3e xt- EXECUTE F.
11e 2e 3e xt* EXECUTE F. ;
: ptest ( F: r -- )
[: F+ F+ ;] >S
[: F- F- ;] >S
[: F* F* ;] >S
FLOCAL p
11e 2e 3e S> EXECUTE F.
11e 2e 3e S> EXECUTE F.
11e 2e 3e S> EXECUTE F.
p F. ;
: ntest ( F: r -- )
FLOCAL p
[: F+ F+ ;] >R 11e 2e 3e R> EXECUTE F.
[: F- F- ;] >R 11e 2e 3e R> EXECUTE F.
[: F* F* ;] >R 11e 2e 3e R> EXECUTE F.
p F. ;
: int-ntest ( n -- )
LOCAL p
[: + + ;] >R #11 2 3 R> EXECUTE .
[: - - ;] >R #11 2 3 R> EXECUTE .
[: * * ;] >R #11 2 3 R> EXECUTE .
p . ;
DEFER do-this
DEFER do-that
: generic do-this do-that ;
: mode-1 [: CR ." x" ;] [IS] do-this [: ." y" ;] [IS] do-that ;
: mode-2 [: CR ." this " ;] [IS] do-this [: ." that " ;] [IS] do-that ;
: TEST-generic mode-1 generic mode-2 generic ;
-- Can we emulate DOES> and LIST> ?
\ : list> ( thread -- element )
\ BEGIN @ dup WHILE dup r@ execute
\ REPEAT drop r> drop ;
\ : print-elements ( a -) list> .element ;
: ITERATE ( addr xt -- ) >R BEGIN DUP WHILE DUP @ SWAP CELL+ R@ EXECUTE REPEAT DROP -R ;
0 VALUE data
: LINK, ALIGN HERE data , TO data ;
0 TO data
LINK, ," ! "
LINK, ," World"
LINK, ," Hello, "
data =: privatedata1
0 TO data
LINK, ," ? "
LINK, ," Wereld"
LINK, ," Hallo, "
data =: privatedata2
: .elements ( addr -- ) [: COUNT TYPE ;] ITERATE ;
: .dump ( addr -- ) [: #20 DUMP ;] ITERATE ;
: #elements ( addr -- ) 0 LOCAL #cnt [: DROP 1 +TO #cnt ;] ITERATE #cnt . ." elements." ;
: .bytes ( addr -- ) 0 LOCAL #cnt [: C@ +TO #cnt ;] ITERATE #cnt . ." bytes used." ;
\ privatedata2 .elements Hallo, Wereld? ok
\ privatedata1 .elements Hello, World! ok
\ privatedata1 #elements 3 elements. ok
\ privatedata2 #elements 3 elements. ok
\ privatedata2 .bytes 15 bytes used. ok
\ privatedata1 .bytes 14 bytes used. ok
: test-5 22 11 0 LOCALS| xt a b |
[: a b + 2* ;] TO xt
xt EXECUTE .
#33 TO a #44 TO b xt EXECUTE . ; ( prints 66 154 )
: foo ( n -- xt1 xt2 ) LOCAL n [: n ;] [: TO n ;] ;
DEFER x
DEFER to-x
-- This works although the Locals stack is accessed in an uncontrolled way.
-- May overwrite local values of other words higher up the call-chain.
: test-undef ( -- )
CR ." undefined behavior "
5 foo [IS] to-x [IS] x
CR x .
6 to-x CR x . ;
: foo-too ( n -- child@ child! )
HERE SWAP , LOCAL 'n
[: @ @ ;]
[: @ ! ;]
SWAP ^, 'n , ( xt-store child@ )
SWAP ^, 'n , ( child@ child! ) ;
: test-undef-too ( -- )
5 foo-too [IS] to-x [IS] x
CR x .
6 to-x CR x . ;
-- An anonymous can have its own locals (EXIT works!).
: test-locals ( a b -- xt )
0 LOCALS| xt b a |
CR ." a + b = " a b + .
<: LOCALS| d c |
CR ." c + d = " c d + .
;> TO xt
#11 #22 xt EXECUTE
a b xt EXECUTE
c d xt EXECUTE ( garbage :-)
xt ;
-- Anonymous CREATE DOES> like
: test-createdoes ( val -- xt2 ) [: DUP @ 1 ROT +! ;] ( val xt1 -- ) ^, ( val xt2 -- ) SWAP , ;
1 test-createdoes =: counter1
#11 test-createdoes =: counter11
CR .( expect 1 2 11 3 12)
CR .( result )
counter1 EXECUTE . counter1 EXECUTE .
counter11 EXECUTE . counter1 EXECUTE . counter11 EXECUTE .
:ABOUT CR ." Try: test -- Prints `16.000000 12.000000 66.000000 3.141593`"
CR ." mode-1 generic -- Prints `xy`"
CR ." mode-2 generic -- Prints `this that`" ;
[ELSE]
:ABOUT CR ." [: -- open anon"
CR ." ;] -- finish anon, leaves xt at compile-time"
CR ." ^{ }^ -- allows data section, picked up by code"
CR ." MYSELF -- recurse a anon"
CR ." SELF -- refer to last data section defined by ^{ " ;
[THEN]
.ABOUT -anons CR
DEPRIVE
(* End of Source *)
Back to comp.lang.forth | Previous | Next — Previous in thread | Next in thread | Find similar
Anonymous code/data/create-does mhx@iae.nl (Marcel Hendrix) - 2013-04-02 23:46 +0200
Re: Anonymous code/data/create-does "WJ" <w_a_x_man@yahoo.com> - 2013-04-02 22:51 +0000
Re: Anonymous code/data/create-does "WJ" <w_a_x_man@yahoo.com> - 2013-04-02 23:00 +0000
Re: Anonymous code/data/create-does Gerry Jackson <gerry@jackson9000.fsnet.co.uk> - 2013-04-03 11:07 +0100
Re: Anonymous code/data/create-does m.a.m.hendrix@tue.nl - 2013-04-03 06:53 -0700
Re: Anonymous code/data/create-does Alex McDonald <blog@rivadpm.com> - 2013-04-03 13:43 -0700
Re: Anonymous code/data/create-does Gerry Jackson <gerry@jackson9000.fsnet.co.uk> - 2013-04-04 18:07 +0100
Re: Anonymous code/data/create-does mhx@iae.nl (Marcel Hendrix) - 2013-04-04 00:38 +0200
Re: Anonymous code/data/create-does Gerry Jackson <gerry@jackson9000.fsnet.co.uk> - 2013-04-04 18:18 +0100
Re: Anonymous code/data/create-does mhx@iae.nl (Marcel Hendrix) - 2013-04-04 20:29 +0200
Re: Anonymous code/data/create-does mhx@iae.nl (Marcel Hendrix) - 2013-04-06 20:40 +0200
Re: Anonymous code/data/create-does Alex McDonald <blog@rivadpm.com> - 2013-04-06 14:09 -0700
Re: Anonymous code/data/create-does mhx@iae.nl (Marcel Hendrix) - 2013-04-07 02:04 +0200
Re: Anonymous code/data/create-does Alex McDonald <blog@rivadpm.com> - 2013-04-06 20:34 -0700
Re: Anonymous code/data/create-does mhx@iae.nl (Marcel Hendrix) - 2013-04-07 14:00 +0200
Re: Anonymous code/data/create-does kenney@cix.compulink.co.uk - 2013-04-08 02:38 -0500
Re: Anonymous code/data/create-does Roelf Toxopeus <rt4all@notthis.hetnet.nl> - 2013-04-08 10:58 +0200
Re: Anonymous code/data/create-does Alex McDonald <blog@rivadpm.com> - 2013-04-08 14:57 -0700
Re: Anonymous code/data/create-does Bernd Paysan <bernd.paysan@gmx.de> - 2013-04-08 19:26 +0200
Re: Anonymous code/data/create-does kenney@cix.compulink.co.uk - 2013-04-09 02:07 -0500
Re: Anonymous code/data/create-does mhx@iae.nl (Marcel Hendrix) - 2013-04-03 22:44 +0200
Re: Anonymous code/data/create-does Lars Brinkhoff <lars.spam@nocrew.org> - 2013-04-04 12:42 +0200
Re: Anonymous code/data/create-does Andrew Haley <andrew29@littlepinkcloud.invalid> - 2013-04-04 07:04 -0500
Re: Anonymous code/data/create-does Andrew Haley <andrew29@littlepinkcloud.invalid> - 2013-04-04 07:07 -0500
csiph-web