surreal/
module.rs

1//! Module system for organizing functions.
2
3use std::collections::{HashMap, HashSet};
4
5use crate::Instruction;
6
7/// A compiled module containing functions.
8#[derive(Debug, Clone)]
9pub struct Module {
10    /// Module name (e.g., "math", "lists").
11    pub name: String,
12
13    /// All bytecode for this module, concatenated.
14    /// Functions reference ranges within this code.
15    pub code: Vec<Instruction>,
16
17    /// Function table: maps (name, arity) -> function metadata.
18    pub functions: HashMap<(String, u8), FunctionDef>,
19
20    /// Exported functions (subset of functions callable from outside).
21    pub exports: HashSet<(String, u8)>,
22}
23
24/// Definition of a function within a module.
25#[derive(Debug, Clone)]
26pub struct FunctionDef {
27    /// Function name.
28    pub name: String,
29
30    /// Number of arguments.
31    pub arity: u8,
32
33    /// Index into module's code where function starts.
34    pub entry: usize,
35}
36
37impl Module {
38    /// Create a new empty module.
39    pub fn new(name: String) -> Self {
40        Self {
41            name,
42            code: Vec::new(),
43            functions: HashMap::new(),
44            exports: HashSet::new(),
45        }
46    }
47
48    /// Add a function to this module.
49    ///
50    /// The function's code is appended to the module's code vector,
51    /// and a FunctionDef is created pointing to the entry point.
52    pub fn add_function(&mut self, name: String, arity: u8, code: Vec<Instruction>) {
53        let entry = self.code.len();
54
55        self.code.extend(code);
56        self.functions
57            .insert((name.clone(), arity), FunctionDef { name, arity, entry });
58    }
59
60    /// Add a function definition at a specific entry point.
61    ///
62    /// Used by codegen when code is built separately.
63    pub fn add_function_at(&mut self, name: String, arity: u8, entry: usize) {
64        self.functions
65            .insert((name.clone(), arity), FunctionDef { name, arity, entry });
66    }
67
68    /// Mark a function as exported (callable from other modules).
69    pub fn export(&mut self, name: &str, arity: u8) {
70        self.exports.insert((name.to_string(), arity));
71    }
72
73    /// Look up a function by name and arity.
74    pub fn get_function(&self, name: &str, arity: u8) -> Option<&FunctionDef> {
75        self.functions.get(&(name.to_string(), arity))
76    }
77
78    /// Check if a function is exported.
79    pub fn is_exported(&self, name: &str, arity: u8) -> bool {
80        self.exports.contains(&(name.to_string(), arity))
81    }
82}