home
readme
diff
tree
note
docs
0commit b99dd0a8bf911b83adf04c1f0453dba6051c0c5a
1Author: lakefox <mason@lakefox.net>
2Date: Sat Feb 28 19:55:17 2026 -0700
3
4 Added arg counting to parser
5
6diff --git a/include/grim.h b/include/grim.h
7index 08d8c61..1377ea8 100755
8--- a/include/grim.h
9+++ b/include/grim.h
10@@ -15,8 +15,6 @@
11 typedef enum {
12 // Color
13 TEST, HEX,
14- // Logic
15- AND, OR, NOT, ONLY, COMMA,
16 // Length
17 PX, EM, PERCENT, CM, CAP, CH, EX, IC, LH, RCAP, RCH, REM, REX, RIC, RLH, VH,
18 VW, VMAX, VMIN, VB, VI, CQW, CQH, CQI, CQB, CQMIN, CQMAX, MM, Q, IN, PC, PT,
19@@ -31,8 +29,6 @@ typedef enum {
20
21 // Global
22 INHERIT, INITIAL, REVERT, REVERT_LAYER, UNSET, AUTO, NONE,
23- // Operator
24- EQ, LT, GT, LE, GE, ADD, SUB, MULT, DIV,
25 // Baseline Position
26 FIRST_BASELINE, LAST_BASELINE,
27 // Box Edge
28@@ -83,7 +79,7 @@ typedef enum {
29 NEAREST, UP, DOWN, TO_ZERO,
30
31 // Keyword
32- PRINT, SCREEN, TOKEN, NO_SUPPORT, IMAGE, STRING, BOOL, VAR, NONOP, ELSE, TAG, CHAR,
33+ SCREEN, TOKEN, NO_SUPPORT, IMAGE, STRING, BOOL, VAR, NONOP, ELSE, TAG, CHAR,
34
35 FUNC_START,
36 // General Functions
37@@ -91,7 +87,7 @@ typedef enum {
38 HYPOT, LOG, EXP, ABS, SIGN, SIN, COS, TAN, ASIN, ACOS, ATAN, ATAN2, VAR_FUNC,
39 BLUR, BRIGHTNESS, CONTRAST, DROP_SHADOW, GRAYSCALE, HUE_ROTATE, INVERT,
40 OPACITY, SEPIA, SATURATE, ATTR, TYPE, ENV, IF, FUNC, LET, RETURN, SET,
41- LIST, AT, EMPTY, INSERT, SIZE, WHILE,
42+ LIST, AT, EMPTY, INSERT, SIZE, WHILE, PRINT,
43
44 // Easing Functions
45 EASING_FUNCTION, LINEAR_EASING_FUNCTION, LINEAR, EASE, EASE_IN, EASE_OUT, EASE_IN_OUT, CUBIC_BEZIER_FUNCTION,
46@@ -106,6 +102,12 @@ typedef enum {
47
48 // Image & Grouping
49 URL, IMAGE_SET, CROSS_FADE, ELEMENT, GROUP, GRADIENT,
50+
51+ // Operator
52+ EQ, LT, GT, LE, GE, ADD, SUB, MULT, DIV,
53+
54+ // Logic
55+ AND, OR, NOT, ONLY, COMMA,
56 NON_FUNC_PADDING
57 } UnitType;
58
59diff --git a/playground/css_unit.c b/playground/css_unit.c
60index 63aef74..cb819b1 100644
61--- a/playground/css_unit.c
62+++ b/playground/css_unit.c
63@@ -116,23 +116,36 @@ int main() {
64 free(vars);
65
66 if (true) {
67- benchmark_get_unit(ustr);
68+ //benchmark_get_unit(ustr);
69+
70+ test_get_unit("1 + 1", (struct Unit[]){{NUMBER, 1}, {NUMBER, 1}, {ADD, 2}}, 3, 0, 2);
71+ test_get_unit("23px * 5678.7%", (struct Unit[]){{PX, 23}, {PERCENT, 5678.7f}, {MULT, 2}}, 3, 0, 2);
72+ test_get_unit("calc(23px * size)", (struct Unit[]){{PX, 23}, {VAR, -1}, {MULT, 2}, {CALC, 1}}, 4, 0, 3);
73+ 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);
74+ // 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);
75+
76+
77+
78+
79+
80
81- test_get_unit("1 + 1", (struct Unit[]){{NUMBER, 1}, {NUMBER, 1}, {ADD, 0}}, 3, 0, 2);
82- test_get_unit("23px * 5678.7%", (struct Unit[]){{PX, 23}, {PERCENT, 5678.7f}, {MULT, 0}}, 3, 0, 2);
83- test_get_unit("calc(23px * size)", (struct Unit[]){{PX, 23}, {VAR, -1}, {MULT, 0}, {CALC, 3}}, 4, 0, 3);
84- 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, 5}, {VAR, 0}, {PRINT, 1}, {GROUP, 14}}, 15, 2, 14);
85 test_get_unit("((let(x 10px) set(x x * 2%) print(x)) (let(y 10px) set(y y * 2) print(y)))", (struct Unit[]){
86- {VAR, 0}, {PX, 10}, {LET, 2},
87- {VAR, 0}, {VAR, 0}, {PERCENT, 2}, {MULT, 0}, {SET, 4},
88- {VAR, 0}, {PRINT, 1},
89- {GROUP, 10},
90- { VAR, 0}, {PX, 10}, {LET, 2},
91- {VAR, 0}, {VAR, 0}, {NUMBER, 2}, {MULT, 0}, {SET, 4},
92- {VAR, 0}, {PRINT, 1},
93- {GROUP, 10},
94- {GROUP, 22}}
95- , 23, 1, 22);
96- 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, 14}}, 15, 1, 14);
97+ {VAR, 0}, {PX, 10}, {LET, 2},
98+ {VAR, 0}, {VAR, 0}, {PERCENT, 2}, {MULT, 2}, {SET, 2},
99+ {VAR, 0}, {PRINT, 1},
100+ {GROUP, 3},
101+ { VAR, 0}, {PX, 10}, {LET, 2},
102+ {VAR, 0}, {VAR, 0}, {NUMBER, 2}, {MULT, 2}, {SET, 2},
103+ {VAR, 0}, {PRINT, 1},
104+ {GROUP, 3},
105+ {GROUP, 2}}
106+ , 23, 1, 22);
107+
108+
109+
110+
111+
112+
113+ 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);
114 }
115 }
116diff --git a/src/grim.c b/src/grim.c
117index 9ecb714..a375ea7 100755
118--- a/src/grim.c
119+++ b/src/grim.c
120@@ -451,7 +451,9 @@ Range getNextUnit(const std::vector<Unit>& units, size_t& offset, size_t end) {
121 float unit_value(struct Units[]** stack, int register_size, int heap_size, struct Unit** units, int* units_len) {
122 struct Unit** heap[heap_size];
123 int heap[heap_size] = {0};
124+
125 struct Unit registers[register_size] = {0};
126+ int register_len = 0;
127
128 // Pre-alloc
129 for (int i = 0; i < heap_size; i++) {
130@@ -465,60 +467,44 @@ float unit_value(struct Units[]** stack, int register_size, int heap_size, struc
131
132 if (value range to put to register)
133 switch (type) {
134- case ADD:
135- case SUB:
136- case DIV:
137- case MULT:
138- case LT:
139- case LE:
140- case GT:
141- case GE:
142- case EQ:
143- case AND:
144- case OR:
145- case NOT:
146- case ONLY: {
147- op = type;
148- continue;
149- }
150 // DEG, TURN are not length values but are treated as generic units (PX)
151 case DEG:
152 case TURN:
153 case NUMBER:
154 // NUMBER is any untyped numbers "2". Treat as a pixel
155 case PX: {
156- iv.type = NUMBER;
157- iv.value = unit.value;
158+ register[register_len].type = NUMBER;
159+ register[register_len++].value = unit.value;
160 break;
161 }
162 case CM: {
163- iv.type = NUMBER;
164- iv.value = unit.value*37.8f;
165+ register[register_len].type = NUMBER;
166+ register[register_len++].value = unit.value*37.8f;
167 break;
168 }
169 case MM: {
170- iv.type = NUMBER;
171- iv.value = unit.value*3.78f;
172+ register[register_len].type = NUMBER;
173+ register[register_len++].value = unit.value*3.78f;
174 break;
175 }
176 case Q: {
177- iv.type = NUMBER;
178- iv.value = unit.value*0.94f;
179+ register[register_len].type = NUMBER;
180+ register[register_len++].value = unit.value*0.94f;
181 break;
182 }
183 case IN: {
184- iv.type = NUMBER;
185- iv.value = unit.value*96.0f;
186+ register[register_len].type = NUMBER;
187+ register[register_len++].value = unit.value*96.0f;
188 break;
189 }
190 case PC: {
191- iv.type = NUMBER;
192- iv.value = unit.value*16.0f;
193+ register[register_len].type = NUMBER;
194+ register[register_len++].value = unit.value*16.0f;
195 break;
196 }
197 case PT: {
198- iv.type = NUMBER;
199- iv.value = unit.value*1.3f;
200+ register[register_len].type = NUMBER;
201+ register[register_len++].value = unit.value*1.3f;
202 break;
203 }
204 case EM:
205@@ -532,20 +518,20 @@ float unit_value(struct Units[]** stack, int register_size, int heap_size, struc
206 case RCH:
207 case RIC:
208 case RLH: {
209- iv.type = NUMBER;
210- iv.value = unit.value*stack[2].value;
211+ register[register_len].type = NUMBER;
212+ register[register_len++].value = unit.value*stack[2].value;
213 break;
214 }
215 case EX:
216 case REX: {
217- iv.type = NUMBER;
218- iv.value = unit.value*(heap.units[2].value*0.5f);
219+ register[register_len].type = NUMBER;
220+ register[register_len++].value = unit.value*(heap.units[2].value*0.5f);
221 break;
222 }
223 case CQH:
224 case VH: {
225- iv.type = NUMBER;
226- iv.value = heap.units[1].value*(unit.value*0.01f);
227+ register[register_len].type = NUMBER;
228+ register[register_len++].value = heap.units[1].value*(unit.value*0.01f);
229 break;
230 }
231 case CQW:
232@@ -553,92 +539,67 @@ float unit_value(struct Units[]** stack, int register_size, int heap_size, struc
233 case CQB:
234 case PERCENT:
235 case VW: {
236- iv.type = NUMBER;
237- iv.value = heap.units[0].value*(unit.value*0.01f);
238+ register[register_len].type = NUMBER;
239+ register[register_len++].value = heap.units[0].value*(unit.value*0.01f);
240 break;
241 }
242 case VMAX:
243 case CQMAX: {
244- iv.type = NUMBER;
245+ register[register_len].type = NUMBER;
246 // 0: width
247 // 1: height
248 if (heap.units[0].value > heap.units[1].value) {
249- iv.value = unit.value*heap.units[0].value;
250+ register[register_len++].value = unit.value*heap.units[0].value;
251 } else {
252- iv.value = unit.value*heap.units[1].value;
253+ register[register_len++].value = unit.value*heap.units[1].value;
254 }
255 break;
256 }
257 case VMIN:
258 case CQMIN: {
259- iv.type = NUMBER;
260+ register[register_len].type = NUMBER;
261 if (heap.units[0].value < heap.units[1].value) {
262- iv.value = unit.value*heap.units[0].value;
263+ register[register_len++].value = unit.value*heap.units[0].value;
264 } else {
265- iv.value = unit.value*heap.units[1].value;
266+ register[register_len++].value = unit.value*heap.units[1].value;
267 }
268 break;
269 }
270 case VB:
271 case VI: {
272- iv.type = NUMBER;
273- iv.value = unit.value*heap.units[0].value;
274+ register[register_len].type = NUMBER;
275+ register[register_len++].value = unit.value*heap.units[0].value;
276 break;
277 }
278-
279-
280-
281-
282-
283-if func range
284-
285 case GROUP: {
286- Snapshot s = m.save();
287- iv = UnitValue(m, units, i+1, i+1+unit.value);
288- i += unit.value;
289- m.restore(s);
290+ // Just returns the first value on the register stack
291+ register_len = 1;
292 break;
293 }
294 case CALC: {
295- iv.type = NUMBER;
296- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
297- iv.value = u1.value;
298- i += unit.value;
299+ // Because the calculation would have already ran, make sure the first value is a number
300+ registers[0].type = NUMBER;
301+ register_len = 1;
302 break;
303 }
304 case MIN: {
305- iv.type = NUMBER;
306+ registers[0].type = NUMBER;
307
308- size_t start = i + 1;
309- size_t end = i + 1 + unit.value;
310-
311- Range r = getNextUnit(units, start, end);
312- iv.value = UnitValue(m, units, r.start, r.end).value;
313-
314- while (start < end) {
315- r = getNextUnit(units, start, end);
316- float u = UnitValue(m, units, r.start, r.end).value;
317- iv.value = std::min(iv.value, u);
318+ for (int j = 1; j < register_len; j++) {
319+ if (registers[0] > registers[j]) {
320+ registers[0] = registers[j];
321+ }
322 }
323-
324- i += unit.value;
325 break;
326 }
327 case MAX: {
328- iv.type = NUMBER;
329-
330- size_t start = i + 1;
331- size_t end = i + 1 + unit.value;
332+ registers[0].type = NUMBER;
333
334- Range r = getNextUnit(units, start, end);
335- iv.value = UnitValue(m, units, r.start, r.end).value;
336-
337- while (start < end) {
338- r = getNextUnit(units, start, end);
339- iv.value = std::max(iv.value, UnitValue(m, units, r.start, r.end).value);
340+ for (int j = 1; j < register_len; j++) {
341+ if (registers[0] < registers[j]) {
342+ registers[0] = registers[j];
343+ }
344 }
345-
346- i += unit.value;
347 break;
348 }
349 case CLAMP: {
350@@ -1184,9 +1145,12 @@ if func range
351 i += unit.value;
352 break;
353 }
354- }
355
356- switch (op) {
357+
358+
359+
360+
361+
362 case ADD:
363 result.type = NUMBER;
364 result.value += iv.value;
365diff --git a/src/parser.c b/src/parser.c
366index 8b15503..533cf00 100755
367--- a/src/parser.c
368+++ b/src/parser.c
369@@ -252,13 +252,28 @@ void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* v
370 *vars_len = before_vars_len;
371 }
372
373- int child_count = *units_len - before_count;
374+ int reg_count = *units_len - before_count;
375
376- if (child_count > *max_register_size) {
377- *max_register_size = child_count;
378+ if (reg_count > *max_register_size) {
379+ *max_register_size = reg_count;
380 }
381
382- placeholder.value = (float)child_count;
383+ float child_count = 0;
384+ float depth = 0;
385+
386+ for (int j = *units_len-1; j >= before_count; j--) {
387+ if ((*units)[j].type >= FUNC_START) {
388+ depth += (*units)[j].value;
389+ }
390+
391+ if (depth == 0) {
392+ child_count++;
393+ } else {
394+ depth--;
395+ }
396+ }
397+
398+ placeholder.value = child_count;
399
400 write_unit(units, units_len, cap, placeholder);
401
402@@ -412,6 +427,7 @@ void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* v
403 (*units)[(*units_len)-1].type == NOT
404 )) {
405 struct Unit u = (*units)[(*units_len)-1];
406+ u.value = 2;
407 (*units_len) -= 1;
408 write_unit(units, units_len, cap, unit);
409 write_unit(units, units_len, cap, u);