summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--oryxc/src/arena.rs265
-rw-r--r--oryxc/src/compiler.rs176
-rw-r--r--oryxc/src/depmap.rs31
-rw-r--r--oryxc/src/hashtrie.rs219
-rw-r--r--oryxc/src/main.rs3
-rw-r--r--oryxc/src/parser.rs14
-rw-r--r--oryxc/src/prelude.rs38
-rw-r--r--oryxc/src/unistr.rs8
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()),
};
}
}