1use crate::color::Themed;
5pub use crate::program_metadata::ProgramMetadata;
6
7#[derive(Debug, Clone, PartialEq)]
9pub struct LocalModule<I, V, Ty, Info = NoInfo> {
10 pub code: Vec<I>,
11 pub functions: Vec<FunctionInfo<Ty>>,
12 pub labels: Vec<LabelInfo>,
13 pub constants: Vec<V>,
14 pub strings: Vec<String>,
15 pub main_function: Option<u32>,
16 pub source_symbols: Vec<SourceSymbolInfo>,
17 pub extra: Info,
18}
19
20impl<I, V, Ty, Info> Default for LocalModule<I, V, Ty, Info>
21where
22 Info: Default,
23{
24 fn default() -> Self {
25 Self {
26 code: Vec::new(),
27 functions: Vec::new(),
28 labels: Vec::new(),
29 constants: Vec::new(),
30 strings: Vec::new(),
31 main_function: None,
32 source_symbols: Vec::new(),
33 extra: Info::default(),
34 }
35 }
36}
37
38#[derive(Debug, Clone, PartialEq, Eq, vihaco_parser_derive::Parse)]
39#[syntax_class(metadata, open = "{", close = "}")]
40pub struct SourceSymbolInfo {
41 pub index: u32,
42 pub name: String,
43}
44
45#[derive(Debug, Clone, PartialEq, vihaco_parser_derive::Parse)]
46#[syntax_class(metadata, open = "{", close = "}")]
47pub struct FunctionInfo<Type> {
48 pub name: u32, pub signature: Signature<Type>,
50 pub local_count: u32,
52 pub start_address: u32, pub end_address: u32, pub file: u32,
55}
56
57#[derive(Debug, Clone, PartialEq, vihaco_parser_derive::Parse)]
58#[syntax_class(metadata, open = "{", close = "}")]
59pub struct Signature<Ty> {
60 pub params: Vec<Parameter<Ty>>,
61 pub ret: Vec<Ty>,
62}
63
64#[derive(Debug, Clone, PartialEq, vihaco_parser_derive::Parse)]
65#[syntax_class(metadata, open = "{", close = "}")]
66pub struct Parameter<Ty> {
67 pub name: u32, pub ty: Ty,
69}
70
71#[derive(Debug, Clone, PartialEq, vihaco_parser_derive::Parse)]
72#[syntax_class(metadata, open = "{", close = "}")]
73pub struct LabelInfo {
74 pub address: u32,
75 pub name: u32, }
77
78#[derive(Debug, Clone, PartialEq, Default, vihaco_parser_derive::Parse)]
79#[syntax_class(metadata)]
80#[pattern = "`{` `}`"]
81pub struct NoInfo;
82
83impl std::fmt::Display for NoInfo {
84 fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85 Ok(())
86 }
87}
88
89impl<I, V, Ty, Info> std::fmt::Display for LocalModule<I, V, Ty, Info>
90where
91 I: std::fmt::Display,
92 V: std::fmt::Display,
93 Ty: std::fmt::Display,
94 Info: std::fmt::Display,
95{
96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 ".text".keyword().fmt(f)?;
98 writeln!(f)?;
99
100 for (addr, inst) in self.code.iter().enumerate() {
101 write!(f, "0x{:04X} ", addr)?;
102 inst.fmt(f)?;
103 writeln!(f)?;
104 }
105
106 writeln!(f)?;
107 ".const".keyword().fmt(f)?;
108 writeln!(f)?;
109 for (const_idx, constant) in self.constants.iter().enumerate() {
110 write!(f, "0x{:04X} ", const_idx)?;
111 constant.fmt(f)?;
112 writeln!(f)?;
113 }
114
115 writeln!(f)?;
116 ".string".keyword().fmt(f)?;
117 writeln!(f)?;
118 for (string_idx, string) in self.strings.iter().enumerate() {
119 if string_idx > 0 {
120 writeln!(f)?;
121 }
122 write!(f, "0x{:04X} \"{}\"", string_idx, string.escape_default())?;
123 }
124
125 writeln!(f)?;
126 if !self.source_symbols.is_empty() {
127 ".machine".keyword().fmt(f)?;
128 writeln!(f, " symbols {{")?;
129 for symbol in &self.source_symbols {
130 writeln!(f, " {}: {},", symbol.index, symbol.name)?;
131 }
132 writeln!(f, "}}")?;
133 writeln!(f)?;
134 }
135 writeln!(f)?;
136 ".feature".keyword().fmt(f)?;
137 writeln!(f)?;
138 self.extra.fmt(f)?;
139 Ok(())
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[derive(Debug, Clone, PartialEq)]
148 enum MockInst {
149 Push(u64),
150 Add,
151 Print,
152 Halt,
153 }
154
155 impl std::fmt::Display for MockInst {
156 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
157 match self {
158 MockInst::Push(v) => write!(f, "push {}", v),
159 MockInst::Add => write!(f, "add"),
160 MockInst::Print => write!(f, "print"),
161 MockInst::Halt => write!(f, "halt"),
162 }
163 }
164 }
165
166 #[test]
167 fn test_module() {
168 let mut module: LocalModule<MockInst, u64, &str> = LocalModule::default();
169 module.code.push(MockInst::Push(42));
170 module.code.push(MockInst::Push(42));
171 module.code.push(MockInst::Add);
172 module.code.push(MockInst::Print);
173 module.code.push(MockInst::Halt);
174
175 module.constants.push(42);
176 module.constants.push(100);
177
178 module.strings.push("hello".to_string());
179 module.strings.push("world".to_string());
180 println!("{:#}", module);
181 }
182}