summaryrefslogtreecommitdiff
path: root/rust
diff options
context:
space:
mode:
authorArnaud Bailly <arnaud.bailly@iohk.io>2024-09-25 15:18:23 +0200
committerArnaud Bailly <arnaud.bailly@iohk.io>2024-09-25 15:18:23 +0200
commitccbec05210dfd810a950b483db0e0c60ce83859d (patch)
tree92b08f003f8caeb816e631305c6240b0360a6270 /rust
parentceca65688101cb3275debe1b8e34198245d18c2d (diff)
downloadlambda-nantes-ccbec05210dfd810a950b483db0e0c60ce83859d.tar.gz
Allow multiple variables in single lambda
Diffstat (limited to 'rust')
-rw-r--r--rust/src/parser.rs35
1 files changed, 33 insertions, 2 deletions
diff --git a/rust/src/parser.rs b/rust/src/parser.rs
index 23a512b..874b893 100644
--- a/rust/src/parser.rs
+++ b/rust/src/parser.rs
@@ -95,10 +95,30 @@ fn parse_abstraction(parser: &mut Parser) -> Result<Value, String> {
parser.backtrack();
e.to_string()
})?;
- let var = parse_variable(parser)?;
+ let vars = parse_variables(parser)?;
let body = parse_expression(parser)?;
parser.expect(Token::RParen)?;
- Ok(Value::Lam(var, Box::new(body)))
+ let result = vars
+ .iter()
+ .rev()
+ .fold(body, |acc, var| Value::Lam(var.clone(), Box::new(acc)));
+ Ok(result)
+}
+
+fn parse_variables(parser: &mut Parser) -> Result<Vec<String>, String> {
+ parse_variable(parser)
+ .map(|s| vec![s])
+ .or_else(|_| parse_variables_list(parser))
+}
+
+fn parse_variables_list(parser: &mut Parser) -> Result<Vec<String>, String> {
+ let mut vars = Vec::new();
+ parser.expect(Token::LParen)?;
+ while let Ok(var) = parse_variable(parser) {
+ vars.push(var);
+ }
+ parser.expect(Token::RParen)?;
+ Ok(vars)
}
fn parse_variable(parser: &mut Parser) -> Result<String, String> {
@@ -290,6 +310,17 @@ mod tests {
}
#[test]
+ fn desugar_abstraction_with_several_variables_into_nested_lambdas() {
+ assert_eq!(
+ vec![Lam(
+ "x".to_string(),
+ Box::new(Lam("y".to_string(), Box::new(Sym("y".to_string()))))
+ )],
+ parse("(lam (x y) y)")
+ );
+ }
+
+ #[test]
fn parse_definition() {
assert_eq!(
vec![Def("x".to_string(), Box::new(Num(12)))],