From fd71d97dfccec52024c5bf533504245e29d1fce1 Mon Sep 17 00:00:00 2001 From: neauoire Date: Mon, 22 Feb 2021 22:15:02 -0800 Subject: [PATCH] Progress on macros --- README.md | 1 + assembler.c | 84 +++++++++++++++++++++++++++++++----------- etc/usm.sublime-syntax | 22 ++++++++++- examples/struct.usm | 30 +++++++++++++++ examples/window.usm | 2 +- 5 files changed, 114 insertions(+), 25 deletions(-) create mode 100644 examples/struct.usm diff --git a/README.md b/README.md index 5ae3f97..92712ca 100644 --- 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 index 140a941..07764ef 100644 --- a/assembler.c +++ b/assembler.c @@ -21,14 +21,23 @@ typedef struct { Uint8 data[65536]; } 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) { @@ -108,6 +127,36 @@ error(char *name, char *id) 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 makelabel(char *name, Uint16 addr, Uint8 len) { @@ -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) +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(*cap) return 1; - return 0; -} - -int -skipbinary(char *w, int *cap) -{ - if(w[0] == ']') { - *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 index 3c288b8..9d47c6d 100644 --- 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 new file mode 100644 index 0000000..f802c53 --- /dev/null +++ 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 index 25f3d2a..665ea1d 100644 --- 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