Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use Idx<T> instead of macro in arena #266

Merged
merged 1 commit into from
Sep 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions crates/mun_codegen/src/ir/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ use crate::{
value::Global,
};
use hir::{
ArenaId, ArithOp, BinaryOp, Body, CmpOp, Expr, ExprId, HirDatabase, HirDisplay,
InferenceResult, Literal, LogicOp, Name, Ordering, Pat, PatId, Path, Resolution,
ResolveBitness, Resolver, Statement, TypeCtor, UnaryOp,
ArithOp, BinaryOp, Body, CmpOp, Expr, ExprId, HirDatabase, HirDisplay, InferenceResult,
Literal, LogicOp, Name, Ordering, Pat, PatId, Path, Resolution, ResolveBitness, Resolver,
Statement, TypeCtor, UnaryOp,
};
use inkwell::{
basic_block::BasicBlock,
Expand Down
18 changes: 8 additions & 10 deletions crates/mun_hir/src/adt.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::{fmt, sync::Arc};

use crate::type_ref::{TypeRefBuilder, TypeRefId, TypeRefMap, TypeRefSourceMap};
use crate::type_ref::{LocalTypeRefId, TypeRefBuilder, TypeRefMap, TypeRefSourceMap};
use crate::{
arena::{Arena, RawId},
arena::{Arena, Idx},
ids::{AstItemDef, StructId, TypeAliasId},
AsName, DefDatabase, Name,
};
Expand All @@ -25,14 +25,9 @@ pub use mun_syntax::ast::StructMemoryKind;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StructFieldData {
pub name: Name,
pub type_ref: TypeRefId,
pub type_ref: LocalTypeRefId,
}

/// An identifier for a struct's or tuple's field
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StructFieldId(RawId);
impl_arena_id!(StructFieldId);

/// A struct's fields' data (record, tuple, or unit struct)
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum StructKind {
Expand All @@ -51,10 +46,13 @@ impl fmt::Display for StructKind {
}
}

/// An identifier for a struct's or tuple's field
pub type LocalStructFieldId = Idx<StructFieldData>;

#[derive(Debug, PartialEq, Eq)]
pub struct StructData {
pub name: Name,
pub fields: Arena<StructFieldId, StructFieldData>,
pub fields: Arena<StructFieldData>,
pub kind: StructKind,
pub memory_kind: StructMemoryKind,
type_ref_map: TypeRefMap,
Expand Down Expand Up @@ -125,7 +123,7 @@ impl StructData {
#[derive(Debug, PartialEq, Eq)]
pub struct TypeAliasData {
pub name: Name,
pub type_ref_id: TypeRefId,
pub type_ref_id: LocalTypeRefId,
type_ref_map: TypeRefMap,
type_ref_source_map: TypeRefSourceMap,
}
Expand Down
107 changes: 69 additions & 38 deletions crates/mun_hir/src/arena.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter::FromIterator;
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
Expand Down Expand Up @@ -32,19 +33,65 @@ impl fmt::Display for RawId {
}
}

/// Enables storing in an `Arena`.
pub trait ArenaId {
fn from_raw(raw: RawId) -> Self;
fn into_raw(self) -> RawId;
pub struct Idx<T> {
raw: RawId,
_ty: PhantomData<fn() -> T>,
}

impl<T> Clone for Idx<T> {
fn clone(&self) -> Self {
*self
}
}

impl<T> Copy for Idx<T> {}

impl<T> PartialEq for Idx<T> {
fn eq(&self, other: &Self) -> bool {
self.raw == other.raw
}
}

impl<T> Eq for Idx<T> {}

impl<T> Hash for Idx<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.raw.hash(state)
}
}

impl<T> fmt::Debug for Idx<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut type_name = std::any::type_name::<T>();
if let Some(idx) = type_name.rfind(':') {
type_name = &type_name[idx + 1..]
}
write!(f, "Idx::<{}>({})", type_name, self.raw)
}
}

