mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-08-16 15:20:40 +03:00
Impl clone for Term, remove unecessary clones
This commit is contained in:
parent
b9edd06eae
commit
216175a7f2
@ -35,3 +35,6 @@ stacker = "0.1"
|
||||
insta = "1.34.0"
|
||||
stdext = "0.3.1"
|
||||
walkdir = "2.3.3"
|
||||
|
||||
[profile.test]
|
||||
opt-level = 2
|
@ -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) {
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
1
tests/golden_tests/compile_file_o_all/long_str_file.hvm
Normal file
1
tests/golden_tests/compile_file_o_all/long_str_file.hvm
Normal file
File diff suppressed because one or more lines are too long
730521
tests/snapshots/compile_file_o_all__long_str_file.hvm.snap
Normal file
730521
tests/snapshots/compile_file_o_all__long_str_file.hvm.snap
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user