From c6789ab3e29d33230da090fe7d8175d9210fa7ab Mon Sep 17 00:00:00 2001 From: romir kulshrestha Date: Wed, 4 Mar 2026 18:23:43 +0100 Subject: less retarded cli args --- Cargo.lock | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++- oryxc/Cargo.toml | 2 +- oryxc/src/errors.rs | 3 +- oryxc/src/main.rs | 109 +++++++++++++---------------------------- oryxc/src/parser.rs | 2 +- 5 files changed, 174 insertions(+), 79 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ed86017..3748ff6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,56 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + [[package]] name = "bitflags" version = "2.11.0" @@ -14,6 +64,52 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "clap" +version = "4.5.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -65,6 +161,18 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + [[package]] name = "lexopt" version = "0.3.2" @@ -92,13 +200,19 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "oryx" version = "0.1.0" dependencies = [ + "clap", "crossbeam-deque", "dashmap", - "lexopt", "phf", "soa-rs", "unicode-width", @@ -254,6 +368,12 @@ dependencies = [ "syn", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "2.0.117" @@ -284,8 +404,23 @@ dependencies = [ "lexopt", ] +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] diff --git a/oryxc/Cargo.toml b/oryxc/Cargo.toml index 1b418f3..4308b1a 100644 --- a/oryxc/Cargo.toml +++ b/oryxc/Cargo.toml @@ -7,7 +7,7 @@ edition = "2024" crossbeam-deque = "0.8.6" dashmap = "6.1.0" # icu = { version = "2.1.1", features = ["compiled_data"] } -lexopt = "0.3.2" +clap = { version = "4", features = ["derive"] } # num-rational = "0.4.2" phf = { version = "0.13.1", features = ["macros"] } soa-rs = "0.9.1" diff --git a/oryxc/src/errors.rs b/oryxc/src/errors.rs index 290abc2..71ed741 100644 --- a/oryxc/src/errors.rs +++ b/oryxc/src/errors.rs @@ -25,8 +25,9 @@ use crate::unicode; const TAB_AS_SPACES: &'static str = " "; const TABSIZE: usize = TAB_AS_SPACES.len(); -#[derive(Clone, Copy, Default, Eq, PartialEq)] +#[derive(Clone, Copy, Default, Eq, PartialEq, clap::ValueEnum)] pub enum ErrorStyle { + #[value(name = "oneline")] OneLine, #[default] Standard, diff --git a/oryxc/src/main.rs b/oryxc/src/main.rs index 7a0b0a8..ed7c550 100644 --- a/oryxc/src/main.rs +++ b/oryxc/src/main.rs @@ -7,101 +7,60 @@ mod parser; mod size; mod unicode; -use std::borrow::Cow; use std::ffi::OsString; -use std::{ - env, - process, - thread, -}; +use std::thread; -use lexopt; +use clap::Parser; #[derive(Clone, Copy, Default)] pub struct Flags { pub debug_lexer: bool, pub debug_parser: bool, - pub help: bool, pub threads: usize, pub error_style: errors::ErrorStyle, } -impl Flags { - fn parse() -> Result<(Flags, Vec), lexopt::Error> { - use lexopt::prelude::*; +#[derive(Parser)] +struct Args { + #[arg(short = 'l', long)] + debug_lexer: bool, - let mut rest = Vec::with_capacity(env::args().len()); - let mut flags = Flags::default(); - let mut parser = lexopt::Parser::from_env(); - parser.set_short_equals(false); + #[arg(short = 'p', long)] + debug_parser: bool, - while let Some(arg) = parser.next()? { - match arg { - Short('h') | Long("help") => flags.help = true, - Short('l') | Long("debug-lexer") => flags.debug_lexer = true, - Short('p') | Long("debug-parser") => flags.debug_parser = true, - Short('s') | Long("error-style") => { - flags.error_style = match parser.value()?.to_string_lossy() - { - Cow::Borrowed("oneline") => errors::ErrorStyle::OneLine, - Cow::Borrowed("standard") => { - errors::ErrorStyle::Standard - }, - s => Err(format!( - "{s}: invalid value for -s/--error-style" - ))?, - }; - }, - Short('t') | Long("threads") => { - flags.threads = parser.value()?.parse()?; - if flags.threads == 0 { - err!("thread count must be greater than 0"); - } - }, - Value(v) => rest.push(v), - _ => return Err(arg.unexpected()), - } - } + #[arg(short = 's', long, default_value = "standard")] + error_style: errors::ErrorStyle, - if flags.threads == 0 { - flags.threads = thread::available_parallelism().map_or_else( - |e| { - warn!(e, "failed to get thread count"); - 1 - }, - |x| x.get(), - ); - } + #[arg(short = 't', long)] + threads: Option, - return Ok((flags, rest)); - } -} - -fn usage() { - eprintln!( - concat!( - "Usage: {0} [-lp] [-s oneline|standard] [-t threads]\n", - " {0} -h", - ), - errors::progname().display() - ); + files: Vec, } fn main() { - let (flags, rest) = match Flags::parse() { - Ok(v) => v, - Err(e) => { - warn!(e); - usage(); - process::exit(1); - }, - }; + let args = Args::parse(); - if flags.help { - usage(); - process::exit(0); + let threads = args.threads.unwrap_or_else(|| { + thread::available_parallelism().map_or_else( + |e| { + warn!(e, "failed to get thread count"); + 1 + }, + |x| x.get(), + ) + }); + + if threads == 0 { + err!("thread count must be greater than 0"); } + let flags = Flags { + debug_lexer: args.debug_lexer, + debug_parser: args.debug_parser, + threads, + error_style: args.error_style, + }; + let _ = errors::ERROR_STYLE.set(flags.error_style); - compiler::start(rest, flags); + compiler::start(args.files, flags); } diff --git a/oryxc/src/parser.rs b/oryxc/src/parser.rs index a623d3e..193428b 100644 --- a/oryxc/src/parser.rs +++ b/oryxc/src/parser.rs @@ -825,7 +825,7 @@ impl<'a> Parser<'a> { p.extra_data.push(*x); } /* FIXME: Missing LHS, and doesn’t conform to the - * description at the definition of AstType */ + * description at the definition of AstType */ return Ok(p.new_node(AstNode { kind: AstType::FunCall, tok, -- cgit v1.2.3 From 0ab2106660280050f5b527ca58c5d673a43980d6 Mon Sep 17 00:00:00 2001 From: romir kulshrestha Date: Wed, 4 Mar 2026 19:02:53 +0100 Subject: idio(ma)tic --- oryxc/src/compiler.rs | 193 ++++++++++++++++++++++---------------------------- oryxc/src/main.rs | 4 +- 2 files changed, 87 insertions(+), 110 deletions(-) diff --git a/oryxc/src/compiler.rs b/oryxc/src/compiler.rs index 8fdd53f..355b496 100644 --- a/oryxc/src/compiler.rs +++ b/oryxc/src/compiler.rs @@ -3,20 +3,17 @@ use std::io::{ self, Write, }; -use std::iter::{ - self, - IntoIterator, -}; -use std::mem::MaybeUninit; -use std::sync::Arc; +use std::iter::once; use std::sync::atomic::{ AtomicUsize, Ordering, }; -use std::vec::Vec; +use std::sync::{ + Arc, + OnceLock, +}; use std::{ fs, - panic, process, thread, }; @@ -44,11 +41,11 @@ use crate::{ pub struct FileId(usize); pub struct FileData { - name: Arc, - buffer: Arc, - tokens: Arc>>, - ast: Arc>>, - extra_data: Arc>>, + pub name: OsString, + pub buffer: String, + pub tokens: OnceLock>, + pub ast: OnceLock>, + pub extra_data: OnceLock>, } impl FileData { @@ -58,26 +55,27 @@ impl FileData { // Append extra data to the end so that we can safely read past // instead of branching on length let mut buffer = fs::read_to_string(&name)?; - buffer.push_str(unsafe { str::from_utf8_unchecked(&PAD) }); - - return Ok(Self { - name: name.into(), - buffer: buffer.into(), - tokens: Arc::new_uninit(), - ast: Arc::new_uninit(), - extra_data: Arc::new_uninit(), - }); + buffer.push_str(unsafe { std::str::from_utf8_unchecked(&PAD) }); + + Ok(Self { + name, + buffer, + tokens: OnceLock::new(), + ast: OnceLock::new(), + extra_data: OnceLock::new(), + }) } } +#[allow(dead_code)] pub enum Job { - Lex { file: FileId }, - Parse { file: FileId }, - ResolveSymbols { file: FileId }, + Lex { file: FileId, fdata: Arc }, + Parse { file: FileId, fdata: Arc }, + ResolveSymbols { file: FileId, fdata: Arc }, } pub struct CompilerState { - pub files: DashMap, + pub files: DashMap>, pub globalq: Injector, pub njobs: AtomicUsize, pub flags: Flags, @@ -95,13 +93,13 @@ where }); for (i, path) in paths.into_iter().enumerate() { let id = FileId(i); - let data = match FileData::new(path.clone().into()) { - Ok(x) => x, - Err(e) => err!(e, "{}", path.display()), - }; - state.files.insert(id, data); + let fdata = Arc::new( + FileData::new(path.clone().into()) + .unwrap_or_else(|e| err!(e, "{}", path.display())), + ); + state.files.insert(id, Arc::clone(&fdata)); state.njobs.fetch_add(1, Ordering::Relaxed); - state.globalq.push(Job::Lex { file: id }); + state.globalq.push(Job::Lex { file: id, fdata }); } let mut workers = Vec::with_capacity(flags.threads); @@ -119,48 +117,28 @@ where let stealer_view = Arc::clone(&stealer_view); let state = Arc::clone(&state); threads.push(thread::spawn(move || { - worker_loop(id, state, w, stealer_view); + worker_loop(id, state, w, stealer_view) })); } for t in threads { - t.join().unwrap_or_else(|e| panic::resume_unwind(e)); - } -} - -macro_rules! fdata_read { - ($state:expr, $file:expr, $($field:ident),+ $(,)?) => { - #[allow(unused_parens)] - let ($($field),+) = { - let fdata = $state.files.get(&$file).unwrap(); - ($(fdata.$field.clone()),+) - }; - }; -} - -macro_rules! fdata_write { - ($state:expr, $file:expr, $($field:ident),+ $(,)?) => { - { - let mut fdata = $state.files.get_mut(&$file).unwrap(); - $( - fdata.$field = Arc::from(MaybeUninit::new($field)); - )+ + if let Err(e) = t.join() { + std::panic::resume_unwind(e) } - }; + } } -fn emit_errors(state: Arc, file: FileId, errors: T) +fn emit_errors(fdata: &FileData, errors: T) where T: IntoIterator, { - fdata_read!(state, file, name, buffer); - for e in errors.into_iter() { - e.report(name.as_ref(), buffer.as_ref()); + for e in errors { + e.report(&fdata.name, &fdata.buffer); } } fn worker_loop( - id: usize, + _id: usize, state: Arc, queue: Worker, stealers: Arc<[Stealer]>, @@ -170,62 +148,61 @@ fn worker_loop( break; } - let job = find_task(&queue, &state.globalq, &stealers); - if let Some(job) = job { - match job { - Job::Lex { file } => { - fdata_read!(state, file, buffer); - let tokens = match lexer::tokenize(buffer.as_ref()) { - Ok(xs) => xs, - Err(e) => { - emit_errors(state.clone(), file, iter::once(e)); - process::exit(1); - }, - }; + let Some(job) = find_task(&queue, &state.globalq, &stealers) else { + thread::yield_now(); + continue; + }; - if state.flags.debug_lexer { - let mut handle = io::stderr().lock(); - for t in tokens.iter() { - let _ = write!(handle, "{t:?}\n"); - } + match job { + Job::Lex { file, fdata } => { + let tokens = match lexer::tokenize(&fdata.buffer) { + Ok(xs) => xs, + Err(e) => { + emit_errors(&fdata, once(e)); + process::exit(1) + }, + }; + + if state.flags.debug_lexer { + let mut handle = io::stderr().lock(); + for t in tokens.iter() { + let _ = write!(handle, "{t:?}\n"); } - - fdata_write!(state, file, tokens); - state.njobs.fetch_add(1, Ordering::Relaxed); - queue.push(Job::Parse { file }); - }, - Job::Parse { file } => { - fdata_read!(state, file, tokens); - let (ast, extra_data) = match parser::parse( - unsafe { tokens.assume_init() }.as_ref(), - ) { + } + + fdata.tokens.set(tokens).unwrap(); + state.njobs.fetch_add(1, Ordering::Relaxed); + queue.push(Job::Parse { file, fdata }); + }, + Job::Parse { file, fdata } => { + let (ast, extra_data) = + match parser::parse(fdata.tokens.get().unwrap()) { Ok(xs) => xs, Err(errs) => { - emit_errors(state.clone(), file, errs); - process::exit(1); + emit_errors(&fdata, errs); + process::exit(1) }, }; - if state.flags.debug_parser { - let mut handle = io::stderr().lock(); - for n in ast.iter() { - let _ = write!(handle, "{n:?}\n"); - } + if state.flags.debug_parser { + let mut handle = io::stderr().lock(); + for n in ast.iter() { + let _ = write!(handle, "{n:?}\n"); } - - fdata_write!(state, file, ast, extra_data); - state.njobs.fetch_add(1, Ordering::Relaxed); - queue.push(Job::ResolveSymbols { file }); - }, - Job::ResolveSymbols { file } => { - err!("not implemented"); - }, - } - - state.njobs.fetch_sub(1, Ordering::Relaxed); - } else { - thread::yield_now(); + } + + fdata.ast.set(ast).unwrap(); + fdata.extra_data.set(extra_data).unwrap(); + state.njobs.fetch_add(1, Ordering::Relaxed); + queue.push(Job::ResolveSymbols { file, fdata }); + }, + Job::ResolveSymbols { file: _, fdata: _ } => { + err!("not implemented"); + // unimplemented!() + }, } + + state.njobs.fetch_sub(1, Ordering::Relaxed); } } @@ -256,5 +233,5 @@ fn find_task( } } - return None; + None } diff --git a/oryxc/src/main.rs b/oryxc/src/main.rs index ed7c550..b5c63cf 100644 --- a/oryxc/src/main.rs +++ b/oryxc/src/main.rs @@ -55,10 +55,10 @@ fn main() { } let flags = Flags { - debug_lexer: args.debug_lexer, + debug_lexer: args.debug_lexer, debug_parser: args.debug_parser, threads, - error_style: args.error_style, + error_style: args.error_style, }; let _ = errors::ERROR_STYLE.set(flags.error_style); -- cgit v1.2.3 From 8ca564832896700916b6d19e007eda361c075fc6 Mon Sep 17 00:00:00 2001 From: romir kulshrestha Date: Wed, 4 Mar 2026 19:06:59 +0100 Subject: fix ordering bug --- oryxc/src/compiler.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oryxc/src/compiler.rs b/oryxc/src/compiler.rs index 355b496..5a16356 100644 --- a/oryxc/src/compiler.rs +++ b/oryxc/src/compiler.rs @@ -144,7 +144,7 @@ fn worker_loop( stealers: Arc<[Stealer]>, ) { loop { - if state.njobs.load(Ordering::Relaxed) == 0 { + if state.njobs.load(Ordering::Acquire) == 0 { break; } @@ -202,7 +202,7 @@ fn worker_loop( }, } - state.njobs.fetch_sub(1, Ordering::Relaxed); + state.njobs.fetch_sub(1, Ordering::Release); } } -- cgit v1.2.3 From cb792e04c739aa0ea1e957595508b5d2b42fe1c2 Mon Sep 17 00:00:00 2001 From: romir kulshrestha Date: Wed, 4 Mar 2026 19:27:00 +0100 Subject: vec supremacy --- Cargo.lock | 88 ------------------------------------------ oryxc/Cargo.toml | 1 - oryxc/src/compiler.rs | 105 ++++++++++++++++++++++++++++++++++---------------- 3 files changed, 72 insertions(+), 122 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3748ff6..8bb0332 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,18 +52,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "bitflags" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - [[package]] name = "clap" version = "4.5.60" @@ -135,32 +123,12 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" -[[package]] -name = "dashmap" -version = "6.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" -dependencies = [ - "cfg-if", - "crossbeam-utils", - "hashbrown", - "lock_api", - "once_cell", - "parking_lot_core", -] - [[package]] name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - [[package]] name = "heck" version = "0.5.0" @@ -179,27 +147,6 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "803ec87c9cfb29b9d2633f20cba1f488db3fd53f2158b1024cbefb47ba05d413" -[[package]] -name = "libc" -version = "0.2.182" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - [[package]] name = "once_cell_polyfill" version = "1.70.2" @@ -212,25 +159,11 @@ version = "0.1.0" dependencies = [ "clap", "crossbeam-deque", - "dashmap", "phf", "soa-rs", "unicode-width", ] -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-link", -] - [[package]] name = "phf" version = "0.13.1" @@ -292,21 +225,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "serde" version = "1.0.228" @@ -342,12 +260,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - [[package]] name = "soa-rs" version = "0.9.1" diff --git a/oryxc/Cargo.toml b/oryxc/Cargo.toml index 4308b1a..267e889 100644 --- a/oryxc/Cargo.toml +++ b/oryxc/Cargo.toml @@ -5,7 +5,6 @@ edition = "2024" [dependencies] crossbeam-deque = "0.8.6" -dashmap = "6.1.0" # icu = { version = "2.1.1", features = ["compiled_data"] } clap = { version = "4", features = ["derive"] } # num-rational = "0.4.2" diff --git a/oryxc/src/compiler.rs b/oryxc/src/compiler.rs index 5a16356..2a0a3c9 100644 --- a/oryxc/src/compiler.rs +++ b/oryxc/src/compiler.rs @@ -1,6 +1,7 @@ use std::ffi::OsString; use std::io::{ self, + Read, Write, }; use std::iter::once; @@ -24,7 +25,6 @@ use crossbeam_deque::{ Stealer, Worker, }; -use dashmap::DashMap; use soa_rs::Soa; use crate::errors::OryxError; @@ -52,9 +52,12 @@ impl FileData { fn new(name: OsString) -> Result { const PAD: [u8; 64] = [0; 64]; /* 512 bits */ + // Pre-allocate to avoid reallocation when appending padding. // Append extra data to the end so that we can safely read past - // instead of branching on length - let mut buffer = fs::read_to_string(&name)?; + // instead of branching on length. + let size = fs::metadata(&name)?.len() as usize; + let mut buffer = String::with_capacity(size + PAD.len()); + fs::File::open(&name)?.read_to_string(&mut buffer)?; buffer.push_str(unsafe { std::str::from_utf8_unchecked(&PAD) }); Ok(Self { @@ -75,31 +78,56 @@ pub enum Job { } pub struct CompilerState { - pub files: DashMap>, - pub globalq: Injector, - pub njobs: AtomicUsize, - pub flags: Flags, + #[allow(dead_code)] + pub files: Vec>, + pub globalq: Injector, + pub njobs: AtomicUsize, + pub flags: Flags, + pub worker_threads: OnceLock>, +} + +impl CompilerState { + fn push_job(&self, queue: &Worker, job: Job) { + queue.push(job); + if let Some(threads) = self.worker_threads.get() { + for t in threads.iter() { + t.unpark(); + } + } + } } pub fn start(paths: T, flags: Flags) where T: IntoIterator, { - let state = Arc::new(CompilerState { - files: DashMap::new(), - globalq: Injector::new(), - njobs: AtomicUsize::new(0), - flags, - }); + let mut files = Vec::new(); + let mut initial_jobs = Vec::new(); + for (i, path) in paths.into_iter().enumerate() { let id = FileId(i); + + // take ownership of the OsString so we can store it in FileData without + // cloning + let display = path.to_string_lossy().into_owned(); let fdata = Arc::new( - FileData::new(path.clone().into()) - .unwrap_or_else(|e| err!(e, "{}", path.display())), + FileData::new(path).unwrap_or_else(|e| err!(e, "{}", display)), ); - state.files.insert(id, Arc::clone(&fdata)); - state.njobs.fetch_add(1, Ordering::Relaxed); - state.globalq.push(Job::Lex { file: id, fdata }); + files.push(Arc::clone(&fdata)); + initial_jobs.push(Job::Lex { file: id, fdata }); + } + + let njobs = initial_jobs.len(); + let state = Arc::new(CompilerState { + files, + globalq: Injector::new(), + njobs: AtomicUsize::new(njobs), + flags, + worker_threads: OnceLock::new(), + }); + + for job in initial_jobs { + state.globalq.push(job); } let mut workers = Vec::with_capacity(flags.threads); @@ -110,19 +138,23 @@ where workers.push(w); } - let mut threads = Vec::with_capacity(flags.threads); let stealer_view: Arc<[_]> = Arc::from(stealers); + let handles: Vec<_> = workers + .into_iter() + .enumerate() + .map(|(id, w)| { + let stealer_view = Arc::clone(&stealer_view); + let state = Arc::clone(&state); + thread::spawn(move || worker_loop(id, state, w, stealer_view)) + }) + .collect(); - for (id, w) in workers.into_iter().enumerate() { - let stealer_view = Arc::clone(&stealer_view); - let state = Arc::clone(&state); - threads.push(thread::spawn(move || { - worker_loop(id, state, w, stealer_view) - })); - } + let worker_threads: Box<[thread::Thread]> = + handles.iter().map(|h| h.thread().clone()).collect(); + let _ = state.worker_threads.set(worker_threads); - for t in threads { - if let Err(e) = t.join() { + for h in handles { + if let Err(e) = h.join() { std::panic::resume_unwind(e) } } @@ -149,7 +181,7 @@ fn worker_loop( } let Some(job) = find_task(&queue, &state.globalq, &stealers) else { - thread::yield_now(); + thread::park(); continue; }; @@ -172,7 +204,7 @@ fn worker_loop( fdata.tokens.set(tokens).unwrap(); state.njobs.fetch_add(1, Ordering::Relaxed); - queue.push(Job::Parse { file, fdata }); + state.push_job(&queue, Job::Parse { file, fdata }); }, Job::Parse { file, fdata } => { let (ast, extra_data) = @@ -194,15 +226,22 @@ fn worker_loop( fdata.ast.set(ast).unwrap(); fdata.extra_data.set(extra_data).unwrap(); state.njobs.fetch_add(1, Ordering::Relaxed); - queue.push(Job::ResolveSymbols { file, fdata }); + state.push_job(&queue, Job::ResolveSymbols { file, fdata }); }, Job::ResolveSymbols { file: _, fdata: _ } => { err!("not implemented"); - // unimplemented!() }, } - state.njobs.fetch_sub(1, Ordering::Release); + if state.njobs.fetch_sub(1, Ordering::Release) == 1 { + // njobs is 0; wake all threads so they can observe the termination + // condition and exit. + if let Some(threads) = state.worker_threads.get() { + for t in threads.iter() { + t.unpark(); + } + } + } } } -- cgit v1.2.3 From 9d0c4a673036e48b4d8a455eb468806e9087fb4e Mon Sep 17 00:00:00 2001 From: romir kulshrestha Date: Wed, 4 Mar 2026 19:54:34 +0100 Subject: multiline usage --- oryxc/src/compiler.rs | 23 ++++++++++------------- oryxc/src/errors.rs | 11 +++++++---- oryxc/src/main.rs | 21 +++++++++++++++++++-- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/oryxc/src/compiler.rs b/oryxc/src/compiler.rs index 2a0a3c9..a83cf45 100644 --- a/oryxc/src/compiler.rs +++ b/oryxc/src/compiler.rs @@ -187,13 +187,11 @@ fn worker_loop( match job { Job::Lex { file, fdata } => { - let tokens = match lexer::tokenize(&fdata.buffer) { - Ok(xs) => xs, - Err(e) => { + let tokens = + lexer::tokenize(&fdata.buffer).unwrap_or_else(|e| { emit_errors(&fdata, once(e)); process::exit(1) - }, - }; + }); if state.flags.debug_lexer { let mut handle = io::stderr().lock(); @@ -207,14 +205,13 @@ fn worker_loop( state.push_job(&queue, Job::Parse { file, fdata }); }, Job::Parse { file, fdata } => { - let (ast, extra_data) = - match parser::parse(fdata.tokens.get().unwrap()) { - Ok(xs) => xs, - Err(errs) => { - emit_errors(&fdata, errs); - process::exit(1) - }, - }; + let (ast, extra_data) = parser::parse( + fdata.tokens.get().unwrap(), + ) + .unwrap_or_else(|errs| { + emit_errors(&fdata, errs); + process::exit(1) + }); if state.flags.debug_parser { let mut handle = io::stderr().lock(); diff --git a/oryxc/src/errors.rs b/oryxc/src/errors.rs index 71ed741..4ad88d6 100644 --- a/oryxc/src/errors.rs +++ b/oryxc/src/errors.rs @@ -12,7 +12,10 @@ use std::fmt::{ }; use std::io::Write; use std::path::Path; -use std::sync::OnceLock; +use std::sync::{ + LazyLock, + OnceLock, +}; use std::{ env, io, @@ -36,12 +39,12 @@ pub enum ErrorStyle { pub static ERROR_STYLE: OnceLock = OnceLock::new(); pub fn progname() -> &'static OsString { - static ARGV0: OnceLock = OnceLock::new(); - return ARGV0.get_or_init(|| { + static ARGV0: LazyLock = LazyLock::new(|| { let default = OsStr::new("oryxc"); let s = env::args_os().next().unwrap_or(default.into()); - return Path::new(&s).file_name().unwrap_or(default).to_os_string(); + Path::new(&s).file_name().unwrap_or(default).to_os_string() }); + &ARGV0 } #[macro_export] diff --git a/oryxc/src/main.rs b/oryxc/src/main.rs index b5c63cf..7320c19 100644 --- a/oryxc/src/main.rs +++ b/oryxc/src/main.rs @@ -10,7 +10,11 @@ mod unicode; use std::ffi::OsString; use std::thread; -use clap::Parser; +use clap::{ + CommandFactory, + FromArgMatches, + Parser, +}; #[derive(Clone, Copy, Default)] pub struct Flags { @@ -38,7 +42,10 @@ struct Args { } fn main() { - let args = Args::parse(); + let args = Args::from_arg_matches( + &Args::command().override_usage(usage()).get_matches(), + ) + .unwrap_or_else(|e| e.exit()); let threads = args.threads.unwrap_or_else(|| { thread::available_parallelism().map_or_else( @@ -64,3 +71,13 @@ fn main() { let _ = errors::ERROR_STYLE.set(flags.error_style); compiler::start(args.files, flags); } + +fn usage() -> String { + format!( + concat!( + "Usage: {0} [-lp] [-s oneline|standard] [-t threads]\n", + " {0} -h", + ), + errors::progname().display() + ) +} -- cgit v1.2.3 From b678c18b38a4ae0b446a19df3929057dcb210d06 Mon Sep 17 00:00:00 2001 From: romir kulshrestha Date: Wed, 4 Mar 2026 20:09:27 +0100 Subject: wake_all() util --- oryxc/src/compiler.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/oryxc/src/compiler.rs b/oryxc/src/compiler.rs index a83cf45..b806a9e 100644 --- a/oryxc/src/compiler.rs +++ b/oryxc/src/compiler.rs @@ -87,14 +87,18 @@ pub struct CompilerState { } impl CompilerState { - fn push_job(&self, queue: &Worker, job: Job) { - queue.push(job); + fn wake_all(&self) { if let Some(threads) = self.worker_threads.get() { for t in threads.iter() { t.unpark(); } } } + + fn push_job(&self, queue: &Worker, job: Job) { + queue.push(job); + self.wake_all(); + } } pub fn start(paths: T, flags: Flags) @@ -233,11 +237,7 @@ fn worker_loop( if state.njobs.fetch_sub(1, Ordering::Release) == 1 { // njobs is 0; wake all threads so they can observe the termination // condition and exit. - if let Some(threads) = state.worker_threads.get() { - for t in threads.iter() { - t.unpark(); - } - } + state.wake_all(); } } } -- cgit v1.2.3 From 90e98f2f64d6700114c8e20c98a88e9814fb49ca Mon Sep 17 00:00:00 2001 From: romir kulshrestha Date: Wed, 4 Mar 2026 20:18:49 +0100 Subject: docstrs --- oryxc/src/compiler.rs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/oryxc/src/compiler.rs b/oryxc/src/compiler.rs index b806a9e..0d1c65d 100644 --- a/oryxc/src/compiler.rs +++ b/oryxc/src/compiler.rs @@ -49,6 +49,7 @@ pub struct FileData { } impl FileData { + /// Read a source file from disk and create a new [`FileData`]. fn new(name: OsString) -> Result { const PAD: [u8; 64] = [0; 64]; /* 512 bits */ @@ -87,6 +88,7 @@ pub struct CompilerState { } impl CompilerState { + /// Unpark all worker threads. fn wake_all(&self) { if let Some(threads) = self.worker_threads.get() { for t in threads.iter() { @@ -95,12 +97,14 @@ impl CompilerState { } } + /// Push a job onto a worker's local queue and wake all threads. fn push_job(&self, queue: &Worker, job: Job) { queue.push(job); self.wake_all(); } } +/// Initialize compiler state and drive all source files through the pipeline. pub fn start(paths: T, flags: Flags) where T: IntoIterator, @@ -164,15 +168,7 @@ where } } -fn emit_errors(fdata: &FileData, errors: T) -where - T: IntoIterator, -{ - for e in errors { - e.report(&fdata.name, &fdata.buffer); - } -} - +/// Steal and execute jobs until all work is complete. fn worker_loop( _id: usize, state: Arc, @@ -242,6 +238,7 @@ fn worker_loop( } } +/// Get next available job or steal from the global queue or peers if local queue is empty. fn find_task( localq: &Worker, globalq: &Injector, @@ -271,3 +268,13 @@ fn find_task( None } + +/// Print all errors to stderr using the file's name and source buffer. +fn emit_errors(fdata: &FileData, errors: T) +where + T: IntoIterator, +{ + for e in errors { + e.report(&fdata.name, &fdata.buffer); + } +} -- cgit v1.2.3