diff --git a/CHANGELOG.md b/CHANGELOG.md index 68349493..edce6c01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project does not currently adhere to a particular versioning scheme. - Add `IO/sleep` builtin function to sleep for a given amount of seconds as a float. ([#581][gh-581]) - Add primitive file IO functions `IO/FS/{read, write, seek, open, close}`. ([#573][gh-573]) - Add encoding/decoding builtin functions `Bytes/{decode_utf8, decode_ascii} String/{encode_ascii, decode_ascii} Utf8/{decode_character, REPLACEMENT_CHARACTER}`. ([#580][gh-580]) +- Add `elif` chains to functional syntax. ([#596][gh-596]) ## [0.2.35] - 2024-06-06 @@ -351,4 +352,5 @@ and this project does not currently adhere to a particular versioning scheme. [gh-582]: https://github.com/HigherOrderCO/Bend/issues/582 [gh-583]: https://github.com/HigherOrderCO/Bend/issues/583 [gh-586]: https://github.com/HigherOrderCO/Bend/issues/586 +[gh-596]: https://github.com/HigherOrderCO/Bend/issues/596 [Unreleased]: https://github.com/HigherOrderCO/Bend/compare/0.2.35...HEAD diff --git a/docs/syntax.md b/docs/syntax.md index 03fd1fca..d7545cbd 100644 --- a/docs/syntax.md +++ b/docs/syntax.md @@ -939,6 +939,20 @@ switch _ = condition { } ``` +It is possible to make if-chains using `elif`: + +```rust +if condition1 { + 0 +} condition2 { + 1 +} condition3 { + 2 +} else { + 3 +} +``` + ### Bend Bend can be used to create recursive data structures: diff --git a/src/fun/parser.rs b/src/fun/parser.rs index 95d5144f..97a464a0 100644 --- a/src/fun/parser.rs +++ b/src/fun/parser.rs @@ -492,22 +492,37 @@ impl<'a> TermParser<'a> { // If if self.try_parse_keyword("if") { + let mut chain = Vec::new(); let cnd = self.parse_term()?; self.consume("{")?; let thn = self.parse_term()?; self.consume("}")?; + + chain.push((cnd, thn)); + + self.skip_trivia_inline()?; + while self.try_parse_keyword("elif") { + let cnd = self.parse_term()?; + self.consume("{")?; + let thn = self.parse_term()?; + self.consume("}")?; + self.skip_trivia_inline()?; + chain.push((cnd, thn)); + } + self.consume("else")?; self.consume("{")?; let els = self.parse_term()?; self.consume("}")?; - return Ok(Term::Swt { - arg: Box::new(cnd), + let els = chain.into_iter().rfold(els, |acc, (cnd, thn)| Term::Swt { bnd: Some(Name::new("%cond")), + arg: Box::new(cnd), with_bnd: Vec::new(), with_arg: Vec::new(), pred: Some(Name::new("%cond-1")), - arms: vec![els, thn], + arms: vec![acc, thn], }); + return Ok(els); } // Match diff --git a/src/imp/parser.rs b/src/imp/parser.rs index 7b604ff1..785d7ef0 100644 --- a/src/imp/parser.rs +++ b/src/imp/parser.rs @@ -583,7 +583,7 @@ impl<'a> PyParser<'a> { self.consume_indent_exactly(*indent)?; let (otherwise, nxt_indent) = self.parse_statement(indent)?; - let otherwise = elifs.into_iter().fold(otherwise, |acc, (cond, then)| Stmt::If { + let otherwise = elifs.into_iter().rfold(otherwise, |acc, (cond, then)| Stmt::If { cond: Box::new(cond), then: Box::new(then), otherwise: Box::new(acc), diff --git a/tests/golden_tests/compile_file/elif_fun.bend b/tests/golden_tests/compile_file/elif_fun.bend new file mode 100644 index 00000000..b78bf309 --- /dev/null +++ b/tests/golden_tests/compile_file/elif_fun.bend @@ -0,0 +1,16 @@ +main = + let cond1 = (== 1 2) + let cond2 = (< 2 1) + let cond3 = (> 3 2) + let cond4 = (== 2 2) + if cond1 { + 1 + } elif cond2 { + 2 + } elif cond3 { + 3 + } elif cond4 { + 4 + } else { + 0 + } diff --git a/tests/snapshots/compile_file__elif.bend.snap b/tests/snapshots/compile_file__elif.bend.snap index 2aff836c..6a1b6cab 100644 --- a/tests/snapshots/compile_file__elif.bend.snap +++ b/tests/snapshots/compile_file__elif.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/elif.bend --- @main = j - & $(2 ?(((d (e (?(((b (?(((?((0 (* 2)) a) a) (* (* 3))) (b c)) c)) (* (* (* 4)))) (d (e f))) f))) (* (* (* (* 1))))) (g (h (i j))))) ~ [=0x0000001] + & $(2 ?(((?(((?(((?((0 (* 4)) a) a) (* (* 3))) b) b) (* (* (* 2)))) d) d) (* (* (* (* 1))))) (g (h (i j))))) ~ [=0x0000001] & $(1 g) ~ [<0x0000002] & $(2 h) ~ [>0x0000003] & $(2 i) ~ [=0x0000002] diff --git a/tests/snapshots/compile_file__elif_fun.bend.snap b/tests/snapshots/compile_file__elif_fun.bend.snap new file mode 100644 index 00000000..f31fcd36 --- /dev/null +++ b/tests/snapshots/compile_file__elif_fun.bend.snap @@ -0,0 +1,9 @@ +--- +source: tests/golden_tests.rs +input_file: tests/golden_tests/compile_file/elif_fun.bend +--- +@main = j + & $(2 ?(((?(((?(((?((0 (* 4)) a) a) (* (* 3))) b) b) (* (* (* 2)))) d) d) (* (* (* (* 1))))) (g (h (i j))))) ~ [=0x0000001] + & $(1 g) ~ [<0x0000002] + & $(2 h) ~ [>0x0000003] + & $(2 i) ~ [=0x0000002]