Files @ 85419b0950c7
Branch filter:

Location: CSY/reowolf/src/protocol/arena.rs

85419b0950c7 2.2 KiB application/rls-services+xml Show Annotation Show as Raw Download as Raw
MH
Rewrote typing to use indices.

Currently it is slower than before, because we do a HashMap lookup
followed up by actually using the index. But it serves as the basis
for a faster type inferencer.

The main goal, however, is to fix the manner in which polymorph
types are determined. The typing queue of functions still needs to
correctly write this data to the type table.
use crate::common::*;
use core::hash::Hash;
use core::marker::PhantomData;

pub struct Id<T> {
    // Not actually a signed index into the heap. But the index is set to -1 if
    // we don't know an ID yet. This is checked during debug mode.
    pub(crate) index: i32,
    _phantom: PhantomData<T>,
}

impl<T> Id<T> {
    pub(crate) fn new_invalid() -> Self     { Self{ index: -1, _phantom: Default::default() } }
    pub(crate) fn new(index: i32) -> Self   { Self{ index, _phantom: Default::default() } }
    pub(crate) fn is_invalid(&self) -> bool { self.index < 0 }
}

#[derive(Debug)]
pub(crate) struct Arena<T> {
    store: Vec<T>,
}
//////////////////////////////////

impl<T> Debug for Id<T> {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        f.debug_struct("Id").field("index", &self.index).finish()
    }
}
impl<T> Clone for Id<T> {
    fn clone(&self) -> Self {
        *self
    }
}
impl<T> Copy for Id<T> {}
impl<T> PartialEq for Id<T> {
    fn eq(&self, other: &Self) -> bool {
        self.index.eq(&other.index)
    }
}
impl<T> Eq for Id<T> {}
impl<T> Hash for Id<T> {
    fn hash<H: std::hash::Hasher>(&self, h: &mut H) {
        self.index.hash(h);
    }
}

impl<T> Arena<T> {
    pub fn new() -> Self {
        Self { store: vec![] }
    }

    pub fn alloc_with_id(&mut self, f: impl FnOnce(Id<T>) -> T) -> Id<T> {
        // Lets keep this a runtime assert.
        assert!(self.store.len() < i32::max_value() as usize, "Arena out of capacity");
        let id = Id::new(self.store.len() as i32);
        self.store.push(f(id));
        id
    }

    pub fn iter(&self) -> impl Iterator<Item = &T> {
        self.store.iter()
    }

    pub fn len(&self) -> usize {
        self.store.len()
    }
}
impl<T> core::ops::Index<Id<T>> for Arena<T> {
    type Output = T;
    fn index(&self, id: Id<T>) -> &Self::Output {
        debug_assert!(!id.is_invalid(), "attempted to index into Arena with an invalid id (index < 0)");
        self.store.index(id.index as usize)
    }
}
impl<T> core::ops::IndexMut<Id<T>> for Arena<T> {
    fn index_mut(&mut self, id: Id<T>) -> &mut Self::Output {
        debug_assert!(!id.is_invalid(), "attempted to index_mut into Arena with an invalid id (index < 0)");
        self.store.index_mut(id.index as usize)
    }
}