home readme diff tree note docs

0commit 60c72d0452854f10ad171d712c9ae7d98f5415e9
1Author: lakefox <mason@lakefox.net>
2Date:   Thu Feb 26 19:11:15 2026 -0700
3
4    RPN added to parser
5
6diff --git a/include/grim.h b/include/grim.h
7index 76dadf6..08d8c61 100755
8--- a/include/grim.h
9+++ b/include/grim.h
10@@ -188,6 +188,6 @@ char* INNER_HTML(Node* node, char** buffer, size_t* size, int depth);
11 
12 void ADD_CLASS(Node* n, char* value);
13 
14-void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* vars_len, int* vars_cap, int* stack_len, char* value);
15+void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* vars_len, int* vars_cap, int* stack_len, int* max_register_size, char* value);
16 
17 #endif // NODE_H
18diff --git a/playground/css_unit.c b/playground/css_unit.c
19index 5262d00..63aef74 100644
20--- a/playground/css_unit.c
21+++ b/playground/css_unit.c
22@@ -25,10 +25,11 @@ void benchmark_get_unit(char* value) {
23 	int vars_len = 0;
24 
25 	int stack_len = 0;
26+	int max_register_size = 0;
27 
28 	for (int i = 0; i < iterations; i++) {
29 		units_len = 0;
30-		get_unit(&units, &cap, &units_len, &vars, &vars_len, &vars_cap, &stack_len, value);
31+		get_unit(&units, &cap, &units_len, &vars, &vars_len, &vars_cap, &stack_len, &max_register_size, value);
32 	}
33 
34 	free(units);
35@@ -44,7 +45,7 @@ void benchmark_get_unit(char* value) {
36 	       (total_time / iterations) * 1000000);
37 }
38 
39-void test_get_unit(char* ustr, struct Unit* known_units, int known_units_len, int stack_size) {
40+void test_get_unit(char* ustr, struct Unit* known_units, int known_units_len, int stack_size, int known_register_size) {
41 	int cap = 10;
42 	struct Unit *units = malloc(sizeof(struct Unit) * cap);
43 	int units_len = 0;
44@@ -54,13 +55,20 @@ void test_get_unit(char* ustr, struct Unit* known_units, int known_units_len, in
45 	int vars_len = 0;
46 
47 	int stack_len = 0;
48+	int max_register_size = 0;
49 
50-	get_unit(&units, &cap, &units_len, &vars, &vars_len, &vars_cap, &stack_len, ustr);
51-
52-	
53-	assert(units_len == known_units_len);
54+	get_unit(&units, &cap, &units_len, &vars, &vars_len, &vars_cap, &stack_len, &max_register_size, ustr);
55 
56 	bool error = false;
57+	if (units_len != known_units_len) {
58+		fprintf(stderr, "UNITS assertion failed on test case \"%s\": %d != %d\n", ustr, units_len, known_units_len);
59+		error = true;
60+	}
61+
62+	if (max_register_size != known_register_size) {
63+		fprintf(stderr, "REGISTER assertion failed on test case \"%s\": %d != %d\n", ustr, max_register_size, known_register_size);
64+		error = true;
65+	}
66 
67 	if (stack_len != stack_size) {
68 		fprintf(stderr, "STACK assertion failed on test case \"%s\": %d != %d\n", ustr, stack_len, stack_size);
69@@ -96,10 +104,11 @@ int main() {
70 	int vars_len = 0;
71 
72 	int stack_len = 0;
73+	int max_register_size = 0;
74 
75-	char* ustr = "((let(x 10px) set(x x * 2%) print(x)) (let(y 10px) set(y y * 2) print(y)))";
76+	char* ustr = "(let(x 10px) set(x 30px) (let(x 50px) print(x)) print(x))";
77 
78-	get_unit(&units, &cap, &units_len, &vars, &vars_len, &vars_cap, &stack_len, ustr);
79+	get_unit(&units, &cap, &units_len, &vars, &vars_len, &vars_cap, &stack_len, &max_register_size, ustr);
80 
81 	printf("Stack Size: %d\n", stack_len);
82 
83@@ -109,20 +118,21 @@ int main() {
84 	if (true) {
85 		benchmark_get_unit(ustr);
86 
87-		test_get_unit("1 + 1", (struct Unit[]){{NUMBER, 1}, {ADD, 0}, {NUMBER, 1}}, 3, 0);
88-		test_get_unit("23px * 5678.7%", (struct Unit[]){{PX, 23}, {MULT, 0}, {PERCENT, 5678.7f}}, 3, 0);
89-		test_get_unit("calc(23px * size)", (struct Unit[]){{CALC, 3}, {PX, 23}, {MULT, 0}, {VAR, -1}}, 4, 0);
90-		test_get_unit("(let(x 10px) set(x 30px) (let(x 50px) print(x)) print(x))", (struct Unit[]){{GROUP, 14}, {LET, 2}, {VAR, 0}, {PX, 10}, {SET, 2}, {VAR, 0}, {PX, 30}, {GROUP, 5}, {LET, 2}, {VAR, 1}, {PX, 50}, {PRINT, 1}, {VAR, 1}, {PRINT, 1}, {VAR, 0}}, 15, 2);
91-		test_get_unit("((let(x 10px) set(x x * 2%) print(x)) (let(y 10px) set(y y * 2) print(y)))", (struct Unit[]){{GROUP, 22}, 
92+		test_get_unit("1 + 1", (struct Unit[]){{NUMBER, 1}, {NUMBER, 1}, {ADD, 0}}, 3, 0, 2);
93+		test_get_unit("23px * 5678.7%", (struct Unit[]){{PX, 23}, {PERCENT, 5678.7f}, {MULT, 0}}, 3, 0, 2);
94+		test_get_unit("calc(23px * size)", (struct Unit[]){{PX, 23}, {VAR, -1}, {MULT, 0}, {CALC, 3}}, 4, 0, 3);
95+		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);
96+		test_get_unit("((let(x 10px) set(x x * 2%) print(x)) (let(y 10px) set(y y * 2) print(y)))", (struct Unit[]){ 
97+				{VAR, 0}, {PX, 10}, {LET, 2},
98+				{VAR, 0}, {VAR, 0}, {PERCENT, 2}, {MULT, 0}, {SET, 4},
99+				{VAR, 0}, {PRINT, 1},
100 			{GROUP, 10}, 
101-				{LET, 2}, {VAR, 0}, {PX, 10}, 
102-				{SET, 4}, {VAR, 0}, {VAR, 0}, {MULT, 0}, {PERCENT, 2}, 
103-				{PRINT, 1}, {VAR, 0}, 
104+				{ VAR, 0}, {PX, 10}, {LET, 2},
105+				{VAR, 0}, {VAR, 0}, {NUMBER, 2}, {MULT, 0}, {SET, 4},
106+				{VAR, 0}, {PRINT, 1},
107 			{GROUP, 10}, 
108-				{LET, 2}, { VAR, 0}, {PX, 10}, 
109-				{SET, 4}, {VAR, 0}, {VAR, 0}, {MULT, 0}, {NUMBER, 2}, 
110-				{PRINT, 1}, {VAR, 0}}
111-			, 23, 1);
112-		test_get_unit("(let(x :name \"john doe\" :age 27))", (struct Unit[]){{GROUP, 14.0f}, {LET, 13}, {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}}, 15, 1);
113+		{GROUP, 22}}
114+			, 23, 1, 22);
115+		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);
116 	}
117 }
118diff --git a/src/grim.c b/src/grim.c
119index 7529c5d..9ecb714 100755
120--- a/src/grim.c
121+++ b/src/grim.c
122@@ -448,21 +448,22 @@ Range getNextUnit(const std::vector<Unit>& units, size_t& offset, size_t end) {
123 // HEAP: [width, height, em, dpi]
124 // HEAP LAYOUT: VAR
125 
126-float unit_value(struct Units[]** stack, struct Unit_Vector** units, int start, int end) {
127-	UnitType result_type = NUMBER;
128-	float result_value = 0;
129-
130-	UnitType op = ADD;
131-
132-	UnitType iv_type = NUMBER;
133-	float iv_value = 0
134+float unit_value(struct Units[]** stack, int register_size, int heap_size, struct Unit** units, int* units_len) {
135+	struct Unit** heap[heap_size];
136+	int heap[heap_size] = {0};
137+	struct Unit registers[register_size] = {0};
138+
139+	// Pre-alloc
140+	for (int i = 0; i < heap_size; i++) {
141+		heap[8] = malloc(sizeof(struct Unit) * 32);
142+	}
143 
144-Init the heap, the stack will be passed for preset values
145-	
146-	for (int i = start; i < end; i++) {
147+	for (int i = 0; i < heap_size; i++) {
148 		struct Unit unit = units.units[i];
149 		UnitType type = unit.type;
150 
151+
152+		if (value range to put to register)
153 		switch (type) {
154 			case ADD:
155 			case SUB:
156@@ -532,7 +533,7 @@ Init the heap, the stack will be passed for preset values
157 			case RIC:
158 			case RLH: {
159 				iv.type = NUMBER;
160-				iv.value = unit.value*heap.units[2].value;
161+				iv.value = unit.value*stack[2].value;
162 				break;
163 			}
164 			case EX:
165@@ -584,9 +585,16 @@ Init the heap, the stack will be passed for preset values
166 				iv.value = unit.value*heap.units[0].value;
167 				break;
168 			}
169+
170+
171+
172+
173+
174+if func range
175+
176 			case GROUP: {
177 				Snapshot s = m.save();
178-			      	iv = UnitValue(m, units, i+1, i+1+unit.value);
179+				iv = UnitValue(m, units, i+1, i+1+unit.value);
180 				i += unit.value;
181 				m.restore(s);
182 				break;
183@@ -931,7 +939,7 @@ Init the heap, the stack will be passed for preset values
184 				break;
185 			}
186 			case ATTR: {
187-			     	Range args[3];
188+				Range args[3];
189 				int found = 0;
190 				size_t start = i + 1;
191 				size_t end = i + 1 + unit.value;
192@@ -1030,7 +1038,7 @@ Init the heap, the stack will be passed for preset values
193 				}
194 
195 
196-			   	i += unit.value;
197+				i += unit.value;
198 				break;
199 			}
200 			case LET: {
201@@ -1170,7 +1178,7 @@ Init the heap, the stack will be passed for preset values
202 
203 
204 
205-			     	Range r = m.get(units[i+1].value);
206+				Range r = m.get(units[i+1].value);
207 				iv = {NUMBER, (float)r.end-(float)r.start};
208 
209 				i += unit.value;
210@@ -1244,7 +1252,11 @@ Init the heap, the stack will be passed for preset values
211 		}
212 	}
213 
214-	return result;
215+	for (int i = 0; i < heap_size; i++) {
216+		free(heap[i]);
217+	}
218+
219+	return registers[0];
220 }
221 
222 // Used for root node without a parent
223diff --git a/src/parser.c b/src/parser.c
224index 2608ea0..8b15503 100755
225--- a/src/parser.c
226+++ b/src/parser.c
227@@ -106,7 +106,7 @@ int write_var(char** vars_ptr, int* len, int* cap, char var[MAX_STR_LEN]) {
228 	return *len-1;
229 }
230 
231-void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* vars_len, int* vars_cap, int* stack_len, char* value) {
232+void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* vars_len, int* vars_cap, int* stack_len, int* max_register_size, char* value) {
233 	char buffer[MAX_STR_LEN];
234 	int buffer_len = 0;
235 
236@@ -123,6 +123,10 @@ void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* v
237 
238 	int size = strlen(value);
239 
240+	if (*max_register_size < 2) {
241+		*max_register_size = 2; // Default 2 for math operations
242+	}
243+
244 	for (int i = 0; i < size; i++) {
245 		char v = value[i];
246 		if (v == '\\' && !escaped) escaped = true;
247@@ -218,35 +222,45 @@ void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* v
248 
249 			args[args_len] = '\0';
250 
251-			int function_idx = *units_len;
252 			struct Unit placeholder = {0};
253 
254 			if (name_len == 0) {
255 				placeholder.type = GROUP;
256 			} else {
257 				const struct FuncMap* fm = find_func(name, name_len);
258-				placeholder.type = fm->type;
259+				if (fm == NULL) {
260+					placeholder.type = FUNC;
261+				} else {
262+					placeholder.type = fm->type;
263+				}
264 			}
265 
266-			write_unit(units, units_len, cap, placeholder);
267+			if (placeholder.type == LET) {
268+				write_unit(units, units_len, cap, placeholder);
269+				*units_len -= 1;
270+			}
271 			int before_count = *units_len;
272 			int before_vars_len = *vars_len;
273 
274-			get_unit(units, cap, units_len, vars, vars_len, vars_cap, stack_len, args);
275+			get_unit(units, cap, units_len, vars, vars_len, vars_cap, stack_len, max_register_size, args);
276 			free(args);
277 
278+
279+			// Reset the vars_len to remove any new vars created in the prevous scope
280+			// unless let was called
281 			if (placeholder.type != LET) {
282 				*vars_len = before_vars_len;
283 			}
284 
285 			int child_count = *units_len - before_count;
286 
287-			// Reset the vars_len to remove any new vars created in the prevous scope
288-			struct Unit final_unit;
289-			final_unit.type = placeholder.type;
290-			final_unit.value = (float)child_count;
291+			if (child_count > *max_register_size) {
292+				*max_register_size = child_count;
293+			}
294 
295-			(*units)[function_idx] = final_unit;
296+			placeholder.value = (float)child_count;
297+
298+			write_unit(units, units_len, cap, placeholder);
299 
300 			buffer[0] = '\0';
301 			buffer_len = 0;
302@@ -353,7 +367,7 @@ void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* v
303 										} else {
304 											unit.type = VAR;
305 
306-											if (((*units_len)-1 >= 1) && (*units)[(*units_len)-1].type == LET) {
307+											if (((*units_len) < *cap) && (*units)[(*units_len)].type == LET) {
308 												unit.value = write_var(vars, vars_len, vars_cap, buffer);
309 
310 												if (unit.value + 1 > *stack_len) {
311@@ -384,7 +398,26 @@ void get_unit(struct Unit** units, int* cap, int* units_len, char** vars, int* v
312 				}
313 			}
314 
315-			write_unit(units, units_len, cap, unit);
316+			if ((*units_len) > 1 && ((*units)[(*units_len)-1].type == MULT || 
317+						(*units)[(*units_len)-1].type == ADD ||
318+						(*units)[(*units_len)-1].type == SUB ||
319+						(*units)[(*units_len)-1].type == DIV ||
320+						(*units)[(*units_len)-1].type == LT ||
321+						(*units)[(*units_len)-1].type == GT ||
322+						(*units)[(*units_len)-1].type == LE ||
323+						(*units)[(*units_len)-1].type == GE ||
324+						(*units)[(*units_len)-1].type == EQ ||
325+						(*units)[(*units_len)-1].type == AND ||
326+						(*units)[(*units_len)-1].type == OR ||
327+						(*units)[(*units_len)-1].type == NOT 
328+				)) {
329+				struct Unit u = (*units)[(*units_len)-1];
330+				(*units_len) -= 1;
331+				write_unit(units, units_len, cap, unit);
332+				write_unit(units, units_len, cap, u);
333+			} else {
334+				write_unit(units, units_len, cap, unit);
335+			}
336 			buffer[0] = '\0';
337 			buffer_len = 0;
338 		} else if (inQuotes) {