mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-09-17 14:47:21 +03:00
[sc-699] Require , in list-like things in imp syntax
This commit is contained in:
parent
8a137b0d87
commit
1585d2d5bc
@ -44,6 +44,7 @@
|
|||||||
"inodes",
|
"inodes",
|
||||||
"insta",
|
"insta",
|
||||||
"interner",
|
"interner",
|
||||||
|
"ints",
|
||||||
"itertools",
|
"itertools",
|
||||||
"ITRS",
|
"ITRS",
|
||||||
"kwarg",
|
"kwarg",
|
||||||
|
@ -16,7 +16,7 @@ def and(a, b):
|
|||||||
def all(tree):
|
def all(tree):
|
||||||
fold tree:
|
fold tree:
|
||||||
case Tree/Node:
|
case Tree/Node:
|
||||||
return and(tree.lft tree.rgt)
|
return and(tree.lft, tree.rgt)
|
||||||
case Tree/Leaf:
|
case Tree/Leaf:
|
||||||
return tree.val
|
return tree.val
|
||||||
|
|
||||||
|
@ -96,6 +96,7 @@ impl<'a> PyParser<'a> {
|
|||||||
let ini_idx = *self.index();
|
let ini_idx = *self.index();
|
||||||
|
|
||||||
let base = match head {
|
let base = match head {
|
||||||
|
// Tuple or parenthesized expression
|
||||||
'(' => {
|
'(' => {
|
||||||
self.advance_one();
|
self.advance_one();
|
||||||
let head = self.parse_expr(false)?;
|
let head = self.parse_expr(false)?;
|
||||||
@ -114,41 +115,49 @@ impl<'a> PyParser<'a> {
|
|||||||
head
|
head
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Map or Sup
|
||||||
'{' => {
|
'{' => {
|
||||||
self.advance_one();
|
self.advance_one();
|
||||||
self.skip_trivia();
|
// Empty map
|
||||||
if self.try_consume_exactly("}") {
|
if self.try_consume("}") {
|
||||||
return Ok(Expr::MapInit { entries: Vec::new() });
|
return Ok(Expr::MapInit { entries: vec![] });
|
||||||
}
|
}
|
||||||
let head = self.parse_expr(false)?;
|
let head = self.parse_expr(false)?;
|
||||||
self.skip_trivia();
|
self.skip_trivia();
|
||||||
if self.starts_with(":") { self.parse_map_init(head)? } else { self.parse_sup(head)? }
|
if self.starts_with(":") { self.parse_map_init(head)? } else { self.parse_sup(head)? }
|
||||||
}
|
}
|
||||||
|
// List or Comprehension
|
||||||
'[' => self.list_or_comprehension()?,
|
'[' => self.list_or_comprehension()?,
|
||||||
|
// Symbol
|
||||||
'`' => Expr::Num { val: Num::U24(self.parse_quoted_symbol()?) },
|
'`' => Expr::Num { val: Num::U24(self.parse_quoted_symbol()?) },
|
||||||
|
// String
|
||||||
'\"' => {
|
'\"' => {
|
||||||
let str = self.parse_quoted_string()?;
|
let str = self.parse_quoted_string()?;
|
||||||
let val = STRINGS.get(str);
|
let val = STRINGS.get(str);
|
||||||
Expr::Str { val }
|
Expr::Str { val }
|
||||||
}
|
}
|
||||||
|
// Char
|
||||||
'\'' => {
|
'\'' => {
|
||||||
let chr = self.parse_quoted_char()?;
|
let chr = self.parse_quoted_char()?;
|
||||||
Expr::Num { val: Num::U24(chr as u32 & 0x00ff_ffff) }
|
Expr::Num { val: Num::U24(chr as u32 & 0x00ff_ffff) }
|
||||||
}
|
}
|
||||||
|
// Unscoped var
|
||||||
'$' => {
|
'$' => {
|
||||||
self.advance_one();
|
self.advance_one();
|
||||||
let nam = self.parse_bend_name()?;
|
let nam = self.parse_bend_name()?;
|
||||||
Expr::Chn { nam }
|
Expr::Chn { nam }
|
||||||
}
|
}
|
||||||
|
// Era
|
||||||
'*' => {
|
'*' => {
|
||||||
self.advance_one();
|
self.advance_one();
|
||||||
Expr::Eraser
|
Expr::Eraser
|
||||||
}
|
}
|
||||||
|
// Number
|
||||||
c if is_num_char(c) => {
|
c if is_num_char(c) => {
|
||||||
let val = self.parse_number()?;
|
let val = self.parse_number()?;
|
||||||
Expr::Num { val }
|
Expr::Num { val }
|
||||||
}
|
}
|
||||||
// var or postfix
|
// var
|
||||||
_ => {
|
_ => {
|
||||||
let nam = self.labelled(|p| p.parse_bend_name(), "expression")?;
|
let nam = self.labelled(|p| p.parse_bend_name(), "expression")?;
|
||||||
Expr::Var { nam }
|
Expr::Var { nam }
|
||||||
@ -178,7 +187,9 @@ impl<'a> PyParser<'a> {
|
|||||||
} else {
|
} else {
|
||||||
args.push(arg);
|
args.push(arg);
|
||||||
}
|
}
|
||||||
self.try_consume(",");
|
if !self.starts_with(")") {
|
||||||
|
self.consume(",")?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if args.is_empty() && kwargs.is_empty() {
|
if args.is_empty() && kwargs.is_empty() {
|
||||||
return Ok(base);
|
return Ok(base);
|
||||||
@ -202,7 +213,7 @@ impl<'a> PyParser<'a> {
|
|||||||
// ctr
|
// ctr
|
||||||
if self.starts_with("{") {
|
if self.starts_with("{") {
|
||||||
if let Expr::Var { nam } = base {
|
if let Expr::Var { nam } = base {
|
||||||
let kwargs = self.list_like(|p| p.data_kwarg(), "{", "}", ",", false, 0)?;
|
let kwargs = self.list_like(|p| p.data_kwarg(), "{", "}", ",", true, 0)?;
|
||||||
return Ok(Expr::Constructor { name: nam, args: Vec::new(), kwargs });
|
return Ok(Expr::Constructor { name: nam, args: Vec::new(), kwargs });
|
||||||
} else {
|
} else {
|
||||||
return self.expected_spanned("Constructor name", ini_idx, end_idx);
|
return self.expected_spanned("Constructor name", ini_idx, end_idx);
|
||||||
@ -218,15 +229,18 @@ impl<'a> PyParser<'a> {
|
|||||||
self.consume(":")?;
|
self.consume(":")?;
|
||||||
let val = self.parse_expr(false)?;
|
let val = self.parse_expr(false)?;
|
||||||
entries.push((head, val));
|
entries.push((head, val));
|
||||||
self.try_consume(",");
|
self.skip_trivia();
|
||||||
let tail = self.list_like(|p| p.parse_map_entry(), "", "}", ",", false, 0)?;
|
if !self.starts_with("}") {
|
||||||
|
self.consume(",")?;
|
||||||
|
}
|
||||||
|
let tail = self.list_like(|p| p.parse_map_entry(), "", "}", ",", true, 0)?;
|
||||||
entries.extend(tail);
|
entries.extend(tail);
|
||||||
Ok(Expr::MapInit { entries })
|
Ok(Expr::MapInit { entries })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_sup(&mut self, head: Expr) -> ParseResult<Expr> {
|
fn parse_sup(&mut self, head: Expr) -> ParseResult<Expr> {
|
||||||
let mut els = vec![head];
|
let mut els = vec![head];
|
||||||
let tail = self.list_like(|p| p.parse_expr(false), "", "}", ",", false, 1)?;
|
let tail = self.list_like(|p| p.parse_expr(false), "", "}", ",", true, 1)?;
|
||||||
els.extend(tail);
|
els.extend(tail);
|
||||||
Ok(Expr::Sup { els })
|
Ok(Expr::Sup { els })
|
||||||
}
|
}
|
||||||
@ -274,8 +288,11 @@ impl<'a> PyParser<'a> {
|
|||||||
} else {
|
} else {
|
||||||
// List
|
// List
|
||||||
let mut head = vec![head];
|
let mut head = vec![head];
|
||||||
self.try_consume(",");
|
self.skip_trivia();
|
||||||
let tail = self.list_like(|p| p.parse_expr(false), "", "]", ",", false, 0)?;
|
if !self.starts_with("]") {
|
||||||
|
self.consume(",")?;
|
||||||
|
}
|
||||||
|
let tail = self.list_like(|p| p.parse_expr(false), "", "]", ",", true, 0)?;
|
||||||
head.extend(tail);
|
head.extend(tail);
|
||||||
Ok(Expr::Lst { els: head })
|
Ok(Expr::Lst { els: head })
|
||||||
}
|
}
|
||||||
@ -685,7 +702,9 @@ impl<'a> PyParser<'a> {
|
|||||||
while !self.starts_with(":") {
|
while !self.starts_with(":") {
|
||||||
with.push(self.parse_bend_name()?);
|
with.push(self.parse_bend_name()?);
|
||||||
self.skip_trivia_inline();
|
self.skip_trivia_inline();
|
||||||
self.try_consume_exactly(",");
|
if !self.starts_with(":") {
|
||||||
|
self.consume_exactly(",")?;
|
||||||
|
}
|
||||||
self.skip_trivia_inline();
|
self.skip_trivia_inline();
|
||||||
}
|
}
|
||||||
with
|
with
|
||||||
@ -721,7 +740,7 @@ impl<'a> PyParser<'a> {
|
|||||||
/// "else" ":"
|
/// "else" ":"
|
||||||
/// <base>
|
/// <base>
|
||||||
fn parse_bend(&mut self, indent: &mut Indent) -> ParseResult<(Stmt, Indent)> {
|
fn parse_bend(&mut self, indent: &mut Indent) -> ParseResult<(Stmt, Indent)> {
|
||||||
let args = self.list_like(|p| p.parse_match_arg(), "", ":", ",", false, 1)?;
|
let args = self.list_like(|p| p.parse_match_arg(), "", ":", ",", true, 1)?;
|
||||||
let (bind, init) = args.into_iter().unzip();
|
let (bind, init) = args.into_iter().unzip();
|
||||||
self.consume_new_line()?;
|
self.consume_new_line()?;
|
||||||
indent.enter_level();
|
indent.enter_level();
|
||||||
@ -822,7 +841,7 @@ impl<'a> PyParser<'a> {
|
|||||||
}
|
}
|
||||||
// Dup pattern
|
// Dup pattern
|
||||||
if self.starts_with("{") {
|
if self.starts_with("{") {
|
||||||
let binds = self.list_like(|p| p.parse_assign_pattern(), "{", "}", "", false, 2)?;
|
let binds = self.list_like(|p| p.parse_assign_pattern(), "{", "}", ",", true, 2)?;
|
||||||
return Ok(AssignPattern::Sup(binds));
|
return Ok(AssignPattern::Sup(binds));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -892,7 +911,7 @@ impl<'a> PyParser<'a> {
|
|||||||
let name = self.parse_bend_name()?;
|
let name = self.parse_bend_name()?;
|
||||||
self.skip_trivia_inline();
|
self.skip_trivia_inline();
|
||||||
let params = if self.starts_with("(") {
|
let params = if self.starts_with("(") {
|
||||||
self.list_like(|p| p.parse_bend_name(), "(", ")", ",", false, 0)?
|
self.list_like(|p| p.parse_bend_name(), "(", ")", ",", true, 0)?
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
};
|
};
|
||||||
@ -932,7 +951,7 @@ impl<'a> PyParser<'a> {
|
|||||||
let mut fields = Vec::new();
|
let mut fields = Vec::new();
|
||||||
self.skip_trivia_inline();
|
self.skip_trivia_inline();
|
||||||
if self.starts_with("{") {
|
if self.starts_with("{") {
|
||||||
fields = self.list_like(|p| p.parse_variant_field(), "{", "}", ",", false, 0)?;
|
fields = self.list_like(|p| p.parse_variant_field(), "{", "}", ",", true, 0)?;
|
||||||
}
|
}
|
||||||
variants.push(Variant { name: ctr_name, fields });
|
variants.push(Variant { name: ctr_name, fields });
|
||||||
if !self.is_eof() {
|
if !self.is_eof() {
|
||||||
@ -957,7 +976,7 @@ impl<'a> PyParser<'a> {
|
|||||||
let name = self.parse_top_level_name()?;
|
let name = self.parse_top_level_name()?;
|
||||||
self.skip_trivia_inline();
|
self.skip_trivia_inline();
|
||||||
let fields = if self.starts_with("{") {
|
let fields = if self.starts_with("{") {
|
||||||
self.list_like(|p| p.parse_variant_field(), "{", "}", ",", false, 0)?
|
self.list_like(|p| p.parse_variant_field(), "{", "}", ",", true, 0)?
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
};
|
};
|
||||||
|
@ -53,17 +53,17 @@ def swt(n):
|
|||||||
|
|
||||||
def fld(list):
|
def fld(list):
|
||||||
fold list:
|
fold list:
|
||||||
case List/cons:
|
case List/Cons:
|
||||||
return 1;
|
return 1;
|
||||||
case List/nil:
|
case List/Nil:
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
def bnd():
|
def bnd():
|
||||||
bend x = 0:
|
bend x = 0:
|
||||||
when x < 10:
|
when x < 10:
|
||||||
return List/cons(x fork(x + 1));
|
return List/Cons(x, fork(x + 1));
|
||||||
else:
|
else:
|
||||||
return List/nil();
|
return List/Nil();
|
||||||
|
|
||||||
def era():
|
def era():
|
||||||
* = (2 + 3)
|
* = (2 + 3)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
def main:
|
def main:
|
||||||
y = 1
|
y = 1
|
||||||
fold x = [0 0 0] with y:
|
fold x = [0, 0, 0] with y:
|
||||||
case List/Cons:
|
case List/Cons:
|
||||||
return List/Cons(x.head + y x.tail(y + 1))
|
return List/Cons(x.head + y, x.tail(y + 1))
|
||||||
case List/Nil:
|
case List/Nil:
|
||||||
return List/Nil
|
return List/Nil
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
def main:
|
|
||||||
return []
|
|
11
tests/golden_tests/run_file/imp_empty_literals.bend
Normal file
11
tests/golden_tests/run_file/imp_empty_literals.bend
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
def list:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def map:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def str:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def main:
|
||||||
|
return []
|
@ -26,14 +26,18 @@ input_file: tests/golden_tests/parse_file/imp_program.bend
|
|||||||
|
|
||||||
(swt) = λ%arg0 use n = %arg0; switch n = n { 0: 42; _ n-1: 1; }
|
(swt) = λ%arg0 use n = %arg0; switch n = n { 0: 42; _ n-1: 1; }
|
||||||
|
|
||||||
(fld) = λ%arg0 use list = %arg0; fold list = list { List/cons: 1; List/nil: 2; }
|
(fld) = λ%arg0 use list = %arg0; fold list = list { List/Cons: 1; List/Nil: 2; }
|
||||||
|
|
||||||
(bnd) = bend x = 0, { when (< x 10): (List/cons x (fork (+ x 1))); else: List/nil }
|
(bnd) = bend x = 0, { when (< x 10): (List/Cons x (fork (+ x 1))); else: List/Nil }
|
||||||
|
|
||||||
(era) = let * = (+ 2 3); let the_expr_killer = *; (the_expr_killer 9)
|
(era) = let * = (+ 2 3); let the_expr_killer = *; (the_expr_killer 9)
|
||||||
|
|
||||||
(main) = do IO { ask x = IO.read; x }
|
(main) = do IO { ask x = IO.read; x }
|
||||||
|
|
||||||
|
(List/Cons) = λhead λtail λList/Cons λList/Nil (List/Cons head tail)
|
||||||
|
|
||||||
|
(List/Nil) = λList/Cons λList/Nil List/Nil
|
||||||
|
|
||||||
(Map/Node) = λvalue λleft λright λMap/Node λMap/Leaf (Map/Node value left right)
|
(Map/Node) = λvalue λleft λright λMap/Node λMap/Leaf (Map/Node value left right)
|
||||||
|
|
||||||
(Map/Leaf) = λMap/Node λMap/Leaf Map/Leaf
|
(Map/Leaf) = λMap/Node λMap/Leaf Map/Leaf
|
||||||
|
5
tests/snapshots/run_file__imp_empty_literals.bend.snap
Normal file
5
tests/snapshots/run_file__imp_empty_literals.bend.snap
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
source: tests/golden_tests.rs
|
||||||
|
input_file: tests/golden_tests/run_file/imp_empty_literals.bend
|
||||||
|
---
|
||||||
|
λ* λa a
|
Loading…
Reference in New Issue
Block a user