chipi_core/backend/
cpp.rs1use crate::codegen_cpp;
7use crate::config::GenTarget;
8use crate::tree;
9use crate::types::ValidatedDef;
10
11use super::{CodegenBackend, CodegenError};
12
13pub struct CppBackend;
15
16pub struct CppOptions {
18 pub namespace: Option<String>,
20 pub guard_style: GuardStyle,
22 pub includes: Vec<String>,
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum GuardStyle {
28 Pragma,
29 Ifndef,
30}
31
32impl CodegenBackend for CppBackend {
33 fn lang(&self) -> &str {
34 "cpp"
35 }
36
37 fn validate_lang_options(&self, options: &toml::Value) -> Result<(), Vec<String>> {
38 let table = match options {
39 toml::Value::Table(t) => t,
40 _ => return Ok(()),
41 };
42
43 let known_keys = ["namespace", "guard_style", "includes"];
44 let mut errors = Vec::new();
45 for key in table.keys() {
46 if !known_keys.contains(&key.as_str()) {
47 errors.push(format!("unknown lang_option: {}", key));
48 }
49 }
50
51 if errors.is_empty() {
52 Ok(())
53 } else {
54 Err(errors)
55 }
56 }
57
58 fn generate(&self, ir: &ValidatedDef, config: &GenTarget) -> Result<String, CodegenError> {
59 let tree = tree::build_tree(ir);
60 let opts = parse_cpp_options(config);
61 Ok(codegen_cpp::generate_cpp_code(
62 ir,
63 &tree,
64 &opts,
65 &config.type_map,
66 ))
67 }
68
69 fn formatter_command(&self) -> Option<&[&str]> {
70 Some(&["clang-format", "-i"])
71 }
72}
73
74fn parse_cpp_options(config: &GenTarget) -> CppOptions {
75 let table = match &config.lang_options {
76 Some(toml::Value::Table(t)) => Some(t.clone()),
77 _ => None,
78 };
79
80 let namespace = table
81 .as_ref()
82 .and_then(|t| t.get("namespace"))
83 .and_then(|v| v.as_str())
84 .map(|s| s.to_string());
85
86 let guard_style = table
87 .as_ref()
88 .and_then(|t| t.get("guard_style"))
89 .and_then(|v| v.as_str())
90 .map(|s| match s {
91 "ifndef" => GuardStyle::Ifndef,
92 _ => GuardStyle::Pragma,
93 })
94 .unwrap_or(GuardStyle::Pragma);
95
96 let includes = table
97 .as_ref()
98 .and_then(|t| t.get("includes"))
99 .and_then(|v| v.as_array())
100 .map(|arr| {
101 arr.iter()
102 .filter_map(|v| v.as_str().map(|s| s.to_string()))
103 .collect()
104 })
105 .unwrap_or_default();
106
107 CppOptions {
108 namespace,
109 guard_style,
110 includes,
111 }
112}