diff options
author | Greg Brown <gmb60@cam.ac.uk> | 2021-04-26 11:14:21 +0100 |
---|---|---|
committer | Greg Brown <gmb60@cam.ac.uk> | 2021-04-30 14:45:12 +0100 |
commit | ef485d6f3e4df6e1a424ba3797388fa0bba6eb2e (patch) | |
tree | 33d6cd11b21791e5727f29a428051578d3ab17fc | |
parent | bf46a471fb268f7c0798a179740b295f8aaa1a31 (diff) |
Replace substitution with translation.
-rw-r--r-- | src/chomp/ast/error.rs | 64 | ||||
-rw-r--r-- | src/chomp/ast/mod.rs | 36 | ||||
-rw-r--r-- | src/chomp/ast/substitute.rs | 447 | ||||
-rw-r--r-- | src/chomp/typed/infer.rs | 35 | ||||
-rw-r--r-- | src/chomp/typed/mod.rs | 27 | ||||
-rw-r--r-- | src/chomp/visit.rs | 35 | ||||
-rw-r--r-- | src/nibble/convert.rs | 19 |
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, }) - } } |