dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit 26069b7788c8de842db5d9b1f60948ec909e6dfe
parent 7ce6c69e6b67eb2d55e46e48f1daa467d34d6ccf
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Fri, 15 Jul 2022 19:51:39 -0400

doc: add caveats about calling Forth words from C

Mfs/doc/cc.txt | 22++++++++++++++++------
Mfs/tests/cc/cc.fs | 2+-
Mfs/tests/cc/test.c | 10++++------
3 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/fs/doc/cc.txt b/fs/doc/cc.txt @@ -68,15 +68,15 @@ When you think about it, it's the same thing as with Forth words. When the function begins, it allocates enough space for its local variables on RS. Its arguments are already on PS, where they should be, so it does nothing. -When the function returns, it frees local frame from RS and PSP according to -the function's "argument balance". If it returns more arguments than it -received, PS will grow, if it returns less arguments than received, PS shrinks. -Then, we return. +When the function returns, it frees local frame from RS. It also adjusts PSP +according to the function's "argument balance". If it returns more arguments +than it received, PS will grow, if it returns less arguments than received, PS +shrinks. Then, we return. Let's use an example: int foobar(int a, int b) { - int x = 42 + int x = 42; return a+b+x; } @@ -131,7 +131,8 @@ gives you the ability to pop or push a variable number of arguments from/to PS. These functions, however, are incompatible with arguments and return values. If you use both at the same time, they'll mess your PS stack. You can only use them -in functions that have a "void (void)" signature. Let's see an example. +in functions that have a "void (void)" signature (except what calling Forth +words, see below). Let's see an example. void foobar() { int b = pspop(); @@ -165,3 +166,12 @@ And right before returning: PSP+0 ->| $0000002d | RSP+0 -> | return addr | |-----------| |-------------| +## Calling Forth words + +Words from the system dictionary can be called. They are considered to have a +int return type and an unspecified number of arguments. + +Arguments to Forth words can be passed normally, but return values have to be +handled with pspop() and pspush(). Whenever you call such a function, you should +return to "PS normality" before using one of your function arguments, because if +you don't, PS offsets for those arguments will be wrong. diff --git a/fs/tests/cc/cc.fs b/fs/tests/cc/cc.fs @@ -32,7 +32,7 @@ cnoop ( no result! ) scnt 0 #eq array 52 #eq global 1234 #eq 42 142 sysword 142 #eq -helloworld S" Hello World!" #s= +capture helloworld S" Hello World!" #s= 42 40 50 isinrange 1 #eq 42 30 40 isinrange 0 #eq 42 5 forloop 47 #eq diff --git a/fs/tests/cc/test.c b/fs/tests/cc/test.c @@ -114,12 +114,10 @@ int global() { int sysword(int a, int b) { return max(a, b); } -// TODO: the effect would be better with stype(), but unfortunately, because -// stype doesn't return an argument, the stackframe is broken when we call it. -// When we begin supporting C signature in forth word annotations, then we can -// revisit this and call stype(). -int helloworld() { - return "Hello World!"; +void helloworld() { + // TODO: detect void return types when calling functions + pspush(0); // dummy element to offset stype's "void" return type + stype("Hello World!"); } // Now let's put all this together an start calling fancy forth words! int isinrange(int n, int l, int h) {