mirror of
https://git.sr.ht/~rabbits/uxn
synced 2024-11-30 01:33:01 +00:00
Progress on macros
This commit is contained in:
parent
9fc632bc28
commit
fd71d97dfc
5 changed files with 114 additions and 25 deletions
|
@ -29,6 +29,7 @@ evaluxn(u, u->vframe); /* Each frame
|
||||||
- `@label`, assign the current address to a label.
|
- `@label`, assign the current address to a label.
|
||||||
- `;variable 2`, assign an address to a label automatically.
|
- `;variable 2`, assign an address to a label automatically.
|
||||||
- `:const 1a2b`, assign an address to a label manually.
|
- `:const 1a2b`, assign an address to a label manually.
|
||||||
|
- `¯o { x 2 y 2 }`, define a macro named `macro`.
|
||||||
|
|
||||||
### Write
|
### Write
|
||||||
|
|
||||||
|
|
84
assembler.c
84
assembler.c
|
@ -21,14 +21,23 @@ typedef struct {
|
||||||
Uint8 data[65536];
|
Uint8 data[65536];
|
||||||
} Program;
|
} Program;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char name[64], keys[16][64];
|
||||||
|
Uint8 len, lens[16];
|
||||||
|
} Macro;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Uint8 len;
|
Uint8 len;
|
||||||
Uint16 addr;
|
Uint16 addr;
|
||||||
char name[64];
|
char name[64];
|
||||||
} Label;
|
} Label;
|
||||||
|
|
||||||
|
int macroslen;
|
||||||
|
Macro macros[256];
|
||||||
|
|
||||||
int labelslen;
|
int labelslen;
|
||||||
Label labels[256];
|
Label labels[256];
|
||||||
|
|
||||||
Program p;
|
Program p;
|
||||||
|
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
@ -69,6 +78,16 @@ pushshort(Uint16 s, int lit)
|
||||||
pushbyte(s & 0xff, 0);
|
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 *
|
Label *
|
||||||
findlabel(char *s)
|
findlabel(char *s)
|
||||||
{
|
{
|
||||||
|
@ -108,6 +127,36 @@ error(char *name, char *id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
int
|
||||||
makelabel(char *name, Uint16 addr, Uint8 len)
|
makelabel(char *name, Uint16 addr, Uint8 len)
|
||||||
{
|
{
|
||||||
|
@ -140,33 +189,19 @@ makevariable(char *id, Uint16 *addr, FILE *f)
|
||||||
char wv[64];
|
char wv[64];
|
||||||
Uint8 origin;
|
Uint8 origin;
|
||||||
fscanf(f, "%s", wv);
|
fscanf(f, "%s", wv);
|
||||||
if(!sihx(wv))
|
|
||||||
return error("Variable value is invalid", wv);
|
|
||||||
origin = *addr;
|
origin = *addr;
|
||||||
*addr += shex(wv);
|
*addr += shex(wv);
|
||||||
return makelabel(id, origin, shex(wv));
|
return makelabel(id, origin, shex(wv));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
skipcomment(char *w, int *cap)
|
skipblock(char *w, int *cap, char a, char b)
|
||||||
{
|
{
|
||||||
if(w[0] == ')') {
|
if(w[0] == b) {
|
||||||
*cap = 0;
|
*cap = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if(w[0] == '(') *cap = 1;
|
if(w[0] == a) *cap = 1;
|
||||||
if(*cap) return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
skipbinary(char *w, int *cap)
|
|
||||||
{
|
|
||||||
if(w[0] == ']') {
|
|
||||||
*cap = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if(w[0] == '[') *cap = 1;
|
|
||||||
if(*cap) return 1;
|
if(*cap) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -213,9 +248,9 @@ pass1(FILE *f)
|
||||||
Uint16 addr = 0;
|
Uint16 addr = 0;
|
||||||
char w[64];
|
char w[64];
|
||||||
while(fscanf(f, "%s", w) == 1) {
|
while(fscanf(f, "%s", w) == 1) {
|
||||||
if(skipcomment(w, &ccmnt)) continue;
|
if(skipblock(w, &ccmnt, '(', ')')) continue;
|
||||||
if(skipstring(w, &cstrg, &addr)) continue;
|
if(skipstring(w, &cstrg, &addr)) continue;
|
||||||
if(skipbinary(w, &cbits))
|
if(skipblock(w, &cbits, '[', ']'))
|
||||||
addr += w[0] != '[' && w[0] != ']' ? 2 : 0;
|
addr += w[0] != '[' && w[0] != ']' ? 2 : 0;
|
||||||
else if(w[0] == '@') {
|
else if(w[0] == '@') {
|
||||||
if(!makelabel(w + 1, addr, 0))
|
if(!makelabel(w + 1, addr, 0))
|
||||||
|
@ -223,6 +258,9 @@ pass1(FILE *f)
|
||||||
} else if(w[0] == ';') {
|
} else if(w[0] == ';') {
|
||||||
if(!makevariable(w + 1, &addr, f))
|
if(!makevariable(w + 1, &addr, f))
|
||||||
return error("Pass1 failed", w);
|
return error("Pass1 failed", w);
|
||||||
|
} else if(w[0] == '&') {
|
||||||
|
if(!makemacro(w + 1, f))
|
||||||
|
return error("Pass1 failed", w);
|
||||||
} else if(w[0] == ':') {
|
} else if(w[0] == ':') {
|
||||||
if(!makeconst(w + 1, f))
|
if(!makeconst(w + 1, f))
|
||||||
return error("Pass1 failed", w);
|
return error("Pass1 failed", w);
|
||||||
|
@ -249,16 +287,18 @@ pass1(FILE *f)
|
||||||
int
|
int
|
||||||
pass2(FILE *f)
|
pass2(FILE *f)
|
||||||
{
|
{
|
||||||
int ccmnt = 0, cstrg = 0, cbits = 0;
|
int ccmnt = 0, cstrg = 0, cbits = 0, cmacro = 0;
|
||||||
char w[64];
|
char w[64];
|
||||||
while(fscanf(f, "%s", w) == 1) {
|
while(fscanf(f, "%s", w) == 1) {
|
||||||
Uint8 op = 0;
|
Uint8 op = 0;
|
||||||
Label *l;
|
Label *l;
|
||||||
if(w[0] == '@') continue;
|
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;
|
if(capturestring(w, &cstrg)) continue;
|
||||||
/* clang-format off */
|
/* 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(w[0] == '|') p.ptr = shex(w + 1);
|
||||||
else if((op = findopcode(w)) || scmp(w, "BRK")) pushbyte(op, 0);
|
else if((op = findopcode(w)) || scmp(w, "BRK")) pushbyte(op, 0);
|
||||||
else if(w[0] == ':') fscanf(f, "%s", w);
|
else if(w[0] == ':') fscanf(f, "%s", w);
|
||||||
|
|
|
@ -21,12 +21,21 @@ contexts:
|
||||||
- match: '\|(\S+)\s?'
|
- match: '\|(\S+)\s?'
|
||||||
scope: punctuation.definition
|
scope: punctuation.definition
|
||||||
pop: true
|
pop: true
|
||||||
|
- match: '\_(\S+)\s?'
|
||||||
|
scope: punctuation.definition
|
||||||
|
pop: true
|
||||||
- match: '\+(\S+)\s?'
|
- match: '\+(\S+)\s?'
|
||||||
scope: keyword.control
|
scope: keyword.control
|
||||||
pop: true
|
pop: true
|
||||||
- match: '\-(\S+)\s?'
|
- match: '\-(\S+)\s?'
|
||||||
scope: keyword.control
|
scope: keyword.control
|
||||||
pop: true
|
pop: true
|
||||||
|
- match: '\~(\S+)\s?'
|
||||||
|
scope: keyword.control
|
||||||
|
pop: true
|
||||||
|
- match: '\=(\S+)\s?'
|
||||||
|
scope: keyword.control
|
||||||
|
pop: true
|
||||||
|
|
||||||
strings:
|
strings:
|
||||||
- match: '\:(\S+)\s?'
|
- match: '\:(\S+)\s?'
|
||||||
|
@ -38,6 +47,9 @@ contexts:
|
||||||
- match: '\@(\S+)\s?'
|
- match: '\@(\S+)\s?'
|
||||||
scope: string.control
|
scope: string.control
|
||||||
pop: true
|
pop: true
|
||||||
|
- match: '\&(\S+)\s?'
|
||||||
|
scope: string.control
|
||||||
|
pop: true
|
||||||
- match: '\,(\S+)\s?'
|
- match: '\,(\S+)\s?'
|
||||||
scope: keyword.control
|
scope: keyword.control
|
||||||
pop: true
|
pop: true
|
||||||
|
@ -50,11 +62,17 @@ contexts:
|
||||||
- match: '\"(\S+)\s?'
|
- match: '\"(\S+)\s?'
|
||||||
scope: keyword.control
|
scope: keyword.control
|
||||||
pop: true
|
pop: true
|
||||||
|
- match: '\['
|
||||||
|
scope: punctuation.definition.keyword.usm
|
||||||
|
push:
|
||||||
|
- meta_scope: keyword.line.double-slash.usm
|
||||||
|
- match: '\]'
|
||||||
|
pop: true
|
||||||
|
|
||||||
comments:
|
comments:
|
||||||
- match: '\('
|
- match: '\('
|
||||||
scope: punctuation.definition.comment.tome
|
scope: punctuation.definition.comment.usm
|
||||||
push:
|
push:
|
||||||
- meta_scope: comment.line.double-slash.tome
|
- meta_scope: comment.line.double-slash.usm
|
||||||
- match: '\)'
|
- match: '\)'
|
||||||
pop: true
|
pop: true
|
||||||
|
|
30
examples/struct.usm
Normal file
30
examples/struct.usm
Normal file
|
@ -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
|
Loading…
Reference in a new issue