Reduct  v1.0.4-3-gdaf0d70
A functional and immutable language.
Loading...
Searching...
No Matches
standard_impl.h
Go to the documentation of this file.
1#ifndef REDUCT_STDLIB_IMPL_H
2#define REDUCT_STDLIB_IMPL_H 1
3
4#include "char.h"
5#include "compile.h"
6#include "core.h"
7#include "defs.h"
8#include "eval.h"
9#include "gc.h"
10#include "handle.h"
11#include "item.h"
12#include "native.h"
13#include "parse.h"
14#include "standard.h"
15#include "stringify.h"
16
18{
19 REDUCT_ASSERT(reduct != REDUCT_NULL);
20
21 if (!REDUCT_HANDLE_IS_TRUTHY(cond))
22 {
23 char* str;
24 reduct_size_t len;
25 reduct_handle_get_string_params(reduct, msg, &str, &len);
26 REDUCT_ERROR_RUNTIME(reduct, "assert failed: %s", str);
27 }
28
29 return *cond;
30}
31
33{
34 REDUCT_ASSERT(reduct != REDUCT_NULL);
35
36 char* str;
37 reduct_size_t len;
38 reduct_handle_get_string_params(reduct, msg, &str, &len);
39 REDUCT_ERROR_RUNTIME(reduct, "%s", str);
40
41 return reduct_handle_nil(reduct);
42}
43
45{
46 REDUCT_ASSERT(reduct != REDUCT_NULL);
47
48 REDUCT_ERROR_CHECK_CALLABLE(reduct, callable, "try");
49 REDUCT_ERROR_CHECK_CALLABLE(reduct, catchFn, "try");
50
51 reduct_error_t* prev = reduct->error;
52
54 if (REDUCT_ERROR_CATCH(&error))
55 {
58 reduct_handle_t result = reduct_eval_call(reduct, *catchFn, 1, &msg);
59 reduct->error = prev;
60 return result;
61 }
62
63 reduct_handle_t result = reduct_eval_call(reduct, *callable, 0, REDUCT_NULL);
64 reduct->error = prev;
65 return result;
66}
67
69{
70 REDUCT_ASSERT(reduct != REDUCT_NULL);
71 REDUCT_ERROR_CHECK_LIST(reduct, list, "map");
72 REDUCT_ERROR_CHECK_CALLABLE(reduct, callable, "map");
73
74 reduct_item_t* listItem = REDUCT_HANDLE_TO_ITEM(list);
75
76 reduct_list_t* mappedList = reduct_list_new(reduct);
77 reduct_handle_t mappedHandle = REDUCT_HANDLE_FROM_LIST(mappedList);
78 REDUCT_GC_RETAIN(reduct, mappedHandle);
79
80 reduct_handle_t entry;
81 REDUCT_LIST_FOR_EACH(&entry, &listItem->list)
82 {
83 reduct_handle_t result = reduct_eval_call(reduct, *callable, 1, &entry);
84 reduct_list_append(reduct, mappedList, result);
85 }
86
87 REDUCT_GC_RELEASE(reduct, mappedHandle);
88 return mappedHandle;
89}
90
92{
93 REDUCT_ASSERT(reduct != REDUCT_NULL);
94 REDUCT_ERROR_CHECK_LIST(reduct, list, "filter");
95 REDUCT_ERROR_CHECK_CALLABLE(reduct, callable, "filter");
96
97 reduct_item_t* listItem = REDUCT_HANDLE_TO_ITEM(list);
98
99 reduct_list_t* filteredList = reduct_list_new(reduct);
100 reduct_handle_t filteredHandle = REDUCT_HANDLE_FROM_LIST(filteredList);
101 REDUCT_GC_RETAIN(reduct, filteredHandle);
102
103 reduct_handle_t entry;
104 REDUCT_LIST_FOR_EACH(&entry, &listItem->list)
105 {
106 reduct_handle_t result = reduct_eval_call(reduct, *callable, 1, &entry);
107 if (REDUCT_HANDLE_IS_TRUTHY(&result))
108 {
109 reduct_list_append(reduct, filteredList, entry);
110 }
111 }
112
113 REDUCT_GC_RELEASE(reduct, filteredHandle);
114 return filteredHandle;
115}
116
118 reduct_handle_t* callable)
119{
120 REDUCT_ASSERT(reduct != REDUCT_NULL);
121 REDUCT_ERROR_CHECK_LIST(reduct, list, "reduce");
122 REDUCT_ERROR_CHECK_CALLABLE(reduct, callable, "reduce");
123
124 reduct_item_t* listItem = REDUCT_HANDLE_TO_ITEM(list);
125 reduct_handle_t accumulator = (initial != REDUCT_NULL) ? *initial : REDUCT_HANDLE_NONE;
126
127 reduct_handle_t entry;
128 REDUCT_LIST_FOR_EACH(&entry, &listItem->list)
129 {
130 if (accumulator == REDUCT_HANDLE_NONE)
131 {
132 accumulator = entry;
133 REDUCT_GC_RETAIN(reduct, accumulator);
134 continue;
135 }
136
137 reduct_handle_t args[2] = {accumulator, entry};
138 reduct_handle_t result = reduct_eval_call(reduct, *callable, 2, args);
139 REDUCT_GC_RETAIN(reduct, result);
140
141 REDUCT_GC_RELEASE(reduct, accumulator);
142 accumulator = result;
143 }
144
145 if (accumulator == REDUCT_HANDLE_NONE)
146 {
147 return reduct_handle_nil(reduct);
148 }
149
150 REDUCT_GC_RELEASE(reduct, accumulator);
151 return accumulator;
152}
153
155{
156 REDUCT_ASSERT(reduct != REDUCT_NULL);
157 REDUCT_ERROR_CHECK_LIST(reduct, list, "apply");
158 REDUCT_ERROR_CHECK_CALLABLE(reduct, callable, "apply");
159
160 reduct_item_t* listItem = REDUCT_HANDLE_TO_ITEM(list);
161 reduct_size_t len = listItem->length;
162 if (len == 0)
163 {
164 return reduct_eval_call(reduct, *callable, 0, REDUCT_NULL);
165 }
166
169 ? stackBuffer
171
172 if (argv == REDUCT_NULL)
173 {
174 REDUCT_ERROR_INTERNAL(reduct, "out of memory");
175 }
176
177 reduct_handle_t entry;
178 REDUCT_LIST_FOR_EACH(&entry, &listItem->list)
179 {
180 argv[_iter.index - 1] = entry;
181 }
182
183 reduct_handle_t result = reduct_eval_call(reduct, *callable, len, argv);
184
185 if (argv != stackBuffer)
186 {
187 REDUCT_FREE(argv);
188 }
189
190 return result;
191}
192
194{
195 if (fn == REDUCT_HANDLE_NONE)
196 {
197 return *arg;
198 }
199 else
200 {
201 return reduct_eval_call(reduct, fn, 1, arg);
202 }
203}
204
205#define REDUCT_ANY_ALL_IMPL(_name, _predicate, _default) \
206 REDUCT_API reduct_handle_t _name(reduct_t* reduct, reduct_handle_t* list, reduct_handle_t* callable) \
207 { \
208 REDUCT_ASSERT(reduct != REDUCT_NULL); \
209 REDUCT_ERROR_CHECK_LIST(reduct, list, #_name); \
210 reduct_item_t* listItem = REDUCT_HANDLE_TO_ITEM(list); \
211 reduct_handle_t fn = (callable != REDUCT_NULL) ? *callable : REDUCT_HANDLE_NONE; \
212 reduct_handle_t entry; \
213 REDUCT_LIST_FOR_EACH(&entry, &listItem->list) \
214 { \
215 reduct_handle_t result = reduct_eval_maybe_call(reduct, fn, &entry); \
216 REDUCT_GC_RETAIN(reduct, result); \
217 if (_predicate) \
218 { \
219 REDUCT_GC_RELEASE(reduct, result); \
220 return REDUCT_HANDLE_FROM_INT(!(_default)); \
221 } \
222 REDUCT_GC_RELEASE(reduct, result); \
223 } \
224 return REDUCT_HANDLE_FROM_INT(_default); \
225 }
226
229
232{
233 reduct_size_t i = left;
234 reduct_size_t j = right;
235
236 for (reduct_size_t k = left; k < end; k++)
237 {
238 reduct_bool_t useLeft = REDUCT_FALSE;
239 if (i < right)
240 {
241 if (j >= end)
242 {
243 useLeft = REDUCT_TRUE;
244 }
245 else
246 {
247 if (callable != REDUCT_HANDLE_NONE)
248 {
249 reduct_handle_t args[2] = {a[i], a[j]};
250 reduct_handle_t res = reduct_eval_call(reduct, callable, 2, args);
251 if (REDUCT_HANDLE_IS_TRUTHY(&res))
252 {
253 useLeft = REDUCT_TRUE;
254 }
255 }
256 else
257 {
258 if (reduct_handle_compare(reduct, &a[i], &a[j]) <= 0)
259 {
260 useLeft = REDUCT_TRUE;
261 }
262 }
263 }
264 }
265
266 if (useLeft)
267 {
268 b[k] = a[i];
269 i++;
270 }
271 else
272 {
273 b[k] = a[j];
274 j++;
275 }
276 }
277}
278
280{
281 REDUCT_ASSERT(reduct != REDUCT_NULL);
282 REDUCT_ASSERT(listHandle != REDUCT_NULL);
283
284 REDUCT_ERROR_CHECK_LIST(reduct, listHandle, "sort");
285 reduct_item_t* list = REDUCT_HANDLE_TO_ITEM(listHandle);
286
287 reduct_handle_t callable = (callableHandle != REDUCT_NULL) ? *callableHandle : REDUCT_HANDLE_NONE;
288 if (callable != REDUCT_HANDLE_NONE)
289 {
290 REDUCT_ERROR_CHECK_CALLABLE(reduct, &callable, "sort");
291 }
292
293 reduct_size_t len = list->length;
294 if (len <= 1)
295 {
296 return *listHandle;
297 }
298
300 if (a == REDUCT_NULL)
301 {
302 REDUCT_ERROR_INTERNAL(reduct, "out of memory");
303 }
304
306 if (b == REDUCT_NULL)
307 {
308 REDUCT_FREE(a);
309 REDUCT_ERROR_INTERNAL(reduct, "out of memory");
310 }
311
312 reduct_handle_t entry;
313 REDUCT_LIST_FOR_EACH(&entry, &list->list)
314 {
315 a[_iter.index - 1] = entry;
316 }
317
318 reduct_handle_t* src = a;
319 reduct_handle_t* dst = b;
320 for (reduct_size_t width = 1; width < list->length; width *= 2)
321 {
322 for (reduct_size_t i = 0; i < list->length; i += 2 * width)
323 {
324 reduct_size_t left = i;
325 reduct_size_t right = REDUCT_MIN(i + width, len);
326 reduct_size_t end = REDUCT_MIN(i + 2 * width, len);
327 reduct_sort_merge(reduct, callable, src, left, right, end, dst);
328 }
329 reduct_handle_t* temp = src;
330 src = dst;
331 dst = temp;
332 }
333
334 reduct_list_t* resultList = reduct_list_new(reduct);
335 reduct_handle_t resultHandle = REDUCT_HANDLE_FROM_LIST(resultList);
336 REDUCT_GC_RETAIN(reduct, resultHandle);
337
338 for (reduct_size_t i = 0; i < len; i++)
339 {
340 reduct_list_append(reduct, resultList, src[i]);
341 }
342
343 REDUCT_FREE(a);
344 REDUCT_FREE(b);
345 REDUCT_GC_RELEASE(reduct, resultHandle);
346 return resultHandle;
347}
348
350 reduct_size_t length)
351{
352 reduct_handle_t nHandle = reduct_get_int(reduct, index);
354 if (n < 0)
355 {
356 n = (reduct_int64_t)length + n;
357 }
358 return n;
359}
360
362 reduct_size_t length, reduct_size_t* outStart, reduct_size_t* outEnd)
363{
364 reduct_int64_t start = reduct_handle_normalize_index(reduct, startH, length);
365 reduct_int64_t end;
366
367 if (endH != REDUCT_NULL)
368 {
369 end = reduct_handle_normalize_index(reduct, endH, length);
370 }
371 else
372 {
373 end = (reduct_int64_t)length;
374 }
375
376 start = REDUCT_MAX(0, REDUCT_MIN(start, (reduct_int64_t)length));
377 end = REDUCT_MAX(0, REDUCT_MIN(end, (reduct_int64_t)length));
378
379 *outStart = (reduct_size_t)start;
380 *outEnd = (reduct_size_t)end;
381}
382
384{
385 reduct_handle_t entryH;
386 REDUCT_LIST_FOR_EACH(&entryH, &listItem->list)
387 {
388 if (REDUCT_HANDLE_IS_LIST(&entryH))
389 {
390 reduct_item_t* entry = REDUCT_HANDLE_TO_ITEM(&entryH);
391 if (entry->length >= 1)
392 {
393 reduct_handle_t entryKey = reduct_list_nth(reduct, &entry->list, 0);
394 if (reduct_handle_compare(reduct, &entryKey, key) == 0)
395 {
396 return entryH;
397 }
398 }
399 }
400 }
401 return REDUCT_HANDLE_NONE;
402}
403
405 reduct_handle_t* outVal)
406{
407 if (!REDUCT_HANDLE_IS_LIST(entryH))
408 {
409 return REDUCT_FALSE;
410 }
411 reduct_item_t* entry = REDUCT_HANDLE_TO_ITEM(entryH);
412 if (entry->length < 1)
413 {
414 return REDUCT_FALSE;
415 }
416
417 if (outKey != REDUCT_NULL)
418 {
419 *outKey = reduct_list_nth(reduct, &entry->list, 0);
420 }
421
422 if (outVal != REDUCT_NULL)
423 {
424 *outVal = (entry->length >= 2) ? reduct_list_nth(reduct, &entry->list, 1) : reduct_handle_nil(reduct);
425 }
426 return REDUCT_TRUE;
427}
428
430{
431 REDUCT_ASSERT(reduct != REDUCT_NULL);
432 REDUCT_ASSERT(argv != REDUCT_NULL || argc == 0);
433
434 reduct_size_t total = 0;
435 for (reduct_size_t i = 0; i < argc; i++)
436 {
437 total += reduct_handle_item(reduct, &argv[i])->length;
438 }
439 return REDUCT_HANDLE_FROM_INT(total);
440}
441
443 reduct_handle_t* step)
444{
445 REDUCT_ASSERT(reduct != REDUCT_NULL);
446
447 reduct_handle_t startH = reduct_get_int(reduct, start);
448 reduct_handle_t endH = reduct_get_int(reduct, end);
449 reduct_handle_t stepH = (step != REDUCT_NULL) ? reduct_get_int(reduct, step) : REDUCT_HANDLE_FROM_INT(1);
450
451 reduct_int64_t startVal = REDUCT_HANDLE_TO_INT(&startH);
452 reduct_int64_t endVal = REDUCT_HANDLE_TO_INT(&endH);
453 reduct_int64_t stepVal = REDUCT_HANDLE_TO_INT(&stepH);
454
455 if (stepVal == 0)
456 {
457 REDUCT_ERROR_RUNTIME(reduct, "range step cannot be 0");
458 }
459
460 reduct_size_t count = 0;
461 if (stepVal > 0)
462 {
463 if (endVal > startVal)
464 {
465 count = (reduct_size_t)((endVal - startVal + stepVal - 1) / stepVal);
466 }
467 }
468 else
469 {
470 if (startVal > endVal)
471 {
472 count = (reduct_size_t)((startVal - endVal - stepVal - 1) / -stepVal);
473 }
474 }
475
476 reduct_list_t* list = reduct_list_new(reduct);
477 reduct_handle_t listHandle = REDUCT_HANDLE_FROM_LIST(list);
478 REDUCT_GC_RETAIN(reduct, listHandle);
479
480 reduct_int64_t current = startVal;
481 for (reduct_size_t i = 0; i < count; i++)
482 {
483 reduct_list_append(reduct, list, REDUCT_HANDLE_FROM_INT(current));
484 current += stepVal;
485 }
486
487 REDUCT_GC_RELEASE(reduct, listHandle);
488 return listHandle;
489}
490
492{
493 REDUCT_ASSERT(reduct != REDUCT_NULL);
494 REDUCT_ASSERT(argv != REDUCT_NULL || argc == 0);
495
496 reduct_bool_t resultIsList = REDUCT_FALSE;
497 reduct_size_t totalLen = 0;
498
499 for (reduct_size_t i = 0; i < argc; i++)
500 {
501 if (REDUCT_HANDLE_IS_LIST(&argv[i]))
502 {
503 resultIsList = REDUCT_TRUE;
504 }
505 totalLen += reduct_handle_item(reduct, &argv[i])->length;
506 }
507
508 if (resultIsList)
509 {
510 reduct_list_t* newList = reduct_list_new(reduct);
511 reduct_handle_t newHandle = REDUCT_HANDLE_FROM_LIST(newList);
512 REDUCT_GC_RETAIN(reduct, newHandle);
513
514 for (reduct_size_t i = 0; i < argc; i++)
515 {
516 if (REDUCT_HANDLE_IS_LIST(&argv[i]))
517 {
518 reduct_list_append_list(reduct, newList, &REDUCT_HANDLE_TO_ITEM(&argv[i])->list);
519 }
520 else
521 {
522 reduct_list_append(reduct, newList, argv[i]);
523 }
524 }
525
526 REDUCT_GC_RELEASE(reduct, newHandle);
527 return newHandle;
528 }
529
530 REDUCT_SCRATCH_BUFFER(buffer, totalLen);
531
532 reduct_size_t currentPos = 0;
533 for (reduct_size_t i = 0; i < argc; i++)
534 {
535 char* str;
536 reduct_size_t len;
537 reduct_handle_get_string_params(reduct, &argv[i], &str, &len);
538 REDUCT_MEMCPY(buffer + currentPos, str, len);
539 currentPos += len;
540 }
541
542 reduct_handle_t result =
545 return result;
546}
547
549{
550 reduct_item_t* item = reduct_handle_item(reduct, handle);
551
552 if (item->length == 0)
553 {
554 return reduct_handle_nil(reduct);
555 }
556
557 reduct_size_t index = first ? 0 : item->length - 1;
558
559 if (item->type == REDUCT_ITEM_TYPE_LIST)
560 {
561 return reduct_list_nth(reduct, &item->list, index);
562 }
563 else
564 {
566 reduct_atom_lookup(reduct, item->atom.string + index, 1, REDUCT_ATOM_LOOKUP_NONE));
567 }
568}
569
571{
572 REDUCT_ASSERT(reduct != REDUCT_NULL);
573 REDUCT_ERROR_CHECK_SEQUENCE(reduct, handle, "first");
574 return reduct_sequence_edge(reduct, handle, REDUCT_TRUE);
575}
576
578{
579 REDUCT_ASSERT(reduct != REDUCT_NULL);
580 REDUCT_ERROR_CHECK_SEQUENCE(reduct, handle, "last");
581 return reduct_sequence_edge(reduct, handle, REDUCT_FALSE);
582}
583
585{
586 reduct_item_t* item = reduct_handle_item(reduct, handle);
587
588 if (item->length <= 1)
589 {
590 return reduct_handle_nil(reduct);
591 }
592
593 reduct_size_t start = rest ? 1 : 0;
594 reduct_size_t end = rest ? item->length : item->length - 1;
595
596 if (item->type == REDUCT_ITEM_TYPE_LIST)
597 {
598 return REDUCT_HANDLE_FROM_LIST(reduct_list_slice(reduct, &item->list, start, end));
599 }
600 else
601 {
603 reduct_atom_lookup(reduct, item->atom.string + start, end - start, REDUCT_ATOM_LOOKUP_NONE));
604 }
605}
606
608{
609 REDUCT_ASSERT(reduct != REDUCT_NULL);
610 REDUCT_ERROR_CHECK_SEQUENCE(reduct, handle, "rest");
611 return reduct_sequence_trim(reduct, handle, REDUCT_TRUE);
612}
613
615{
616 REDUCT_ASSERT(reduct != REDUCT_NULL);
617 REDUCT_ERROR_CHECK_SEQUENCE(reduct, handle, "init");
618 return reduct_sequence_trim(reduct, handle, REDUCT_FALSE);
619}
620
622 reduct_handle_t* defaultVal)
623{
624 REDUCT_ASSERT(reduct != REDUCT_NULL);
625 REDUCT_ERROR_CHECK_SEQUENCE(reduct, handle, "nth");
626
627 reduct_item_t* item = reduct_handle_item(reduct, handle);
628
629 reduct_int64_t n = reduct_handle_normalize_index(reduct, index, item->length);
630
631 if (n < 0 || n >= (reduct_int64_t)item->length)
632 {
633 return (defaultVal != REDUCT_NULL) ? *defaultVal : reduct_handle_nil(reduct);
634 }
635
636 if (item->type == REDUCT_ITEM_TYPE_LIST)
637 {
638 return reduct_list_nth(reduct, &item->list, (reduct_size_t)n);
639 }
640 else
641 {
643 }
644}
645
646static inline char reduct_handle_get_char(reduct_t* reduct, reduct_handle_t* handle, char defaultChar)
647{
648 char* str;
649 reduct_size_t len;
650 reduct_handle_get_string_params(reduct, handle, &str, &len);
651 return (len > 0) ? str[0] : defaultChar;
652}
653
655 reduct_handle_t* value, reduct_handle_t* fillVal)
656{
657 REDUCT_ASSERT(reduct != REDUCT_NULL);
658
659 reduct_item_t* item = reduct_handle_item(reduct, handle);
660
661 reduct_int64_t n = reduct_handle_normalize_index(reduct, index, item->length);
662 if (n < 0)
663 {
664 n = 0;
665 }
666
667 reduct_size_t targetIndex = (reduct_size_t)n;
668
669 if (targetIndex >= item->length && fillVal == REDUCT_NULL)
670 {
671 REDUCT_ERROR_RUNTIME(reduct, "assoc index %zu out of bounds", targetIndex);
672 }
673
674 switch (item->type)
675 {
677 {
678 if (targetIndex < item->length)
679 {
680 reduct_list_t* newList = reduct_list_assoc(reduct, &item->list, targetIndex, *value);
681 return REDUCT_HANDLE_FROM_LIST(newList);
682 }
683
684 reduct_list_t* newList = reduct_list_new(reduct);
685 reduct_handle_t newListH = REDUCT_HANDLE_FROM_LIST(newList);
686 REDUCT_GC_RETAIN(reduct, newListH);
687 reduct_list_append_list(reduct, newList, &item->list);
688 for (reduct_size_t i = item->length; i < targetIndex; i++)
689 {
690 reduct_list_append(reduct, newList, *fillVal);
691 }
692 reduct_list_append(reduct, newList, *value);
693 REDUCT_GC_RELEASE(reduct, newListH);
694 return newListH;
695 }
697 {
698 char charToPut = reduct_handle_get_char(reduct, value, '\0');
699 char padChar = (fillVal != REDUCT_NULL) ? reduct_handle_get_char(reduct, fillVal, ' ') : ' ';
700
701 reduct_size_t newLen = REDUCT_MAX(item->length, targetIndex + 1);
702
703 REDUCT_SCRATCH_BUFFER(buffer, newLen);
704
705 reduct_size_t prefixLen = REDUCT_MIN(item->length, targetIndex);
706 REDUCT_MEMCPY(buffer, item->atom.string, prefixLen);
707 for (reduct_size_t i = item->length; i < targetIndex; i++)
708 {
709 buffer[i] = padChar;
710 }
711 buffer[targetIndex] = charToPut;
712 if (targetIndex + 1 < item->length)
713 {
714 reduct_size_t suffixLen = item->length - (targetIndex + 1);
715 REDUCT_MEMCPY(buffer + targetIndex + 1, item->atom.string + targetIndex + 1, suffixLen);
716 }
717
718 reduct_handle_t result =
721 return result;
722 }
723 default:
724 REDUCT_ERROR_RUNTIME(reduct, "assoc expected list or atom, got %s", reduct_item_type_str(item->type));
725 }
726}
727
729{
730 REDUCT_ASSERT(reduct != REDUCT_NULL);
731
732 reduct_item_t* item = reduct_handle_item(reduct, handle);
733
734 reduct_int64_t n = reduct_handle_normalize_index(reduct, index, item->length);
735
736 if (n < 0 || n >= (reduct_int64_t)item->length)
737 {
738 return *handle;
739 }
740
741 reduct_size_t targetIndex = (reduct_size_t)n;
742 reduct_size_t newLen = item->length - 1;
743
744 switch (item->type)
745 {
747 {
748 reduct_list_t* newList = reduct_list_dissoc(reduct, &item->list, targetIndex);
749 return REDUCT_HANDLE_FROM_LIST(newList);
750 }
752 {
753 REDUCT_SCRATCH_BUFFER(buffer, newLen);
754
755 REDUCT_MEMCPY(buffer, item->atom.string, targetIndex);
756 REDUCT_MEMCPY(buffer + targetIndex, item->atom.string + targetIndex + 1, item->length - targetIndex - 1);
757
758 reduct_handle_t result =
761 return result;
762 }
763 default:
764 REDUCT_ERROR_RUNTIME(reduct, "dissoc expected list or atom, got %s", reduct_item_type_str(item->type));
765 }
766}
767
769 reduct_handle_t* callable, reduct_handle_t* fillVal)
770{
771 REDUCT_ASSERT(reduct != REDUCT_NULL);
772
773 reduct_item_t* item = reduct_handle_item(reduct, handle);
774
775 reduct_int64_t targetIndex = reduct_handle_normalize_index(reduct, index, item->length);
776 if (targetIndex < 0)
777 {
778 targetIndex = 0;
779 }
780
781 if ((reduct_size_t)targetIndex >= item->length && fillVal == REDUCT_NULL)
782 {
783 REDUCT_ERROR_RUNTIME(reduct, "update index %lld out of bounds", (long long)targetIndex);
784 }
785
786 reduct_handle_t currentVal = reduct_nth(reduct, handle, index, fillVal);
787 reduct_handle_t newVal = reduct_eval_call(reduct, *callable, 1, &currentVal);
788
789 return reduct_assoc(reduct, handle, index, &newVal, fillVal);
790}
791
793{
794 REDUCT_ASSERT(reduct != REDUCT_NULL);
795
796 reduct_item_t* item = reduct_handle_item(reduct, handle);
797
798 switch (item->type)
799 {
801 {
802 reduct_handle_t current;
803 REDUCT_LIST_FOR_EACH(&current, &item->list)
804 {
805 if (reduct_handle_compare(reduct, &current, target) == 0)
806 {
807 return REDUCT_HANDLE_FROM_INT(_iter.index - 1);
808 }
809 }
810 }
811 break;
813 {
814 char* targetStr;
815 reduct_size_t targetLen;
816 reduct_handle_get_string_params(reduct, target, &targetStr, &targetLen);
817
818 if (targetLen == 0)
819 {
820 return REDUCT_HANDLE_FROM_INT(0);
821 }
822
823 if (targetLen <= item->length)
824 {
825 for (reduct_size_t i = 0; i <= item->length - targetLen; i++)
826 {
827 if (REDUCT_MEMCMP(item->atom.string + i, targetStr, targetLen) == 0)
828 {
829 return REDUCT_HANDLE_FROM_INT(i);
830 }
831 }
832 }
833 break;
834 }
835 default:
836 REDUCT_ERROR_RUNTIME(reduct, "index-of expected list or atom, got %s", reduct_item_type_str(item->type));
837 }
838
839 return reduct_handle_nil(reduct);
840}
841
843{
844 REDUCT_ASSERT(reduct != REDUCT_NULL);
845
846 reduct_item_t* item = reduct_handle_item(reduct, handle);
847
848 if (item->length <= 1)
849 {
850 return *handle;
851 }
852
853 switch (item->type)
854 {
856 {
857 reduct_list_t* newList = reduct_list_new(reduct);
858 reduct_handle_t newHandle = REDUCT_HANDLE_FROM_LIST(newList);
859 REDUCT_GC_RETAIN(reduct, newHandle);
860
861 reduct_size_t i = item->length;
862 while (i > 0)
863 {
864 reduct_list_append(reduct, newList, reduct_list_nth(reduct, &item->list, --i));
865 }
866
867 REDUCT_GC_RELEASE(reduct, newHandle);
868 return newHandle;
869 }
871 {
872 REDUCT_SCRATCH_BUFFER(buffer, item->length);
873
874 for (reduct_size_t i = 0; i < item->length; i++)
875 {
876 buffer[i] = item->atom.string[item->length - 1 - i];
877 }
878
879 reduct_handle_t result =
882 return result;
883 }
884 default:
885 REDUCT_ERROR_RUNTIME(reduct, "reverse expected list or atom, got %s", reduct_item_type_str(item->type));
886 }
887}
888
890 reduct_handle_t* endH)
891{
892 REDUCT_ASSERT(reduct != REDUCT_NULL);
893 REDUCT_ASSERT(handle != REDUCT_NULL);
894 REDUCT_ASSERT(startH != REDUCT_NULL);
895
896 reduct_item_t* item = reduct_handle_item(reduct, handle);
897 reduct_size_t start, end;
898 reduct_sequence_normalize_range(reduct, startH, endH, item->length, &start, &end);
899
900 if (start >= end)
901 {
902 return reduct_handle_nil(reduct);
903 }
904
905 switch (item->type)
906 {
908 {
909 return REDUCT_HANDLE_FROM_LIST(reduct_list_slice(reduct, &item->list, start, end));
910 }
912 {
914 reduct_atom_lookup(reduct, item->atom.string + start, end - start, REDUCT_ATOM_LOOKUP_NONE));
915 }
916 default:
917 REDUCT_ERROR_RUNTIME(reduct, "slice expected list or atom, got %s", reduct_item_type_str(item->type));
918 }
919}
920
922{
923 REDUCT_ASSERT(reduct != REDUCT_NULL);
924
925 if (!REDUCT_HANDLE_IS_LIST(handle))
926 {
927 return *handle;
928 }
929
930 reduct_int64_t depth = -1;
931 if (depthH != REDUCT_NULL)
932 {
933 reduct_handle_t d = reduct_get_int(reduct, depthH);
934 depth = REDUCT_HANDLE_TO_INT(&d);
935 }
936
937 if (depth == 0)
938 {
939 return *handle;
940 }
941
942 reduct_item_t* item = REDUCT_HANDLE_TO_ITEM(handle);
943 reduct_list_t* newList = reduct_list_new(reduct);
944 reduct_handle_t newHandle = REDUCT_HANDLE_FROM_LIST(newList);
945 REDUCT_GC_RETAIN(reduct, newHandle);
946
947 reduct_handle_t current;
948 REDUCT_LIST_FOR_EACH(&current, &item->list)
949 {
950 if (REDUCT_HANDLE_IS_LIST(&current))
951 {
952 reduct_handle_t nextDepthH = REDUCT_HANDLE_FROM_INT(depth - 1);
953 reduct_handle_t flattened = reduct_flatten(reduct, &current, &nextDepthH);
954 REDUCT_GC_RETAIN(reduct, flattened);
955
956 if (REDUCT_HANDLE_IS_LIST(&flattened))
957 {
958 reduct_list_append_list(reduct, newList, &REDUCT_HANDLE_TO_ITEM(&flattened)->list);
959 }
960 else if (flattened != reduct_handle_nil(reduct))
961 {
962 reduct_list_append(reduct, newList, flattened);
963 }
964 REDUCT_GC_RELEASE(reduct, flattened);
965 }
966 else
967 {
968 reduct_list_append(reduct, newList, current);
969 }
970 }
971
972 REDUCT_GC_RELEASE(reduct, newHandle);
973 return newHandle;
974}
975
977{
978 REDUCT_ASSERT(reduct != REDUCT_NULL);
979 reduct_handle_t index = reduct_index_of(reduct, handle, target);
980 return REDUCT_HANDLE_FROM_BOOL(index != reduct_handle_nil(reduct));
981}
982
984 reduct_handle_t* newVal)
985{
986 REDUCT_ASSERT(reduct != REDUCT_NULL);
987 reduct_item_t* item = reduct_handle_item(reduct, handle);
988
989 switch (item->type)
990 {
992 {
993 reduct_list_t* newList = reduct_list_new(reduct);
994 reduct_handle_t newHandle = REDUCT_HANDLE_FROM_LIST(newList);
995 REDUCT_GC_RETAIN(reduct, newHandle);
996
997 reduct_handle_t entry;
998 REDUCT_LIST_FOR_EACH(&entry, &item->list)
999 {
1000 if (reduct_handle_compare(reduct, &entry, oldVal) == 0)
1001 {
1002 reduct_list_append(reduct, newList, *newVal);
1003 }
1004 else
1005 {
1006 reduct_list_append(reduct, newList, entry);
1007 }
1008 }
1009
1010 REDUCT_GC_RELEASE(reduct, newHandle);
1011 return newHandle;
1012 }
1014 {
1015 char* oldStr;
1016 reduct_size_t oldLen;
1017 reduct_handle_get_string_params(reduct, oldVal, &oldStr, &oldLen);
1018
1019 char* newStr;
1020 reduct_size_t newLen;
1021 reduct_handle_get_string_params(reduct, newVal, &newStr, &newLen);
1022
1023 if (oldLen == 0)
1024 {
1025 return *handle;
1026 }
1027
1028 reduct_size_t count = 0;
1029 for (reduct_size_t i = 0; i <= item->length - oldLen; i++)
1030 {
1031 if (REDUCT_MEMCMP(item->atom.string + i, oldStr, oldLen) == 0)
1032 {
1033 count++;
1034 i += oldLen - 1;
1035 }
1036 }
1037
1038 if (count == 0)
1039 {
1040 return *handle;
1041 }
1042
1043 reduct_size_t resultLen = item->length + (count * (newLen - oldLen));
1044 char* buffer = (char*)REDUCT_MALLOC(resultLen);
1045 if (buffer == REDUCT_NULL)
1046 {
1047 REDUCT_ERROR_INTERNAL(reduct, "out of memory");
1048 }
1049
1050 reduct_size_t currentPos = 0;
1051 for (reduct_size_t i = 0; i < item->length;)
1052 {
1053 if (i <= item->length - oldLen && REDUCT_MEMCMP(item->atom.string + i, oldStr, oldLen) == 0)
1054 {
1055 REDUCT_MEMCPY(buffer + currentPos, newStr, newLen);
1056 currentPos += newLen;
1057 i += oldLen;
1058 }
1059 else
1060 {
1061 buffer[currentPos++] = item->atom.string[i++];
1062 }
1063 }
1064
1065 reduct_handle_t result =
1067 REDUCT_FREE(buffer);
1068 return result;
1069 }
1070 default:
1071 REDUCT_ERROR_RUNTIME(reduct, "replace expected list or atom, got %s", reduct_item_type_str(item->type));
1072 }
1073}
1074
1076{
1077 REDUCT_ASSERT(reduct != REDUCT_NULL);
1078 if (!REDUCT_HANDLE_IS_LIST(handle))
1079 {
1080 return *handle;
1081 }
1082
1083 reduct_item_t* item = REDUCT_HANDLE_TO_ITEM(handle);
1084 reduct_list_t* newList = reduct_list_new(reduct);
1085 reduct_handle_t resultHandle = REDUCT_HANDLE_FROM_LIST(newList);
1086 REDUCT_GC_RETAIN(reduct, resultHandle);
1087
1088 reduct_handle_t current;
1089 REDUCT_LIST_FOR_EACH(&current, &item->list)
1090 {
1092 reduct_handle_t existing;
1093 REDUCT_LIST_FOR_EACH(&existing, newList)
1094 {
1095 if (reduct_handle_compare(reduct, &current, &existing) == 0)
1096 {
1097 found = REDUCT_TRUE;
1098 break;
1099 }
1100 }
1101
1102 if (!found)
1103 {
1104 reduct_list_append(reduct, newList, current);
1105 }
1106 }
1107
1108 REDUCT_GC_RELEASE(reduct, resultHandle);
1109 return resultHandle;
1110}
1111
1113{
1114 REDUCT_ASSERT(reduct != REDUCT_NULL);
1115 if (!REDUCT_HANDLE_IS_LIST(handle))
1116 {
1117 return *handle;
1118 }
1119
1120 reduct_handle_t nHandle = reduct_get_int(reduct, sizeH);
1122
1123 if (n <= 0)
1124 {
1125 REDUCT_ERROR_RUNTIME(reduct, "chunk size must be greater than 0");
1126 }
1127
1128 reduct_item_t* item = REDUCT_HANDLE_TO_ITEM(handle);
1129 reduct_list_t* resultList = reduct_list_new(reduct);
1130 reduct_handle_t resultHandle = REDUCT_HANDLE_FROM_LIST(resultList);
1131 REDUCT_GC_RETAIN(reduct, resultHandle);
1132
1133 reduct_size_t chunkSize = (reduct_size_t)n;
1134 for (reduct_size_t i = 0; i < item->length; i += chunkSize)
1135 {
1136 reduct_size_t end = REDUCT_MIN(i + chunkSize, item->length);
1137 reduct_list_t* chunk = reduct_list_slice(reduct, &item->list, i, end);
1138 reduct_list_append(reduct, resultList, REDUCT_HANDLE_FROM_LIST(chunk));
1139 }
1140
1141 REDUCT_GC_RELEASE(reduct, resultHandle);
1142 return resultHandle;
1143}
1144
1146{
1147 REDUCT_ASSERT(reduct != REDUCT_NULL);
1148 if (!REDUCT_HANDLE_IS_LIST(handle))
1149 {
1150 return reduct_handle_nil(reduct);
1151 }
1152
1153 reduct_item_t* item = REDUCT_HANDLE_TO_ITEM(handle);
1154 reduct_handle_t current;
1155 REDUCT_LIST_FOR_EACH(&current, &item->list)
1156 {
1157 reduct_handle_t result = reduct_eval_call(reduct, *callable, 1, &current);
1158 if (REDUCT_HANDLE_IS_TRUTHY(&result))
1159 {
1160 return current;
1161 }
1162 }
1163
1164 return reduct_handle_nil(reduct);
1165}
1166
1168 reduct_handle_t* defaultVal)
1169{
1170 REDUCT_ASSERT(reduct != REDUCT_NULL);
1171
1172 reduct_handle_t current = *list;
1173 reduct_handle_t pathH = *path;
1174
1175 if (!REDUCT_HANDLE_IS_LIST(&pathH))
1176 {
1177 reduct_item_t* item = reduct_handle_item(reduct, &current);
1178 if (item->type != REDUCT_ITEM_TYPE_LIST)
1179 {
1180 return (defaultVal != REDUCT_NULL) ? *defaultVal : reduct_handle_nil(reduct);
1181 }
1182
1183 reduct_handle_t entryH = reduct_list_find_entry(reduct, item, &pathH);
1184 if (entryH != REDUCT_HANDLE_NONE)
1185 {
1186 reduct_item_t* entry = REDUCT_HANDLE_TO_ITEM(&entryH);
1187 return (entry->length >= 2) ? reduct_list_nth(reduct, &entry->list, 1) : reduct_handle_nil(reduct);
1188 }
1189 return (defaultVal != REDUCT_NULL) ? *defaultVal : reduct_handle_nil(reduct);
1190 }
1191 reduct_item_t* pathItem = REDUCT_HANDLE_TO_ITEM(&pathH);
1192 reduct_handle_t key;
1193 REDUCT_LIST_FOR_EACH(&key, &pathItem->list)
1194 {
1195 current = reduct_get_in(reduct, &current, &key, REDUCT_NULL);
1196 if (current == reduct_handle_nil(reduct))
1197 {
1198 return (defaultVal != REDUCT_NULL) ? *defaultVal : reduct_handle_nil(reduct);
1199 }
1200 }
1201
1202 return current;
1203}
1204
1206 reduct_handle_t* val)
1207{
1208 REDUCT_ASSERT(reduct != REDUCT_NULL);
1209
1210 if (!REDUCT_HANDLE_IS_LIST(path))
1211 {
1212 reduct_item_t* listItem = reduct_handle_item(reduct, list);
1213 reduct_list_t* newList = reduct_list_new(reduct);
1214 reduct_handle_t targetEntry = reduct_list_find_entry(reduct, listItem, path);
1215
1216 reduct_handle_t entryH;
1217 REDUCT_LIST_FOR_EACH(&entryH, &listItem->list)
1218 {
1219 if (entryH == targetEntry)
1220 {
1221 reduct_list_t* newEntry = reduct_list_new(reduct);
1222 reduct_list_append(reduct, newEntry, *path);
1223 reduct_list_append(reduct, newEntry, *val);
1224 reduct_list_append(reduct, newList, REDUCT_HANDLE_FROM_LIST(newEntry));
1225 continue;
1226 }
1227 reduct_list_append(reduct, newList, entryH);
1228 }
1229
1230 if (targetEntry == REDUCT_HANDLE_NONE)
1231 {
1232 reduct_list_t* newEntry = reduct_list_new(reduct);
1233 reduct_list_append(reduct, newEntry, *path);
1234 reduct_list_append(reduct, newEntry, *val);
1235 reduct_list_append(reduct, newList, REDUCT_HANDLE_FROM_LIST(newEntry));
1236 }
1237
1238 return REDUCT_HANDLE_FROM_LIST(newList);
1239 }
1240
1241 reduct_item_t* pathItem = REDUCT_HANDLE_TO_ITEM(path);
1242 if (pathItem->length == 0)
1243 {
1244 return *val;
1245 }
1246
1247 reduct_handle_t firstKey = reduct_list_nth(reduct, &pathItem->list, 0);
1248 reduct_handle_t restPath;
1249
1250 if (pathItem->length == 1)
1251 {
1252 restPath = firstKey;
1253 return reduct_assoc_in(reduct, list, &restPath, val);
1254 }
1255 else
1256 {
1257 restPath = REDUCT_HANDLE_FROM_LIST(reduct_list_slice(reduct, &pathItem->list, 1, pathItem->length));
1258 REDUCT_GC_RETAIN(reduct, restPath);
1259
1260 reduct_handle_t subList = reduct_get_in(reduct, list, &firstKey, REDUCT_NULL);
1261 if (!REDUCT_HANDLE_IS_LIST(&subList))
1262 {
1263 subList = REDUCT_HANDLE_FROM_LIST(reduct_list_new(reduct));
1264 }
1265
1266 reduct_handle_t updatedSubList = reduct_assoc_in(reduct, &subList, &restPath, val);
1267 reduct_handle_t result = reduct_assoc_in(reduct, list, &firstKey, &updatedSubList);
1268
1269 REDUCT_GC_RELEASE(reduct, restPath);
1270 return result;
1271 }
1272}
1273
1275{
1276 REDUCT_ASSERT(reduct != REDUCT_NULL);
1277
1278 if (!REDUCT_HANDLE_IS_LIST(path))
1279 {
1280 reduct_item_t* listItem = reduct_handle_item(reduct, list);
1281 reduct_list_t* newList = reduct_list_new(reduct);
1282 reduct_handle_t targetEntry = reduct_list_find_entry(reduct, listItem, path);
1283
1284 reduct_handle_t entryH;
1285 REDUCT_LIST_FOR_EACH(&entryH, &listItem->list)
1286 {
1287 if (entryH == targetEntry)
1288 {
1289 continue;
1290 }
1291 reduct_list_append(reduct, newList, entryH);
1292 }
1293
1294 return REDUCT_HANDLE_FROM_LIST(newList);
1295 }
1296 reduct_item_t* pathItem = REDUCT_HANDLE_TO_ITEM(path);
1297 if (pathItem->length == 0)
1298 {
1299 return *list;
1300 }
1301
1302 reduct_handle_t firstKey = reduct_list_nth(reduct, &pathItem->list, 0);
1303 if (pathItem->length == 1)
1304 {
1305 return reduct_dissoc_in(reduct, list, &firstKey);
1306 }
1307 else
1308 {
1309 reduct_handle_t restPath =
1310 REDUCT_HANDLE_FROM_LIST(reduct_list_slice(reduct, &pathItem->list, 1, pathItem->length));
1311 REDUCT_GC_RETAIN(reduct, restPath);
1312
1313 reduct_handle_t subList = reduct_get_in(reduct, list, &firstKey, REDUCT_NULL);
1314 if (REDUCT_HANDLE_IS_LIST(&subList))
1315 {
1316 reduct_handle_t updatedSubList = reduct_dissoc_in(reduct, &subList, &restPath);
1317 reduct_handle_t result = reduct_assoc_in(reduct, list, &firstKey, &updatedSubList);
1318 REDUCT_GC_RELEASE(reduct, restPath);
1319 return result;
1320 }
1321
1322 REDUCT_GC_RELEASE(reduct, restPath);
1323 return *list;
1324 }
1325}
1326
1328 reduct_handle_t* callable)
1329{
1330 REDUCT_ASSERT(reduct != REDUCT_NULL);
1331
1332 reduct_handle_t currentVal = reduct_get_in(reduct, list, path, REDUCT_NULL);
1333 reduct_handle_t newVal = reduct_eval_call(reduct, *callable, 1, &currentVal);
1334
1335 return reduct_assoc_in(reduct, list, path, &newVal);
1336}
1337
1339 const char* name)
1340{
1341 REDUCT_ERROR_CHECK_LIST(reduct, listHandle, name);
1342 reduct_item_t* item = REDUCT_HANDLE_TO_ITEM(listHandle);
1343 reduct_list_t* resultList = reduct_list_new(reduct);
1344 reduct_handle_t resultHandle = REDUCT_HANDLE_FROM_LIST(resultList);
1345 REDUCT_GC_RETAIN(reduct, resultHandle);
1346
1347 reduct_handle_t childHandle;
1348 REDUCT_LIST_FOR_EACH(&childHandle, &item->list)
1349 {
1350 if (REDUCT_HANDLE_IS_LIST(&childHandle))
1351 {
1352 reduct_item_t* childItem = REDUCT_HANDLE_TO_ITEM(&childHandle);
1353 if (childItem->length > index)
1354 {
1355 reduct_list_append(reduct, resultList, reduct_list_nth(reduct, &childItem->list, index));
1356 }
1357 }
1358 }
1359
1360 REDUCT_GC_RELEASE(reduct, resultHandle);
1361 return resultHandle;
1362}
1363
1365{
1366 REDUCT_ASSERT(reduct != REDUCT_NULL);
1367 return reduct_list_project(reduct, listHandle, 0, "keys");
1368}
1369
1371{
1372 REDUCT_ASSERT(reduct != REDUCT_NULL);
1373 return reduct_list_project(reduct, listHandle, 1, "values");
1374}
1375
1377{
1378 REDUCT_ASSERT(reduct != REDUCT_NULL);
1379 REDUCT_ASSERT(argv != REDUCT_NULL || argc == 0);
1380
1381 reduct_list_t* resultList = reduct_list_new(reduct);
1382 reduct_handle_t result = REDUCT_HANDLE_FROM_LIST(resultList);
1383 REDUCT_GC_RETAIN(reduct, result);
1384
1385 for (reduct_size_t i = 0; i < argc; i++)
1386 {
1387 if (!REDUCT_HANDLE_IS_LIST(&argv[i]))
1388 {
1389 continue;
1390 }
1391
1392 reduct_item_t* currentItem = REDUCT_HANDLE_TO_ITEM(&argv[i]);
1393 reduct_handle_t entryH;
1394 REDUCT_LIST_FOR_EACH(&entryH, &currentItem->list)
1395 {
1396 reduct_handle_t key, val;
1397 if (reduct_list_get_entry(reduct, &entryH, &key, &val))
1398 {
1399 reduct_handle_t next = reduct_assoc_in(reduct, &result, &key, &val);
1400 REDUCT_GC_RETAIN(reduct, next);
1401 REDUCT_GC_RELEASE(reduct, result);
1402 result = next;
1403 }
1404 }
1405 }
1406
1407 REDUCT_GC_RELEASE(reduct, result);
1408 return result;
1409}
1410
1412{
1413 REDUCT_ASSERT(reduct != REDUCT_NULL);
1414 REDUCT_ASSERT(argv != REDUCT_NULL || argc == 0);
1415
1416 reduct_list_t* list = reduct_list_new(reduct);
1417 reduct_handle_t listHandle = REDUCT_HANDLE_FROM_LIST(list);
1418 REDUCT_GC_RETAIN(reduct, listHandle);
1419
1420 for (reduct_size_t i = 0; i < argc; i++)
1421 {
1422 char* str;
1423 reduct_size_t len;
1424 reduct_handle_get_string_params(reduct, &argv[i], &str, &len);
1425 for (reduct_size_t j = 0; j < len; j++)
1426 {
1427 reduct_list_append(reduct, list, REDUCT_HANDLE_FROM_INT((reduct_int64_t)(unsigned char)str[j]));
1428 }
1429 }
1430
1431 REDUCT_GC_RELEASE(reduct, listHandle);
1432 return listHandle;
1433}
1434
1436{
1437 REDUCT_ASSERT(reduct != REDUCT_NULL);
1438 REDUCT_ASSERT(argv != REDUCT_NULL || argc == 0);
1439
1440 reduct_size_t totalLen = 0;
1441 for (reduct_size_t i = 0; i < argc; i++)
1442 {
1443 if (!REDUCT_HANDLE_IS_LIST(&argv[i]))
1444 {
1445 continue;
1446 }
1447 totalLen += REDUCT_HANDLE_TO_ITEM(&argv[i])->length;
1448 }
1449
1450 REDUCT_SCRATCH_BUFFER(buffer, totalLen);
1451
1452 reduct_size_t currentPos = 0;
1453 for (reduct_size_t i = 0; i < argc; i++)
1454 {
1455 if (!REDUCT_HANDLE_IS_LIST(&argv[i]))
1456 {
1457 continue;
1458 }
1459 reduct_item_t* list = REDUCT_HANDLE_TO_ITEM(&argv[i]);
1460 reduct_handle_t valH;
1461 REDUCT_LIST_FOR_EACH(&valH, &list->list)
1462 {
1463 reduct_handle_t charH = reduct_get_int(reduct, &valH);
1464 buffer[currentPos++] = (char)REDUCT_HANDLE_TO_INT(&charH);
1465 }
1466 }
1467
1468 reduct_handle_t result =
1471 return result;
1472}
1473
1475{
1476 REDUCT_ASSERT(reduct != REDUCT_NULL);
1477
1478 reduct_handle_t nHandle = reduct_get_int(reduct, count);
1480
1481 if (n < 0)
1482 {
1483 REDUCT_ERROR_RUNTIME(reduct, "repeat count cannot be negative, got %lld", n);
1484 }
1485
1486 reduct_list_t* newList = reduct_list_new(reduct);
1487 reduct_handle_t newHandle = REDUCT_HANDLE_FROM_LIST(newList);
1488 REDUCT_GC_RETAIN(reduct, newHandle);
1489
1490 for (reduct_size_t i = 0; i < (reduct_size_t)n; i++)
1491 {
1492 reduct_list_append(reduct, newList, *handle);
1493 }
1494
1495 REDUCT_GC_RELEASE(reduct, newHandle);
1496 return newHandle;
1497}
1498
1500 reduct_handle_t* target, reduct_bool_t start, const char* name)
1501{
1502 REDUCT_ASSERT(reduct != REDUCT_NULL);
1503
1504 REDUCT_ERROR_CHECK_SEQUENCE(reduct, handle, name);
1505 reduct_item_t* item = REDUCT_HANDLE_TO_ITEM(handle);
1506
1507 if (item->type == REDUCT_ITEM_TYPE_LIST)
1508 {
1509 if (item->length == 0)
1510 {
1511 return REDUCT_HANDLE_FALSE();
1512 }
1513 reduct_size_t index = start ? 0 : item->length - 1;
1514 reduct_handle_t edge = reduct_list_nth(reduct, &item->list, index);
1515 return (reduct_handle_compare(reduct, &edge, target) == 0) ? REDUCT_HANDLE_TRUE() : REDUCT_HANDLE_FALSE();
1516 }
1517 else
1518 {
1519 char *srcStr, *tgtStr;
1520 reduct_size_t srcLen, tgtLen;
1521 reduct_handle_get_string_params(reduct, handle, &srcStr, &srcLen);
1522 reduct_handle_get_string_params(reduct, target, &tgtStr, &tgtLen);
1523
1524 if (tgtLen > srcLen)
1525 {
1526 return REDUCT_HANDLE_FALSE();
1527 }
1528 const char* offset = start ? srcStr : srcStr + srcLen - tgtLen;
1529 return (REDUCT_MEMCMP(offset, tgtStr, tgtLen) == 0) ? REDUCT_HANDLE_TRUE() : REDUCT_HANDLE_FALSE();
1530 }
1531 return REDUCT_HANDLE_FALSE();
1532}
1533
1535{
1536 return reduct_sequence_check_edge(reduct, handle, prefix, REDUCT_TRUE, "starts-with?");
1537}
1538
1540{
1541 return reduct_sequence_check_edge(reduct, handle, suffix, REDUCT_FALSE, "ends-with?");
1542}
1543
1545{
1546 REDUCT_ASSERT(reduct != REDUCT_NULL);
1547 if (!REDUCT_HANDLE_IS_LIST(listHandle))
1548 {
1549 REDUCT_ERROR_RUNTIME(reduct, "join expects a list as the first argument, got %s",
1551 }
1552
1553 reduct_item_t* list = REDUCT_HANDLE_TO_ITEM(listHandle);
1554 if (list->length == 0)
1555 {
1557 }
1558
1559 char* sepStr;
1560 reduct_size_t sepLen;
1561 reduct_handle_get_string_params(reduct, sepHandle, &sepStr, &sepLen);
1562
1563 reduct_size_t totalLen = 0;
1564 reduct_handle_t entry;
1565 REDUCT_LIST_FOR_EACH(&entry, &list->list)
1566 {
1567 totalLen += reduct_handle_item(reduct, &entry)->length;
1568 }
1569
1570 if (list->length > 1)
1571 {
1572 totalLen += sepLen * (list->length - 1);
1573 }
1574
1575 REDUCT_SCRATCH_BUFFER(buffer, totalLen);
1576
1577 reduct_size_t currentPos = 0;
1578 REDUCT_LIST_FOR_EACH(&entry, &list->list)
1579 {
1580 char* str;
1581 reduct_size_t len;
1582 reduct_handle_get_string_params(reduct, &entry, &str, &len);
1583 REDUCT_MEMCPY(buffer + currentPos, str, len);
1584 currentPos += len;
1585
1586 if (_iter.index < list->length)
1587 {
1588 REDUCT_MEMCPY(buffer + currentPos, sepStr, sepLen);
1589 currentPos += sepLen;
1590 }
1591 }
1592
1593 reduct_handle_t result =
1596 return result;
1597}
1598
1600{
1601 REDUCT_ASSERT(reduct != REDUCT_NULL);
1602
1603 char *srcStr, *sepStr;
1604 reduct_size_t srcLen, sepLen;
1605
1606 reduct_handle_get_string_params(reduct, srcHandle, &srcStr, &srcLen);
1607 reduct_handle_get_string_params(reduct, sepHandle, &sepStr, &sepLen);
1608
1609 reduct_list_t* resultList = reduct_list_new(reduct);
1610 reduct_handle_t resultHandle = REDUCT_HANDLE_FROM_LIST(resultList);
1611 REDUCT_GC_RETAIN(reduct, resultHandle);
1612
1613 if (sepLen == 0)
1614 {
1615 for (reduct_size_t i = 0; i < srcLen; i++)
1616 {
1617 reduct_list_append(reduct, resultList,
1619 }
1620 }
1621 else
1622 {
1623 reduct_size_t lastPos = 0;
1624 for (reduct_size_t i = 0; i <= srcLen - sepLen; i++)
1625 {
1626 if (REDUCT_MEMCMP(srcStr + i, sepStr, sepLen) == 0)
1627 {
1628 reduct_list_append(reduct, resultList,
1630 reduct_atom_lookup(reduct, srcStr + lastPos, i - lastPos, REDUCT_ATOM_LOOKUP_NONE)));
1631 i += sepLen - 1;
1632 lastPos = i + 1;
1633 }
1634 }
1635
1636 reduct_list_append(reduct, resultList,
1638 reduct_atom_lookup(reduct, srcStr + lastPos, srcLen - lastPos, REDUCT_ATOM_LOOKUP_NONE)));
1639 }
1640
1641 REDUCT_GC_RELEASE(reduct, resultHandle);
1642 return resultHandle;
1643}
1644
1646{
1647 char* srcStr;
1648 reduct_size_t srcLen;
1649 reduct_handle_get_string_params(reduct, srcHandle, &srcStr, &srcLen);
1650
1651 if (srcLen == 0)
1652 {
1653 return *srcHandle;
1654 }
1655
1656 REDUCT_SCRATCH_BUFFER(buffer, srcLen);
1657 for (reduct_size_t i = 0; i < srcLen; i++)
1658 {
1659 buffer[i] = upper ? REDUCT_CHAR_TO_UPPER(srcStr[i]) : REDUCT_CHAR_TO_LOWER(srcStr[i]);
1660 }
1661
1662 reduct_handle_t result =
1665 return result;
1666}
1667
1669{
1670 REDUCT_ASSERT(reduct != REDUCT_NULL);
1671 return reduct_string_transform(reduct, srcHandle, REDUCT_TRUE);
1672}
1673
1675{
1676 REDUCT_ASSERT(reduct != REDUCT_NULL);
1677 return reduct_string_transform(reduct, srcHandle, REDUCT_FALSE);
1678}
1679
1681{
1682 REDUCT_ASSERT(reduct != REDUCT_NULL);
1683
1684 char* srcStr;
1685 reduct_size_t srcLen;
1686 reduct_handle_get_string_params(reduct, srcHandle, &srcStr, &srcLen);
1687
1688 if (srcLen == 0)
1689 {
1690 return *srcHandle;
1691 }
1692
1693 reduct_size_t start = 0;
1694 while (start < srcLen && REDUCT_CHAR_IS_WHITESPACE(srcStr[start]))
1695 {
1696 start++;
1697 }
1698
1699 if (start == srcLen)
1700 {
1702 }
1703
1704 reduct_size_t end = srcLen - 1;
1705 while (end > start && REDUCT_CHAR_IS_WHITESPACE(srcStr[end]))
1706 {
1707 end--;
1708 }
1709
1711 reduct_atom_lookup(reduct, srcStr + start, end - start + 1, REDUCT_ATOM_LOOKUP_NONE));
1712}
1713
1714#define REDUCT_INTROSPECTION_LOOP(_predicate) \
1715 do \
1716 { \
1717 REDUCT_ASSERT(reduct != REDUCT_NULL); \
1718 REDUCT_ASSERT(argv != REDUCT_NULL || argc == 0); \
1719 for (reduct_size_t i = 0; i < argc; i++) \
1720 { \
1721 if (!(_predicate)) \
1722 { \
1723 return REDUCT_HANDLE_FALSE(); \
1724 } \
1725 } \
1726 return REDUCT_HANDLE_TRUE(); \
1727 } while (0)
1728
1729#define REDUCT_INTROSPECTION_IMPL(_name, _predicate_macro) \
1730 REDUCT_API reduct_handle_t _name(reduct_t* reduct, reduct_size_t argc, reduct_handle_t* argv) \
1731 { \
1732 REDUCT_UNUSED(reduct); \
1733 REDUCT_INTROSPECTION_LOOP(_predicate_macro(&argv[i])); \
1734 }
1735
1744
1745#define REDUCT_PREDICATE_IS_STRING(_h) (REDUCT_HANDLE_IS_ATOM(_h) && !REDUCT_HANDLE_IS_NUMBER_SHAPED(_h))
1747
1748#define REDUCT_PREDICATE_IS_EMPTY(_h) (reduct_handle_item(reduct, _h)->length == 0)
1750
1751#define REDUCT_PREDICATE_IS_NIL(_h) (*(_h) == reduct_handle_nil(reduct))
1753
1754#define REDUCT_GET_NUMERIC_IMPL(_name, _res, _type, _other, _targetUnion, _otherUnion) \
1755 REDUCT_API reduct_handle_t reduct_get_##_name(reduct_t* reduct, reduct_handle_t* handle) \
1756 { \
1757 REDUCT_ASSERT(reduct != REDUCT_NULL); \
1758 if (REDUCT_HANDLE_IS_##_type(handle)) \
1759 { \
1760 return *handle; \
1761 } \
1762 if (REDUCT_HANDLE_IS_##_other(handle)) \
1763 { \
1764 return REDUCT_HANDLE_FROM_##_res((reduct_##_name##_t)REDUCT_HANDLE_TO_##_other(handle)); \
1765 } \
1766 reduct_item_t* item = reduct_handle_item(reduct, handle); \
1767 if (item->flags & REDUCT_ITEM_FLAG_##_type##_SHAPED) \
1768 { \
1769 return REDUCT_HANDLE_FROM_##_res(item->atom._targetUnion); \
1770 } \
1771 if (item->flags & REDUCT_ITEM_FLAG_##_other##_SHAPED) \
1772 { \
1773 return REDUCT_HANDLE_FROM_##_res((reduct_##_name##_t)item->atom._otherUnion); \
1774 } \
1775 REDUCT_ERROR_RUNTIME(reduct, "expected " #_name ", got %s", reduct_item_type_str(item->type)); \
1776 }
1777
1778REDUCT_GET_NUMERIC_IMPL(int, INT, INT, FLOAT, integerValue, floatValue)
1779REDUCT_GET_NUMERIC_IMPL(float, FLOAT, FLOAT, INT, floatValue, integerValue)
1780
1782{
1783 REDUCT_ASSERT(reduct != REDUCT_NULL);
1784
1785 if (REDUCT_HANDLE_IS_ATOM(handle))
1786 {
1787 reduct_item_t* item = reduct_handle_item(reduct, handle);
1790 }
1791
1792 char stackBuffer[REDUCT_STACK_BUFFER_SIZE];
1793 reduct_size_t len = reduct_stringify(reduct, handle, stackBuffer, REDUCT_STACK_BUFFER_SIZE);
1794 if (len < REDUCT_STACK_BUFFER_SIZE)
1795 {
1796 return REDUCT_HANDLE_FROM_ATOM(reduct_atom_lookup(reduct, stackBuffer, len, REDUCT_ATOM_LOOKUP_QUOTED));
1797 }
1798
1799 REDUCT_SCRATCH_BUFFER(buffer, len);
1800 reduct_stringify(reduct, handle, buffer, len + 1);
1801 reduct_handle_t result =
1804 return result;
1805}
1806
1807static void reduct_path_copy(reduct_t* reduct, char* dest, const char* src, reduct_size_t len, reduct_size_t max)
1808{
1809 if (len >= max)
1810 {
1811 REDUCT_ERROR_RUNTIME(reduct, "path too long");
1812 }
1813 REDUCT_MEMCPY(dest, src, len);
1814 dest[len] = '\0';
1815}
1816
1817static void reduct_resolve_path(reduct_t* reduct, const char* path, reduct_size_t pathLen, char* outPath,
1818 reduct_size_t maxLen)
1819{
1820 reduct_bool_t isAbsolute = REDUCT_FALSE;
1821 if (pathLen > 0 && (path[0] == '/' || path[0] == '\\'))
1822 {
1823 isAbsolute = REDUCT_TRUE;
1824 }
1825 if (pathLen > 1 && ((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z')) && path[1] == ':')
1826 {
1827 isAbsolute = REDUCT_TRUE;
1828 }
1829
1830 if (isAbsolute || reduct->evalState == REDUCT_NULL || reduct->evalState->frameCount == 0)
1831 {
1832 reduct_path_copy(reduct, outPath, path, pathLen, maxLen);
1833 return;
1834 }
1835
1836 reduct_input_t* input = REDUCT_NULL;
1837 for (reduct_size_t i = reduct->evalState->frameCount; i > 0; i--)
1838 {
1839 reduct_eval_frame_t* frame = &reduct->evalState->frames[i - 1];
1840 reduct_item_t* funcItem = REDUCT_CONTAINER_OF(frame->closure->function, reduct_item_t, function);
1841 if (funcItem->input != REDUCT_NULL && funcItem->input->path[0] != '\0')
1842 {
1843 input = funcItem->input;
1844 break;
1845 }
1846 }
1847
1848 if (input == REDUCT_NULL)
1849 {
1850 reduct_path_copy(reduct, outPath, path, pathLen, maxLen);
1851 return;
1852 }
1853
1854 const char* lastSlash = NULL;
1855 const char* p = input->path;
1856 while (*p != '\0')
1857 {
1858 if (*p == '/' || *p == '\\')
1859 {
1860 lastSlash = p;
1861 }
1862 p++;
1863 }
1864
1865 if (lastSlash == REDUCT_NULL)
1866 {
1867 reduct_path_copy(reduct, outPath, path, pathLen, maxLen);
1868 return;
1869 }
1870
1871 reduct_size_t dirLen = (reduct_size_t)(lastSlash - input->path) + 1;
1872 if (dirLen + pathLen >= maxLen)
1873 {
1874 REDUCT_ERROR_RUNTIME(reduct, "path too long");
1875 }
1876
1877 REDUCT_MEMCPY(outPath, input->path, dirLen);
1878 REDUCT_MEMCPY(outPath + dirLen, path, pathLen);
1879 outPath[dirLen + pathLen] = '\0';
1880}
1881
1883{
1884 REDUCT_ASSERT(reduct != REDUCT_NULL);
1885
1886 char* str;
1887 reduct_size_t len;
1888 reduct_handle_get_string_params(reduct, handle, &str, &len);
1889
1890 reduct_handle_t ast = reduct_parse(reduct, str, len, "<run>");
1891 reduct_function_t* function = reduct_compile(reduct, &ast);
1892 return reduct_eval(reduct, function);
1893}
1894
1895static void reduct_get_resolved_path(reduct_t* reduct, reduct_handle_t* pathHandle, char* outBuf)
1896{
1897 char* pathStr;
1898 reduct_size_t pathLen;
1899 reduct_handle_get_string_params(reduct, pathHandle, &pathStr, &pathLen);
1900 reduct_resolve_path(reduct, pathStr, pathLen, outBuf, REDUCT_PATH_MAX);
1901}
1902
1904{
1905 REDUCT_ASSERT(reduct != REDUCT_NULL);
1906 char pathBuf[REDUCT_PATH_MAX];
1907 reduct_get_resolved_path(reduct, path, pathBuf);
1908
1909 reduct_handle_t ast = reduct_parse_file(reduct, pathBuf);
1910 reduct_function_t* function = reduct_compile(reduct, &ast);
1911 return reduct_eval(reduct, function);
1912}
1913
1915{
1916 REDUCT_ASSERT(reduct != REDUCT_NULL);
1917 char pathBuf[REDUCT_PATH_MAX];
1918 reduct_get_resolved_path(reduct, path, pathBuf);
1919
1920 reduct_file_t file = REDUCT_FOPEN(pathBuf, "rb");
1921 if (file == REDUCT_NULL)
1922 {
1923 REDUCT_ERROR_RUNTIME(reduct, "could not open file '%s'", pathBuf);
1924 }
1925
1926 fseek(file, 0, SEEK_END);
1927 long size = ftell(file);
1928 fseek(file, 0, SEEK_SET);
1929
1930 char* buffer = (char*)REDUCT_MALLOC(size);
1931 if (buffer == REDUCT_NULL)
1932 {
1933 REDUCT_FCLOSE(file);
1934 REDUCT_ERROR_INTERNAL(reduct, "out of memory");
1935 }
1936
1937 if (REDUCT_FREAD(buffer, 1, size, file) != (reduct_size_t)size)
1938 {
1939 REDUCT_FREE(buffer);
1940 REDUCT_FCLOSE(file);
1941 REDUCT_ERROR_RUNTIME(reduct, "could not read file '%s'", pathBuf);
1942 }
1943
1944 REDUCT_FCLOSE(file);
1945 reduct_handle_t result =
1947 REDUCT_FREE(buffer);
1948 return result;
1949}
1950
1952{
1953 REDUCT_ASSERT(reduct != REDUCT_NULL);
1954
1955 char pathBuf[REDUCT_PATH_MAX];
1956 reduct_get_resolved_path(reduct, path, pathBuf);
1957
1958 char* contentStr;
1959 reduct_size_t contentLen;
1960 reduct_handle_get_string_params(reduct, content, &contentStr, &contentLen);
1961
1962 reduct_file_t file = REDUCT_FOPEN(pathBuf, "wb");
1963 if (file == REDUCT_NULL)
1964 {
1965 REDUCT_ERROR_RUNTIME(reduct, "could not open file '%s' for writing", pathBuf);
1966 }
1967
1968 if (REDUCT_FWRITE(contentStr, 1, contentLen, file) != contentLen)
1969 {
1970 REDUCT_FCLOSE(file);
1971 REDUCT_ERROR_RUNTIME(reduct, "could not write to file '%s'", pathBuf);
1972 }
1973
1974 REDUCT_FCLOSE(file);
1975 return *content;
1976}
1977
1979{
1980 REDUCT_ASSERT(reduct != REDUCT_NULL);
1981
1982 int c = REDUCT_FGETC(REDUCT_STDIN);
1983 if (c == EOF)
1984 {
1985 return reduct_handle_nil(reduct);
1986 }
1987
1988 char ch = (char)c;
1990}
1991
1993{
1994 REDUCT_ASSERT(reduct != REDUCT_NULL);
1995
1996 char stackBuffer[REDUCT_STACK_BUFFER_SIZE];
1998 char* buffer = stackBuffer;
1999 reduct_size_t length = 0;
2000
2001 while (REDUCT_TRUE)
2002 {
2003 int c = REDUCT_FGETC(REDUCT_STDIN);
2004 if (c == EOF || c == '\n')
2005 {
2006 if (c == EOF && length == 0)
2007 {
2008 if (buffer != stackBuffer)
2009 {
2010 REDUCT_FREE(buffer);
2011 }
2012 return reduct_handle_nil(reduct);
2013 }
2014 break;
2015 }
2016
2017 if (length + 1 >= capacity)
2018 {
2019 reduct_size_t newCapacity = capacity * 2;
2020 char* newBuffer = (char*)REDUCT_MALLOC(newCapacity);
2021 if (newBuffer == REDUCT_NULL)
2022 {
2023 if (buffer != stackBuffer)
2024 {
2025 REDUCT_FREE(buffer);
2026 }
2027 REDUCT_ERROR_INTERNAL(reduct, "out of memory");
2028 }
2029 REDUCT_MEMCPY(newBuffer, buffer, length);
2030 if (buffer != stackBuffer)
2031 {
2032 REDUCT_FREE(buffer);
2033 }
2034 buffer = newBuffer;
2035 capacity = newCapacity;
2036 }
2037 buffer[length++] = (char)c;
2038 }
2039
2040 reduct_handle_t result =
2042 if (buffer != stackBuffer)
2043 {
2044 REDUCT_FREE(buffer);
2045 }
2046 return result;
2047}
2048
2050{
2051 REDUCT_ASSERT(reduct != REDUCT_NULL);
2052
2053 for (reduct_size_t i = 0; i < argc; i++)
2054 {
2055 char* str;
2056 reduct_size_t len;
2057 reduct_handle_get_string_params(reduct, &argv[i], &str, &len);
2058 REDUCT_FWRITE(str, 1, len, REDUCT_STDOUT);
2059 if (i < argc - 1)
2060 {
2061 REDUCT_FWRITE(" ", 1, 1, REDUCT_STDOUT);
2062 }
2063 }
2064 return reduct_handle_nil(reduct);
2065}
2066
2068{
2069 REDUCT_ASSERT(reduct != REDUCT_NULL);
2070
2071 reduct_handle_t handle = reduct_print(reduct, argc, argv);
2072 REDUCT_FWRITE("\n", 1, 1, REDUCT_STDOUT);
2073 return handle;
2074}
2075
2077{
2078 REDUCT_ASSERT(reduct != REDUCT_NULL);
2079 REDUCT_ASSERT(handle != REDUCT_NULL);
2080
2081 char* str;
2082 reduct_size_t len;
2083 reduct_handle_get_string_params(reduct, handle, &str, &len);
2084
2085 if (len == 0)
2086 {
2087 REDUCT_ERROR_RUNTIME(reduct, "ord expects a non-empty atom");
2088 }
2089
2091}
2092
2094{
2095 REDUCT_ASSERT(reduct != REDUCT_NULL);
2096
2097 reduct_handle_t iVal = reduct_get_int(reduct, handle);
2099
2100 if (val < 0 || val > 255)
2101 {
2102 REDUCT_ERROR_RUNTIME(reduct, "chr expects an integer in range 0-255, got %lld", (long long)val);
2103 }
2104
2105 char c = (char)(reduct_uint8_t)val;
2107}
2108
2110{
2111 REDUCT_ASSERT(reduct != REDUCT_NULL);
2112
2113 if (argc == 0)
2114 {
2116 }
2117
2118 char* fmtStr;
2119 reduct_size_t fmtLen;
2120 reduct_handle_get_string_params(reduct, &argv[0], &fmtStr, &fmtLen);
2121
2122 reduct_size_t totalLen = 0;
2123 reduct_size_t argIndex = 1;
2124
2125 for (reduct_size_t i = 0; i < fmtLen; i++)
2126 {
2127 if (fmtStr[i] == '{')
2128 {
2129 if (i + 1 < fmtLen && fmtStr[i + 1] == '{')
2130 {
2131 totalLen++;
2132 i++;
2133 continue;
2134 }
2135
2136 reduct_size_t j = i + 1;
2137 reduct_int64_t explicitIndex = -1;
2138 if (j < fmtLen && fmtStr[j] >= '0' && fmtStr[j] <= '9')
2139 {
2140 explicitIndex = 0;
2141 while (j < fmtLen && fmtStr[j] >= '0' && fmtStr[j] <= '9')
2142 {
2143 explicitIndex = explicitIndex * 10 + (fmtStr[j] - '0');
2144 j++;
2145 }
2146 }
2147
2148 if (j < fmtLen && fmtStr[j] == '}')
2149 {
2150 reduct_size_t idx = (explicitIndex != -1) ? (reduct_size_t)explicitIndex + 1 : argIndex++;
2151 if (idx >= argc)
2152 {
2153 REDUCT_ERROR_RUNTIME(reduct, "format index out of range");
2154 }
2155 totalLen += reduct_stringify(reduct, &argv[idx], REDUCT_NULL, 0);
2156 i = j;
2157 continue;
2158 }
2159
2160 REDUCT_ERROR_RUNTIME(reduct, "invalid format string");
2161 }
2162 else if (fmtStr[i] == '}')
2163 {
2164 if (i + 1 < fmtLen && fmtStr[i + 1] == '}')
2165 {
2166 totalLen++;
2167 i++;
2168 continue;
2169 }
2170
2171 REDUCT_ERROR_RUNTIME(reduct, "single '}' encountered in format string");
2172 }
2173 totalLen++;
2174 }
2175
2176 REDUCT_SCRATCH_BUFFER(buffer, totalLen);
2177
2178 reduct_size_t currentPos = 0;
2179 argIndex = 1;
2180
2181 for (reduct_size_t i = 0; i < fmtLen; i++)
2182 {
2183 if (fmtStr[i] == '{')
2184 {
2185 if (i + 1 < fmtLen && fmtStr[i + 1] == '{')
2186 {
2187 buffer[currentPos++] = '{';
2188 i++;
2189 continue;
2190 }
2191
2192 reduct_size_t j = i + 1;
2193 reduct_int64_t explicitIndex = -1;
2194 if (j < fmtLen && fmtStr[j] >= '0' && fmtStr[j] <= '9')
2195 {
2196 explicitIndex = 0;
2197 while (j < fmtLen && fmtStr[j] >= '0' && fmtStr[j] <= '9')
2198 {
2199 explicitIndex = explicitIndex * 10 + (fmtStr[j] - '0');
2200 j++;
2201 }
2202 }
2203
2204 if (j < fmtLen && fmtStr[j] == '}')
2205 {
2206 reduct_size_t idx = (explicitIndex != -1) ? (reduct_size_t)explicitIndex + 1 : argIndex++;
2207 currentPos += reduct_stringify(reduct, &argv[idx], buffer + currentPos, totalLen - currentPos + 1);
2208 i = j;
2209 continue;
2210 }
2211 }
2212 else if (fmtStr[i] == '}')
2213 {
2214 if (i + 1 < fmtLen && fmtStr[i + 1] == '}')
2215 {
2216 buffer[currentPos++] = '}';
2217 i++;
2218 continue;
2219 }
2220 }
2221 buffer[currentPos++] = fmtStr[i];
2222 }
2223
2224 reduct_handle_t result =
2227 return result;
2228}
2229
2238
2247
2249{
2250 REDUCT_ASSERT(reduct != REDUCT_NULL);
2251
2252 extern char** environ;
2253 reduct_size_t count = 0;
2254 while (environ[count] != REDUCT_NULL)
2255 {
2256 count++;
2257 }
2258
2259 reduct_list_t* list = reduct_list_new(reduct);
2260 for (reduct_size_t i = 0; i < count; i++)
2261 {
2262 char* env = environ[i];
2263 char* eq = strchr(env, '=');
2264 if (eq != REDUCT_NULL)
2265 {
2266 reduct_list_t* pair = reduct_list_new(reduct);
2267 reduct_list_append(reduct, pair,
2269 reduct_atom_lookup(reduct, env, (reduct_size_t)(eq - env), REDUCT_ATOM_LOOKUP_NONE)));
2270 reduct_list_append(reduct, pair,
2273
2274 reduct_list_append(reduct, list, REDUCT_HANDLE_FROM_LIST(pair));
2275 }
2276 }
2277
2278 return REDUCT_HANDLE_FROM_LIST(list);
2279}
2280
2282{
2283 REDUCT_ASSERT(reduct != REDUCT_NULL);
2284
2285 if (reduct->argc == 0)
2286 {
2287 return reduct_handle_nil(reduct);
2288 }
2289
2290 reduct_list_t* list = reduct_list_new(reduct);
2291 for (int i = 0; i < reduct->argc; i++)
2292 {
2293 reduct_list_append(reduct, list,
2294 REDUCT_HANDLE_FROM_ATOM(reduct_atom_lookup(reduct, reduct->argv[i], REDUCT_STRLEN(reduct->argv[i]),
2296 }
2297
2298 return REDUCT_HANDLE_FROM_LIST(list);
2299}
2300
2301#define REDUCT_MATH_MIN_MAX_IMPL(_name, _op) \
2302 REDUCT_API reduct_handle_t _name(reduct_t* reduct, reduct_size_t argc, reduct_handle_t* argv) \
2303 { \
2304 REDUCT_ASSERT(reduct != REDUCT_NULL); \
2305 if (argc == 0) \
2306 { \
2307 return reduct_handle_nil(reduct); \
2308 } \
2309 reduct_handle_t current = argv[0]; \
2310 for (reduct_size_t i = 1; i < argc; i++) \
2311 { \
2312 reduct_promotion_t prom; \
2313 reduct_handle_promote(reduct, &current, &argv[i], &prom); \
2314 if (prom.type == REDUCT_PROMOTION_TYPE_INT) \
2315 { \
2316 current = REDUCT_HANDLE_FROM_INT(prom.a.intVal _op prom.b.intVal ? prom.a.intVal : prom.b.intVal); \
2317 } \
2318 else \
2319 { \
2320 current = \
2321 REDUCT_HANDLE_FROM_FLOAT(prom.a.floatVal _op prom.b.floatVal ? prom.a.floatVal : prom.b.floatVal); \
2322 } \
2323 } \
2324 return current; \
2325 }
2326
2329
2331 reduct_handle_t* maxVal)
2332{
2333 REDUCT_ASSERT(reduct != REDUCT_NULL);
2334
2335 reduct_handle_t current = *val;
2336 reduct_promotion_t prom;
2337
2338 reduct_handle_promote(reduct, &current, minVal, &prom);
2339 if (prom.type == REDUCT_PROMOTION_TYPE_INT)
2340 {
2341 current = REDUCT_HANDLE_FROM_INT(prom.a.intVal < prom.b.intVal ? prom.b.intVal : prom.a.intVal);
2342 }
2343 else
2344 {
2345 current = REDUCT_HANDLE_FROM_FLOAT(prom.a.floatVal < prom.b.floatVal ? prom.b.floatVal : prom.a.floatVal);
2346 }
2347
2348 reduct_handle_promote(reduct, &current, maxVal, &prom);
2349 if (prom.type == REDUCT_PROMOTION_TYPE_INT)
2350 {
2351 current = REDUCT_HANDLE_FROM_INT(prom.a.intVal > prom.b.intVal ? prom.b.intVal : prom.a.intVal);
2352 }
2353 else
2354 {
2355 current = REDUCT_HANDLE_FROM_FLOAT(prom.a.floatVal > prom.b.floatVal ? prom.b.floatVal : prom.a.floatVal);
2356 }
2357
2358 return current;
2359}
2360
2361#define REDUCT_MATH_UNARY_IMPL(_name, _int_func, _float_func) \
2362 REDUCT_API reduct_handle_t _name(reduct_t* reduct, reduct_handle_t* val) \
2363 { \
2364 REDUCT_ASSERT(reduct != REDUCT_NULL); \
2365 if (REDUCT_HANDLE_IS_INT_SHAPED(val)) \
2366 { \
2367 reduct_handle_t iVal = reduct_get_int(reduct, val); \
2368 reduct_int64_t i = REDUCT_HANDLE_TO_INT(&iVal); \
2369 return REDUCT_HANDLE_FROM_INT((reduct_int64_t)_int_func(i)); \
2370 } \
2371 reduct_handle_t floatVal = reduct_get_float(reduct, val); \
2372 reduct_float_t f = REDUCT_HANDLE_TO_FLOAT(&floatVal); \
2373 return REDUCT_HANDLE_FROM_FLOAT((reduct_float_t)_float_func(f)); \
2374 }
2375
2376#define REDUCT_INT_ABS(_x) ((_x) < 0 ? -(_x) : (_x))
2380
2381#define REDUCT_MATH_UNARY_TO_INT_IMPL(_name, _float_func) \
2382 REDUCT_API reduct_handle_t _name(struct reduct* reduct, reduct_handle_t* val) \
2383 { \
2384 REDUCT_ASSERT(reduct != REDUCT_NULL); \
2385 if (REDUCT_HANDLE_IS_INT_SHAPED(val)) \
2386 { \
2387 return reduct_get_int(reduct, val); \
2388 } \
2389 reduct_handle_t floatVal = reduct_get_float(reduct, val); \
2390 reduct_float_t f = REDUCT_HANDLE_TO_FLOAT(&floatVal); \
2391 return REDUCT_HANDLE_FROM_INT((reduct_int64_t)_float_func(f)); \
2392 }
2393
2397
2399{
2400 REDUCT_ASSERT(reduct != REDUCT_NULL);
2401
2402 reduct_promotion_t prom;
2403 reduct_handle_promote(reduct, base, exp, &prom);
2404
2405 if (prom.type == REDUCT_PROMOTION_TYPE_INT)
2406 {
2409 }
2411}
2412
2414{
2415 REDUCT_ASSERT(reduct != REDUCT_NULL);
2416
2417 if (base == REDUCT_NULL)
2418 {
2420 {
2421 reduct_handle_t iVal = reduct_get_int(reduct, val);
2424 }
2425
2426 reduct_handle_t floatVal = reduct_get_float(reduct, val);
2429 }
2430
2431 reduct_promotion_t prom;
2432 reduct_handle_promote(reduct, val, base, &prom);
2433
2434 if (prom.type == REDUCT_PROMOTION_TYPE_INT)
2435 {
2438 }
2441}
2442
2443#define REDUCT_MATH_UNARY_FLOAT_IMPL(_name, _func) \
2444 REDUCT_API reduct_handle_t _name(struct reduct* reduct, reduct_handle_t* val) \
2445 { \
2446 REDUCT_ASSERT(reduct != REDUCT_NULL); \
2447 reduct_handle_t fv = reduct_get_float(reduct, val); \
2448 return REDUCT_HANDLE_FROM_FLOAT((reduct_float_t)_func(REDUCT_HANDLE_TO_FLOAT(&fv))); \
2449 }
2450
2463
2465{
2466 REDUCT_ASSERT(reduct != REDUCT_NULL);
2467 reduct_handle_t yFloatVal = reduct_get_float(reduct, y);
2468 reduct_handle_t xFloatVal = reduct_get_float(reduct, x);
2469 reduct_float_t yf = REDUCT_HANDLE_TO_FLOAT(&yFloatVal);
2470 reduct_float_t xf = REDUCT_HANDLE_TO_FLOAT(&xFloatVal);
2472}
2473
2475{
2476 REDUCT_ASSERT(reduct != REDUCT_NULL);
2477
2478 reduct_promotion_t prom;
2479 reduct_handle_promote(reduct, minVal, maxVal, &prom);
2480
2482
2483 if (prom.type == REDUCT_PROMOTION_TYPE_INT)
2484 {
2485 reduct_int64_t res = prom.a.intVal + (reduct_int64_t)(r * (prom.b.intVal - prom.a.intVal));
2486 return REDUCT_HANDLE_FROM_INT(res);
2487 }
2488 reduct_float_t res = prom.a.floatVal + (r * (prom.b.floatVal - prom.a.floatVal));
2489 return REDUCT_HANDLE_FROM_FLOAT(res);
2490}
2491
2493{
2494 REDUCT_ASSERT(reduct != REDUCT_NULL);
2495 reduct_handle_t iVal = reduct_get_int(reduct, val);
2497 REDUCT_SRAND((unsigned int)i);
2498 return reduct_handle_nil(reduct);
2499}
2500
2501#define REDUCT_STDLIB_WRAPPER_0(_name, _impl) \
2502 static reduct_handle_t reduct_stdlib_##_name(reduct_t* reduct, reduct_size_t argc, reduct_handle_t* argv) \
2503 { \
2504 reduct_error_check_arity(reduct, argc, 0, #_name); \
2505 (void)argv; \
2506 return _impl(reduct); \
2507 }
2508
2509#define REDUCT_STDLIB_WRAPPER_1(_name, _impl) \
2510 static reduct_handle_t reduct_stdlib_##_name(reduct_t* reduct, reduct_size_t argc, reduct_handle_t* argv) \
2511 { \
2512 reduct_error_check_arity(reduct, argc, 1, #_name); \
2513 return _impl(reduct, &argv[0]); \
2514 }
2515
2516#define REDUCT_STDLIB_WRAPPER_2(_name, _impl) \
2517 static reduct_handle_t reduct_stdlib_##_name(reduct_t* reduct, reduct_size_t argc, reduct_handle_t* argv) \
2518 { \
2519 reduct_error_check_arity(reduct, argc, 2, #_name); \
2520 return _impl(reduct, &argv[0], &argv[1]); \
2521 }
2522
2523#define REDUCT_STDLIB_WRAPPER_3(_name, _impl) \
2524 static reduct_handle_t reduct_stdlib_##_name(reduct_t* reduct, reduct_size_t argc, reduct_handle_t* argv) \
2525 { \
2526 reduct_error_check_arity(reduct, argc, 3, #_name); \
2527 return _impl(reduct, &argv[0], &argv[1], &argv[2]); \
2528 }
2529
2530#define REDUCT_STDLIB_WRAPPER_R12(_name, _impl) \
2531 static reduct_handle_t reduct_stdlib_##_name(reduct_t* reduct, reduct_size_t argc, reduct_handle_t* argv) \
2532 { \
2533 reduct_error_check_arity_range(reduct, argc, 1, 2, #_name); \
2534 return _impl(reduct, &argv[0], argc == 2 ? &argv[1] : REDUCT_NULL); \
2535 }
2536
2537#define REDUCT_STDLIB_WRAPPER_R23(_name, _impl) \
2538 static reduct_handle_t reduct_stdlib_##_name(reduct_t* reduct, reduct_size_t argc, reduct_handle_t* argv) \
2539 { \
2540 reduct_error_check_arity_range(reduct, argc, 2, 3, #_name); \
2541 return _impl(reduct, &argv[0], &argv[1], argc == 3 ? &argv[2] : REDUCT_NULL); \
2542 }
2543
2544#define REDUCT_STDLIB_WRAPPER_R34(_name, _impl) \
2545 static reduct_handle_t reduct_stdlib_##_name(reduct_t* reduct, reduct_size_t argc, reduct_handle_t* argv) \
2546 { \
2547 reduct_error_check_arity_range(reduct, argc, 3, 4, #_name); \
2548 return _impl(reduct, &argv[0], &argv[1], &argv[2], argc == 4 ? &argv[3] : REDUCT_NULL); \
2549 }
2550
2551#define REDUCT_STDLIB_WRAPPER_ARG2(_name, _impl) \
2552 static reduct_handle_t reduct_stdlib_##_name(reduct_t* reduct, reduct_size_t argc, reduct_handle_t* argv) \
2553 { \
2554 reduct_error_check_arity(reduct, argc, 2, #_name); \
2555 return _impl(reduct, &argv[0], &argv[1]); \
2556 }
2557
2558#define REDUCT_STDLIB_WRAPPER_V1(_name, _impl) \
2559 static reduct_handle_t reduct_stdlib_##_name(reduct_t* reduct, reduct_size_t argc, reduct_handle_t* argv) \
2560 { \
2561 reduct_error_check_min_arity(reduct, argc, 1, #_name); \
2562 return _impl(reduct, argc, argv); \
2563 }
2564
2583
2585{
2586 reduct_error_check_arity_range(reduct, argc, 2, 3, "reduce");
2587 return reduct_reduce(reduct, &argv[0], argc == 3 ? &argv[1] : REDUCT_NULL, argc == 3 ? &argv[2] : &argv[1]);
2588}
2589
2595
2597{
2598 reduct_error_check_arity_range(reduct, argc, 1, 3, "range");
2599 reduct_handle_t* start = (argc >= 2) ? &argv[0] : REDUCT_NULL;
2600 reduct_handle_t* end = (argc == 1) ? &argv[0] : (argc >= 2 ? &argv[1] : REDUCT_NULL);
2601 reduct_handle_t* step = (argc == 3) ? &argv[2] : REDUCT_NULL;
2602
2603 if (argc == 1)
2604 {
2606 return reduct_range(reduct, &zero, end, REDUCT_NULL);
2607 }
2608
2609 return reduct_range(reduct, start, end, step);
2610}
2611
2613{
2614 return reduct_concat(reduct, argc, argv);
2615}
2616
2642
2644{
2645 reduct_error_check_arity(reduct, argc, 2, "repeat");
2646 return reduct_repeat(reduct, &argv[0], &argv[1]);
2647}
2648
2653
2660
2662{
2663 return reduct_eval(reduct, reduct_compile(reduct, arg));
2664}
2666
2668{
2669 char* str;
2670 reduct_size_t len;
2671 reduct_handle_get_string_params(reduct, arg, &str, &len);
2672 return reduct_parse(reduct, str, len, "<parse>");
2673}
2675
2682
2684{
2685 return reduct_print(reduct, argc, argv);
2686}
2687
2689{
2690 return reduct_println(reduct, argc, argv);
2691}
2692
2695
2697{
2698 return reduct_format(reduct, argc, argv);
2699}
2700
2708
2717
2732
2734{
2735 REDUCT_ASSERT(reduct != REDUCT_NULL);
2736
2737 if (sets & REDUCT_STDLIB_ERROR)
2738 {
2739 reduct_native_t natives[] = {
2740 {"assert!", reduct_stdlib_assert},
2741 {"throw!", reduct_stdlib_throw},
2742 {"try", reduct_stdlib_try},
2743 };
2744 reduct_native_register(reduct, natives, sizeof(natives) / sizeof(reduct_native_t));
2745 }
2746 if (sets & REDUCT_STDLIB_HIGHER_ORDER)
2747 {
2748 reduct_native_t natives[] = {
2749 {"map", reduct_stdlib_map},
2750 {"filter", reduct_stdlib_filter},
2751 {"reduce", reduct_stdlib_reduce},
2752 {"apply", reduct_stdlib_apply},
2753 {"any?", reduct_stdlib_any},
2754 {"all?", reduct_stdlib_all},
2755 {"sort", reduct_stdlib_sort},
2756 };
2757 reduct_native_register(reduct, natives, sizeof(natives) / sizeof(reduct_native_t));
2758 }
2759 if (sets & REDUCT_STDLIB_SEQUENCES)
2760 {
2761 reduct_native_t natives[] = {
2762 {"len", reduct_stdlib_len},
2763 {"range", reduct_stdlib_range},
2764 {"concat", reduct_stdlib_concat},
2765 {"first", reduct_stdlib_first},
2766 {"last", reduct_stdlib_last},
2767 {"rest", reduct_stdlib_rest},
2768 {"init", reduct_stdlib_init},
2769 {"nth", reduct_stdlib_nth},
2770 {"assoc", reduct_stdlib_assoc},
2771 {"dissoc", reduct_stdlib_dissoc},
2772 {"update", reduct_stdlib_update},
2773 {"index-of", reduct_stdlib_index_of},
2774 {"reverse", reduct_stdlib_reverse},
2775 {"slice", reduct_stdlib_slice},
2776 {"flatten", reduct_stdlib_flatten},
2777 {"contains?", reduct_stdlib_contains},
2778 {"replace", reduct_stdlib_replace},
2779 {"unique", reduct_stdlib_unique},
2780 {"chunk", reduct_stdlib_chunk},
2781 {"find", reduct_stdlib_find},
2782 {"get-in", reduct_stdlib_get_in},
2783 {"assoc-in", reduct_stdlib_assoc_in},
2784 {"dissoc-in", reduct_stdlib_dissoc_in},
2785 {"update-in", reduct_stdlib_update_in},
2786 {"keys", reduct_stdlib_keys},
2787 {"values", reduct_stdlib_values},
2788 {"merge", reduct_stdlib_merge},
2789 {"explode", reduct_stdlib_explode},
2790 {"implode", reduct_stdlib_implode},
2791 {"repeat", reduct_stdlib_repeat},
2792 };
2793 reduct_native_register(reduct, natives, sizeof(natives) / sizeof(reduct_native_t));
2794 }
2795 if (sets & REDUCT_STDLIB_STRING)
2796 {
2797 reduct_native_t natives[] = {
2798 {"starts-with?", reduct_stdlib_starts_with},
2799 {"ends-with?", reduct_stdlib_ends_with},
2800 {"contains?", reduct_stdlib_contains},
2801 {"replace", reduct_stdlib_replace},
2802 {"join", reduct_stdlib_join},
2803 {"split", reduct_stdlib_split},
2804 {"upper", reduct_stdlib_upper},
2805 {"lower", reduct_stdlib_lower},
2806 {"trim", reduct_stdlib_trim},
2807 };
2808 reduct_native_register(reduct, natives, sizeof(natives) / sizeof(reduct_native_t));
2809 }
2810 if (sets & REDUCT_STDLIB_INTROSPECTION)
2811 {
2812 reduct_native_t natives[] = {
2813 {"atom?", reduct_stdlib_is_atom},
2814 {"int?", reduct_stdlib_is_int},
2815 {"float?", reduct_stdlib_is_float},
2816 {"number?", reduct_stdlib_is_number},
2817 {"string?", reduct_stdlib_is_string},
2818 {"lambda?", reduct_stdlib_is_lambda},
2819 {"native?", reduct_stdlib_is_native},
2820 {"callable?", reduct_stdlib_is_callable},
2821 {"list?", reduct_stdlib_is_list},
2822 {"empty?", reduct_stdlib_is_empty},
2823 {"nil?", reduct_stdlib_is_nil},
2824 };
2825 reduct_native_register(reduct, natives, sizeof(natives) / sizeof(reduct_native_t));
2826 }
2827 if (sets & REDUCT_STDLIB_TYPE_CASTING)
2828 {
2829 reduct_native_t natives[] = {
2830 {"int", reduct_stdlib_int},
2831 {"float", reduct_stdlib_float},
2832 {"string", reduct_stdlib_string},
2833 };
2834 reduct_native_register(reduct, natives, sizeof(natives) / sizeof(reduct_native_t));
2835 }
2836 if (sets & REDUCT_STDLIB_SYSTEM)
2837 {
2838 reduct_native_t natives[] = {
2839 {"eval", reduct_stdlib_eval},
2840 {"parse", reduct_stdlib_parse},
2841 {"run", reduct_stdlib_run},
2842 {"load!", reduct_stdlib_load},
2843 {"read-file!", reduct_stdlib_read_file},
2844 {"write-file!", reduct_stdlib_write_file},
2845 {"read-char!", reduct_stdlib_read_char},
2846 {"read-line!", reduct_stdlib_read_line},
2847 {"print!", reduct_stdlib_print},
2848 {"println!", reduct_stdlib_println},
2849 {"ord", reduct_stdlib_ord},
2850 {"chr", reduct_stdlib_chr},
2851 {"format", reduct_stdlib_format},
2852 {"now!", reduct_stdlib_now},
2853 {"uptime!", reduct_stdlib_uptime},
2854 {"env!", reduct_stdlib_env},
2855 {"args!", reduct_stdlib_args},
2856 };
2857 reduct_native_register(reduct, natives, sizeof(natives) / sizeof(reduct_native_t));
2858 }
2859 if (sets & REDUCT_STDLIB_MATH)
2860 {
2861 reduct_native_t natives[] = {
2862 {"min", reduct_stdlib_min},
2863 {"max", reduct_stdlib_max},
2864 {"clamp", reduct_stdlib_clamp},
2865 {"abs", reduct_stdlib_abs},
2866 {"floor", reduct_stdlib_floor},
2867 {"ceil", reduct_stdlib_ceil},
2868 {"round", reduct_stdlib_round},
2869 {"pow", reduct_stdlib_pow},
2870 {"exp", reduct_stdlib_exp},
2871 {"log", reduct_stdlib_log},
2872 {"sqrt", reduct_stdlib_sqrt},
2873 {"sin", reduct_stdlib_sin},
2874 {"cos", reduct_stdlib_cos},
2875 {"tan", reduct_stdlib_tan},
2876 {"asin", reduct_stdlib_asin},
2877 {"acos", reduct_stdlib_acos},
2878 {"atan", reduct_stdlib_atan},
2879 {"atan2", reduct_stdlib_atan2},
2880 {"sinh", reduct_stdlib_sinh},
2881 {"cosh", reduct_stdlib_cosh},
2882 {"tanh", reduct_stdlib_tanh},
2883 {"asinh", reduct_stdlib_asinh},
2884 {"acosh", reduct_stdlib_acosh},
2885 {"atanh", reduct_stdlib_atanh},
2886 {"rand", reduct_stdlib_rand},
2887 {"seed!", reduct_stdlib_seed},
2888 };
2889 reduct_native_register(reduct, natives, sizeof(natives) / sizeof(reduct_native_t));
2890 }
2891}
2892
2893#endif
Character handling.
Bytecode compilation.
Core definitions and structures.
#define REDUCT_ATANH(_x)
Definition defs.h:80
#define REDUCT_LOG(_x)
Definition defs.h:66
#define REDUCT_MIN(_a, _b)
Definition defs.h:123
#define REDUCT_MALLOC(_size)
Definition defs.h:27
#define REDUCT_STRLEN(s)
Definition defs.h:38
#define REDUCT_ROUND(_x)
Definition defs.h:63
size_t reduct_size_t
Definition defs.h:100
#define REDUCT_STDIN
Definition defs.h:53
#define REDUCT_ACOS(_x)
Definition defs.h:72
#define REDUCT_COSH(_x)
Definition defs.h:76
#define REDUCT_CEIL(_x)
Definition defs.h:62
#define REDUCT_SCRATCH_BUFFER_FREE(_name)
Scratch buffer free macro.
Definition defs.h:218
#define REDUCT_ATAN2(_y, _x)
Definition defs.h:74
#define REDUCT_RAND_MAX
Definition defs.h:85
#define REDUCT_COS(_x)
Definition defs.h:69
reduct_bool_t
Boolean type.
Definition defs.h:135
@ REDUCT_FALSE
Definition defs.h:137
@ REDUCT_TRUE
Definition defs.h:136
#define REDUCT_MEMCMP(_s1, _s2, _size)
Definition defs.h:34
#define REDUCT_FCLOSE(_file)
Definition defs.h:46
#define REDUCT_FGETC(_file)
Definition defs.h:49
#define REDUCT_FWRITE(_ptr, _size, _nmemb, _file)
Definition defs.h:48
#define REDUCT_SQRT(_x)
Definition defs.h:67
#define REDUCT_SCRATCH_BUFFER(_name, _size)
Scratch buffer macro.
Definition defs.h:201
#define REDUCT_CONTAINER_OF(_ptr, _type, _member)
Container of macro.
Definition defs.h:184
int64_t reduct_int64_t
Definition defs.h:92
#define REDUCT_TAN(_x)
Definition defs.h:70
#define REDUCT_FOPEN(_path, _mode)
Definition defs.h:45
#define REDUCT_EXP(_x)
Definition defs.h:65
#define REDUCT_TANH(_x)
Definition defs.h:77
#define REDUCT_MEMCPY(_dest, _src, _size)
Definition defs.h:33
reduct_uint64_t reduct_handle_t
Handle type.
Definition defs.h:189
#define REDUCT_TIME()
Definition defs.h:57
#define REDUCT_CLOCK()
Definition defs.h:58
FILE * reduct_file_t
Definition defs.h:44
double reduct_float_t
Definition defs.h:102
#define REDUCT_SRAND(_seed)
Definition defs.h:84
#define REDUCT_FREAD(_ptr, _size, _nmemb, _file)
Definition defs.h:47
#define REDUCT_ASSERT(_cond)
Definition defs.h:25
#define REDUCT_ATAN(_x)
Definition defs.h:73
#define REDUCT_POW(_x, _y)
Definition defs.h:64
#define REDUCT_SIN(_x)
Definition defs.h:68
#define REDUCT_FABS(_x)
Definition defs.h:81
#define REDUCT_FLOOR(_x)
Definition defs.h:61
#define REDUCT_PATH_MAX
Maximum path length for Reduct.
Definition defs.h:173
uint8_t reduct_uint8_t
Definition defs.h:99
#define REDUCT_FREE(_ptr)
Definition defs.h:30
#define REDUCT_RAND()
Definition defs.h:83
#define REDUCT_ACOSH(_x)
Definition defs.h:79
#define REDUCT_STDOUT
Definition defs.h:54
#define REDUCT_ASINH(_x)
Definition defs.h:78
#define REDUCT_API
Definition defs.h:7
#define REDUCT_SINH(_x)
Definition defs.h:75
#define REDUCT_MAX(_a, _b)
Definition defs.h:124
#define REDUCT_UNUSED(_x)
Definition defs.h:126
#define REDUCT_STACK_BUFFER_SIZE
The size of temporary stack allocated buffers.
Definition defs.h:191
#define REDUCT_NULL
Definition defs.h:23
#define REDUCT_ASIN(_x)
Definition defs.h:71
Virtual machine evaluation.
Garbage collection.
REDUCT_API reduct_atom_t * reduct_atom_lookup(struct reduct *reduct, const char *str, reduct_size_t len, reduct_atom_lookup_flags_t flags)
Lookup an atom in the Reduct structure.
@ REDUCT_ATOM_LOOKUP_NONE
No flags.
Definition atom.h:39
@ REDUCT_ATOM_LOOKUP_QUOTED
Atom should be explicitly quoted.
Definition atom.h:40
#define REDUCT_CHAR_TO_LOWER(_c)
Get the lowercase equivalent of a character.
Definition char.h:62
#define REDUCT_CHAR_TO_UPPER(_c)
Get the uppercase equivalent of a character.
Definition char.h:70
#define REDUCT_CHAR_IS_WHITESPACE(_c)
Check if a character is whitespace.
Definition char.h:78
REDUCT_API reduct_function_t * reduct_compile(reduct_t *reduct, reduct_handle_t *ast)
Compiles a Reduct AST into a callable bytecode function.
#define REDUCT_ERROR_RUNTIME(_reduct,...)
Throw a runtime error using the jump buffer in the error structure.
Definition error.h:175
#define REDUCT_ERROR()
Create a Reduct error structure.
Definition error.h:53
REDUCT_API void reduct_error_check_arity(struct reduct *reduct, reduct_size_t argc, reduct_size_t expected, const char *name)
Check the arity of a native function call.
#define REDUCT_ERROR_INTERNAL(_reduct,...)
Throw an internal error using the jump buffer in the error structure.
Definition error.h:183
#define REDUCT_ERROR_CATCH(_error)
Catch an error using the jump buffer in the error structure.
Definition error.h:115
#define REDUCT_ERROR_CHECK_LIST(_reduct, _handle, _name)
Assert that a handle is a list.
Definition error.h:198
REDUCT_API void reduct_error_check_arity_range(struct reduct *reduct, reduct_size_t argc, reduct_size_t min, reduct_size_t max, const char *name)
#define REDUCT_ERROR_CHECK_CALLABLE(_reduct, _handle, _name)
Assert that a handle is a callable.
Definition error.h:210
#define REDUCT_ERROR_CHECK_SEQUENCE(_reduct, _handle, _name)
Assert that a handle is a sequence (list or atom).
Definition error.h:222
REDUCT_API reduct_handle_t reduct_eval_call(reduct_t *reduct, reduct_handle_t callable, reduct_size_t argc, reduct_handle_t *argv)
Calls a Reduct callable (closure or native) with arguments.
Definition eval_impl.h:538
REDUCT_API reduct_handle_t reduct_eval(reduct_t *reduct, reduct_function_t *function)
Evaluates a compiled Reduct function.
#define REDUCT_GC_RETAIN(_reduct, _handle)
Retain an item, preventing it from being collected by the GC.
Definition gc.h:38
#define REDUCT_GC_RELEASE(_reduct, _handle)
Release a previously retained item, allowing it to be collected by the GC.
Definition gc.h:70
#define REDUCT_HANDLE_FALSE()
Constant false handle.
Definition handle.h:267
#define REDUCT_HANDLE_IS_LAMBDA(_handle)
Check if a handle is a lambda.
Definition handle.h:211
#define REDUCT_HANDLE_IS_NUMBER_SHAPED(_handle)
Check if a handle is a number or references a number shaped item.
Definition handle.h:162
#define REDUCT_HANDLE_FROM_LIST(_list)
Create a handle from a list pointer.
Definition handle.h:93
#define REDUCT_HANDLE_FROM_BOOL(_cond)
Create a boolean handle from a C condition.
Definition handle.h:276
#define REDUCT_HANDLE_TO_INT(_handle)
Get the integer value of a handle.
Definition handle.h:236
#define REDUCT_HANDLE_TO_ITEM(_handle)
Get the item pointer of a handle.
Definition handle.h:257
REDUCT_API void reduct_handle_promote(struct reduct *reduct, reduct_handle_t *a, reduct_handle_t *b, reduct_promotion_t *out)
Promote two handles to a common numeric type.
Definition handle_impl.h:54
REDUCT_API reduct_handle_t reduct_handle_nil(struct reduct *reduct)
Get the constant nil handle.
#define REDUCT_HANDLE_FROM_FLOAT(_val)
Create a handle from a float.
Definition handle.h:62
#define REDUCT_HANDLE_IS_CALLABLE(_handle)
Check if a handle is callable.
Definition handle.h:228
#define REDUCT_HANDLE_GET_TYPE(_handle)
Get the type of the item referenced by the handle, or REDUCT_ITEM_TYPE_ATOM if not an item.
Definition handle.h:153
#define REDUCT_HANDLE_IS_LIST(_handle)
Check if a handle is a list.
Definition handle.h:187
#define REDUCT_HANDLE_TO_FLOAT(_handle)
Get the float value of a handle.
Definition handle.h:244
#define REDUCT_HANDLE_FROM_ATOM(_atom)
Create a handle from an atom pointer.
Definition handle.h:85
#define REDUCT_HANDLE_FROM_INT(_val)
Create a handle from an integer.
Definition handle.h:54
REDUCT_API struct reduct_item * reduct_handle_item(struct reduct *reduct, reduct_handle_t *handle)
Ensure that a handle is an item and return the pointer.
#define REDUCT_HANDLE_NONE
Invalid handle constant.
Definition handle.h:36
REDUCT_API void reduct_handle_get_string_params(struct reduct *reduct, reduct_handle_t *handle, char **outStr, reduct_size_t *outLen)
Get the string pointer and length from an atom handle.
#define REDUCT_HANDLE_IS_TRUTHY(_handle)
Check if a handle is truthy.
Definition handle.h:338
REDUCT_API reduct_int64_t reduct_handle_compare(struct reduct *reduct, reduct_handle_t *a, reduct_handle_t *b)
Compare two items for ordering (less than, equal, or greater than).
#define REDUCT_HANDLE_IS_FLOAT_SHAPED(_handle)
Check if a handle is a float or references a float shaped item.
Definition handle.h:144
#define REDUCT_HANDLE_IS_INT_SHAPED(_handle)
Check if a handle is an integer of references a integer shaped item.
Definition handle.h:134
#define REDUCT_HANDLE_TRUE()
Constant true handle.
Definition handle.h:269
#define REDUCT_HANDLE_IS_NATIVE(_handle)
Check if a handle is a native function.
Definition handle.h:219
#define REDUCT_HANDLE_IS_ATOM(_handle)
Check if a handle is an atom.
Definition handle.h:179
@ REDUCT_PROMOTION_TYPE_INT
Definition handle.h:374
#define REDUCT_ITEM_TYPE_LIST
A list.
Definition item.h:28
REDUCT_API const char * reduct_item_type_str(reduct_item_type_t type)
Get the string representation of an Reduct item type.
Definition item_impl.h:139
#define REDUCT_ITEM_TYPE_ATOM
An atom.
Definition item.h:27
REDUCT_API void reduct_native_register(struct reduct *reduct, reduct_native_t *array, reduct_size_t count)
Register native functions.
REDUCT_API reduct_handle_t reduct_parse_file(reduct_t *reduct, const char *path)
Parse a Reduct file.
Definition parse_impl.h:388
REDUCT_API reduct_handle_t reduct_parse(reduct_t *reduct, const char *str, reduct_size_t len, const char *path)
Parse a Reduct string.
Definition parse_impl.h:369
REDUCT_API reduct_handle_t reduct_sqrt(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_round(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_is_empty(struct reduct *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_cosh(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_sin(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_any(struct reduct *reduct, reduct_handle_t *list, reduct_handle_t *callable)
REDUCT_API reduct_handle_t reduct_write_file(struct reduct *reduct, reduct_handle_t *path, reduct_handle_t *content)
REDUCT_API reduct_handle_t reduct_atan2(struct reduct *reduct, reduct_handle_t *y, reduct_handle_t *x)
REDUCT_API reduct_handle_t reduct_read_line(struct reduct *reduct)
REDUCT_API reduct_handle_t reduct_exp(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_acosh(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_acos(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_unique(struct reduct *reduct, reduct_handle_t *handle)
REDUCT_API reduct_handle_t reduct_max(struct reduct *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_chunk(struct reduct *reduct, reduct_handle_t *handle, reduct_handle_t *sizeH)
REDUCT_API reduct_handle_t reduct_asin(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_is_atom(struct reduct *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_read_char(struct reduct *reduct)
REDUCT_API reduct_handle_t reduct_sinh(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_env(struct reduct *reduct)
REDUCT_API reduct_handle_t reduct_chr(struct reduct *reduct, reduct_handle_t *handle)
REDUCT_API reduct_handle_t reduct_is_float(struct reduct *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_find(struct reduct *reduct, reduct_handle_t *handle, reduct_handle_t *callable)
REDUCT_API reduct_handle_t reduct_range(struct reduct *reduct, reduct_handle_t *start, reduct_handle_t *end, reduct_handle_t *step)
REDUCT_API reduct_handle_t reduct_is_lambda(struct reduct *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_contains(struct reduct *reduct, reduct_handle_t *handle, reduct_handle_t *target)
REDUCT_API reduct_handle_t reduct_cos(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_seed(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_get_float(struct reduct *reduct, reduct_handle_t *handle)
REDUCT_API reduct_handle_t reduct_is_int(struct reduct *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_is_list(struct reduct *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_dissoc(struct reduct *reduct, reduct_handle_t *handle, reduct_handle_t *index)
REDUCT_API reduct_handle_t reduct_ord(struct reduct *reduct, reduct_handle_t *handle)
REDUCT_API reduct_handle_t reduct_floor(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_flatten(struct reduct *reduct, reduct_handle_t *handle, reduct_handle_t *depthH)
REDUCT_API reduct_handle_t reduct_is_number(struct reduct *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_args(struct reduct *reduct)
REDUCT_API reduct_handle_t reduct_atan(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_is_nil(struct reduct *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_abs(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_all(struct reduct *reduct, reduct_handle_t *list, reduct_handle_t *callable)
REDUCT_API reduct_handle_t reduct_ceil(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_log(struct reduct *reduct, reduct_handle_t *val, reduct_handle_t *base)
REDUCT_API reduct_handle_t reduct_is_callable(struct reduct *reduct, reduct_size_t argc, reduct_handle_t *argv)
reduct_stdlib_sets_t
Built-in library sets.
Definition standard.h:25
REDUCT_API reduct_handle_t reduct_run(struct reduct *reduct, reduct_handle_t *handle)
REDUCT_API reduct_handle_t reduct_atanh(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_rand(struct reduct *reduct, reduct_handle_t *minVal, reduct_handle_t *maxVal)
REDUCT_API reduct_handle_t reduct_get_int(struct reduct *reduct, reduct_handle_t *handle)
REDUCT_API reduct_handle_t reduct_is_string(struct reduct *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_is_native(struct reduct *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_asinh(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_min(struct reduct *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_tanh(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_read_file(struct reduct *reduct, reduct_handle_t *path)
REDUCT_API reduct_handle_t reduct_replace(struct reduct *reduct, reduct_handle_t *handle, reduct_handle_t *oldVal, reduct_handle_t *newVal)
REDUCT_API reduct_handle_t reduct_tan(struct reduct *reduct, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_load(struct reduct *reduct, reduct_handle_t *path)
@ REDUCT_STDLIB_SEQUENCES
Definition standard.h:28
@ REDUCT_STDLIB_SYSTEM
Definition standard.h:32
@ REDUCT_STDLIB_HIGHER_ORDER
Definition standard.h:27
@ REDUCT_STDLIB_ERROR
Definition standard.h:26
@ REDUCT_STDLIB_STRING
Definition standard.h:29
@ REDUCT_STDLIB_INTROSPECTION
Definition standard.h:30
@ REDUCT_STDLIB_TYPE_CASTING
Definition standard.h:31
@ REDUCT_STDLIB_MATH
Definition standard.h:33
REDUCT_API reduct_size_t reduct_stringify(reduct_t *reduct, reduct_handle_t *handle, char *buffer, reduct_size_t size)
Converts a Reduct handle to its string representation.
Handle management.
Item management.
REDUCT_API reduct_handle_t reduct_list_nth(struct reduct *reduct, reduct_list_t *list, reduct_size_t index)
Get the nth element of the list.
Definition list_impl.h:157
REDUCT_API reduct_list_t * reduct_list_dissoc(struct reduct *reduct, reduct_list_t *list, reduct_size_t index)
Create a new list with the element at the specified index removed.
Definition list_impl.h:106
REDUCT_API reduct_list_t * reduct_list_assoc(struct reduct *reduct, reduct_list_t *list, reduct_size_t index, reduct_handle_t val)
Create a new list with an updated value at the specified index.
Definition list_impl.h:74
REDUCT_API reduct_list_t * reduct_list_slice(struct reduct *reduct, reduct_list_t *list, reduct_size_t start, reduct_size_t end)
Create a new list by slicing an existing list.
Definition list_impl.h:131
REDUCT_API void reduct_list_append(struct reduct *reduct, reduct_list_t *list, reduct_handle_t val)
Append an element to the list.
#define REDUCT_LIST_FOR_EACH(_handle, _list)
Macro for iterating over all elements in a list.
Definition list.h:181
REDUCT_API void reduct_list_append_list(struct reduct *reduct, reduct_list_t *list, reduct_list_t *other)
Append all elements from one list to another.
REDUCT_API reduct_list_t * reduct_list_new(struct reduct *reduct)
Create a new editable list.
Native function registration.
Parser.
Built-in library registration and operations.
static reduct_handle_t reduct_list_find_entry(reduct_t *reduct, reduct_item_t *listItem, reduct_handle_t *key)
REDUCT_API reduct_handle_t reduct_sort(reduct_t *reduct, reduct_handle_t *listHandle, reduct_handle_t *callableHandle)
static reduct_handle_t reduct_eval_maybe_call(reduct_t *reduct, reduct_handle_t fn, reduct_handle_t *arg)
REDUCT_API reduct_handle_t reduct_ends_with(reduct_t *reduct, reduct_handle_t *handle, reduct_handle_t *suffix)
REDUCT_API reduct_handle_t reduct_get_string(reduct_t *reduct, reduct_handle_t *handle)
REDUCT_API reduct_handle_t reduct_reduce(reduct_t *reduct, reduct_handle_t *list, reduct_handle_t *initial, reduct_handle_t *callable)
#define REDUCT_INT_ABS(_x)
REDUCT_API reduct_handle_t reduct_split(reduct_t *reduct, reduct_handle_t *srcHandle, reduct_handle_t *sepHandle)
REDUCT_API void reduct_stdlib_register(reduct_t *reduct, reduct_stdlib_sets_t sets)
#define REDUCT_STDLIB_WRAPPER_R34(_name, _impl)
REDUCT_API reduct_handle_t reduct_starts_with(reduct_t *reduct, reduct_handle_t *handle, reduct_handle_t *prefix)
#define REDUCT_STDLIB_WRAPPER_V1(_name, _impl)
#define REDUCT_MATH_UNARY_TO_INT_IMPL(_name, _float_func)
#define REDUCT_STDLIB_WRAPPER_0(_name, _impl)
#define REDUCT_PREDICATE_IS_EMPTY(_h)
REDUCT_API reduct_handle_t reduct_slice(reduct_t *reduct, reduct_handle_t *handle, reduct_handle_t *startH, reduct_handle_t *endH)
REDUCT_API reduct_handle_t reduct_trim(reduct_t *reduct, reduct_handle_t *srcHandle)
REDUCT_API reduct_handle_t reduct_concat(reduct_t *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_rest(reduct_t *reduct, reduct_handle_t *handle)
static reduct_handle_t reduct_stdlib_eval_impl(reduct_t *reduct, reduct_handle_t *arg)
#define REDUCT_STDLIB_WRAPPER_R23(_name, _impl)
REDUCT_API reduct_handle_t reduct_assoc(reduct_t *reduct, reduct_handle_t *handle, reduct_handle_t *index, reduct_handle_t *value, reduct_handle_t *fillVal)
REDUCT_API reduct_handle_t reduct_implode(reduct_t *reduct, reduct_size_t argc, reduct_handle_t *argv)
static char reduct_handle_get_char(reduct_t *reduct, reduct_handle_t *handle, char defaultChar)
REDUCT_API reduct_handle_t reduct_try(reduct_t *reduct, reduct_handle_t *callable, reduct_handle_t *catchFn)
REDUCT_API reduct_handle_t reduct_apply(reduct_t *reduct, reduct_handle_t *list, reduct_handle_t *callable)
REDUCT_API reduct_handle_t reduct_repeat(reduct_t *reduct, reduct_handle_t *handle, reduct_handle_t *count)
static reduct_handle_t reduct_stdlib_parse_impl(reduct_t *reduct, reduct_handle_t *arg)
#define REDUCT_GET_NUMERIC_IMPL(_name, _res, _type, _other, _targetUnion, _otherUnion)
static reduct_handle_t reduct_stdlib_println(reduct_t *reduct, reduct_size_t argc, reduct_handle_t *argv)
static void reduct_path_copy(reduct_t *reduct, char *dest, const char *src, reduct_size_t len, reduct_size_t max)
REDUCT_API reduct_handle_t reduct_index_of(reduct_t *reduct, reduct_handle_t *handle, reduct_handle_t *target)
#define REDUCT_INTROSPECTION_IMPL(_name, _predicate_macro)
static reduct_handle_t reduct_stdlib_repeat(reduct_t *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_now(reduct_t *reduct)
REDUCT_API reduct_handle_t reduct_throw(reduct_t *reduct, reduct_handle_t *msg)
REDUCT_API reduct_handle_t reduct_len(reduct_t *reduct, reduct_size_t argc, reduct_handle_t *argv)
#define REDUCT_STDLIB_WRAPPER_R12(_name, _impl)
REDUCT_API reduct_handle_t reduct_values(reduct_t *reduct, reduct_handle_t *listHandle)
REDUCT_API reduct_handle_t reduct_update(reduct_t *reduct, reduct_handle_t *handle, reduct_handle_t *index, reduct_handle_t *callable, reduct_handle_t *fillVal)
#define REDUCT_STDLIB_WRAPPER_3(_name, _impl)
REDUCT_API reduct_handle_t reduct_update_in(reduct_t *reduct, reduct_handle_t *list, reduct_handle_t *path, reduct_handle_t *callable)
REDUCT_API reduct_handle_t reduct_format(reduct_t *reduct, reduct_size_t argc, reduct_handle_t *argv)
static void reduct_resolve_path(reduct_t *reduct, const char *path, reduct_size_t pathLen, char *outPath, reduct_size_t maxLen)
REDUCT_API reduct_handle_t reduct_merge(reduct_t *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_assoc_in(reduct_t *reduct, reduct_handle_t *list, reduct_handle_t *path, reduct_handle_t *val)
REDUCT_API reduct_handle_t reduct_get_in(reduct_t *reduct, reduct_handle_t *list, reduct_handle_t *path, reduct_handle_t *defaultVal)
REDUCT_API reduct_handle_t reduct_keys(reduct_t *reduct, reduct_handle_t *listHandle)
REDUCT_API reduct_handle_t reduct_lower(reduct_t *reduct, reduct_handle_t *srcHandle)
static void reduct_sort_merge(reduct_t *reduct, reduct_handle_t callable, reduct_handle_t *a, reduct_size_t left, reduct_size_t right, reduct_size_t end, reduct_handle_t *b)
REDUCT_API reduct_handle_t reduct_filter(reduct_t *reduct, reduct_handle_t *list, reduct_handle_t *callable)
#define REDUCT_STDLIB_WRAPPER_2(_name, _impl)
static reduct_handle_t reduct_stdlib_range(reduct_t *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_first(reduct_t *reduct, reduct_handle_t *handle)
REDUCT_API reduct_handle_t reduct_assert(reduct_t *reduct, reduct_handle_t *cond, reduct_handle_t *msg)
REDUCT_API reduct_handle_t reduct_pow(reduct_t *reduct, reduct_handle_t *base, reduct_handle_t *exp)
REDUCT_API reduct_handle_t reduct_clamp(reduct_t *reduct, reduct_handle_t *val, reduct_handle_t *minVal, reduct_handle_t *maxVal)
REDUCT_API reduct_handle_t reduct_nth(reduct_t *reduct, reduct_handle_t *handle, reduct_handle_t *index, reduct_handle_t *defaultVal)
#define REDUCT_PREDICATE_IS_STRING(_h)
REDUCT_API reduct_handle_t reduct_print(reduct_t *reduct, reduct_size_t argc, reduct_handle_t *argv)
static reduct_int64_t reduct_handle_normalize_index(reduct_t *reduct, reduct_handle_t *index, reduct_size_t length)
REDUCT_API reduct_handle_t reduct_println(reduct_t *reduct, reduct_size_t argc, reduct_handle_t *argv)
static reduct_handle_t reduct_stdlib_reduce(reduct_t *reduct, reduct_size_t argc, reduct_handle_t *argv)
static reduct_handle_t reduct_sequence_trim(reduct_t *reduct, reduct_handle_t *handle, reduct_bool_t rest)
REDUCT_API reduct_handle_t reduct_dissoc_in(reduct_t *reduct, reduct_handle_t *list, reduct_handle_t *path)
REDUCT_API reduct_handle_t reduct_init(reduct_t *reduct, reduct_handle_t *handle)
static reduct_handle_t reduct_sequence_check_edge(reduct_t *reduct, reduct_handle_t *handle, reduct_handle_t *target, reduct_bool_t start, const char *name)
#define REDUCT_MATH_UNARY_FLOAT_IMPL(_name, _func)
REDUCT_API reduct_handle_t reduct_uptime(reduct_t *reduct)
REDUCT_API reduct_handle_t reduct_join(reduct_t *reduct, reduct_handle_t *listHandle, reduct_handle_t *sepHandle)
#define REDUCT_PREDICATE_IS_NIL(_h)
#define REDUCT_MATH_UNARY_IMPL(_name, _int_func, _float_func)
static reduct_handle_t reduct_list_project(reduct_t *reduct, reduct_handle_t *listHandle, reduct_size_t index, const char *name)
static reduct_handle_t reduct_stdlib_print(reduct_t *reduct, reduct_size_t argc, reduct_handle_t *argv)
REDUCT_API reduct_handle_t reduct_explode(reduct_t *reduct, reduct_size_t argc, reduct_handle_t *argv)
static reduct_handle_t reduct_sequence_edge(reduct_t *reduct, reduct_handle_t *handle, reduct_bool_t first)
static reduct_handle_t reduct_stdlib_format(reduct_t *reduct, reduct_size_t argc, reduct_handle_t *argv)
#define REDUCT_MATH_MIN_MAX_IMPL(_name, _op)
REDUCT_API reduct_handle_t reduct_upper(reduct_t *reduct, reduct_handle_t *srcHandle)
#define REDUCT_STDLIB_WRAPPER_1(_name, _impl)
REDUCT_API reduct_handle_t reduct_reverse(reduct_t *reduct, reduct_handle_t *handle)
static reduct_handle_t reduct_stdlib_concat(reduct_t *reduct, reduct_size_t argc, reduct_handle_t *argv)
static reduct_bool_t reduct_list_get_entry(reduct_t *reduct, reduct_handle_t *entryH, reduct_handle_t *outKey, reduct_handle_t *outVal)
static reduct_handle_t reduct_string_transform(reduct_t *reduct, reduct_handle_t *srcHandle, reduct_bool_t upper)
#define REDUCT_ANY_ALL_IMPL(_name, _predicate, _default)
#define REDUCT_STDLIB_WRAPPER_ARG2(_name, _impl)
REDUCT_API reduct_handle_t reduct_last(reduct_t *reduct, reduct_handle_t *handle)
static void reduct_sequence_normalize_range(reduct_t *reduct, reduct_handle_t *startH, reduct_handle_t *endH, reduct_size_t length, reduct_size_t *outStart, reduct_size_t *outEnd)
static void reduct_get_resolved_path(reduct_t *reduct, reduct_handle_t *pathHandle, char *outBuf)
REDUCT_API reduct_handle_t reduct_map(reduct_t *reduct, reduct_handle_t *list, reduct_handle_t *callable)
Stringification.
char * string
Pointer to the string.
Definition atom.h:53
Error structure.
Definition error.h:37
char message[REDUCT_ERROR_MAX_LEN]
Definition error.h:45
Evaluation frame structure.
Definition eval.h:29
struct reduct_closure * closure
The closure being evaluated.
Definition eval.h:30
Compiled function structure.
Definition function.h:78
Input structure.
Definition core.h:38
char path[REDUCT_PATH_MAX]
Definition core.h:43
Item structure.
Definition item.h:57
reduct_list_t list
A list.
Definition item.h:67
reduct_uint32_t length
Common length for the item. (Stored in the union to save space due to padding rules....
Definition item.h:65
struct reduct_input * input
The parsed input that created this item.
Definition item.h:58
reduct_atom_t atom
An atom.
Definition item.h:66
reduct_item_type_t type
The type of the item.
Definition item.h:61
List structure.
Definition list.h:48
Native function definition structure.
Definition native.h:32
Promotion result for numeric operations.
Definition handle.h:383
reduct_int64_t intVal
Definition handle.h:386
reduct_float_t floatVal
Definition handle.h:387
union reduct_promotion_t::@7 a
union reduct_promotion_t::@8 b
reduct_promotion_type_t type
Definition handle.h:384
State structure.
Definition core.h:61
reduct_error_t * error
Definition core.h:78
struct reduct_eval_state * evalState
Definition core.h:79