seqc/codegen/
runtime.rs

1//! Runtime function declarations for LLVM IR.
2//!
3//! All runtime functions are declared here in a single data-driven table.
4//! This eliminates ~500 lines of duplicate writeln! calls and ensures
5//! consistency between the FFI and non-FFI code paths.
6
7use super::error::CodeGenError;
8use std::collections::HashMap;
9use std::fmt::Write as _;
10use std::sync::LazyLock;
11
12/// A runtime function declaration for LLVM IR.
13pub struct RuntimeDecl {
14    /// LLVM declaration string (e.g., "declare ptr @patch_seq_add(ptr)")
15    pub decl: &'static str,
16    /// Optional category comment (e.g., "; Stack operations")
17    pub category: Option<&'static str>,
18}
19
20/// All runtime function declarations, organized by category.
21/// Each entry generates a single `declare` statement in the LLVM IR.
22pub static RUNTIME_DECLARATIONS: LazyLock<Vec<RuntimeDecl>> = LazyLock::new(|| {
23    vec![
24        // Core push operations
25        RuntimeDecl {
26            decl: "declare ptr @patch_seq_push_int(ptr, i64)",
27            category: Some("; Runtime function declarations"),
28        },
29        RuntimeDecl {
30            decl: "declare ptr @patch_seq_push_string(ptr, ptr)",
31            category: None,
32        },
33        RuntimeDecl {
34            decl: "declare ptr @patch_seq_push_symbol(ptr, ptr)",
35            category: None,
36        },
37        RuntimeDecl {
38            decl: "declare ptr @patch_seq_push_interned_symbol(ptr, ptr)",
39            category: None,
40        },
41        // I/O operations
42        RuntimeDecl {
43            decl: "declare ptr @patch_seq_write(ptr)",
44            category: None,
45        },
46        RuntimeDecl {
47            decl: "declare ptr @patch_seq_write_line(ptr)",
48            category: None,
49        },
50        RuntimeDecl {
51            decl: "declare ptr @patch_seq_read_line(ptr)",
52            category: None,
53        },
54        RuntimeDecl {
55            decl: "declare ptr @patch_seq_read_line_plus(ptr)",
56            category: None,
57        },
58        RuntimeDecl {
59            decl: "declare ptr @patch_seq_read_n(ptr)",
60            category: None,
61        },
62        // Type conversions
63        RuntimeDecl {
64            decl: "declare ptr @patch_seq_int_to_string(ptr)",
65            category: None,
66        },
67        RuntimeDecl {
68            decl: "declare ptr @patch_seq_symbol_to_string(ptr)",
69            category: None,
70        },
71        RuntimeDecl {
72            decl: "declare ptr @patch_seq_string_to_symbol(ptr)",
73            category: None,
74        },
75        // Integer arithmetic
76        RuntimeDecl {
77            decl: "declare ptr @patch_seq_add(ptr)",
78            category: None,
79        },
80        RuntimeDecl {
81            decl: "declare ptr @patch_seq_subtract(ptr)",
82            category: None,
83        },
84        RuntimeDecl {
85            decl: "declare ptr @patch_seq_multiply(ptr)",
86            category: None,
87        },
88        RuntimeDecl {
89            decl: "declare ptr @patch_seq_divide(ptr)",
90            category: None,
91        },
92        RuntimeDecl {
93            decl: "declare ptr @patch_seq_modulo(ptr)",
94            category: None,
95        },
96        // Integer comparisons
97        RuntimeDecl {
98            decl: "declare ptr @patch_seq_eq(ptr)",
99            category: None,
100        },
101        RuntimeDecl {
102            decl: "declare ptr @patch_seq_lt(ptr)",
103            category: None,
104        },
105        RuntimeDecl {
106            decl: "declare ptr @patch_seq_gt(ptr)",
107            category: None,
108        },
109        RuntimeDecl {
110            decl: "declare ptr @patch_seq_lte(ptr)",
111            category: None,
112        },
113        RuntimeDecl {
114            decl: "declare ptr @patch_seq_gte(ptr)",
115            category: None,
116        },
117        RuntimeDecl {
118            decl: "declare ptr @patch_seq_neq(ptr)",
119            category: None,
120        },
121        // Boolean operations
122        RuntimeDecl {
123            decl: "declare ptr @patch_seq_and(ptr)",
124            category: Some("; Boolean operations"),
125        },
126        RuntimeDecl {
127            decl: "declare ptr @patch_seq_or(ptr)",
128            category: None,
129        },
130        RuntimeDecl {
131            decl: "declare ptr @patch_seq_not(ptr)",
132            category: None,
133        },
134        // Bitwise operations
135        RuntimeDecl {
136            decl: "declare ptr @patch_seq_band(ptr)",
137            category: Some("; Bitwise operations"),
138        },
139        RuntimeDecl {
140            decl: "declare ptr @patch_seq_bor(ptr)",
141            category: None,
142        },
143        RuntimeDecl {
144            decl: "declare ptr @patch_seq_bxor(ptr)",
145            category: None,
146        },
147        RuntimeDecl {
148            decl: "declare ptr @patch_seq_bnot(ptr)",
149            category: None,
150        },
151        RuntimeDecl {
152            decl: "declare ptr @patch_seq_shl(ptr)",
153            category: None,
154        },
155        RuntimeDecl {
156            decl: "declare ptr @patch_seq_shr(ptr)",
157            category: None,
158        },
159        RuntimeDecl {
160            decl: "declare ptr @patch_seq_popcount(ptr)",
161            category: None,
162        },
163        RuntimeDecl {
164            decl: "declare ptr @patch_seq_clz(ptr)",
165            category: None,
166        },
167        RuntimeDecl {
168            decl: "declare ptr @patch_seq_ctz(ptr)",
169            category: None,
170        },
171        RuntimeDecl {
172            decl: "declare ptr @patch_seq_int_bits(ptr)",
173            category: None,
174        },
175        // LLVM intrinsics
176        RuntimeDecl {
177            decl: "declare i64 @llvm.ctpop.i64(i64)",
178            category: None,
179        },
180        RuntimeDecl {
181            decl: "declare i64 @llvm.ctlz.i64(i64, i1)",
182            category: None,
183        },
184        RuntimeDecl {
185            decl: "declare i64 @llvm.cttz.i64(i64, i1)",
186            category: None,
187        },
188        RuntimeDecl {
189            decl: "declare void @llvm.memmove.p0.p0.i64(ptr, ptr, i64, i1)",
190            category: None,
191        },
192        RuntimeDecl {
193            decl: "declare void @llvm.trap() noreturn nounwind",
194            category: None,
195        },
196        // Stack operations
197        RuntimeDecl {
198            decl: "declare ptr @patch_seq_dup(ptr)",
199            category: Some("; Stack operations"),
200        },
201        RuntimeDecl {
202            decl: "declare ptr @patch_seq_drop_op(ptr)",
203            category: None,
204        },
205        RuntimeDecl {
206            decl: "declare ptr @patch_seq_swap(ptr)",
207            category: None,
208        },
209        RuntimeDecl {
210            decl: "declare ptr @patch_seq_over(ptr)",
211            category: None,
212        },
213        RuntimeDecl {
214            decl: "declare ptr @patch_seq_rot(ptr)",
215            category: None,
216        },
217        RuntimeDecl {
218            decl: "declare ptr @patch_seq_nip(ptr)",
219            category: None,
220        },
221        RuntimeDecl {
222            decl: "declare void @patch_seq_clone_value(ptr, ptr)",
223            category: None,
224        },
225        RuntimeDecl {
226            decl: "declare ptr @patch_seq_tuck(ptr)",
227            category: None,
228        },
229        RuntimeDecl {
230            decl: "declare ptr @patch_seq_2dup(ptr)",
231            category: None,
232        },
233        RuntimeDecl {
234            decl: "declare ptr @patch_seq_3drop(ptr)",
235            category: None,
236        },
237        RuntimeDecl {
238            decl: "declare ptr @patch_seq_pick_op(ptr)",
239            category: None,
240        },
241        RuntimeDecl {
242            decl: "declare ptr @patch_seq_roll(ptr)",
243            category: None,
244        },
245        RuntimeDecl {
246            decl: "declare ptr @patch_seq_push_value(ptr, %Value)",
247            category: None,
248        },
249        // Quotation operations
250        RuntimeDecl {
251            decl: "declare ptr @patch_seq_push_quotation(ptr, i64, i64)",
252            category: Some("; Quotation operations"),
253        },
254        RuntimeDecl {
255            decl: "declare ptr @patch_seq_call(ptr)",
256            category: None,
257        },
258        RuntimeDecl {
259            decl: "declare i64 @patch_seq_peek_is_quotation(ptr)",
260            category: None,
261        },
262        RuntimeDecl {
263            decl: "declare i64 @patch_seq_peek_quotation_fn_ptr(ptr)",
264            category: None,
265        },
266        RuntimeDecl {
267            decl: "declare ptr @patch_seq_times(ptr)",
268            category: None,
269        },
270        RuntimeDecl {
271            decl: "declare ptr @patch_seq_while_loop(ptr)",
272            category: None,
273        },
274        RuntimeDecl {
275            decl: "declare ptr @patch_seq_until_loop(ptr)",
276            category: None,
277        },
278        RuntimeDecl {
279            decl: "declare ptr @patch_seq_spawn(ptr)",
280            category: None,
281        },
282        RuntimeDecl {
283            decl: "declare ptr @patch_seq_weave(ptr)",
284            category: None,
285        },
286        RuntimeDecl {
287            decl: "declare ptr @patch_seq_resume(ptr)",
288            category: None,
289        },
290        RuntimeDecl {
291            decl: "declare ptr @patch_seq_weave_cancel(ptr)",
292            category: None,
293        },
294        RuntimeDecl {
295            decl: "declare ptr @patch_seq_yield(ptr)",
296            category: None,
297        },
298        RuntimeDecl {
299            decl: "declare ptr @patch_seq_cond(ptr)",
300            category: None,
301        },
302        // Closure operations
303        RuntimeDecl {
304            decl: "declare ptr @patch_seq_create_env(i32)",
305            category: Some("; Closure operations"),
306        },
307        RuntimeDecl {
308            decl: "declare void @patch_seq_env_set(ptr, i32, %Value)",
309            category: None,
310        },
311        RuntimeDecl {
312            decl: "declare %Value @patch_seq_env_get(ptr, i64, i32)",
313            category: None,
314        },
315        RuntimeDecl {
316            decl: "declare i64 @patch_seq_env_get_int(ptr, i64, i32)",
317            category: None,
318        },
319        RuntimeDecl {
320            decl: "declare i64 @patch_seq_env_get_bool(ptr, i64, i32)",
321            category: None,
322        },
323        RuntimeDecl {
324            decl: "declare double @patch_seq_env_get_float(ptr, i64, i32)",
325            category: None,
326        },
327        RuntimeDecl {
328            decl: "declare i64 @patch_seq_env_get_quotation(ptr, i64, i32)",
329            category: None,
330        },
331        RuntimeDecl {
332            decl: "declare ptr @patch_seq_env_get_string(ptr, i64, i32)",
333            category: None,
334        },
335        RuntimeDecl {
336            decl: "declare ptr @patch_seq_env_push_string(ptr, ptr, i64, i32)",
337            category: None,
338        },
339        RuntimeDecl {
340            decl: "declare %Value @patch_seq_make_closure(i64, ptr)",
341            category: None,
342        },
343        RuntimeDecl {
344            decl: "declare ptr @patch_seq_push_closure(ptr, i64, i32)",
345            category: None,
346        },
347        RuntimeDecl {
348            decl: "declare ptr @patch_seq_push_seqstring(ptr, ptr)",
349            category: None,
350        },
351        // Concurrency operations
352        RuntimeDecl {
353            decl: "declare ptr @patch_seq_make_channel(ptr)",
354            category: Some("; Concurrency operations"),
355        },
356        RuntimeDecl {
357            decl: "declare ptr @patch_seq_chan_send(ptr)",
358            category: None,
359        },
360        RuntimeDecl {
361            decl: "declare ptr @patch_seq_chan_receive(ptr)",
362            category: None,
363        },
364        RuntimeDecl {
365            decl: "declare ptr @patch_seq_close_channel(ptr)",
366            category: None,
367        },
368        RuntimeDecl {
369            decl: "declare ptr @patch_seq_yield_strand(ptr)",
370            category: None,
371        },
372        RuntimeDecl {
373            decl: "declare void @patch_seq_maybe_yield()",
374            category: None,
375        },
376        // Scheduler operations
377        RuntimeDecl {
378            decl: "declare void @patch_seq_scheduler_init()",
379            category: Some("; Scheduler operations"),
380        },
381        RuntimeDecl {
382            decl: "declare ptr @patch_seq_scheduler_run()",
383            category: None,
384        },
385        RuntimeDecl {
386            decl: "declare i64 @patch_seq_strand_spawn(ptr, ptr)",
387            category: None,
388        },
389        // Command-line argument operations
390        RuntimeDecl {
391            decl: "declare void @patch_seq_args_init(i32, ptr)",
392            category: Some("; Command-line argument operations"),
393        },
394        RuntimeDecl {
395            decl: "declare ptr @patch_seq_arg_count(ptr)",
396            category: None,
397        },
398        RuntimeDecl {
399            decl: "declare ptr @patch_seq_arg_at(ptr)",
400            category: None,
401        },
402        // File operations
403        RuntimeDecl {
404            decl: "declare ptr @patch_seq_file_slurp(ptr)",
405            category: Some("; File operations"),
406        },
407        RuntimeDecl {
408            decl: "declare ptr @patch_seq_file_exists(ptr)",
409            category: None,
410        },
411        RuntimeDecl {
412            decl: "declare ptr @patch_seq_file_for_each_line_plus(ptr)",
413            category: None,
414        },
415        // List operations
416        RuntimeDecl {
417            decl: "declare ptr @patch_seq_list_make(ptr)",
418            category: Some("; List operations"),
419        },
420        RuntimeDecl {
421            decl: "declare ptr @patch_seq_list_push(ptr)",
422            category: None,
423        },
424        RuntimeDecl {
425            decl: "declare ptr @patch_seq_list_get(ptr)",
426            category: None,
427        },
428        RuntimeDecl {
429            decl: "declare ptr @patch_seq_list_set(ptr)",
430            category: None,
431        },
432        RuntimeDecl {
433            decl: "declare ptr @patch_seq_list_map(ptr)",
434            category: None,
435        },
436        RuntimeDecl {
437            decl: "declare ptr @patch_seq_list_filter(ptr)",
438            category: None,
439        },
440        RuntimeDecl {
441            decl: "declare ptr @patch_seq_list_fold(ptr)",
442            category: None,
443        },
444        RuntimeDecl {
445            decl: "declare ptr @patch_seq_list_each(ptr)",
446            category: None,
447        },
448        RuntimeDecl {
449            decl: "declare ptr @patch_seq_list_length(ptr)",
450            category: None,
451        },
452        RuntimeDecl {
453            decl: "declare ptr @patch_seq_list_empty(ptr)",
454            category: None,
455        },
456        // Map operations
457        RuntimeDecl {
458            decl: "declare ptr @patch_seq_make_map(ptr)",
459            category: Some("; Map operations"),
460        },
461        RuntimeDecl {
462            decl: "declare ptr @patch_seq_map_get(ptr)",
463            category: None,
464        },
465        RuntimeDecl {
466            decl: "declare ptr @patch_seq_map_set(ptr)",
467            category: None,
468        },
469        RuntimeDecl {
470            decl: "declare ptr @patch_seq_map_has(ptr)",
471            category: None,
472        },
473        RuntimeDecl {
474            decl: "declare ptr @patch_seq_map_remove(ptr)",
475            category: None,
476        },
477        RuntimeDecl {
478            decl: "declare ptr @patch_seq_map_keys(ptr)",
479            category: None,
480        },
481        RuntimeDecl {
482            decl: "declare ptr @patch_seq_map_values(ptr)",
483            category: None,
484        },
485        RuntimeDecl {
486            decl: "declare ptr @patch_seq_map_size(ptr)",
487            category: None,
488        },
489        RuntimeDecl {
490            decl: "declare ptr @patch_seq_map_empty(ptr)",
491            category: None,
492        },
493        // TCP operations
494        RuntimeDecl {
495            decl: "declare ptr @patch_seq_tcp_listen(ptr)",
496            category: Some("; TCP operations"),
497        },
498        RuntimeDecl {
499            decl: "declare ptr @patch_seq_tcp_accept(ptr)",
500            category: None,
501        },
502        RuntimeDecl {
503            decl: "declare ptr @patch_seq_tcp_read(ptr)",
504            category: None,
505        },
506        RuntimeDecl {
507            decl: "declare ptr @patch_seq_tcp_write(ptr)",
508            category: None,
509        },
510        RuntimeDecl {
511            decl: "declare ptr @patch_seq_tcp_close(ptr)",
512            category: None,
513        },
514        // OS operations
515        RuntimeDecl {
516            decl: "declare ptr @patch_seq_getenv(ptr)",
517            category: Some("; OS operations"),
518        },
519        RuntimeDecl {
520            decl: "declare ptr @patch_seq_home_dir(ptr)",
521            category: None,
522        },
523        RuntimeDecl {
524            decl: "declare ptr @patch_seq_current_dir(ptr)",
525            category: None,
526        },
527        RuntimeDecl {
528            decl: "declare ptr @patch_seq_path_exists(ptr)",
529            category: None,
530        },
531        RuntimeDecl {
532            decl: "declare ptr @patch_seq_path_is_file(ptr)",
533            category: None,
534        },
535        RuntimeDecl {
536            decl: "declare ptr @patch_seq_path_is_dir(ptr)",
537            category: None,
538        },
539        RuntimeDecl {
540            decl: "declare ptr @patch_seq_path_join(ptr)",
541            category: None,
542        },
543        RuntimeDecl {
544            decl: "declare ptr @patch_seq_path_parent(ptr)",
545            category: None,
546        },
547        RuntimeDecl {
548            decl: "declare ptr @patch_seq_path_filename(ptr)",
549            category: None,
550        },
551        RuntimeDecl {
552            decl: "declare ptr @patch_seq_exit(ptr)",
553            category: None,
554        },
555        RuntimeDecl {
556            decl: "declare ptr @patch_seq_os_name(ptr)",
557            category: None,
558        },
559        RuntimeDecl {
560            decl: "declare ptr @patch_seq_os_arch(ptr)",
561            category: None,
562        },
563        // String operations
564        RuntimeDecl {
565            decl: "declare ptr @patch_seq_string_concat(ptr)",
566            category: Some("; String operations"),
567        },
568        RuntimeDecl {
569            decl: "declare ptr @patch_seq_string_length(ptr)",
570            category: None,
571        },
572        RuntimeDecl {
573            decl: "declare ptr @patch_seq_string_byte_length(ptr)",
574            category: None,
575        },
576        RuntimeDecl {
577            decl: "declare ptr @patch_seq_string_char_at(ptr)",
578            category: None,
579        },
580        RuntimeDecl {
581            decl: "declare ptr @patch_seq_string_substring(ptr)",
582            category: None,
583        },
584        RuntimeDecl {
585            decl: "declare ptr @patch_seq_char_to_string(ptr)",
586            category: None,
587        },
588        RuntimeDecl {
589            decl: "declare ptr @patch_seq_string_find(ptr)",
590            category: None,
591        },
592        RuntimeDecl {
593            decl: "declare ptr @patch_seq_string_split(ptr)",
594            category: None,
595        },
596        RuntimeDecl {
597            decl: "declare ptr @patch_seq_string_contains(ptr)",
598            category: None,
599        },
600        RuntimeDecl {
601            decl: "declare ptr @patch_seq_string_starts_with(ptr)",
602            category: None,
603        },
604        RuntimeDecl {
605            decl: "declare ptr @patch_seq_string_empty(ptr)",
606            category: None,
607        },
608        RuntimeDecl {
609            decl: "declare ptr @patch_seq_string_trim(ptr)",
610            category: None,
611        },
612        RuntimeDecl {
613            decl: "declare ptr @patch_seq_string_chomp(ptr)",
614            category: None,
615        },
616        RuntimeDecl {
617            decl: "declare ptr @patch_seq_string_to_upper(ptr)",
618            category: None,
619        },
620        RuntimeDecl {
621            decl: "declare ptr @patch_seq_string_to_lower(ptr)",
622            category: None,
623        },
624        RuntimeDecl {
625            decl: "declare ptr @patch_seq_string_equal(ptr)",
626            category: None,
627        },
628        RuntimeDecl {
629            decl: "declare ptr @patch_seq_json_escape(ptr)",
630            category: None,
631        },
632        RuntimeDecl {
633            decl: "declare ptr @patch_seq_string_to_int(ptr)",
634            category: None,
635        },
636        // Encoding operations
637        RuntimeDecl {
638            decl: "declare ptr @patch_seq_base64_encode(ptr)",
639            category: Some("; Encoding operations"),
640        },
641        RuntimeDecl {
642            decl: "declare ptr @patch_seq_base64_decode(ptr)",
643            category: None,
644        },
645        RuntimeDecl {
646            decl: "declare ptr @patch_seq_base64url_encode(ptr)",
647            category: None,
648        },
649        RuntimeDecl {
650            decl: "declare ptr @patch_seq_base64url_decode(ptr)",
651            category: None,
652        },
653        RuntimeDecl {
654            decl: "declare ptr @patch_seq_hex_encode(ptr)",
655            category: None,
656        },
657        RuntimeDecl {
658            decl: "declare ptr @patch_seq_hex_decode(ptr)",
659            category: None,
660        },
661        // Crypto operations
662        RuntimeDecl {
663            decl: "declare ptr @patch_seq_sha256(ptr)",
664            category: Some("; Crypto operations"),
665        },
666        RuntimeDecl {
667            decl: "declare ptr @patch_seq_hmac_sha256(ptr)",
668            category: None,
669        },
670        RuntimeDecl {
671            decl: "declare ptr @patch_seq_constant_time_eq(ptr)",
672            category: None,
673        },
674        RuntimeDecl {
675            decl: "declare ptr @patch_seq_random_bytes(ptr)",
676            category: None,
677        },
678        RuntimeDecl {
679            decl: "declare ptr @patch_seq_uuid4(ptr)",
680            category: None,
681        },
682        // HTTP client operations
683        RuntimeDecl {
684            decl: "declare ptr @patch_seq_http_get(ptr)",
685            category: Some("; HTTP client operations"),
686        },
687        RuntimeDecl {
688            decl: "declare ptr @patch_seq_http_post(ptr)",
689            category: None,
690        },
691        RuntimeDecl {
692            decl: "declare ptr @patch_seq_http_put(ptr)",
693            category: None,
694        },
695        RuntimeDecl {
696            decl: "declare ptr @patch_seq_http_delete(ptr)",
697            category: None,
698        },
699        // Symbol operations
700        RuntimeDecl {
701            decl: "declare ptr @patch_seq_symbol_equal(ptr)",
702            category: Some("; Symbol operations"),
703        },
704        // Variant operations
705        RuntimeDecl {
706            decl: "declare ptr @patch_seq_variant_field_count(ptr)",
707            category: Some("; Variant operations"),
708        },
709        RuntimeDecl {
710            decl: "declare ptr @patch_seq_variant_tag(ptr)",
711            category: None,
712        },
713        RuntimeDecl {
714            decl: "declare ptr @patch_seq_variant_field_at(ptr)",
715            category: None,
716        },
717        RuntimeDecl {
718            decl: "declare ptr @patch_seq_variant_append(ptr)",
719            category: None,
720        },
721        RuntimeDecl {
722            decl: "declare ptr @patch_seq_variant_last(ptr)",
723            category: None,
724        },
725        RuntimeDecl {
726            decl: "declare ptr @patch_seq_variant_init(ptr)",
727            category: None,
728        },
729        RuntimeDecl {
730            decl: "declare ptr @patch_seq_make_variant_0(ptr)",
731            category: None,
732        },
733        RuntimeDecl {
734            decl: "declare ptr @patch_seq_make_variant_1(ptr)",
735            category: None,
736        },
737        RuntimeDecl {
738            decl: "declare ptr @patch_seq_make_variant_2(ptr)",
739            category: None,
740        },
741        RuntimeDecl {
742            decl: "declare ptr @patch_seq_make_variant_3(ptr)",
743            category: None,
744        },
745        RuntimeDecl {
746            decl: "declare ptr @patch_seq_make_variant_4(ptr)",
747            category: None,
748        },
749        RuntimeDecl {
750            decl: "declare ptr @patch_seq_unpack_variant(ptr, i64)",
751            category: None,
752        },
753        RuntimeDecl {
754            decl: "declare ptr @patch_seq_symbol_eq_cstr(ptr, ptr)",
755            category: None,
756        },
757        // Float operations
758        RuntimeDecl {
759            decl: "declare ptr @patch_seq_push_float(ptr, double)",
760            category: Some("; Float operations"),
761        },
762        RuntimeDecl {
763            decl: "declare ptr @patch_seq_f_add(ptr)",
764            category: None,
765        },
766        RuntimeDecl {
767            decl: "declare ptr @patch_seq_f_subtract(ptr)",
768            category: None,
769        },
770        RuntimeDecl {
771            decl: "declare ptr @patch_seq_f_multiply(ptr)",
772            category: None,
773        },
774        RuntimeDecl {
775            decl: "declare ptr @patch_seq_f_divide(ptr)",
776            category: None,
777        },
778        RuntimeDecl {
779            decl: "declare ptr @patch_seq_f_eq(ptr)",
780            category: None,
781        },
782        RuntimeDecl {
783            decl: "declare ptr @patch_seq_f_lt(ptr)",
784            category: None,
785        },
786        RuntimeDecl {
787            decl: "declare ptr @patch_seq_f_gt(ptr)",
788            category: None,
789        },
790        RuntimeDecl {
791            decl: "declare ptr @patch_seq_f_lte(ptr)",
792            category: None,
793        },
794        RuntimeDecl {
795            decl: "declare ptr @patch_seq_f_gte(ptr)",
796            category: None,
797        },
798        RuntimeDecl {
799            decl: "declare ptr @patch_seq_f_neq(ptr)",
800            category: None,
801        },
802        RuntimeDecl {
803            decl: "declare ptr @patch_seq_int_to_float(ptr)",
804            category: None,
805        },
806        RuntimeDecl {
807            decl: "declare ptr @patch_seq_float_to_int(ptr)",
808            category: None,
809        },
810        RuntimeDecl {
811            decl: "declare ptr @patch_seq_float_to_string(ptr)",
812            category: None,
813        },
814        RuntimeDecl {
815            decl: "declare ptr @patch_seq_string_to_float(ptr)",
816            category: None,
817        },
818        // Test framework operations
819        RuntimeDecl {
820            decl: "declare ptr @patch_seq_test_init(ptr)",
821            category: Some("; Test framework operations"),
822        },
823        RuntimeDecl {
824            decl: "declare ptr @patch_seq_test_finish(ptr)",
825            category: None,
826        },
827        RuntimeDecl {
828            decl: "declare ptr @patch_seq_test_has_failures(ptr)",
829            category: None,
830        },
831        RuntimeDecl {
832            decl: "declare ptr @patch_seq_test_assert(ptr)",
833            category: None,
834        },
835        RuntimeDecl {
836            decl: "declare ptr @patch_seq_test_assert_not(ptr)",
837            category: None,
838        },
839        RuntimeDecl {
840            decl: "declare ptr @patch_seq_test_assert_eq(ptr)",
841            category: None,
842        },
843        RuntimeDecl {
844            decl: "declare ptr @patch_seq_test_assert_eq_str(ptr)",
845            category: None,
846        },
847        RuntimeDecl {
848            decl: "declare ptr @patch_seq_test_fail(ptr)",
849            category: None,
850        },
851        RuntimeDecl {
852            decl: "declare ptr @patch_seq_test_pass_count(ptr)",
853            category: None,
854        },
855        RuntimeDecl {
856            decl: "declare ptr @patch_seq_test_fail_count(ptr)",
857            category: None,
858        },
859        // Time operations
860        RuntimeDecl {
861            decl: "declare ptr @patch_seq_time_now(ptr)",
862            category: Some("; Time operations"),
863        },
864        RuntimeDecl {
865            decl: "declare ptr @patch_seq_time_nanos(ptr)",
866            category: None,
867        },
868        RuntimeDecl {
869            decl: "declare ptr @patch_seq_time_sleep_ms(ptr)",
870            category: None,
871        },
872        // Stack introspection
873        RuntimeDecl {
874            decl: "declare ptr @patch_seq_stack_dump(ptr)",
875            category: Some("; Stack introspection"),
876        },
877        // SON serialization
878        RuntimeDecl {
879            decl: "declare ptr @patch_seq_son_dump(ptr)",
880            category: Some("; SON serialization"),
881        },
882        RuntimeDecl {
883            decl: "declare ptr @patch_seq_son_dump_pretty(ptr)",
884            category: None,
885        },
886        // Helpers for conditionals
887        RuntimeDecl {
888            decl: "declare i64 @patch_seq_peek_int_value(ptr)",
889            category: Some("; Helpers for conditionals"),
890        },
891        RuntimeDecl {
892            decl: "declare i1 @patch_seq_peek_bool_value(ptr)",
893            category: None,
894        },
895        RuntimeDecl {
896            decl: "declare ptr @patch_seq_pop_stack(ptr)",
897            category: None,
898        },
899        // Tagged stack operations
900        RuntimeDecl {
901            decl: "declare ptr @seq_stack_new_default()",
902            category: Some("; Tagged stack operations"),
903        },
904        RuntimeDecl {
905            decl: "declare void @seq_stack_free(ptr)",
906            category: None,
907        },
908        RuntimeDecl {
909            decl: "declare ptr @seq_stack_base(ptr)",
910            category: None,
911        },
912        RuntimeDecl {
913            decl: "declare i64 @seq_stack_sp(ptr)",
914            category: None,
915        },
916        RuntimeDecl {
917            decl: "declare void @seq_stack_set_sp(ptr, i64)",
918            category: None,
919        },
920        RuntimeDecl {
921            decl: "declare void @seq_stack_grow(ptr, i64)",
922            category: None,
923        },
924        RuntimeDecl {
925            decl: "declare void @patch_seq_set_stack_base(ptr)",
926            category: None,
927        },
928    ]
929});
930
931/// Mapping from Seq word names to their C runtime symbol names.
932/// This centralizes all the name transformations in one place:
933/// - Symbolic operators (=, <, >) map to descriptive names (eq, lt, gt)
934/// - Hyphens become underscores for C compatibility
935/// - Special characters get escaped (?, +, ->)
936/// - Reserved words get suffixes (drop -> drop_op)
937pub static BUILTIN_SYMBOLS: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
938    HashMap::from([
939        // I/O operations
940        ("io.write", "patch_seq_write"),
941        ("io.write-line", "patch_seq_write_line"),
942        ("io.read-line", "patch_seq_read_line"),
943        ("io.read-line+", "patch_seq_read_line_plus"),
944        ("io.read-n", "patch_seq_read_n"),
945        ("int->string", "patch_seq_int_to_string"),
946        ("symbol->string", "patch_seq_symbol_to_string"),
947        ("string->symbol", "patch_seq_string_to_symbol"),
948        // Command-line arguments
949        ("args.count", "patch_seq_arg_count"),
950        ("args.at", "patch_seq_arg_at"),
951        // Integer Arithmetic
952        ("i.add", "patch_seq_add"),
953        ("i.subtract", "patch_seq_subtract"),
954        ("i.multiply", "patch_seq_multiply"),
955        ("i.divide", "patch_seq_divide"),
956        ("i.modulo", "patch_seq_modulo"),
957        // Terse integer arithmetic aliases
958        ("i.+", "patch_seq_add"),
959        ("i.-", "patch_seq_subtract"),
960        ("i.*", "patch_seq_multiply"),
961        ("i./", "patch_seq_divide"),
962        ("i.%", "patch_seq_modulo"),
963        // Integer comparison (symbol form)
964        ("i.=", "patch_seq_eq"),
965        ("i.<", "patch_seq_lt"),
966        ("i.>", "patch_seq_gt"),
967        ("i.<=", "patch_seq_lte"),
968        ("i.>=", "patch_seq_gte"),
969        ("i.<>", "patch_seq_neq"),
970        // Integer comparison (verbose form)
971        ("i.eq", "patch_seq_eq"),
972        ("i.lt", "patch_seq_lt"),
973        ("i.gt", "patch_seq_gt"),
974        ("i.lte", "patch_seq_lte"),
975        ("i.gte", "patch_seq_gte"),
976        ("i.neq", "patch_seq_neq"),
977        // Boolean
978        ("and", "patch_seq_and"),
979        ("or", "patch_seq_or"),
980        ("not", "patch_seq_not"),
981        // Bitwise
982        ("band", "patch_seq_band"),
983        ("bor", "patch_seq_bor"),
984        ("bxor", "patch_seq_bxor"),
985        ("bnot", "patch_seq_bnot"),
986        ("shl", "patch_seq_shl"),
987        ("shr", "patch_seq_shr"),
988        ("popcount", "patch_seq_popcount"),
989        ("clz", "patch_seq_clz"),
990        ("ctz", "patch_seq_ctz"),
991        ("int-bits", "patch_seq_int_bits"),
992        // Stack operations
993        ("dup", "patch_seq_dup"),
994        ("swap", "patch_seq_swap"),
995        ("over", "patch_seq_over"),
996        ("rot", "patch_seq_rot"),
997        ("nip", "patch_seq_nip"),
998        ("tuck", "patch_seq_tuck"),
999        ("2dup", "patch_seq_2dup"),
1000        ("3drop", "patch_seq_3drop"),
1001        ("drop", "patch_seq_drop_op"),
1002        ("pick", "patch_seq_pick_op"),
1003        ("roll", "patch_seq_roll"),
1004        // Channel operations (errors are values, not crashes)
1005        ("chan.make", "patch_seq_make_channel"),
1006        ("chan.send", "patch_seq_chan_send"),
1007        ("chan.receive", "patch_seq_chan_receive"),
1008        ("chan.close", "patch_seq_close_channel"),
1009        ("chan.yield", "patch_seq_yield_strand"),
1010        // Quotation operations
1011        ("call", "patch_seq_call"),
1012        ("times", "patch_seq_times"),
1013        ("while", "patch_seq_while_loop"),
1014        ("until", "patch_seq_until_loop"),
1015        ("strand.spawn", "patch_seq_spawn"),
1016        ("strand.weave", "patch_seq_weave"),
1017        ("strand.resume", "patch_seq_resume"),
1018        ("strand.weave-cancel", "patch_seq_weave_cancel"),
1019        ("yield", "patch_seq_yield"),
1020        ("cond", "patch_seq_cond"),
1021        // TCP operations
1022        ("tcp.listen", "patch_seq_tcp_listen"),
1023        ("tcp.accept", "patch_seq_tcp_accept"),
1024        ("tcp.read", "patch_seq_tcp_read"),
1025        ("tcp.write", "patch_seq_tcp_write"),
1026        ("tcp.close", "patch_seq_tcp_close"),
1027        // OS operations
1028        ("os.getenv", "patch_seq_getenv"),
1029        ("os.home-dir", "patch_seq_home_dir"),
1030        ("os.current-dir", "patch_seq_current_dir"),
1031        ("os.path-exists", "patch_seq_path_exists"),
1032        ("os.path-is-file", "patch_seq_path_is_file"),
1033        ("os.path-is-dir", "patch_seq_path_is_dir"),
1034        ("os.path-join", "patch_seq_path_join"),
1035        ("os.path-parent", "patch_seq_path_parent"),
1036        ("os.path-filename", "patch_seq_path_filename"),
1037        ("os.exit", "patch_seq_exit"),
1038        ("os.name", "patch_seq_os_name"),
1039        ("os.arch", "patch_seq_os_arch"),
1040        // String operations
1041        ("string.concat", "patch_seq_string_concat"),
1042        ("string.length", "patch_seq_string_length"),
1043        ("string.byte-length", "patch_seq_string_byte_length"),
1044        ("string.char-at", "patch_seq_string_char_at"),
1045        ("string.substring", "patch_seq_string_substring"),
1046        ("char->string", "patch_seq_char_to_string"),
1047        ("string.find", "patch_seq_string_find"),
1048        ("string.split", "patch_seq_string_split"),
1049        ("string.contains", "patch_seq_string_contains"),
1050        ("string.starts-with", "patch_seq_string_starts_with"),
1051        ("string.empty?", "patch_seq_string_empty"),
1052        ("string.trim", "patch_seq_string_trim"),
1053        ("string.chomp", "patch_seq_string_chomp"),
1054        ("string.to-upper", "patch_seq_string_to_upper"),
1055        ("string.to-lower", "patch_seq_string_to_lower"),
1056        ("string.equal?", "patch_seq_string_equal"),
1057        ("string.json-escape", "patch_seq_json_escape"),
1058        ("string->int", "patch_seq_string_to_int"),
1059        // Encoding operations
1060        ("encoding.base64-encode", "patch_seq_base64_encode"),
1061        ("encoding.base64-decode", "patch_seq_base64_decode"),
1062        ("encoding.base64url-encode", "patch_seq_base64url_encode"),
1063        ("encoding.base64url-decode", "patch_seq_base64url_decode"),
1064        ("encoding.hex-encode", "patch_seq_hex_encode"),
1065        ("encoding.hex-decode", "patch_seq_hex_decode"),
1066        // Crypto operations
1067        ("crypto.sha256", "patch_seq_sha256"),
1068        ("crypto.hmac-sha256", "patch_seq_hmac_sha256"),
1069        ("crypto.constant-time-eq", "patch_seq_constant_time_eq"),
1070        ("crypto.random-bytes", "patch_seq_random_bytes"),
1071        ("crypto.uuid4", "patch_seq_uuid4"),
1072        // HTTP client operations
1073        ("http.get", "patch_seq_http_get"),
1074        ("http.post", "patch_seq_http_post"),
1075        ("http.put", "patch_seq_http_put"),
1076        ("http.delete", "patch_seq_http_delete"),
1077        // Symbol operations
1078        ("symbol.=", "patch_seq_symbol_equal"),
1079        // File operations
1080        ("file.slurp", "patch_seq_file_slurp"),
1081        ("file.exists?", "patch_seq_file_exists"),
1082        ("file.for-each-line+", "patch_seq_file_for_each_line_plus"),
1083        // List operations
1084        ("list.make", "patch_seq_list_make"),
1085        ("list.push", "patch_seq_list_push"),
1086        ("list.get", "patch_seq_list_get"),
1087        ("list.set", "patch_seq_list_set"),
1088        ("list.map", "patch_seq_list_map"),
1089        ("list.filter", "patch_seq_list_filter"),
1090        ("list.fold", "patch_seq_list_fold"),
1091        ("list.each", "patch_seq_list_each"),
1092        ("list.length", "patch_seq_list_length"),
1093        ("list.empty?", "patch_seq_list_empty"),
1094        // Map operations
1095        ("map.make", "patch_seq_make_map"),
1096        ("map.get", "patch_seq_map_get"),
1097        ("map.set", "patch_seq_map_set"),
1098        ("map.has?", "patch_seq_map_has"),
1099        ("map.remove", "patch_seq_map_remove"),
1100        ("map.keys", "patch_seq_map_keys"),
1101        ("map.values", "patch_seq_map_values"),
1102        ("map.size", "patch_seq_map_size"),
1103        ("map.empty?", "patch_seq_map_empty"),
1104        // Variant operations
1105        ("variant.field-count", "patch_seq_variant_field_count"),
1106        ("variant.tag", "patch_seq_variant_tag"),
1107        ("variant.field-at", "patch_seq_variant_field_at"),
1108        ("variant.append", "patch_seq_variant_append"),
1109        ("variant.last", "patch_seq_variant_last"),
1110        ("variant.init", "patch_seq_variant_init"),
1111        ("variant.make-0", "patch_seq_make_variant_0"),
1112        ("variant.make-1", "patch_seq_make_variant_1"),
1113        ("variant.make-2", "patch_seq_make_variant_2"),
1114        ("variant.make-3", "patch_seq_make_variant_3"),
1115        ("variant.make-4", "patch_seq_make_variant_4"),
1116        // wrap-N aliases for dynamic variant construction (SON)
1117        ("wrap-0", "patch_seq_make_variant_0"),
1118        ("wrap-1", "patch_seq_make_variant_1"),
1119        ("wrap-2", "patch_seq_make_variant_2"),
1120        ("wrap-3", "patch_seq_make_variant_3"),
1121        ("wrap-4", "patch_seq_make_variant_4"),
1122        // Float arithmetic
1123        ("f.add", "patch_seq_f_add"),
1124        ("f.subtract", "patch_seq_f_subtract"),
1125        ("f.multiply", "patch_seq_f_multiply"),
1126        ("f.divide", "patch_seq_f_divide"),
1127        // Terse float arithmetic aliases
1128        ("f.+", "patch_seq_f_add"),
1129        ("f.-", "patch_seq_f_subtract"),
1130        ("f.*", "patch_seq_f_multiply"),
1131        ("f./", "patch_seq_f_divide"),
1132        // Float comparison (symbol form)
1133        ("f.=", "patch_seq_f_eq"),
1134        ("f.<", "patch_seq_f_lt"),
1135        ("f.>", "patch_seq_f_gt"),
1136        ("f.<=", "patch_seq_f_lte"),
1137        ("f.>=", "patch_seq_f_gte"),
1138        ("f.<>", "patch_seq_f_neq"),
1139        // Float comparison (verbose form)
1140        ("f.eq", "patch_seq_f_eq"),
1141        ("f.lt", "patch_seq_f_lt"),
1142        ("f.gt", "patch_seq_f_gt"),
1143        ("f.lte", "patch_seq_f_lte"),
1144        ("f.gte", "patch_seq_f_gte"),
1145        ("f.neq", "patch_seq_f_neq"),
1146        // Float type conversions
1147        ("int->float", "patch_seq_int_to_float"),
1148        ("float->int", "patch_seq_float_to_int"),
1149        ("float->string", "patch_seq_float_to_string"),
1150        ("string->float", "patch_seq_string_to_float"),
1151        // Test framework operations
1152        ("test.init", "patch_seq_test_init"),
1153        ("test.finish", "patch_seq_test_finish"),
1154        ("test.has-failures", "patch_seq_test_has_failures"),
1155        ("test.assert", "patch_seq_test_assert"),
1156        ("test.assert-not", "patch_seq_test_assert_not"),
1157        ("test.assert-eq", "patch_seq_test_assert_eq"),
1158        ("test.assert-eq-str", "patch_seq_test_assert_eq_str"),
1159        ("test.fail", "patch_seq_test_fail"),
1160        ("test.pass-count", "patch_seq_test_pass_count"),
1161        ("test.fail-count", "patch_seq_test_fail_count"),
1162        // Time operations
1163        ("time.now", "patch_seq_time_now"),
1164        ("time.nanos", "patch_seq_time_nanos"),
1165        ("time.sleep-ms", "patch_seq_time_sleep_ms"),
1166        // SON serialization
1167        ("son.dump", "patch_seq_son_dump"),
1168        ("son.dump-pretty", "patch_seq_son_dump_pretty"),
1169        // Stack introspection
1170        ("stack.dump", "patch_seq_stack_dump"),
1171    ])
1172});
1173
1174/// Emit all runtime function declarations to the IR string.
1175pub fn emit_runtime_decls(ir: &mut String) -> Result<(), CodeGenError> {
1176    for decl in RUNTIME_DECLARATIONS.iter() {
1177        if let Some(cat) = decl.category {
1178            writeln!(ir, "{}", cat)?;
1179        }
1180        writeln!(ir, "{}", decl.decl)?;
1181    }
1182    writeln!(ir)?;
1183    Ok(())
1184}