mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-09-11 03:45:29 +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"));
|
||||
|
||||
@ -80,6 +80,7 @@ impl Pattern {
|
||||
pub fn encode_builtins(&mut self) {
|
||||
match self {
|
||||
Pattern::Lst(pats) => *self = Self::encode_list(std::mem::take(pats)),
|
||||
Pattern::Str(str) => *self = Self::encode_str(str),
|
||||
Pattern::Ctr(_, pats) => {
|
||||
for pat in pats {
|
||||
pat.encode_builtins();
|
||||
@ -94,11 +95,20 @@ impl 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| {
|
||||
nxt.encode_builtins();
|
||||
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);
|
||||
}
|
||||
}
|
||||
Pattern::Var(..) | Pattern::Num(..) => {}
|
||||
Pattern::Var(..) | Pattern::Num(..) | Pattern::Str(_) => {}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -58,7 +58,7 @@ impl Pattern {
|
||||
check.push(snd);
|
||||
}
|
||||
Pattern::Lst(args) => args.iter().for_each(|arg| check.push(arg)),
|
||||
Pattern::Var(_) | Pattern::Num(_) => {}
|
||||
Pattern::Var(_) | Pattern::Num(_) | Pattern::Str(_) => {}
|
||||
}
|
||||
}
|
||||
unbounds
|
||||
|
@ -111,6 +111,7 @@ impl fmt::Display for Pattern {
|
||||
Pattern::Num(num) => write!(f, "{num}"),
|
||||
Pattern::Tup(fst, snd) => write!(f, "({}, {})", fst, snd,),
|
||||
Pattern::Lst(pats) => write!(f, "[{}]", DisplayJoin(|| pats, ", ")),
|
||||
Pattern::Str(str) => write!(f, "\"{str}\""),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,6 +147,7 @@ pub enum Pattern {
|
||||
Num(NumCtr),
|
||||
Tup(Box<Pattern>, Box<Pattern>),
|
||||
Lst(Vec<Pattern>),
|
||||
Str(GlobalString),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
@ -640,6 +641,7 @@ impl Pattern {
|
||||
set.push(nam);
|
||||
}
|
||||
Pattern::Num(_) => {}
|
||||
Pattern::Str(_) => {}
|
||||
}
|
||||
}
|
||||
let mut set = Vec::new();
|
||||
@ -664,6 +666,7 @@ impl Pattern {
|
||||
Pattern::Num(_) => Box::new([].iter()),
|
||||
Pattern::Tup(fst, snd) => Box::new([fst.as_ref(), snd.as_ref()].into_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::Tup(_, _) => Some(Name::new("(,)")),
|
||||
Pattern::Lst(_) => todo!(),
|
||||
Pattern::Str(_) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -702,11 +706,12 @@ impl Pattern {
|
||||
pub fn is_simple(&self) -> bool {
|
||||
match self {
|
||||
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::Tup(fst, snd) => {
|
||||
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::Succ(n, _)) => Type::NumSucc(*n),
|
||||
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(_, Some(None))) => Term::Era,
|
||||
Pattern::Tup(fst, snd) => Term::Tup { fst: Box::new(fst.to_term()), snd: Box::new(snd.to_term()) },
|
||||
Pattern::Lst(_) => {
|
||||
let mut p = self.clone();
|
||||
p.encode_builtins();
|
||||
p.to_term()
|
||||
}
|
||||
Pattern::Lst(_) | Pattern::Str(_) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,26 +405,27 @@ where
|
||||
.map(Pattern::Lst)
|
||||
.boxed();
|
||||
|
||||
let num = any()
|
||||
let num_val = any()
|
||||
.filter(|t| matches!(t, Token::Num(_)))
|
||||
.map(|t| {
|
||||
let Token::Num(n) = t else { unreachable!() };
|
||||
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(name_or_era().or_not())
|
||||
.map(|(num, nam)| Pattern::Num(NumCtr::Succ(num, nam)))
|
||||
.labelled("<Num>+")
|
||||
.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}"))));
|
||||
}
|
||||
Pattern::Tup(_, _) => (),
|
||||
Pattern::Lst(..) => unreachable!(),
|
||||
Pattern::Lst(..) => (),
|
||||
Pattern::Str(..) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ impl Pattern {
|
||||
}
|
||||
Pattern::Var(None) => (),
|
||||
Pattern::Num(_) => (),
|
||||
Pattern::Str(_) => (),
|
||||
Pattern::Tup(fst, snd) => {
|
||||
to_resolve.push(fst);
|
||||
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
|
||||
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
|
||||
|
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