Skip to main content

seqc/codegen/
runtime.rs

1//! Runtime function declarations for LLVM IR.
2//!
3//! The full set of `declare` statements and Seq-word → C-symbol mappings is
4//! split across the sibling `runtime/` sub-modules by category. Each
5//! sub-module exposes two slices — `DECLS` and `SYMBOLS` — and this file
6//! concatenates them into the public `RUNTIME_DECLARATIONS` and
7//! `BUILTIN_SYMBOLS` statics used by the rest of codegen.
8//!
9//! Adding a new runtime entry point is a two-line edit to the appropriate
10//! sub-module: append a `RuntimeDecl { decl, category }` and, if the entry
11//! point is callable from Seq, append a `(seq-word, c-symbol)` pair.
12
13mod adt;
14mod args_exit;
15mod arith;
16mod callable;
17mod closure;
18mod collections;
19mod concurrency;
20mod float;
21mod fs;
22mod http;
23mod misc;
24mod os;
25mod stack;
26mod stdio;
27mod tcp;
28mod test_time;
29mod text;
30mod udp;
31
32use super::error::CodeGenError;
33use std::collections::HashMap;
34use std::fmt::Write as _;
35use std::sync::LazyLock;
36
37/// A runtime function declaration for LLVM IR.
38pub struct RuntimeDecl {
39    /// LLVM declaration string (e.g., "declare ptr @patch_seq_add(ptr)")
40    pub decl: &'static str,
41    /// Optional category comment (e.g., "; Stack operations")
42    pub category: Option<&'static str>,
43}
44
45/// All runtime function declarations, assembled in IR-emission order.
46pub static RUNTIME_DECLARATIONS: LazyLock<Vec<&'static RuntimeDecl>> = LazyLock::new(|| {
47    let slices: &[&[RuntimeDecl]] = &[
48        stdio::DECLS,
49        arith::DECLS,
50        stack::DECLS,
51        callable::DECLS,
52        closure::DECLS,
53        concurrency::DECLS,
54        args_exit::DECLS,
55        fs::DECLS,
56        collections::DECLS,
57        tcp::DECLS,
58        udp::DECLS,
59        http::DECLS,
60        os::DECLS,
61        text::DECLS,
62        adt::DECLS,
63        float::DECLS,
64        test_time::DECLS,
65        misc::DECLS,
66    ];
67    slices.iter().flat_map(|s| s.iter()).collect()
68});
69
70/// Mapping from Seq word names to their C runtime symbol names.
71/// This centralizes all the name transformations in one place:
72/// - Symbolic operators (=, <, >) map to descriptive names (eq, lt, gt)
73/// - Hyphens become underscores for C compatibility
74/// - Special characters get escaped (?, +, ->)
75/// - Reserved words get suffixes (drop -> drop_op)
76pub static BUILTIN_SYMBOLS: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
77    let slices: &[&[(&str, &str)]] = &[
78        stdio::SYMBOLS,
79        args_exit::SYMBOLS,
80        arith::SYMBOLS,
81        stack::SYMBOLS,
82        concurrency::SYMBOLS,
83        callable::SYMBOLS,
84        closure::SYMBOLS,
85        tcp::SYMBOLS,
86        udp::SYMBOLS,
87        http::SYMBOLS,
88        os::SYMBOLS,
89        text::SYMBOLS,
90        misc::SYMBOLS,
91        adt::SYMBOLS,
92        fs::SYMBOLS,
93        collections::SYMBOLS,
94        float::SYMBOLS,
95        test_time::SYMBOLS,
96    ];
97    slices.iter().flat_map(|s| s.iter().copied()).collect()
98});
99
100/// Emit all runtime function declarations to the IR string.
101pub fn emit_runtime_decls(ir: &mut String) -> Result<(), CodeGenError> {
102    for decl in RUNTIME_DECLARATIONS.iter() {
103        if let Some(cat) = decl.category {
104            writeln!(ir, "{}", cat)?;
105        }
106        writeln!(ir, "{}", decl.decl)?;
107    }
108    writeln!(ir)?;
109    Ok(())
110}