mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-11-05 04:51:40 +03:00
Add merge definitions pass
This commit is contained in:
parent
1b932afeba
commit
a1a90486c5
26
src/lib.rs
26
src/lib.rs
@ -41,10 +41,7 @@ pub fn compile_book(book: &mut Book, opts: Opts) -> Result<CompileResult, String
|
||||
Ok(CompileResult { core_book, hvmc_names, labels, warnings })
|
||||
}
|
||||
|
||||
pub fn desugar_book(
|
||||
book: &mut Book,
|
||||
Opts { eta, ref_to_ref, prune, supercombinators, simplify_main, .. }: Opts,
|
||||
) -> Result<(DefId, Vec<Warning>), String> {
|
||||
pub fn desugar_book(book: &mut Book, opts: Opts) -> Result<(DefId, Vec<Warning>), String> {
|
||||
let mut warnings = Vec::new();
|
||||
let main = book.check_has_main()?;
|
||||
book.check_shared_names()?;
|
||||
@ -57,19 +54,22 @@ pub fn desugar_book(
|
||||
book.check_unbound_vars()?;
|
||||
book.make_var_names_unique();
|
||||
book.linearize_vars();
|
||||
book.eta_reduction(eta);
|
||||
book.eta_reduction(opts.eta);
|
||||
// sanity check
|
||||
book.check_unbound_vars()?;
|
||||
if supercombinators {
|
||||
if opts.supercombinators {
|
||||
book.detach_supercombinators(main);
|
||||
}
|
||||
if ref_to_ref {
|
||||
if opts.ref_to_ref {
|
||||
book.simplify_ref_to_ref()?;
|
||||
}
|
||||
if simplify_main {
|
||||
if opts.simplify_main {
|
||||
book.simplify_main_ref(main);
|
||||
}
|
||||
book.prune(Some(main), prune, &mut warnings);
|
||||
if opts.merge_definitions {
|
||||
book.merge_definition(main);
|
||||
}
|
||||
book.prune(Some(main), opts.prune, &mut warnings);
|
||||
Ok((main, warnings))
|
||||
}
|
||||
|
||||
@ -190,8 +190,11 @@ pub struct Opts {
|
||||
/// Enables [term::transform::simplify_main_ref].
|
||||
pub simplify_main: bool,
|
||||
|
||||
/// Enables dereferences in `pre_reduce` pass.
|
||||
/// Enables dereferences in [hvmc_net::pre_reduce] pass.
|
||||
pub pre_reduce_refs: bool,
|
||||
|
||||
/// Enables [term::transform::definition_merge]
|
||||
pub merge_definitions: bool,
|
||||
}
|
||||
|
||||
impl Opts {
|
||||
@ -205,6 +208,7 @@ impl Opts {
|
||||
supercombinators: true,
|
||||
simplify_main: true,
|
||||
pre_reduce_refs: true,
|
||||
merge_definitions: true,
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,6 +238,8 @@ impl Opts {
|
||||
"no-simplify-main" => self.simplify_main = false,
|
||||
"pre-reduce-refs" => self.pre_reduce_refs = true,
|
||||
"no-pre-reduce-refs" => self.pre_reduce_refs = false,
|
||||
"merge-defnitions" => self.merge_definitions = true,
|
||||
"no-merge-defnitions" => self.merge_definitions = false,
|
||||
other => return Err(format!("Unknown option '{other}'.")),
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ struct Args {
|
||||
all, eta, no-eta, prune, no-prune, ref-to-ref, no-ref-to-ref,
|
||||
supercombinators (enabled by default), no-supercombinators,
|
||||
simplify-main, no-simplify-main, pre-reduce-refs, no-pre-reduce-refs
|
||||
merge-definitions, no-merge-definitions
|
||||
"#,
|
||||
)]
|
||||
pub opts: Vec<String>,
|
||||
|
@ -34,8 +34,8 @@ pub struct Book {
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct DefNames {
|
||||
id_to_name: IndexMap<DefId, Name>,
|
||||
name_to_id: IndexMap<Name, DefId>,
|
||||
pub id_to_name: IndexMap<DefId, Name>,
|
||||
pub name_to_id: IndexMap<Name, DefId>,
|
||||
id_count: DefId,
|
||||
}
|
||||
|
||||
@ -63,13 +63,13 @@ pub enum Origin {
|
||||
Generated,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum MatchNum {
|
||||
Zero,
|
||||
Succ(Option<Option<Name>>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Tag {
|
||||
Named(Name),
|
||||
Numeric(u32),
|
||||
@ -77,7 +77,7 @@ pub enum Tag {
|
||||
Static,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
|
||||
pub enum Term {
|
||||
Lam {
|
||||
tag: Tag,
|
||||
@ -149,7 +149,7 @@ pub enum Term {
|
||||
Era,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Pattern {
|
||||
Var(Option<Name>),
|
||||
Ctr(Name, Vec<Pattern>),
|
||||
@ -158,7 +158,7 @@ pub enum Pattern {
|
||||
List(Vec<Pattern>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Op {
|
||||
ADD,
|
||||
SUB,
|
||||
|
48
src/term/transform/definition_merge.rs
Normal file
48
src/term/transform/definition_merge.rs
Normal file
@ -0,0 +1,48 @@
|
||||
use super::simplify_ref_to_ref::subst_ref_to_ref;
|
||||
use crate::term::{Book, DefId, Name, Term};
|
||||
use std::collections::HashMap;
|
||||
|
||||
impl Book {
|
||||
/// Merges definitions that have the same structure into one definintion.
|
||||
/// Expects variables to be linear.
|
||||
pub fn merge_definition(&mut self, main: DefId) {
|
||||
let mut term_to_defid: HashMap<Term, DefId> = HashMap::new();
|
||||
let mut defid_map: HashMap<DefId, DefId> = HashMap::new();
|
||||
|
||||
for (id, def) in &mut self.defs {
|
||||
if id == &main {
|
||||
continue;
|
||||
}
|
||||
|
||||
def.assert_no_pattern_matching_rules();
|
||||
let term = std::mem::take(&mut def.rules[0].body);
|
||||
|
||||
if let Some(new) = term_to_defid.get(&term) {
|
||||
defid_map.insert(*id, *new);
|
||||
} else {
|
||||
term_to_defid.insert(term, *id);
|
||||
}
|
||||
}
|
||||
|
||||
for (term, id) in term_to_defid {
|
||||
self.defs.get_mut(&id).unwrap().rules[0].body = term;
|
||||
}
|
||||
|
||||
for (old, new) in &defid_map {
|
||||
let old_name = self.def_names.id_to_name.remove(old).unwrap();
|
||||
let new_name = self.def_names.name(new).unwrap();
|
||||
|
||||
let merged_name = Name(format!("{}${}", new_name, old_name));
|
||||
|
||||
self.def_names.id_to_name.insert(*new, merged_name.clone());
|
||||
self.def_names.name_to_id.insert(merged_name, *new);
|
||||
|
||||
self.def_names.name_to_id.remove(&old_name);
|
||||
self.defs.remove(old);
|
||||
}
|
||||
|
||||
for def in self.defs.values_mut() {
|
||||
subst_ref_to_ref(&mut def.rules[0].body, &defid_map);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
pub mod definition_merge;
|
||||
pub mod definition_pruning;
|
||||
pub mod desugar_implicit_match_binds;
|
||||
pub mod desugar_let_destructors;
|
||||
|
@ -43,7 +43,7 @@ impl Book {
|
||||
}
|
||||
}
|
||||
|
||||
fn subst_ref_to_ref(term: &mut Term, ref_map: &HashMap<DefId, DefId>) {
|
||||
pub fn subst_ref_to_ref(term: &mut Term, ref_map: &HashMap<DefId, DefId>) {
|
||||
match term {
|
||||
Term::Ref { def_id } => {
|
||||
if let Some(target_id) = ref_map.get(def_id) {
|
||||
|
@ -0,0 +1,6 @@
|
||||
true = @t @f t
|
||||
false = @t @f f
|
||||
fst = @a @b a
|
||||
snd = @a @b b
|
||||
|
||||
main = @* (fst true (snd false *))
|
@ -2,10 +2,9 @@
|
||||
source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_file_o_all/adt_option_and.hvm
|
||||
---
|
||||
@A = ({2 @H {2 @G a}} a)
|
||||
@A = ({2 @H {2 @C a}} a)
|
||||
@C = (* @None)
|
||||
@D = {4 a (b {2 {4 [b a] c} {2 * c}})}
|
||||
@G = (* @None)
|
||||
@H = {4 a ({2 @D {2 @C (a b)}} b)}
|
||||
@None = {2 * {2 a a}}
|
||||
@Some = (a {2 {4 a b} {2 * b}})
|
||||
|
@ -2,9 +2,9 @@
|
||||
source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_file_o_all/ex0.hvm
|
||||
---
|
||||
@1 = (* (a a))
|
||||
@C_2 = ({3 (a b) (c a)} (c b))
|
||||
@S = (a ((a b) (* b)))
|
||||
@Z = (* (a a))
|
||||
@main = a
|
||||
& @C_2 ~ (@S (@Z a))
|
||||
& @C_2 ~ (@S (@1 a))
|
||||
|
||||
|
@ -0,0 +1,10 @@
|
||||
---
|
||||
source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_file_o_all/merge_definitions.hvm
|
||||
---
|
||||
@1 = (a (* a))
|
||||
@2 = (* (a a))
|
||||
@main = (* a)
|
||||
& @1 ~ (@1 (b a))
|
||||
& @2 ~ (@2 (* b))
|
||||
|
@ -4,8 +4,7 @@ input_file: tests/golden_tests/compile_file_o_all/nested_adt_match.hvm
|
||||
---
|
||||
@8 = ({2 @C {2 @A a}} a)
|
||||
@A = #0
|
||||
@C = {4 {2 @G {2 @E a}} a}
|
||||
@E = #0
|
||||
@C = {4 {2 @G {2 @A a}} a}
|
||||
@G = {4 a a}
|
||||
@Some = (a {2 {4 a b} {2 * b}})
|
||||
@main = a
|
||||
|
@ -2,9 +2,8 @@
|
||||
source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_file_o_all/tagged_sup.hvm
|
||||
---
|
||||
@a = {3 (a a) (b b)}
|
||||
@b = {3 (a a) (b b)}
|
||||
@1 = {3 (a a) (b b)}
|
||||
@c = {5 (a a) (b b)}
|
||||
@main = a
|
||||
& @a ~ (@b (@c a))
|
||||
& @1 ~ (@1 (@c a))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user