Skip to content

Commit

Permalink
feat: Add AstClone to clone arena allocated ASTs
Browse files Browse the repository at this point in the history
  • Loading branch information
Marwes committed Apr 13, 2020
1 parent 732f09f commit 3ee7bd2
Show file tree
Hide file tree
Showing 17 changed files with 470 additions and 59 deletions.
21 changes: 5 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ either = "1"
vec_map = "0.8"
typed-arena = "1"

gluon_codegen = "0.13.1" # GLUON
gluon_codegen = { version = "0.13.1", path = "../codegen" } # GLUON

serde = { version = "1.0.0", features = ["rc"], optional = true }
serde_state = { version = "0.4.0", features = ["rc"], optional = true }
Expand All @@ -47,7 +47,6 @@ compiletest_rs = { version = "0.3.23", optional = true }
env_logger = "0.7"
pretty_assertions = "0.6"


[features]
serialization = ["serde", "serde_state", "serde_derive", "serde_derive_state"]
nightly = ["compiletest_rs"]
152 changes: 136 additions & 16 deletions base/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use std::{

use {either::Either, itertools::Itertools, ordered_float::NotNan};

use gluon_codegen::AstClone;

#[cfg(feature = "serde")]
use crate::{
serde::de::DeserializeState,
Expand Down Expand Up @@ -74,13 +76,13 @@ impl<'a, T: ?Sized + IdentEnv> IdentEnv for &'a mut T {
}
}

#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, AstClone)]
pub struct InnerAstType<'ast, Id> {
metadata: Option<Metadata>,
typ: Spanned<Type<Id, AstType<'ast, Id>>, BytePos>,
}

#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, AstClone)]
pub struct AstType<'ast, Id> {
_typ: &'ast mut InnerAstType<'ast, Id>,
}
Expand Down Expand Up @@ -261,7 +263,7 @@ pub enum Literal {
/// Pattern which contains a location
pub type SpannedPattern<'ast, Id> = Spanned<Pattern<'ast, Id>, BytePos>;

#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, AstClone)]
pub enum PatternField<'ast, Id> {
Type {
name: Spanned<Id, BytePos>,
Expand All @@ -280,7 +282,7 @@ impl<Id> PatternField<'_, Id> {
}
}

#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, AstClone)]
pub enum Pattern<'ast, Id> {
/// An as-pattern, eg. `option @ { monoid, functor }`
As(Spanned<Id, BytePos>, &'ast mut SpannedPattern<'ast, Id>),
Expand Down Expand Up @@ -362,19 +364,19 @@ impl<Id> Default for Pattern<'_, Id> {
}
}

#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, AstClone)]
pub struct Alternative<'ast, Id> {
pub pattern: SpannedPattern<'ast, Id>,
pub expr: SpannedExpr<'ast, Id>,
}

#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, AstClone)]
pub struct Array<'ast, Id> {
pub typ: ArcType<Id>,
pub exprs: &'ast mut [SpannedExpr<'ast, Id>],
}

#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, AstClone)]
pub struct Lambda<'ast, Id> {
pub id: TypedIdent<Id>,
pub args: &'ast mut [Argument<SpannedIdent<Id>>],
Expand All @@ -389,14 +391,14 @@ pub type SpannedAlias<'ast, Id> = Spanned<AliasData<Id, AstType<'ast, Id>>, Byte

pub type SpannedAstType<'ast, Id> = Spanned<Type<Id, AstType<'ast, Id>>, BytePos>;

#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, AstClone)]
pub struct ExprField<Id, E> {
pub metadata: Metadata,
pub name: Spanned<Id, BytePos>,
pub value: Option<E>,
}

#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, AstClone)]
pub struct Do<'ast, Id> {
pub id: Option<SpannedPattern<'ast, Id>>,
pub bound: &'ast mut SpannedExpr<'ast, Id>,
Expand All @@ -405,7 +407,7 @@ pub struct Do<'ast, Id> {
}

/// The representation of gluon's expression syntax
#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, AstClone)]
pub enum Expr<'ast, Id> {
/// Identifiers
Ident(TypedIdent<Id>),
Expand Down Expand Up @@ -586,7 +588,7 @@ impl<'ast, Id> Expr<'ast, Id> {
}
}

#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, AstClone)]
pub struct TypeBinding<'ast, Id> {
pub metadata: Metadata,
pub name: Spanned<Id, BytePos>,
Expand All @@ -600,11 +602,11 @@ impl<Id> TypeBinding<'_, Id> {
}
}

