Skip to main content

brik64_bir/
module.rs

1//! BIR module — parsed representation of a BIR program.
2
3/// A parsed BIR function.
4#[derive(Debug, Clone)]
5pub struct BirFunction {
6    /// Fully qualified name (e.g. `fn::main`).
7    pub name: String,
8    /// Parameter names.
9    pub params: Vec<String>,
10    /// Raw instruction lines.
11    pub instructions: Vec<String>,
12}
13
14/// A parsed BIR module containing one or more functions.
15#[derive(Debug, Clone)]
16pub struct BirModule {
17    /// Functions in declaration order.
18    pub functions: Vec<BirFunction>,
19}
20
21/// Parse error.
22#[derive(Debug)]
23pub struct ParseError(pub String);
24
25impl std::fmt::Display for ParseError {
26    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27        write!(f, "BIR parse error: {}", self.0)
28    }
29}
30
31impl BirModule {
32    /// Parse a BIR text program into a module.
33    ///
34    /// ```
35    /// use brik64_bir::BirModule;
36    ///
37    /// let src = "FUNCTION fn::answer [] -> i64\n  CONST $0 42\n  RETURN $0\nEND\n";
38    /// let module = BirModule::parse(src).unwrap();
39    /// assert_eq!(module.functions.len(), 1);
40    /// assert_eq!(module.functions[0].name, "fn::answer");
41    /// ```
42    pub fn parse(source: &str) -> Result<BirModule, ParseError> {
43        let mut functions = Vec::new();
44        let mut current: Option<BirFunction> = None;
45
46        for (lineno, raw) in source.lines().enumerate() {
47            let line = raw.trim();
48            if line.is_empty() || line.starts_with(';') {
49                continue;
50            }
51
52            if line.starts_with("FUNCTION ") {
53                if let Some(f) = current.take() {
54                    functions.push(f);
55                }
56                // Parse: FUNCTION fn::name [param1 param2] -> type
57                let rest = &line[9..];
58                let bracket_start = rest.find('[').ok_or_else(|| {
59                    ParseError(format!("line {}: missing '[' in FUNCTION", lineno + 1))
60                })?;
61                let name = rest[..bracket_start].trim().to_string();
62                let bracket_end = rest.find(']').ok_or_else(|| {
63                    ParseError(format!("line {}: missing ']' in FUNCTION", lineno + 1))
64                })?;
65                let params_str = &rest[bracket_start + 1..bracket_end];
66                let params = params_str
67                    .split_whitespace()
68                    .filter(|s| !s.is_empty())
69                    .map(String::from)
70                    .collect();
71                current = Some(BirFunction {
72                    name,
73                    params,
74                    instructions: Vec::new(),
75                });
76            } else if line == "END" {
77                if let Some(f) = current.take() {
78                    functions.push(f);
79                }
80            } else if let Some(ref mut f) = current {
81                f.instructions.push(line.to_string());
82            }
83        }
84
85        if let Some(f) = current {
86            functions.push(f);
87        }
88
89        Ok(BirModule { functions })
90    }
91
92    /// Find a function by name.
93    pub fn get_function(&self, name: &str) -> Option<&BirFunction> {
94        self.functions.iter().find(|f| f.name == name)
95    }
96}