making the loader function customizable

Signed-off-by: Jakub Doka <jakub.doka2@gmail.com>
This commit is contained in:
Jakub Doka 2024-11-30 15:44:51 +01:00
parent e44d003e7f
commit e7cd2c0129
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
2 changed files with 32 additions and 18 deletions

View file

@ -571,7 +571,7 @@ Vec := fn($Elem: type): type return struct {
len: uint, len: uint,
cap: uint, cap: uint,
new := fn(): Self return .{data: @bitcast(0), len: 0, cap: 0} new := fn(): Self return .{data: @bitcast(@alignof(Elem)), len: 0, cap: 0}
deinit := fn(vec: ^Self): void { deinit := fn(vec: ^Self): void {
free(@bitcast(vec.data), vec.cap * @sizeof(Elem), @alignof(Elem)); free(@bitcast(vec.data), vec.cap * @sizeof(Elem), @alignof(Elem));

View file

@ -37,15 +37,16 @@ impl log::Log for Logger {
} }
#[derive(Default)] #[derive(Default)]
pub struct Options { pub struct Options<'a> {
pub fmt: bool, pub fmt: bool,
pub fmt_stdout: bool, pub fmt_stdout: bool,
pub dump_asm: bool, pub dump_asm: bool,
pub in_house_regalloc: bool, pub in_house_regalloc: bool,
pub extra_threads: usize, pub extra_threads: usize,
pub resolver: Option<PathResolver<'a>>,
} }
impl Options { impl Options<'static> {
pub fn from_args(args: &[&str], out: &mut Vec<u8>) -> std::io::Result<Self> { pub fn from_args(args: &[&str], out: &mut Vec<u8>) -> std::io::Result<Self> {
if args.contains(&"--help") || args.contains(&"-h") { if args.contains(&"--help") || args.contains(&"-h") {
writeln!(out, "Usage: hbc [OPTIONS...] <FILE>")?; writeln!(out, "Usage: hbc [OPTIONS...] <FILE>")?;
@ -71,6 +72,7 @@ impl Options {
.transpose()? .transpose()?
.map_or(1, NonZeroUsize::get) .map_or(1, NonZeroUsize::get)
- 1, - 1,
..Default::default()
}) })
} }
} }
@ -81,7 +83,11 @@ pub fn run_compiler(
out: &mut Vec<u8>, out: &mut Vec<u8>,
warnings: &mut String, warnings: &mut String,
) -> std::io::Result<()> { ) -> std::io::Result<()> {
let parsed = parse_from_fs(options.extra_threads, root_file)?; let parsed = parse_from_fs(
options.extra_threads,
root_file,
options.resolver.unwrap_or(&default_resolve),
)?;
if (options.fmt || options.fmt_stdout) && !parsed.errors.is_empty() { if (options.fmt || options.fmt_stdout) && !parsed.errors.is_empty() {
*out = parsed.errors.into_bytes(); *out = parsed.errors.into_bytes();
@ -220,23 +226,31 @@ pub struct Loaded {
errors: String, errors: String,
} }
pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Loaded> { fn default_resolve(path: &str, from: &str, tmp: &mut PathBuf) -> Result<PathBuf, CantLoadFile> {
fn resolve(path: &str, from: &str, tmp: &mut PathBuf) -> Result<PathBuf, CantLoadFile> { tmp.clear();
tmp.clear(); match Path::new(from).parent() {
match Path::new(from).parent() { Some(parent) => tmp.extend([parent, Path::new(path)]),
Some(parent) => tmp.extend([parent, Path::new(path)]), None => tmp.push(path),
None => tmp.push(path), };
};
tmp.canonicalize().map_err(|source| CantLoadFile { path: std::mem::take(tmp), source }) tmp.canonicalize().map_err(|source| CantLoadFile { path: std::mem::take(tmp), source })
} }
#[derive(Debug)] /// fn(path, from, tmp)
struct CantLoadFile { pub type PathResolver<'a> =
path: PathBuf, &'a (dyn Fn(&str, &str, &mut PathBuf) -> Result<PathBuf, CantLoadFile> + Send + Sync);
source: io::Error,
}
#[derive(Debug)]
pub struct CantLoadFile {
path: PathBuf,
source: io::Error,
}
pub fn parse_from_fs(
extra_threads: usize,
root: &str,
resolve: PathResolver,
) -> io::Result<Loaded> {
impl core::fmt::Display for CantLoadFile { impl core::fmt::Display for CantLoadFile {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "can't load file: {}", display_rel_path(&self.path),) write!(f, "can't load file: {}", display_rel_path(&self.path),)