Impl clone for Term, remove unecessary clones

This commit is contained in:
LunaAmora 2024-02-29 11:16:09 -03:00
parent b9edd06eae
commit 216175a7f2
5 changed files with 730587 additions and 26 deletions

View File

@ -35,3 +35,6 @@ stacker = "0.1"
insta = "1.34.0"
stdext = "0.3.1"
walkdir = "2.3.3"
[profile.test]
opt-level = 2

View File

@ -67,7 +67,7 @@ pub struct Rule {
pub body: Term,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
#[derive(Debug, Default, PartialEq, Eq, Hash)]
pub enum Term {
Lam {
tag: Tag,
@ -139,6 +139,31 @@ pub enum Term {
#[default]
Err,
}
impl Clone for Term {
fn clone(&self) -> Self {
stacker::maybe_grow(1024 * 32, 1024 * 1024, move || match self {
Self::Lam { tag, nam, bod } => Self::Lam { tag: tag.clone(), nam: nam.clone(), bod: bod.clone() },
Self::Var { nam } => Self::Var { nam: nam.clone() },
Self::Chn { tag, nam, bod } => Self::Chn { tag: tag.clone(), nam: nam.clone(), bod: bod.clone() },
Self::Lnk { nam } => Self::Lnk { nam: nam.clone() },
Self::Let { pat, val, nxt } => Self::Let { pat: pat.clone(), val: val.clone(), nxt: nxt.clone() },
Self::App { tag, fun, arg } => Self::App { tag: tag.clone(), fun: fun.clone(), arg: arg.clone() },
Self::Tup { fst, snd } => Self::Tup { fst: fst.clone(), snd: snd.clone() },
Self::Dup { tag, fst, snd, val, nxt } => {
Self::Dup { tag: tag.clone(), fst: fst.clone(), snd: snd.clone(), val: val.clone(), nxt: nxt.clone() }
}
Self::Sup { tag, fst, snd } => Self::Sup { tag: tag.clone(), fst: fst.clone(), snd: snd.clone() },
Self::Num { val } => Self::Num { val: val.clone() },
Self::Str { val } => Self::Str { val: val.clone() },
Self::Lst { els } => Self::Lst { els: els.clone() },
Self::Opx { op, fst, snd } => Self::Opx { op: op.clone(), fst: fst.clone(), snd: snd.clone() },
Self::Mat { args, rules } => Self::Mat { args: args.clone(), rules: rules.clone() },
Self::Ref { nam } => Self::Ref { nam: nam.clone() },
Self::Era => Self::Era,
Self::Err => Self::Err,
})
}
}
impl Drop for Term {
fn drop(&mut self) {

View File

@ -44,7 +44,7 @@ impl Term {
Term::Mat { args, rules } => {
let (new_args, extracted) = extract_args(args);
let term = simplify_match_expression(&new_args, rules, ctrs, adts)?;
let term = simplify_match_expression(new_args, std::mem::take(rules), ctrs, adts)?;
*self = bind_extracted_args(extracted, term);
}
@ -99,13 +99,13 @@ impl Term {
/// For Var matches, we skip creating the surrounding match term since it's
/// redundant. (would be simply match x {x: ...})
fn simplify_match_expression(
args: &[Term],
rules: &[Rule],
args: Vec<Term>,
rules: Vec<Rule>,
ctrs: &Constructors,
adts: &Adts,
) -> Result<Term, MatchErr> {
let fst_row_irrefutable = rules[0].pats.iter().all(|p| p.is_wildcard());
let fst_col_type = infer_match_arg_type(rules, 0, ctrs)?;
let fst_col_type = infer_match_arg_type(&rules, 0, ctrs)?;
if fst_row_irrefutable {
irrefutable_fst_row_rule(args, rules, ctrs, adts)
@ -120,16 +120,19 @@ fn simplify_match_expression(
/// An optimization to not generate unnecessary pattern matching when we
/// know the first case always matches.
fn irrefutable_fst_row_rule(
args: &[Term],
rules: &[Rule],
args: Vec<Term>,
mut rules: Vec<Rule>,
ctrs: &Constructors,
adts: &Adts,
) -> Result<Term, MatchErr> {
let mut term = rules[0].body.clone();
rules.truncate(1);
let Rule { pats, body: mut term } = rules.pop().unwrap();
term.simplify_matches(ctrs, adts)?;
let term = rules[0].pats.iter().zip(args).fold(term, |term, (pat, arg)| Term::Let {
pat: pat.clone(),
val: Box::new(arg.clone()),
let term = pats.into_iter().zip(args).fold(term, |term, (pat, arg)| Term::Let {
pat,
val: Box::new(arg),
nxt: Box::new(term),
});
Ok(term)
@ -140,18 +143,25 @@ fn irrefutable_fst_row_rule(
/// `match x0 ... xN { var p1 ... pN: (Body var p1 ... pN) }`
/// becomes
/// `match x1 ... xN { p1 ... pN: let var = x0; (Body var p1 ... pN) }`
fn var_rule(args: &[Term], rules: &[Rule], ctrs: &Constructors, adts: &Adts) -> Result<Term, MatchErr> {
fn var_rule(
mut args: Vec<Term>,
rules: Vec<Rule>,
ctrs: &Constructors,
adts: &Adts,
) -> Result<Term, MatchErr> {
let mut new_rules = vec![];
for rule in rules {
let body = Term::Let {
pat: rule.pats[0].clone(),
val: Box::new(args[0].clone()),
nxt: Box::new(rule.body.clone()),
};
let new_rule = Rule { pats: rule.pats[1 ..].to_vec(), body };
for mut rule in rules {
let rest = rule.pats.split_off(1);
let body =
Term::Let { pat: rule.pats.pop().unwrap(), val: Box::new(args[0].clone()), nxt: Box::new(rule.body) };
let new_rule = Rule { pats: rest, body };
new_rules.push(new_rule);
}
let mut term = Term::Mat { args: args[1 ..].to_vec(), rules: new_rules };
let rest = args.split_off(1);
let mut term = Term::Mat { args: rest, rules: new_rules };
term.simplify_matches(ctrs, adts)?;
Ok(term)
}
@ -202,8 +212,8 @@ fn var_rule(args: &[Term], rules: &[Rule], ctrs: &Constructors, adts: &Adts) ->
/// }
/// ```
fn switch_rule(
args: &[Term],
rules: &[Rule],
mut args: Vec<Term>,
rules: Vec<Rule>,
typ: Type,
ctrs: &Constructors,
adts: &Adts,
@ -214,7 +224,7 @@ fn switch_rule(
Type::Num => {
// Since numbers have infinite (2^60) constructors, they require special treatment.
let mut ctrs = IndexSet::new();
for rule in rules {
for rule in &rules {
ctrs.insert(rule.pats[0].clone());
if rule.pats[0].is_wildcard() {
break;
@ -237,7 +247,7 @@ fn switch_rule(
Type::NumSucc(exp) => {
// Number match with + can't have number larger than that in the +
// TODO: could be just a warning.
for rule in rules {
for rule in &rules {
if let Pattern::Num(NumCtr::Num(got)) = rule.pats[0]
&& got >= exp
{
@ -256,12 +266,13 @@ fn switch_rule(
let Term::Var { nam: arg_nam } = &args[0] else { unreachable!() };
let nested_fields = switch_rule_nested_fields(arg_nam, &ctr);
let matched_ctr = switch_rule_matched_ctr(ctr.clone(), &nested_fields);
let mut body = switch_rule_submatch(args, rules, &matched_ctr, &nested_fields)?;
let mut body = switch_rule_submatch(&args, &rules, &matched_ctr, &nested_fields)?;
body.simplify_matches(ctrs, adts)?;
let pats = vec![matched_ctr];
new_rules.push(Rule { pats, body });
}
let term = Term::Mat { args: vec![args[0].clone()], rules: new_rules };
args.truncate(1);
let term = Term::Mat { args, rules: new_rules };
Ok(term)
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff