device_driver_generation/
lib.rs1#![doc = include_str!(concat!("../", env!("CARGO_PKG_README")))]
2
3use itertools::Itertools;
4
5#[cfg(feature = "dsl")]
6mod dsl_hir;
7mod lir;
8#[cfg(feature = "manifest")]
9mod manifest;
10pub mod mir;
11
12#[cfg(feature = "dsl")]
17pub fn transform_dsl(input: proc_macro2::TokenStream, driver_name: &str) -> String {
18 let mir = match _private_transform_dsl_mir(input) {
19 Ok(mir) => mir,
20 Err(e) => return e.into_compile_error().to_string(),
21 };
22
23 transform_mir(mir, driver_name)
24}
25
26#[doc(hidden)]
27#[cfg(feature = "dsl")]
28pub fn _private_transform_dsl_mir(
29 input: proc_macro2::TokenStream,
30) -> Result<mir::Device, syn::Error> {
31 let hir = syn::parse2::<dsl_hir::Device>(input)?;
33
34 let mir = dsl_hir::mir_transform::transform(hir)?;
36
37 Ok(mir)
38}
39
40#[cfg(feature = "json")]
45pub fn transform_json(source: &str, driver_name: &str) -> String {
46 let mir = match _private_transform_json_mir(source) {
47 Ok(mir) => mir,
48 Err(e) => return anyhow_error_to_compile_error(e),
49 };
50
51 transform_mir(mir, driver_name)
52}
53
54#[doc(hidden)]
55#[cfg(feature = "json")]
56pub fn _private_transform_json_mir(source: &str) -> anyhow::Result<mir::Device> {
57 let value = dd_manifest_tree::parse_manifest::<dd_manifest_tree::JsonValue>(source)?;
58 let mir = manifest::transform(value)?;
59
60 Ok(mir)
61}
62
63#[cfg(feature = "yaml")]
68pub fn transform_yaml(source: &str, driver_name: &str) -> String {
69 let mir = match _private_transform_yaml_mir(source) {
70 Ok(mir) => mir,
71 Err(e) => return anyhow_error_to_compile_error(e),
72 };
73
74 transform_mir(mir, driver_name)
75}
76
77#[doc(hidden)]
78#[cfg(feature = "yaml")]
79pub fn _private_transform_yaml_mir(source: &str) -> anyhow::Result<mir::Device> {
80 let value = dd_manifest_tree::parse_manifest::<dd_manifest_tree::YamlValue>(source)?;
81 let mir = manifest::transform(value)?;
82
83 Ok(mir)
84}
85
86#[cfg(feature = "toml")]
91pub fn transform_toml(source: &str, driver_name: &str) -> String {
92 let mir = match _private_transform_toml_mir(source) {
93 Ok(mir) => mir,
94 Err(e) => return anyhow_error_to_compile_error(e),
95 };
96
97 transform_mir(mir, driver_name)
98}
99
100#[doc(hidden)]
101#[cfg(feature = "toml")]
102pub fn _private_transform_toml_mir(source: &str) -> anyhow::Result<mir::Device> {
103 let value = dd_manifest_tree::parse_manifest::<dd_manifest_tree::TomlValue>(source)?;
104 let mir = manifest::transform(value)?;
105
106 Ok(mir)
107}
108
109fn transform_mir(mut mir: mir::Device, driver_name: &str) -> String {
110 match mir::passes::run_passes(&mut mir) {
112 Ok(()) => {}
113 Err(e) => return anyhow_error_to_compile_error(e),
114 }
115
116 let mut lir = match mir::lir_transform::transform(mir, driver_name) {
118 Ok(lir) => lir,
119 Err(e) => return anyhow_error_to_compile_error(e),
120 };
121
122 match lir::passes::run_passes(&mut lir) {
124 Ok(()) => {}
125 Err(e) => return anyhow_error_to_compile_error(e),
126 };
127
128 let output = lir::code_transform::DeviceTemplateRust::new(&lir).to_string();
130
131 match format_code(&output) {
132 Ok(formatted_output) => formatted_output,
133 Err(e) => format!(
134 "{}\n\n{output}",
135 e.to_string().lines().map(|e| format!("// {e}")).join("\n")
136 ),
137 }
138}
139
140fn anyhow_error_to_compile_error(error: anyhow::Error) -> String {
141 syn::Error::new(proc_macro2::Span::call_site(), format!("{error:#}"))
142 .into_compile_error()
143 .to_string()
144}
145
146fn format_code(input: &str) -> Result<String, anyhow::Error> {
147 Ok(prettyplease::unparse(&syn::parse_file(input)?))
148}