mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-09-19 15:48:27 +03:00
Merge pull request #188 from HigherOrderCO/feature/sc-439/refactor-some-recursive-passes-to-stack-based
[sc-439] Refactor some recursive passes to stack based
This commit is contained in:
commit
2bd63b9494
@ -48,8 +48,8 @@ impl Term {
|
||||
fst.encode_builtins();
|
||||
snd.encode_builtins();
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
scrutinee.encode_builtins();
|
||||
Term::Mat { matched, arms } => {
|
||||
matched.encode_builtins();
|
||||
for (pat, arm) in arms {
|
||||
pat.encode_builtins();
|
||||
arm.encode_builtins();
|
||||
|
@ -37,27 +37,32 @@ impl Book {
|
||||
|
||||
impl Pattern {
|
||||
fn check(&self, arities: &HashMap<Name, usize>) -> Result<(), String> {
|
||||
match self {
|
||||
Pattern::Ctr(name, args) => {
|
||||
let arity = arities.get(name).unwrap();
|
||||
let args = args.len();
|
||||
if *arity != args {
|
||||
Err(format!("Arity error. Constructor '{}' expects {} fields, found {}.", name, arity, args))
|
||||
} else {
|
||||
Ok(())
|
||||
let mut to_check = vec![self];
|
||||
|
||||
while let Some(pat) = to_check.pop() {
|
||||
match pat {
|
||||
Pattern::Ctr(name, args) => {
|
||||
let arity = arities.get(name).unwrap();
|
||||
let args = args.len();
|
||||
if *arity != args {
|
||||
return Err(format!(
|
||||
"Arity error. Constructor '{}' expects {} fields, found {}.",
|
||||
name, arity, args
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
Pattern::Tup(fst, snd) => {
|
||||
fst.check(arities)?;
|
||||
snd.check(arities)
|
||||
}
|
||||
Pattern::Lst(els) => {
|
||||
for el in els {
|
||||
el.check(arities)?;
|
||||
Pattern::Tup(fst, snd) => {
|
||||
to_check.push(fst);
|
||||
to_check.push(snd);
|
||||
}
|
||||
Ok(())
|
||||
Pattern::Lst(els) => {
|
||||
for el in els {
|
||||
to_check.push(el);
|
||||
}
|
||||
}
|
||||
Pattern::Var(..) | Pattern::Num(..) => {}
|
||||
}
|
||||
Pattern::Var(..) | Pattern::Num(..) => Ok(()),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -59,8 +59,8 @@ impl Term {
|
||||
val.check_unbound_pats(is_ctr)?;
|
||||
nxt.check_unbound_pats(is_ctr)?;
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
scrutinee.check_unbound_pats(is_ctr)?;
|
||||
Term::Mat { matched, arms } => {
|
||||
matched.check_unbound_pats(is_ctr)?;
|
||||
for (pat, body) in arms {
|
||||
pat.check_unbounds(is_ctr)?;
|
||||
body.check_unbound_pats(is_ctr)?;
|
||||
|
@ -95,8 +95,8 @@ pub fn check_uses<'a>(
|
||||
check_uses(fst, scope, globals)?;
|
||||
check_uses(snd, scope, globals)?;
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
check_uses(scrutinee, scope, globals)?;
|
||||
Term::Mat { matched, arms } => {
|
||||
check_uses(matched, scope, globals)?;
|
||||
for (pat, term) in arms {
|
||||
pat.names().for_each(|nam| push_scope(Some(nam), scope));
|
||||
|
||||
|
@ -59,11 +59,11 @@ impl fmt::Display for Term {
|
||||
Term::App { tag, fun, arg } => {
|
||||
write!(f, "{}({} {})", tag.display_padded(), fun.display_app(tag), arg)
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
Term::Mat { matched, arms } => {
|
||||
write!(
|
||||
f,
|
||||
"match {} {{ {} }}",
|
||||
scrutinee,
|
||||
matched,
|
||||
DisplayJoin(|| arms.iter().map(|(pat, term)| display!("{}: {}", pat, term)), "; "),
|
||||
)
|
||||
}
|
||||
|
@ -283,8 +283,8 @@ impl Term {
|
||||
nxt.subst(from, to);
|
||||
}
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
scrutinee.subst(from, to);
|
||||
Term::Mat { matched, arms } => {
|
||||
matched.subst(from, to);
|
||||
|
||||
for (rule, term) in arms {
|
||||
let can_subst;
|
||||
@ -318,8 +318,8 @@ impl Term {
|
||||
Term::Lnk { nam } if nam == from => {
|
||||
*self = to.clone();
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
scrutinee.subst_unscoped(from, to);
|
||||
Term::Mat { matched, arms } => {
|
||||
matched.subst_unscoped(from, to);
|
||||
arms.iter_mut().for_each(|(_, arm)| arm.subst_unscoped(from, to));
|
||||
}
|
||||
Term::Lst { els } => els.iter_mut().for_each(|el| el.subst_unscoped(from, to)),
|
||||
@ -389,8 +389,8 @@ impl Term {
|
||||
go(fst, free_vars);
|
||||
go(snd, free_vars);
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
go(scrutinee, free_vars);
|
||||
Term::Mat { matched, arms } => {
|
||||
go(matched, free_vars);
|
||||
|
||||
for (rule, term) in arms {
|
||||
let mut new_scope = IndexMap::new();
|
||||
@ -430,8 +430,8 @@ impl Term {
|
||||
Term::Lnk { nam } => {
|
||||
uses.insert(nam.clone());
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
go(scrutinee, decls, uses);
|
||||
Term::Mat { matched, arms } => {
|
||||
go(matched, decls, uses);
|
||||
for (_, arm) in arms {
|
||||
go(arm, decls, uses);
|
||||
}
|
||||
|
@ -209,19 +209,19 @@ impl<'a> Reader<'a> {
|
||||
term
|
||||
}
|
||||
|
||||
/// Enters both ports 1 and 2 of a node,
|
||||
/// Returning a Term if is possible to simplify the net, or the Terms on the two ports of the node.
|
||||
/// Enters both ports 1 and 2 of a node,
|
||||
/// Returning a Term if is possible to simplify the net, or the Terms on the two ports of the node.
|
||||
/// The two possible outcomes are always equivalent.
|
||||
///
|
||||
/// If:
|
||||
/// - The node Kind is CON/TUP/DUP
|
||||
/// - Both ports 1 and 2 are connected to the same node on slots 1 and 2 respectively
|
||||
/// - That node Kind is the same as the given node Kind
|
||||
///
|
||||
/// Then:
|
||||
/// If:
|
||||
/// - The node Kind is CON/TUP/DUP
|
||||
/// - Both ports 1 and 2 are connected to the same node on slots 1 and 2 respectively
|
||||
/// - That node Kind is the same as the given node Kind
|
||||
///
|
||||
/// Then:
|
||||
/// Reads the port 0 of the connected node, and returns that term.
|
||||
///
|
||||
/// Otherwise:
|
||||
/// Otherwise:
|
||||
/// Returns the terms on ports 1 and 2 of the given node.
|
||||
///
|
||||
/// # Example
|
||||
@ -230,7 +230,7 @@ impl<'a> Reader<'a> {
|
||||
/// // λa let (a, b) = a; (a, b)
|
||||
/// ([a b] [a b])
|
||||
///
|
||||
/// // The node `(a, b)` is just a reconstruction of the destructuring of `a`,
|
||||
/// // The node `(a, b)` is just a reconstruction of the destructuring of `a`,
|
||||
/// // So we can skip both steps and just return the "value" unchanged:
|
||||
///
|
||||
/// // λa a
|
||||
@ -301,8 +301,8 @@ impl Term {
|
||||
| Term::Opx { fst, snd, .. } => {
|
||||
fst.insert_split(split, threshold)? + snd.insert_split(split, threshold)?
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
let mut n = scrutinee.insert_split(split, threshold)?;
|
||||
Term::Mat { matched, arms } => {
|
||||
let mut n = matched.insert_split(split, threshold)?;
|
||||
for arm in arms {
|
||||
n += arm.1.insert_split(split, threshold)?;
|
||||
}
|
||||
@ -365,8 +365,8 @@ impl Term {
|
||||
fst.fix_names(id_counter, book);
|
||||
snd.fix_names(id_counter, book);
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
scrutinee.fix_names(id_counter, book);
|
||||
Term::Mat { matched, arms } => {
|
||||
matched.fix_names(id_counter, book);
|
||||
|
||||
for (rule, term) in arms {
|
||||
if let Pattern::Num(MatchNum::Succ(Some(nam))) = rule {
|
||||
|
@ -161,10 +161,10 @@ impl<'a> EncodeTermState<'a> {
|
||||
Some(Port(app, 2))
|
||||
}
|
||||
// core: & cond ~ (zero succ) ret
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
Term::Mat { matched, arms } => {
|
||||
let if_ = self.inet.new_node(Mat);
|
||||
|
||||
let cond = self.encode_term(scrutinee, Port(if_, 0));
|
||||
let cond = self.encode_term(matched, Port(if_, 0));
|
||||
self.link_local(Port(if_, 0), cond);
|
||||
|
||||
debug_assert!(matches!(arms[0].0, Pattern::Num(MatchNum::Zero)));
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::collections::{hash_map::Entry, HashMap};
|
||||
|
||||
use crate::{
|
||||
term::{Adt, AdtEncoding, Book, Name, Tag, Term, LCONS, LNIL, SCONS, SNIL},
|
||||
term::{Adt, AdtEncoding, Book, Name, Tag, Term, LIST, STRING},
|
||||
Warning,
|
||||
};
|
||||
use indexmap::IndexSet;
|
||||
@ -95,44 +95,44 @@ impl Book {
|
||||
uses: &mut Definitions,
|
||||
adt_encoding: AdtEncoding,
|
||||
) {
|
||||
self.find_manual_adt_encoding(term, uses, adt_encoding);
|
||||
let mut to_find = vec![term];
|
||||
|
||||
match term {
|
||||
Term::Ref { nam: def_name } => match self.ctrs.get(def_name) {
|
||||
Some(name) => self.insert_ctrs_used(name, uses, adt_encoding),
|
||||
None => self.insert_used(def_name, used, uses, adt_encoding),
|
||||
},
|
||||
while let Some(term) = to_find.pop() {
|
||||
self.find_manual_adt_encoding(term, uses, adt_encoding);
|
||||
|
||||
Term::Lam { bod, .. } | Term::Chn { bod, .. } => {
|
||||
self.find_used_definitions(bod, used, uses, adt_encoding)
|
||||
}
|
||||
Term::Let { val: fst, nxt: snd, .. }
|
||||
| Term::Dup { val: fst, nxt: snd, .. }
|
||||
| Term::App { fun: fst, arg: snd, .. }
|
||||
| Term::Sup { fst, snd, .. }
|
||||
| Term::Tup { fst, snd }
|
||||
| Term::Opx { fst, snd, .. } => {
|
||||
self.find_used_definitions(fst, used, uses, adt_encoding);
|
||||
self.find_used_definitions(snd, used, uses, adt_encoding);
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
self.find_used_definitions(scrutinee, used, uses, adt_encoding);
|
||||
for (_, term) in arms {
|
||||
self.find_used_definitions(term, used, uses, adt_encoding);
|
||||
match term {
|
||||
Term::Ref { nam: def_name } => match self.ctrs.get(def_name) {
|
||||
Some(name) => self.insert_ctrs_used(name, uses, adt_encoding),
|
||||
None => self.insert_used(def_name, used, uses, adt_encoding),
|
||||
},
|
||||
|
||||
Term::Lam { bod, .. } | Term::Chn { bod, .. } => to_find.push(bod),
|
||||
Term::Let { val: fst, nxt: snd, .. }
|
||||
| Term::Dup { val: fst, nxt: snd, .. }
|
||||
| Term::App { fun: fst, arg: snd, .. }
|
||||
| Term::Sup { fst, snd, .. }
|
||||
| Term::Tup { fst, snd }
|
||||
| Term::Opx { fst, snd, .. } => {
|
||||
to_find.push(fst);
|
||||
to_find.push(snd);
|
||||
}
|
||||
}
|
||||
Term::Lst { els } => {
|
||||
self.insert_ctrs_used(&Name::new(LCONS), uses, adt_encoding);
|
||||
self.insert_ctrs_used(&Name::new(LNIL), uses, adt_encoding);
|
||||
for term in els {
|
||||
self.find_used_definitions(term, used, uses, adt_encoding);
|
||||
Term::Mat { matched, arms } => {
|
||||
to_find.push(matched);
|
||||
for (_, bod) in arms {
|
||||
to_find.push(bod);
|
||||
}
|
||||
}
|
||||
Term::Lst { els } => {
|
||||
self.insert_ctrs_used(&Name::new(LIST), uses, adt_encoding);
|
||||
for term in els {
|
||||
to_find.push(term);
|
||||
}
|
||||
}
|
||||
Term::Str { .. } => {
|
||||
self.insert_ctrs_used(&Name::new(STRING), uses, adt_encoding);
|
||||
}
|
||||
Term::Var { .. } | Term::Lnk { .. } | Term::Num { .. } | Term::Era | Term::Err => (),
|
||||
}
|
||||
Term::Str { .. } => {
|
||||
self.insert_ctrs_used(&Name::new(SCONS), uses, adt_encoding);
|
||||
self.insert_ctrs_used(&Name::new(SNIL), uses, adt_encoding);
|
||||
}
|
||||
Term::Var { .. } | Term::Lnk { .. } | Term::Num { .. } | Term::Era | Term::Err => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,76 +13,78 @@ impl Book {
|
||||
|
||||
impl Term {
|
||||
pub fn desugar_implicit_match_binds(&mut self, ctrs: &IndexMap<Name, Name>, adts: &IndexMap<Name, Adt>) {
|
||||
match self {
|
||||
Term::Mat { matched: scrutinee, .. } => {
|
||||
let scrutinee = if let Term::Var { nam } = scrutinee.as_ref() {
|
||||
nam.clone()
|
||||
} else {
|
||||
let Term::Mat { matched: scrutinee, arms } = std::mem::take(self) else { unreachable!() };
|
||||
let mut to_desugar = vec![self];
|
||||
|
||||
let nam = Name::new("%temp%scrutinee");
|
||||
while let Some(term) = to_desugar.pop() {
|
||||
match term {
|
||||
Term::Mat { matched, .. } => {
|
||||
let matched = if let Term::Var { nam } = matched.as_ref() {
|
||||
nam.clone()
|
||||
} else {
|
||||
let Term::Mat { matched, arms } = std::mem::take(term) else { unreachable!() };
|
||||
|
||||
*self = Term::Let {
|
||||
pat: Pattern::Var(Some(nam.clone())),
|
||||
val: scrutinee,
|
||||
nxt: Box::new(Term::Mat { matched: Box::new(Term::Var { nam: nam.clone() }), arms }),
|
||||
let nam = Name::new("%matched");
|
||||
|
||||
*term = Term::Let {
|
||||
pat: Pattern::Var(Some(nam.clone())),
|
||||
val: matched,
|
||||
nxt: Box::new(Term::Mat { matched: Box::new(Term::Var { nam: nam.clone() }), arms }),
|
||||
};
|
||||
|
||||
nam
|
||||
};
|
||||
|
||||
nam
|
||||
};
|
||||
let (Term::Mat { arms, .. } | Term::Let { nxt: box Term::Mat { arms, .. }, .. }) = term else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (Term::Mat { arms, .. } | Term::Let { nxt: box Term::Mat { arms, .. }, .. }) = self else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
for (pat, body) in arms {
|
||||
match pat {
|
||||
Pattern::Var(_) => (),
|
||||
Pattern::Ctr(nam, pat_args) => {
|
||||
let adt = ctrs.get(nam).unwrap();
|
||||
let Adt { ctrs, .. } = adts.get(adt).unwrap();
|
||||
let ctr_args = ctrs.get(nam).unwrap();
|
||||
if pat_args.is_empty() && !ctr_args.is_empty() {
|
||||
// Implicit ctr args
|
||||
*pat_args =
|
||||
ctr_args.iter().map(|x| Pattern::Var(Some(format!("{scrutinee}.{x}").into()))).collect();
|
||||
for (pat, body) in arms {
|
||||
match pat {
|
||||
Pattern::Var(_) => (),
|
||||
Pattern::Ctr(nam, pat_args) => {
|
||||
let adt = ctrs.get(nam).unwrap();
|
||||
let Adt { ctrs, .. } = adts.get(adt).unwrap();
|
||||
let ctr_args = ctrs.get(nam).unwrap();
|
||||
if pat_args.is_empty() && !ctr_args.is_empty() {
|
||||
// Implicit ctr args
|
||||
*pat_args =
|
||||
ctr_args.iter().map(|field| Pattern::Var(Some(format!("{matched}.{field}").into()))).collect();
|
||||
}
|
||||
}
|
||||
Pattern::Num(MatchNum::Zero) => (),
|
||||
Pattern::Num(MatchNum::Succ(Some(_))) => (),
|
||||
Pattern::Num(MatchNum::Succ(p @ None)) => {
|
||||
// Implicit num arg
|
||||
*p = Some(Some(format!("{matched}-1").into()));
|
||||
}
|
||||
Pattern::Tup(_, _) => (),
|
||||
Pattern::Lst(..) => unreachable!(),
|
||||
}
|
||||
Pattern::Num(MatchNum::Zero) => (),
|
||||
Pattern::Num(MatchNum::Succ(Some(_))) => (),
|
||||
Pattern::Num(MatchNum::Succ(p @ None)) => {
|
||||
// Implicit num arg
|
||||
*p = Some(Some(format!("{scrutinee}-1").into()));
|
||||
}
|
||||
Pattern::Tup(_, _) => (),
|
||||
Pattern::Lst(..) => unreachable!(),
|
||||
to_desugar.push(body);
|
||||
}
|
||||
body.desugar_implicit_match_binds(ctrs, adts);
|
||||
}
|
||||
Term::Let { pat: Pattern::Var(_), val: fst, nxt: snd }
|
||||
| Term::App { fun: fst, arg: snd, .. }
|
||||
| Term::Dup { val: fst, nxt: snd, .. }
|
||||
| Term::Tup { fst, snd }
|
||||
| Term::Sup { fst, snd, .. }
|
||||
| Term::Opx { fst, snd, .. } => {
|
||||
to_desugar.push(fst);
|
||||
to_desugar.push(snd);
|
||||
}
|
||||
Term::Lam { bod, .. } | Term::Chn { bod, .. } => to_desugar.push(bod),
|
||||
Term::Era
|
||||
| Term::Ref { .. }
|
||||
| Term::Num { .. }
|
||||
| Term::Str { .. }
|
||||
| Term::Lnk { .. }
|
||||
| Term::Var { .. }
|
||||
| Term::Err => (),
|
||||
Term::Let { pat: _, .. } => {
|
||||
unreachable!("Expected destructor let expressions to have been desugared already")
|
||||
}
|
||||
Term::Lst { .. } => unreachable!("Should have been desugared already"),
|
||||
}
|
||||
Term::Let { pat: Pattern::Var(_), val: fst, nxt: snd }
|
||||
| Term::App { fun: fst, arg: snd, .. }
|
||||
| Term::Dup { val: fst, nxt: snd, .. }
|
||||
| Term::Tup { fst, snd }
|
||||
| Term::Sup { fst, snd, .. }
|
||||
| Term::Opx { fst, snd, .. } => {
|
||||
fst.desugar_implicit_match_binds(ctrs, adts);
|
||||
snd.desugar_implicit_match_binds(ctrs, adts);
|
||||
}
|
||||
Term::Lam { bod, .. } | Term::Chn { bod, .. } => {
|
||||
bod.desugar_implicit_match_binds(ctrs, adts);
|
||||
}
|
||||
Term::Era
|
||||
| Term::Ref { .. }
|
||||
| Term::Num { .. }
|
||||
| Term::Str { .. }
|
||||
| Term::Lnk { .. }
|
||||
| Term::Var { .. }
|
||||
| Term::Err => (),
|
||||
Term::Let { pat: _, .. } => {
|
||||
unreachable!("Expected destructor let expressions to have been desugared already")
|
||||
}
|
||||
Term::Lst { .. } => unreachable!("Should have been desugared already"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ impl Term {
|
||||
fst.desugar_let_destructors();
|
||||
snd.desugar_let_destructors();
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
scrutinee.desugar_let_destructors();
|
||||
Term::Mat { matched, arms } => {
|
||||
matched.desugar_let_destructors();
|
||||
for (_, arm) in arms {
|
||||
arm.desugar_let_destructors();
|
||||
}
|
||||
|
@ -230,8 +230,8 @@ impl Term {
|
||||
|
||||
val_detach & nxt_detach
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
let mut detach = go(scrutinee, depth + 1, term_info);
|
||||
Term::Mat { matched, arms } => {
|
||||
let mut detach = go(matched, depth + 1, term_info);
|
||||
let parent_scope = term_info.replace_scope(HashSet::new());
|
||||
|
||||
for (pat, term) in arms {
|
||||
|
@ -320,8 +320,8 @@ fn normal_order_step(term: &mut Term) -> bool {
|
||||
_ => normal_order_step(fun) || normal_order_step(arg),
|
||||
}
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
if normal_order_step(scrutinee) {
|
||||
Term::Mat { matched, arms } => {
|
||||
if normal_order_step(matched) {
|
||||
return true;
|
||||
}
|
||||
for (_, arm) in arms {
|
||||
@ -401,8 +401,8 @@ fn subst_rule_body(term: &mut Term, subst_var: &Name, body: &Term, name_gen: &mu
|
||||
term.subst(subst_var, body);
|
||||
}
|
||||
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
subst_rule_body(scrutinee, subst_var, body, name_gen);
|
||||
Term::Mat { matched, arms } => {
|
||||
subst_rule_body(matched, subst_var, body, name_gen);
|
||||
for (_, arm) in arms {
|
||||
subst_rule_body(arm, subst_var, body, name_gen);
|
||||
}
|
||||
|
@ -54,8 +54,8 @@ impl Term {
|
||||
fst.eta_reduction();
|
||||
snd.eta_reduction();
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
scrutinee.eta_reduction();
|
||||
Term::Mat { matched, arms } => {
|
||||
matched.eta_reduction();
|
||||
for (pat, term) in arms {
|
||||
debug_assert!(pat.is_detached_num_match());
|
||||
term.eta_reduction();
|
||||
|
@ -8,55 +8,58 @@ impl Book {
|
||||
pub fn inline(&mut self) {
|
||||
let mut inlineables = HashSet::new();
|
||||
for (def_name, def) in self.defs.iter() {
|
||||
def.assert_no_pattern_matching_rules();
|
||||
if def.rules[0].body.is_inlineable() {
|
||||
if def.rule().body.is_inlineable() {
|
||||
inlineables.insert(def_name.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let defs = self.defs.clone();
|
||||
for def in self.defs.values_mut() {
|
||||
def.rules[0].body.inline(&inlineables, &defs);
|
||||
def.rule_mut().body.inline(&inlineables, &defs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Term {
|
||||
fn inline(&mut self, inlineables: &HashSet<Name>, defs: &IndexMap<Name, Definition>) {
|
||||
match self {
|
||||
Term::Ref { nam: def_name } => {
|
||||
if inlineables.contains(def_name) {
|
||||
*self = defs.get(def_name).unwrap().rules[0].body.clone();
|
||||
let mut to_inline = vec![self];
|
||||
|
||||
while let Some(term) = to_inline.pop() {
|
||||
match term {
|
||||
Term::Ref { nam: def_name } => {
|
||||
if inlineables.contains(def_name) {
|
||||
*term = defs.get(def_name).unwrap().rule().body.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Term::Lam { bod, .. } => bod.inline(inlineables, defs),
|
||||
Term::Lam { bod, .. } => to_inline.push(bod),
|
||||
|
||||
Term::App { fun: fst, arg: snd, .. }
|
||||
| Term::Dup { val: fst, nxt: snd, .. }
|
||||
| Term::Opx { fst, snd, .. }
|
||||
| Term::Sup { fst, snd, .. }
|
||||
| Term::Tup { fst, snd } => {
|
||||
fst.inline(inlineables, defs);
|
||||
snd.inline(inlineables, defs);
|
||||
}
|
||||
|
||||
Term::Mat { arms, .. } => {
|
||||
for (_, bod) in arms {
|
||||
bod.inline(inlineables, defs);
|
||||
Term::App { fun: fst, arg: snd, .. }
|
||||
| Term::Dup { val: fst, nxt: snd, .. }
|
||||
| Term::Opx { fst, snd, .. }
|
||||
| Term::Sup { fst, snd, .. }
|
||||
| Term::Tup { fst, snd } => {
|
||||
to_inline.push(fst);
|
||||
to_inline.push(snd);
|
||||
}
|
||||
|
||||
Term::Mat { arms, .. } => {
|
||||
for (_, bod) in arms {
|
||||
to_inline.push(bod);
|
||||
}
|
||||
}
|
||||
|
||||
Term::Var { .. }
|
||||
| Term::Chn { .. }
|
||||
| Term::Lnk { .. }
|
||||
| Term::Let { .. }
|
||||
| Term::Num { .. }
|
||||
| Term::Str { .. }
|
||||
| Term::Lst { .. }
|
||||
| Term::Era => {}
|
||||
|
||||
Term::Err => unreachable!(),
|
||||
}
|
||||
|
||||
Term::Var { .. }
|
||||
| Term::Chn { .. }
|
||||
| Term::Lnk { .. }
|
||||
| Term::Let { .. }
|
||||
| Term::Num { .. }
|
||||
| Term::Str { .. }
|
||||
| Term::Lst { .. }
|
||||
| Term::Era => {}
|
||||
|
||||
Term::Err => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,8 +70,8 @@ fn count_var_uses_in_term(term: &Term, uses: &mut HashMap<Name, Val>) {
|
||||
count_var_uses_in_term(fst, uses);
|
||||
count_var_uses_in_term(snd, uses);
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
count_var_uses_in_term(scrutinee, uses);
|
||||
Term::Mat { matched, arms } => {
|
||||
count_var_uses_in_term(matched, uses);
|
||||
for (rule, term) in arms {
|
||||
if let Pattern::Num(MatchNum::Succ(Some(nam))) = rule {
|
||||
add_var(nam.as_ref(), uses);
|
||||
@ -211,8 +211,8 @@ fn term_to_affine(
|
||||
term_to_affine(fst, var_uses, inst_count, let_bodies);
|
||||
term_to_affine(snd, var_uses, inst_count, let_bodies);
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
term_to_affine(scrutinee, var_uses, inst_count, let_bodies);
|
||||
Term::Mat { matched, arms } => {
|
||||
term_to_affine(matched, var_uses, inst_count, let_bodies);
|
||||
for (rule, term) in arms {
|
||||
match rule {
|
||||
Pattern::Num(MatchNum::Succ(Some(nam))) => {
|
||||
|
@ -20,22 +20,26 @@ impl Book {
|
||||
|
||||
impl Pattern {
|
||||
pub fn resolve_ctrs(&mut self, is_ctr: &impl Fn(&Name) -> bool) {
|
||||
match self {
|
||||
Pattern::Var(Some(nam)) => {
|
||||
if is_ctr(nam) {
|
||||
*self = Pattern::Ctr(nam.clone(), vec![]);
|
||||
let mut to_resolve = vec![self];
|
||||
|
||||
while let Some(pat) = to_resolve.pop() {
|
||||
match pat {
|
||||
Pattern::Var(Some(nam)) => {
|
||||
if is_ctr(nam) {
|
||||
*pat = Pattern::Ctr(nam.clone(), vec![]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Pattern::Ctr(_, args) | Pattern::Lst(args) => {
|
||||
for arg in args {
|
||||
arg.resolve_ctrs(is_ctr);
|
||||
Pattern::Ctr(_, args) | Pattern::Lst(args) => {
|
||||
for arg in args {
|
||||
to_resolve.push(arg);
|
||||
}
|
||||
}
|
||||
Pattern::Var(None) => (),
|
||||
Pattern::Num(_) => (),
|
||||
Pattern::Tup(fst, snd) => {
|
||||
to_resolve.push(fst);
|
||||
to_resolve.push(snd);
|
||||
}
|
||||
}
|
||||
Pattern::Var(None) => (),
|
||||
Pattern::Num(_) => (),
|
||||
Pattern::Tup(fst, snd) => {
|
||||
fst.resolve_ctrs(is_ctr);
|
||||
snd.resolve_ctrs(is_ctr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -43,36 +47,40 @@ impl Pattern {
|
||||
|
||||
impl Term {
|
||||
pub fn resolve_ctrs_in_pats(&mut self, is_ctr: &impl Fn(&Name) -> bool) {
|
||||
match self {
|
||||
Term::Let { pat, val, nxt } => {
|
||||
pat.resolve_ctrs(is_ctr);
|
||||
val.resolve_ctrs_in_pats(is_ctr);
|
||||
nxt.resolve_ctrs_in_pats(is_ctr);
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
scrutinee.resolve_ctrs_in_pats(is_ctr);
|
||||
for (pat, body) in arms {
|
||||
let mut to_resolve = vec![self];
|
||||
|
||||
while let Some(pat) = to_resolve.pop() {
|
||||
match pat {
|
||||
Term::Let { pat, val, nxt } => {
|
||||
pat.resolve_ctrs(is_ctr);
|
||||
body.resolve_ctrs_in_pats(is_ctr);
|
||||
to_resolve.push(val);
|
||||
to_resolve.push(nxt);
|
||||
}
|
||||
Term::Mat { matched, arms } => {
|
||||
to_resolve.push(matched);
|
||||
for (pat, body) in arms {
|
||||
pat.resolve_ctrs(is_ctr);
|
||||
to_resolve.push(body);
|
||||
}
|
||||
}
|
||||
Term::App { fun: fst, arg: snd, .. }
|
||||
| Term::Tup { fst, snd }
|
||||
| Term::Dup { val: fst, nxt: snd, .. }
|
||||
| Term::Sup { fst, snd, .. }
|
||||
| Term::Opx { fst, snd, .. } => {
|
||||
to_resolve.push(fst);
|
||||
to_resolve.push(snd);
|
||||
}
|
||||
Term::Lam { bod, .. } | Term::Chn { bod, .. } => to_resolve.push(bod),
|
||||
Term::Var { .. }
|
||||
| Term::Lnk { .. }
|
||||
| Term::Ref { .. }
|
||||
| Term::Num { .. }
|
||||
| Term::Str { .. }
|
||||
| Term::Lst { .. }
|
||||
| Term::Era
|
||||
| Term::Err => (),
|
||||
}
|
||||
Term::App { fun: fst, arg: snd, .. }
|
||||
| Term::Tup { fst, snd }
|
||||
| Term::Dup { val: fst, nxt: snd, .. }
|
||||
| Term::Sup { fst, snd, .. }
|
||||
| Term::Opx { fst, snd, .. } => {
|
||||
fst.resolve_ctrs_in_pats(is_ctr);
|
||||
snd.resolve_ctrs_in_pats(is_ctr);
|
||||
}
|
||||
Term::Lam { bod, .. } | Term::Chn { bod, .. } => bod.resolve_ctrs_in_pats(is_ctr),
|
||||
Term::Var { .. }
|
||||
| Term::Lnk { .. }
|
||||
| Term::Ref { .. }
|
||||
| Term::Num { .. }
|
||||
| Term::Str { .. }
|
||||
| Term::Lst { .. }
|
||||
| Term::Era
|
||||
| Term::Err => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,8 +86,8 @@ impl Term {
|
||||
fst.resolve_refs(def_names, scope)?;
|
||||
snd.resolve_refs(def_names, scope)?;
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
scrutinee.resolve_refs(def_names, scope)?;
|
||||
Term::Mat { matched, arms } => {
|
||||
matched.resolve_refs(def_names, scope)?;
|
||||
for (pat, term) in arms {
|
||||
let nam = if let Pattern::Num(MatchNum::Succ(Some(nam))) = pat { nam.as_ref() } else { None };
|
||||
push_scope(nam, scope);
|
||||
|
@ -41,8 +41,8 @@ impl Term {
|
||||
fst.resugar_tagged_scott(book, errs);
|
||||
snd.resugar_tagged_scott(book, errs);
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
scrutinee.resugar_tagged_scott(book, errs);
|
||||
Term::Mat { matched, arms } => {
|
||||
matched.resugar_tagged_scott(book, errs);
|
||||
for (_, arm) in arms {
|
||||
arm.resugar_tagged_scott(book, errs);
|
||||
}
|
||||
@ -220,9 +220,9 @@ impl Term {
|
||||
}
|
||||
}
|
||||
|
||||
let scrutinee = Box::new(std::mem::take(cur));
|
||||
let matched = Box::new(std::mem::take(cur));
|
||||
let arms = arms.into_iter().rev().map(|(pat, term)| (pat, std::mem::take(term))).collect();
|
||||
*self = Term::Mat { matched: scrutinee, arms };
|
||||
*self = Term::Mat { matched, arms };
|
||||
|
||||
self.resugar_tagged_scott(book, errs);
|
||||
}
|
||||
|
@ -38,8 +38,8 @@ impl Term {
|
||||
// (SNil)
|
||||
Term::Ref { nam: def_name } if def_name.as_str() == SNIL => *self = Term::Str { val: String::new() },
|
||||
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
scrutinee.resugar_strings();
|
||||
Term::Mat { matched, arms } => {
|
||||
matched.resugar_strings();
|
||||
for (_, arm) in arms {
|
||||
arm.resugar_strings();
|
||||
}
|
||||
|
@ -56,8 +56,8 @@ pub fn subst_ref_to_ref(term: &mut Term, ref_map: &BTreeMap<Name, Name>) -> bool
|
||||
let snd_subst = subst_ref_to_ref(snd, ref_map);
|
||||
fst_subst | snd_subst
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
let mut subst = subst_ref_to_ref(scrutinee, ref_map);
|
||||
Term::Mat { matched, arms } => {
|
||||
let mut subst = subst_ref_to_ref(matched, ref_map);
|
||||
for (_, term) in arms {
|
||||
subst |= subst_ref_to_ref(term, ref_map);
|
||||
}
|
||||
|
@ -61,8 +61,8 @@ impl UniqueNameGenerator {
|
||||
*snd = self.pop(snd.as_ref());
|
||||
*fst = self.pop(fst.as_ref());
|
||||
}
|
||||
Term::Mat { matched: scrutinee, arms } => {
|
||||
self.unique_names_in_term(scrutinee);
|
||||
Term::Mat { matched, arms } => {
|
||||
self.unique_names_in_term(matched);
|
||||
for (pat, term) in arms {
|
||||
pat.names().for_each(|nam| self.push(Some(nam)));
|
||||
self.unique_names_in_term(term);
|
||||
|
@ -3,9 +3,9 @@ source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/encode_pattern_match/match_adt_unscoped_var.hvm
|
||||
---
|
||||
TaggedScott:
|
||||
(Foo) = λ$x let %temp%scrutinee = (Some 1); (Bar$match$1_$_Foo$match$1 %temp%scrutinee $x)
|
||||
(Foo) = λ$x let %matched = (Some 1); (Bar$match$1_$_Foo$match$1 %matched $x)
|
||||
|
||||
(Bar) = (let %temp%scrutinee = (Some 1); (Bar$match$1_$_Foo$match$1 %temp%scrutinee $x) λ$x *)
|
||||
(Bar) = (let %matched = (Some 1); (Bar$match$1_$_Foo$match$1 %matched $x) λ$x *)
|
||||
|
||||
(main) = *
|
||||
|
||||
@ -16,9 +16,9 @@ TaggedScott:
|
||||
(Some) = λval #Maybe λNone #Maybe λSome #Maybe.Some.val (Some val)
|
||||
|
||||
Scott:
|
||||
(Foo) = λ$x let %temp%scrutinee = (Some 1); (Bar$match$1_$_Foo$match$1 %temp%scrutinee $x)
|
||||
(Foo) = λ$x let %matched = (Some 1); (Bar$match$1_$_Foo$match$1 %matched $x)
|
||||
|
||||
(Bar) = (let %temp%scrutinee = (Some 1); (Bar$match$1_$_Foo$match$1 %temp%scrutinee $x) λ$x *)
|
||||
(Bar) = (let %matched = (Some 1); (Bar$match$1_$_Foo$match$1 %matched $x) λ$x *)
|
||||
|
||||
(main) = *
|
||||
|
||||
|
@ -3,7 +3,7 @@ source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/encode_pattern_match/match_list_sugar.hvm
|
||||
---
|
||||
TaggedScott:
|
||||
(main) = let %temp%scrutinee = LNil; (main$match$1 %temp%scrutinee)
|
||||
(main) = let %matched = LNil; (main$match$1 %matched)
|
||||
|
||||
(main$match$1) = λa #List (a #List.LCons.head λb #List.LCons.tail λc 1 0)
|
||||
|
||||
@ -12,7 +12,7 @@ TaggedScott:
|
||||
(LCons) = λhead λtail #List λLCons #List λLNil #List.LCons.tail (#List.LCons.head (LCons head) tail)
|
||||
|
||||
Scott:
|
||||
(main) = let %temp%scrutinee = LNil; (main$match$1 %temp%scrutinee)
|
||||
(main) = let %matched = LNil; (main$match$1 %matched)
|
||||
|
||||
(main$match$1) = λa (a λb λc 1 0)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user