Skip to main content

python_assembler/builder/
mod.rs

1#![doc = include_str!("readme.md")]
2
3use crate::{
4    instructions::PythonInstruction,
5    program::{PycHeader, PythonCodeObject, PythonObject, PythonProgram},
6};
7
8/// PycProgram 的构建器
9#[derive(Debug)]
10pub struct PythonBuilder {
11    _instructions: Vec<PythonInstruction>,
12    constants: Vec<PythonObject>,
13    names: Vec<String>,
14}
15
16impl PythonBuilder {
17    /// 创建一个新的 PythonBuilder 实例。
18    pub fn new() -> Self {
19        Self { _instructions: vec![PythonInstruction::RESUME], constants: vec![PythonObject::None], names: Vec::new() }
20    }
21
22    /// 添加打印字符串指令:print("...")
23    pub fn print_str(mut self, s: &str) -> Self {
24        let const_value = PythonObject::Str(s.to_string());
25        let const_index = self.constants.len() as u32;
26        self.constants.push(const_value);
27
28        let print_name = "print".to_string();
29        let name_index = if let Some(idx) = self.names.iter().position(|n| n == &print_name) {
30            idx as u32
31        }
32        else {
33            self.names.push(print_name);
34            (self.names.len() - 1) as u32
35        };
36
37        // Python 3.11+ 打印序列
38        self._instructions.push(PythonInstruction::PUSH_NULL);
39        self._instructions.push(PythonInstruction::LOAD_GLOBAL(name_index << 1)); // 3.11+ LOAD_GLOBAL arg is (index << 1) | push_null
40        self._instructions.push(PythonInstruction::LOAD_CONST(const_index));
41        self._instructions.push(PythonInstruction::CALL(1));
42        self._instructions.push(PythonInstruction::POP_TOP);
43        self
44    }
45
46    /// 构建 PythonProgram。
47    pub fn build(mut self, header: PycHeader) -> PythonProgram {
48        use crate::program::PythonVersion;
49
50        // 结束指令
51        self._instructions.push(PythonInstruction::RETURN_CONST(0)); // 返回 None (constants[0])
52
53        let version = PythonVersion::from_magic(header.magic);
54        PythonProgram {
55            header,
56            code_object: PythonCodeObject {
57                name: "<module>".to_string(),
58                qualname: "<module>".to_string(),
59                source_name: "<string>".to_string(),
60                first_line: 1,
61                last_line: 1,
62                co_argcount: 0,
63                co_posonlyargcount: 0,
64                co_kwonlyargcount: 0,
65                co_nlocals: 0,
66                co_stacksize: 10,
67                co_flags: 0x40, // CO_NOFREE
68                co_code: self._instructions,
69                co_consts: self.constants,
70                co_names: self.names,
71                co_localsplusnames: vec![],
72                co_localspluskinds: vec![],
73                co_linetable: vec![0, 1], // Simple linetable
74                co_exceptiontable: vec![],
75            },
76            version,
77        }
78    }
79}