#[derive(Clone, Default, Eq, PartialEq, Debug, Hash)]
#[derive(Clone, Default, Eq, PartialEq, Debug, Hash, AstClone)]
#[cfg_attr(feature = "serde_derive", derive(Deserialize, Serialize))]
pub struct Argument<Id> {
pub struct Argument<N> {
pub arg_type: ArgType,
pub name: Id,
pub name: N,
}

impl<Id> Argument<Id> {
Expand All @@ -623,7 +625,7 @@ impl<Id> Argument<Id> {
}
}

#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, AstClone)]
pub enum ValueBindings<'ast, Id> {
Plain(&'ast mut ValueBinding<'ast, Id>),
Recursive(&'ast mut [ValueBinding<'ast, Id>]),
Expand Down Expand Up @@ -675,7 +677,7 @@ impl<'a, 'ast, Id> IntoIterator for &'a mut ValueBindings<'ast, Id> {
}
}

#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, AstClone)]
pub struct ValueBinding<'ast, Id> {
pub metadata: Metadata,
pub name: SpannedPattern<'ast, Id>,
Expand Down Expand Up @@ -1468,3 +1470,121 @@ macro_rules! mk_ast_arena {
}
};
}

pub trait AstClone<'ast, Id> {
fn ast_clone(&self, arena: ArenaRef<'_, 'ast, Id>) -> Self;
}

impl<'ast, Id, T> AstClone<'ast, Id> for Option<T>
where
T: AstClone<'ast, Id>,
{
fn ast_clone(&self, arena: ArenaRef<'_, 'ast, Id>) -> Self {
self.as_ref().map(|x| x.ast_clone(arena))
}
}

impl<'ast, Id, T> AstClone<'ast, Id> for PhantomData<T> {
fn ast_clone(&self, _arena: ArenaRef<'_, 'ast, Id>) -> Self {
PhantomData
}
}

impl<'ast, Id, T> AstClone<'ast, Id> for Arc<[crate::types::AliasData<Id, T>]>
where
Id: Clone + AstClone<'ast, Id>,
T: AstClone<'ast, Id>,
{
fn ast_clone(&self, arena: ArenaRef<'_, 'ast, Id>) -> Self {
Arc::from(self.iter().map(|e| e.ast_clone(arena)).collect::<Vec<_>>())
}
}

impl<'ast, Id, T> AstClone<'ast, Id> for Vec<T>
where
T: Clone,
{
fn ast_clone(&self, _arena: ArenaRef<'_, 'ast, Id>) -> Self {
self.clone()
}
}

impl<'ast, Id, T> AstClone<'ast, Id> for crate::types::AppVec<T>
where
T: Clone,
{
fn ast_clone(&self, _arena: ArenaRef<'_, 'ast, Id>) -> Self {
self.clone()
}
}

impl<'ast, Id, T, P> AstClone<'ast, Id> for Spanned<T, P>
where
T: AstClone<'ast, Id>,
P: Clone,
{
fn ast_clone(&self, arena: ArenaRef<'_, 'ast, Id>) -> Self {
pos::spanned(self.span.clone(), self.value.ast_clone(arena))
}
}

impl<'ast, Id, T> AstClone<'ast, Id> for TypedIdent<Id, T>
where
Id: Clone,
T: AstClone<'ast, Id>,
{
fn ast_clone(&self, arena: ArenaRef<'_, 'ast, Id>) -> Self {
TypedIdent {
name: self.name.clone(),
typ: self.typ.ast_clone(arena),
}
}
}

impl<'ast, Id, T> AstClone<'ast, Id> for &'ast mut [T]
where
T: AstClone<'ast, Id> + AstAlloc<'ast, Id>,
{
fn ast_clone(&self, arena: ArenaRef<'_, 'ast, Id>) -> Self {
let elems: Vec<_> = self.iter().map(|e| e.ast_clone(arena)).collect();
arena.alloc_extend(elems)
}
}

impl<'ast, Id, T> AstClone<'ast, Id> for &'ast mut T
where
T: AstClone<'ast, Id> + AstAlloc<'ast, Id>,
{
fn ast_clone(&self, arena: ArenaRef<'_, 'ast, Id>) -> Self {
arena.alloc((**self).ast_clone(arena))
}
}

macro_rules! impl_ast_clone {
($($ty: ty $(where [$($where_: tt)*])? ,)*) => {
$(
impl<'ast, Id> AstClone<'ast, Id> for $ty
$( where $($where_)* )?
{
fn ast_clone(&self, _arena: ArenaRef<'_, 'ast, Id>) -> Self {
self.clone()
}
}
)*
};
}

impl_ast_clone! {
ArcType<Id>,
Literal,
Metadata,
crate::types::TypeVariable,
ArcKind,
crate::types::ArgType,
crate::types::BuiltinType,
usize,
u32,
bool,
BytePos,
Symbol,
}
5 changes: 1 addition & 4 deletions base/src/pos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,7 @@ where
Span::new(start, end)
}

pub fn spanned<T, Pos>(span: Span<Pos>, value: T) -> Spanned<T, Pos>
where
Pos: Ord,
{
pub fn spanned<T, Pos>(span: Span<Pos>, value: T) -> Spanned<T, Pos> {
Spanned { span, value }
}

Expand Down
Loading

0 comments on commit 3ee7bd2

Please sign in to comment.