Skip to content

Commit

Permalink
[frontend] grammar for datatypes
Browse files Browse the repository at this point in the history
Signed-off-by: anqurvanillapy <[email protected]>
  • Loading branch information
anqurvanillapy committed Aug 21, 2024
1 parent 9115242 commit de12cb9
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 41 deletions.
7 changes: 6 additions & 1 deletion reuse-frontend/src/concrete.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
use crate::name::Ident;
use crate::syntax::{Decl, Param, Syntax};
use crate::syntax::{Ctor, CtorParams, Decl, Param, Syntax};

#[allow(dead_code)]
pub type ParamExpr<'src> = Param<'src, Expr<'src>>;

#[allow(dead_code)]
pub type CtorExpr<'src> = Ctor<'src, Expr<'src>>;
#[allow(dead_code)]
pub type CtorParamsExpr<'src> = CtorParams<'src, Expr<'src>>;

#[allow(dead_code)]
pub struct File<'src> {
pub decls: Box<[Decl<'src, Expr<'src>>]>,
Expand Down
4 changes: 4 additions & 0 deletions reuse-frontend/src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ impl<'src> Ident<'src> {
pub fn new(id: ID, raw: &'src str) -> Self {
Self { id, raw }
}

pub fn unbound() -> Self {
Self { id: 0, raw: "_" }
}
}

impl<'src> Display for Ident<'src> {
Expand Down
149 changes: 119 additions & 30 deletions reuse-frontend/src/surface/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use chumsky::error::Rich;
use chumsky::extra::Err;
use chumsky::prelude::just;
use chumsky::text::ascii::keyword;
use chumsky::text::{ident, inline_whitespace, newline};
use chumsky::{IterParser, Parser};

use crate::concrete::{Expr, File, ParamExpr};
use crate::concrete::{CtorExpr, CtorParamsExpr, Expr, File, ParamExpr};
use crate::name::{IDs, Ident};
use crate::syntax::{Decl, Def, FnDef, Param};
use crate::syntax::{DataDef, Decl, Def, FnDef, Param};

#[cfg(test)]
mod tests;
Expand Down Expand Up @@ -43,35 +42,17 @@ impl Surface {
}

fn decl<'src>(&mut self) -> out!(Decl<'src, Expr<'src>>) {
self.fn_decl()
self.fn_decl().or(self.data_decl())
}

fn fn_decl<'src>(&mut self) -> out!(Decl<'src, Expr<'src>>) {
keyword("def")
just("def")
.padded()
.ignore_then(self.ident())
.padded()
.then(
self.ident()
.padded()
.map(|name| Param {
name,
typ: Box::new(Expr::Type),
})
.separated_by(just(','))
.at_least(1)
.collect::<Vec<_>>()
.delimited_by(just('['), just(']'))
.or_not(),
)
.then(self.typ_params().or_not())
.padded()
.then(
self.param()
.padded()
.separated_by(just(','))
.collect::<Vec<_>>()
.delimited_by(just('('), just(')')),
)
.then(self.val_params())
.padded()
.then(
just("->")
Expand All @@ -87,14 +68,89 @@ impl Surface {
.then_ignore(newline())
.map(|((((name, typ_params), val_params), ret), body)| Decl {
name,
typ_params: typ_params.unwrap_or_default().into_boxed_slice(),
val_params: val_params.into_boxed_slice(),
eff: Box::new(Expr::Pure), // TODO: parse effects
ret: ret.unwrap_or_else(|| Box::new(Expr::NoneType)),
def: Def::Fn(FnDef { body }),
def: Def::Fn(FnDef {
typ_params: typ_params.unwrap_or_default(),
val_params,
eff: Box::new(Expr::Pure), // TODO: parse effects
ret: ret.unwrap_or_else(|| Box::new(Expr::NoneType)),
body,
}),
})
}

fn data_decl<'src>(&mut self) -> out!(Decl<'src, Expr<'src>>) {
just("data")
.padded()
.ignore_then(self.ident())
.padded()
.then(self.typ_params().or_not())
.padded()
.then_ignore(just(':'))
.then_ignore(inline_whitespace())
.then_ignore(newline())
.then(self.ctors())
.map(|((name, typ_params), ctors)| Decl {
name,
def: Def::Data(DataDef {
typ_params: typ_params.unwrap_or_default(),
ctors,
}),
})
}

fn ctors<'src>(&mut self) -> out!(Box<[CtorExpr<'src>]>) {
self.ctor()
.padded_by(inline_whitespace())
.repeated()
.at_least(1)
.collect::<Vec<_>>()
.map(Vec::into_boxed_slice)
}

