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 write_file(&self, filename: &str, content: String) -> 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() } }