Skip to content

Commit

Permalink
Merge pull request #213 from HigherOrderCO/feature/sc-441/add-string-…
Browse files Browse the repository at this point in the history
…sugar-in-patterns

[sc-441] Add string patterns
  • Loading branch information
developedby authored Feb 28, 2024
2 parents 5d9a967 + fb8f3fe commit 9c27eaa
Show file tree
Hide file tree
Showing 14 changed files with 65 additions and 23 deletions.
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"namegen",
"nams",
"numop",
"nums",
"oper",
"opre",
"oprune",
Expand Down
14 changes: 12 additions & 2 deletions src/term/builtins.rs
Original file line number Diff line number Diff line change
@@ -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"));

Expand Down Expand Up @@ -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();
Expand All @@ -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(SNIL), vec![]);

str.chars().rfold(lnil, |tail, head| {
let head = Pattern::Num(NumCtr::Num(head as u64));
Pattern::Ctr(Name::from(SCONS), vec![head, tail])
})
}
}
2 changes: 1 addition & 1 deletion src/term/check/ctrs_arities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl Pattern {
to_check.push(el);
}
}
Pattern::Var(..) | Pattern::Num(..) => {}
Pattern::Var(..) | Pattern::Num(..) | Pattern::Str(_) => {}
}
}
Ok(())
Expand Down
2 changes: 1 addition & 1 deletion src/term/check/unbound_pats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/term/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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}\""),
}
}
}
Expand Down
14 changes: 8 additions & 6 deletions src/term/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -640,6 +641,7 @@ impl Pattern {
set.push(nam);
}
Pattern::Num(_) => {}
Pattern::Str(_) => {}
}
}
let mut set = Vec::new();
Expand All @@ -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()),
}
}

Expand All @@ -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!(),
}
}

Expand All @@ -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!(),
}
}

Expand All @@ -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()),
}
}

Expand All @@ -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!(),
}
}

Expand Down
21 changes: 10 additions & 11 deletions src/term/parser/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,26 +405,25 @@ where
.map(Pattern::Lst)
.boxed();

let num = any()
.filter(|t| matches!(t, Token::Num(_)))
.map(|t| {
let Token::Num(n) = t else { unreachable!() };
n
})
.labelled("<Num>");
let num_val = any().filter(|t| matches!(t, Token::Num(_))).map(|t| {
let Token::Num(n) = t else { unreachable!() };
n
});

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();

let str = select!(Token::Str(s) => Pattern::Str(s)).labelled("<String>").boxed();

choice((succ_pat, num_pat, chr_pat, var, ctr, list, tup))
choice((succ, num, chr, str, var, ctr, list, tup))
})
}

Expand Down
3 changes: 2 additions & 1 deletion src/term/transform/desugar_implicit_match_binds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ impl Term {
*p = Some(Some(Name::new(format!("{nam}-{n}"))));
}
Pattern::Tup(_, _) => (),
Pattern::Lst(..) => unreachable!(),
Pattern::Lst(..) => (),
Pattern::Str(..) => (),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/term/transform/resolve_ctrs_in_pats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
9 changes: 9 additions & 0 deletions tests/golden_tests/run_file/match_str.hvm
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(is_as "As") = 2
(is_as "as") = 2
(is_as "") = 1
(is_as *) = 0

map f (List.cons x xs) = (List.cons (f x) (map f xs))
map f [] = []

main = (map is_as ["As" "as" "" "Asd" "qwerty" "AAs"])
6 changes: 6 additions & 0 deletions tests/golden_tests/simplify_matches/match_str.hvm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(is_as "As") = 2
(is_as "as") = 2
(is_as "") = 1
(is_as *) = 0

main = *
2 changes: 1 addition & 1 deletion tests/snapshots/compile_file__missing_pat.hvm.snap
Original file line number Diff line number Diff line change
Expand Up @@ -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>
 2 | : *
5 changes: 5 additions & 0 deletions tests/snapshots/run_file__match_str.hvm.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/run_file/match_str.hvm
---
[2, 2, 1, 0, 0, 0]
7 changes: 7 additions & 0 deletions tests/snapshots/simplify_matches__match_str.hvm.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/simplify_matches/match_str.hvm
---
(is_as) = λa match a { (String.cons b c): (match b { 65: λd (match d { (String.cons f g): λh (match f { 115: λ* λj (match j { (String.cons * *): λ* 0; (String.nil): λ* 2 } *); *: λ* λ* 0 } h g); (String.nil): λ* 0 } *); 97: λhb (match hb { (String.cons jb kb): λlb (match jb { 115: λ* λnb (match nb { (String.cons * *): λ* 0; (String.nil): λ* 2 } *); *: λ* λ* 0 } lb kb); (String.nil): λ* 0 } *); *: λ* 0 } c); (String.nil): 1 }

(main) = *

0 comments on commit 9c27eaa

Please sign in to comment.