home
readme
diff
tree
note
docs
0commit 440895de367aca1b1eab94209200b2bb00b682ef
1Author: lakefox <mason@lakefox.net>
2Date: Fri Jan 23 20:02:40 2026 -0700
3
4 Removed UnitType union in favor of a float
5
6diff --git a/Makefile b/Makefile
7index 5197f09..e30b7f0 100755
8--- a/Makefile
9+++ b/Makefile
10@@ -1,4 +1,5 @@
11 # --- Variables ---
12+#CCFLAGS = -std=c++2b -O3
13 CCFLAGS = -Wall -Wextra -std=c++2b -g -O0 -fsanitize=address,undefined -fno-omit-frame-pointer
14 # -O2 -Wall -Wformat -Wformat=2 -Wconversion -Wimplicit-fallthrough \
15 # -Werror=format-security \
16diff --git a/include/grim.h b/include/grim.h
17index 45d25bb..7ca03fd 100755
18--- a/include/grim.h
19+++ b/include/grim.h
20@@ -98,7 +98,7 @@ enum class UnitType : short {
21 HYPOT, LOG, EXP, ABS, SIGN, SIN, COS, TAN, ASIN, ACOS, ATAN, ATAN2, VAR_FUNC,
22 BLUR, BRIGHTNESS, CONTRAST, DROP_SHADOW, GRAYSCALE, HUE_ROTATE, INVERT,
23 OPACITY, SEPIA, SATURATE, ATTR, TYPE, ENV, IF, FUNC, LET, RETURN, SET,
24- LIST,
25+ LIST, AT,
26
27 // Easing Functions
28 EASING_FUNCTION, LINEAR_EASING_FUNCTION, LINEAR, EASE, EASE_IN, EASE_OUT, EASE_IN_OUT, CUBIC_BEZIER_FUNCTION,
29@@ -117,20 +117,10 @@ enum class UnitType : short {
30 };
31
32
33-// 4 bytes
34-union UnitValue {
35- UnitType ENUM;
36- int INT;
37- unsigned int UINT;
38- float FLOAT;
39- bool BOOL;
40- char CHAR;
41-};
42-
43 // 8 bytes
44 struct Unit {
45 UnitType type; // short
46- UnitValue value;
47+ float value;
48 };
49
50 struct Range {
51@@ -164,8 +154,8 @@ class Memory {
52 size_t len = end-start;
53 arena.push_back({id, pointer, len, current});
54 current = &arena.back();
55- pointer += len;
56 std::copy(units.begin() + start, units.begin() + end, heap.begin() + pointer);
57+ pointer += len;
58 }
59
60 // Used to prefill the heap
61diff --git a/playground/unitvalue.cc b/playground/unitvalue.cc
62index bab6d4a..9d56df9 100644
63--- a/playground/unitvalue.cc
64+++ b/playground/unitvalue.cc
65@@ -51,13 +51,13 @@ int main() {
66
67 Memory m;
68 // Preset width, height, and em
69- m.push_back(sym.get("width"),{UnitType::NUMBER, {.FLOAT = 1000.0f}});
70- m.push_back(sym.get("height"),{UnitType::NUMBER, {.FLOAT = 700.0f}});
71- m.push_back(sym.get("em"),{UnitType::NUMBER, {.FLOAT= 16.0f}});
72+ m.push_back(sym.get("width"),{UnitType::NUMBER, 1000.0f});
73+ m.push_back(sym.get("height"),{UnitType::NUMBER, 700.0f});
74+ m.push_back(sym.get("em"),{UnitType::NUMBER, 16.0f});
75
76- std::vector<Unit> units = getUnit("if((1 > 1): 10px; else: 11vw;)", &sym);
77+ std::vector<Unit> units = getUnit("list(x 5 2 3 4) print(at(x 0)) set(at(x 0) 13) print(at(x 0))", &sym);
78
79 Unit u = UnitValue(m, units, 0, units.size());
80
81- std::cout << "Value: " << u.value.FLOAT << std::endl;
82+ std::cout << "Value: " << u.value << std::endl;
83 }
84diff --git a/src/grim.cc b/src/grim.cc
85index 0ea2d69..8ab1d5a 100755
86--- a/src/grim.cc
87+++ b/src/grim.cc
88@@ -878,7 +878,7 @@ bool executeQuery(Window* w, std::string p) {
89 Context c;
90 c.id = window->symbol_table.get("all");
91 c.type = UnitType::BOOL;
92- c.value.BOOL = w->getMedia() == Media::All;
93+ c.value = w->getMedia() == Media::All;
94 c.previous = nullptr;
95
96
97@@ -910,7 +910,7 @@ Range getNextUnit(const std::vector<Unit>& units, size_t& offset, size_t end) {
98
99 if (unit.type > UnitType::FUNC_START) {
100 // Range is the function unit + its body
101- size_t argEnd = offset + unit.value.INT + 1;
102+ size_t argEnd = offset + unit.value + 1;
103 offset = argEnd; // Move offset past this function for next time
104 return {start, argEnd};
105 } else {
106@@ -924,7 +924,7 @@ Range getNextUnit(const std::vector<Unit>& units, size_t& offset, size_t end) {
107 Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
108 Unit result{};
109 result.type = UnitType::NUMBER;
110- result.value.FLOAT = 0.0f;
111+ result.value = 0.0f;
112 UnitType op = UnitType::ADD;
113
114 Unit iv;
115@@ -957,37 +957,37 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
116 // NUMBER is any untyped numbers "2". Treat as a pixel
117 case UnitType::PX: {
118 iv.type = UnitType::NUMBER;
119- iv.value.FLOAT = unit.value.FLOAT;
120+ iv.value = unit.value;
121 break;
122 }
123 case UnitType::CM: {
124 iv.type = UnitType::NUMBER;
125- iv.value.FLOAT = unit.value.FLOAT*37.8f;
126+ iv.value = unit.value*37.8f;
127 break;
128 }
129 case UnitType::MM: {
130 iv.type = UnitType::NUMBER;
131- iv.value.FLOAT = unit.value.FLOAT*3.78f;
132+ iv.value = unit.value*3.78f;
133 break;
134 }
135 case UnitType::Q: {
136 iv.type = UnitType::NUMBER;
137- iv.value.FLOAT = unit.value.FLOAT*0.94f;
138+ iv.value = unit.value*0.94f;
139 break;
140 }
141 case UnitType::IN: {
142 iv.type = UnitType::NUMBER;
143- iv.value.FLOAT = unit.value.FLOAT*96.0f;
144+ iv.value = unit.value*96.0f;
145 break;
146 }
147 case UnitType::PC: {
148 iv.type = UnitType::NUMBER;
149- iv.value.FLOAT = unit.value.FLOAT*16.0f;
150+ iv.value = unit.value*16.0f;
151 break;
152 }
153 case UnitType::PT: {
154 iv.type = UnitType::NUMBER;
155- iv.value.FLOAT = unit.value.FLOAT*1.3f;
156+ iv.value = unit.value*1.3f;
157 break;
158 }
159 case UnitType::EM:
160@@ -1002,19 +1002,19 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
161 case UnitType::RIC:
162 case UnitType::RLH: {
163 iv.type = UnitType::NUMBER;
164- iv.value.FLOAT = unit.value.FLOAT*m.heap[2].value.FLOAT;
165+ iv.value = unit.value*m.heap[2].value;
166 break;
167 }
168 case UnitType::EX:
169 case UnitType::REX: {
170 iv.type = UnitType::NUMBER;
171- iv.value.FLOAT = unit.value.FLOAT*(m.heap[2].value.FLOAT*0.5f);
172+ iv.value = unit.value*(m.heap[2].value*0.5f);
173 break;
174 }
175 case UnitType::CQH:
176 case UnitType::VH: {
177 iv.type = UnitType::NUMBER;
178- iv.value.FLOAT = m.heap[1].value.FLOAT*(unit.value.FLOAT*0.01f);
179+ iv.value = m.heap[1].value*(unit.value*0.01f);
180 break;
181 }
182 case UnitType::CQW:
183@@ -1023,7 +1023,7 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
184 case UnitType::PERCENT:
185 case UnitType::VW: {
186 iv.type = UnitType::NUMBER;
187- iv.value.FLOAT = m.heap[0].value.FLOAT*(unit.value.FLOAT*0.01f);
188+ iv.value = m.heap[0].value*(unit.value*0.01f);
189 break;
190 }
191 case UnitType::VMAX:
192@@ -1031,76 +1031,76 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
193 iv.type = UnitType::NUMBER;
194 // 0: width
195 // 1: height
196- if (m.heap[0].value.FLOAT > m.heap[1].value.FLOAT) {
197- iv.value.FLOAT = unit.value.FLOAT*m.heap[0].value.FLOAT;
198+ if (m.heap[0].value > m.heap[1].value) {
199+ iv.value = unit.value*m.heap[0].value;
200 } else {
201- iv.value.FLOAT = unit.value.FLOAT*m.heap[1].value.FLOAT;
202+ iv.value = unit.value*m.heap[1].value;
203 }
204 break;
205 }
206 case UnitType::VMIN:
207 case UnitType::CQMIN: {
208 iv.type = UnitType::NUMBER;
209- if (m.heap[0].value.FLOAT < m.heap[1].value.FLOAT) {
210- iv.value.FLOAT = unit.value.FLOAT*m.heap[0].value.FLOAT;
211+ if (m.heap[0].value < m.heap[1].value) {
212+ iv.value = unit.value*m.heap[0].value;
213 } else {
214- iv.value.FLOAT = unit.value.FLOAT*m.heap[1].value.FLOAT;
215+ iv.value = unit.value*m.heap[1].value;
216 }
217 break;
218 }
219 case UnitType::VB:
220 case UnitType::VI: {
221 iv.type = UnitType::NUMBER;
222- iv.value.FLOAT = unit.value.FLOAT*m.heap[0].value.FLOAT;
223+ iv.value = unit.value*m.heap[0].value;
224 break;
225 }
226 case UnitType::GROUP: {
227 Snapshot s = m.save();
228- iv = UnitValue(m, units, i+1, i+1+unit.value.INT);
229- i += unit.value.INT;
230+ iv = UnitValue(m, units, i+1, i+1+unit.value);
231+ i += unit.value;
232 m.restore(s);
233 break;
234 }
235 case UnitType::CALC: {
236 iv.type = UnitType::NUMBER;
237- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value.INT);
238- iv.value.FLOAT = u1.value.FLOAT;
239- i += unit.value.INT;
240+ Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
241+ iv.value = u1.value;
242+ i += unit.value;
243 break;
244 }
245 case UnitType::MIN: {
246 iv.type = UnitType::NUMBER;
247
248 size_t start = i + 1;
249- size_t end = i + 1 + unit.value.INT;
250+ size_t end = i + 1 + unit.value;
251
252 Range r = getNextUnit(units, start, end);
253- iv.value.FLOAT = UnitValue(m, units, r.start, r.end).value.FLOAT;
254+ iv.value = UnitValue(m, units, r.start, r.end).value;
255
256 while (start < end) {
257 r = getNextUnit(units, start, end);
258- float u = UnitValue(m, units, r.start, r.end).value.FLOAT;
259- iv.value.FLOAT = std::min(iv.value.FLOAT, u);
260+ float u = UnitValue(m, units, r.start, r.end).value;
261+ iv.value = std::min(iv.value, u);
262 }
263
264- i += unit.value.INT;
265+ i += unit.value;
266 break;
267 }
268 case UnitType::MAX: {
269 iv.type = UnitType::NUMBER;
270
271 size_t start = i + 1;
272- size_t end = i + 1 + unit.value.INT;
273+ size_t end = i + 1 + unit.value;
274
275 Range r = getNextUnit(units, start, end);
276- iv.value.FLOAT = UnitValue(m, units, r.start, r.end).value.FLOAT;
277+ iv.value = UnitValue(m, units, r.start, r.end).value;
278
279 while (start < end) {
280 r = getNextUnit(units, start, end);
281- iv.value.FLOAT = std::max(iv.value.FLOAT, UnitValue(m, units, r.start, r.end).value.FLOAT);
282+ iv.value = std::max(iv.value, UnitValue(m, units, r.start, r.end).value);
283 }
284
285- i += unit.value.INT;
286+ i += unit.value;
287 break;
288 }
289 case UnitType::CLAMP: {
290@@ -1109,20 +1109,20 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
291 float args[3];
292 int found = 0;
293 size_t start = i + 1;
294- size_t end = i + 1 + unit.value.INT;
295+ size_t end = i + 1 + unit.value;
296
297 while (start < end) {
298 Range r = getNextUnit(units, start, end);
299- args[found++] = UnitValue(m, units, r.start, r.end).value.FLOAT;
300+ args[found++] = UnitValue(m, units, r.start, r.end).value;
301 }
302
303 if (found == 3) {
304- iv.value.FLOAT = std::clamp(args[1], args[0], args[2]);
305+ iv.value = std::clamp(args[1], args[0], args[2]);
306 } else {
307- iv.value.FLOAT = args[0];
308+ iv.value = args[0];
309 }
310
311- i += unit.value.INT;
312+ i += unit.value;
313 break;
314 }
315 case UnitType::ROUND: {
316@@ -1133,7 +1133,7 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
317 Unit args[3];
318 int found = 0;
319 size_t start = i + 1;
320- size_t end = i + 1 + unit.value.INT;
321+ size_t end = i + 1 + unit.value;
322
323 while (start < end) {
324 Range r = getNextUnit(units, start, end);
325@@ -1146,27 +1146,27 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
326 } else if (found == 2) {
327 ut = UnitType::NEAREST;
328
329- args[2].value.FLOAT = args[1].value.FLOAT;
330- args[1].value.FLOAT = args[0].value.FLOAT;
331+ args[2].value = args[1].value;
332+ args[1].value = args[0].value;
333 } else if (found == 1) {
334 ut = UnitType::NEAREST;
335
336- args[1].value.FLOAT = args[0].value.FLOAT;
337- args[2].value.FLOAT = 1.0f;
338+ args[1].value = args[0].value;
339+ args[2].value = 1.0f;
340 }
341
342
343 if (ut == UnitType::NEAREST) {
344- iv.value.FLOAT = std::round(args[1].value.FLOAT/args[2].value.FLOAT)*args[2].value.FLOAT;
345+ iv.value = std::round(args[1].value/args[2].value)*args[2].value;
346 } else if (ut == UnitType::UP) {
347- iv.value.FLOAT = std::ceil(args[1].value.FLOAT/args[2].value.FLOAT)*args[2].value.FLOAT;
348+ iv.value = std::ceil(args[1].value/args[2].value)*args[2].value;
349 } else if (ut == UnitType::DOWN) {
350- iv.value.FLOAT = std::floor(args[1].value.FLOAT/args[2].value.FLOAT)*args[2].value.FLOAT;
351+ iv.value = std::floor(args[1].value/args[2].value)*args[2].value;
352 } else if (ut == UnitType::TO_ZERO) {
353- iv.value.FLOAT = std::trunc(args[1].value.FLOAT/args[2].value.FLOAT)*args[2].value.FLOAT;
354+ iv.value = std::trunc(args[1].value/args[2].value)*args[2].value;
355 }
356
357- i += unit.value.INT;
358+ i += unit.value;
359 break;
360 }
361 case UnitType::MOD: {
362@@ -1175,20 +1175,20 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
363 float args[2];
364 int found = 0;
365 size_t start = i + 1;
366- size_t end = i + 1 + unit.value.INT;
367+ size_t end = i + 1 + unit.value;
368
369 while (start < end) {
370 Range r = getNextUnit(units, start, end);
371- args[found++] = UnitValue(m, units, r.start, r.end).value.FLOAT;
372+ args[found++] = UnitValue(m, units, r.start, r.end).value;
373 }
374
375 if (found == 2) {
376- iv.value.FLOAT = std::fmod(args[0], args[1]);
377+ iv.value = std::fmod(args[0], args[1]);
378 } else {
379- iv.value.FLOAT = args[0];
380+ iv.value = args[0];
381 }
382
383- i += unit.value.INT;
384+ i += unit.value;
385 break;
386 }
387 case UnitType::PROGRESS: {
388@@ -1197,22 +1197,22 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
389 float args[3];
390 int found = 0;
391 size_t start = i + 1;
392- size_t end = i + 1 + unit.value.INT;
393+ size_t end = i + 1 + unit.value;
394
395 while (start < end) {
396 Range r = getNextUnit(units, start, end);
397- args[found++] = UnitValue(m, units, r.start, r.end).value.FLOAT;
398+ args[found++] = UnitValue(m, units, r.start, r.end).value;
399 }
400
401 if (found == 3) {
402 // (progress - progress start) / (progress end - progress start)
403- iv.value.FLOAT = (args[0]-args[1])/(args[2]-args[1]);
404+ iv.value = (args[0]-args[1])/(args[2]-args[1]);
405 } else {
406- iv.value.FLOAT = args[0];
407+ iv.value = args[0];
408 }
409
410
411- i += unit.value.INT;
412+ i += unit.value;
413 break;
414 }
415 case UnitType::REMD: {
416@@ -1221,62 +1221,62 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
417 float args[2];
418 int found = 0;
419 size_t start = i + 1;
420- size_t end = i + 1 + unit.value.INT;
421+ size_t end = i + 1 + unit.value;
422
423 while (start < end) {
424 Range r = getNextUnit(units, start, end);
425- args[found++] = UnitValue(m, units, r.start, r.end).value.FLOAT;
426+ args[found++] = UnitValue(m, units, r.start, r.end).value;
427 }
428
429 if (found == 2) {
430- iv.value.FLOAT = std::fmodf(args[0], args[1]);
431+ iv.value = std::fmodf(args[0], args[1]);
432 } else {
433- iv.value.FLOAT = args[0];
434+ iv.value = args[0];
435 }
436
437- i += unit.value.INT;
438+ i += unit.value;
439 break;
440 }
441 case UnitType::SIN: {
442 iv.type = UnitType::NUMBER;
443- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value.INT);
444- iv.value.FLOAT = std::sinf(u1.value.FLOAT);
445- i += unit.value.INT;
446+ Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
447+ iv.value = std::sinf(u1.value);
448+ i += unit.value;
449 break;
450 }
451 case UnitType::COS: {
452 iv.type = UnitType::NUMBER;
453- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value.INT);
454- iv.value.FLOAT = std::cosf(u1.value.FLOAT);
455- i += unit.value.INT;
456+ Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
457+ iv.value = std::cosf(u1.value);
458+ i += unit.value;
459 break;
460 }
461 case UnitType::TAN: {
462 iv.type = UnitType::NUMBER;
463- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value.INT);
464- iv.value.FLOAT = std::tanf(u1.value.FLOAT);
465- i += unit.value.INT;
466+ Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
467+ iv.value = std::tanf(u1.value);
468+ i += unit.value;
469 break;
470 }
471 case UnitType::ASIN: {
472 iv.type = UnitType::NUMBER;
473- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value.INT);
474- iv.value.FLOAT = std::asinf(u1.value.FLOAT);
475- i += unit.value.INT;
476+ Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
477+ iv.value = std::asinf(u1.value);
478+ i += unit.value;
479 break;
480 }
481 case UnitType::ACOS: {
482 iv.type = UnitType::NUMBER;
483- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value.INT);
484- iv.value.FLOAT = std::acosf(u1.value.FLOAT);
485- i += unit.value.INT;
486+ Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
487+ iv.value = std::acosf(u1.value);
488+ i += unit.value;
489 break;
490 }
491 case UnitType::ATAN: {
492 iv.type = UnitType::NUMBER;
493- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value.INT);
494- iv.value.FLOAT = std::atanf(u1.value.FLOAT);
495- i += unit.value.INT;
496+ Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
497+ iv.value = std::atanf(u1.value);
498+ i += unit.value;
499 break;
500 }
501 case UnitType::ATAN2: {
502@@ -1285,20 +1285,20 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
503 float args[2];
504 int found = 0;
505 size_t start = i + 1;
506- size_t end = i + 1 + unit.value.INT;
507+ size_t end = i + 1 + unit.value;
508
509 while (start < end) {
510 Range r = getNextUnit(units, start, end);
511- args[found++] = UnitValue(m, units, r.start, r.end).value.FLOAT;
512+ args[found++] = UnitValue(m, units, r.start, r.end).value;
513 }
514
515 if (found == 2) {
516- iv.value.FLOAT = std::atan2f(args[0], args[1]);
517+ iv.value = std::atan2f(args[0], args[1]);
518 } else {
519- iv.value.FLOAT = args[0];
520+ iv.value = args[0];
521 }
522
523- i += unit.value.INT;
524+ i += unit.value;
525 break;
526 }
527 case UnitType::POW: {
528@@ -1307,27 +1307,27 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
529 float args[2];
530 int found = 0;
531 size_t start = i + 1;
532- size_t end = i + 1 + unit.value.INT;
533+ size_t end = i + 1 + unit.value;
534
535 while (start < end) {
536 Range r = getNextUnit(units, start, end);
537- args[found++] = UnitValue(m, units, r.start, r.end).value.FLOAT;
538+ args[found++] = UnitValue(m, units, r.start, r.end).value;
539 }
540
541 if (found == 2) {
542- iv.value.FLOAT = std::powf(args[0], args[1]);
543+ iv.value = std::powf(args[0], args[1]);
544 } else {
545- iv.value.FLOAT = args[0];
546+ iv.value = args[0];
547 }
548
549- i += unit.value.INT;
550+ i += unit.value;
551 break;
552 }
553 case UnitType::SQRT: {
554 iv.type = UnitType::NUMBER;
555- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value.INT);
556- iv.value.FLOAT = std::sqrtf(u1.value.FLOAT);
557- i += unit.value.INT;
558+ Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
559+ iv.value = std::sqrtf(u1.value);
560+ i += unit.value;
561 break;
562 }
563 case UnitType::HYPOT: {
564@@ -1336,17 +1336,17 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
565
566 float v = 0;
567 size_t start = i + 1;
568- size_t end = i + 1 + unit.value.INT;
569+ size_t end = i + 1 + unit.value;
570
571 while (start < end) {
572 Range r = getNextUnit(units, start, end);
573- float t = UnitValue(m, units, r.start, r.end).value.FLOAT;
574+ float t = UnitValue(m, units, r.start, r.end).value;
575 v += t * t;
576 }
577
578- iv.value.FLOAT = std::sqrtf(v);
579+ iv.value = std::sqrtf(v);
580
581- i += unit.value.INT;
582+ i += unit.value;
583 break;
584 }
585 case UnitType::LOG: {
586@@ -1355,56 +1355,56 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
587 float args[2];
588 int found = 0;
589 size_t start = i + 1;
590- size_t end = i + 1 + unit.value.INT;
591+ size_t end = i + 1 + unit.value;
592
593 while (start < end) {
594 Range r = getNextUnit(units, start, end);
595- args[found++] = UnitValue(m, units, r.start, r.end).value.FLOAT;
596+ args[found++] = UnitValue(m, units, r.start, r.end).value;
597 }
598
599 if (found == 2) {
600- iv.value.FLOAT = std::logf(args[0]) / std::logf(args[1]);
601+ iv.value = std::logf(args[0]) / std::logf(args[1]);
602 } else if (found == 1) {
603- iv.value.FLOAT = std::logf(args[0]);
604+ iv.value = std::logf(args[0]);
605 }
606
607- i += unit.value.INT;
608+ i += unit.value;
609 break;
610 }
611 case UnitType::EXP: {
612 iv.type = UnitType::NUMBER;
613- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value.INT);
614- iv.value.FLOAT = std::expf(u1.value.FLOAT);
615- i += unit.value.INT;
616+ Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
617+ iv.value = std::expf(u1.value);
618+ i += unit.value;
619 break;
620 }
621 case UnitType::ABS: {
622 iv.type = UnitType::NUMBER;
623- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value.INT);
624- iv.value.FLOAT = std::fabsf(u1.value.FLOAT);
625- i += unit.value.INT;
626+ Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
627+ iv.value = std::fabsf(u1.value);
628+ i += unit.value;
629 break;
630 }
631 case UnitType::SIGN: {
632 iv.type = UnitType::NUMBER;
633- Unit u1 = UnitValue(m, units, i+1, i+1+unit.value.INT);
634+ Unit u1 = UnitValue(m, units, i+1, i+1+unit.value);
635
636- if (u1.value.FLOAT > 0) {
637- iv.value.FLOAT = 1;
638- } else if (u1.value.FLOAT < 0) {
639- iv.value.FLOAT = -1;
640+ if (u1.value > 0) {
641+ iv.value = 1;
642+ } else if (u1.value < 0) {
643+ iv.value = -1;
644 } else {
645- iv.value.FLOAT = 0;
646+ iv.value = 0;
647 }
648
649- i += unit.value.INT;
650+ i += unit.value;
651 break;
652 }
653 case UnitType::ATTR: {
654 Range args[3];
655 int found = 0;
656 size_t start = i + 1;
657- size_t end = i + 1 + unit.value.INT;
658+ size_t end = i + 1 + unit.value;
659
660 while (start < end) {
661 args[found++] = getNextUnit(units, start, end);
662@@ -1414,7 +1414,7 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
663
664 if (u1.type == UnitType::VAR) {
665
666- Range r = m.get(u1.value.INT); // Pull the marker off the ctx
667+ Range r = m.get(u1.value); // Pull the marker off the ctx
668 Unit value = UnitValue(m, units, r.start, r.end);
669
670 if (r.end - r.start > 0) {
671@@ -1437,14 +1437,14 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
672 }
673 }
674
675- i += unit.value.INT;
676+ i += unit.value;
677 break;
678 }
679 case UnitType::VAR_FUNC: {
680 Unit args[2];
681 int found = 0;
682 size_t start = i + 1;
683- size_t end = i + 1 + unit.value.INT;
684+ size_t end = i + 1 + unit.value;
685
686 while (start < end) {
687 Range r = getNextUnit(units, start, end);
688@@ -1452,7 +1452,7 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
689 }
690
691 if (args[0].type == UnitType::VAR) {
692- Range r = m.get(args[0].value.INT); // Pull the marker off the ctx
693+ Range r = m.get(args[0].value); // Pull the marker off the ctx
694
695 if (r.end > 0) {
696 iv = UnitValue(m, units, r.start, r.end);
697@@ -1462,11 +1462,11 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
698 }
699 }
700
701- i += unit.value.INT;
702+ i += unit.value;
703 break;
704 }
705 case UnitType::VAR: {
706- Range r = m.get(unit.value.INT);
707+ Range r = m.get(unit.value);
708
709 if (r.end > 0) {
710 iv = m.heap[r.start];
711@@ -1476,47 +1476,56 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
712 }
713 case UnitType::LET: {
714 if (units[start + 1].type == UnitType::VAR) {
715- Unit u = UnitValue(m, units, i + 2, i + 1 + unit.value.INT);
716- m.push_back(units[i+1].value.INT, u);
717+ Unit u = UnitValue(m, units, i + 2, i + 1 + unit.value);
718+ m.push_back(units[i+1].value, u);
719 }
720
721- i += unit.value.INT;
722+ i += unit.value;
723 break;
724 }
725 case UnitType::SET: {
726 if (units[i + 1].type == UnitType::VAR) {
727- Range r = m.get(units[i + 1].value.INT);
728- Unit u = UnitValue(m, units, i + 2, i + 1 + unit.value.INT);
729+ Range r = m.get(units[i + 1].value);
730+ Unit u = UnitValue(m, units, i + 2, i + 1 + unit.value);
731
732 // r.end is the length
733 if (r.end > 0) { // need to write over
734 m.heap[r.start] = u;
735 } else {
736- m.push_back(units[i + 1].value.INT, u);
737+ m.push_back(units[i + 1].value, u);
738+ }
739+ } else if (units[i + 1].type == UnitType::AT && units[i + 2].type == UnitType::VAR) {
740+ // Set at in a list
741+ Range r = m.get(units[i+2].value);
742+
743+ if (r.end > 0) {
744+ Unit p = UnitValue(m, units, i + 2, i + 1 + units[i+2].value);
745+ Unit u = UnitValue(m, units, i + 2, i + 1 + unit.value);
746+ m.heap[r.start + p.value] = u;
747 }
748 }
749
750- i += unit.value.INT;
751+ i += unit.value;
752 break;
753 }
754 case UnitType::PRINT: {
755- Unit u = UnitValue(m, units, i+1, i+1+unit.value.INT);
756- std::cout << "> " << u.value.FLOAT << std::endl;
757+ Unit u = UnitValue(m, units, i+1, i+1+unit.value);
758+ std::cout << "> " << u.value << std::endl;
759 iv = u;
760- i += unit.value.INT;
761+ i += unit.value;
762 break;
763 }
764 case UnitType::IF: {
765 Range args[4]; // condition trueval else falseval
766 int found = 0;
767 size_t start = i + 1;
768- size_t end = i + 1 + unit.value.INT;
769+ size_t end = i + 1 + unit.value;
770
771 while (start < end) {
772 args[found++] = getNextUnit(units, start, end);
773 }
774
775- bool condition = UnitValue(m, units, args[0].start, args[0].end).value.BOOL;
776+ bool condition = UnitValue(m, units, args[0].start, args[0].end).value;
777
778 if (condition) {
779 iv = UnitValue(m, units, args[1].start, args[1].end);
780@@ -1530,73 +1539,98 @@ Unit UnitValue(Memory& m, std::vector<Unit>& units, size_t start, size_t end) {
781 }
782
783
784- i += unit.value.INT;
785+ i += unit.value;
786 break;
787 }
788 case UnitType::LIST: {
789-
790+ if (units[start + 1].type == UnitType::VAR) {
791+
792+ // how to pre allocate a empty list????
793+ // empty(5)
794+ // link(links two lists) join(joins them in memory)???
795+ // make a JUMP to padd the list
796+
797+ m.push(units[i+1].value, units, i+2, i+1+unit.value);
798+ // m.push_back({UnitType::JUMP, 0})
799+ }
800+
801+ i += unit.value;
802+ break;
803+ }
804+ case UnitType::AT: {
805+ if (units[start + 1].type == UnitType::VAR) {
806+ Range r = m.get(units[i+1].value);
807+
808+ if (r.end > 0) {
809+ Unit u = UnitValue(m, units, i + 1, i + 1 + unit.value);
810+ iv = m.heap[r.start + u.value];
811+ }
812+ }
813+
814+ i += unit.value;
815+ break;
816 }
817 }
818
819 switch (op) {
820 case UnitType::ADD:
821 result.type = UnitType::NUMBER;
822- result.value.FLOAT += iv.value.FLOAT;
823+ result.value += iv.value;
824 op = UnitType::NONOP;
825 break;
826 case UnitType::SUB:
827 result.type = UnitType::NUMBER;
828- result.value.FLOAT -= iv.value.FLOAT;
829+ result.value -= iv.value;
830 op = UnitType::NONOP;
831 break;
832 case UnitType::DIV:
833 result.type = UnitType::NUMBER;
834- result.value.FLOAT /= iv.value.FLOAT;
835+ result.value /= iv.value;
836 op = UnitType::NONOP;
837 break;
838 case UnitType::MULT:
839 result.type = UnitType::NUMBER;
840- result.value.FLOAT *= iv.value.FLOAT;
841+ result.value *= iv.value;
842 op = UnitType::NONOP;
843 break;
844 case UnitType::LT:
845 result.type = UnitType::BOOL;
846- result.value.BOOL = result.value.FLOAT < iv.value.FLOAT;
847+ result.value = result.value < iv.value;
848 op = UnitType::NONOP;
849 break;
850 case UnitType::GT:
851 result.type = UnitType::BOOL;
852- result.value.BOOL = result.value.FLOAT > iv.value.FLOAT;
853+ result.value = result.value > iv.value;
854 op = UnitType::NONOP;
855 break;
856 case UnitType::LE:
857 result.type = UnitType::BOOL;
858- result.value.BOOL = result.value.FLOAT <= iv.value.FLOAT;
859+ result.value = result.value <= iv.value;
860 op = UnitType::NONOP;
861 break;
862 case UnitType::GE:
863 result.type = UnitType::BOOL;
864- result.value.BOOL = result.value.FLOAT >= iv.value.FLOAT;
865+ result.value = result.value >= iv.value;
866 op = UnitType::NONOP;
867 break;
868 case UnitType::EQ:
869 result.type = UnitType::BOOL;
870- result.value.BOOL = result.value.FLOAT == iv.value.FLOAT;
871+ result.value = result.value == iv.value;
872 op = UnitType::NONOP;
873 break;
874 case UnitType::AND:
875 result.type = UnitType::BOOL;
876- result.value.BOOL = result.value.FLOAT && iv.value.FLOAT;
877+ result.value = result.value && iv.value;
878 op = UnitType::NONOP;
879 break;
880 case UnitType::OR:
881 result.type = UnitType::BOOL;
882- result.value.BOOL = result.value.FLOAT || iv.value.FLOAT;
883+ result.value = result.value || iv.value;
884 op = UnitType::NONOP;
885 break;
886 case UnitType::NOT:
887 result.type = UnitType::BOOL;
888- result.value.BOOL = !iv.value.FLOAT;
889+ result.value = !iv.value;
890 op = UnitType::NONOP;
891 break;
892 default:
893diff --git a/src/parser.cc b/src/parser.cc
894index b92c0b3..6508b7f 100755
895--- a/src/parser.cc
896+++ b/src/parser.cc
897@@ -7,6 +7,8 @@
898 #include <algorithm>
899 #include <cmath>
900 #include <string_view>
901+#include <bit>
902+#include <cstdint>
903
904 struct SymbolTable {
905 std::unordered_map<std::string, int> table{};
906@@ -1050,6 +1052,7 @@ static const std::unordered_map<std::string_view, UnitType> kFunc{
907 {"var", UnitType::VAR},
908 {"print", UnitType::PRINT},
909 {"list", UnitType::LIST},
910+ {"at", UnitType::AT},
911 {"", UnitType::GROUP}
912 };
913
914@@ -1085,7 +1088,7 @@ std::vector<Unit> getUnit(std::string value, SymbolTable* externalTable = nullpt
915 for (size_t j = 0; j < str_buffer.length(); j++) {
916 Unit unit{};
917 unit.type = UnitType::STRING;
918- unit.value.CHAR = str_buffer[j];
919+ unit.value = str_buffer[j];
920 units.push_back(unit);
921 }
922
923@@ -1093,7 +1096,7 @@ std::vector<Unit> getUnit(std::string value, SymbolTable* externalTable = nullpt
924
925 Unit unit{};
926 unit.type = UnitType::STRING_TERM;
927- unit.value.INT = str_buffer.length();
928+ unit.value = str_buffer.length();
929 units.push_back(unit);
930
931 inQuotes = false;
932@@ -1143,7 +1146,7 @@ std::vector<Unit> getUnit(std::string value, SymbolTable* externalTable = nullpt
933 }
934
935 // The value of the function is the child count
936- unit.value.INT = children.size();
937+ unit.value = children.size();
938
939 units.push_back(unit);
940 units.insert(units.end(), children.begin(), children.end());
941@@ -1168,16 +1171,16 @@ std::vector<Unit> getUnit(std::string value, SymbolTable* externalTable = nullpt
942 Color Matching
943 */
944 unit.type = UnitType::HEX;
945- unit.value.UINT = it->second;
946+ unit.value = it->second;
947 } else {
948 bool found = false;
949 for (const auto& [suffix, type, trim] : sufMatch) {
950 if (buffer.ends_with(suffix)) {
951 found = true;
952 try {
953- unit.value.FLOAT = std::stof(std::string(buffer.substr(0, buffer.size() - trim)));
954+ unit.value = std::stof(std::string(buffer.substr(0, buffer.size() - trim)));
955 } catch (...) {
956- unit.value.FLOAT = 0.0f;
957+ unit.value = 0.0f;
958 }
959
960 unit.type = type;
961@@ -1191,23 +1194,23 @@ std::vector<Unit> getUnit(std::string value, SymbolTable* externalTable = nullpt
962 # Prefix for HEX codes
963 */
964 unit.type = UnitType::HEX;
965- unit.value.UINT = std::stoul(buffer.substr(1), nullptr, 16);
966+ unit.value = std::bit_cast<float>(static_cast<uint32_t>(std::stoul(buffer.substr(1), nullptr, 16)));
967 } else if (auto it = kAbsSize.find(buffer); it != kAbsSize.end()) {
968 /*
969 Absolute size matching
970 */
971 unit.type = UnitType::EM;
972- unit.value.FLOAT = it->second;
973+ unit.value = it->second;
974 } else if (buffer == "true") {
975 unit.type = UnitType::BOOL;
976- unit.value.BOOL = true;
977+ unit.value = true;
978 } else if (buffer == "false") {
979 unit.type = UnitType::BOOL;
980- unit.value.BOOL = false;
981+ unit.value = false;
982 } else {
983 // Maybe its a number?
984 try {
985- unit.value.FLOAT = std::stof(buffer);
986+ unit.value = std::stof(buffer);
987 unit.type = UnitType::NUMBER;
988 } catch (...) {
989 // If we are here it is not a known parsable word, this could be a typo
990@@ -1215,7 +1218,7 @@ std::vector<Unit> getUnit(std::string value, SymbolTable* externalTable = nullpt
991 // parsed but not size.
992 if (!buffer.empty() && buffer.find_first_not_of(' ') != std::string::npos) {
993 unit.type = UnitType::VAR;
994- unit.value.INT = table.get(buffer);
995+ unit.value = table.get(buffer);
996 } else {
997 continue;
998 }
999diff --git a/tests/unitvalue.cc b/tests/unitvalue.cc
1000index 6bd824d..7b396c2 100644
1001--- a/tests/unitvalue.cc
1002+++ b/tests/unitvalue.cc
1003@@ -96,11 +96,11 @@ TEST_CASE("BENCH") {
1004
1005 Memory m;
1006 // Preset width, height, and em
1007- m.push_back(sym.get("width"),{UnitType::NUMBER, {.FLOAT = 1000.0f}});
1008- m.push_back(sym.get("height"),{UnitType::NUMBER, {.FLOAT = 700.0f}});
1009- m.push_back(sym.get("em"),{UnitType::NUMBER, {.FLOAT= 16.0f}});
1010+ m.push_back(sym.get("width"),{UnitType::NUMBER, 1000.0f});
1011+ m.push_back(sym.get("height"),{UnitType::NUMBER, 700.0f});
1012+ m.push_back(sym.get("em"),{UnitType::NUMBER, 16.0f});
1013
1014- std::vector<Unit> units = getUnit("let(x 10px) set(x (x + 100)) (min(5 x) * 2)", &sym);
1015+ std::vector<Unit> units = getUnit("list(x 5 2 3 4) set(at(x 0) 13)", &sym);
1016
1017 Snapshot s = m.save();
1018