Add elif chain to functional syntax

This commit is contained in:
imaqtkatt 2024-06-20 16:12:49 -03:00
parent c4afa0f248
commit 8694b79500
7 changed files with 61 additions and 5 deletions

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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),

View File

@ -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
}

View File

@ -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]

View File

@ -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]