home
readme
diff
tree
note
docs
0commit c2a132346b4c1ede1e3e72f94eaf3f1b60626956
1Author: lakefox <mason@lakefox.net>
2Date: Sat Mar 7 11:31:34 2026 -0700
3
4 Save
5
6diff --git a/include/grim.h b/include/grim.h
7index 1377ea8..c5406ec 100755
8--- a/include/grim.h
9+++ b/include/grim.h
10@@ -79,7 +79,7 @@ typedef enum {
11 NEAREST, UP, DOWN, TO_ZERO,
12
13 // Keyword
14- SCREEN, TOKEN, NO_SUPPORT, IMAGE, STRING, BOOL, VAR, NONOP, ELSE, TAG, CHAR,
15+ SCREEN, TOKEN, NO_SUPPORT, IMAGE, STRING, BOOL, VAR, NONOP, ELSE, TAG, CHAR, JUMP,
16
17 FUNC_START,
18 // General Functions
19diff --git a/playground/css_unit.c b/playground/css_unit.c
20index cb819b1..7902943 100644
21--- a/playground/css_unit.c
22+++ b/playground/css_unit.c
23@@ -106,7 +106,7 @@ int main() {
24 int stack_len = 0;
25 int max_register_size = 0;
26
27- char* ustr = "(let(x 10px) set(x 30px) (let(x 50px) print(x)) print(x))";
28+ char* ustr = "(if(style(--scheme) == dark #eeeeee))";
29
30 get_unit(&units, &cap, &units_len, &vars, &vars_len, &vars_cap, &stack_len, &max_register_size, ustr);
31
32@@ -123,29 +123,17 @@ int main() {
33 test_get_unit("calc(23px * size)", (struct Unit[]){{PX, 23}, {VAR, -1}, {MULT, 2}, {CALC, 1}}, 4, 0, 3);
34 test_get_unit("(let(x 10px) set(x 30px) (let(x 50px) print(x)) print(x))", (struct Unit[]){{VAR, 0}, {PX, 10}, {LET, 2}, {VAR, 0}, {PX, 30}, {SET, 2}, {VAR, 1}, {PX, 50}, {LET, 2}, {VAR, 1}, {PRINT, 1}, {GROUP, 2}, {VAR, 0}, {PRINT, 1}, {GROUP, 4}}, 15, 2, 14);
35 // test_get_unit("(min(x 10px) set(x 30px) (min(x 50px) print(x)) print(x))", (struct Unit[]){{VAR, -1}, {PX, 10}, {MIN, 2}, {VAR, -1}, {PX, 30}, {SET, 2}, {VAR, -1}, {PX, 50}, {MIN, 2}, {VAR, -1}, {PRINT, 1}, {GROUP, 2}, {VAR, -1}, {PRINT, 1}, {GROUP, 4}}, 15, 0, 14);
36-
37-
38-
39-
40-
41-
42 test_get_unit("((let(x 10px) set(x x * 2%) print(x)) (let(y 10px) set(y y * 2) print(y)))", (struct Unit[]){
43- {VAR, 0}, {PX, 10}, {LET, 2},
44- {VAR, 0}, {VAR, 0}, {PERCENT, 2}, {MULT, 2}, {SET, 2},
45- {VAR, 0}, {PRINT, 1},
46- {GROUP, 3},
47- { VAR, 0}, {PX, 10}, {LET, 2},
48- {VAR, 0}, {VAR, 0}, {NUMBER, 2}, {MULT, 2}, {SET, 2},
49- {VAR, 0}, {PRINT, 1},
50- {GROUP, 3},
51- {GROUP, 2}}
52- , 23, 1, 22);
53-
54-
55-
56-
57-
58-
59+ {VAR, 0}, {PX, 10}, {LET, 2},
60+ {VAR, 0}, {VAR, 0}, {PERCENT, 2}, {MULT, 2}, {SET, 2},
61+ {VAR, 0}, {PRINT, 1},
62+ {GROUP, 3},
63+ { VAR, 0}, {PX, 10}, {LET, 2},
64+ {VAR, 0}, {VAR, 0}, {NUMBER, 2}, {MULT, 2}, {SET, 2},
65+ {VAR, 0}, {PRINT, 1},
66+ {GROUP, 3},
67+ {GROUP, 2}}
68+ , 23, 1, 22);
69 test_get_unit("(let(x :name \"john doe\" :age 27))", (struct Unit[]){{VAR, 0}, {TAG, 1035}, {STRING, 8}, {CHAR, 106}, {CHAR, 111}, {CHAR, 104}, {CHAR, 110}, {CHAR, 32}, {CHAR, 100}, {CHAR, 111}, {CHAR, 101}, {TAG, 606}, {NUMBER, 27}, {LET, 13}, {GROUP, 1}}, 15, 1, 14);
70 }
71 }
72diff --git a/playground/syntax.wr b/playground/syntax.wr
73index 0e75392..7fd64d2 100644
74--- a/playground/syntax.wr
75+++ b/playground/syntax.wr
76@@ -115,6 +115,45 @@ Context -> width -> screen -> etc
77 map(at(. 0), (set()))
78 ))
79
80+ if(true, print(123), print(456))
81+ switch(x, print("First"), print("Second"))
82+
83+ bool 1, switch 3, num 123, print 1, jump 2, num 456, print 1
84+
85+ bool * switch execute jump
86+
87+ still need a if for if else chains
88+
89+
90+ bool 1 if 5
91+
92+ if the condition is true continue else jump the number
93+
94+ if(cond, print("true"), if(cond2, print("else")))
95+ bool 1, if 3, string..., print 4, jump 5,
96+ cond if jumping over the jump if to exectue the else part
97+ if the cond is true continue will hit jump and miss the logic part
98+
99+ Changes:
100+ Old:
101+ if(style(--scheme: dark): #eeeeee;)
102+ New:
103+ if(style(--scheme) == dark, #eeeeee, #fff)
104+ Old:
105+ 3px yellow if(
106+ style(--color: green): dashed;
107+ style(--color: yellow): inset;
108+ else: solid;
109+ )
110+ New:
111+ 3px yellow if(style(--color) == green, dashed
112+ if(style(--color) == yellow, inset, solid)
113+ )
114+
115+
116+ for(range(0,10), (print($)))
117+
118+ NUM 0, NUM 10, RANGE 2, SCOPE 1, PRINT 1, GROUP 1, FOR 2
119
120
121 )
122diff --git a/src/grim.c b/src/grim.c
123index a375ea7..b88c795 100755
124--- a/src/grim.c
125+++ b/src/grim.c
126@@ -6,6 +6,7 @@
127 #include <string.h>
128 #include <ctype.h>
129 #include <malloc.h>
130+#include <math.h>
131
132 // +------------------------------------------------------+
133 // |(TOC) Table of contents |
134@@ -460,12 +461,12 @@ float unit_value(struct Units[]** stack, int register_size, int heap_size, struc
135 heap[8] = malloc(sizeof(struct Unit) * 32);
136 }
137
138- for (int i = 0; i < heap_size; i++) {
139+ for (int i = 0; i < units_len; i++) {
140 struct Unit unit = units.units[i];
141 UnitType type = unit.type;
142
143+ int idx = register_len-unit.value;
144
145- if (value range to put to register)
146 switch (type) {
147 // DEG, TURN are not length values but are treated as generic units (PX)
148 case DEG:
149@@ -571,408 +572,230 @@ float unit_value(struct Units[]** stack, int register_size, int heap_size, struc
150 register[register_len++].value = unit.value*heap.units[0].value;
151 break;
152 }
153- case GROUP: {
154- // Just returns the first value on the register stack
155- register_len = 1;
156- break;
157- }
158+ case GROUP:
159 case CALC: {
160- // Because the calculation would have already ran, make sure the first value is a number
161- registers[0].type = NUMBER;
162- register_len = 1;
163+ // Take the last computed value in the group and move it to the front
164+ registers[idx] = registers[register_len-1];
165+ register_len = idx;
166 break;
167 }
168 case MIN: {
169- registers[0].type = NUMBER;
170+ registers[idx].type = NUMBER;
171
172- for (int j = 1; j < register_len; j++) {
173- if (registers[0] > registers[j]) {
174- registers[0] = registers[j];
175+ for (int j = idx+1; j < register_len; j++) {
176+ if (registers[idx] > registers[j]) {
177+ registers[idx] = registers[j];
178 }
179 }
180+ register_len = idx;
181 break;
182 }
183 case MAX: {
184- registers[0].type = NUMBER;
185+ registers[idx].type = NUMBER;
186
187- for (int j = 1; j < register_len; j++) {
188- if (registers[0] < registers[j]) {
189- registers[0] = registers[j];
190+ for (int j = idx+1; j < register_len; j++) {
191+ if (registers[idx] < registers[j]) {
192+ registers[idx] = registers[j];
193 }
194 }
195+ register_len = idx;
196 break;
197 }
198 case CLAMP: {
199- iv.type = NUMBER;
200-
201- float args[3];
202- int found = 0;
203- size_t start = i + 1;
204- size_t end = i + 1 + unit.value;
205-
206- while (start < end) {
207- Range r = getNextUnit(units, start, end);
208- args[found++] = UnitValue(m, units, r.start, r.end).value;
209+ if (unit.value == 3) {
210+ // if idx+1 (val) is greater than idx+2 (max)
211+ if (registers[idx+1] > registers[idx+2]) {
212+ // set idx (min also the return value) to idx+2 (max)
213+ registers[idx] = registers[idx+2];
214+ // if idx+1 > idx (min) then set idx (return) to idx+1 (val)
215+ } else if (registers[idx+1] > registers[idx]) {
216+ registers[idx] = registers[idx+1];
217+ }
218+ // if the value is less than idx (min) then idx (return) remains the same
219 }
220
221- if (found == 3) {
222- iv.value = std::clamp(args[1], args[0], args[2]);
223- } else {
224- iv.value = args[0];
225- }
226-
227- i += unit.value;
228+ registers[idx].type = NUMBER;
229+ register_len = idx;
230 break;
231 }
232 case ROUND: {
233- iv.type = NUMBER;
234-
235- UnitType ut = NEAREST;
236-
237- Unit args[3];
238- int found = 0;
239- size_t start = i + 1;
240- size_t end = i + 1 + unit.value;
241-
242- while (start < end) {
243- Range r = getNextUnit(units, start, end);
244- args[found++] = UnitValue(m, units, r.start, r.end);
245- }
246-
247- if (found == 3) {
248- ut = args[0].type;
249-
250- } else if (found == 2) {
251- ut = NEAREST;
252-
253- args[2].value = args[1].value;
254- args[1].value = args[0].value;
255- } else if (found == 1) {
256- ut = NEAREST;
257-
258- args[1].value = args[0].value;
259- args[2].value = 1.0f;
260- }
261-
262+ if (unit.value == 3) {
263+ if (registers[idx].type == NEAREST) {
264+ registers[idx].value = roundf(registers[idx + 1].value/registers[idx + 2].value)*registers[idx + 2].value;
265+ } else if (registers[idx].type == UP) {
266+ registers[idx].value = ceilf(registers[idx + 1].value/registers[idx + 2].value)*registers[idx + 2].value;
267+ } else if (registers[idx].type == DOWN) {
268+ registers[idx].value = floorf(registers[idx + 1].value/registers[idx + 2].value)*registers[idx + 2].value;
269+ } else if (registers[idx].type == TO_ZERO) {
270+ registers[idx].value = truncf(registers[idx + 1].value/registers[idx + 2].value)*registers[idx + 2].value;
271+ }
272+ } else if (unit.value == 2) {
273+ registers[idx].value = roundf(registers[idx].value/registers[idx + 1].value)*registers[idx + 1].value;
274+ } else if (unit.value == 1) {
275+ registers[idx].value = roundf(registers[idx].value);
276
277- if (ut == NEAREST) {
278- iv.value = std::round(args[1].value/args[2].value)*args[2].value;
279- } else if (ut == UP) {
280- iv.value = std::ceil(args[1].value/args[2].value)*args[2].value;
281- } else if (ut == DOWN) {
282- iv.value = std::floor(args[1].value/args[2].value)*args[2].value;
283- } else if (ut == TO_ZERO) {
284- iv.value = std::trunc(args[1].value/args[2].value)*args[2].value;
285 }
286
287- i += unit.value;
288+ registers[idx].type = NUMBER;
289+ register_len = idx;
290 break;
291 }
292+ case REMD:
293 case MOD: {
294- iv.type = NUMBER;
295-
296- float args[2];
297- int found = 0;
298- size_t start = i + 1;
299- size_t end = i + 1 + unit.value;
300-
301- while (start < end) {
302- Range r = getNextUnit(units, start, end);
303- args[found++] = UnitValue(m, units, r.start, r.end).value;
304- }
305-
306- if (found == 2) {
307- iv.value = std::fmod(args[0], args[1]);
308- } else {
309- iv.value = args[0];
310+ if (unit.value == 2) {
311+ registers[idx].value = fmodf(registers[idx].value, registers[idx + 1].value);
312 }
313
314- i += unit.value;
315+ registers[idx].type = NUMBER;
316+ register_len = idx;
317 break;
318 }
319 case PROGRESS: {
320- iv.type = NUMBER;
321-
322- float args[3];
323- int found = 0;
324- size_t start = i + 1;
325- size_t end = i + 1 + unit.value;
326-
327- while (start < end) {
328- Range r = getNextUnit(units, start, end);
329- args[found++] = UnitValue(m, units, r.start, r.end).value;
330- }
331-
332- if (found == 3) {
333+ if (unit.value == 3) {
334 // (progress - progress start) / (progress end - progress start)
335- iv.value = (args[0]-args[1])/(args[2]-args[1]);
336- } else {
337- iv.value = args[0];
338+ registers[idx].value = (registers[idx].value-registers[idx + 1].value)/(registers[idx + 2].value-registers[idx + 1].value);
339 }
340-
341
342- i += unit.value;
343- break;
344- }
345- case REMD: {
346- iv.type = NUMBER;
347-
348- float args[2];
349- int found = 0;
350- size_t start = i + 1;
351- size_t end = i + 1 + unit.value;
352-
353- while (start < end) {
354- Range r = getNextUnit(units, start, end);
355- args[found++] = UnitValue(m, units, r.start, r.end).value;
356- }
357-
358- if (found == 2) {
359- iv.value = std::fmodf(args[0], args[1]);
360- } else {
361- iv.value = args[0];
362- }
363-
364- i += unit.value;
365+ registers[idx].type = NUMBER;
366+ register_len = idx;
367 break;
368 }
369 case SIN: {
370- iv.type = NUMBER;
371- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
372- iv.value = std::sinf(u1.value);
373- i += unit.value;
374+ register[idx].value = sinf(register[idx].value);
375+ registers[idx].type = NUMBER;
376 break;
377 }
378 case COS: {
379- iv.type = NUMBER;
380- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
381- iv.value = std::cosf(u1.value);
382- i += unit.value;
383+ register[idx].value = cosf(register[idx].value);
384+ registers[idx].type = NUMBER;
385 break;
386 }
387 case TAN: {
388- iv.type = NUMBER;
389- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
390- iv.value = std::tanf(u1.value);
391- i += unit.value;
392+ register[idx].value = tanf(register[idx].value);
393+ registers[idx].type = NUMBER;
394 break;
395 }
396 case ASIN: {
397- iv.type = NUMBER;
398- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
399- iv.value = std::asinf(u1.value);
400- i += unit.value;
401+ register[idx].value = asinf(register[idx].value);
402+ registers[idx].type = NUMBER;
403 break;
404 }
405 case ACOS: {
406- iv.type = NUMBER;
407- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
408- iv.value = std::acosf(u1.value);
409- i += unit.value;
410+ register[idx].value = acosf(register[idx].value);
411+ registers[idx].type = NUMBER;
412 break;
413 }
414 case ATAN: {
415- iv.type = NUMBER;
416- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
417- iv.value = std::atanf(u1.value);
418- i += unit.value;
419+ register[idx].value = atanf(register[idx].value);
420+ registers[idx].type = NUMBER;
421 break;
422 }
423 case ATAN2: {
424- iv.type = NUMBER;
425-
426- float args[2];
427- int found = 0;
428- size_t start = i + 1;
429- size_t end = i + 1 + unit.value;
430-
431- while (start < end) {
432- Range r = getNextUnit(units, start, end);
433- args[found++] = UnitValue(m, units, r.start, r.end).value;
434- }
435-
436- if (found == 2) {
437- iv.value = std::atan2f(args[0], args[1]);
438- } else {
439- iv.value = args[0];
440+ if (unit.value == 2) {
441+ register[idx].value = atan2f(register[idx].value, register[idx + 2].value);
442 }
443
444- i += unit.value;
445+ registers[idx].type = NUMBER;
446+ register_len = idx;
447 break;
448 }
449 case POW: {
450- iv.type = NUMBER;
451-
452- float args[2];
453- int found = 0;
454- size_t start = i + 1;
455- size_t end = i + 1 + unit.value;
456-
457- while (start < end) {
458- Range r = getNextUnit(units, start, end);
459- args[found++] = UnitValue(m, units, r.start, r.end).value;
460+ if (unit.value == 2) {
461+ register[idx].value = powf(register[idx].value, register[idx + 2].value);
462 }
463
464- if (found == 2) {
465- iv.value = std::powf(args[0], args[1]);
466- } else {
467- iv.value = args[0];
468- }
469-
470- i += unit.value;
471+ registers[idx].type = NUMBER;
472+ register_len = idx;
473 break;
474 }
475 case SQRT: {
476- iv.type = NUMBER;
477- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
478- iv.value = std::sqrtf(u1.value);
479- i += unit.value;
480+ register[idx].value = sqrtf(register[idx].value);
481+ registers[idx].type = NUMBER;
482 break;
483 }
484 case HYPOT: {
485- iv.type = NUMBER;
486-
487-
488 float v = 0;
489- size_t start = i + 1;
490- size_t end = i + 1 + unit.value;
491
492- while (start < end) {
493- Range r = getNextUnit(units, start, end);
494- float t = UnitValue(m, units, r.start, r.end).value;
495- v += t * t;
496+ for (float j = idx; j < register_len; j++) {
497+ v += registers[j].value * registers[j].value;
498 }
499+
500+ registers[idx].value = sqrtf(v);
501
502- iv.value = std::sqrtf(v);
503-
504- i += unit.value;
505+ registers[idx].type = NUMBER;
506+ register_len = idx;
507 break;
508 }
509 case LOG: {
510- iv.type = NUMBER;
511-
512- float args[2];
513- int found = 0;
514- size_t start = i + 1;
515- size_t end = i + 1 + unit.value;
516-
517- while (start < end) {
518- Range r = getNextUnit(units, start, end);
519- args[found++] = UnitValue(m, units, r.start, r.end).value;
520+ if (unit.value == 2) {
521+ registers[idx].value = logf(registers[idx].value) / logf(registers[idx + 1].value);
522+ } else if (unit.value == 1) {
523+ registers[idx].value = logf(registers[idx].value);
524 }
525
526- if (found == 2) {
527- iv.value = std::logf(args[0]) / std::logf(args[1]);
528- } else if (found == 1) {
529- iv.value = std::logf(args[0]);
530- }
531-
532- i += unit.value;
533+ registers[idx].type = NUMBER;
534+ register_len = idx;
535 break;
536 }
537 case EXP: {
538- iv.type = NUMBER;
539- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
540- iv.value = std::expf(u1.value);
541- i += unit.value;
542+ register[idx].value = expf(register[idx].value);
543+ registers[idx].type = NUMBER;
544 break;
545 }
546 case ABS: {
547- iv.type = NUMBER;
548- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
549- iv.value = std::fabsf(u1.value);
550- i += unit.value;
551+ register[idx].value = absf(register[idx].value);
552+ registers[idx].type = NUMBER;
553 break;
554 }
555 case SIGN: {
556- iv.type = NUMBER;
557- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
558-
559- if (u1.value > 0) {
560- iv.value = 1;
561- } else if (u1.value < 0) {
562- iv.value = -1;
563+ if (registers[idx].value > 0) {
564+ registers[idx].value = 1;
565+ } else if (registers[idx].value < 0) {
566+ registers[idx].value = -1;
567 } else {
568- iv.value = 0;
569+ registers[idx].value = 0;
570 }
571
572- i += unit.value;
573+ registers[idx].type = NUMBER;
574 break;
575 }
576 case ATTR: {
577- Range args[3];
578- int found = 0;
579- size_t start = i + 1;
580- size_t end = i + 1 + unit.value;
581-
582- while (start < end) {
583- args[found++] = getNextUnit(units, start, end);
584- }
585-
586- Unit u1 = units[args[0].start];
587-
588- Range r = m.get(u1.value); // Pull the marker off the ctx
589- Unit value = UnitValue(m, units, r.start, r.end);
590-
591- if (r.end - r.start > 0) {
592- if (found > 1) {
593- // Get the passed type attr(0(value) 1(type), 2(default))
594- Unit u2 = units[args[1].start];
595-
596- // Cast the user defined type onto the value
597- if (u2.type == TYPE) {
598- value.type = units[args[1].start+1].type;
599- } else {
600- value.type = u2.type;
601- }
602+ // ATTR and VAR_FUNC don't need to get the value of the VAR only check to see if its
603+ // been replaced, if not provide a default
604+ if (registers[idx].type == VAR) {
605+ if (units.value > 2) {
606+ registers[idx] = registers[idx + 2];
607 }
608-
609- iv = value;
610- } else if (found == 3) {
611- // Default value
612- iv = UnitValue(m, units, args[2].start, args[2].end);
613 }
614-
615- i += unit.value;
616+ if (units.value > 1) {
617+ registers[idx] = registers[idx + 1].type;
618+ }
619+ register_len = idx;
620+ break;
621+ }
622+ case TYPE: {
623 break;
624 }
625 case VAR_FUNC: {
626- Unit args[2];
627- int found = 0;
628- size_t start = i + 1;
629- size_t end = i + 1 + unit.value;
630-
631- while (start < end) {
632- Range r = getNextUnit(units, start, end);
633- args[found++] = UnitValue(m, units, r.start, r.end);
634- }
635-
636- Range r = m.get(args[0].value); // Pull the marker off the ctx
637-
638- if (r.end > 0) {
639- iv = UnitValue(m, units, r.start, r.end);
640- } else if (found == 2) {
641- // Default value
642- iv = args[1];
643+ if (registers[idx].type == VAR) {
644+ if (units.value > 1) {
645+ registers[idx] = registers[idx + 1];
646+ }
647 }
648-
649- i += unit.value;
650+ register_len = idx;
651 break;
652 }
653 case VAR: {
654- Range r = m.get(unit.value);
655-
656- if (r.end > 0) {
657- iv = heap.units[r.start];
658+ if (registers[idx].type == VAR) {
659+ if (registers[idx].value > -1) {
660+ registers[idx].value = stack[registers[idx].value];
661+ }
662 }
663
664 break;
665 }
666 case PRINT: {
667- Unit u = UnitValue(m, units, i+1, i+1+unit.value);
668- std::cout << "> " << u.value << std::endl;
669- iv = u;
670- i += unit.value;
671+ printf("> %f", registers[idx].value);
672 break;
673 }
674 case IF: {
675diff --git a/src/parser.c b/src/parser.c
676index 533cf00..5f680b0 100755
677--- a/src/parser.c
678+++ b/src/parser.c
679@@ -239,6 +239,7 @@ void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* v
680 write_unit(units, units_len, cap, placeholder);
681 *units_len -= 1;
682 }
683+
684 int before_count = *units_len;
685 int before_vars_len = *vars_len;
686