sailfish/sailfish-compiler/src/compiler.rs

85 lines
2.2 KiB
Rust

use quote::ToTokens;
use std::fs;
use std::path::{Path, PathBuf};
use crate::error::*;
use crate::optimizer::Optimizer;
use crate::parser::Parser;
use crate::resolver::Resolver;
use crate::translator::Translator;
use crate::util::rustfmt_block;
pub struct Compiler {
delimiter: char,
escape: bool,
cache_dir: PathBuf,
}
impl Default for Compiler {
fn default() -> Self {
Self {
delimiter: '%',
escape: true,
cache_dir: Path::new(env!("OUT_DIR")).join("cache"),
}
}
}
impl Compiler {
pub fn new() -> Self {
Self::default()
}
pub fn delimiter(mut self, new: char) -> Self {
self.delimiter = new;
self
}
pub fn escape(mut self, new: bool) -> Self {
self.escape = new;
self
}
pub fn compile_file(&self, input: &Path, output: &Path) -> Result<(), Error> {
// TODO: introduce cache system
let parser = Parser::new().delimiter(self.delimiter);
let translator = Translator::new().escape(self.escape);
let resolver = Resolver::new();
let optimizer = Optimizer::new();
let compile_file = |input: &Path, output: &Path| -> Result<(), Error> {
let content = fs::read_to_string(&*input)
.chain_err(|| format!("Failed to open template file: {:?}", input))?;
let stream = parser.parse(&*content);
let mut tsource = translator.translate(stream)?;
drop(content);
resolver.resolve(&mut tsource.ast)?;
optimizer.optimize(&mut tsource.ast);
if let Some(parent) = output.parent() {
fs::create_dir_all(parent)?;
}
if output.exists() {
fs::remove_file(output)?;
}
let string = tsource.ast.into_token_stream().to_string();
fs::write(output, rustfmt_block(&*string).unwrap_or(string))?;
Ok(())
};
compile_file(&*input, &*output)
.chain_err(|| "Failed to compile template.")
.map_err(|mut e| {
e.source = fs::read_to_string(&*input).ok();
e.source_file = Some(input.to_owned());
e
})?;
Ok(())
}
}