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 --- oryxc/src/main.rs | 109 +++++++++++++++++------------------------------------- 1 file changed, 34 insertions(+), 75 deletions(-) (limited to 'oryxc/src/main.rs') 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); } -- 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(-) (limited to 'oryxc/src/main.rs') 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 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(-) (limited to 'oryxc/src/main.rs') 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