- 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:
@@ -10,7 +10,10 @@ use std::{
|
||||
};
|
||||
|
||||
pub use common::logging::log;
|
||||
use common::prelude::Instruction;
|
||||
use common::{
|
||||
build::{BuildError, Builder},
|
||||
prelude::Instruction,
|
||||
};
|
||||
|
||||
// Module declarations
|
||||
#[macro_use]
|
||||
@@ -37,17 +40,27 @@ pub use self::{
|
||||
|
||||
use crate::util::logging::{Entry, Logger};
|
||||
|
||||
pub struct CompilerEngine {
|
||||
result_tx: mpsc::Sender<Result<Vec<Instruction>, AssembleError>>,
|
||||
result_rx: Option<mpsc::Receiver<Result<Vec<Instruction>, AssembleError>>>,
|
||||
pub struct Assembler {
|
||||
src_path: PathBuf,
|
||||
result_tx: mpsc::Sender<Result<Vec<u8>, AssembleError>>,
|
||||
result_rx: Option<mpsc::Receiver<Result<Vec<u8>, AssembleError>>>,
|
||||
is_running: bool,
|
||||
}
|
||||
|
||||
impl CompilerEngine {
|
||||
impl From<AssembleError> for BuildError {
|
||||
fn from(err: AssembleError) -> Self {
|
||||
Self::Generic(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl Builder for Assembler {
|
||||
type Output = Vec<u8>;
|
||||
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
fn new(src_path: impl Into<PathBuf>) -> Self {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
Self {
|
||||
src_path: src_path.into(),
|
||||
result_tx: tx,
|
||||
result_rx: Some(rx),
|
||||
is_running: false,
|
||||
@@ -55,25 +68,29 @@ impl CompilerEngine {
|
||||
}
|
||||
|
||||
/// Start the compilation process in a separate thread
|
||||
pub fn start_compilation(&mut self, src: &Path) {
|
||||
fn start(&mut self) {
|
||||
if self.is_running {
|
||||
return;
|
||||
}
|
||||
|
||||
let src = src.to_path_buf();
|
||||
let src = self.src_path.clone();
|
||||
let tx = self.result_tx.clone();
|
||||
|
||||
thread::spawn(move || {
|
||||
let result = assemble(&src);
|
||||
tx.send(result)
|
||||
.expect("Failed to send compilation result from worker thread");
|
||||
if let Ok(res) = assemble(&src) {
|
||||
let buffer: Vec<u8> = res
|
||||
.iter()
|
||||
.flat_map(|instruction| instruction.encode().to_be_bytes())
|
||||
.collect();
|
||||
tx.send(Ok(buffer))
|
||||
.expect("Failed to send compilation result from worker thread");
|
||||
}
|
||||
});
|
||||
|
||||
self.is_running = true;
|
||||
}
|
||||
|
||||
/// Check if compilation is complete and get the result
|
||||
pub fn try_get_result(&mut self) -> Option<Result<Vec<Instruction>, AssembleError>> {
|
||||
fn poll(&mut self) -> Option<Result<Self::Output, common::build::BuildError>> {
|
||||
if !self.is_running {
|
||||
return None;
|
||||
}
|
||||
@@ -86,22 +103,20 @@ impl CompilerEngine {
|
||||
{
|
||||
Ok(result) => {
|
||||
self.is_running = false;
|
||||
Some(result)
|
||||
Some(result.map_err(std::convert::Into::into))
|
||||
}
|
||||
Err(mpsc::TryRecvError::Empty) => None,
|
||||
Err(mpsc::TryRecvError::Disconnected) => {
|
||||
self.is_running = false;
|
||||
Some(Err(AssembleError::Generic))
|
||||
Some(Err(BuildError::Generic(String::from(
|
||||
"Compilation terminated before a result was returned",
|
||||
))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Block until compilation is complete and return the result
|
||||
pub fn wait_for_result(&mut self) -> Result<Vec<Instruction>, AssembleError> {
|
||||
if !self.is_running {
|
||||
return Err(AssembleError::Generic);
|
||||
}
|
||||
|
||||
fn output(&mut self) -> Result<Self::Output, common::build::BuildError> {
|
||||
if let Ok(result) = self
|
||||
.result_rx
|
||||
.take()
|
||||
@@ -109,14 +124,18 @@ impl CompilerEngine {
|
||||
.recv()
|
||||
{
|
||||
self.is_running = false;
|
||||
result
|
||||
result.map_err(std::convert::Into::into)
|
||||
} else {
|
||||
self.is_running = false;
|
||||
Err(AssembleError::Generic)
|
||||
Err(BuildError::Generic(String::from(
|
||||
"Compilation terminated before a result was returned",
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Assembler {}
|
||||
|
||||
fn assemble(src: &Path) -> Result<Vec<Instruction>, AssembleError> {
|
||||
let mut modules = HashSet::new();
|
||||
let mut program = Program::new();
|
||||
@@ -142,12 +161,6 @@ fn assemble(src: &Path) -> Result<Vec<Instruction>, AssembleError> {
|
||||
Ok(instructions)
|
||||
}
|
||||
|
||||
impl Default for CompilerEngine {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare_dependency(
|
||||
path: &Path,
|
||||
modules: &mut HashSet<u64>,
|
||||
|
||||
+1
-26
@@ -18,33 +18,8 @@ pub mod tooling;
|
||||
mod util;
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::assembler::CompilerEngine;
|
||||
pub use crate::assembler::Assembler;
|
||||
pub use crate::image_builder;
|
||||
pub use crate::tooling::brainf;
|
||||
pub use crate::tooling::project;
|
||||
}
|
||||
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use num_cpus as _;
|
||||
use threadpool as _;
|
||||
|
||||
use crate::prelude::CompilerEngine;
|
||||
|
||||
pub fn assemble_file(input: &str, output: &str) -> Result<(), std::io::Error> {
|
||||
let mut engine = CompilerEngine::new();
|
||||
engine.start_compilation(Path::new(input));
|
||||
let result = engine.wait_for_result().expect("assembler failed.");
|
||||
|
||||
let buffer: Vec<u8> = result
|
||||
.iter()
|
||||
.flat_map(|instruction| instruction.encode().to_be_bytes())
|
||||
.collect();
|
||||
|
||||
if let Err(e) = fs::write(output, buffer) {
|
||||
eprintln!("Failed to write to output file: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+10
-5
@@ -1,9 +1,6 @@
|
||||
use common as _;
|
||||
use num_cpus as _;
|
||||
use threadpool as _;
|
||||
use common::{self as _, build::Builder};
|
||||
|
||||
use assembler::{
|
||||
assemble_file,
|
||||
prelude::*,
|
||||
tooling::{brainf, project},
|
||||
};
|
||||
@@ -47,5 +44,13 @@ fn main() {
|
||||
|
||||
let input_path = &args[2];
|
||||
let output_path = &args[4];
|
||||
assemble_file(input_path, output_path).unwrap();
|
||||
|
||||
let mut engine = Assembler::new(PathBuf::from(input_path));
|
||||
engine.start();
|
||||
let result = engine.output().expect("assembler failed.");
|
||||
|
||||
if let Err(e) = fs::write(output_path, result) {
|
||||
eprintln!("Failed to write to output file: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user