Skip to content

Commit

Permalink
Refactor to use custom arena with better types than id-arena
Browse files Browse the repository at this point in the history
  • Loading branch information
ThePuzzlemaker committed Feb 5, 2024
1 parent 891c3e6 commit 090e716
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 98 deletions.
14 changes: 0 additions & 14 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,7 @@ dependencies = [
"chumsky",
"clap",
"eyre",
"id-arena",
"im",
"index_vec",
"itertools",
"lasso",
"logos",
Expand Down Expand Up @@ -523,12 +521,6 @@ dependencies = [
"serde",
]

[[package]]
name = "id-arena"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"

[[package]]
name = "im"
version = "15.1.0"
Expand All @@ -549,12 +541,6 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"

[[package]]
name = "index_vec"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74086667896a940438f2118212f313abba4aff3831fef6f4b17d02add5c8bb60"

[[package]]
name = "indexmap"
version = "1.9.3"
Expand Down
2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ lasso = { version = "0.6.0", features = ["multi-threaded"] }
logos = "0.12.1"
itertools = "0.10.5"
chumsky = { git = "https://github.com/zesterer/chumsky.git", features = ["pratt", "label"] }
id-arena = "2.2.1"
index_vec = "0.1.3"
im = "15.1.0"
pretty = "0.12.3"

Expand Down
48 changes: 48 additions & 0 deletions src/arena.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use std::{marker::PhantomData, ops::Index};

#[derive(Debug)]
pub struct Arena<Id: IdLike, T> {
inner: Vec<T>,
_phantom: PhantomData<Id>,
}

impl<Id: IdLike, T> Arena<Id, T> {
pub fn new() -> Self {
Self {
inner: vec![],
_phantom: PhantomData,
}
}

pub fn len(&self) -> usize {
self.inner.len()
}

pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}

pub fn push(&mut self, x: T) -> Id {
self.inner.push(x);
Id::from_raw(self.inner.len() - 1)
}
}

impl<Id: IdLike, T> Default for Arena<Id, T> {
fn default() -> Self {
Self::new()
}
}

impl<Id: IdLike, T> Index<Id> for Arena<Id, T> {
type Output = T;

fn index(&self, index: Id) -> &Self::Output {
&self.inner[index.into_raw()]
}
}

pub trait IdLike {
fn from_raw(index: usize) -> Self;
fn into_raw(self) -> usize;
}
101 changes: 71 additions & 30 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,65 @@ use std::{
fmt::{self, Display},
};

use id_arena::{Arena, Id};

use crate::{
arena::{Arena, IdLike},
ctxt::GlobalCtxt,
parse::Span,
symbol::{Ident, Symbol},
};

pub const DUMMY_AST_ID: AstId = AstId { _raw: 0 };
pub const DUMMY_AST_ID: AstId = AstId(0);

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct AstId(u32);

