- 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:
2026-02-22 21:43:22 +00:00
parent 4ed5da259e
commit 7117b927f3
9 changed files with 203 additions and 129 deletions
+41 -28
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
}