diff options
author | Greg Brown <gmb60@cam.ac.uk> | 2021-01-08 18:00:11 +0000 |
---|---|---|
committer | Greg Brown <gmb60@cam.ac.uk> | 2021-01-08 18:00:11 +0000 |
commit | e1452227b8bd9ad3805480f8a5a66a75fb8370dd (patch) | |
tree | b02c9dfdc157d753e3f1c8a09bbd2ffb0bbfcc36 /src/chomp/check/substitute.rs | |
parent | fe2eac31d9dbec772796c3ea75be32e9cd01b810 (diff) |
Do more restructuring.
Diffstat (limited to 'src/chomp/check/substitute.rs')
-rw-r--r-- | src/chomp/check/substitute.rs | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/chomp/check/substitute.rs b/src/chomp/check/substitute.rs new file mode 100644 index 0000000..32595b1 --- /dev/null +++ b/src/chomp/check/substitute.rs @@ -0,0 +1,77 @@ +use super::{ + super::{ + ast::{Alt, Call, Cat, Epsilon, Expression, Fix, Literal, Parameter, Variable}, + error::SubstituteError, + visit::{Folder, Visitable}, + }, + DeepenVars, ShallowVars, +}; + +#[derive(Clone, Debug)] +pub struct SubstituteParams { + params: Vec<Expression>, +} + +impl SubstituteParams { + pub fn new(params: Vec<Expression>) -> Self { + Self { params } + } +} + +impl Folder for SubstituteParams { + type Out = Result<Expression, SubstituteError>; + + fn fold_epsilon(&mut self, eps: Epsilon) -> Self::Out { + Ok(eps.into()) + } + + fn fold_literal(&mut self, lit: Literal) -> Self::Out { + Ok(lit.into()) + } + + fn fold_cat(&mut self, mut cat: Cat) -> Self::Out { + cat.fst = Box::new(cat.fst.fold(self)?); + cat.snd = Box::new(cat.snd.fold(self)?); + Ok(cat.into()) + } + + fn fold_alt(&mut self, mut alt: Alt) -> Self::Out { + alt.left = Box::new(alt.left.fold(self)?); + alt.right = Box::new(alt.right.fold(self)?); + Ok(alt.into()) + } + + fn fold_fix(&mut self, 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(fix.into()) + } + + fn fold_variable(&mut self, var: Variable) -> Self::Out { + Ok(Expression::Variable(var)) + } + + fn fold_call(&mut self, mut call: Call) -> Self::Out { + call.args = call + .args + .into_iter() + .map(|arg| arg.fold(self)) + .collect::<Result<_, _>>()?; + Ok(call.into()) + } + + fn fold_parameter(&mut self, param: Parameter) -> Self::Out { + self.params + .get(param.index()) + .cloned() + .ok_or(SubstituteError::FreeParameter(param)) + } +} |