impl AstId {
pub fn from_raw(id: u32) -> AstId {
AstId(id)
}

index_vec::define_index_type! {
pub struct AstId = u32;
pub fn into_raw(self) -> u32 {
self.0
}
}

DISABLE_MAX_INDEX_CHECK = cfg!(not(debug_assertions));
DEBUG_FORMAT = "AstId({})";
DISPLAY_FORMAT = "{}";
IMPL_RAW_CONVERSIONS = true;
impl Display for AstId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct Expr(usize);

impl IdLike for Expr {
fn from_raw(index: usize) -> Self {
Self(index)
}

fn into_raw(self) -> usize {
self.0
}
}

#[derive(Clone, Debug)]
pub struct Expr {
pub struct ExprData {
pub id: AstId,
pub kind: ExprKind,
pub span: Span,
}

impl Expr {
pub fn new(gcx: &GlobalCtxt, kind: ExprKind, span: Span) -> Id<Expr> {
pub fn new(gcx: &GlobalCtxt, kind: ExprKind, span: Span) -> Expr {
let id = gcx.arenas.ast.next_ast_id();
let expr = gcx
.arenas
.ast
.expr
.borrow_mut()
.alloc(Expr { id, kind, span });
.push(ExprData { id, kind, span });
gcx.arenas.ast.insert_node(id, Node::Expr(expr));
expr
}
Expand All @@ -47,38 +71,55 @@ impl Expr {
#[derive(Clone, Debug)]
pub enum ExprKind {
Let {
is_mut: bool,
varlist: im::Vector<(Ident, Option<Id<Ty>>, Id<Expr>)>,
in_block: im::Vector<Id<Expr>>,
varlist: im::Vector<(bool, Ident, Option<Ty>, Expr)>,
in_block: im::Vector<Expr>,
},
BinaryOp {
left: Id<Expr>,
left: Expr,
kind: BinOpKind,
right: Id<Expr>,
right: Expr,
},
UnaryMinus(Id<Expr>),
UnaryNot(Id<Expr>),
//Paren(Id<Expr>),
UnaryMinus(Expr),
UnaryNot(Expr),
Do {
exprs: im::Vector<Id<Expr>>,
exprs: im::Vector<Expr>,
},
Numeral(Numeral),
Ident(Ident),
Bool(bool),
Error,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct Ty(usize);

impl IdLike for Ty {
fn from_raw(index: usize) -> Self {
Self(index)
}

fn into_raw(self) -> usize {
self.0
}
}

#[derive(Clone, Debug)]
pub struct Ty {
pub struct TyData {
pub id: AstId,
pub kind: TyKind,
pub span: Span,
}

impl Ty {
pub fn new(gcx: &GlobalCtxt, kind: TyKind, span: Span) -> Id<Ty> {
pub fn new(gcx: &GlobalCtxt, kind: TyKind, span: Span) -> Ty {
let id = gcx.arenas.ast.next_ast_id();
let ty = gcx.arenas.ast.ty.borrow_mut().alloc(Ty { id, kind, span });
let ty = gcx
.arenas
.ast
.ty
.borrow_mut()
.push(TyData { id, kind, span });
gcx.arenas.ast.insert_node(id, Node::Ty(ty));
ty
}
Expand Down Expand Up @@ -125,8 +166,8 @@ pub struct Parentage {

#[derive(Debug)]
pub struct AstArenas {
pub expr: RefCell<Arena<Expr>>,
pub ty: RefCell<Arena<Ty>>,
pub expr: RefCell<Arena<Expr, ExprData>>,
pub ty: RefCell<Arena<Ty, TyData>>,
pub parentage: RefCell<Parentage>,
next_ast_id: Cell<u32>,
ast_id_to_node: RefCell<HashMap<AstId, Node>>,
Expand All @@ -139,11 +180,11 @@ impl AstArenas {
self.parentage.borrow_mut().map.clear();
}

pub fn expr(&self, id: Id<Expr>) -> Expr {
pub fn expr(&self, id: Expr) -> ExprData {
self.expr.borrow()[id].clone()
}

pub fn ty(&self, id: Id<Ty>) -> Ty {
pub fn ty(&self, id: Ty) -> TyData {
self.ty.borrow()[id].clone()
}

Expand Down Expand Up @@ -182,8 +223,8 @@ impl Default for AstArenas {

#[derive(Copy, Clone, Debug)]
pub enum Node {
Expr(Id<Expr>),
Ty(Id<Ty>),
Expr(Expr),
Ty(Ty),
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod arena;
pub mod ast;
pub mod ctxt;
pub mod diagnostic;
Expand Down
32 changes: 10 additions & 22 deletions src/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use chumsky::{
prelude::*,
util::MaybeRef,
};
use id_arena::Id;

use crate::{
ast::{self, BinOpKind, Expr, ExprKind, Numeral, Radix, Ty, TyKind},
Expand Down Expand Up @@ -57,7 +56,7 @@ fn maybe_nls<'src>() -> impl Parser<'src, CalInput<'src>, (), Extra<'src>> + Clo
just(Token::Nl).ignored().repeated()
}

fn numeral<'src>() -> impl Parser<'src, CalInput<'src>, Id<Expr>, Extra<'src>> + Clone + 'src {
fn numeral<'src>() -> impl Parser<'src, CalInput<'src>, Expr, Extra<'src>> + Clone + 'src {
any().try_map_with(|tok, extra| {
let span = extra.span();
if let Token::Numeral(num) = tok {
Expand All @@ -76,7 +75,7 @@ fn numeral<'src>() -> impl Parser<'src, CalInput<'src>, Id<Expr>, Extra<'src>> +
})
}

fn binop(lhs: Id<Expr>, op: Token, rhs: Id<Expr>, span: Span, gcx: &GlobalCtxt) -> Id<Expr> {
fn binop(lhs: Expr, op: Token, rhs: Expr, span: Span, gcx: &GlobalCtxt) -> Expr {
Expr::new(
gcx,
ExprKind::BinaryOp {
Expand Down Expand Up @@ -111,7 +110,7 @@ fn binop(lhs: Id<Expr>, op: Token, rhs: Id<Expr>, span: Span, gcx: &GlobalCtxt)

// TODO: check for where recovery should be done

pub fn ty<'src>() -> impl Parser<'src, CalInput<'src>, Id<Ty>, Extra<'src>> + Clone + 'src {
pub fn ty<'src>() -> impl Parser<'src, CalInput<'src>, Ty, Extra<'src>> + Clone + 'src {
select! {
Token::IdentLike(IdentLike::Primitive(Primitive::Uint)) => TyKind::Primitive(ast::Primitive::Uint),
Token::IdentLike(IdentLike::Primitive(Primitive::Bool)) => TyKind::Primitive(ast::Primitive::Bool),
Expand All @@ -121,7 +120,7 @@ pub fn ty<'src>() -> impl Parser<'src, CalInput<'src>, Id<Ty>, Extra<'src>> + Cl
})
}

pub fn expr<'src>() -> impl Parser<'src, CalInput<'src>, Id<Expr>, Extra<'src>> + Clone + 'src {
pub fn expr<'src>() -> impl Parser<'src, CalInput<'src>, Expr, Extra<'src>> + Clone + 'src {
let expr = recursive(|expr| {
let exprs_block = expr
.clone()
Expand All @@ -130,7 +129,7 @@ pub fn expr<'src>() -> impl Parser<'src, CalInput<'src>, Id<Expr>, Extra<'src>>
just(Token::Nl).repeated().at_least(1).ignored(),
)))
.allow_trailing()
.collect::<Vec<Id<Expr>>>()
.collect::<Vec<Expr>>()
.map(im::Vector::from);

let primary = choice((
Expand Down Expand Up @@ -275,11 +274,8 @@ pub fn expr<'src>() -> impl Parser<'src, CalInput<'src>, Id<Expr>, Extra<'src>>
just(keyword(Keyword::Mut))
.then_ignore(maybe_nls())
.or_not()
.map(|x| x.is_some()),
)
.then(
ident()
.or(under_ident())
.map(|x| x.is_some())
.then(ident().or(under_ident()))
.then_ignore(maybe_nls())
.then(
just(Token::Colon)
Expand All @@ -293,7 +289,7 @@ pub fn expr<'src>() -> impl Parser<'src, CalInput<'src>, Id<Expr>, Extra<'src>>
// TODO: should this be `pratt`?
.then(expr)
.then_ignore(maybe_nls())
.map(|((ident, ty), expr)| (ident, ty, expr))
.map(|(((is_mut, ident), ty), expr)| (is_mut, ident, ty, expr))
.separated_by(just(Token::Comma).then_ignore(maybe_nls()))
.at_least(1)
.allow_trailing()
Expand All @@ -305,17 +301,9 @@ pub fn expr<'src>() -> impl Parser<'src, CalInput<'src>, Id<Expr>, Extra<'src>>
.then_ignore(maybe_nls())
.then(exprs_block)
.then_ignore(just(keyword(Keyword::End)))
.map_with(|((is_mut, varlist), in_block), extra| {
.map_with(|(varlist, in_block), extra| {
let span = extra.span();
Expr::new(
extra.state(),
ExprKind::Let {
is_mut,
varlist,
in_block,
},
span,
)
Expr::new(extra.state(), ExprKind::Let { varlist, in_block }, span)
})
.or(pratt);

Expand Down
Loading

0 comments on commit 090e716

Please sign in to comment.