use std::{collections::HashMap, path::PathBuf}; use anyhow::{Context, Result}; use crate::{ ir::{EnumDefinition, ServiceDefinition, TypeDefinition}, IR, }; pub trait Compile { fn new(options: &HashMap) -> Result where Self: Sized; fn name(&self) -> String; fn start(&mut self, ctx: &mut CompileContext) -> Result<()>; fn generate_type( &mut self, ctx: &mut CompileContext, definition: &TypeDefinition, ) -> Result<()>; fn generate_enum( &mut self, ctx: &mut CompileContext, definition: &EnumDefinition, ) -> Result<()>; fn generate_service( &mut self, ctx: &mut CompileContext, definition: &ServiceDefinition, ) -> Result<()>; fn finalize(&mut self, ctx: &mut CompileContext, ir: &IR) -> Result<()>; } pub struct CompileContext { output_folder: PathBuf, } impl CompileContext { pub fn new(output_folder: &str) -> Self { CompileContext { output_folder: output_folder.into(), } } pub fn to_snake(name: &str) -> String { let mut result = String::new(); let mut last_upper = false; for c in name.chars() { if c.is_uppercase() { if last_upper { result.push(c.to_ascii_lowercase()); } else { if !result.is_empty() { result.push('_'); } result.push(c.to_ascii_lowercase()); } last_upper = true; } else { result.push(c); last_upper = false; } } result } pub fn strip_template_ignores(content: &str) -> String { let mut result = String::new(); let mut ignore = false; for line in content.lines() { if ignore { ignore = false; continue; } if line.trim().contains("@template-ignore") { ignore = true; continue; } result.push_str(line); result.push_str("\n"); } result } pub fn write_file(&self, filename: &str, content: &str) -> Result<()> { let res_path = self.output_folder.clone().join(filename); let res_dir = res_path.parent().context("Path has no parent!")?; std::fs::create_dir_all(res_dir)?; std::fs::write(res_path, content)?; Ok(()) } } pub struct FileGenerator { content: Vec, } impl FileGenerator { pub fn new() -> Self { FileGenerator { content: Vec::new(), } } pub fn a(&mut self, indent: usize, content: T) { let line = " ".repeat(indent) + &content.to_string(); self.content.push(line); } pub fn a0(&mut self, content: T) { self.a(0, content); } pub fn a1(&mut self, content: T) { self.a(1, content); } pub fn a2(&mut self, content: T) { self.a(2, content); } pub fn a3(&mut self, content: T) { self.a(3, content); } pub fn a4(&mut self, content: T) { self.a(4, content); } pub fn a5(&mut self, content: T) { self.a(5, content); } pub fn a6(&mut self, content: T) { self.a(6, content); } // pub fn add_line(&mut self, line: &str) { // self.content.push(line.to_string()); // } pub fn get_content(&self) -> String { self.content.join("\n") } pub fn into_content(self) -> String { self.get_content() } }