impl<T> Idx<T> {
pub fn from_raw(raw: RawId) -> Self {
Idx {
raw,
_ty: PhantomData,
}
}
pub fn into_raw(self) -> RawId {
self.raw
}
}

/// An `Arena<T>` holds a collection of `T`s but allocates persistent ID's that are used to refer
/// to an element in the arena. When adding an item to an `Arena` it returns an `Idx<T>` that is
/// only valid for the `Arena` that allocated the `Idx`. Its only possible to add items to an
/// `Arena`.
#[derive(Clone, PartialEq, Eq)]
pub struct Arena<ID: ArenaId, T> {
pub struct Arena<T> {
data: Vec<T>,
_ty: PhantomData<ID>,
}

impl<ID: ArenaId, T: fmt::Debug> fmt::Debug for Arena<ID, T> {
impl<T: fmt::Debug> fmt::Debug for Arena<T> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("Arena")
.field("len", &self.len())
Expand All @@ -53,7 +100,7 @@ impl<ID: ArenaId, T: fmt::Debug> fmt::Debug for Arena<ID, T> {
}
}

impl<ID: ArenaId, T> Arena<ID, T> {
impl<T> Arena<T> {
/// Returns the number of elements in the arena
pub fn len(&self) -> usize {
self.data.len()
Expand All @@ -65,67 +112,51 @@ impl<ID: ArenaId, T> Arena<ID, T> {
}

/// Stores `value` in the arena and returns the associated Id.
pub fn alloc(&mut self, value: T) -> ID {
pub fn alloc(&mut self, value: T) -> Idx<T> {
let id = RawId(self.data.len() as u32);
self.data.push(value);
ID::from_raw(id)
Idx::from_raw(id)
}

/// Iterate over the elements in the arena
pub fn iter(&self) -> impl Iterator<Item = (ID, &T)> {
pub fn iter(
&self,
) -> impl Iterator<Item = (Idx<T>, &T)> + ExactSizeIterator + DoubleEndedIterator {
self.data
.iter()
.enumerate()
.map(|(idx, value)| (ID::from_raw(RawId(idx as u32)), value))
.map(|(idx, value)| (Idx::from_raw(RawId(idx as u32)), value))
}
}

impl<ID: ArenaId, T> Default for Arena<ID, T> {
fn default() -> Arena<ID, T> {
Arena {
data: Vec::new(),
_ty: PhantomData,
}
impl<T> Default for Arena<T> {
fn default() -> Arena<T> {
Arena { data: Vec::new() }
}
}

impl<ID: ArenaId, T> Index<ID> for Arena<ID, T> {
impl<T> Index<Idx<T>> for Arena<T> {
type Output = T;
fn index(&self, idx: ID) -> &T {
fn index(&self, idx: Idx<T>) -> &T {
let idx = idx.into_raw().0 as usize;
&self.data[idx]
}
}

impl<ID: ArenaId, T> IndexMut<ID> for Arena<ID, T> {
fn index_mut(&mut self, idx: ID) -> &mut T {
impl<T> IndexMut<Idx<T>> for Arena<T> {
fn index_mut(&mut self, idx: Idx<T>) -> &mut T {
let idx = idx.into_raw().0 as usize;
&mut self.data[idx]
}
}

impl<ID: ArenaId, T> FromIterator<T> for Arena<ID, T> {
impl<T> FromIterator<T> for Arena<T> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = T>,
{
Arena {
data: Vec::from_iter(iter),
_ty: PhantomData,
}
}
}

/// Implements `ArenaId` for the specified type.
macro_rules! impl_arena_id {
($name:ident) => {
impl $crate::ArenaId for $name {
fn from_raw(raw: $crate::RawId) -> Self {
$name(raw)
}
fn into_raw(self) -> $crate::RawId {
self.0
}
}
};
}
59 changes: 27 additions & 32 deletions crates/mun_hir/src/arena/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use std::marker::PhantomData;

use super::ArenaId;
use super::Idx;

/// A map from arena IDs to some other type. Space requirement is O(highest ID).
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
Expand All @@ -11,67 +11,62 @@ pub struct ArenaMap<ID, T> {
_ty: PhantomData<ID>,
}

impl<ID: ArenaId, T> ArenaMap<ID, T> {
pub fn insert(&mut self, id: ID, t: T) {
let idx = to_idx(id);
if self.v.capacity() <= idx {
self.v.reserve(idx + 1 - self.v.capacity());
}
if self.v.len() <= idx {
while self.v.len() <= idx {
self.v.push(None);
}
}
impl<T, V> ArenaMap<Idx<T>, V> {
pub fn insert(&mut self, id: Idx<T>, t: V) {
let idx = Self::idx_to_raw(id);
self.v.resize_with((idx + 1).max(self.v.len()), || None);
self.v[idx] = Some(t);
}

pub fn get(&self, id: ID) -> Option<&T> {
self.v.get(to_idx(id)).and_then(|it| it.as_ref())
pub fn get(&self, id: Idx<T>) -> Option<&V> {
self.v.get(Self::idx_to_raw(id)).and_then(|it| it.as_ref())
}

pub fn get_mut(&mut self, id: ID) -> Option<&mut T> {
self.v.get_mut(to_idx(id)).and_then(|it| it.as_mut())
pub fn get_mut(&mut self, id: Idx<T>) -> Option<&mut V> {
self.v
.get_mut(Self::idx_to_raw(id))
.and_then(|it| it.as_mut())
}

pub fn values(&self) -> impl Iterator<Item = &T> {
pub fn values(&self) -> impl Iterator<Item = &V> {
self.v.iter().filter_map(|o| o.as_ref())
}

pub fn values_mut(&mut self) -> impl Iterator<Item = &mut T> {
pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
self.v.iter_mut().filter_map(|o| o.as_mut())
}

pub fn iter(&self) -> impl Iterator<Item = (ID, &T)> {
pub fn iter(&self) -> impl Iterator<Item = (Idx<T>, &V)> {
self.v
.iter()
.enumerate()
.filter_map(|(idx, o)| Some((from_idx(idx), o.as_ref()?)))
.filter_map(|(idx, o)| Some((Self::idx_from_raw(idx), o.as_ref()?)))
}

pub fn iter_mut(&mut self) -> impl Iterator<Item = (ID, &mut T)> {
pub fn iter_mut(&mut self) -> impl Iterator<Item = (Idx<T>, &mut V)> {
self.v
.iter_mut()
.enumerate()
.filter_map(|(idx, o)| Some((from_idx(idx), o.as_mut()?)))
.filter_map(|(idx, o)| Some((Self::idx_from_raw(idx), o.as_mut()?)))
}
}

fn to_idx<ID: ArenaId>(id: ID) -> usize {
u32::from(id.into_raw()) as usize
}
fn idx_to_raw(id: Idx<T>) -> usize {
u32::from(id.into_raw()) as usize
}

fn from_idx<ID: ArenaId>(idx: usize) -> ID {
ID::from_raw((idx as u32).into())
fn idx_from_raw(idx: usize) -> Idx<T> {
Idx::from_raw((idx as u32).into())
}
}

impl<ID: ArenaId, T> std::ops::Index<ID> for ArenaMap<ID, T> {
impl<T, V> std::ops::Index<Idx<V>> for ArenaMap<Idx<V>, T> {
type Output = T;
fn index(&self, id: ID) -> &T {
self.v[to_idx(id)].as_ref().unwrap()
fn index(&self, id: Idx<V>) -> &T {
self.v[Self::idx_to_raw(id)].as_ref().unwrap()
}
}

impl<ID, T> Default for ArenaMap<ID, T> {
impl<T, V> Default for ArenaMap<Idx<V>, T> {
fn default() -> Self {
ArenaMap {
v: Vec::new(),
Expand Down
Loading