use std::cell::UnsafeCell; use std::fmt::{ self, Debug, Formatter, }; use std::sync::Arc; use dashmap::DashMap; macro_rules! mkidtype { ($name:ident) => { #[repr(transparent)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct $name(pub u32); impl $name { #[allow(dead_code)] pub const INVALID: Self = Self(u32::MAX); } impl From for $name { fn from(n: usize) -> Self { return Self(n as u32); } } impl Into for $name { fn into(self) -> usize { return self.0 as usize; } } impl std::ops::Index<$name> for [T] { type Output = T; fn index(&self, index: $name) -> &Self::Output { return &self[index.0 as usize]; } } impl std::ops::IndexMut<$name> for [T] { fn index_mut(&mut self, index: $name) -> &mut Self::Output { return &mut self[index.0 as usize]; } } }; } pub(crate) use mkidtype; mkidtype!(FileId); mkidtype!(ScopeId); mkidtype!(SymbolId); mkidtype!(TypeId); /* Bypass Rust autism */ #[repr(transparent)] #[derive(Debug)] pub struct TypeCell(UnsafeCell); impl TypeCell { pub fn new(id: TypeId) -> Self { return Self(UnsafeCell::new(id)); } pub fn get(&self) -> TypeId { return unsafe { *self.0.get() }; } pub fn set(&self, id: TypeId) { return unsafe { *self.0.get() = id }; } } unsafe impl Sync for TypeCell {} impl ScopeId { pub const GLOBAL: Self = Self(0); } /// A fully-qualified symbol name #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct QualifiedId { pub file: FileId, pub scope: ScopeId, pub sym: SymbolId, } #[derive(Debug)] pub struct Scope { pub parent: ScopeId, pub symtab: DashMap, } impl Scope { pub fn new(parent: ScopeId) -> Self { return Self { parent, symtab: DashMap::new(), }; } } #[repr(u8)] #[derive(Debug, Default)] pub enum ResolutionState { #[default] Unresolved, Resolving, Resolved, Poisoned, } #[derive(Debug)] pub struct Symbol { pub state: ResolutionState, pub kind: SymbolType, pub vtype: TypeId, } impl Symbol { pub fn new(kind: SymbolType) -> Self { return Self { state: ResolutionState::Unresolved, kind, vtype: TypeId::INVALID, }; } } #[repr(u8)] #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum SymbolType { Constant, FuncParam, } #[derive(Clone, Eq, PartialEq, Hash)] pub enum OryxType { /* Untyped types – the types of constant literals */ UBoolean, UNumber, UString, Boolean, Function { args: Arc<[TypeId]>, rets: Arc<[TypeId]>, }, Integer { bits: usize, signed: bool, }, Pointer { base: TypeId, }, Type(TypeId), MultiValue(Arc<[TypeId]>), } #[derive(Clone, Copy)] pub struct SubNodes(pub u32, pub u32); impl Debug for SubNodes { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let __ = format_args!("_"); return f .debug_tuple("SubNodes") .field(if self.0 != u32::MAX { &self.0 } else { &__ }) .field(if self.1 != u32::MAX { &self.1 } else { &__ }) .finish(); } } impl Default for SubNodes { fn default() -> Self { return Self(u32::MAX, u32::MAX); } }