fn ctor<'src>(&mut self) -> out!(CtorExpr<'src>) {
self.ident()
.then_ignore(inline_whitespace())
.then(
self.ctor_unnamed_params()
.or(self.ctor_named_params())
.or_not()
.map(Option::unwrap_or_default),
)
.then_ignore(inline_whitespace())
.then_ignore(newline())
.map(|(name, params)| CtorExpr { name, params })
}

fn ctor_unnamed_params<'src>(&mut self) -> out!(CtorParamsExpr<'src>) {
just('(')
.ignore_then(
self.type_expr()
.padded()
.separated_by(just(','))
.allow_trailing()
.at_least(1)
.collect::<Vec<_>>()
.map(Vec::into_boxed_slice)
.map(CtorParamsExpr::Unnamed),
)
.then_ignore(just(')'))
}

fn ctor_named_params<'src>(&mut self) -> out!(CtorParamsExpr<'src>) {
just('(')
.ignore_then(
self.param()
.padded()
.separated_by(just(','))
.allow_trailing()
.at_least(1)
.collect::<Vec<_>>()
.map(Vec::into_boxed_slice)
.map(CtorParamsExpr::Named),
)
.then_ignore(just(')'))
}

fn expr<'src>(&mut self) -> out!(Box<Expr<'src>>) {
primitive!("None", None)
.or(primitive!("False", True))
Expand All @@ -118,6 +174,39 @@ impl Surface {
.map(|(name, typ)| Param { name, typ })
}

fn val_params<'src>(&mut self) -> out!(Box<[ParamExpr<'src>]>) {
just('(')
.ignore_then(
self.param()
.padded()
.separated_by(just(','))
.allow_trailing()
.collect::<Vec<_>>()
.map(Vec::into_boxed_slice)
.or_not()
.map(Option::unwrap_or_default),
)
.then_ignore(just(')'))
}

fn typ_params<'src>(&mut self) -> out!(Box<[ParamExpr<'src>]>) {
just('[')
.ignore_then(
self.ident()
.padded()
.map(|name| Param {
name,
typ: Box::new(Expr::Type),
})
.separated_by(just(','))
.allow_trailing()
.at_least(1)
.collect::<Vec<_>>()
.map(Vec::into_boxed_slice),
)
.then_ignore(just(']'))
}

fn ident<'src>(&mut self) -> out!(Ident<'src>) {
let id = self.ids.fresh();
ident().map(move |s| Ident::new(id, s))
Expand Down
7 changes: 6 additions & 1 deletion reuse-frontend/src/surface/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ fn it_parses_file() {
def f0 () -> None : None
def f1 () -> None : None
def f2 [T] (s: str) -> None :
def f2 [T, U,] (s: str) -> None :
None
data
Foo [T]:
A
B(str)
";
Surface::default()
Expand Down
32 changes: 23 additions & 9 deletions reuse-frontend/src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,45 @@ pub struct Param<'src, T: Syntax> {
#[allow(dead_code)]
pub struct Decl<'src, T: Syntax> {
pub name: Ident<'src>,
pub typ_params: Box<[Param<'src, T>]>,
pub val_params: Box<[Param<'src, T>]>,
pub eff: Box<T>,
pub ret: Box<T>,
pub def: Def<'src, T>,
}

#[allow(dead_code)]
pub enum Def<'src, T: Syntax> {
Fn(FnDef<T>),
Fn(FnDef<'src, T>),
Data(DataDef<'src, T>),
}

#[allow(dead_code)]
pub struct FnDef<T: Syntax> {
pub struct FnDef<'src, T: Syntax> {
pub typ_params: Box<[Param<'src, T>]>,
pub val_params: Box<[Param<'src, T>]>,
pub eff: Box<T>,
pub ret: Box<T>,
pub body: Box<T>,
}

#[allow(dead_code)]
pub struct DataDef<'src, T: Syntax> {
ctors: Box<[Ctor<'src, T>]>,
pub typ_params: Box<[Param<'src, T>]>,
pub ctors: Box<[Ctor<'src, T>]>,
}

#[allow(dead_code)]
pub struct Ctor<'src, T: Syntax> {
name: Ident<'src>,
val_params: Box<[Param<'src, T>]>,
pub name: Ident<'src>,
pub params: CtorParams<'src, T>,
}

#[allow(dead_code)]
pub enum CtorParams<'src, T: Syntax> {
None,
Unnamed(Box<[Box<T>]>),
Named(Box<[Param<'src, T>]>),
}

impl<'src, T: Syntax> Default for CtorParams<'src, T> {
fn default() -> Self {
Self::None
}
}

0 comments on commit de12cb9

Please sign in to comment.