commit f22d2deb4c8bc8e97458bdb4e4c6abcebb6d0aea
parent e9aa475699b83ff9d30fcbb1e92f4e84e5adb745
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Sun, 25 Sep 2022 09:29:28 -0400
cc: invert default function storage type
We replace the "extern" keyword with the "static" one.
Diffstat:
7 files changed, 65 insertions(+), 68 deletions(-)
diff --git a/fs/app/cos/cvm.c b/fs/app/cos/cvm.c
@@ -1,7 +1,5 @@
// This doesn't compile. It's a prototype of what it will look like.
-// TODO: struct
// TODO: function pointer arrays (iord iowr).
-// TODO: make "extern" default. explicit "static" is better I think...
// TODO: += -= &= |= %
// TODO: %s %x (4b hex) %w (2b hex) %b (1b hex) formatting
// TODO: NULL
diff --git a/fs/cc/ast.fs b/fs/cc/ast.fs
@@ -136,17 +136,17 @@ extends Declarations struct[ Statements
nip exit then then
Node nextsibling repeat ( name ) drop 0 ;
-0 value curextern \ is current definition "extern"?
+0 value curstatic \ is current definition "static"?
extends NamedNode struct[ Function
sfield type \ type of return value
sfield address
sfield cursf \ last SF offset computed
- sfield flags
+ sfield flags \ b0=static
: :new ( type name -- node )
AST_FUNCTION NamedNode :new ( type name node )
rot ( type ) , 0 ( address ) , 0 ( cursf ) ,
- curextern ( flags ) , tuck :storename ;
+ curstatic ( flags ) , tuck :storename ;
: :finddecl ( name fnode -- dnode-or-0 )
firstchild ( args ) 2dup findDecl ?dup if
@@ -584,8 +584,8 @@ current to parseStatements
\\ Parse the next element in a Unit node
: parseUnit ( unitnode tok -- )
dup S" #[" s= if drop #[0 drop exit then
- 0 to curextern
- dup S" extern" s= if drop nextt 1 to curextern then
+ 0 to curstatic
+ dup S" static" s= if drop nextt 1 to curstatic then
dup S" struct" s= if drop parseStruct else
parseType _assert ( unode type ) parseType* ( unode type tok )
expectIdent ( unode type name ) nextt case ( unode type name )
diff --git a/fs/cc/cc.fs b/fs/cc/cc.fs
@@ -19,7 +19,6 @@ require sys/xhere.fs
: :cfunc
xhere$ xhere[ newparseunit nextt parseUnit ]xhere
curunit Node firstchild dup _assert ( node )
- 1 over to Function flags ( set extern )
_debug if dup printast nl> then
dup trnode _debug if dup printast nl> then gennode ;
diff --git a/fs/cc/gen.fs b/fs/cc/gen.fs
@@ -153,7 +153,7 @@ ASTIDCNT wordtbl gentbl ( node -- )
:w ( Function )
_debug if ." debugging: " dup Function name stype nl> then
ops$
- dup Function flags 1 and ( extern? ) if
+ dup Function flags 1 and not if \ not static
sysdict over Function name entry then ( fnode )
here over to Function address
dup Function :args Declarations :totsize over
diff --git a/fs/doc/cc.txt b/fs/doc/cc.txt
@@ -29,13 +29,13 @@ For this reason, the core of the language is very close to ANSI.
There are two ways to compile code with this compiler. The regular method is
through "cc<<", which compiles the specified file. For example, "cc<< foo.c"
-Reads the file "foo.c" as a unit and compile every element in it. Functions with
-the "extern" storage type will be added to the system dictionary.
+Reads the file "foo.c" as a unit and compile every element in it. Functions will
+be added to the system dictionary unless they have the "static" storage type.
Another method is to compile in an "inline" manner with ":cfunc". This word
-reads a single function from the input stream and compiles it, automatically
-adding the "extern" storage type to it. It returns to normal Forth
-interpretation when it parses the last closing "}" character. Example:
+reads a single function from the input stream and compiles it. It returns to
+normal Forth interpretation when it parses the last closing "}" character.
+Example:
:cfunc int foo() {
return 42;
@@ -265,11 +265,11 @@ i]# --> Ident ]#
## Linkage
-By default, functions have internal linkage. You give a function external
-linkage with "extern".
+By default, functions have external linkage. You give a function internal
+linkage with "static".
-void foo() { }
-extern void bar() { foo(); }
+static void foo() { }
+void bar() { foo(); }
This unit will compile fine. Because "foo()" is in the same unit as "bar()",
"bar()" can call "foo()". However, that function can't be called from another
diff --git a/fs/lib/crc.c b/fs/lib/crc.c
@@ -1,4 +1,4 @@
-extern unsigned int crc32(unsigned int crc, int c) {
+unsigned int crc32(unsigned int crc, int c) {
unsigned int i, b;
crc = crc ^ c;
diff --git a/fs/tests/cc/test.c b/fs/tests/cc/test.c
@@ -3,82 +3,82 @@
#[ 42 const MYCONST ]#
// just return a constant
-extern int retconst() {
+int retconst() {
return #[ MYCONST c]# ;
}
-extern int variables() {
+int variables() {
unsigned int foo = 40, _bar = 2;
_bar = foo + _bar;
return foo + _bar;
}
// test unary op and that we don't require whitespace around symbols
-extern int neg() {int a=$2a; return -a;}
-extern int bwnot() {
+int neg() {int a=$2a; return -a;}
+int bwnot() {
int a='*';
return ~a;
}
// test binop precedence
-extern int exprbinops() {
+int exprbinops() {
unsigned int a=1, b=2;
return a + b * 3;
}
-extern int binopand() {
+int binopand() {
int a=$ff;
return a & 42;
}
-extern int binopor() {
+int binopor() {
int a=2;
return 40 | a;
}
-extern int binopxor() {
+int binopxor() {
int a=43;
return a ^ 1;
}
-extern int binopshl() {
+int binopshl() {
int a=42;
return a << 3;
}
-extern int binopshr() {
+int binopshr() {
int a=42;
return a >> 2;
}
-extern int binopdiv() {
+int binopdiv() {
int a=42;
return a / 3;
}
-extern int boolops() {
+int boolops() {
int a=66, b=2;
return a < 54 && 2 == b;
}
-extern int funcall() {
+int funcall() {
return retconst();
}
-extern void pushpop() {
+void pushpop() {
pspush(pspop());
}
// this function has a internal linkage
-int adder(int a, int b) {
+static int adder(int a, int b) {
return a + b;
}
-extern int subber(int a, int b) {
+int subber(int a, int b) {
return a - b;
}
// are arguments, both constants and lvalues, properly passed?
-extern int plusone(int x) {
+int plusone(int x) {
return adder(1, x);
}
-extern int ptrget() {
+int ptrget() {
int a = 42;
int *b = &a;
return *b;
}
-extern int ptrset() {
+int ptrset() {
int a = 42;
int *b = &a;
*b = 54;
return a;
}
-extern int condif(int x) {
+int condif(int x) {
if (x == 42) {
x = x+100;
} else {
@@ -87,29 +87,29 @@ extern int condif(int x) {
return x;
}
// test that ++ and -- modify the lvalue directly
-extern int incdec(int x) {
+int incdec(int x) {
++x;
--x;
return ++x;
}
// test that the final "--" doesn't affect the result
-extern int incdecp(int x) {
+int incdecp(int x) {
x++;
x--;
return x--;
}
// test that parens override precedence
-extern int exprparens() {
+int exprparens() {
return (1 + 2) * 3;
}
// test that a void function doesn't add anything to PS
-extern void cnoop() {}
+void cnoop() {}
// test that pointer arithmetics properly multiply operands by 2 or 4.
-extern int* ptrari(int *x) {
+int* ptrari(int *x) {
cnoop(); // this doesn't mess up PS
return x + 1;
}
-extern int array() {
+int array() {
int a[3] = {42, 12, 2};
return *a + a[1] - *(a+2);
}
@@ -117,29 +117,29 @@ extern int array() {
int global1 = 1234;
int global2[3] = {4, 5, 6};
-extern int global() {
+int global() {
return global1;
}
-extern int globalinc() {
+int globalinc() {
global1++;
return ++global1;
}
// "max" is a forth word defined in the system
-extern int sysword(int a, int b) {
+int sysword(int a, int b) {
return max(a, b);
}
-extern void helloworld() {
+void helloworld() {
stype("Hello World!");
}
// Now let's put all this together an start calling fancy forth words!
// Here, we see the power of macros in action. Let's say we want to call the
// system word "=><=". It's not a valid C identifier, right? ok, but what about
// using macros to trick the parser into accepting it?
-extern int isinrange(int n, int l, int h) {
+int isinrange(int n, int l, int h) {
#[ S" =><=" i]# (n, l, h);
return pspop();
}
-extern int forsum(int n) {
+int forsum(int n) {
int i;
int r = 0;
for (i=0; i<n; i++) {
@@ -147,21 +147,21 @@ extern int forsum(int n) {
}
return r;
}
-extern unsigned int multret(unsigned int x) {
+unsigned int multret(unsigned int x) {
if (x < 10) {
return x;
} else {
return x-10;
}
}
-extern void multretvoid(unsigned int x) {
+void multretvoid(unsigned int x) {
if (x == 42) {
stype("Answer to the universe");
return;
}
stype("Nope");
}
-extern int forbreak() {
+int forbreak() {
int i, j;
for (i=0; i<100; i++) {
if (i==10) {
@@ -172,29 +172,29 @@ extern int forbreak() {
}
return i;
}
-extern int lts(int a, int b) {
+int lts(int a, int b) {
return a < b;
}
-extern int ltu(unsigned int a, unsigned int b) {
+int ltu(unsigned int a, unsigned int b) {
return a < b;
}
-extern int boolnot(int x) {
+int boolnot(int x) {
return !x;
}
-extern char get8b(char *s, int i) {
+char get8b(char *s, int i) {
return s[i]; // 0th is length
}
-extern void set8b(char *s, int i, char c) {
+void set8b(char *s, int i, char c) {
s[i] = c;
}
-extern void whilesum(int n) {
+void whilesum(int n) {
int res = 0;
while (n) {
res = res + n--;
}
return res;
}
-extern void dowhilesum(int n) {
+void dowhilesum(int n) {
int res = 0;
do {
res = res + n--;
@@ -202,7 +202,7 @@ extern void dowhilesum(int n) {
return res;
}
// unary op, apart from ++ and --, *don't* modify their target.
-extern int unaryopmut(int n) {
+int unaryopmut(int n) {
!n;
return n;
}
@@ -213,25 +213,25 @@ struct MyStruct {
char baz[2];
};
-extern short structget(struct MyStruct *s) {
+short structget(struct MyStruct *s) {
return s->bar;
}
-extern void structset(struct MyStruct *s, char val) {
+void structset(struct MyStruct *s, char val) {
s->baz[1] = val;
}
-extern int sysstructget(struct Field *f) {
+int sysstructget(struct Field *f) {
return f->size;
}
-extern void sysstructset(struct Field *f, int val) {
+void sysstructset(struct Field *f, int val) {
f->size = val;
}
// Below this comment are simple construct that were buggy before
-extern int binop1(int a, int b) {
+int binop1(int a, int b) {
int c;
c = a ^ b;
return c;
}
-extern int binop2(int n) {
+int binop2(int n) {
int x = 42;
x = x + n - '0';
return x;