mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-11-04 01:20:56 +03:00
[sc-441] Add string patterns
This commit is contained in:
parent
5d9a967713
commit
0fc957ea6e
@ -1,4 +1,4 @@
|
|||||||
use super::{parser::parse_book, Book, Name, Pattern, Term};
|
use super::{parser::parse_book, Book, Name, NumCtr, Pattern, Term};
|
||||||
|
|
||||||
const BUILTINS: &str = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/term/builtins.hvm"));
|
const BUILTINS: &str = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/term/builtins.hvm"));
|
||||||
|
|
||||||
@ -80,6 +80,7 @@ impl Pattern {
|
|||||||
pub fn encode_builtins(&mut self) {
|
pub fn encode_builtins(&mut self) {
|
||||||
match self {
|
match self {
|
||||||
Pattern::Lst(pats) => *self = Self::encode_list(std::mem::take(pats)),
|
Pattern::Lst(pats) => *self = Self::encode_list(std::mem::take(pats)),
|
||||||
|
Pattern::Str(str) => *self = Self::encode_str(str),
|
||||||
Pattern::Ctr(_, pats) => {
|
Pattern::Ctr(_, pats) => {
|
||||||
for pat in pats {
|
for pat in pats {
|
||||||
pat.encode_builtins();
|
pat.encode_builtins();
|
||||||
@ -94,11 +95,20 @@ impl Pattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn encode_list(elements: Vec<Pattern>) -> Pattern {
|
fn encode_list(elements: Vec<Pattern>) -> Pattern {
|
||||||
let lnil = Pattern::Var(Some(Name::from(LNIL)));
|
let lnil = Pattern::Ctr(Name::from(LNIL), vec![]);
|
||||||
|
|
||||||
elements.into_iter().rfold(lnil, |acc, mut nxt| {
|
elements.into_iter().rfold(lnil, |acc, mut nxt| {
|
||||||
nxt.encode_builtins();
|
nxt.encode_builtins();
|
||||||
Pattern::Ctr(Name::from(LCONS), vec![nxt, acc])
|
Pattern::Ctr(Name::from(LCONS), vec![nxt, acc])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encode_str(str: &str) -> Pattern {
|
||||||
|
let lnil = Pattern::Ctr(Name::from(LNIL), vec![]);
|
||||||
|
|
||||||
|
str.chars().rfold(lnil, |tail, head| {
|
||||||
|
let head = Pattern::Num(NumCtr::Num(head as u64));
|
||||||
|
Pattern::Ctr(Name::from(LCONS), vec![head, tail])
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ impl Pattern {
|
|||||||
to_check.push(el);
|
to_check.push(el);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Pattern::Var(..) | Pattern::Num(..) => {}
|
Pattern::Var(..) | Pattern::Num(..) | Pattern::Str(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -58,7 +58,7 @@ impl Pattern {
|
|||||||
check.push(snd);
|
check.push(snd);
|
||||||
}
|
}
|
||||||
Pattern::Lst(args) => args.iter().for_each(|arg| check.push(arg)),
|
Pattern::Lst(args) => args.iter().for_each(|arg| check.push(arg)),
|
||||||
Pattern::Var(_) | Pattern::Num(_) => {}
|
Pattern::Var(_) | Pattern::Num(_) | Pattern::Str(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unbounds
|
unbounds
|
||||||
|
@ -111,6 +111,7 @@ impl fmt::Display for Pattern {
|
|||||||
Pattern::Num(num) => write!(f, "{num}"),
|
Pattern::Num(num) => write!(f, "{num}"),
|
||||||
Pattern::Tup(fst, snd) => write!(f, "({}, {})", fst, snd,),
|
Pattern::Tup(fst, snd) => write!(f, "({}, {})", fst, snd,),
|
||||||
Pattern::Lst(pats) => write!(f, "[{}]", DisplayJoin(|| pats, ", ")),
|
Pattern::Lst(pats) => write!(f, "[{}]", DisplayJoin(|| pats, ", ")),
|
||||||
|
Pattern::Str(str) => write!(f, "\"{str}\""),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,6 +147,7 @@ pub enum Pattern {
|
|||||||
Num(NumCtr),
|
Num(NumCtr),
|
||||||
Tup(Box<Pattern>, Box<Pattern>),
|
Tup(Box<Pattern>, Box<Pattern>),
|
||||||
Lst(Vec<Pattern>),
|
Lst(Vec<Pattern>),
|
||||||
|
Str(GlobalString),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
@ -640,6 +641,7 @@ impl Pattern {
|
|||||||
set.push(nam);
|
set.push(nam);
|
||||||
}
|
}
|
||||||
Pattern::Num(_) => {}
|
Pattern::Num(_) => {}
|
||||||
|
Pattern::Str(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut set = Vec::new();
|
let mut set = Vec::new();
|
||||||
@ -664,6 +666,7 @@ impl Pattern {
|
|||||||
Pattern::Num(_) => Box::new([].iter()),
|
Pattern::Num(_) => Box::new([].iter()),
|
||||||
Pattern::Tup(fst, snd) => Box::new([fst.as_ref(), snd.as_ref()].into_iter()),
|
Pattern::Tup(fst, snd) => Box::new([fst.as_ref(), snd.as_ref()].into_iter()),
|
||||||
Pattern::Lst(els) => Box::new(els.iter()),
|
Pattern::Lst(els) => Box::new(els.iter()),
|
||||||
|
Pattern::Str(_) => Box::new([].iter()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -687,6 +690,7 @@ impl Pattern {
|
|||||||
Pattern::Num(NumCtr::Succ(num, _)) => Some(Name::new(format!("{num}+"))),
|
Pattern::Num(NumCtr::Succ(num, _)) => Some(Name::new(format!("{num}+"))),
|
||||||
Pattern::Tup(_, _) => Some(Name::new("(,)")),
|
Pattern::Tup(_, _) => Some(Name::new("(,)")),
|
||||||
Pattern::Lst(_) => todo!(),
|
Pattern::Lst(_) => todo!(),
|
||||||
|
Pattern::Str(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -702,11 +706,12 @@ impl Pattern {
|
|||||||
pub fn is_simple(&self) -> bool {
|
pub fn is_simple(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Pattern::Var(_) => true,
|
Pattern::Var(_) => true,
|
||||||
Pattern::Ctr(_, args) | Pattern::Lst(args) => args.iter().all(|arg| matches!(arg, Pattern::Var(_))),
|
Pattern::Ctr(_, args) => args.iter().all(|arg| matches!(arg, Pattern::Var(_))),
|
||||||
Pattern::Num(_) => true,
|
Pattern::Num(_) => true,
|
||||||
Pattern::Tup(fst, snd) => {
|
Pattern::Tup(fst, snd) => {
|
||||||
matches!(fst.as_ref(), Pattern::Var(_)) && matches!(snd.as_ref(), Pattern::Var(_))
|
matches!(fst.as_ref(), Pattern::Var(_)) && matches!(snd.as_ref(), Pattern::Var(_))
|
||||||
}
|
}
|
||||||
|
Pattern::Lst(_) | Pattern::Str(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -721,6 +726,7 @@ impl Pattern {
|
|||||||
Pattern::Num(NumCtr::Num(_)) => Type::Num,
|
Pattern::Num(NumCtr::Num(_)) => Type::Num,
|
||||||
Pattern::Num(NumCtr::Succ(n, _)) => Type::NumSucc(*n),
|
Pattern::Num(NumCtr::Succ(n, _)) => Type::NumSucc(*n),
|
||||||
Pattern::Lst(..) => Type::Adt(builtins::LIST.into()),
|
Pattern::Lst(..) => Type::Adt(builtins::LIST.into()),
|
||||||
|
Pattern::Str(..) => Type::Adt(builtins::STRING.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -736,11 +742,7 @@ impl Pattern {
|
|||||||
Pattern::Num(NumCtr::Succ(val, Some(Some(nam)))) => Term::add_num(Term::Var { nam: nam.clone() }, *val),
|
Pattern::Num(NumCtr::Succ(val, Some(Some(nam)))) => Term::add_num(Term::Var { nam: nam.clone() }, *val),
|
||||||
Pattern::Num(NumCtr::Succ(_, Some(None))) => Term::Era,
|
Pattern::Num(NumCtr::Succ(_, Some(None))) => Term::Era,
|
||||||
Pattern::Tup(fst, snd) => Term::Tup { fst: Box::new(fst.to_term()), snd: Box::new(snd.to_term()) },
|
Pattern::Tup(fst, snd) => Term::Tup { fst: Box::new(fst.to_term()), snd: Box::new(snd.to_term()) },
|
||||||
Pattern::Lst(_) => {
|
Pattern::Lst(_) | Pattern::Str(_) => todo!(),
|
||||||
let mut p = self.clone();
|
|
||||||
p.encode_builtins();
|
|
||||||
p.to_term()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,26 +405,27 @@ where
|
|||||||
.map(Pattern::Lst)
|
.map(Pattern::Lst)
|
||||||
.boxed();
|
.boxed();
|
||||||
|
|
||||||
let num = any()
|
let num_val = any()
|
||||||
.filter(|t| matches!(t, Token::Num(_)))
|
.filter(|t| matches!(t, Token::Num(_)))
|
||||||
.map(|t| {
|
.map(|t| {
|
||||||
let Token::Num(n) = t else { unreachable!() };
|
let Token::Num(n) = t else { unreachable!() };
|
||||||
n
|
n
|
||||||
})
|
});
|
||||||
.labelled("<Num>");
|
|
||||||
|
|
||||||
let num_pat = num.map(|n| Pattern::Num(NumCtr::Num(n)));
|
let num = num_val.map(|n| Pattern::Num(NumCtr::Num(n))).labelled("<Num>");
|
||||||
|
|
||||||
let succ_pat = num
|
let succ = num_val
|
||||||
.then_ignore(just(Token::Add))
|
.then_ignore(just(Token::Add))
|
||||||
.then(name_or_era().or_not())
|
.then(name_or_era().or_not())
|
||||||
.map(|(num, nam)| Pattern::Num(NumCtr::Succ(num, nam)))
|
.map(|(num, nam)| Pattern::Num(NumCtr::Succ(num, nam)))
|
||||||
.labelled("<Num>+")
|
.labelled("<Num>+")
|
||||||
.boxed();
|
.boxed();
|
||||||
|
|
||||||
let chr_pat = select!(Token::Char(c) => Pattern::Num(NumCtr::Num(c))).labelled("<Char>").boxed();
|
let chr = select!(Token::Char(c) => Pattern::Num(NumCtr::Num(c))).labelled("<Char>").boxed();
|
||||||
|
|
||||||
choice((succ_pat, num_pat, chr_pat, var, ctr, list, tup))
|
let str = select!(Token::Str(s) => Pattern::Str(s)).labelled("<String>").boxed();
|
||||||
|
|
||||||
|
choice((succ, num, chr, str, var, ctr, list, tup))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,8 @@ impl Term {
|
|||||||
*p = Some(Some(Name::new(format!("{nam}-{n}"))));
|
*p = Some(Some(Name::new(format!("{nam}-{n}"))));
|
||||||
}
|
}
|
||||||
Pattern::Tup(_, _) => (),
|
Pattern::Tup(_, _) => (),
|
||||||
Pattern::Lst(..) => unreachable!(),
|
Pattern::Lst(..) => (),
|
||||||
|
Pattern::Str(..) => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ impl Pattern {
|
|||||||
}
|
}
|
||||||
Pattern::Var(None) => (),
|
Pattern::Var(None) => (),
|
||||||
Pattern::Num(_) => (),
|
Pattern::Num(_) => (),
|
||||||
|
Pattern::Str(_) => (),
|
||||||
Pattern::Tup(fst, snd) => {
|
Pattern::Tup(fst, snd) => {
|
||||||
to_resolve.push(fst);
|
to_resolve.push(fst);
|
||||||
to_resolve.push(snd);
|
to_resolve.push(snd);
|
||||||
|
6
tests/golden_tests/simplify_matches/match_str.hvm
Normal file
6
tests/golden_tests/simplify_matches/match_str.hvm
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
(is_as "As") = 2
|
||||||
|
(is_as "as") = 2
|
||||||
|
(is_as "") = 1
|
||||||
|
(is_as *) = 0
|
||||||
|
|
||||||
|
main = *
|
@ -2,5 +2,5 @@
|
|||||||
source: tests/golden_tests.rs
|
source: tests/golden_tests.rs
|
||||||
input_file: tests/golden_tests/compile_file/missing_pat.hvm
|
input_file: tests/golden_tests/compile_file/missing_pat.hvm
|
||||||
---
|
---
|
||||||
At tests/golden_tests/compile_file/missing_pat.hvm:2:3: found ':' expected '(', '#', '$', <Name>, '[', '{', 'λ', 'let', 'match', '*', '|', <Num>+, <Num>, or <Char>
|
At tests/golden_tests/compile_file/missing_pat.hvm:2:3: found ':' expected '(', '#', '$', <Name>, '[', '{', 'λ', 'let', 'match', '*', '|', <Num>+, <Num>, <Char>, or <String>
|
||||||
[0m 2 | [4m[31m:[0m *[0m
|
[0m 2 | [4m[31m:[0m *[0m
|
||||||
|
7
tests/snapshots/simplify_matches__match_str.hvm.snap
Normal file
7
tests/snapshots/simplify_matches__match_str.hvm.snap
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
source: tests/golden_tests.rs
|
||||||
|
input_file: tests/golden_tests/simplify_matches/match_str.hvm
|
||||||
|
---
|
||||||
|
(is_as) = λa match a { (List.cons b c): (match b { 65: λd (match d { (List.cons f g): λh (match f { 115: λ* λj (match j { (List.cons * *): λ* 0; (List.nil): λ* 2 } *); *: λ* λ* 0 } h g); (List.nil): λ* 0 } *); 97: λhb (match hb { (List.cons jb kb): λlb (match jb { 115: λ* λnb (match nb { (List.cons * *): λ* 0; (List.nil): λ* 2 } *); *: λ* λ* 0 } lb kb); (List.nil): λ* 0 } *); *: λ* 0 } c); (List.nil): 1 }
|
||||||
|
|
||||||
|
(main) = *
|
Loading…
Reference in New Issue
Block a user