commit f966805f2daffa8b6c7d5902a354125778090f1c
parent 532a1af32c49c58bfbdbab24b0eb6fb6010866b5
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Tue, 23 Aug 2022 21:11:58 -0400
Add local variables
Diffstat:
5 files changed, 63 insertions(+), 7 deletions(-)
diff --git a/fs/doc/usage.txt b/fs/doc/usage.txt
@@ -83,6 +83,40 @@ Each metadata element has this structure:
4b type ID
( any other type-specific data )
+# Local variables
+
+It's a common pattern, to avoid PS juggling, to place an element on RS and
+recall that element with r@. It works well, but unfortunately, this only works
+with a single element. Another drawback is that this element can be "buried" by
+a pattern (a "next" loop for example) that needs to place something on RS.
+
+A workaround to this is to declare a "private" value near the word and store
+temporary values in there. It works too, but because those values are statically
+allocated, this can't be done in words that require recursion.
+
+Local variables are there to the rescue! There are 4 of them: V1 V2 V3 V4. These
+words do a simple thing: they reference an element on RS with "to" semantics.
+They are also impervious to being "buried" because they remember their "slot" at
+compile time and adjust their compilation accordingly.
+
+In other words, if RSTART is the address in memory of RSP when the word starts
+executing and considering the fact that RSP grows "downwards" in memory,
+V1=RSTART-4 and V4=RSTART-16.
+
+When using local variables, you are responsible with pushing and popping to/from
+RS. All those variables give you are "to" semantics to a "RS slot". Example:
+
+: foo ( a b c -- ) >r >r >r V1 . spc> V2 . spc> V3 . rdrop rdrop rdrop ;
+
+1 2 3 foo \ prints "3 2 1"
+
+: inc ( a -- a+1 ) >r 1 to+ V1 V1 rdrop ;
+42 inc . \ prints 43
+
+\ this works too
+: inc5 ( a -- a+5 ) >r 5 >r begin 1 to+ V1 next V1 rdrop ;
+42 inc5 . \ prints 47
+
# Structures
Structures are an effective way to address offsets from base addresses while
diff --git a/fs/tests/kernel.fs b/fs/tests/kernel.fs
@@ -90,6 +90,12 @@ ll llcnt 3 #eq
' bar 'emeta lladd 42 , ( ll )
42 ' bar emeta findemeta ( ll ) #eq
+\ Local variables
+: foo 54 >r 42 >r 1 to+ V1 2 to+ V2 V2 V1 rdrop rdrop ;
+foo 55 #eq 44 #eq
+: inc5 >r 5 >r begin 1 to+ V1 next V1 rdrop ;
+42 inc5 47 #eq
+
\ Structures
struct[ Foo
sfield bar
diff --git a/fs/xcomp/bootlo.fs b/fs/xcomp/bootlo.fs
@@ -4,7 +4,7 @@
' [ execute, ' exit, execute, exit,
," entry" 0 , sysdict @ , 5 c, here w>e sysdict ! ]
dup 1+ swap c@ tuck move, nextmeta @ , over @ , c,
- here w>e swap ! 0 nextmeta ! ;
+ here w>e swap ! 0 nextmeta ! 0 [rcnt] ! ;
," code" 0 , sysdict @ , 4 c, here w>e sysdict ! ]
sysdict word entry ;
code : ] code ] ;
@@ -32,7 +32,7 @@ code : ] code ] ;
: begin here ; immediate
: again compile (br) , ; immediate
: until compile (?br) , ; immediate
-: next compile (next) , ; immediate
+: next compile (next) , 4 [rcnt] +! ; immediate
: leave 1 litn 0 r', compile ! ; immediate
: = - not ;
: \ begin in< $0a = until ; immediate
@@ -185,6 +185,12 @@ alias noop [then]
litn litn compile _ else
swap _ then ; immediate
+\ Local variables
+: _varto ( a -- ) to? ?dup if execute else @ then ;
+: var, ( off -- ) [rcnt] @ neg CELLSZ - -^ r', compile _varto ;
+: V1 0 var, ; immediate : V2 4 var, ; immediate
+: V3 8 var, ; immediate : V4 12 var, ; immediate
+
\ Structures
0 value _extends
diff --git a/fs/xcomp/i386.fs b/fs/xcomp/i386.fs
@@ -24,10 +24,10 @@
\ Constants and labels
0 to realmode
: values ( n -- ) >r begin 0 value next ;
-26 values L1 L2 lblmainalias lbltoptr lbltoexec lbltoexec2 lblbootptr lblin<
+27 values L1 L2 lblmainalias lbltoptr lbltoexec lbltoexec2 lblbootptr lblin<
lblcurword lblnextmeta lblret lblsysdict lblemit lblparsec lblparseh
- lblparseud lblerrmsg lblrtype lblhere lblmovewrite lblwrite lblcwrite
- lblfind lblcompiling lblareg lblidt
+ lblparseud lblerrmsg lblrtype lblhere lbl[rcnt] lblmovewrite lblwrite
+ lblcwrite lblfind lblcompiling lblareg lblidt
$8000 const HERESTART \ TODO: find a better place
$500 to binstart
$2000 const STACKSZ
@@ -459,13 +459,20 @@ xcode []= ( a1 a2 u -- f )
[ebp] ax mov,
ret,
+pc to lbl[rcnt] 0 ,
+xcode [rcnt]
+ lbl[rcnt] pspushN,
+ ret,
+
\ 83 c4 XX --> add esp, XX
pc 2 nc, $83 $c4
xcode r+, ( n -- )
si ( pc ) i) mov,
cx 2 i) mov,
lblmovewrite abs>rel call,
- xwordlbl c, abs>rel jmp,
+ AX pspop,
+ lbl[rcnt] m) ax add,
+ lblcwrite abs>rel jmp,
\ 83 ed 04 --> sub ebp, 4
\ 89 45 00 --> mov [ebp], esp
diff --git a/posix/vm.c b/posix/vm.c
@@ -27,7 +27,8 @@ The VM is little endian.
#define HERE SYSVARS
#define SYSDICT (HERE+4)
#define NEXTMETA (SYSDICT+4)
-#define INRD (NEXTMETA+4)
+#define _RCNT_ (NEXTMETA+4)
+#define INRD (_RCNT_+4)
#define EMIT (INRD+4)
#define ABORT (EMIT+4)
#define MAINLOOP (ABORT+4)
@@ -334,6 +335,7 @@ static void RSADDWR() { // op: 21
dword n = ppop();
cwrite(0x20); // RSADD
cwrite(n);
+ sd(_RCNT_, gd(_RCNT_)+n);
}
static void RSADDR() { // op: 22
@@ -1059,6 +1061,7 @@ static void buildsysdict() {
sysconst("curword", CURWORD);
sysconst("sysdict", SYSDICT);
sysconst("nextmeta", NEXTMETA);
+ sysconst("[rcnt]", _RCNT_);
entry("_fsinfobuf"); allot(0x112); // used in FINFO
entry("mainloop");
sd(MAINLOOP, here());