/* * Copyright (C) 2023 The Trinitrix Project * * This file is part of the Trixy crate for Trinitrix. * * Trixy is free software: you can redistribute it and/or modify * it under the terms of the Lesser GNU General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * and the Lesser GNU General Public License along with this program. * If not, see . */ use std::{env, fs, io::Write, path::PathBuf, process::Command}; use trixy_lang_parser::parse_trixy_lang; use crate::config::TrixyConfig; pub mod config; mod generate; const VIM_LINE_RUST: &'static str = "// vim: filetype=rust\n"; const VIM_LINE_C: &'static str = "// vim: filetype=c\n"; impl TrixyConfig { /// This is the heart of Trixy /// It mainly does one thing: /// - Generate a tree of modules from the input trixy file /// pub fn generate(&self) { let source_code = fs::read_to_string(&self.trixy_path).unwrap_or_else(|err| { panic! {"Can't read file at path: '{}'. The Error is: '{}'", self.trixy_path.display(), err}; }); let trixy_code = parse_trixy_lang(&source_code).unwrap_or_else(|err| { panic! {"Parsing of the trixy file failed: \n{}", err} }); // host code let host_code = prettyplease::unparse( &syn::parse2(generate::generate(&trixy_code, &self)) .expect("This code was generated, it should also be parsable"), ); let mut host_code_out = fs::File::create(PathBuf::from(format!( "{}/{}", env::var("OUT_DIR").expect("The build script should have this define"), &self.host_code_name.display() ))) .expect("This file should always be free to use"); write!(host_code_out, "{}\n{}", host_code, VIM_LINE_RUST).expect("Write should work"); // c header let c_header = generate::c_api::header::generate(&trixy_code, &self); let c_header_path = PathBuf::from(format!( "{}/{}", env::var("OUT_DIR").expect("The build script should have this define"), &self.c_header_name.display() )); let mut c_header_out = fs::File::create(&c_header_path).expect("This file should always be free to use"); write!(c_header_out, "{}\n{}", c_header, VIM_LINE_C).expect("Write should work"); Command::new("clang-format") .args(["-i", &c_header_path.to_str().unwrap()]) .status() .unwrap_or_else(|err| { panic!( "Failed to format the c header file with `clang-format`; Error: `{}`", err ) }); if let Some(dist_dir) = &self.dist_dir_path { if !dist_dir.is_dir() { fs::create_dir(dist_dir).unwrap_or_else(|err| { panic! { "Failed to create the dist directory ('{}') because of: `{}`", dist_dir.display(), err} }); } if self.check_dist_dir { if dist_dir.read_dir().iter().count() != 1 { panic!("Your specified dist dir already has something in it! Set `check_dist_dir` to `false` to override this check"); } } let c_header_dist = PathBuf::from(format!( "{}/{}", dist_dir.display(), self.c_header_name.display() )); fs::copy(c_header_path, c_header_dist).unwrap_or_else( |err| panic! {"Failed to copy the c header to the dist dir because of: `{}`", err}, ); } } }