... | ... |
@@ -29,6 +29,7 @@ evaluxn(u, u->vframe); /* Each frame |
29 | 29 |
- `@label`, assign the current address to a label. |
30 | 30 |
- `;variable 2`, assign an address to a label automatically. |
31 | 31 |
- `:const 1a2b`, assign an address to a label manually. |
32 |
+- `¯o { x 2 y 2 }`, define a macro named `macro`. |
|
32 | 33 |
|
33 | 34 |
### Write |
34 | 35 |
|
... | ... |
@@ -21,14 +21,23 @@ typedef struct { |
21 | 21 |
Uint8 data[65536]; |
22 | 22 |
} Program; |
23 | 23 |
|
24 |
+typedef struct { |
|
25 |
+ char name[64], keys[16][64]; |
|
26 |
+ Uint8 len, lens[16]; |
|
27 |
+} Macro; |
|
28 |
+ |
|
24 | 29 |
typedef struct { |
25 | 30 |
Uint8 len; |
26 | 31 |
Uint16 addr; |
27 | 32 |
char name[64]; |
28 | 33 |
} Label; |
29 | 34 |
|
35 |
+int macroslen; |
|
36 |
+Macro macros[256]; |
|
37 |
+ |
|
30 | 38 |
int labelslen; |
31 | 39 |
Label labels[256]; |
40 |
+ |
|
32 | 41 |
Program p; |
33 | 42 |
|
34 | 43 |
/* clang-format off */ |
... | ... |
@@ -69,6 +78,16 @@ pushshort(Uint16 s, int lit) |
69 | 78 |
pushbyte(s & 0xff, 0); |
70 | 79 |
} |
71 | 80 |
|
81 |
+Macro * |
|
82 |
+findmacro(char *s) |
|
83 |
+{ |
|
84 |
+ int i; |
|
85 |
+ for(i = 0; i < macroslen; ++i) |
|
86 |
+ if(scmp(macros[i].name, s)) |
|
87 |
+ return ¯os[i]; |
|
88 |
+ return NULL; |
|
89 |
+} |
|
90 |
+ |
|
72 | 91 |
Label * |
73 | 92 |
findlabel(char *s) |
74 | 93 |
{ |
... | ... |
@@ -108,6 +127,36 @@ error(char *name, char *id) |
108 | 127 |
return 0; |
109 | 128 |
} |
110 | 129 |
|
130 |
+int |
|
131 |
+makemacro(char *name, FILE *f) |
|
132 |
+{ |
|
133 |
+ Uint8 mode = 0; |
|
134 |
+ Macro *m; |
|
135 |
+ char wv[64]; |
|
136 |
+ if(findmacro(name)) |
|
137 |
+ return error("Macro duplicate", name); |
|
138 |
+ if(sihx(name)) |
|
139 |
+ return error("Macro name is hex number", name); |
|
140 |
+ if(findopcode(name)) |
|
141 |
+ return error("Macro name is invalid", name); |
|
142 |
+ m = ¯os[macroslen++]; |
|
143 |
+ while(fscanf(f, "%s", wv)) { |
|
144 |
+ if(wv[0] == '{') |
|
145 |
+ continue; |
|
146 |
+ if(wv[0] == '}') |
|
147 |
+ break; |
|
148 |
+ if(mode == 0) |
|
149 |
+ scpy(wv, m->keys[m->len], 64); |
|
150 |
+ else { |
|
151 |
+ m->lens[m->len] = shex(wv); |
|
152 |
+ m->len++; |
|
153 |
+ } |
|
154 |
+ mode = !mode; |
|
155 |
+ } |
|
156 |
+ printf("New macro: %s[%d items]\n", name, m->len); |
|
157 |
+ return 1; |
|
158 |
+} |
|
159 |
+ |
|
111 | 160 |
int |
112 | 161 |
makelabel(char *name, Uint16 addr, Uint8 len) |
113 | 162 |
{ |
... | ... |
@@ -140,33 +189,19 @@ makevariable(char *id, Uint16 *addr, FILE *f) |
140 | 189 |
char wv[64]; |
141 | 190 |
Uint8 origin; |
142 | 191 |
fscanf(f, "%s", wv); |
143 |
- if(!sihx(wv)) |
|
144 |
- return error("Variable value is invalid", wv); |
|
145 | 192 |
origin = *addr; |
146 | 193 |
*addr += shex(wv); |
147 | 194 |
return makelabel(id, origin, shex(wv)); |
148 | 195 |
} |
149 | 196 |
|
150 | 197 |
int |
151 |
-skipcomment(char *w, int *cap) |
|
152 |
-{ |
|
153 |
- if(w[0] == ')') { |
|
154 |
- *cap = 0; |
|
155 |
- return 1; |
|
156 |
- } |
|
157 |
- if(w[0] == '(') *cap = 1; |
|
158 |
- if(*cap) return 1; |
|
159 |
- return 0; |
|
160 |
-} |
|
161 |
- |
|
162 |
-int |
|
163 |
-skipbinary(char *w, int *cap) |
|
198 |
+skipblock(char *w, int *cap, char a, char b) |
|
164 | 199 |
{ |
165 |
- if(w[0] == ']') { |
|
200 |
+ if(w[0] == b) { |
|
166 | 201 |
*cap = 0; |
167 | 202 |
return 1; |
168 | 203 |
} |
169 |
- if(w[0] == '[') *cap = 1; |
|
204 |
+ if(w[0] == a) *cap = 1; |
|
170 | 205 |
if(*cap) return 1; |
171 | 206 |
return 0; |
172 | 207 |
} |
... | ... |
@@ -213,9 +248,9 @@ pass1(FILE *f) |
213 | 248 |
Uint16 addr = 0; |
214 | 249 |
char w[64]; |
215 | 250 |
while(fscanf(f, "%s", w) == 1) { |
216 |
- if(skipcomment(w, &ccmnt)) continue; |
|
251 |
+ if(skipblock(w, &ccmnt, '(', ')')) continue; |
|
217 | 252 |
if(skipstring(w, &cstrg, &addr)) continue; |
218 |
- if(skipbinary(w, &cbits)) |
|
253 |
+ if(skipblock(w, &cbits, '[', ']')) |
|
219 | 254 |
addr += w[0] != '[' && w[0] != ']' ? 2 : 0; |
220 | 255 |
else if(w[0] == '@') { |
221 | 256 |
if(!makelabel(w + 1, addr, 0)) |
... | ... |
@@ -223,6 +258,9 @@ pass1(FILE *f) |
223 | 258 |
} else if(w[0] == ';') { |
224 | 259 |
if(!makevariable(w + 1, &addr, f)) |
225 | 260 |
return error("Pass1 failed", w); |
261 |
+ } else if(w[0] == '&') { |
|
262 |
+ if(!makemacro(w + 1, f)) |
|
263 |
+ return error("Pass1 failed", w); |
|
226 | 264 |
} else if(w[0] == ':') { |
227 | 265 |
if(!makeconst(w + 1, f)) |
228 | 266 |
return error("Pass1 failed", w); |
... | ... |
@@ -249,16 +287,18 @@ pass1(FILE *f) |
249 | 287 |
int |
250 | 288 |
pass2(FILE *f) |
251 | 289 |
{ |
252 |
- int ccmnt = 0, cstrg = 0, cbits = 0; |
|
290 |
+ int ccmnt = 0, cstrg = 0, cbits = 0, cmacro = 0; |
|
253 | 291 |
char w[64]; |
254 | 292 |
while(fscanf(f, "%s", w) == 1) { |
255 | 293 |
Uint8 op = 0; |
256 | 294 |
Label *l; |
257 | 295 |
if(w[0] == '@') continue; |
258 |
- if(skipcomment(w, &ccmnt)) continue; |
|
296 |
+ if(w[0] == '&') continue; |
|
297 |
+ if(skipblock(w, &ccmnt, '(', ')')) continue; |
|
298 |
+ if(skipblock(w, &cmacro, '{', '}')) continue; |
|
259 | 299 |
if(capturestring(w, &cstrg)) continue; |
260 | 300 |
/* clang-format off */ |
261 |
- if(skipbinary(w, &cbits)) { if(w[0] != '[' && w[0] != ']') { pushshort(shex(w), 0); } } |
|
301 |
+ if(skipblock(w, &cbits, '[', ']')) { if(w[0] != '[' && w[0] != ']') { pushshort(shex(w), 0); } } |
|
262 | 302 |
else if(w[0] == '|') p.ptr = shex(w + 1); |
263 | 303 |
else if((op = findopcode(w)) || scmp(w, "BRK")) pushbyte(op, 0); |
264 | 304 |
else if(w[0] == ':') fscanf(f, "%s", w); |
... | ... |
@@ -21,12 +21,21 @@ contexts: |
21 | 21 |
- match: '\|(\S+)\s?' |
22 | 22 |
scope: punctuation.definition |
23 | 23 |
pop: true |
24 |
+ - match: '\_(\S+)\s?' |
|
25 |
+ scope: punctuation.definition |
|
26 |
+ pop: true |
|
24 | 27 |
- match: '\+(\S+)\s?' |
25 | 28 |
scope: keyword.control |
26 | 29 |
pop: true |
27 | 30 |
- match: '\-(\S+)\s?' |
28 | 31 |
scope: keyword.control |
29 | 32 |
pop: true |
33 |
+ - match: '\~(\S+)\s?' |
|
34 |
+ scope: keyword.control |
|
35 |
+ pop: true |
|
36 |
+ - match: '\=(\S+)\s?' |
|
37 |
+ scope: keyword.control |
|
38 |
+ pop: true |
|
30 | 39 |
|
31 | 40 |
strings: |
32 | 41 |
- match: '\:(\S+)\s?' |
... | ... |
@@ -38,6 +47,9 @@ contexts: |
38 | 47 |
- match: '\@(\S+)\s?' |
39 | 48 |
scope: string.control |
40 | 49 |
pop: true |
50 |
+ - match: '\&(\S+)\s?' |
|
51 |
+ scope: string.control |
|
52 |
+ pop: true |
|
41 | 53 |
- match: '\,(\S+)\s?' |
42 | 54 |
scope: keyword.control |
43 | 55 |
pop: true |
... | ... |
@@ -50,11 +62,17 @@ contexts: |
50 | 62 |
- match: '\"(\S+)\s?' |
51 | 63 |
scope: keyword.control |
52 | 64 |
pop: true |
65 |
+ - match: '\[' |
|
66 |
+ scope: punctuation.definition.keyword.usm |
|
67 |
+ push: |
|
68 |
+ - meta_scope: keyword.line.double-slash.usm |
|
69 |
+ - match: '\]' |
|
70 |
+ pop: true |
|
53 | 71 |
|
54 | 72 |
comments: |
55 | 73 |
- match: '\(' |
56 |
- scope: punctuation.definition.comment.tome |
|
74 |
+ scope: punctuation.definition.comment.usm |
|
57 | 75 |
push: |
58 |
- - meta_scope: comment.line.double-slash.tome |
|
76 |
+ - meta_scope: comment.line.double-slash.usm |
|
59 | 77 |
- match: '\)' |
60 | 78 |
pop: true |
61 | 79 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,30 @@ |
1 |
+( blank ) |
|
2 |
+ |
|
3 |
+:dev/r fff8 ( std read port ) |
|
4 |
+:dev/w fff9 ( std write port ) |
|
5 |
+ |
|
6 |
+&point2d { x 2 y 2 } |
|
7 |
+&point3d { x 2 y 2 z 2 } |
|
8 |
+ |
|
9 |
+;position point2d |
|
10 |
+;vertex point3d |
|
11 |
+ |
|
12 |
+( TODO ) |
|
13 |
+ |
|
14 |
+|0100 @RESET |
|
15 |
+ |
|
16 |
+ ,position:x #0002 STR2 |
|
17 |
+ |
|
18 |
+ ~position:x |
|
19 |
+ |
|
20 |
+ #02 =position:x |
|
21 |
+ |
|
22 |
+ #abcd =vertex:x |
|
23 |
+ |
|
24 |
+BRK |
|
25 |
+ |
|
26 |
+|c000 @FRAME BRK |
|
27 |
+|d000 @ERROR BRK |
|
28 |
+ |
|
29 |
+|FFF0 [ f2ac 35bb 2b53 ] ( palette ) |
|
30 |
+|FFFA .RESET .FRAME .ERROR |