- updated common with new compiler/builder trait to provide a common
interface for build tools - updated editor and build tooling to use new system
This commit is contained in:
+59
-49
@@ -1,8 +1,11 @@
|
||||
#![feature(try_trait_v2)]
|
||||
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use common::logging::log;
|
||||
use common::{
|
||||
build::{BuildError, Builder},
|
||||
logging::log,
|
||||
};
|
||||
|
||||
use crate::{model::CompilerError, specialised::build_specialised};
|
||||
|
||||
@@ -11,64 +14,71 @@ mod frontend;
|
||||
mod model;
|
||||
mod specialised;
|
||||
|
||||
pub fn compile_file(
|
||||
input_path: &Path,
|
||||
output_path: &Path,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let input = std::fs::read_to_string(input_path).expect("Failed to read input file");
|
||||
pub struct Compiler {
|
||||
src_path: PathBuf,
|
||||
result: Option<Result<String, BuildError>>,
|
||||
}
|
||||
|
||||
let input_ext = input_path
|
||||
.extension()
|
||||
.and_then(|s| s.to_str())
|
||||
.unwrap_or("");
|
||||
impl Compiler {
|
||||
fn build(&mut self) -> Result<String, Box<dyn std::error::Error>> {
|
||||
let input =
|
||||
std::fs::read_to_string(&self.src_path).expect("Failed to read input file");
|
||||
|
||||
// check if we're using a specialised compiler
|
||||
if let Some(output) = build_specialised(input_ext, &input) {
|
||||
let result = match output {
|
||||
Ok(output) => output,
|
||||
let input_ext = self
|
||||
.src_path
|
||||
.extension()
|
||||
.and_then(|s| s.to_str())
|
||||
.unwrap_or("");
|
||||
|
||||
// check if we're using a specialised compiler
|
||||
if let Some(output) = build_specialised(input_ext, &input) {
|
||||
return output.map_err(|err| format!("Compilation failed: {err:?}").into());
|
||||
}
|
||||
|
||||
// Parse the input using the frontend, providing the file extension and data.
|
||||
let ast = match frontend::compiler_frontend(input_ext, &input) {
|
||||
Ok(ast) => ast,
|
||||
Err(err) => return Err(format!("Compilation failed: {err:?}").into()),
|
||||
};
|
||||
|
||||
std::fs::write(output_path, &result).expect("Failed to write output");
|
||||
// println!("Parsed AST: {:#?}", ast);
|
||||
|
||||
log(&format!(
|
||||
"Compilation Successful ✅ \n\tSource: {}\n\tOutput: {}\n",
|
||||
input_path.display(),
|
||||
output_path.display(),
|
||||
));
|
||||
// Generate the output using the backend with the parsed result.
|
||||
let result = match backend::compiler_backend("dsa", &ast) {
|
||||
Ok(result) => result,
|
||||
Err(err) => return Err(format!("Compilation failed: {err:?}").into()),
|
||||
};
|
||||
|
||||
return Ok(());
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl Builder for Compiler {
|
||||
type Output = String;
|
||||
|
||||
fn new(src_path: impl Into<PathBuf>) -> Self {
|
||||
Self {
|
||||
src_path: src_path.into(),
|
||||
result: None,
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the input using the frontend, providing the file extension and data.
|
||||
let ast = match frontend::compiler_frontend(input_ext, &input) {
|
||||
Ok(ast) => ast,
|
||||
Err(err) => return Err(format!("Compilation failed: {err:?}").into()),
|
||||
};
|
||||
fn start(&mut self) {
|
||||
match self.build() {
|
||||
Ok(x) => self.result = Some(Ok(x)),
|
||||
Err(err) => self.result = Some(Err(err.into())),
|
||||
}
|
||||
}
|
||||
|
||||
println!("Parsed AST: {:#?}", ast);
|
||||
fn poll(&mut self) -> Option<Result<Self::Output, BuildError>> {
|
||||
self.result.take()
|
||||
}
|
||||
|
||||
let output_ext = output_path
|
||||
.extension()
|
||||
.and_then(|s| s.to_str())
|
||||
.unwrap_or("");
|
||||
|
||||
// Generate the output using the backend with the parsed result.
|
||||
let result = match backend::compiler_backend(output_ext, &ast) {
|
||||
Ok(result) => result,
|
||||
Err(err) => return Err(format!("Compilation failed: {err:?}").into()),
|
||||
};
|
||||
|
||||
// println!("{result}");
|
||||
std::fs::write(output_path, &result).expect("Failed to write output");
|
||||
|
||||
log(&format!(
|
||||
"Compilation Successful ✅ \n\tSource: {}\n\tOutput: {}\n",
|
||||
input_path.display(),
|
||||
output_path.display(),
|
||||
));
|
||||
|
||||
Ok(())
|
||||
fn output(&mut self) -> Result<Self::Output, BuildError> {
|
||||
self.result.clone().ok_or(BuildError::Generic(String::from(
|
||||
"Compiler was never started",
|
||||
)))?
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error(msg: impl Into<String>) -> CompilerError {
|
||||
|
||||
+16
-2
@@ -1,4 +1,7 @@
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use common::{build::Builder, logging::log};
|
||||
use compiler::Compiler;
|
||||
|
||||
fn main() {
|
||||
// read from input file: syntax "c_compiler <src.c> [output.dsa]"
|
||||
@@ -15,5 +18,16 @@ fn main() {
|
||||
"output.dsa"
|
||||
};
|
||||
|
||||
compiler::compile_file(Path::new(input_file), Path::new(output_file)).unwrap();
|
||||
{
|
||||
let mut builder = Compiler::new(PathBuf::from(input_file));
|
||||
builder.start();
|
||||
let result = builder.output().unwrap();
|
||||
|
||||
std::fs::write(output_file, &result).expect("Failed to write output");
|
||||
|
||||
log(&format!(
|
||||
"Compilation Successful ✅ \n\tSource: {}\n\tOutput: {}\n",
|
||||
input_file, output_file,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use core::fmt;
|
||||
|
||||
use common::build::BuildError;
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum CompilerError {
|
||||
@@ -14,6 +16,12 @@ pub enum CompilerError {
|
||||
Unimplemented(String),
|
||||
}
|
||||
|
||||
impl From<CompilerError> for BuildError {
|
||||
fn from(err: CompilerError) -> Self {
|
||||
BuildError::Generic(format!("{:?}", err))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub struct Name {
|
||||
pub name: String,
|
||||
|
||||
Reference in New Issue
Block a user