uni_core/
builtins.rs

1use crate::compat::Rc;
2use crate::interpreter::Interpreter;
3use crate::value::Value;
4
5use crate::primitives::{
6    // Basic math functions
7    abs_builtin,
8    // Basic arithmetic
9    add_builtin,
10    // Bitwise operations
11    bit_and_builtin,
12    bit_not_builtin,
13    bit_or_builtin,
14    bit_xor_builtin,
15    // List operations
16    cons_builtin,
17    construct_record_builtin,
18    // I/O operations
19    cr_builtin,
20    // Meta operations
21    def_builtin,
22    div_builtin,
23    doc_builtin,
24    // Stack operations
25    drop_builtin,
26    eq_builtin,
27    // Variable operations
28    fetch_builtin,  // @
29    floor_div_builtin,
30    from_r_builtin,
31    get_record_field_builtin,
32    greater_equal_builtin,
33    greater_than_builtin,
34    head_builtin,
35    help_builtin,
36    is_record_type_builtin,
37    less_equal_builtin,
38    // Comparison operations
39    less_than_builtin,
40    list_builtin,
41    list_to_vector_builtin,
42    make_record_type_builtin,
43    make_vector_builtin,
44    max_builtin,
45    min_builtin,
46    mod_builtin,
47    mul_builtin,
48    not_equal_builtin,
49    null_predicate_builtin,
50    pick_builtin,
51    // Control flow - if is now special in evaluator
52    // I/O operations
53    print_builtin,
54    words_builtin,
55    // Stack management
56    clear_builtin,
57    stack_builtin,
58    r_fetch_builtin,
59    record_type_of_builtin,
60    roll_builtin,
61    set_record_field_builtin,
62    // Shift operations
63    shl_builtin,
64    shr_builtin,
65    space_builtin,
66    store_builtin,  // !
67    sub_builtin,
68    tail_builtin,
69    // Return stack operations
70    to_r_builtin,
71    // String operations
72    to_string_builtin,
73    trunc_div_builtin,
74    // Predicate operations
75    truthy_predicate_builtin,
76    // Type introspection
77    type_of_builtin,
78    val_builtin,
79    var_builtin,
80    vector_builtin,
81    vector_length_builtin,
82    vector_ref_builtin,
83    vector_set_builtin,
84    vector_to_list_builtin,
85};
86
87// Advanced math operations (only with advanced_math feature)
88#[cfg(feature = "advanced_math")]
89use crate::primitives::{
90    ceil_builtin,
91    cos_builtin,
92    exp_builtin,
93    floor_builtin,
94    log_builtin,
95    pow_builtin,
96    round_builtin,
97    sin_builtin,
98    sqrt_builtin,
99    tan_builtin,
100};
101
102// Date/time operations (only with datetime feature)
103#[cfg(feature = "datetime")]
104use crate::primitives::{
105    date_add_builtin, date_equal_builtin, date_greater_than_builtin, date_less_than_builtin,
106    date_sub_builtin, datetime_builtin, datetime_to_string_builtin,
107    datetime_with_offset_builtin, day_builtin, duration_builtin, duration_equal_builtin,
108    duration_greater_than_builtin, duration_less_than_builtin, duration_to_seconds_builtin,
109    hour_builtin, minute_builtin, month_builtin, now_builtin, second_builtin,
110    string_to_datetime_builtin, timestamp_builtin, timestamp_to_datetime_builtin,
111    to_local_builtin, to_utc_builtin, weekday_builtin, year_builtin,
112};
113
114// I16 buffer operations (audio/DSP)
115use crate::primitives::{
116    i16_avg_builtin, i16_buffer_builtin, i16_length_builtin, i16_max_builtin, i16_min_builtin,
117    i16_pop_builtin, i16_push_builtin, i16_ref_builtin, i16_set_builtin,
118};
119
120// RUST CONCEPT: Registering all builtins with the interpreter
121pub fn register_builtins(interp: &mut Interpreter) {
122    use crate::interpreter::DictEntry;
123
124    // Arithmetic operations
125    let add_atom = interp.intern_atom("+");
126    interp.dictionary.insert(
127        add_atom,
128        DictEntry {
129            value: Value::Builtin(add_builtin),
130            is_executable: true,
131            doc: Some(Rc::<str>::from(
132                "Add two numbers or concatenate strings.\nUsage: a b + => result\nExamples: 5 3 + => 8\n\"Hello \" \"World\" + => \"Hello World\"",
133            )),
134        },
135    );
136
137    let sub_atom = interp.intern_atom("-");
138    interp.dictionary.insert(
139        sub_atom,
140        DictEntry {
141            value: Value::Builtin(sub_builtin),
142            is_executable: true,
143            doc: Some(Rc::<str>::from(
144                "Subtract two numbers.\nUsage: a b - => result\nExample: 10 3 - => 7",
145            )),
146        },
147    );
148
149    let mul_atom = interp.intern_atom("*");
150    interp.dictionary.insert(
151        mul_atom,
152        DictEntry {
153            value: Value::Builtin(mul_builtin),
154            is_executable: true,
155            doc: Some(Rc::<str>::from(
156                "Multiply two numbers.\nUsage: a b * => result\nExample: 6 7 * => 42",
157            )),
158        },
159    );
160
161    let div_atom = interp.intern_atom("/");
162    interp.dictionary.insert(
163        div_atom,
164        DictEntry {
165            value: Value::Builtin(div_builtin),
166            is_executable: true,
167            doc: Some(Rc::<str>::from(
168                "Divide two numbers.\nUsage: a b / => result\nExample: 15 3 / => 5",
169            )),
170        },
171    );
172
173    let floor_div_atom = interp.intern_atom("//");
174    interp.dictionary.insert(
175        floor_div_atom,
176        DictEntry {
177            value: Value::Builtin(floor_div_builtin),
178            is_executable: true,
179            doc: Some(Rc::<str>::from(
180                "Floor division (like Python's //).\nUsage: a b // => result\nExample: 7 2 // => 3, -7 2 // => -4",
181            )),
182        },
183    );
184
185    let mod_atom = interp.intern_atom("mod");
186    interp.dictionary.insert(
187        mod_atom,
188        DictEntry {
189            value: Value::Builtin(mod_builtin),
190            is_executable: true,
191            doc: Some(Rc::<str>::from(
192                "Calculate modulo (remainder after division).\nUsage: a b mod => remainder\nExample: 10 3 mod => 1",
193            )),
194        },
195    );
196
197    let trunc_div_atom = interp.intern_atom("div");
198    interp.dictionary.insert(
199        trunc_div_atom,
200        DictEntry {
201            value: Value::Builtin(trunc_div_builtin),
202            is_executable: true,
203            doc: Some(Rc::<str>::from(
204                "Truncating integer division (rounds toward zero).\nUsage: a b div => result\nExample: 7 2 div => 3, -7 2 div => -3",
205            )),
206        },
207    );
208
209    let eq_atom = interp.intern_atom("=");
210    interp.dictionary.insert(
211        eq_atom,
212        DictEntry {
213            value: Value::Builtin(eq_builtin),
214            is_executable: true,
215            doc: Some(Rc::<str>::from(
216                "Test equality of two values.\nUsage: a b = => boolean\nExample: 5 5 = => true",
217            )),
218        },
219    );
220
221    // Stack operations
222    let roll_atom = interp.intern_atom("roll");
223    interp.dictionary.insert(
224        roll_atom,
225        DictEntry {
226            value: Value::Builtin(roll_builtin),
227            is_executable: true,
228            doc: Some(Rc::<str>::from(
229                "Rotate n-th stack item to top.\nUsage: x1 x2 ... xn n roll => x2 ... xn x1\nExample: 1 2 3 2 roll => 2 3 1",
230            )),
231        },
232    );
233
234    let pick_atom = interp.intern_atom("pick");
235    interp.dictionary.insert(
236        pick_atom,
237        DictEntry {
238            value: Value::Builtin(pick_builtin),
239            is_executable: true,
240            doc: Some(Rc::<str>::from(
241                "Copy n-th stack item to top.\nUsage: x1 x2 ... xn n pick => x1 x2 ... xn x1\nExample: 1 2 3 2 pick => 1 2 3 1",
242            )),
243        },
244    );
245
246    let drop_atom = interp.intern_atom("drop");
247    interp.dictionary.insert(
248        drop_atom,
249        DictEntry {
250            value: Value::Builtin(drop_builtin),
251            is_executable: true,
252            doc: Some(Rc::<str>::from(
253                "Remove top stack item.\nUsage: x drop =>\nExample: 1 2 3 drop => 1 2",
254            )),
255        },
256    );
257
258    // NOTE: exec and if are now handled specially in the evaluator, not as builtins
259
260    // Dictionary operations
261    let def_atom = interp.intern_atom("def");
262    interp.dictionary.insert(
263        def_atom,
264        DictEntry {
265            value: Value::Builtin(def_builtin),
266            is_executable: true,
267            doc: Some(Rc::<str>::from(
268                "Define an executable word. Usage: 'name body def",
269            )),
270        },
271    );
272
273    let val_atom = interp.intern_atom("val");
274    interp.dictionary.insert(
275        val_atom,
276        DictEntry {
277            value: Value::Builtin(val_builtin),
278            is_executable: true,
279            doc: Some(Rc::<str>::from(
280                "Define a constant value. Usage: 'name value val",
281            )),
282        },
283    );
284
285    // Variable operations (Forth-style)
286    let var_atom = interp.intern_atom("var");
287    interp.dictionary.insert(
288        var_atom,
289        DictEntry {
290            value: Value::Builtin(var_builtin),
291            is_executable: true,
292            doc: Some(Rc::<str>::from(
293                "Create a mutable variable.\nUsage: initial-value 'name var\nExample: 0 'counter var",
294            )),
295        },
296    );
297
298    let fetch_atom = interp.intern_atom("@");
299    interp.dictionary.insert(
300        fetch_atom,
301        DictEntry {
302            value: Value::Builtin(fetch_builtin),
303            is_executable: true,
304            doc: Some(Rc::<str>::from(
305                "Fetch value from variable.\nUsage: var @ => value\nExample: counter @ .",
306            )),
307        },
308    );
309
310    let store_atom = interp.intern_atom("!");
311    interp.dictionary.insert(
312        store_atom,
313        DictEntry {
314            value: Value::Builtin(store_builtin),
315            is_executable: true,
316            doc: Some(Rc::<str>::from(
317                "Store value into variable.\nUsage: value var !\nExample: 42 counter !",
318            )),
319        },
320    );
321
322    let doc_atom = interp.intern_atom("doc");
323    interp.dictionary.insert(
324        doc_atom,
325        DictEntry {
326            value: Value::Builtin(doc_builtin),
327            is_executable: true,
328            doc: Some(Rc::<str>::from(
329                "Attach documentation to the most recent def/val.\nUsage: \"lines\" doc",
330            )),
331        },
332    );
333
334    let help_atom = interp.intern_atom("help");
335    interp.dictionary.insert(
336        help_atom,
337        DictEntry {
338            value: Value::Builtin(help_builtin),
339            is_executable: true,
340            doc: Some(Rc::<str>::from(
341                "Display documentation for a word. Usage: 'name help",
342            )),
343        },
344    );
345
346    // I/O operations
347    let print_atom = interp.intern_atom(".");
348    interp.dictionary.insert(
349        print_atom,
350        DictEntry {
351            value: Value::Builtin(print_builtin),
352            is_executable: true,
353            doc: Some(Rc::<str>::from(
354                "Print top stack value to output.\nUsage: value . => (prints value)\nExample: \"Hello\" . => Hello",
355            )),
356        },
357    );
358
359    let words_atom = interp.intern_atom("words");
360    interp.dictionary.insert(
361        words_atom,
362        DictEntry {
363            value: Value::Builtin(words_builtin),
364            is_executable: true,
365            doc: Some(Rc::<str>::from(
366                "Display all defined words in the dictionary.\nUsage: words => (displays all words)\nExample: words => Defined words (120): ...",
367            )),
368        },
369    );
370
371    let cr_atom = interp.intern_atom("cr");
372    interp.dictionary.insert(
373        cr_atom,
374        DictEntry {
375            value: Value::Builtin(cr_builtin),
376            is_executable: true,
377            doc: Some(Rc::<str>::from(
378                "Output a newline character.\nUsage: cr => (outputs newline)\nExample: \"Hello\" . cr \"World\" . cr",
379            )),
380        },
381    );
382
383    let space_atom = interp.intern_atom("space");
384    interp.dictionary.insert(
385        space_atom,
386        DictEntry {
387            value: Value::Builtin(space_builtin),
388            is_executable: true,
389            doc: Some(Rc::<str>::from(
390                "Output a space character.\nUsage: space => (outputs space)\nExample: \"Hello\" . space \"World\" .",
391            )),
392        },
393    );
394
395    // Stack management operations
396    let stack_atom = interp.intern_atom("stack");
397    interp.dictionary.insert(
398        stack_atom,
399        DictEntry {
400            value: Value::Builtin(stack_builtin),
401            is_executable: true,
402            doc: Some(Rc::<str>::from(
403                "Display the current stack contents.\nUsage: stack => (displays stack)\nExample: 1 2 3 stack => Stack (3 items): ...",
404            )),
405        },
406    );
407
408    let clear_atom = interp.intern_atom("clear");
409    interp.dictionary.insert(
410        clear_atom,
411        DictEntry {
412            value: Value::Builtin(clear_builtin),
413            is_executable: true,
414            doc: Some(Rc::<str>::from(
415                "Clear all items from the stack.\nUsage: clear => (empties stack)\nExample: 1 2 3 clear stack => Stack is empty",
416            )),
417        },
418    );
419
420    // I16 buffer operations (audio/DSP)
421    let i16_buffer_atom = interp.intern_atom("i16-buffer");
422    interp.dictionary.insert(
423        i16_buffer_atom,
424        DictEntry {
425            value: Value::Builtin(i16_buffer_builtin),
426            is_executable: true,
427            doc: Some(Rc::<str>::from(
428                "Create i16 buffer of specified size.\nUsage: size i16-buffer => buffer\nExample: 1024 i16-buffer => #<i16-buffer:1024:[0 0 0 0 0 0 0 0 ...]>",
429            )),
430        },
431    );
432
433    let i16_ref_atom = interp.intern_atom("i16-ref");
434    interp.dictionary.insert(
435        i16_ref_atom,
436        DictEntry {
437            value: Value::Builtin(i16_ref_builtin),
438            is_executable: true,
439            doc: Some(Rc::<str>::from(
440                "Get value at index from i16 buffer.\nUsage: buffer index i16-ref => value\nExample: buffer 0 i16-ref => 100",
441            )),
442        },
443    );
444
445    let i16_set_atom = interp.intern_atom("i16-set!");
446    interp.dictionary.insert(
447        i16_set_atom,
448        DictEntry {
449            value: Value::Builtin(i16_set_builtin),
450            is_executable: true,
451            doc: Some(Rc::<str>::from(
452                "Set value at index in i16 buffer.\nUsage: value buffer index i16-set! => buffer\nExample: 100 buffer 0 i16-set! => buffer",
453            )),
454        },
455    );
456
457    let i16_length_atom = interp.intern_atom("i16-length");
458    interp.dictionary.insert(
459        i16_length_atom,
460        DictEntry {
461            value: Value::Builtin(i16_length_builtin),
462            is_executable: true,
463            doc: Some(Rc::<str>::from(
464                "Get length of i16 buffer.\nUsage: buffer i16-length => buffer length\nExample: buffer i16-length => buffer 1024",
465            )),
466        },
467    );
468
469    let i16_push_atom = interp.intern_atom("i16-push!");
470    interp.dictionary.insert(
471        i16_push_atom,
472        DictEntry {
473            value: Value::Builtin(i16_push_builtin),
474            is_executable: true,
475            doc: Some(Rc::<str>::from(
476                "Append value to end of i16 buffer.\nUsage: value buffer i16-push! => buffer\nExample: 100 buffer i16-push! => buffer",
477            )),
478        },
479    );
480
481    let i16_pop_atom = interp.intern_atom("i16-pop!");
482    interp.dictionary.insert(
483        i16_pop_atom,
484        DictEntry {
485            value: Value::Builtin(i16_pop_builtin),
486            is_executable: true,
487            doc: Some(Rc::<str>::from(
488                "Remove and return last value from i16 buffer.\nUsage: buffer i16-pop! => buffer value\nExample: buffer i16-pop! => buffer 100",
489            )),
490        },
491    );
492
493    let i16_max_atom = interp.intern_atom("i16-max");
494    interp.dictionary.insert(
495        i16_max_atom,
496        DictEntry {
497            value: Value::Builtin(i16_max_builtin),
498            is_executable: true,
499            doc: Some(Rc::<str>::from(
500                "Find maximum value in i16 buffer.\nUsage: buffer i16-max => buffer max-value\nExample: buffer i16-max => buffer 1000",
501            )),
502        },
503    );
504
505    let i16_min_atom = interp.intern_atom("i16-min");
506    interp.dictionary.insert(
507        i16_min_atom,
508        DictEntry {
509            value: Value::Builtin(i16_min_builtin),
510            is_executable: true,
511            doc: Some(Rc::<str>::from(
512                "Find minimum value in i16 buffer.\nUsage: buffer i16-min => buffer min-value\nExample: buffer i16-min => buffer -500",
513            )),
514        },
515    );
516
517    let i16_avg_atom = interp.intern_atom("i16-avg");
518    interp.dictionary.insert(
519        i16_avg_atom,
520        DictEntry {
521            value: Value::Builtin(i16_avg_builtin),
522            is_executable: true,
523            doc: Some(Rc::<str>::from(
524                "Compute average value of i16 buffer.\nUsage: buffer i16-avg => buffer average\nExample: buffer i16-avg => buffer 250",
525            )),
526        },
527    );
528
529    // String operations
530    let to_string_atom = interp.intern_atom("->string");
531    interp.dictionary.insert(
532        to_string_atom,
533        DictEntry {
534            value: Value::Builtin(to_string_builtin),
535            is_executable: true,
536            doc: Some(Rc::<str>::from(
537                "Convert value to string representation.\nUsage: value ->string => string\nExample: 42 ->string => \"42\"",
538            )),
539        },
540    );
541
542    // List operations
543    let head_atom = interp.intern_atom("head");
544    interp.dictionary.insert(
545        head_atom,
546        DictEntry {
547            value: Value::Builtin(head_builtin),
548            is_executable: true,
549            doc: Some(Rc::<str>::from(
550                "Get first element of a list.\nUsage: [x y z] head => x\nExample: [1 2 3] head => 1",
551            )),
552        },
553    );
554
555    let tail_atom = interp.intern_atom("tail");
556    interp.dictionary.insert(
557        tail_atom,
558        DictEntry {
559            value: Value::Builtin(tail_builtin),
560            is_executable: true,
561            doc: Some(Rc::<str>::from(
562                "Get all but first element of a list.\nUsage: [x y z] tail => [y z]\nExample: [1 2 3] tail => [2 3]",
563            )),
564        },
565    );
566
567    let cons_atom = interp.intern_atom("cons");
568    interp.dictionary.insert(
569        cons_atom,
570        DictEntry {
571            value: Value::Builtin(cons_builtin),
572            is_executable: true,
573            doc: Some(Rc::<str>::from(
574                "Prepend element to list (construct cons cell).\nUsage: x [y z] cons => [x y z]\nExample: 1 [2 3] cons => [1 2 3]",
575            )),
576        },
577    );
578
579    let list_atom = interp.intern_atom("list");
580    interp.dictionary.insert(
581        list_atom,
582        DictEntry {
583            value: Value::Builtin(list_builtin),
584            is_executable: true,
585            doc: Some(Rc::<str>::from(
586                "Convert all stack items into a list.\nUsage: x y z n list => [x y z]\nExample: 1 2 3 3 list => [1 2 3]",
587            )),
588        },
589    );
590
591    let vector_atom = interp.intern_atom("vector");
592    interp.dictionary.insert(
593        vector_atom,
594        DictEntry {
595            value: Value::Builtin(vector_builtin),
596            is_executable: true,
597            doc: Some(Rc::<str>::from(
598                "Create vector from stack items.\nUsage: x y z n vector => #[x y z]\nExample: 1 2 3 3 vector => #[1 2 3]",
599            )),
600        },
601    );
602
603    let make_vector_atom = interp.intern_atom("make-vector");
604    interp.dictionary.insert(
605        make_vector_atom,
606        DictEntry {
607            value: Value::Builtin(make_vector_builtin),
608            is_executable: true,
609            doc: Some(Rc::<str>::from(
610                "Create vector of size n filled with value.\nUsage: n value make-vector => #[value ...]\nExample: 3 0 make-vector => #[0 0 0]",
611            )),
612        },
613    );
614
615    let vector_length_atom = interp.intern_atom("vector-length");
616    interp.dictionary.insert(
617        vector_length_atom,
618        DictEntry {
619            value: Value::Builtin(vector_length_builtin),
620            is_executable: true,
621            doc: Some(Rc::<str>::from(
622                "Get length of a vector.\nUsage: #[a b c] vector-length => 3\nExample: #[1 2 3] vector-length => 3",
623            )),
624        },
625    );
626
627    let vector_ref_atom = interp.intern_atom("vector-ref");
628    interp.dictionary.insert(
629        vector_ref_atom,
630        DictEntry {
631            value: Value::Builtin(vector_ref_builtin),
632            is_executable: true,
633            doc: Some(Rc::<str>::from(
634                "Get element at index from vector.\nUsage: #[a b c] i vector-ref => element\nExample: #[10 20 30] 1 vector-ref => 20",
635            )),
636        },
637    );
638
639    let vector_set_atom = interp.intern_atom("vector-set!");
640    interp.dictionary.insert(
641        vector_set_atom,
642        DictEntry {
643            value: Value::Builtin(vector_set_builtin),
644            is_executable: true,
645            doc: Some(Rc::<str>::from(
646                "Set element at index in vector.\nUsage: value #[a b c] i vector-set! => #[a value c]\nExample: 99 #[10 20 30] 1 vector-set! => #[10 99 30]",
647            )),
648        },
649    );
650
651    let vector_to_list_atom = interp.intern_atom("vector->list");
652    interp.dictionary.insert(
653        vector_to_list_atom,
654        DictEntry {
655            value: Value::Builtin(vector_to_list_builtin),
656            is_executable: true,
657            doc: Some(Rc::<str>::from(
658                "Convert vector to list.\nUsage: #[a b c] vector->list => [a b c]\nExample: #[1 2 3] vector->list => [1 2 3]",
659            )),
660        },
661    );
662
663    let list_to_vector_atom = interp.intern_atom("list->vector");
664    interp.dictionary.insert(
665        list_to_vector_atom,
666        DictEntry {
667            value: Value::Builtin(list_to_vector_builtin),
668            is_executable: true,
669            doc: Some(Rc::<str>::from(
670                "Convert list to vector.\nUsage: [a b c] list->vector => #[a b c]\nExample: [1 2 3] list->vector => #[1 2 3]",
671            )),
672        },
673    );
674
675    // Type checking predicates
676    let null_predicate_atom = interp.intern_atom("null?");
677    interp.dictionary.insert(
678        null_predicate_atom,
679        DictEntry {
680            value: Value::Builtin(null_predicate_builtin),
681            is_executable: true,
682            doc: Some(Rc::<str>::from(
683                "Test if value is null.\nUsage: value null? => boolean\nExample: null null? => true",
684            )),
685        },
686    );
687
688    let truthy_predicate_atom = interp.intern_atom("truthy?");
689    interp.dictionary.insert(
690        truthy_predicate_atom,
691        DictEntry {
692            value: Value::Builtin(truthy_predicate_builtin),
693            is_executable: true,
694            doc: Some(Rc::<str>::from(
695                "Test if value is truthy (non-null, non-false, non-zero).\nUsage: value truthy? => boolean\nExample: 5 truthy? => true",
696            )),
697        },
698    );
699
700    let type_of_atom = interp.intern_atom("type");
701    interp.dictionary.insert(
702        type_of_atom,
703        DictEntry {
704            value: Value::Builtin(type_of_builtin),
705            is_executable: true,
706            doc: Some(Rc::<str>::from(
707                "( x -- string ) Return type name of value as a string.\nTypes: number, integer, rational, gaussian, complex, atom, string, boolean, null, list, vector, nil, builtin",
708            )),
709        },
710    );
711
712    // Comparison operations
713    let less_than_atom = interp.intern_atom("<");
714    interp.dictionary.insert(
715        less_than_atom,
716        DictEntry {
717            value: Value::Builtin(less_than_builtin),
718            is_executable: true,
719            doc: Some(Rc::<str>::from(
720                "Test if first number is less than second.\nUsage: a b < => boolean\nExample: 3 5 < => true",
721            )),
722        },
723    );
724
725    let greater_than_atom = interp.intern_atom(">");
726    interp.dictionary.insert(
727        greater_than_atom,
728        DictEntry {
729            value: Value::Builtin(greater_than_builtin),
730            is_executable: true,
731            doc: Some(Rc::<str>::from(
732                "Test if first number is greater than second.\nUsage: a b > => boolean\nExample: 5 3 > => true",
733            )),
734        },
735    );
736
737    let less_equal_atom = interp.intern_atom("<=");
738    interp.dictionary.insert(
739        less_equal_atom,
740        DictEntry {
741            value: Value::Builtin(less_equal_builtin),
742            is_executable: true,
743            doc: Some(Rc::<str>::from(
744                "Test if first number is less than or equal to second.\nUsage: a b <= => boolean\nExample: 3 3 <= => true",
745            )),
746        },
747    );
748
749    let greater_equal_atom = interp.intern_atom(">=");
750    interp.dictionary.insert(
751        greater_equal_atom,
752        DictEntry {
753            value: Value::Builtin(greater_equal_builtin),
754            is_executable: true,
755            doc: Some(Rc::<str>::from(
756                "Test if first number is greater than or equal to second.\nUsage: a b >= => boolean\nExample: 5 5 >= => true",
757            )),
758        },
759    );
760
761    let not_equal_atom = interp.intern_atom("!=");
762    interp.dictionary.insert(
763        not_equal_atom,
764        DictEntry {
765            value: Value::Builtin(not_equal_builtin),
766            is_executable: true,
767            doc: Some(Rc::<str>::from(
768                "Test if two values are not equal.\nUsage: a b != => boolean\nExample: 5 3 != => true",
769            )),
770        },
771    );
772
773    // Basic math functions
774    let abs_atom = interp.intern_atom("abs");
775    interp.dictionary.insert(
776        abs_atom,
777        DictEntry {
778            value: Value::Builtin(abs_builtin),
779            is_executable: true,
780            doc: Some(Rc::<str>::from(
781                "Calculate absolute value.\nUsage: n abs => |n|\nExample: -5 abs => 5",
782            )),
783        },
784    );
785
786    let min_atom = interp.intern_atom("min");
787    interp.dictionary.insert(
788        min_atom,
789        DictEntry {
790            value: Value::Builtin(min_builtin),
791            is_executable: true,
792            doc: Some(Rc::<str>::from(
793                "Return minimum of two numbers.\nUsage: a b min => min(a,b)\nExample: 3 7 min => 3",
794            )),
795        },
796    );
797
798    let max_atom = interp.intern_atom("max");
799    interp.dictionary.insert(
800        max_atom,
801        DictEntry {
802            value: Value::Builtin(max_builtin),
803            is_executable: true,
804            doc: Some(Rc::<str>::from(
805                "Return maximum of two numbers.\nUsage: a b max => max(a,b)\nExample: 3 7 max => 7",
806            )),
807        },
808    );
809
810    #[cfg(feature = "advanced_math")]
811    {
812    let sqrt_atom = interp.intern_atom("sqrt");
813    interp.dictionary.insert(
814        sqrt_atom,
815        DictEntry {
816            value: Value::Builtin(sqrt_builtin),
817            is_executable: true,
818            doc: Some(Rc::<str>::from(
819                "Calculate square root.\nUsage: n sqrt => √n\nExample: 16 sqrt => 4",
820            )),
821        },
822    );
823    }
824
825    // Advanced math functions
826    #[cfg(feature = "advanced_math")]
827    {
828    let pow_atom = interp.intern_atom("pow");
829    interp.dictionary.insert(
830        pow_atom,
831        DictEntry {
832            value: Value::Builtin(pow_builtin),
833            is_executable: true,
834            doc: Some(Rc::<str>::from(
835                "Raise number to power.\nUsage: base exponent pow => base^exponent\nExample: 2 8 pow => 256",
836            )),
837        },
838    );
839    }
840
841    #[cfg(feature = "advanced_math")]
842    {
843    let floor_atom = interp.intern_atom("floor");
844    interp.dictionary.insert(
845        floor_atom,
846        DictEntry {
847            value: Value::Builtin(floor_builtin),
848            is_executable: true,
849            doc: Some(Rc::<str>::from(
850                "Round down to nearest integer.\nUsage: n floor => ⌊n⌋\nExample: 3.7 floor => 3",
851            )),
852        },
853    );
854    }
855
856    #[cfg(feature = "advanced_math")]
857    {
858    let ceil_atom = interp.intern_atom("ceil");
859    interp.dictionary.insert(
860        ceil_atom,
861        DictEntry {
862            value: Value::Builtin(ceil_builtin),
863            is_executable: true,
864            doc: Some(Rc::<str>::from(
865                "Round up to nearest integer.\nUsage: n ceil => ⌈n⌉\nExample: 3.2 ceil => 4",
866            )),
867        },
868    );
869    }
870
871    #[cfg(feature = "advanced_math")]
872    {
873    let round_atom = interp.intern_atom("round");
874    interp.dictionary.insert(
875        round_atom,
876        DictEntry {
877            value: Value::Builtin(round_builtin),
878            is_executable: true,
879            doc: Some(Rc::<str>::from(
880                "Round to nearest integer.\nUsage: n round => round(n)\nExample: 3.5 round => 4",
881            )),
882        },
883    );
884    }
885
886    // Trigonometric functions
887    #[cfg(feature = "advanced_math")]
888    {
889    let sin_atom = interp.intern_atom("sin");
890    interp.dictionary.insert(
891        sin_atom,
892        DictEntry {
893            value: Value::Builtin(sin_builtin),
894            is_executable: true,
895            doc: Some(Rc::<str>::from(
896                "Calculate sine (radians).\nUsage: radians sin => sin(radians)\nExample: 0 sin => 0",
897            )),
898        },
899    );
900    }
901
902    #[cfg(feature = "advanced_math")]
903    {
904    let cos_atom = interp.intern_atom("cos");
905    interp.dictionary.insert(
906        cos_atom,
907        DictEntry {
908            value: Value::Builtin(cos_builtin),
909            is_executable: true,
910            doc: Some(Rc::<str>::from(
911                "Calculate cosine (radians).\nUsage: radians cos => cos(radians)\nExample: 0 cos => 1",
912            )),
913        },
914    );
915    }
916
917    #[cfg(feature = "advanced_math")]
918    {
919    let tan_atom = interp.intern_atom("tan");
920    interp.dictionary.insert(
921        tan_atom,
922        DictEntry {
923            value: Value::Builtin(tan_builtin),
924            is_executable: true,
925            doc: Some(Rc::<str>::from(
926                "Calculate tangent (radians).\nUsage: radians tan => tan(radians)\nExample: 0 tan => 0",
927            )),
928        },
929    );
930    }
931
932    // Logarithmic functions
933    #[cfg(feature = "advanced_math")]
934    {
935    let log_atom = interp.intern_atom("log");
936    interp.dictionary.insert(
937        log_atom,
938        DictEntry {
939            value: Value::Builtin(log_builtin),
940            is_executable: true,
941            doc: Some(Rc::<str>::from(
942                "Calculate natural logarithm.\nUsage: n log => ln(n)\nExample: 2.718281828 log => 1",
943            )),
944        },
945    );
946    }
947
948    #[cfg(feature = "advanced_math")]
949    {
950    let exp_atom = interp.intern_atom("exp");
951    interp.dictionary.insert(
952        exp_atom,
953        DictEntry {
954            value: Value::Builtin(exp_builtin),
955            is_executable: true,
956            doc: Some(Rc::<str>::from(
957                "Calculate e raised to power.\nUsage: n exp => e^n\nExample: 1 exp => 2.718281828",
958            )),
959        },
960    );
961    }
962
963    // Bitwise operations
964    let bit_and_atom = interp.intern_atom("bit-and");
965    interp.dictionary.insert(
966        bit_and_atom,
967        DictEntry {
968            value: Value::Builtin(bit_and_builtin),
969            is_executable: true,
970            doc: Some(Rc::<str>::from(
971                "Bitwise AND of two integers.\nUsage: a b bit-and => a&b\nExample: 12 10 bit-and => 8",
972            )),
973        },
974    );
975
976    let bit_or_atom = interp.intern_atom("bit-or");
977    interp.dictionary.insert(
978        bit_or_atom,
979        DictEntry {
980            value: Value::Builtin(bit_or_builtin),
981            is_executable: true,
982            doc: Some(Rc::<str>::from(
983                "Bitwise OR of two integers.\nUsage: a b bit-or => a|b\nExample: 12 10 bit-or => 14",
984            )),
985        },
986    );
987
988    let bit_xor_atom = interp.intern_atom("bit-xor");
989    interp.dictionary.insert(
990        bit_xor_atom,
991        DictEntry {
992            value: Value::Builtin(bit_xor_builtin),
993            is_executable: true,
994            doc: Some(Rc::<str>::from(
995                "Bitwise XOR of two integers.\nUsage: a b bit-xor => a^b\nExample: 12 10 bit-xor => 6",
996            )),
997        },
998    );
999
1000    let bit_not_atom = interp.intern_atom("bit-not");
1001    interp.dictionary.insert(
1002        bit_not_atom,
1003        DictEntry {
1004            value: Value::Builtin(bit_not_builtin),
1005            is_executable: true,
1006            doc: Some(Rc::<str>::from(
1007                "Bitwise NOT (complement) of integer.\nUsage: n bit-not => ~n\nExample: 5 bit-not => -6",
1008            )),
1009        },
1010    );
1011
1012    // Shift operations
1013    let shl_atom = interp.intern_atom("shl");
1014    interp.dictionary.insert(
1015        shl_atom,
1016        DictEntry {
1017            value: Value::Builtin(shl_builtin),
1018            is_executable: true,
1019            doc: Some(Rc::<str>::from(
1020                "Shift bits left.\nUsage: n count shl => n<<count\nExample: 5 2 shl => 20",
1021            )),
1022        },
1023    );
1024
1025    let shr_atom = interp.intern_atom("shr");
1026    interp.dictionary.insert(
1027        shr_atom,
1028        DictEntry {
1029            value: Value::Builtin(shr_builtin),
1030            is_executable: true,
1031            doc: Some(Rc::<str>::from(
1032                "Shift bits right.\nUsage: n count shr => n>>count\nExample: 20 2 shr => 5",
1033            )),
1034        },
1035    );
1036
1037    // Return stack operations
1038    let to_r_atom = interp.intern_atom(">r");
1039    interp.dictionary.insert(
1040        to_r_atom,
1041        DictEntry {
1042            value: Value::Builtin(to_r_builtin),
1043            is_executable: true,
1044            doc: Some(Rc::<str>::from(
1045                "Move value from data stack to return stack.\nUsage: x >r => (moves x to return stack)\nExample: 5 >r => (5 now on return stack)",
1046            )),
1047        },
1048    );
1049
1050    let from_r_atom = interp.intern_atom("r>");
1051    interp.dictionary.insert(
1052        from_r_atom,
1053        DictEntry {
1054            value: Value::Builtin(from_r_builtin),
1055            is_executable: true,
1056            doc: Some(Rc::<str>::from(
1057                "Move value from return stack to data stack.\nUsage: r> => x\nExample: r> => (moves top of return stack to data stack)",
1058            )),
1059        },
1060    );
1061
1062    let r_fetch_atom = interp.intern_atom("r@");
1063    interp.dictionary.insert(
1064        r_fetch_atom,
1065        DictEntry {
1066            value: Value::Builtin(r_fetch_builtin),
1067            is_executable: true,
1068            doc: Some(Rc::<str>::from(
1069                "Copy top of return stack to data stack.\nUsage: r@ => x\nExample: r@ => (copies top of return stack without removing it)",
1070            )),
1071        },
1072    );
1073
1074    // Record operations
1075    let make_record_type_atom = interp.intern_atom("make-record-type");
1076    interp.dictionary.insert(
1077        make_record_type_atom,
1078        DictEntry {
1079            value: Value::Builtin(make_record_type_builtin),
1080            is_executable: true,
1081            doc: Some(Rc::<str>::from(
1082                "Create a record type with named fields.\nUsage: [field-names...] \"type-name\" make-record-type => record-type\nExample: [\"name\" \"age\"] \"person\" make-record-type",
1083            )),
1084        },
1085    );
1086
1087    let construct_record_atom = interp.intern_atom("construct-record");
1088    interp.dictionary.insert(
1089        construct_record_atom,
1090        DictEntry {
1091            value: Value::Builtin(construct_record_builtin),
1092            is_executable: true,
1093            doc: Some(Rc::<str>::from(
1094                "Internal helper to construct record instances.\nUsage: field-values... n \"type-name\" construct-record => record",
1095            )),
1096        },
1097    );
1098
1099    let is_record_type_atom = interp.intern_atom("is-record-type?");
1100    interp.dictionary.insert(
1101        is_record_type_atom,
1102        DictEntry {
1103            value: Value::Builtin(is_record_type_builtin),
1104            is_executable: true,
1105            doc: Some(Rc::<str>::from(
1106                "Check if value is a record of specific type.\nUsage: value \"type-name\" is-record-type? => boolean",
1107            )),
1108        },
1109    );
1110
1111    let get_record_field_atom = interp.intern_atom("get-record-field");
1112    interp.dictionary.insert(
1113        get_record_field_atom,
1114        DictEntry {
1115            value: Value::Builtin(get_record_field_builtin),
1116            is_executable: true,
1117            doc: Some(Rc::<str>::from(
1118                "Get field value from record.\nUsage: record \"type-name\" field-index get-record-field => value",
1119            )),
1120        },
1121    );
1122
1123    let set_record_field_atom = interp.intern_atom("set-record-field!");
1124    interp.dictionary.insert(
1125        set_record_field_atom,
1126        DictEntry {
1127            value: Value::Builtin(set_record_field_builtin),
1128            is_executable: true,
1129            doc: Some(Rc::<str>::from(
1130                "Set field value in record.\nUsage: new-value record \"type-name\" field-index set-record-field! => record",
1131            )),
1132        },
1133    );
1134
1135    let record_type_of_atom = interp.intern_atom("record-type-of");
1136    interp.dictionary.insert(
1137        record_type_of_atom,
1138        DictEntry {
1139            value: Value::Builtin(record_type_of_builtin),
1140            is_executable: true,
1141            doc: Some(Rc::<str>::from(
1142                "Get type name from record instance.\nUsage: record record-type-of => \"type-name\"",
1143            )),
1144        },
1145    );
1146
1147    // Date/time operations (only with datetime feature)
1148    #[cfg(feature = "datetime")]
1149    {
1150    let now_atom = interp.intern_atom("now");
1151    interp.dictionary.insert(
1152        now_atom,
1153        DictEntry {
1154            value: Value::Builtin(now_builtin),
1155            is_executable: true,
1156            doc: Some(Rc::<str>::from(
1157                "Get current date/time in local timezone.\nUsage: now => datetime",
1158            )),
1159        },
1160    );
1161
1162    let datetime_atom = interp.intern_atom("datetime");
1163    interp.dictionary.insert(
1164        datetime_atom,
1165        DictEntry {
1166            value: Value::Builtin(datetime_builtin),
1167            is_executable: true,
1168            doc: Some(Rc::<str>::from(
1169                "Create datetime in local timezone.\nUsage: year month day hour minute second datetime => datetime\nExample: 2025 10 1 14 30 0 datetime",
1170            )),
1171        },
1172    );
1173
1174    let datetime_with_offset_atom = interp.intern_atom("datetime-with-offset");
1175    interp.dictionary.insert(
1176        datetime_with_offset_atom,
1177        DictEntry {
1178            value: Value::Builtin(datetime_with_offset_builtin),
1179            is_executable: true,
1180            doc: Some(Rc::<str>::from(
1181                "Create datetime with specific offset.\nUsage: year month day hour minute second offset-hours datetime-with-offset => datetime\nExample: 2025 10 1 14 30 0 -5 datetime-with-offset",
1182            )),
1183        },
1184    );
1185
1186    let year_atom = interp.intern_atom("year");
1187    interp.dictionary.insert(
1188        year_atom,
1189        DictEntry {
1190            value: Value::Builtin(year_builtin),
1191            is_executable: true,
1192            doc: Some(Rc::<str>::from(
1193                "Extract year from datetime.\nUsage: datetime year => year",
1194            )),
1195        },
1196    );
1197
1198    let month_atom = interp.intern_atom("month");
1199    interp.dictionary.insert(
1200        month_atom,
1201        DictEntry {
1202            value: Value::Builtin(month_builtin),
1203            is_executable: true,
1204            doc: Some(Rc::<str>::from(
1205                "Extract month (1-12) from datetime.\nUsage: datetime month => month",
1206            )),
1207        },
1208    );
1209
1210    let day_atom = interp.intern_atom("day");
1211    interp.dictionary.insert(
1212        day_atom,
1213        DictEntry {
1214            value: Value::Builtin(day_builtin),
1215            is_executable: true,
1216            doc: Some(Rc::<str>::from(
1217                "Extract day (1-31) from datetime.\nUsage: datetime day => day",
1218            )),
1219        },
1220    );
1221
1222    let hour_atom = interp.intern_atom("hour");
1223    interp.dictionary.insert(
1224        hour_atom,
1225        DictEntry {
1226            value: Value::Builtin(hour_builtin),
1227            is_executable: true,
1228            doc: Some(Rc::<str>::from(
1229                "Extract hour (0-23) from datetime.\nUsage: datetime hour => hour",
1230            )),
1231        },
1232    );
1233
1234    let minute_atom = interp.intern_atom("minute");
1235    interp.dictionary.insert(
1236        minute_atom,
1237        DictEntry {
1238            value: Value::Builtin(minute_builtin),
1239            is_executable: true,
1240            doc: Some(Rc::<str>::from(
1241                "Extract minute (0-59) from datetime.\nUsage: datetime minute => minute",
1242            )),
1243        },
1244    );
1245
1246    let second_atom = interp.intern_atom("second");
1247    interp.dictionary.insert(
1248        second_atom,
1249        DictEntry {
1250            value: Value::Builtin(second_builtin),
1251            is_executable: true,
1252            doc: Some(Rc::<str>::from(
1253                "Extract second (0-59) from datetime.\nUsage: datetime second => second",
1254            )),
1255        },
1256    );
1257
1258    let weekday_atom = interp.intern_atom("weekday");
1259    interp.dictionary.insert(
1260        weekday_atom,
1261        DictEntry {
1262            value: Value::Builtin(weekday_builtin),
1263            is_executable: true,
1264            doc: Some(Rc::<str>::from(
1265                "Get day of week (0=Monday, 6=Sunday) from datetime.\nUsage: datetime weekday => weekday",
1266            )),
1267        },
1268    );
1269
1270    let timestamp_atom = interp.intern_atom("timestamp");
1271    interp.dictionary.insert(
1272        timestamp_atom,
1273        DictEntry {
1274            value: Value::Builtin(timestamp_builtin),
1275            is_executable: true,
1276            doc: Some(Rc::<str>::from(
1277                "Convert datetime to Unix timestamp (seconds since epoch).\nUsage: datetime timestamp => timestamp",
1278            )),
1279        },
1280    );
1281
1282    let timestamp_to_datetime_atom = interp.intern_atom("timestamp->datetime");
1283    interp.dictionary.insert(
1284        timestamp_to_datetime_atom,
1285        DictEntry {
1286            value: Value::Builtin(timestamp_to_datetime_builtin),
1287            is_executable: true,
1288            doc: Some(Rc::<str>::from(
1289                "Convert Unix timestamp to datetime in local timezone.\nUsage: timestamp timestamp->datetime => datetime",
1290            )),
1291        },
1292    );
1293
1294    let to_utc_atom = interp.intern_atom("to-utc");
1295    interp.dictionary.insert(
1296        to_utc_atom,
1297        DictEntry {
1298            value: Value::Builtin(to_utc_builtin),
1299            is_executable: true,
1300            doc: Some(Rc::<str>::from(
1301                "Convert datetime to UTC.\nUsage: datetime to-utc => datetime",
1302            )),
1303        },
1304    );
1305
1306    let to_local_atom = interp.intern_atom("to-local");
1307    interp.dictionary.insert(
1308        to_local_atom,
1309        DictEntry {
1310            value: Value::Builtin(to_local_builtin),
1311            is_executable: true,
1312            doc: Some(Rc::<str>::from(
1313                "Convert datetime to local timezone.\nUsage: datetime to-local => datetime",
1314            )),
1315        },
1316    );
1317
1318    let datetime_to_string_atom = interp.intern_atom("datetime->string");
1319    interp.dictionary.insert(
1320        datetime_to_string_atom,
1321        DictEntry {
1322            value: Value::Builtin(datetime_to_string_builtin),
1323            is_executable: true,
1324            doc: Some(Rc::<str>::from(
1325                "Format datetime as ISO 8601 string.\nUsage: datetime datetime->string => string",
1326            )),
1327        },
1328    );
1329
1330    let string_to_datetime_atom = interp.intern_atom("string->datetime");
1331    interp.dictionary.insert(
1332        string_to_datetime_atom,
1333        DictEntry {
1334            value: Value::Builtin(string_to_datetime_builtin),
1335            is_executable: true,
1336            doc: Some(Rc::<str>::from(
1337                "Parse ISO 8601 string to datetime.\nUsage: string string->datetime => datetime",
1338            )),
1339        },
1340    );
1341
1342    let date_less_than_atom = interp.intern_atom("date<");
1343    interp.dictionary.insert(
1344        date_less_than_atom,
1345        DictEntry {
1346            value: Value::Builtin(date_less_than_builtin),
1347            is_executable: true,
1348            doc: Some(Rc::<str>::from(
1349                "Compare datetimes (less than).\nUsage: datetime1 datetime2 date< => boolean",
1350            )),
1351        },
1352    );
1353
1354    let date_greater_than_atom = interp.intern_atom("date>");
1355    interp.dictionary.insert(
1356        date_greater_than_atom,
1357        DictEntry {
1358            value: Value::Builtin(date_greater_than_builtin),
1359            is_executable: true,
1360            doc: Some(Rc::<str>::from(
1361                "Compare datetimes (greater than).\nUsage: datetime1 datetime2 date> => boolean",
1362            )),
1363        },
1364    );
1365
1366    let date_equal_atom = interp.intern_atom("date=");
1367    interp.dictionary.insert(
1368        date_equal_atom,
1369        DictEntry {
1370            value: Value::Builtin(date_equal_builtin),
1371            is_executable: true,
1372            doc: Some(Rc::<str>::from(
1373                "Compare datetimes (equal).\nUsage: datetime1 datetime2 date= => boolean",
1374            )),
1375        },
1376    );
1377
1378    // Duration operations
1379    let duration_atom = interp.intern_atom("duration");
1380    interp.dictionary.insert(
1381        duration_atom,
1382        DictEntry {
1383            value: Value::Builtin(duration_builtin),
1384            is_executable: true,
1385            doc: Some(Rc::<str>::from(
1386                "Create duration from components.\nUsage: days hours minutes seconds duration => duration\nExample: 1 2 30 0 duration",
1387            )),
1388        },
1389    );
1390
1391    let duration_to_seconds_atom = interp.intern_atom("duration->seconds");
1392    interp.dictionary.insert(
1393        duration_to_seconds_atom,
1394        DictEntry {
1395            value: Value::Builtin(duration_to_seconds_builtin),
1396            is_executable: true,
1397            doc: Some(Rc::<str>::from(
1398                "Convert duration to total seconds.\nUsage: duration duration->seconds => seconds",
1399            )),
1400        },
1401    );
1402
1403    let date_add_atom = interp.intern_atom("date+");
1404    interp.dictionary.insert(
1405        date_add_atom,
1406        DictEntry {
1407            value: Value::Builtin(date_add_builtin),
1408            is_executable: true,
1409            doc: Some(Rc::<str>::from(
1410                "Add duration to datetime.\nUsage: datetime duration date+ => datetime",
1411            )),
1412        },
1413    );
1414
1415    let date_sub_atom = interp.intern_atom("date-");
1416    interp.dictionary.insert(
1417        date_sub_atom,
1418        DictEntry {
1419            value: Value::Builtin(date_sub_builtin),
1420            is_executable: true,
1421            doc: Some(Rc::<str>::from(
1422                "Subtract datetime or duration.\nUsage: datetime1 datetime2 date- => duration (time between)\nUsage: datetime duration date- => datetime (subtract duration)",
1423            )),
1424        },
1425    );
1426
1427    let duration_less_than_atom = interp.intern_atom("duration<");
1428    interp.dictionary.insert(
1429        duration_less_than_atom,
1430        DictEntry {
1431            value: Value::Builtin(duration_less_than_builtin),
1432            is_executable: true,
1433            doc: Some(Rc::<str>::from(
1434                "Compare durations (less than).\nUsage: duration1 duration2 duration< => boolean",
1435            )),
1436        },
1437    );
1438
1439    let duration_greater_than_atom = interp.intern_atom("duration>");
1440    interp.dictionary.insert(
1441        duration_greater_than_atom,
1442        DictEntry {
1443            value: Value::Builtin(duration_greater_than_builtin),
1444            is_executable: true,
1445            doc: Some(Rc::<str>::from(
1446                "Compare durations (greater than).\nUsage: duration1 duration2 duration> => boolean",
1447            )),
1448        },
1449    );
1450
1451    let duration_equal_atom = interp.intern_atom("duration=");
1452    interp.dictionary.insert(
1453        duration_equal_atom,
1454        DictEntry {
1455            value: Value::Builtin(duration_equal_builtin),
1456            is_executable: true,
1457            doc: Some(Rc::<str>::from(
1458                "Compare durations (equal).\nUsage: duration1 duration2 duration= => boolean",
1459            )),
1460        },
1461    );
1462    } // end datetime feature block
1463
1464    // Register hardware-specific primitives (feature-gated)
1465    #[cfg(feature = "hardware-microbit")]
1466    crate::hardware::microbit::register_microbit_primitives(interp);
1467
1468    #[cfg(feature = "hardware-pico")]
1469    crate::hardware::pico::register_pico_primitives(interp);
1470}
1471
1472#[cfg(test)]
1473mod tests {
1474    use super::*;
1475    use crate::interpreter::DictEntry;
1476
1477    fn setup_interpreter() -> Interpreter {
1478        Interpreter::new()
1479    }
1480
1481    #[test]
1482    fn test_all_builtins_registered() {
1483        let mut interp = setup_interpreter();
1484
1485        let expected_builtins = [
1486            // Basic arithmetic
1487            "+", "-", "*", "/", "//", "div", "mod", "=", // Comparison operations
1488            "<", ">", "<=", ">=", "!=", // Basic math functions
1489            "abs", "min", "max", "sqrt", // Advanced math functions
1490            "pow", "floor", "ceil", "round", // Trigonometric functions
1491            "sin", "cos", "tan", // Logarithmic functions
1492            "log", "exp", // Bitwise operations
1493            "bit-and", "bit-or", "bit-xor", "bit-not", // Shift operations
1494            "shl", "shr", // Stack operations
1495            "roll", "pick", "drop", // Return stack operations
1496            ">r", "r>", "r@", // Control flow & meta
1497            "def", "val", // exec and if are now special in evaluator
1498            // I/O operations
1499            ".",       // String operations
1500            "->string", // List operations
1501            "head", "tail", "cons", "list", // Predicates
1502            "truthy?",
1503        ];
1504
1505        for builtin_name in expected_builtins.iter() {
1506            let atom = interp.intern_atom(builtin_name);
1507            assert!(
1508                interp.dictionary.contains_key(&atom),
1509                "Expected builtin '{}' to be registered",
1510                builtin_name
1511            );
1512
1513            // Verify it's actually a builtin function
1514            assert!(matches!(
1515                interp.dictionary.get(&atom),
1516                Some(DictEntry {
1517                    value: Value::Builtin(_),
1518                    ..
1519                })
1520            ));
1521        }
1522    }
1523}