summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Brown <gmb60@cam.ac.uk>2021-04-26 11:14:21 +0100
committerGreg Brown <gmb60@cam.ac.uk>2021-04-30 14:45:12 +0100
commitef485d6f3e4df6e1a424ba3797388fa0bba6eb2e (patch)
tree33d6cd11b21791e5727f29a428051578d3ab17fc
parentbf46a471fb268f7c0798a179740b295f8aaa1a31 (diff)
Replace substitution with translation.
-rw-r--r--src/chomp/ast/error.rs64
-rw-r--r--src/chomp/ast/mod.rs36
-rw-r--r--src/chomp/ast/substitute.rs447
-rw-r--r--src/chomp/typed/infer.rs35
-rw-r--r--src/chomp/typed/mod.rs27
-rw-r--r--src/chomp/visit.rs35
-rw-r--r--src/nibble/convert.rs19
7 files changed, 310 insertions, 353 deletions
diff --git a/src/chomp/ast/error.rs b/src/chomp/ast/error.rs
index 9e4282b..9057ec3 100644
--- a/src/chomp/ast/error.rs
+++ b/src/chomp/ast/error.rs
@@ -1,68 +1,52 @@
+use super::{Expression, Lambda, NamedExpression};
+use proc_macro2::Span;
use std::{
error::Error,
fmt::{self, Display},
};
-use proc_macro2::Span;
-
-use crate::chomp::Name;
-
-use super::{Call, Parameter};
-
#[derive(Debug)]
-pub enum SubstituteError {
- FreeParameter {
- param: Parameter,
+pub enum TranslateError {
+ CallNotAFunction {
+ on: Expression,
span: Option<Span>,
- name: Option<Name>,
},
WrongArgCount {
- call: Call,
- expected: usize,
+ lambda: Lambda,
+ args: Vec<NamedExpression>,
span: Option<Span>,
},
}
-impl From<SubstituteError> for syn::Error {
- fn from(e: SubstituteError) -> Self {
+impl From<TranslateError> for syn::Error {
+ fn from(e: TranslateError) -> Self {
let msg = e.to_string();
let span = match e {
- SubstituteError::FreeParameter { span, .. }
- | SubstituteError::WrongArgCount { span, .. } => span,
+ TranslateError::CallNotAFunction { span, .. }
+ | TranslateError::WrongArgCount { span, .. } => span,
};
Self::new(span.unwrap_or_else(Span::call_site), msg)
}
}
-impl Display for SubstituteError {
+impl Display for TranslateError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- Self::FreeParameter { param, name, .. } => {
- if let Some(name) = name {
- write!(f, "unbound parameter: `{}`", name)
- } else {
- write!(f, "unbound parameter: '{}", param.index)
- }
- }
- Self::WrongArgCount { call, expected, .. } => {
- if call.args.len() == 1 {
- write!(
- f,
- "this function takes {} arguments but 1 was supplied",
- expected
- )
- } else {
- write!(
- f,
- "this function takes {} arguments but {} were supplied",
- expected,
- call.args.len()
- )
- }
+ Self::CallNotAFunction { .. } => {
+ write!(f, "call expected a function")
}
+ Self::WrongArgCount { lambda, args, .. } => match (lambda.args.len(), args.len()) {
+ (1, n) => write!(f, "this function takes 1 argument but {} were supplied", n),
+ (m, _) => write!(f, "this function takes {} arguments but 1 was supplied", m),
+ (m, n) => write!(
+ f,
+ "this function takes {} arguments but {} were supplied",
+ m, n
+ ),
+ },
}
}
}
-impl Error for SubstituteError {}
+impl Error for TranslateError {}
diff --git a/src/chomp/ast/mod.rs b/src/chomp/ast/mod.rs
index d833da4..232381a 100644
--- a/src/chomp/ast/mod.rs
+++ b/src/chomp/ast/mod.rs
@@ -116,16 +116,20 @@ impl Display for Call {
/// A function abstraction.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Lambda {
- pub first: Name,
- pub rest: Vec<Name>,
+ pub args: Vec<Name>,
pub inner: Box<NamedExpression>,
}
impl Display for Lambda {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "/{}", self.first)?;
- for name in self.rest {
- write!(f, ", {}", name)?;
+ write!(f, "/")?;
+ let mut iter = self.args.iter();
+ if let Some(arg) = iter.next() {
+ write!(f, "{}", arg)?;
+
+ for arg in iter {
+ write!(f, ", {}", arg)?;
+ }
}
write!(f, "/ {}", self.inner)
}
@@ -151,6 +155,16 @@ pub enum Expression {
Lambda(Lambda),
}
+impl Expression {
+ pub fn try_into_lambda(self) -> Result<Lambda, Self> {
+ if let Self::Lambda(l) = self {
+ Ok(l)
+ } else {
+ Err(self)
+ }
+ }
+}
+
impl Display for Expression {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
@@ -297,23 +311,15 @@ impl PartialEq for NamedExpression {
impl Eq for NamedExpression {}
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Let {
pub name: Name,
pub val: NamedExpression,
pub inner: Box<TopLevel>,
}
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub enum TopLevel {
Let(Let),
Goal(NamedExpression),
}
-
-impl PartialEq for Function {
- fn eq(&self, other: &Self) -> bool {
- self.name == other.name && self.params == other.params && self.expr == other.expr
- }
-}
-
-impl Eq for Function {}
diff --git a/src/chomp/ast/substitute.rs b/src/chomp/ast/substitute.rs
index 2008a15..80df588 100644
--- a/src/chomp/ast/substitute.rs
+++ b/src/chomp/ast/substitute.rs
@@ -1,21 +1,18 @@
-use proc_macro2::Span;
-
+use super::{
+ error::TranslateError, Alt, Call, Cat, Epsilon, Fix, Lambda, Literal, NamedExpression, Variable,
+};
use crate::chomp::{
visit::{Folder, Mapper, Visitable},
Name,
};
+use proc_macro2::Span;
-use super::{
- error::SubstituteError, Alt, Call, Cat, Epsilon, Fix, Function, Literal, NamedExpression,
- Parameter, Variable,
-};
-
-#[derive(Clone, Copy, Debug, Default)]
-pub struct DeepenVars {
+struct Deepen {
pub depth: usize,
+ pub by: usize,
}
-impl Mapper for DeepenVars {
+impl Mapper for Deepen {
type Out = ();
fn map_epsilon(
@@ -41,10 +38,8 @@ impl Mapper for DeepenVars {
cat: &mut Cat,
) -> Self::Out {
cat.first.map(self);
- cat.second.map(self);
-
- for (_, term) in &mut cat.rest {
- term.map(self);
+ for (_, other) in &mut cat.rest {
+ other.map(self);
}
}
@@ -55,10 +50,8 @@ impl Mapper for DeepenVars {
alt: &mut Alt,
) -> Self::Out {
alt.first.map(self);
- alt.second.map(self);
-
- for (_, term) in &mut alt.rest {
- term.map(self);
+ for (_, other) in &mut alt.rest {
+ other.map(self);
}
}
@@ -68,9 +61,7 @@ impl Mapper for DeepenVars {
_span: Option<Span>,
fix: &mut Fix,
) -> Self::Out {
- self.depth += 1;
fix.inner.map(self);
- self.depth -= 1;
}
fn map_variable(
@@ -80,194 +71,93 @@ impl Mapper for DeepenVars {
var: &mut Variable,
) -> Self::Out {
if var.index >= self.depth {
- var.index += 1;
+ var.index += self.by;
}
}
- fn map_parameter(
- &mut self,
- _name: &mut Option<Name>,
- _span: Option<Span>,
- _param: &mut Parameter,
- ) -> Self::Out {
- }
-
fn map_call(
&mut self,
_name: &mut Option<Name>,
_span: Option<Span>,
call: &mut Call,
) -> Self::Out {
+ call.on.map(self);
for arg in &mut call.args {
- arg.map(self)
+ arg.map(self);
}
}
-}
-
-#[derive(Clone, Copy, Debug, Default)]
-pub struct ShallowVars {
- pub depth: usize,
-}
-
-impl Mapper for ShallowVars {
- type Out = ();
-
- fn map_epsilon(
- &mut self,
- _name: &mut Option<Name>,
- _span: Option<Span>,
- _eps: &mut Epsilon,
- ) -> Self::Out {
- }
-
- fn map_literal(
- &mut self,
- _name: &mut Option<Name>,
- _span: Option<Span>,
- _lit: &mut Literal,
- ) -> Self::Out {
- }
- fn map_cat(
+ fn map_lambda(
&mut self,
_name: &mut Option<Name>,
_span: Option<Span>,
- cat: &mut Cat,
- ) -> Self::Out {
- cat.first.map(self);
- cat.second.map(self);
-
- for (_, term) in &mut cat.rest {
- term.map(self);
- }
- }
-
- fn map_alt(
- &mut self,
- _name: &mut Option<Name>,
- _span: Option<Span>,
- alt: &mut Alt,
- ) -> Self::Out {
- alt.first.map(self);
- alt.second.map(self);
-
- for (_, term) in &mut alt.rest {
- term.map(self);
- }
- }
-
- fn map_fix(
- &mut self,
- _name: &mut Option<Name>,
- _span: Option<Span>,
- fix: &mut Fix,
- ) -> Self::Out {
- self.depth += 1;
- fix.inner.map(self);
- self.depth -= 1;
- }
-
- fn map_variable(
- &mut self,
- _name: &mut Option<Name>,
- _span: Option<Span>,
- var: &mut Variable,
- ) -> Self::Out {
- if var.index >= self.depth {
- var.index -= 1;
- }
- }
-
- fn map_parameter(
- &mut self,
- _name: &mut Option<Name>,
- _span: Option<Span>,
- _param: &mut Parameter,
- ) -> Self::Out {
- }
-
- fn map_call(
- &mut self,
- _name: &mut Option<Name>,
- _span: Option<Span>,
- call: &mut Call,
+ lambda: &mut Lambda,
) -> Self::Out {
- for arg in &mut call.args {
- arg.map(self)
- }
+ self.depth += lambda.args.len();
+ lambda.inner.map(self);
+ self.depth -= lambda.args.len();
}
}
-#[derive(Clone, Debug)]
-pub struct SubstituteParams {
- pub params: Vec<NamedExpression>,
+pub struct Substitute {
+ pub index: usize,
+ pub expr: NamedExpression,
}
-impl Folder for SubstituteParams {
- type Out = Result<NamedExpression, SubstituteError>;
+impl Folder for Substitute {
+ type Out = NamedExpression;
fn fold_epsilon(&mut self, name: Option<Name>, span: Option<Span>, eps: Epsilon) -> Self::Out {
- Ok(NamedExpression {
+ NamedExpression {
name,
expr: eps.into(),
span,
- })
+ }
}
fn fold_literal(&mut self, name: Option<Name>, span: Option<Span>, lit: Literal) -> Self::Out {
- Ok(NamedExpression {
+ NamedExpression {
name,
expr: lit.into(),
span,
- })
+ }
}
fn fold_cat(&mut self, name: Option<Name>, span: Option<Span>, mut cat: Cat) -> Self::Out {
- cat.first = Box::new(cat.first.fold(self)?);
- cat.second = Box::new(cat.second.fold(self)?);
+ cat.first = Box::new(cat.first.fold(self));
cat.rest = cat
.rest
.into_iter()
- .map(|(p, term)| Ok((p, term.fold(self)?)))
- .collect::<Result<_, _>>()?;
- Ok(NamedExpression {
+ .map(|(span, e)| (span, e.fold(self)))
+ .collect();
+ NamedExpression {
name,
expr: cat.into(),
span,
- })
+ }
}
fn fold_alt(&mut self, name: Option<Name>, span: Option<Span>, mut alt: Alt) -> Self::Out {
- alt.first = Box::new(alt.first.fold(self)?);
- alt.second = Box::new(alt.second.fold(self)?);
+ alt.first = Box::new(alt.first.fold(self));
alt.rest = alt
.rest
.into_iter()
- .map(|(p, term)| Ok((p, term.fold(self)?)))
- .collect::<Result<_, _>>()?;
- Ok(NamedExpression {
+ .map(|(span, e)| (span, e.fold(self)))
+ .collect();
+ NamedExpression {
name,
expr: alt.into(),
span,
- })
+ }
}
fn fold_fix(&mut self, name: Option<Name>, span: Option<Span>, mut fix: Fix) -> Self::Out {
- for param in &mut self.params {
- param.map(&mut DeepenVars::default());
- }
-
- fix.inner = Box::new(fix.inner.fold(self)?);
-
- for param in &mut self.params {
- param.map(&mut ShallowVars::default());
- }
-
- Ok(NamedExpression {
+ fix.inner = Box::new(fix.inner.fold(self));
+ NamedExpression {
name,
expr: fix.into(),
span,
- })
+ }
}
fn fold_variable(
@@ -276,50 +166,69 @@ impl Folder for SubstituteParams {
span: Option<Span>,
var: Variable,
) -> Self::Out {
- Ok(NamedExpression {
+ if var.index == self.index {
+ self.expr.clone()
+ } else {
+ NamedExpression {
+ name,
+ expr: Variable {
+ index: if var.index > self.index {
+ var.index - 1
+ } else {
+ var.index
+ },
+ }
+ .into(),
+ span,
+ }
+ }
+ }
+
+ fn fold_call(&mut self, name: Option<Name>, span: Option<Span>, mut call: Call) -> Self::Out {
+ call.on = Box::new(call.on.fold(self));
+ call.args = call.args.into_iter().map(|e| e.fold(self)).collect();
+ NamedExpression {
name,
- expr: var.into(),
+ expr: call.into(),
span,
- })
+ }
}
- fn fold_parameter(
+ fn fold_lambda(
&mut self,
name: Option<Name>,
span: Option<Span>,
- param: Parameter,
+ mut lambda: Lambda,
) -> Self::Out {
- let mut expr = self
- .params
- .get(param.index)
- .cloned()
- .ok_or_else(|| SubstituteError::FreeParameter { param, span, name: name.clone() })?;
- expr.name = expr.name.or(name);
- expr.span = expr.span.or(span);
- Ok(expr)
- }
-
- fn fold_call(&mut self, name: Option<Name>, span: Option<Span>, mut call: Call) -> Self::Out {
- call.args = call
- .args
- .into_iter()
- .map(|arg| arg.fold(self))
- .collect::<Result<_, _>>()?;
- Ok(NamedExpression {
+ self.index += lambda.args.len();
+ lambda.inner = Box::new(lambda.inner.fold(self));
+ self.index -= lambda.args.len();
+ NamedExpression {
name,
- expr: call.into(),
+ expr: lambda.into(),
span,
- })
+ }
}
}
-#[derive(Clone, Debug)]
-pub struct InlineCalls {
- pub function: Function,
+pub struct Translate {
+ changed: bool,
}
-impl Folder for InlineCalls {
- type Out = Result<NamedExpression, SubstituteError>;
+impl Translate {
+ pub fn new() -> Self {
+ Self { changed: false }
+ }
+}
+
+impl Default for Translate {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl Folder for Translate {
+ type Out = Result<NamedExpression, TranslateError>;
fn fold_epsilon(&mut self, name: Option<Name>, span: Option<Span>, eps: Epsilon) -> Self::Out {
Ok(NamedExpression {
@@ -337,15 +246,7 @@ impl Folder for InlineCalls {
})
}
- fn fold_cat(&mut self, name: Option<Name>, span: Option<Span>, mut cat: Cat) -> Self::Out {
- cat.first = Box::new(cat.first.fold(self)?);
- cat.second = Box::new(cat.second.fold(self)?);
- cat.rest = cat
- .rest
- .into_iter()
- .map(|(punct, term)| Ok((punct, term.fold(self)?)))
- .collect::<Result<_, _>>()?;
-
+ fn fold_cat(&mut self, name: Option<Name>, span: Option<Span>, cat: Cat) -> Self::Out {
Ok(NamedExpression {
name,
expr: cat.into(),
@@ -353,15 +254,7 @@ impl Folder for InlineCalls {
})
}
- fn fold_alt(&mut self, name: Option<Name>, span: Option<Span>, mut alt: Alt) -> Self::Out {
- alt.first = Box::new(alt.first.fold(self)?);
- alt.second = Box::new(alt.second.fold(self)?);
- alt.rest = alt
- .rest
- .into_iter()
- .map(|(punct, term)| Ok((punct, term.fold(self)?)))
- .collect::<Result<_, _>>()?;
-
+ fn fold_alt(&mut self, name: Option<Name>, span: Option<Span>, alt: Alt) -> Self::Out {
Ok(NamedExpression {
name,
expr: alt.into(),
@@ -369,9 +262,7 @@ impl Folder for InlineCalls {
})
}
- fn fold_fix(&mut self, name: Option<Name>, span: Option<Span>, mut fix: Fix) -> Self::Out {
- fix.inner = Box::new(fix.inner.fold(self)?);
-
+ fn fold_fix(&mut self, name: Option<Name>, span: Option<Span>, fix: Fix) -> Self::Out {
Ok(NamedExpression {
name,
expr: fix.into(),
@@ -392,48 +283,130 @@ impl Folder for InlineCalls {
})
}
- fn fold_parameter(
- &mut self,
- name: Option<Name>,
- span: Option<Span>,
- param: Parameter,
- ) -> Self::Out {
+ fn fold_call(&mut self, name: Option<Name>, span: Option<Span>, call: Call) -> Self::Out {
+ let mut on = *call.on;
+ self.changed = true;
+ while self.changed {
+ self.changed = false;
+ on = on.fold(self)?;
+ }
+
+ let lambda = on
+ .expr
+ .try_into_lambda()
+ .map_err(|on| TranslateError::CallNotAFunction { on, span })?;
+
+ if lambda.args.len() != call.args.len() {
+ return Err(TranslateError::WrongArgCount {
+ lambda,
+ args: call.args,
+ span,
+ });
+ }
+
+ let mut out = *lambda.inner;
+
+ for ((i, mut arg), name) in call.args.into_iter().enumerate().zip(lambda.args).rev() {
+ arg.name = arg.name.or(Some(name));
+ arg.map(&mut Deepen { depth: 0, by: i });
+ out = out.fold(&mut Substitute {
+ index: 0,
+ expr: arg,
+ });
+ }
+
+ self.changed = true;
+ while self.changed {
+ self.changed = false;
+ out = out.fold(self)?;
+ }
+
+ self.changed = true;
+ out.name = name.or(out.name);
+ out.span = span.or(out.span);
+ Ok(out)
+ }
+
+ fn fold_lambda(&mut self, name: Option<Name>, span: Option<Span>, lambda: Lambda) -> Self::Out {
Ok(NamedExpression {
name,
- expr: param.into(),
+ expr: lambda.into(),
span,
})
}
+}
- fn fold_call(&mut self, name: Option<Name>, span: Option<Span>, mut call: Call) -> Self::Out {
- call.args = call
- .args
- .into_iter()
- .map(|arg| arg.fold(self))
- .collect::<Result<_, _>>()?;
-
- if call.name != self.function.name {
- Ok(NamedExpression {
- name,
- expr: call.into(),
- span,
- })
- } else if call.args.len() == self.function.params.len() {
- let mut expr = self
- .function
- .expr
- .clone()
- .fold(&mut SubstituteParams { params: call.args })?;
- expr.name = Some(name.or(expr.name).unwrap_or(call.name));
- expr.span = span.or(expr.span);
-
- Ok(expr)
- } else {
- Err(SubstituteError::WrongArgCount {
- call,
- expected: self.function.params.len(),
- span,
- })
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ /// Returns (/x/ x) 'index
+ fn make_expr(index: usize) -> NamedExpression {
+ let var = NamedExpression {
+ name: None,
+ expr: Variable { index: 0 }.into(),
+ span: None,
+ };
+
+ let lambda = NamedExpression {
+ name: None,
+ expr: Lambda {
+ args: vec!["x".to_owned().into()],
+ inner: Box::new(var),
+ }
+ .into(),
+ span: None,
+ };
+
+ let var = NamedExpression {
+ name: None,
+ expr: Variable { index }.into(),
+ span: None,
+ };
+
+ NamedExpression {
+ name: None,
+ expr: Call {
+ on: Box::new(lambda),
+ args: vec![var],
+ }
+ .into(),
+ span: None,
}
}
+
+ #[test]
+ fn deepen_lambda() {
+ let mut expr = make_expr(0);
+ expr.map(&mut Deepen { depth: 0, by: 1 });
+ assert_eq!(expr, make_expr(1))
+ }
+
+ #[test]
+ fn substitute_renames_bigger() {
+ let expr = make_expr(1);
+ let expr = expr.fold(&mut Substitute {
+ index: 0,
+ expr: NamedExpression {
+ name: None,
+ expr: Epsilon.into(),
+ span: None,
+ },
+ });
+ assert_eq!(expr, make_expr(0))
+ }
+
+ #[test]
+ fn translate_lambda() {
+ let expr = make_expr(1);
+ let expr = expr.fold(&mut Translate::new()).unwrap();
+ assert_eq!(
+ expr,
+ NamedExpression {
+ name: Some("x".to_owned().into()),
+ expr: Variable { index: 1 }.into(),
+ span: None
+ }
+ )
+ }
}
diff --git a/src/chomp/typed/infer.rs b/src/chomp/typed/infer.rs
index 44ea654..e2c2198 100644
--- a/src/chomp/typed/infer.rs
+++ b/src/chomp/typed/infer.rs
@@ -1,16 +1,8 @@
use proc_macro2::Span;
-use crate::chomp::{
- ast::{Alt, Call, Cat, Epsilon, Fix, Literal, Parameter, Variable},
- visit::{Folder, Visitable},
- Name,
-};
+use crate::chomp::{Name, ast::{Alt, Call, Cat, Epsilon, Fix, Lambda, Literal, NamedExpression, Variable, substitute::Translate}, visit::{Folder, Visitable}};
-use super::{
- context::Context,
- error::{TypeError, VariableError},
- Type, Typed, TypedExpression,
-};
+use super::{Type, Typed, TypedExpression, context::Context, error::{TypeError, VariableError}};
#[derive(Debug)]
pub struct TypeInfer<'a> {
@@ -38,13 +30,10 @@ impl Folder for TypeInfer<'_> {
fn fold_cat(&mut self, name: Option<Name>, span: Option<Span>, cat: Cat) -> Self::Out {
let first = cat.first.fold(self)?;
- let second = cat.second;
let rest = cat.rest;
- let punct = cat.punct;
self.context
.with_unguard(|context| -> Result<TypedExpression, TypeError> {
let mut infer = TypeInfer { context };
- let second = second.fold(&mut infer)?;
let rest = rest
.into_iter()
.map(|(punct, term)| -> Result<_, TypeError> {
@@ -52,7 +41,7 @@ impl Folder for TypeInfer<'_> {
})
.collect::<Result<Vec<_>, _>>()?;
Ok(TypedExpression {
- inner: super::Cat::new(first, punct, second, rest)?.into(),
+ inner: super::Cat::new(first, rest)?.into(),
name,
span,
})
@@ -61,15 +50,13 @@ impl Folder for TypeInfer<'_> {
fn fold_alt(&mut self, name: Option<Name>, span: Option<Span>, alt: Alt) -> Self::Out {
let first = alt.first.fold(self)?;
- let second = alt.second.fold(self)?;
let rest = alt
.rest
.into_iter()
.map(|(punct, term)| -> Result<_, TypeError> { Ok((punct, term.fold(self)?)) })
.collect::<Result<Vec<_>, _>>()?;
- let punct = alt.punct;
Ok(TypedExpression {
- inner: super::Alt::new(first, punct, second, rest)?.into(),
+ inner: super::Alt::new(first, rest)?.into(),
name,
span,
})
@@ -123,16 +110,18 @@ impl Folder for TypeInfer<'_> {
})
}
- fn fold_parameter(
+ fn fold_call(&mut self, name: Option<Name>, span: Option<Span>, call: Call) -> Self::Out {
+ let translated = NamedExpression { name, expr: call.into(), span}.fold(&mut Translate::new())?;
+ let inner = translated.fold(self)?;
+ todo!()
+ }
+
+ fn fold_lambda(
&mut self,
_name: Option<Name>,
_span: Option<Span>,
- _param: Parameter,
+ _lambda: Lambda,
) -> Self::Out {
unimplemented!()
}
-
- fn fold_call(&mut self, _name: Option<Name>, _span: Option<Span>, _call: Call) -> Self::Out {
- unimplemented!()
- }
}
diff --git a/src/chomp/typed/mod.rs b/src/chomp/typed/mod.rs
index 2a9e365..cddb05a 100644
--- a/src/chomp/typed/mod.rs
+++ b/src/chomp/typed/mod.rs
@@ -1,4 +1,4 @@
-use std::{hash, iter};
+use std::hash;
use proc_macro2::Span;
@@ -125,16 +125,16 @@ pub struct Cat {
impl Cat {
fn new<I: IntoIterator<Item = (Option<Span>, TypedExpression)>>(
first: TypedExpression,
- punct: Option<Span>,
- second: TypedExpression,
rest: I,
) -> Result<Self, CatError> {
if first.get_type().nullable() {
- return Err(CatError::FirstNullable { expr: first, punct });
+ return Err(CatError::FirstNullable {
+ expr: first,
+ punct: todo!(),
+ });
}
- iter::once((punct, second))
- .chain(rest)
+ rest.into_iter()
.try_fold(
(first.get_type().clone(), vec![first]),
|(ty, mut terms), (punct, right)| {
@@ -178,12 +178,9 @@ pub struct Alt {
impl Alt {
pub fn new<I: IntoIterator<Item = (Option<Span>, TypedExpression)>>(
first: TypedExpression,
- punct: Option<Span>,
- second: TypedExpression,
rest: I,
) -> Result<Self, AltError> {
- iter::once((punct, second))
- .chain(rest)
+ rest.into_iter()
.try_fold(
(first.get_type().clone(), vec![first]),
|(ty, mut terms), (punct, right)| {
@@ -248,6 +245,14 @@ impl Variable {
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+pub struct Call {
+ ty: Type,
+}
+
+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+pub struct Lambda {}
+
+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
enum RawTypedExpression {
Epsilon(Epsilon),
Literal(Literal),
@@ -255,6 +260,8 @@ enum RawTypedExpression {
Alt(Alt),
Fix(Fix),
Variable(Variable),
+ Call(Call),
+ Lambda(Lambda),
}
impl From<Epsilon> for RawTypedExpression {
diff --git a/src/chomp/visit.rs b/src/chomp/visit.rs
index bdef30e..7e716d3 100644
--- a/src/chomp/visit.rs
+++ b/src/chomp/visit.rs
@@ -1,9 +1,7 @@
use proc_macro2::Span;
use super::{
- ast::{
- Alt, Call, Cat, Epsilon, Expression, Fix, Literal, NamedExpression, Parameter, Variable,
- },
+ ast::{Alt, Call, Cat, Epsilon, Expression, Fix, Lambda, Literal, NamedExpression, Variable},
Name,
};
@@ -36,14 +34,14 @@ pub trait Visitor {
var: &Variable,
) -> Self::Out;
- fn visit_parameter(
+ fn visit_call(&mut self, name: Option<&Name>, span: Option<Span>, call: &Call) -> Self::Out;
+
+ fn visit_lambda(
&mut self,
name: Option<&Name>,
span: Option<Span>,
- param: &Parameter,
+ lambda: &Lambda,
) -> Self::Out;
-
- fn visit_call(&mut self, name: Option<&Name>, span: Option<Span>, call: &Call) -> Self::Out;
}
pub trait Mapper {
@@ -76,18 +74,18 @@ pub trait Mapper {
var: &mut Variable,
) -> Self::Out;
- fn map_parameter(
+ fn map_call(
&mut self,
name: &mut Option<Name>,
span: Option<Span>,
- param: &mut Parameter,
+ call: &mut Call,
) -> Self::Out;
- fn map_call(
+ fn map_lambda(
&mut self,
name: &mut Option<Name>,
span: Option<Span>,
- call: &mut Call,
+ lambda: &mut Lambda,
) -> Self::Out;
}
@@ -107,14 +105,9 @@ pub trait Folder {
fn fold_variable(&mut self, name: Option<Name>, span: Option<Span>, var: Variable)
-> Self::Out;
- fn fold_parameter(
- &mut self,
- name: Option<Name>,
- span: Option<Span>,
- param: Parameter,
- ) -> Self::Out;
-
fn fold_call(&mut self, name: Option<Name>, span: Option<Span>, call: Call) -> Self::Out;
+
+ fn fold_lambda(&mut self, name: Option<Name>, span: Option<Span>, lambda: Lambda) -> Self::Out;
}
pub trait Visitable {
@@ -134,8 +127,8 @@ impl Visitable for NamedExpression {
Expression::Alt(a) => visitor.visit_alt(self.name.as_ref(), self.span, a),
Expression::Fix(f) => visitor.visit_fix(self.name.as_ref(), self.span, f),
Expression::Variable(v) => visitor.visit_variable(self.name.as_ref(), self.span, v),
- Expression::Parameter(p) => visitor.visit_parameter(self.name.as_ref(), self.span, p),
Expression::Call(c) => visitor.visit_call(self.name.as_ref(), self.span, c),
+ Expression::Lambda(l) => visitor.visit_lambda(self.name.as_ref(), self.span, l),
}
}
@@ -147,8 +140,8 @@ impl Visitable for NamedExpression {
Expression::Alt(a) => mapper.map_alt(&mut self.name, self.span, a),
Expression::Fix(f) => mapper.map_fix(&mut self.name, self.span, f),
Expression::Variable(v) => mapper.map_variable(&mut self.name, self.span, v),
- Expression::Parameter(p) => mapper.map_parameter(&mut self.name, self.span, p),
Expression::Call(c) => mapper.map_call(&mut self.name, self.span, c),
+ Expression::Lambda(l) => mapper.map_lambda(&mut self.name, self.span, l),
}
}
@@ -160,8 +153,8 @@ impl Visitable for NamedExpression {
Expression::Alt(a) => folder.fold_alt(self.name, self.span, a),
Expression::Fix(f) => folder.fold_fix(self.name, self.span, f),
Expression::Variable(v) => folder.fold_variable(self.name, self.span, v),
- Expression::Parameter(p) => folder.fold_parameter(self.name, self.span, p),
Expression::Call(c) => folder.fold_call(self.name, self.span, c),
+ Expression::Lambda(l) => folder.fold_lambda(self.name, self.span, l),
}
}
}
diff --git a/src/nibble/convert.rs b/src/nibble/convert.rs
index 1e1ea08..e5e8c5d 100644
--- a/src/nibble/convert.rs
+++ b/src/nibble/convert.rs
@@ -39,7 +39,11 @@ impl Context {
res
}
- pub fn with_variables<I: IntoIterator<Item = Name>, F: FnOnce(&mut Self) -> R, R>(&mut self, names: I, f: F) -> R {
+ pub fn with_variables<I: IntoIterator<Item = Name>, F: FnOnce(&mut Self) -> R, R>(
+ &mut self,
+ names: I,
+ f: F,
+ ) -> R {
let len = self.bindings.len();
self.bindings.extend(names);
let res = f(self);
@@ -286,17 +290,18 @@ impl Convert for Alt {
impl Convert for Lambda {
fn convert(self, context: &mut Context) -> Result<NamedExpression, ConvertError> {
let span = self.span();
- let mut names = self.args.into_iter().map(Name::from);
+ let mut args: Vec<_> = self.args.into_iter().map(Name::from).collect();
let expr = self.expr;
- let inner = context.with_variables(names.clone(), |ctx| expr.convert(ctx))?;
- let first = names.next().unwrap();
- let rest = names.collect();
+ let inner = context.with_variables(args.clone(), |ctx| expr.convert(ctx))?;
Ok(NamedExpression {
name: None,
- expr: ast::Lambda { first, rest, inner: Box::new(inner)}.into(),
+ expr: ast::Lambda {
+ args,
+ inner: Box::new(inner),
+ }
+ .into(),
span,
})
-
}
}