commit 38b0690556ce15ece376dea3fe58a86d5cd3b7f2
parent cf38c68a0d2fbb76063d5e63691c7cc4e1e295cb
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Sun, 4 Dec 2022 21:06:42 -0500
comp/c: allow empty cases in switch
Also, asm/uxntal compiles under the forth VM, but not i386.
Diffstat:
7 files changed, 27 insertions(+), 32 deletions(-)
diff --git a/fs/asm/uxntal.c b/fs/asm/uxntal.c
@@ -1,7 +1,7 @@
/* Source: https://git.sr.ht/~rabbits/uxn
* License: /license/dll-uxn.txt
*/
-// TODO: Doesn't compile yet. See TODOs below
+// TODO: Doesn't compile on i386 yet. See TODOs below
#define TRIM $100
#define LENGTH $10000
@@ -10,27 +10,27 @@ typedef unsigned char Uint8;
typedef char Sint8;
typedef unsigned short Uint16;
-typedef struct {
+struct Macro {
// TODO: allow multiple decls per line
char name[$40];
char items[$40*$40];
Uint8 len;
-} Macro;
+};
-typedef struct {
+struct Label {
char name[$40];
Uint16 addr;
Uint16 refs;
-} Label;
+};
-typedef struct {
+struct Reference {
char name[$40];
char rune;
Uint16 addr;
-} Reference;
+};
// TODO: this is pretty memory hungry by Dusk standards, revisit algo.
-typedef struct {
+struct Program {
Uint8 data[LENGTH];
unsigned int ptr;
unsigned int length;
@@ -41,7 +41,7 @@ typedef struct {
Macro macros[$100];
Reference refs[$800];
char scope[$40];
-} Program;
+};
Program p;
@@ -79,7 +79,6 @@ static Macro *
findmacro(char *name)
{
int i;
- // TODO: compile error below
for(i = 0; i < p.mlen; i++)
if(scmp(p.macros[i].name, name, $40))
return &p.macros[i];
@@ -99,9 +98,9 @@ findlabel(char *name)
static Uint8
findopcode(char *s)
{
- int i;
+ int i, m;
for(i = 0; i < $20; i++) {
- int m = 0;
+ m = 0;
if(!scmp(ops[i], s, 3))
// TODO: implement continue
// continue;
@@ -132,7 +131,7 @@ freadword(char *buf, int hdl)
for (i=0; i < $3f; i++) {
// TODO: add CC test for this, I'm really not sure it's going to work.
*buf++ = c;
- c = fgetc(hdl)
+ c = fgetc(hdl);
if ((c > 0) && (c <= ' ')) {
*buf = 0;
return 1;
@@ -194,6 +193,7 @@ makereference(char *scope, char *label, Uint16 addr)
char subw[$40], parent[$40];
int pos;
Reference *r;
+ Label *l;
if(p.rlen == $800)
return error("References limit exceeded", label);
r = &p.refs[p.rlen++];
@@ -202,7 +202,6 @@ makereference(char *scope, char *label, Uint16 addr)
else {
pos = spos(label + 1, '/');
if(pos > 0) {
- Label *l;
if((l = findlabel(scpy(label + 1, parent, pos))))
l->refs++;
}
@@ -279,7 +278,7 @@ parse(char *w, int hdl)
i = 1; /* track nested comment depth */
while(freadword(word, hdl) == 1) {
if(slen(word) != 1)
- continue;
+ /* continue; */ {}
else if(word[0] == '(')
i++;
else if(word[0] == ')' && --i < 1)
@@ -385,8 +384,9 @@ resolve(void)
{
Label *l;
int i;
+ Reference *r;
for(i = 0; i < p.rlen; i++) {
- Reference *r = &p.refs[i];
+ r = &p.refs[i];
switch(r->rune) {
case '_':
if(!(l = findlabel(r->name)))
@@ -455,11 +455,11 @@ review()
int i;
for(i = 0; i < p.llen; i++)
if(p.labels[i].name[0] >= 'A' && p.labels[i].name[0] <= 'Z')
- continue; /* Ignore capitalized labels(devices) */
+ /* continue; */ { } /* Ignore capitalized labels(devices) */
else if(!p.labels[i].refs)
fprintf(p.labels[i].name, "-- Unused label: %s\n", ConsoleOut());
fprintf(
- p.mlen, p.llen, p.length-TRIM
+ p.mlen, p.llen, p.length-TRIM,
"Assembled %d bytes, %d labels, %d macros.\n", ConsoleOut());
}
diff --git a/fs/comp/c/pgen.fs b/fs/comp/c/pgen.fs
@@ -329,9 +329,10 @@ current to parseFactor
current to parseExpression
+$40 const MAXSWITCHCASES
\ breaks are a list of forward jumps addr that need to be resolved at the end
\ of the "breakeable" structure.
-10 Stack :new structbind Stack breaks
+MAXSWITCHCASES Stack :new structbind Stack breaks
: addbreak vmjmp[, breaks :push ;
: resolvebreaks ( tgtlvl -- )
begin ( tgt ) breaks :count over > while breaks :pop ]vmjmp repeat drop ;
@@ -389,7 +390,6 @@ alias noop parseStatement ( tok -- ) \ forward declaration
\ generate our switch code so that it fetches its pointer to a lookup table at
\ a specific literal. It's only when we're done generating the case code that
\ we generate the lookup table and place a pointer to it at that placeholder.
-$40 const MAXSWITCHCASES
MAXSWITCHCASES << Stack :new structbind Stack _cases
: _switch
breaks :count >r \ V1=breakcnt
@@ -397,12 +397,12 @@ MAXSWITCHCASES << Stack :new structbind Stack _cases
CELLSZ _litarena :allot dup vmswitch, >r \ V2='lookup
vmjmp[, >r \ V3=defjump
nextt '{' expectChar nextt begin ( tok )
- dup S" case" s= if
- drop nextt parseConstExpr _cases :push here _cases :push
- nextt ':' expectChar nextt then ( tok )
dup '}' isChar? not while ( tok )
dup S" default" s= not while ( tok )
- parseStatement nextt repeat ( tok ) \ default
+ dup S" case" s= if
+ drop nextt parseConstExpr _cases :push here _cases :push
+ nextt ':' expectChar ( )
+ else parseStatement then ( ) nextt repeat ( tok ) \ default
r> ( defjump ) ]vmjmp nextt ':' expectChar parseStatements else ( tok ) \ }
r> ( defjump ) ]vmjmp then ( tok ) drop
_cases :count 1+ CELLSZ * _litarena :[
diff --git a/fs/tests/asm/all.fs b/fs/tests/asm/all.fs
@@ -1,4 +1,3 @@
\ Run all asm test suites
f<< /tests/asm/i386.fs
f<< /tests/asm/arm.fs
-f<< /tests/asm/uxntal.fs
diff --git a/fs/tests/asm/uxntal.fs b/fs/tests/asm/uxntal.fs
@@ -1,7 +0,0 @@
-?f<< /tests/harness.fs
-\ Doesn't compile yet
-\ ?f<< /asm/uxntal.fs
-testbegin
-\ Tests for asm/uxntal.fs
-testend
-
diff --git a/fs/tests/comp/c/cc.fs b/fs/tests/comp/c/cc.fs
@@ -72,6 +72,7 @@ globdata 4 + 16b @ 42 #eq
33 switchstmt 0 #eq
42 switchstmt 12 #eq
1234 switchstmt 3 #eq
+'A' switchstmt 2 #eq
5678 switchstmt 2 #eq
2 3 binop1 1 #eq
diff --git a/fs/tests/comp/c/test.c b/fs/tests/comp/c/test.c
@@ -281,6 +281,7 @@ int switchstmt(int x) {
switch (x) {
case 42: return 12;
case 1234: ++y;
+ case 'B'-1:
case 5678: ++y; break;
default: --y;
}
diff --git a/fs/tests/emul/uxn/vm.fs b/fs/tests/emul/uxn/vm.fs
@@ -2,6 +2,7 @@
?f<< /drv/ramdrive.fs
?f<< /fs/blob.fs
?f<< /emul/uxn/varvara.fs
+\ ?f<< /asm/uxntal.fs
testbegin
\ Testing uxn VM
\ Compiled from dummy.tal with uxn's official assembler