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