commit fd71d97dfccec52024c5bf533504245e29d1fce1
parent 9fc632bc28521e9fc7c4f26b330d662faacabfed
Author: neauoire <aliceffekt@gmail.com>
Date: Mon, 22 Feb 2021 22:15:02 -0800
Progress on macros
Diffstat:
5 files changed, 114 insertions(+), 25 deletions(-)
diff --git a/README.md b/README.md
@@ -29,6 +29,7 @@ evaluxn(u, u->vframe); /* Each frame
- `@label`, assign the current address to a label.
- `;variable 2`, assign an address to a label automatically.
- `:const 1a2b`, assign an address to a label manually.
+- `¯o { x 2 y 2 }`, define a macro named `macro`.
### Write
diff --git a/assembler.c b/assembler.c
@@ -22,13 +22,22 @@ typedef struct {
} Program;
typedef struct {
+ char name[64], keys[16][64];
+ Uint8 len, lens[16];
+} Macro;
+
+typedef struct {
Uint8 len;
Uint16 addr;
char name[64];
} Label;
+int macroslen;
+Macro macros[256];
+
int labelslen;
Label labels[256];
+
Program p;
/* clang-format off */
@@ -69,6 +78,16 @@ pushshort(Uint16 s, int lit)
pushbyte(s & 0xff, 0);
}
+Macro *
+findmacro(char *s)
+{
+ int i;
+ for(i = 0; i < macroslen; ++i)
+ if(scmp(macros[i].name, s))
+ return ¯os[i];
+ return NULL;
+}
+
Label *
findlabel(char *s)
{
@@ -109,6 +128,36 @@ error(char *name, char *id)
}
int
+makemacro(char *name, FILE *f)
+{
+ Uint8 mode = 0;
+ Macro *m;
+ char wv[64];
+ if(findmacro(name))
+ return error("Macro duplicate", name);
+ if(sihx(name))
+ return error("Macro name is hex number", name);
+ if(findopcode(name))
+ return error("Macro name is invalid", name);
+ m = ¯os[macroslen++];
+ while(fscanf(f, "%s", wv)) {
+ if(wv[0] == '{')
+ continue;
+ if(wv[0] == '}')
+ break;
+ if(mode == 0)
+ scpy(wv, m->keys[m->len], 64);
+ else {
+ m->lens[m->len] = shex(wv);
+ m->len++;
+ }
+ mode = !mode;
+ }
+ printf("New macro: %s[%d items]\n", name, m->len);
+ return 1;
+}
+
+int
makelabel(char *name, Uint16 addr, Uint8 len)
{
Label *l;
@@ -140,33 +189,19 @@ makevariable(char *id, Uint16 *addr, FILE *f)
char wv[64];
Uint8 origin;
fscanf(f, "%s", wv);
- if(!sihx(wv))
- return error("Variable value is invalid", wv);
origin = *addr;
*addr += shex(wv);
return makelabel(id, origin, shex(wv));
}
int
-skipcomment(char *w, int *cap)
-{
- if(w[0] == ')') {
- *cap = 0;
- return 1;
- }
- if(w[0] == '(') *cap = 1;
- if(*cap) return 1;
- return 0;
-}
-
-int
-skipbinary(char *w, int *cap)
+skipblock(char *w, int *cap, char a, char b)
{
- if(w[0] == ']') {
+ if(w[0] == b) {
*cap = 0;
return 1;
}
- if(w[0] == '[') *cap = 1;
+ if(w[0] == a) *cap = 1;
if(*cap) return 1;
return 0;
}
@@ -213,9 +248,9 @@ pass1(FILE *f)
Uint16 addr = 0;
char w[64];
while(fscanf(f, "%s", w) == 1) {
- if(skipcomment(w, &ccmnt)) continue;
+ if(skipblock(w, &ccmnt, '(', ')')) continue;
if(skipstring(w, &cstrg, &addr)) continue;
- if(skipbinary(w, &cbits))
+ if(skipblock(w, &cbits, '[', ']'))
addr += w[0] != '[' && w[0] != ']' ? 2 : 0;
else if(w[0] == '@') {
if(!makelabel(w + 1, addr, 0))
@@ -223,6 +258,9 @@ pass1(FILE *f)
} else if(w[0] == ';') {
if(!makevariable(w + 1, &addr, f))
return error("Pass1 failed", w);
+ } else if(w[0] == '&') {
+ if(!makemacro(w + 1, f))
+ return error("Pass1 failed", w);
} else if(w[0] == ':') {
if(!makeconst(w + 1, f))
return error("Pass1 failed", w);
@@ -249,16 +287,18 @@ pass1(FILE *f)
int
pass2(FILE *f)
{
- int ccmnt = 0, cstrg = 0, cbits = 0;
+ int ccmnt = 0, cstrg = 0, cbits = 0, cmacro = 0;
char w[64];
while(fscanf(f, "%s", w) == 1) {
Uint8 op = 0;
Label *l;
if(w[0] == '@') continue;
- if(skipcomment(w, &ccmnt)) continue;
+ if(w[0] == '&') continue;
+ if(skipblock(w, &ccmnt, '(', ')')) continue;
+ if(skipblock(w, &cmacro, '{', '}')) continue;
if(capturestring(w, &cstrg)) continue;
/* clang-format off */
- if(skipbinary(w, &cbits)) { if(w[0] != '[' && w[0] != ']') { pushshort(shex(w), 0); } }
+ if(skipblock(w, &cbits, '[', ']')) { if(w[0] != '[' && w[0] != ']') { pushshort(shex(w), 0); } }
else if(w[0] == '|') p.ptr = shex(w + 1);
else if((op = findopcode(w)) || scmp(w, "BRK")) pushbyte(op, 0);
else if(w[0] == ':') fscanf(f, "%s", w);
diff --git a/etc/usm.sublime-syntax b/etc/usm.sublime-syntax
@@ -21,12 +21,21 @@ contexts:
- match: '\|(\S+)\s?'
scope: punctuation.definition
pop: true
+ - match: '\_(\S+)\s?'
+ scope: punctuation.definition
+ pop: true
- match: '\+(\S+)\s?'
scope: keyword.control
pop: true
- match: '\-(\S+)\s?'
scope: keyword.control
pop: true
+ - match: '\~(\S+)\s?'
+ scope: keyword.control
+ pop: true
+ - match: '\=(\S+)\s?'
+ scope: keyword.control
+ pop: true
strings:
- match: '\:(\S+)\s?'
@@ -38,6 +47,9 @@ contexts:
- match: '\@(\S+)\s?'
scope: string.control
pop: true
+ - match: '\&(\S+)\s?'
+ scope: string.control
+ pop: true
- match: '\,(\S+)\s?'
scope: keyword.control
pop: true
@@ -50,11 +62,17 @@ contexts:
- match: '\"(\S+)\s?'
scope: keyword.control
pop: true
+ - match: '\['
+ scope: punctuation.definition.keyword.usm
+ push:
+ - meta_scope: keyword.line.double-slash.usm
+ - match: '\]'
+ pop: true
comments:
- match: '\('
- scope: punctuation.definition.comment.tome
+ scope: punctuation.definition.comment.usm
push:
- - meta_scope: comment.line.double-slash.tome
+ - meta_scope: comment.line.double-slash.usm
- match: '\)'
pop: true
diff --git a/examples/struct.usm b/examples/struct.usm
@@ -0,0 +1,30 @@
+( blank )
+
+:dev/r fff8 ( std read port )
+:dev/w fff9 ( std write port )
+
+&point2d { x 2 y 2 }
+&point3d { x 2 y 2 z 2 }
+
+;position point2d
+;vertex point3d
+
+( TODO )
+
+|0100 @RESET
+
+ ,position:x #0002 STR2
+
+ ~position:x
+
+ #02 =position:x
+
+ #abcd =vertex:x
+
+BRK
+
+|c000 @FRAME BRK
+|d000 @ERROR BRK
+
+|FFF0 [ f2ac 35bb 2b53 ] ( palette )
+|FFFA .RESET .FRAME .ERROR
diff --git a/examples/window.usm b/examples/window.usm
@@ -3,7 +3,7 @@
:dev/r fff8 ( std read port )
:dev/w fff9 ( std write port )
-( window ) ;wx1 2 ;wy1 2 ;wx2 2 ;wy2 2
+( window ) ;wx1 2 ;wy1 2 ;wx2 2 ;wy2 2
( drawing ) ;color 1 ;x1 2 ;x2 2 ;y1 2 ;y2 2
( mouse ) ;mousex 2 ;mousey 2 ;state 1