home
readme
diff
tree
note
docs
0commit 8d62ad7566558c937bf0ec832d7d2ee71a6f9ade
1Author: lakefox <mason@lakefox.net>
2Date: Mon Apr 6 09:52:31 2026 -0600
3
4 While, range, range as
5
6diff --git a/Makefile b/Makefile
7index c9a7370..b3d0445 100755
8--- a/Makefile
9+++ b/Makefile
10@@ -57,12 +57,12 @@ GDB_FLAGS ?=
11 debug_css_units:
12 @clear
13 make run_css_unit_playground
14- gdb $(GDB_FLAGS) -ex "b 146" -ex "run" -ex "print *units@units_len" build/css_unit_playground
15+ gdb $(GDB_FLAGS) -ex "b 147" -ex "run" -ex "print *units@units_len" build/css_unit_playground
16
17 debug_unit_debug:
18 @clear
19 make run_unit_value_playground
20- gdb $(GDB_FLAGS) -ex "b 146" -ex "run" -ex "print *units@units_len" build/unit_value_playground
21+ gdb $(GDB_FLAGS) -ex "b 147" -ex "run" -ex "print *units@units_len" build/unit_value_playground
22
23
24 quiet_%: GDB_FLAGS = --batch
25diff --git a/include/grim.h b/include/grim.h
26index 7db3a5d..b14402e 100755
27--- a/include/grim.h
28+++ b/include/grim.h
29@@ -79,7 +79,7 @@ typedef enum {
30 NEAREST, UP, DOWN, TO_ZERO,
31
32 // Keyword
33- SCREEN, TOKEN, NO_SUPPORT, IMAGE, BOOL, VAR, PTR, TAG, CHAR, JUMP, FREE, REG, ARG,
34+ SCREEN, TOKEN, NO_SUPPORT, IMAGE, BOOL, VAR, PTR, TAG, CHAR, JUMP, FREE, REG, ARG, AS,
35
36 FUNC_START,
37 // General Functions
38diff --git a/maps/match.gperf b/maps/match.gperf
39index c8a69d9..d959404 100644
40--- a/maps/match.gperf
41+++ b/maps/match.gperf
42@@ -145,4 +145,5 @@ nearest, NEAREST
43 up, UP
44 down, DOWN
45 to-zero, TO_ZERO
46+as, AS
47 %%
48diff --git a/playground/css_unit.c b/playground/css_unit.c
49index 832de62..1a15211 100644
50--- a/playground/css_unit.c
51+++ b/playground/css_unit.c
52@@ -73,6 +73,8 @@ void test_get_unit(char* ustr, struct Unit* known_units, int known_units_len, in
53
54 get_unit(&units, &cap, &units_len, &vars, &vars_len, &vars_cap, &funcs, &funcs_len, &funcs_cap, &stack_len, &max_register_size, ustr);
55
56+ printf("-------------- CASE ----------------\n");
57+
58 bool error = false;
59 if (units_len != known_units_len) {
60 printf("| \n");
61@@ -139,7 +141,7 @@ int main() {
62 int stack_len = 0;
63 int max_register_size = 0;
64
65- char* ustr = "let(i 0) while((i < 90) set(i (i + 1))) print(i)";
66+ char* ustr = "let(a 0) while(range(1000000 as b) (set(a (a + b)))) print(a)";
67
68 get_unit(&units, &cap, &units_len, &vars, &vars_len, &vars_cap, &funcs, &funcs_len, &funcs_cap, &stack_len, &max_register_size, ustr);
69
70@@ -166,11 +168,11 @@ int main() {
71 );
72 test_get_unit("calc(23px * size)",
73 (struct Unit[]){{PX, 23}, {VAR, 0}, {MULT, 2}, {CALC, 1}},
74- 4, 1, 2
75+ 4, 0, 3
76 );
77 test_get_unit("(let(x 10px) set(x 30px) (let(x 50px) print(x)) print(x))",
78 (struct Unit[]){{PTR, 0}, {PX, 10}, {LET, 2}, {PTR, 0}, {PX, 30}, {SET, 2}, {PTR, 1}, {PX, 50}, {LET, 2}, {VAR, 1}, {PRINT, 1}, {GROUP, 2}, {VAR, 0}, {PRINT, 1}, {GROUP, 4}},
79- 15, 2, 4
80+ 15, 2, 14
81 );
82 test_get_unit("((let(x 10px) set(x x * 2%) print(x)) (let(y 10px) set(y y * 2) print(y)))", (struct Unit[]){
83 {PTR, 0}, {PX, 10}, {LET, 2},
84@@ -182,28 +184,28 @@ int main() {
85 {VAR, 0}, {PRINT, 1},
86 {GROUP, 3},
87 {GROUP, 2}}
88- , 23, 1, 3);
89+ , 23, 1, 22);
90 test_get_unit("(let(x :name \"john doe\" :age 27))",
91 (struct Unit[]){{PTR, 0}, {TAG, 1035}, {CHAR, 106}, {CHAR, 111}, {CHAR, 104}, {CHAR, 110}, {CHAR, 32}, {CHAR, 100}, {CHAR, 111}, {CHAR, 101}, {TAG, 606}, {NUMBER, 27}, {LET, 12}, {GROUP, 1}},
92- 14, 1, 12
93+ 14, 1, 13
94 );
95 test_get_unit("(if((style(--scheme) == dark) calc(#eeeeee == '1')))",
96 (struct Unit[]){{VAR, 0}, {CUSTOM_FUNCS, 1}, {VAR, 0}, {EQ, 2}, {GROUP, 1}, {IF, 6}, {HEX, 2.19425599e-38}, {CHAR, 49}, {EQ, 2}, {CALC, 1}, {GROUP, 1}},
97- 11, 1, 2
98+ 11, 0, 10
99 );
100
101 test_get_unit("(if((style(--scheme) == dark) calc(#eeeeee == '1') print(123)))",
102 (struct Unit[]){{VAR, 0}, {CUSTOM_FUNCS, 1}, {VAR, 0}, {EQ, 2}, {GROUP, 1}, {IF, 6}, {HEX, 2.19425599e-38}, {CHAR, 49}, {EQ, 2}, {CALC, 1}, {JUMP, 3}, {NUMBER, 123}, {PRINT, 1}, {GROUP, 3}},
103- 14, 1, 3
104+ 14, 0, 13
105 );
106
107 test_get_unit("(if((style(--scheme) == dark) calc(#eeeeee == calc(123)) print(123)))",
108 (struct Unit[]){{VAR, 0}, {CUSTOM_FUNCS, 1}, {VAR, 0}, {EQ, 2}, {GROUP, 1}, {IF, 7}, {HEX, 2.19425599e-38}, {NUMBER, 123}, {CALC, 1}, {EQ, 2}, {CALC, 1}, {JUMP, 3}, {NUMBER, 123}, {PRINT, 1}, {GROUP, 3}},
109- 15, 1, 3
110+ 15, 0, 14
111 );
112 test_get_unit("let(height 10) def(x (name age) print(name age height 1 2 3)) x(1 1)",
113 (struct Unit[]){{PTR, 0}, {NUMBER, 10}, {LET, 2}, {DEF, 11}, {REG, 0}, {REG, 1}, {VAR, 0}, {NUMBER, 1}, {NUMBER, 2}, {NUMBER, 3}, {PRINT, 6}, {JUMP, 2}, {NUMBER, 1}, {NUMBER, 1}, {CUSTOM_FUNCS+4, 2}},
114- 15, 3, 6
115+ 15, 1, 14
116 );
117
118 }
119diff --git a/playground/syntax.wr b/playground/syntax.wr
120index 1c6b2de..f18b996 100644
121--- a/playground/syntax.wr
122+++ b/playground/syntax.wr
123@@ -70,9 +70,9 @@ Context -> width -> screen -> etc
124 for(each(x) (print(.)))
125
126
127- // Elements are made and/or accessed with queryselectors
128- // if no relationship is given then it won't be inserted
129- // either way the a ref to the element is always returned
130+ -- Elements are made and/or accessed with queryselectors
131+ -- if no relationship is given then it won't be inserted
132+ -- either way the a ref to the element is always returned
133 $(body>modal (
134 :click ((e) (
135 :text ("You clicked me " x "times")
136@@ -209,7 +209,6 @@ Context -> width -> screen -> etc
137 </person>`
138 )
139
140- let(p1 x(name("John") age(12) first_or_last("first")))
141 let(p2 x("Mary" 99 "first"))
142
143 let(people p1)
144@@ -222,6 +221,15 @@ Context -> width -> screen -> etc
145 map(value ($1 + 60))
146 ))
147
148- print(uppercase(value("test")))
149+ -- Test comment
150+ -- print(uppercase(value("test")))
151+
152+ ===
153+ This is a multiline comment
154+
155+ while(range(0 10 5 as i) (
156+ print(at(x i))
157+ ))
158+ ===
159
160 )
161diff --git a/playground/unit_value.c b/playground/unit_value.c
162index 067b7eb..2511be7 100644
163--- a/playground/unit_value.c
164+++ b/playground/unit_value.c
165@@ -145,7 +145,7 @@ int main() {
166 int stack_len = 0;
167 int max_register_size = 0;
168
169- char* ustr = "let(i 0) while(true (print(i < 10, i) set(i (i + 1))))";
170+ char* ustr = "let(a 0) while(range(1000000) (set(a (a + 1)))) a";
171
172 get_unit(&units, &cap, &units_len, &vars, &vars_len, &vars_cap, &funcs, &funcs_len, &funcs_cap, &stack_len, &max_register_size, ustr);
173
174@@ -177,7 +177,7 @@ int main() {
175
176
177 if (true) {
178- //benchmark_unit_value(ustr);
179+ // benchmark_unit_value(ustr);
180
181 test_unit_value("1 + 1", 2);
182 test_unit_value("pow(10 2)", 100);
183@@ -199,6 +199,8 @@ int main() {
184 test_unit_value("let(height 10) def(x (age name) (age + height * name)) x(4 x(5 x(6 x(7 8))))", 456960);
185 test_unit_value("let(height 10) def(x () (21 + 3)) x()", 24);
186 test_unit_value("let(height 10) def(x (name age) (age + height * name)) x(4 x(5 x(6 x(7 8))))", 16560);
187+ test_unit_value("let(a 0) while(range(1000000 as b) (set(a (b)))) a", 1000000);
188+ test_unit_value("let(a 0) while(range(1000000) (set(a (a + 1)))) a", 1000000);
189
190 // cases for all rel units and every function
191 }
192diff --git a/src/grim.c b/src/grim.c
193index 67b29a4..02823fe 100755
194--- a/src/grim.c
195+++ b/src/grim.c
196@@ -809,23 +809,29 @@ float unit_value(struct Slot stack[], int register_size, struct Unit* units, int
197 }
198 case PRINT: {
199 printf("> ");
200+ bool last_char = false;
201 for (int j = idx; j < idx+(int)unit.value; j++) {
202 if (registers[j].type == CHAR) {
203 printf("%c", (char)registers[j].value);
204- } else if (registers[j].type == BOOL) {
205- if (registers[j].value == 0) {
206- printf("false ");
207+ last_char = true;
208+ } else {
209+ printf(" ");
210+ last_char = false;
211+ if (registers[j].type == BOOL) {
212+ if (registers[j].value == 0) {
213+ printf("false ");
214+ } else {
215+ printf("true ");
216+ }
217+ } else if (registers[j].type == HEX) {
218+ uint32_t u32;
219+ char hex[11];
220+ memcpy(&u32, ®isters[j].value, sizeof(u32));
221+ sprintf(hex, "0x%08x", u32);
222+ printf("%s ", hex);
223 } else {
224- printf("true ");
225+ printf("%f ", registers[j].value);
226 }
227- } else if (registers[j].type == HEX) {
228- uint32_t u32;
229- char hex[11];
230- memcpy(&u32, ®isters[j].value, sizeof(u32));
231- sprintf(hex, "0x%08x", u32);
232- printf("%s ", hex);
233- } else {
234- printf("%f ", registers[j].value);
235 }
236 }
237 printf("\n");
238@@ -956,6 +962,19 @@ float unit_value(struct Slot stack[], int register_size, struct Unit* units, int
239 register_len = idx + 1;
240 break;
241 }
242+ case RANGE: {
243+ if (units[i-3].value < units[i-2].value) {
244+ units[i-3].value += units[i-1].value;
245+ registers[idx].type = BOOL;
246+ registers[idx].value = 1;
247+ } else {
248+ registers[idx].type = BOOL;
249+ registers[idx].value = 0;
250+ units[i-3].value = units[i-4].value;
251+ }
252+ register_len = idx+1;
253+ break;
254+ }
255 case ADD:
256 registers[idx].type = NUMBER;
257 registers[idx].value += registers[idx+1].value;
258diff --git a/src/parser.c b/src/parser.c
259index 3560c76..14bf694 100755
260--- a/src/parser.c
261+++ b/src/parser.c
262@@ -187,7 +187,7 @@ void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* v
263 }
264
265 if (i+1 < size) {
266- if (v == '/' && value[i+1] == '/') {
267+ if (v == '-' && value[i+1] == '-') {
268 inlineComment = true;
269 continue;
270 }
271@@ -199,16 +199,18 @@ void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* v
272 continue;
273 }
274
275- if (v == '/' && value[i+1] == '*') {
276- multilineComment = true;
277- }
278+ if (i + 2 < size) {
279+ if (v == '=' && value[i+1] == '=' && value[i+2] == '=') {
280+ multilineComment = true;
281+ }
282
283- if (multilineComment) {
284- if (v == '*' && value[i+1] == '/') {
285- i++;
286- multilineComment = false;
287+ if (multilineComment) {
288+ if (v == '=' && value[i+1] == '=' && value[i+2] == '=') {
289+ i++;
290+ multilineComment = false;
291+ }
292+ continue;
293 }
294- continue;
295 }
296 }
297
298@@ -353,7 +355,7 @@ void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* v
299 } else if (child_count == 3) {
300 // if else
301 // Move back 1 and add a jump at the end of the conditional logic
302- if ((unsigned long)(*cap) < (indexes[2] + 23) * sizeof(struct Unit)) {
303+ if ((unsigned long)(*cap) < (indexes[2]) * sizeof(struct Unit)) {
304 *units = realloc(*units, sizeof(struct Unit) * (*cap * 2));
305 }
306
307@@ -393,13 +395,97 @@ void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* v
308 *units = realloc(*units, sizeof(struct Unit) * (*cap * 2));
309 }
310
311- memmove((*units) + indexes[0], (*units) + indexes[0] - 1, (*units_len - indexes[0]) * sizeof(struct Unit));
312- (*units)[indexes[0]].type = IF;
313- (*units)[indexes[0]].value = (*units_len-indexes[0]);
314- (*units)[*units_len].type = JUMP;
315- (*units)[*units_len].value = before_count-1;
316- *units_len += 1;
317+ if ((*units)[indexes[0]-1].type == RANGE && (*units)[indexes[0]-2].type == REG) {
318+ // Need to remove the REG and replace all of the REG REFS with the correct value
319+ struct Unit reg = (*units)[indexes[0]-2];
320+ memmove((*units) + indexes[0] - 2, (*units) + indexes[0] - 1, (*units_len - indexes[0]) * sizeof(struct Unit));
321+ memmove((*units) + indexes[0], (*units) + indexes[0] - 1, (*units_len - indexes[0]) * sizeof(struct Unit));
322+ (*units)[indexes[0] - 2].value = 4; // We just wrote over the REG so update RANGE to 4
323
324+ (*units)[indexes[0] - 1].type = IF;
325+ (*units)[indexes[0] - 1].value = (*units_len-indexes[0]);
326+ (*units)[*units_len-1].type = JUMP;
327+ if (before_count > 0) {
328+ (*units)[*units_len-1].value = before_count; // +1 because the RANGE has a reset value at pos 0
329+ } else {
330+ (*units)[*units_len-1].value = 1;
331+ }
332+
333+ // Replace all REG with the correct position
334+ for (int j = indexes[0]; j < *units_len; j++) {
335+ if ((*units)[j].type == REG && (*units)[j].value == reg.value) {
336+ (*units)[j].value = before_count+1; // the second value in the chunk
337+ }
338+ }
339+ } else {
340+ memmove((*units) + indexes[0], (*units) + indexes[0] - 1, (*units_len - indexes[0]) * sizeof(struct Unit));
341+
342+ (*units)[indexes[0]].type = IF;
343+ (*units)[indexes[0]].value = (*units_len-indexes[0]);
344+ (*units)[*units_len].type = JUMP;
345+ if (before_count > 0) {
346+ (*units)[*units_len].value = before_count-1;
347+ } else {
348+ (*units)[*units_len].value = 0;
349+ }
350+ *units_len += 1;
351+ }
352+ } else if (placeholder.type == RANGE) {
353+ if (sizeof(units) / sizeof(struct Unit) < ((*units_len)+3) * sizeof(struct Unit)) {
354+ *units = realloc(*units, sizeof(struct Unit) * (*cap * 2));
355+ }
356+ bool has_as = false;
357+ int as_pos = 0;
358+ struct Unit as;
359+ for (int j = before_count; j < *units_len; j++) {
360+ if ((*units)[j].type == AS) {
361+ has_as = true;
362+ as_pos = j;
363+ as = (*units)[j + 1];
364+ break;
365+ }
366+ }
367+
368+ if (!has_as) {
369+ as_pos = placeholder.value;
370+ }
371+
372+ int count = as_pos-before_count;
373+ int start = (*units_len - 1)-placeholder.value; // -1 because *units_len stores next postition
374+
375+ struct Unit range = (*units)[*units_len-1];
376+ struct Unit start_value = (*units)[before_count];
377+ struct Unit end_value = (*units)[before_count + 1];
378+ struct Unit inc_value = (*units)[before_count + 2];
379+
380+ if (count < 2) {
381+ // Add a starting value of 0
382+ end_value = start_value;
383+ start_value.type = NUMBER;
384+ start_value.value = 0;
385+ *units_len += 1;
386+ }
387+ if (count < 3) {
388+ // Add a step of 1
389+ inc_value.type = NUMBER;
390+ inc_value.value = 1;
391+ *units_len += 1;
392+ }
393+
394+ (*units)[before_count] = start_value;
395+ (*units)[before_count + 1] = start_value;
396+ (*units)[before_count + 2] = end_value;
397+ (*units)[before_count + 3] = inc_value;
398+
399+ if (has_as) {
400+ (*units)[before_count + 4] = as;
401+ (*units)[before_count + 5] = range;
402+ (*units)[before_count + 5].value = 5;
403+ } else {
404+ *units_len += 1;
405+ (*units)[before_count + 4] = range;
406+ (*units)[before_count + 4].value = 4;
407+ }
408 }
409
410 if (hasOP) {
411@@ -533,11 +619,12 @@ void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* v
412 if (!var_found) {
413 unit.type = REG;
414 int tag_value = 0;
415- for (int j = 1; j < buffer_len; j++) {
416- tag_value += buffer[j]*j;
417+ for (int j = 0; j < buffer_len; j++) {
418+ tag_value += buffer[j]*(j+1);
419 }
420
421- unit.value = tag_value; }
422+ unit.value = tag_value;
423+ }
424 }
425 }
426 } else {