diff options
| author | Thomas Voss <mail@thomasvoss.com> | 2026-03-17 19:56:03 +0100 |
|---|---|---|
| committer | Thomas Voss <mail@thomasvoss.com> | 2026-03-17 19:56:16 +0100 |
| commit | db11ea02d777a33fedb6af4ee056e85f52fbb008 (patch) | |
| tree | 95243c3efe24bac3caabf2eb364911230a59d3ce | |
| parent | ad2c6812a71f10797a4023e175b7a0d2d9b1fa81 (diff) | |
| -rw-r--r-- | oryxc/src/arena.rs | 265 | ||||
| -rw-r--r-- | oryxc/src/compiler.rs | 176 | ||||
| -rw-r--r-- | oryxc/src/depmap.rs | 31 | ||||
| -rw-r--r-- | oryxc/src/hashtrie.rs | 219 | ||||
| -rw-r--r-- | oryxc/src/main.rs | 3 | ||||
| -rw-r--r-- | oryxc/src/parser.rs | 14 | ||||
| -rw-r--r-- | oryxc/src/prelude.rs | 38 | ||||
| -rw-r--r-- | oryxc/src/unistr.rs | 8 |
8 files changed, 70 insertions, 684 deletions
diff --git a/oryxc/src/arena.rs b/oryxc/src/arena.rs deleted file mode 100644 index cb05908..0000000 --- a/oryxc/src/arena.rs +++ /dev/null @@ -1,265 +0,0 @@ -use std::alloc::{ - self, - Layout, -}; -use std::cell::{ - Cell, - RefCell, -}; -use std::ptr::{ - self, - NonNull, -}; -use std::slice; -use std::sync::Mutex; - -use crate::err; - -#[derive(Copy, Clone)] -struct RawBlock { - ptr: NonNull<u8>, - layout: Layout, -} - -unsafe impl Send for RawBlock {} -unsafe impl Sync for RawBlock {} - -pub struct GlobalArena { - blksz: usize, - blocks: Mutex<Vec<RawBlock>>, -} - -impl GlobalArena { - pub fn new(blksz: usize) -> Self { - return Self { - blksz, - blocks: Mutex::new(Vec::new()), - }; - } - - fn allocate_block(&self, layout: Layout) -> RawBlock { - let layout = Layout::from_size_align( - layout.size().max(self.blksz), - layout.align().max(16), - ) - .unwrap_or_else(|e| err!(e, "allocation error")); - let ptr = NonNull::new(unsafe { alloc::alloc(layout) }) - .unwrap_or_else(|| alloc::handle_alloc_error(layout)); - - let block = RawBlock { ptr, layout }; - self.blocks.lock().unwrap().push(block.clone()); - return block; - } -} - -impl Drop for GlobalArena { - fn drop(&mut self) { - for block in self.blocks.lock().unwrap().iter() { - unsafe { - alloc::dealloc(block.ptr.as_ptr(), block.layout); - } - } - } -} - -#[derive(Clone, Copy)] -pub struct Mark { - blk: usize, - beg: *mut u8, - end: *mut u8, -} - -pub struct LocalArena<'a> { - parent: &'a GlobalArena, - beg: Cell<*mut u8>, - end: Cell<*mut u8>, - curblk: Cell<usize>, - blks: RefCell<Vec<RawBlock>>, - #[cfg(debug_assertions)] - pub waterline: Cell<usize>, -} - -impl<'a> LocalArena<'a> { - pub fn new(parent: &'a GlobalArena) -> Self { - return Self { - parent, - beg: Cell::new(ptr::null_mut()), - end: Cell::new(ptr::null_mut()), - curblk: Cell::new(usize::MAX), - blks: RefCell::new(Vec::new()), - #[cfg(debug_assertions)] - waterline: Cell::new(0), - }; - } - - fn alloc_raw(&self, layout: Layout) -> NonNull<u8> { - if cfg!(debug_assertions) { - self.waterline.update(|x| x + layout.size()); - } - - let beg = self.beg.get() as usize; - - let align_offset = - beg.wrapping_add(layout.align() - 1) & !(layout.align() - 1); - let Some(next_beg) = align_offset.checked_add(layout.size()) else { - err!("allocation overflow"); - }; - - return if next_beg <= self.end.get() as usize { - self.beg.set(next_beg as *mut u8); - unsafe { NonNull::new_unchecked(align_offset as *mut u8) } - } else { - self.alloc_slow(layout) - }; - } - - #[cold] - fn alloc_slow(&self, layout: Layout) -> NonNull<u8> { - let mut blks = self.blks.borrow_mut(); - let next_blk = self.curblk.get().wrapping_add(1); - - /* Find the next recycleable block that fits */ - let mut found_blk = None; - let mut align_beg = 0; - for i in next_blk..blks.len() { - let blk = &blks[i]; - let beg = blk.ptr.as_ptr() as usize; - let end = beg + blk.layout.size(); - let aligned = - beg.wrapping_add(layout.align() - 1) & !(layout.align() - 1); - if aligned.checked_add(layout.size()).unwrap_or(usize::MAX) <= end { - found_blk = Some(i); - align_beg = aligned; - break; - } - } - - if let Some(i) = found_blk { - blks.swap(next_blk, i); - - let blk = &blks[next_blk]; - let end = blk.ptr.as_ptr() as usize + blk.layout.size(); - - self.curblk.set(next_blk); - self.beg.set((align_beg + layout.size()) as *mut u8); - self.end.set(end as *mut u8); - - return unsafe { NonNull::new_unchecked(align_beg as *mut u8) }; - } - - let blk = self.parent.allocate_block(layout); - let beg = blk.ptr.as_ptr() as usize; - let end = beg + blk.layout.size(); - let align_beg = - beg.wrapping_add(layout.align() - 1) & !(layout.align() - 1); - - blks.push(blk); - let last_blk = blks.len() - 1; - blks.swap(next_blk, last_blk); - - self.curblk.set(next_blk); - self.beg.set((align_beg + layout.size()) as *mut u8); - self.end.set(end as *mut u8); - - unsafe { NonNull::new_unchecked(align_beg as *mut u8) } - } - - pub fn alloc<T>(&self, value: T) -> &'a mut T { - let ptr = self.alloc_raw(Layout::new::<T>()).cast::<T>().as_ptr(); - unsafe { - ptr::write(ptr, value); - return &mut *ptr; - } - } - - pub fn alloc_slice<T>(&self, len: usize) -> &'a mut [T] { - let layout = Layout::array::<T>(len) - .unwrap_or_else(|e| err!(e, "allocation error")); - let ptr = self.alloc_raw(layout).cast::<T>().as_ptr(); - return unsafe { slice::from_raw_parts_mut(ptr, len) }; - } - - pub fn mark(&self) -> Mark { - return Mark { - blk: self.curblk.get(), - beg: self.beg.get(), - end: self.end.get(), - }; - } - - pub fn restore(&self, mark: Mark) { - self.curblk.set(mark.blk); - self.beg.set(mark.beg); - self.end.set(mark.end); - } - - pub fn scope<'s, R, F>(&'s mut self, f: F) -> R - where - F: FnOnce(&ScopedArena<'s, 'a>) -> R, - { - let m = self.mark(); - let r = f(&ScopedArena { inner: self }); - self.restore(m); - return r; - } -} - -/// A wrapper around LocalArena that bounds returned references to 's. -pub struct ScopedArena<'s, 'a> { - inner: &'s LocalArena<'a>, -} - -impl<'s, 'a> ScopedArena<'s, 'a> { - pub fn alloc<T>(&self, value: T) -> &'s mut T { - return self.inner.alloc(value); - } - - pub fn alloc_slice<T>(&self, len: usize) -> &'s mut [T] { - return self.inner.alloc_slice(len); - } -} - -#[cfg(test)] -mod tests { - use super::{ - GlobalArena, - LocalArena, - }; - - #[test] - fn test_alloc_slice() { - let arena_global = GlobalArena::new(8); - let arena_local_1 = LocalArena::new(&arena_global); - let arena_local_2 = LocalArena::new(&arena_global); - - let s1 = arena_local_1.alloc_slice(8); - let s2 = arena_local_2.alloc_slice(4); - assert_eq!(s1.len(), 8); - assert_eq!(s2.len(), 4); - - for i in 0..s1.len() { - s1[i] = i; - } - for i in 0..s2.len() { - s2[i] = i; - } - } - - #[test] - fn test_arena_grows() { - let arena_global = GlobalArena::new(8); - let arena_local = LocalArena::new(&arena_global); - - let s1 = arena_local.alloc_slice(8); - let s2 = arena_local.alloc_slice(69); - assert_eq!(s1.len(), 8); - assert_eq!(s2.len(), 69); - - for i in 0..s1.len() { - s1[i] = i; - } - for i in 0..s2.len() { - s2[i] = i; - } - } -} diff --git a/oryxc/src/compiler.rs b/oryxc/src/compiler.rs index 8ad00fb..6119915 100644 --- a/oryxc/src/compiler.rs +++ b/oryxc/src/compiler.rs @@ -20,7 +20,6 @@ use std::{ thread, }; -use boxcar; use crossbeam_deque::{ Injector, Steal, @@ -29,19 +28,10 @@ use crossbeam_deque::{ }; use soa_rs::Soa; -use crate::arena::{ - GlobalArena, - LocalArena, -}; -use crate::depmap::DepMap; use crate::errors::OryxError; -use crate::hashtrie::HTrie; use crate::intern::Interner; use crate::lexer::Token; -use crate::parser::{ - Ast, - AstType, -}; +use crate::parser::Ast; use crate::prelude::*; use crate::unistr::UniStr; use crate::{ @@ -49,7 +39,6 @@ use crate::{ err, lexer, parser, - size, }; #[allow(dead_code)] @@ -58,7 +47,7 @@ pub struct FileData { pub buffer: String, pub tokens: OnceLock<Soa<Token>>, pub ast: OnceLock<Ast>, - pub scopes: OnceLock<HTrie<ScopeId, Scope>>, + pub scopes: OnceLock<Vec<Scope>>, } impl FileData { @@ -87,24 +76,8 @@ impl FileData { #[allow(dead_code)] #[derive(Clone)] pub enum JobType { - Lex { - file: FileId, - fdata: Arc<FileData>, - }, - Parse { - file: FileId, - fdata: Arc<FileData>, - }, - IndexScopeConstants { - fdata: Arc<FileData>, - block: u32, - parent: ScopeId, - }, - ResolveDefBind { - fdata: Arc<FileData>, - node: u32, - scope: ScopeId, - }, + Lex { file: FileId, fdata: Arc<FileData> }, + Parse { file: FileId, fdata: Arc<FileData> }, } mkidtype!(JobId); @@ -117,7 +90,6 @@ pub struct Job { struct CompilerState<'a> { #[allow(dead_code)] - global_arena: GlobalArena, globalq: Injector<Job>, njobs: AtomicUsize, flags: Flags, @@ -128,9 +100,7 @@ struct CompilerState<'a> { * order to avoid any potential undefined behaviour. */ interner: Interner<UniStr<'a>, SymbolId>, files: Vec<Arc<FileData>>, - deps: DepMap, next_id: AtomicU32, - types: boxcar::Vec<OryxType>, } impl<'a> CompilerState<'a> { @@ -164,6 +134,17 @@ impl<'a> CompilerState<'a> { self.wake_all(); } + /// Push multiple jobs onto a worker’s local queue and wake all + /// threads. + #[inline(always)] + pub fn job_push_multi(&self, queue: &Worker<Job>, jobs: &[Job]) { + self.njobs.fetch_add(jobs.len(), Ordering::Relaxed); + for job in jobs.iter() { + queue.push(job.clone()); + } + self.wake_all(); + } + /// Signal a job completion by decrementing the job count. /// /// Returns the number of remaining jobs @@ -202,28 +183,12 @@ where let state = Arc::new(CompilerState { files, - global_arena: GlobalArena::new(size::kibibytes(64)), globalq: Injector::new(), njobs: AtomicUsize::new(njobs), flags, worker_threads: OnceLock::new(), interner: Interner::new(), - deps: DepMap::with_capacity(256), next_id: AtomicU32::new(njobs as u32), - /* Temporary solution */ - types: boxcar::vec![ - OryxType::Integer /* int */ { bits: 64, signed: true }, - OryxType::Integer /* i8 */ { bits: 8, signed: true }, - OryxType::Integer /* i16 */ { bits: 16, signed: true }, - OryxType::Integer /* i32 */ { bits: 32, signed: true }, - OryxType::Integer /* i64 */ { bits: 64, signed: true }, - OryxType::Integer /* i128 */ { bits: 128, signed: true }, - OryxType::Integer /* u8 */ { bits: 8, signed: false }, - OryxType::Integer /* u16 */ { bits: 16, signed: false }, - OryxType::Integer /* u32 */ { bits: 32, signed: false }, - OryxType::Integer /* u64 */ { bits: 64, signed: false }, - OryxType::Integer /* u128 */ { bits: 128, signed: false }, - ], }); for job in initial_jobs { @@ -248,7 +213,6 @@ where for (i, w) in workers.into_iter().enumerate() { let stealers = Arc::clone(&stealers); let state = Arc::clone(&state); - let arena = LocalArena::new(&state.global_arena); let handle = s.spawn(move || worker_loop(i, state, w, stealers)); worker_threads[i].write(handle.thread().clone()); handles[i].write(handle); @@ -282,7 +246,6 @@ fn worker_loop( stealers: Arc<[Stealer<Job>]>, ) -> bool { let mut ok = true; - let arena = LocalArena::new(&c_state.global_arena); loop { let Some(job) = find_task(&queue, &c_state.globalq, &stealers) else { @@ -338,108 +301,19 @@ fn worker_loop( } } - let root = (ast.nodes.len() - 1) as u32; fdata.ast.set(ast).unwrap(); - fdata.scopes.set(HTrie::new()).unwrap(); - - c_state.job_push( - &queue, - c_state.job_new(JobType::IndexScopeConstants { - fdata, - block: root, - parent: ScopeId::INVALID, - }), - ); + fdata.scopes.set(Vec::new()).unwrap(); + + // c_state.job_push( + // &queue, + // c_state.job_new(JobType::IndexScopeConstants { + // fdata, + // block: root, + // parent: ScopeId::INVALID, + // }), + // ); true }, - - JobType::IndexScopeConstants { - fdata, - block, - parent, - } => { - let tokens = fdata.tokens.get().unwrap(); - let ast = fdata.ast.get().unwrap(); - let SubNodes(beg, nstmts) = ast.nodes.sub()[block as usize]; - - let mut errors = Vec::new(); - let scope = Scope::new(parent); - - /* First pass inserts all the symbols in this scope into the - * symbol table */ - for i in beg..beg + nstmts { - let node = ast.extra[i as usize]; - if ast.nodes.kind()[node as usize] != AstType::MultiDefBind - { - continue; - } - - let identsbeg = ast.nodes.sub()[node as usize].0; - let nidents = ast.extra[identsbeg as usize]; - - for j in 0..nidents { - let ident = ast.extra[(identsbeg + 1 + j * 2) as usize]; - let span = tokens.view()[ident as usize]; - - /* Make string slice lifetime 'static */ - let view = unsafe { - &*(&fdata.buffer[span.0..span.1] as *const str) - }; - - let symid = c_state.interner.intern(UniStr(view)); - let sym = Symbol { - state: ResolutionState::Unresolved, - kind: SymbolType::Constant, - }; - - if let Some(mut sym) = - scope.symtab.insert(symid, sym, &arena) - { - sym.state = ResolutionState::Poisoned; - scope.symtab.insert(symid, sym, &arena); - errors.push(OryxError::new( - span, - format!( - "symbol ‘{view}’ defined multiple times" - ), - )); - } - } - } - - let scopeid = if parent == ScopeId::INVALID { - ScopeId::GLOBAL - } else { - ScopeId(c_state.genid()) - }; - fdata.scopes.get().unwrap().insert(scopeid, scope, &arena); - - /* Second pass emits jobs to resolve types */ - for i in beg..beg + nstmts { - let node = ast.extra[i as usize]; - if ast.nodes.kind()[node as usize] != AstType::MultiDefBind - { - continue; - } - c_state.job_push( - &queue, - c_state.job_new(JobType::ResolveDefBind { - fdata: fdata.clone(), - node, - scope: scopeid, - }), - ); - } - - let ok = errors.is_empty(); - emit_errors(&fdata, errors); - ok - }, - - JobType::ResolveDefBind { fdata, node, scope } => { - todo!("resolving is yet to be implemented"); - true - }, }; if !result { ok = false; diff --git a/oryxc/src/depmap.rs b/oryxc/src/depmap.rs deleted file mode 100644 index 60e358e..0000000 --- a/oryxc/src/depmap.rs +++ /dev/null @@ -1,31 +0,0 @@ -use boxcar; -use dashmap::DashMap; - -use crate::compiler::Job; -use crate::prelude::*; - -pub struct DepMap(DashMap<Dependency, boxcar::Vec<Job>>); - -#[derive(Eq, Hash, PartialEq)] -pub enum Dependency { - Symbol(SymbolId), -} - -impl DepMap { - pub fn with_capacity(n: usize) -> Self { - return Self(DashMap::with_capacity(n)); - } - - pub fn add(&self, d: Dependency, j: Job) { - self.0 - .entry(d) - .and_modify(|v| { - v.push(j.clone()); - }) - .or_insert_with(|| boxcar::vec![j]); - } - - pub fn pop(&self, d: Dependency) -> Option<boxcar::Vec<Job>> { - return self.0.remove(&d).map(|(_, v)| v); - } -} diff --git a/oryxc/src/hashtrie.rs b/oryxc/src/hashtrie.rs deleted file mode 100644 index 87c561e..0000000 --- a/oryxc/src/hashtrie.rs +++ /dev/null @@ -1,219 +0,0 @@ -use std::hash::{ - Hash, - Hasher, -}; -use std::ptr; -use std::sync::atomic::{ - AtomicPtr, - Ordering, -}; - -use crate::arena::LocalArena; - -struct FNV1a { - state: u64, -} - -impl FNV1a { - const OFFSET_BASIS: u64 = 0xCBF29CE484222325; - const PRIME: u64 = 0x00000100000001B3; - - fn new() -> Self { - return Self { - state: Self::OFFSET_BASIS, - }; - } -} - -impl Hasher for FNV1a { - fn write(&mut self, bytes: &[u8]) { - for &b in bytes { - self.state ^= b as u64; - self.state = self.state.wrapping_mul(Self::PRIME); - } - } - - fn finish(&self) -> u64 { - return self.state; - } -} - -pub struct HTrieNode<K, V> -where - K: Copy + Eq + Hash, -{ - sub: [AtomicPtr<HTrieNode<K, V>>; 4], - key: K, - val: AtomicPtr<V>, -} - -impl<K, V> HTrieNode<K, V> -where - K: Copy + Eq + Hash, -{ - fn new(key: K, valptr: *mut V) -> Self { - return Self { - sub: [ - AtomicPtr::new(ptr::null_mut()), - AtomicPtr::new(ptr::null_mut()), - AtomicPtr::new(ptr::null_mut()), - AtomicPtr::new(ptr::null_mut()), - ], - key, - val: AtomicPtr::new(valptr), - }; - } -} - -#[derive(Debug)] -pub struct HTrie<K, V> -where - K: Copy + Eq + Hash, -{ - root: AtomicPtr<HTrieNode<K, V>>, -} - -impl<K, V> HTrie<K, V> -where - K: Copy + Eq + Hash, -{ - pub fn new() -> Self { - return Self { - root: AtomicPtr::new(ptr::null_mut()), - }; - } - - /// Lock-free insert into the hash-trie. - /// - /// Returns `None` if the key was newly inserted. - /// Returns `Some(val)` with the previous value if the key already - /// existed. - pub fn insert(&self, key: K, val: V, arena: &LocalArena) -> Option<V> { - let mut h = { - let mut h = FNV1a::new(); - key.hash(&mut h); - h.finish() - }; - - let mut m = &self.root; - let valptr = arena.alloc(val); - - loop { - let mut n = m.load(Ordering::Acquire); - - if n.is_null() { - let mark = arena.mark(); - let node = arena.alloc(HTrieNode::new(key, valptr)); - - match m.compare_exchange( - ptr::null_mut(), - node as *mut HTrieNode<K, V>, - Ordering::Release, - Ordering::Acquire, - ) { - Ok(_) => { - return None; - }, - Err(ptr) => { - arena.restore(mark); - n = ptr; - }, - } - } - - let n = unsafe { &*n }; - - if n.key == key { - let old_valptr = n.val.swap(valptr, Ordering::AcqRel); - - if old_valptr.is_null() { - return None; - } else { - let old_val = unsafe { ptr::read(old_valptr) }; - return Some(old_val); - } - } - - m = &n.sub[(h >> 62) as usize]; - h <<= 2; - } - } - - /// Check if the given key exists in the hash-trie. - pub fn contains(&self, key: K) -> bool { - let mut h = { - let mut h = FNV1a::new(); - key.hash(&mut h); - h.finish() - }; - - let mut m = &self.root; - - loop { - let n = m.load(Ordering::Acquire); - if n.is_null() { - return false; - } - let n = unsafe { &*n }; - if n.key == key { - return !n.val.load(Ordering::Acquire).is_null(); - } - m = &n.sub[(h >> 62) as usize]; - h <<= 2; - } - } -} - -#[cfg(test)] -mod tests { - use crate::arena::{ - GlobalArena, - LocalArena, - }; - use crate::hashtrie::HTrie; - - #[test] - fn test_htrie_insert() { - let ga = GlobalArena::new(128); - let la = LocalArena::new(&ga); - let ht = HTrie::new(); - - assert_eq!(ht.insert("foo", "bar", &la), None); - assert_eq!(ht.insert("hello", "sailor", &la), None); - assert_eq!(ht.insert("thomas", "voss", &la), None); - } - - #[test] - fn test_htrie_overwrite() { - let ga = GlobalArena::new(128); - let la = LocalArena::new(&ga); - let ht = HTrie::new(); - - ht.insert("foo", "bar", &la); - ht.insert("hello", "sailor", &la); - ht.insert("thomas", "voss", &la); - assert_eq!(ht.insert("foo", "bar-0", &la), Some("bar")); - assert_eq!(ht.insert("hello", "sailor-0", &la), Some("sailor")); - assert_eq!(ht.insert("thomas", "voss-0", &la), Some("voss")); - assert_eq!(ht.insert("foo", "bar-1", &la), Some("bar-0")); - assert_eq!(ht.insert("hello", "sailor-1", &la), Some("sailor-0")); - assert_eq!(ht.insert("thomas", "voss-1", &la), Some("voss-0")); - } - - #[test] - fn test_htrie_contains() { - let ga = GlobalArena::new(128); - let la = LocalArena::new(&ga); - let ht = HTrie::new(); - - assert!(!ht.contains("foo")); - assert!(!ht.contains("hello")); - assert!(!ht.contains("thomas")); - ht.insert("foo", "bar", &la); - ht.insert("hello", "sailor", &la); - ht.insert("thomas", "voss", &la); - assert!(ht.contains("foo")); - assert!(ht.contains("hello")); - assert!(ht.contains("thomas")); - } -} diff --git a/oryxc/src/main.rs b/oryxc/src/main.rs index a5cd0a8..8d38ab1 100644 --- a/oryxc/src/main.rs +++ b/oryxc/src/main.rs @@ -1,10 +1,7 @@ #![allow(unsafe_op_in_unsafe_fn)] -mod arena; mod compiler; -mod depmap; mod errors; -mod hashtrie; mod intern; mod lexer; mod parser; diff --git a/oryxc/src/parser.rs b/oryxc/src/parser.rs index 629b290..8c24df1 100644 --- a/oryxc/src/parser.rs +++ b/oryxc/src/parser.rs @@ -46,8 +46,10 @@ pub struct AstNode { #[derive(Debug)] pub struct Ast { - pub nodes: Soa<AstNode>, - pub extra: Vec<u32>, + pub nodes: Soa<AstNode>, + pub extra: Vec<u32>, + pub types: Box<[TypeId]>, + pub textra: boxcar::Vec<TypeId>, } struct Parser<'a> { @@ -917,8 +919,12 @@ pub fn parse(tokens: &Soa<Token>) -> Result<Ast, Vec<OryxError>> { tok: 0, sub: SubNodes(stmtsbeg as u32, nstmts as u32), }); + let nodecnt = p.ast.len(); return Ok(Ast { - nodes: p.ast, - extra: p.extra_data, + nodes: p.ast, + extra: p.extra_data, + types: vec![TypeId::INVALID; nodecnt].into_boxed_slice(), + /* TODO: Get the parser to try to compute the required capacity */ + textra: boxcar::vec![], }); } diff --git a/oryxc/src/prelude.rs b/oryxc/src/prelude.rs index 0d1fc15..5628c87 100644 --- a/oryxc/src/prelude.rs +++ b/oryxc/src/prelude.rs @@ -1,11 +1,10 @@ +use std::collections::HashMap; use std::fmt::{ self, Debug, Formatter, }; -use crate::hashtrie::HTrie; - macro_rules! mkidtype { ($name:ident) => { #[repr(transparent)] @@ -38,17 +37,33 @@ impl ScopeId { pub const GLOBAL: Self = Self(0); } +impl TypeId { + const MVMSK: u32 = 1 << 31; + + pub fn to_mvindex(&self) -> Option<usize> { + return if self.0 & Self::MVMSK != 0 { + Some((self.0 & !Self::MVMSK) as usize) + } else { + None + }; + } + + pub fn from_mvindex(i: usize) -> Self { + return Self(i as u32 & Self::MVMSK); + } +} + #[derive(Debug)] pub struct Scope { pub parent: ScopeId, - pub symtab: HTrie<SymbolId, Symbol>, + pub symtab: HashMap<SymbolId, Symbol>, } impl Scope { pub fn new(parent: ScopeId) -> Self { return Self { parent, - symtab: HTrie::new(), + symtab: HashMap::new(), }; } } @@ -77,10 +92,19 @@ pub enum SymbolType { } pub enum OryxType { - Integer { bits: usize, signed: bool }, Boolean, - Pointer { base: u32 }, - Function { args: Vec<u32>, rets: Vec<u32> }, + Function { + args: Box<[TypeId]>, + rets: Box<[TypeId]>, + }, + Integer { + bits: usize, + signed: bool, + }, + Pointer { + base: u32, + }, + Type(TypeId), } #[derive(Clone, Copy)] diff --git a/oryxc/src/unistr.rs b/oryxc/src/unistr.rs index 158fed1..f9ea3d0 100644 --- a/oryxc/src/unistr.rs +++ b/oryxc/src/unistr.rs @@ -45,10 +45,10 @@ impl PartialEq for UniStr<'_> { unicode_normalization::is_nfkd_quick(other.0.chars()) == IsNormalized::Yes, ) { - (true, true) => self.0 == other.0, - (true, false) => self.0.chars() == other.0.nfkd(), - (false, true) => self.0.nfkd() == other.0.chars(), - (false, false) => self.0.nfkd() == other.0.nfkd(), + (true, true) => self.0.eq(other.0), + (true, false) => self.0.chars().eq(other.0.nfkd()), + (false, true) => self.0.nfkd().eq(other.0.chars()), + (false, false) => self.0.nfkd().eq(other.0.nfkd()), }; } } |