[sc-653] Reorder compiled redexes recursive last

This commit is contained in:
Nicolas Abril 2024-05-02 16:53:16 +02:00
parent bd6b4c129a
commit 1313a73aa1
28 changed files with 266 additions and 157 deletions

View File

@ -15,6 +15,7 @@
"combinators",
"concat",
"ctrs",
"cuda",
"Dall",
"datatypes",
"Deque",

View File

@ -235,15 +235,6 @@ impl DiagnosticsConfig {
}
}
pub fn default_strict() -> Self {
// TODO: Pre-reduce recursion check disabled while execution not implemented for hvm32
Self { recursion_cycle: Severity::Error, ..Self::default() }
}
pub fn default_lazy() -> Self {
Self { recursion_cycle: Severity::Allow, ..Self::default() }
}
pub fn warning_severity(&self, warn: WarningType) -> Severity {
match warn {
WarningType::UnusedDefinition => self.unused_definition,
@ -258,7 +249,9 @@ impl DiagnosticsConfig {
impl Default for DiagnosticsConfig {
fn default() -> Self {
Self::new(Severity::Warning, false)
let mut cfg = Self::new(Severity::Warning, false);
cfg.recursion_cycle = Severity::Error;
cfg
}
}

View File

@ -1,2 +1,3 @@
pub mod check_net_size;
pub mod mutual_recursion;
pub mod reorder_redexes;

View File

@ -1,5 +1,6 @@
use crate::{
diagnostics::{Diagnostics, WarningType, ERR_INDENT_SIZE},
maybe_grow,
term::transform::definition_merge::MERGE_SEPARATOR,
};
use hvmc::ast::{Book, Tree};
@ -101,8 +102,9 @@ impl Graph {
}
}
/// Collect active refs from the tree.
fn collect_refs(current: Ref, tree: &Tree, graph: &mut Graph) {
match tree {
maybe_grow(|| match tree {
Tree::Ref { nam } => graph.add(current, nam.clone()),
Tree::Ctr { ports, .. } => {
if let Some(last) = ports.last() {
@ -114,7 +116,7 @@ fn collect_refs(current: Ref, tree: &Tree, graph: &mut Graph) {
collect_refs(current.clone(), subtree, graph);
}
}
}
});
}
impl From<&Book> for Graph {
@ -122,13 +124,17 @@ impl From<&Book> for Graph {
let mut graph = Self::new();
for (r#ref, net) in book.iter() {
// Collect active refs from root.
// Collect active refs from the root.
collect_refs(r#ref.clone(), &net.root, &mut graph);
for (left, _) in net.redexes.iter() {
// If left is an active reference, add to the graph.
// Collect active refs from redexes.
for (left, right) in net.redexes.iter() {
if let Tree::Ref { nam } = left {
graph.add(r#ref.clone(), nam.clone());
}
if let Tree::Ref { nam } = right {
graph.add(r#ref.clone(), nam.clone());
}
}
}

View File

@ -0,0 +1,120 @@
use hvmc::ast::{Book, Net, Tree};
use std::collections::{HashMap, HashSet};
use crate::maybe_grow;
/// Reorder redexes in the book to have more efficient execution.
///
/// Especially for hvm-cuda, we want to keep the number of nodes/vars/redexes
/// low so we put redexes with recursive refs last (at the bottom of the stack).
pub fn reorder_redexes_recursive_last(book: &mut Book) {
// Direct dependencies
let deps = book.iter().map(|(nam, net)| (nam.clone(), dependencies(net))).collect::<HashMap<_, _>>();
// Look at dependencies to find if recursive
let recursive_nets = cycles(&deps).into_iter().flatten().collect::<HashSet<_>>();
for net in book.values_mut() {
reorder_redexes_net(net, &recursive_nets);
}
}
/// Reorder redexes to have recursive last (bottom of the stack).
fn reorder_redexes_net(net: &mut Net, recursive_nets: &HashSet<String>) {
let mut recursive_redexes = vec![];
let mut non_recursive_redexes = vec![];
for (a, b) in std::mem::take(&mut net.redexes) {
if tree_has_recursive(&a, recursive_nets) || tree_has_recursive(&b, recursive_nets) {
recursive_redexes.push((a, b));
} else {
non_recursive_redexes.push((a, b));
}
}
let mut redexes = recursive_redexes;
redexes.append(&mut non_recursive_redexes);
net.redexes = redexes;
}
/// Whether a tree has a reference to a recursive net or not.
fn tree_has_recursive(tree: &Tree, recursive_nets: &HashSet<String>) -> bool {
maybe_grow(|| {
if let Tree::Ref { nam } = tree {
recursive_nets.contains(nam)
} else {
for child in tree.children() {
if tree_has_recursive(child, recursive_nets) {
return true;
}
}
false
}
})
}
type DepGraph = HashMap<String, HashSet<String>>;
type Cycles = Vec<Vec<String>>;
/// Find all cycles in the dependency graph.
pub fn cycles(deps: &DepGraph) -> Cycles {
let mut cycles = vec![];
let mut stack = vec![];
let mut visited = HashSet::new();
for nam in deps.keys() {
if !visited.contains(nam) {
find_cycles(deps, nam, &mut visited, &mut stack, &mut cycles);
}
}
cycles
}
fn find_cycles(
deps: &DepGraph,
nam: &String,
visited: &mut HashSet<String>,
stack: &mut Vec<String>,
cycles: &mut Cycles,
) {
maybe_grow(|| {
// Check if the current ref is already in the stack, which indicates a cycle.
if let Some(cycle_start) = stack.iter().position(|n| n == nam) {
// If found, add the cycle to the cycles vector.
cycles.push(stack[cycle_start ..].to_vec());
return;
}
// If the ref has not been visited yet, mark it as visited.
if visited.insert(nam.clone()) {
// Add the current ref to the stack to keep track of the path.
stack.push(nam.clone());
// Get the dependencies of the current ref.
if let Some(dependencies) = deps.get(nam) {
// Search for cycles from each dependency.
for dep in dependencies {
find_cycles(deps, dep, visited, stack, cycles);
}
}
stack.pop();
}
})
}
/// Gather the set of net that this net directly depends on (has a ref in the net).
fn dependencies(net: &Net) -> HashSet<String> {
let mut deps = HashSet::new();
dependencies_tree(&net.root, &mut deps);
for (a, b) in &net.redexes {
dependencies_tree(a, &mut deps);
dependencies_tree(b, &mut deps);
}
deps
}
fn dependencies_tree(tree: &Tree, deps: &mut HashSet<String>) {
if let Tree::Ref { nam } = tree {
deps.insert(nam.clone());
} else {
for subtree in tree.children() {
dependencies_tree(subtree, deps);
}
}
}

View File

@ -6,6 +6,7 @@ use hvmc::ast::Net;
use hvmc_net::{
check_net_size::{check_net_sizes, MAX_NET_SIZE},
mutual_recursion,
reorder_redexes::reorder_redexes_recursive_last,
};
use net::hvmc_to_net::hvmc_to_net;
use std::{process::Output, str::FromStr};
@ -38,6 +39,7 @@ pub fn compile_book(
args: Option<Vec<Term>>,
) -> Result<CompileResult, Diagnostics> {
let mut diagnostics = desugar_book(book, opts.clone(), diagnostics_cfg, args)?;
let (mut core_book, labels) = book_to_nets(book, &mut diagnostics)?;
if opts.eta {
@ -45,7 +47,6 @@ pub fn compile_book(
}
mutual_recursion::check_cycles(&core_book, &mut diagnostics)?;
if opts.eta {
core_book.values_mut().for_each(Net::eta_reduce);
}
@ -65,6 +66,10 @@ pub fn compile_book(
check_net_sizes(&core_book, &mut diagnostics)?;
if opts.recursive_last {
reorder_redexes_recursive_last(&mut core_book);
}
Ok(CompileResult { core_book, labels, diagnostics })
}
@ -103,8 +108,8 @@ pub fn desugar_book(
// Auto match linearization
match opts.linearize_matches {
OptLevel::Disabled => (),
OptLevel::Enabled => ctx.book.linearize_match_binds(),
OptLevel::Extra => ctx.book.linearize_matches(),
OptLevel::Alt => ctx.book.linearize_match_binds(),
OptLevel::Enabled => ctx.book.linearize_matches(),
}
// Manual match linearization
ctx.book.linearize_match_with();
@ -175,7 +180,7 @@ pub fn run_book(
return Err(format!("Error reading result from hvm. Output :\n{}{}{}", err, status, out).into());
};
let (term, diags) = readback_hvm_net(&net, &book, &labels, run_opts.linear);
let (term, diags) = readback_hvm_net(&net, &book, &labels, run_opts.linear_readback);
Ok((term, stats.to_string(), diags))
}
@ -189,23 +194,16 @@ pub fn readback_hvm_net(net: &Net, book: &Book, labels: &Labels, linear: bool) -
#[derive(Clone, Copy, Debug, Default)]
pub struct RunOpts {
pub linear: bool,
pub lazy_mode: bool,
pub linear_readback: bool,
pub pretty: bool,
}
impl RunOpts {
pub fn lazy() -> Self {
Self { lazy_mode: true, ..Self::default() }
}
}
#[derive(Clone, Copy, Debug, Default)]
pub enum OptLevel {
#[default]
Disabled,
#[default]
Enabled,
Extra,
Alt,
}
impl OptLevel {
@ -214,7 +212,7 @@ impl OptLevel {
}
pub fn is_extra(&self) -> bool {
matches!(self, OptLevel::Extra)
matches!(self, OptLevel::Enabled)
}
}
@ -237,6 +235,9 @@ pub struct CompileOpts {
/// Enables [term::transform::inline].
pub inline: bool,
/// Enables [hvmc_net::reorder_redexes::reorder_redexes_recursive_last].
pub recursive_last: bool,
}
impl CompileOpts {
@ -249,24 +250,23 @@ impl CompileOpts {
float_combinators: true,
merge: true,
inline: true,
linearize_matches: OptLevel::Extra,
recursive_last: true,
linearize_matches: OptLevel::Enabled,
}
}
/// Set all opts as false and keep the current adt encoding.
#[must_use]
pub fn set_no_all(self) -> Self {
Self::default()
}
/// All optimizations disabled, except float_combinators and linearize_matches
pub fn default_strict() -> Self {
Self { float_combinators: true, linearize_matches: OptLevel::Extra, eta: true, ..Self::default() }
}
// Disable optimizations that don't work or are unnecessary on lazy mode
pub fn default_lazy() -> Self {
Self::default()
Self {
eta: false,
prune: false,
linearize_matches: OptLevel::Disabled,
float_combinators: false,
merge: false,
inline: false,
recursive_last: false,
}
}
pub fn check_for_strict(&self) {
@ -284,14 +284,16 @@ impl CompileOpts {
}
impl Default for CompileOpts {
/// Enables eta, linearize_matches, float_combinators and reorder_redexes_recursive_last.
fn default() -> Self {
Self {
eta: false,
eta: true,
prune: false,
linearize_matches: OptLevel::Enabled,
float_combinators: false,
float_combinators: true,
merge: false,
inline: false,
recursive_last: true,
}
}
}

View File

@ -34,9 +34,6 @@ enum Mode {
)]
comp_opts: Vec<OptArgs>,
#[arg(short = 'L', help = "Lazy mode")]
lazy_mode: bool,
#[command(flatten)]
warn_opts: CliWarnOpts,
@ -54,9 +51,6 @@ enum Mode {
)]
comp_opts: Vec<OptArgs>,
#[arg(short = 'L', help = "Lazy mode")]
lazy_mode: bool,
#[command(flatten)]
warn_opts: CliWarnOpts,
@ -65,9 +59,6 @@ enum Mode {
},
/// Compiles the program and runs it with the hvm.
Run {
#[arg(short = 'L', help = "Lazy mode")]
lazy_mode: bool,
#[arg(short = 'p', help = "Debug and normalization pretty printing")]
pretty: bool,
@ -106,9 +97,6 @@ enum Mode {
#[arg(short = 'p', help = "Debug and normalization pretty printing")]
pretty: bool,
#[arg(short = 'L', help = "Lazy mode")]
lazy_mode: bool,
#[command(flatten)]
warn_opts: CliWarnOpts,
@ -166,7 +154,7 @@ pub enum OptArgs {
Prune,
NoPrune,
LinearizeMatches,
LinearizeMatchesExtra,
LinearizeMatchesAlt,
NoLinearizeMatches,
FloatCombinators,
NoFloatCombinators,
@ -174,11 +162,13 @@ pub enum OptArgs {
NoMerge,
Inline,
NoInline,
RecursiveLast,
NoRecursiveLast,
}
fn compile_opts_from_cli(args: &Vec<OptArgs>, lazy_mode: bool) -> CompileOpts {
fn compile_opts_from_cli(args: &Vec<OptArgs>) -> CompileOpts {
use OptArgs::*;
let mut opts = if lazy_mode { CompileOpts::default_lazy() } else { CompileOpts::default_strict() };
let mut opts = CompileOpts::default();
for arg in args {
match arg {
@ -194,9 +184,11 @@ fn compile_opts_from_cli(args: &Vec<OptArgs>, lazy_mode: bool) -> CompileOpts {
NoMerge => opts.merge = false,
Inline => opts.inline = true,
NoInline => opts.inline = false,
RecursiveLast => opts.recursive_last = true,
NoRecursiveLast => opts.recursive_last = false,
LinearizeMatches => opts.linearize_matches = OptLevel::Enabled,
LinearizeMatchesExtra => opts.linearize_matches = OptLevel::Extra,
LinearizeMatchesAlt => opts.linearize_matches = OptLevel::Alt,
NoLinearizeMatches => opts.linearize_matches = OptLevel::Disabled,
}
}
@ -242,26 +234,18 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Diagnostics> {
};
match cli.mode {
Mode::Check { comp_opts, lazy_mode, warn_opts, path } => {
let diagnostics_cfg = set_warning_cfg_from_cli(
if lazy_mode { DiagnosticsConfig::default_lazy() } else { DiagnosticsConfig::default_strict() },
lazy_mode,
warn_opts,
);
let compile_opts = compile_opts_from_cli(&comp_opts, lazy_mode);
Mode::Check { comp_opts, warn_opts, path } => {
let diagnostics_cfg = set_warning_cfg_from_cli(DiagnosticsConfig::default(), warn_opts);
let compile_opts = compile_opts_from_cli(&comp_opts);
let mut book = load_book(&path)?;
let diagnostics = check_book(&mut book, diagnostics_cfg, compile_opts)?;
eprintln!("{}", diagnostics);
}
Mode::Compile { path, comp_opts, warn_opts, lazy_mode } => {
let diagnostics_cfg = set_warning_cfg_from_cli(
if lazy_mode { DiagnosticsConfig::default_lazy() } else { DiagnosticsConfig::default_strict() },
lazy_mode,
warn_opts,
);
let opts = compile_opts_from_cli(&comp_opts, lazy_mode);
Mode::Compile { path, comp_opts, warn_opts } => {
let diagnostics_cfg = set_warning_cfg_from_cli(DiagnosticsConfig::default(), warn_opts);
let opts = compile_opts_from_cli(&comp_opts);
let mut book = load_book(&path)?;
let compile_res = compile_book(&mut book, opts, diagnostics_cfg, None)?;
@ -270,14 +254,10 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Diagnostics> {
println!("{}", compile_res.core_book);
}
Mode::Desugar { path, comp_opts, warn_opts, pretty, lazy_mode } => {
let diagnostics_cfg = set_warning_cfg_from_cli(
if lazy_mode { DiagnosticsConfig::default_lazy() } else { DiagnosticsConfig::default_strict() },
lazy_mode,
warn_opts,
);
Mode::Desugar { path, comp_opts, warn_opts, pretty } => {
let diagnostics_cfg = set_warning_cfg_from_cli(DiagnosticsConfig::default(), warn_opts);
let opts = compile_opts_from_cli(&comp_opts, lazy_mode);
let opts = compile_opts_from_cli(&comp_opts);
let mut book = load_book(&path)?;
let diagnostics = desugar_book(&mut book, opts, diagnostics_cfg, None)?;
@ -290,17 +270,17 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Diagnostics> {
}
}
Mode::Run { lazy_mode, run_opts, pretty, comp_opts, warn_opts, arguments, path } => {
Mode::Run { run_opts, pretty, comp_opts, warn_opts, arguments, path } => {
let RunArgs { linear, print_stats } = run_opts;
let diagnostics_cfg =
set_warning_cfg_from_cli(DiagnosticsConfig::new(Severity::Allow, arg_verbose), lazy_mode, warn_opts);
set_warning_cfg_from_cli(DiagnosticsConfig::new(Severity::Allow, arg_verbose), warn_opts);
let compile_opts = compile_opts_from_cli(&comp_opts, lazy_mode);
let compile_opts = compile_opts_from_cli(&comp_opts);
compile_opts.check_for_strict();
let run_opts = RunOpts { linear, lazy_mode, pretty };
let run_opts = RunOpts { linear_readback: linear, pretty };
let book = load_book(&path)?;
let (term, stats, diags) = run_book(book, run_opts, compile_opts, diagnostics_cfg, arguments)?;
@ -319,12 +299,8 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Diagnostics> {
Ok(())
}
fn set_warning_cfg_from_cli(
mut cfg: DiagnosticsConfig,
lazy_mode: bool,
warn_opts: CliWarnOpts,
) -> DiagnosticsConfig {
fn set(cfg: &mut DiagnosticsConfig, severity: Severity, cli_val: WarningArgs, lazy_mode: bool) {
fn set_warning_cfg_from_cli(mut cfg: DiagnosticsConfig, warn_opts: CliWarnOpts) -> DiagnosticsConfig {
fn set(cfg: &mut DiagnosticsConfig, severity: Severity, cli_val: WarningArgs) {
match cli_val {
WarningArgs::All => {
cfg.irrefutable_match = severity;
@ -332,9 +308,7 @@ fn set_warning_cfg_from_cli(
cfg.unreachable_match = severity;
cfg.unused_definition = severity;
cfg.repeated_bind = severity;
if !lazy_mode {
cfg.recursion_cycle = severity;
}
cfg.recursion_cycle = severity;
}
WarningArgs::IrrefutableMatch => cfg.irrefutable_match = severity,
WarningArgs::RedundantMatch => cfg.redundant_match = severity,
@ -356,9 +330,9 @@ fn set_warning_cfg_from_cli(
let mut denies = warn_opts.denies.into_iter();
for id in warn_opts_ids {
match id.as_ref() {
"allows" => set(&mut cfg, Severity::Allow, allows.next().unwrap(), lazy_mode),
"denies" => set(&mut cfg, Severity::Error, denies.next().unwrap(), lazy_mode),
"warns" => set(&mut cfg, Severity::Warning, warns.next().unwrap(), lazy_mode),
"allows" => set(&mut cfg, Severity::Allow, allows.next().unwrap()),
"denies" => set(&mut cfg, Severity::Error, denies.next().unwrap()),
"warns" => set(&mut cfg, Severity::Warning, warns.next().unwrap()),
_ => unreachable!(),
}
}

View File

@ -17,8 +17,8 @@ use super::{num_to_name, FanKind, Op};
#[derive(Debug, Clone)]
pub struct ViciousCycleErr;
pub fn book_to_nets(book: &Book, info: &mut Diagnostics) -> Result<(hvmc::ast::Book, Labels), Diagnostics> {
info.start_pass();
pub fn book_to_nets(book: &Book, diags: &mut Diagnostics) -> Result<(hvmc::ast::Book, Labels), Diagnostics> {
diags.start_pass();
let mut hvmc = hvmc::ast::Book::default();
let mut labels = Labels::default();
@ -31,8 +31,11 @@ pub fn book_to_nets(book: &Book, info: &mut Diagnostics) -> Result<(hvmc::ast::B
let name = if def.name == *main { book.hvmc_entrypoint().to_string() } else { def.name.0.to_string() };
if let Some(net) = info.take_inet_err(net, name.clone()) {
hvmc.insert(name, net);
match net {
Ok(net) => {
hvmc.insert(name, net);
}
Err(err) => diags.add_inet_error(err, name),
}
}
}
@ -40,7 +43,7 @@ pub fn book_to_nets(book: &Book, info: &mut Diagnostics) -> Result<(hvmc::ast::B
labels.con.finish();
labels.dup.finish();
Ok((hvmc, labels))
diags.fatal((hvmc, labels))
}
/// Converts an LC term into an IC net.

View File

@ -117,9 +117,8 @@ fn compile_term() {
fn compile_file() {
run_golden_test_dir(function_name!(), &|code, path| {
let mut book = do_parse_book(code, path)?;
let compile_opts = CompileOpts::default_strict();
let mut diagnostics_cfg = DiagnosticsConfig::default_strict();
diagnostics_cfg.unused_definition = Severity::Allow;
let compile_opts = CompileOpts::default();
let diagnostics_cfg = DiagnosticsConfig { unused_definition: Severity::Allow, ..Default::default() };
let res = compile_book(&mut book, compile_opts, diagnostics_cfg, None)?;
Ok(format!("{}{}", res.diagnostics, res.core_book))
@ -130,10 +129,12 @@ fn compile_file() {
fn compile_file_o_all() {
run_golden_test_dir(function_name!(), &|code, path| {
let mut book = do_parse_book(code, path)?;
let opts = CompileOpts::default_strict().set_all();
let mut diagnostics_cfg = DiagnosticsConfig::default_strict();
diagnostics_cfg.recursion_cycle = Severity::Warning;
diagnostics_cfg.unused_definition = Severity::Allow;
let opts = CompileOpts::default().set_all();
let diagnostics_cfg = DiagnosticsConfig {
recursion_cycle: Severity::Warning,
unused_definition: Severity::Allow,
..Default::default()
};
let res = compile_book(&mut book, opts, diagnostics_cfg, None)?;
Ok(format!("{}{}", res.diagnostics, res.core_book))
@ -144,8 +145,8 @@ fn compile_file_o_all() {
fn compile_file_o_no_all() {
run_golden_test_dir(function_name!(), &|code, path| {
let mut book = do_parse_book(code, path)?;
let compile_opts = CompileOpts::default_strict().set_no_all();
let diagnostics_cfg = DiagnosticsConfig::default_strict();
let compile_opts = CompileOpts::default().set_no_all();
let diagnostics_cfg = DiagnosticsConfig::default();
let res = compile_book(&mut book, compile_opts, diagnostics_cfg, None)?;
Ok(format!("{}", res.core_book))
})
@ -154,11 +155,17 @@ fn compile_file_o_no_all() {
#[test]
fn linear_readback() {
run_golden_test_dir(function_name!(), &|code, path| {
let _guard = RUN_MUTEX.lock().unwrap();
let book = do_parse_book(code, path)?;
let compile_opts = CompileOpts::default_strict().set_all();
let diagnostics_cfg = DiagnosticsConfig::default_strict();
let (term, _, diags) =
run_book(book, RunOpts { linear: true, ..Default::default() }, compile_opts, diagnostics_cfg, None)?;
let compile_opts = CompileOpts::default().set_all();
let diagnostics_cfg = DiagnosticsConfig::default();
let (term, _, diags) = run_book(
book,
RunOpts { linear_readback: true, ..Default::default() },
compile_opts,
diagnostics_cfg,
None,
)?;
let res = format!("{diags}{term}");
Ok(res)
});
@ -169,7 +176,7 @@ fn run_file() {
run_golden_test_dir_multiple(function_name!(), &[(&|code, path| {
let _guard = RUN_MUTEX.lock().unwrap();
let book = do_parse_book(code, path)?;
let compile_opts = CompileOpts::default_strict();
let compile_opts = CompileOpts::default();
let diagnostics_cfg = DiagnosticsConfig {
unused_definition: Severity::Allow,
..DiagnosticsConfig::new(Severity::Error, true)
@ -185,8 +192,9 @@ fn run_file() {
#[test]
#[ignore = "while lazy execution is not implemented for hvm32"]
fn run_lazy() {
run_golden_test_dir(function_name!(), &|code, path| {
let _guard = RUN_MUTEX.lock().unwrap();
run_golden_test_dir(function_name!(), &|_code, _path| {
todo!()
/* let _guard = RUN_MUTEX.lock().unwrap();
let book = do_parse_book(code, path)?;
let compile_opts = CompileOpts::default_lazy();
let diagnostics_cfg = DiagnosticsConfig {
@ -198,7 +206,7 @@ fn run_lazy() {
let (term, _, diags) = run_book(book, run_opts, compile_opts, diagnostics_cfg, None)?;
let res = format!("{diags}{term}");
Ok(res)
Ok(res) */
})
}
@ -255,7 +263,7 @@ fn parse_file() {
fn encode_pattern_match() {
run_golden_test_dir(function_name!(), &|code, path| {
let mut result = String::new();
let diagnostics_cfg = DiagnosticsConfig::default_strict();
let diagnostics_cfg = DiagnosticsConfig::default();
let mut book = do_parse_book(code, path)?;
let mut ctx = Ctx::new(&mut book, diagnostics_cfg);
ctx.check_shared_names();
@ -286,7 +294,7 @@ fn encode_pattern_match() {
#[test]
fn desugar_file() {
run_golden_test_dir(function_name!(), &|code, path| {
let compile_opts = CompileOpts::default_strict();
let compile_opts = CompileOpts::default();
let diagnostics_cfg = DiagnosticsConfig {
unused_definition: Severity::Allow,
..DiagnosticsConfig::new(Severity::Error, true)
@ -305,7 +313,7 @@ fn hangs() {
run_golden_test_dir(function_name!(), &move |code, path| {
let _guard = RUN_MUTEX.lock().unwrap();
let book = do_parse_book(code, path)?;
let compile_opts = CompileOpts::default_strict().set_all();
let compile_opts = CompileOpts::default().set_all();
let diagnostics_cfg = DiagnosticsConfig::new(Severity::Allow, false);
let thread =
@ -328,7 +336,7 @@ fn compile_entrypoint() {
let mut book = do_parse_book(code, path)?;
book.entrypoint = Some(Name::new("foo"));
let diagnostics_cfg = DiagnosticsConfig { ..DiagnosticsConfig::new(Severity::Error, true) };
let res = compile_book(&mut book, CompileOpts::default_strict(), diagnostics_cfg, None)?;
let res = compile_book(&mut book, CompileOpts::default(), diagnostics_cfg, None)?;
Ok(format!("{}{}", res.diagnostics, res.core_book))
})
}
@ -340,7 +348,7 @@ fn run_entrypoint() {
let _guard = RUN_MUTEX.lock().unwrap();
let mut book = do_parse_book(code, path)?;
book.entrypoint = Some(Name::new("foo"));
let compile_opts = CompileOpts::default_strict().set_all();
let compile_opts = CompileOpts::default().set_all();
let diagnostics_cfg = DiagnosticsConfig { ..DiagnosticsConfig::new(Severity::Error, true) };
let (term, _, diags) = run_book(book, RunOpts::default(), compile_opts, diagnostics_cfg, None)?;
let res = format!("{diags}{term}");
@ -374,8 +382,7 @@ fn mutual_recursion() {
let diagnostics_cfg =
DiagnosticsConfig { recursion_cycle: Severity::Error, ..DiagnosticsConfig::new(Severity::Allow, true) };
let mut book = do_parse_book(code, path)?;
let mut opts = CompileOpts::default_strict();
opts.merge = true;
let opts = CompileOpts { merge: true, ..CompileOpts::default() };
let res = compile_book(&mut book, opts, diagnostics_cfg, None)?;
Ok(format!("{}{}", res.diagnostics, res.core_book))
})
@ -400,8 +407,8 @@ fn io() {
(&|code, path| {
let _guard = RUN_MUTEX.lock().unwrap();
let book = do_parse_book(code, path)?;
let compile_opts = CompileOpts::default_strict();
let diagnostics_cfg = DiagnosticsConfig::default_strict();
let compile_opts = CompileOpts::default();
let diagnostics_cfg = DiagnosticsConfig::default();
let (term, _, diags) = run_book(book, RunOpts::default(), compile_opts, diagnostics_cfg, None)?;
let res = format!("{diags}{term}");
Ok(format!("Strict mode:\n{res}"))
@ -410,7 +417,6 @@ fn io() {
}
#[test]
//#[ignore = "while execution is not implemented for hvm32"]
fn examples() -> Result<(), Diagnostics> {
let examples_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("examples");
@ -426,8 +432,8 @@ fn examples() -> Result<(), Diagnostics> {
let code = std::fs::read_to_string(path).map_err(|e| e.to_string())?;
let book = do_parse_book(&code, path).unwrap();
let compile_opts = CompileOpts::default_strict();
let diagnostics_cfg = DiagnosticsConfig::default_strict();
let compile_opts = CompileOpts::default();
let diagnostics_cfg = DiagnosticsConfig::default();
let (term, _, diags) = run_book(book, RunOpts::default(), compile_opts, diagnostics_cfg, None)?;
let res = format!("{diags}{term}");
@ -448,9 +454,9 @@ fn examples() -> Result<(), Diagnostics> {
fn scott_triggers_unused() {
run_golden_test_dir(function_name!(), &|code, path| {
let mut book = do_parse_book(code, path)?;
let opts = CompileOpts::default_strict();
let opts = CompileOpts::default();
let diagnostics_cfg =
DiagnosticsConfig { unused_definition: Severity::Error, ..DiagnosticsConfig::default_strict() };
DiagnosticsConfig { unused_definition: Severity::Error, ..DiagnosticsConfig::default() };
let res = compile_book(&mut book, opts, diagnostics_cfg, None)?;
Ok(format!("{}{}", res.diagnostics, res.core_book))
})

View File

@ -1 +1 @@
main = λa λb switch a { 0: b; _: b }
main = λa λb λc switch a { 0: b; _: c }

View File

@ -0,0 +1,3 @@
desugar
tests/golden_tests/cli/desugar_linearize_matches_alt.hvm
-Olinearize-matches-alt

View File

@ -0,0 +1 @@
main = λa λb switch a { 0: b; _: b }

View File

@ -1,3 +0,0 @@
desugar
tests/golden_tests/cli/desugar_linearize_matches_extra.hvm
-Olinearize-matches-extra

View File

@ -1 +0,0 @@
main = λa λb λc switch a { 0: b; _: c }

View File

@ -1,4 +1,4 @@
tail_recursive = @a (a @x (+ 1 (tail_recursive x)) 0)
tail_recursive = @x (x @pred @acc (tail_recursive pred (+ 1 acc)) @acc 0)
fold = @bm (bm
@lft @rgt (add (fold lft) (fold rgt))

View File

@ -3,7 +3,7 @@ source: tests/golden_tests.rs
input_file: tests/golden_tests/cli/compile_no_opts.hvm
---
error: invalid value 'no-pre-reduce' for '-O <COMP_OPTS>'
[possible values: all, no-all, eta, no-eta, prune, no-prune, linearize-matches, linearize-matches-extra, no-linearize-matches, float-combinators, no-float-combinators, merge, no-merge, inline, no-inline]
[possible values: all, no-all, eta, no-eta, prune, no-prune, linearize-matches, linearize-matches-alt, no-linearize-matches, float-combinators, no-float-combinators, merge, no-merge, inline, no-inline, recursive-last, no-recursive-last]
tip: a similar value exists: 'no-prune'

View File

@ -3,6 +3,6 @@ source: tests/golden_tests.rs
input_file: tests/golden_tests/cli/compile_pre_reduce.hvm
---
error: invalid value 'pre-reduce' for '-O <COMP_OPTS>'
[possible values: all, no-all, eta, no-eta, prune, no-prune, linearize-matches, linearize-matches-extra, no-linearize-matches, float-combinators, no-float-combinators, merge, no-merge, inline, no-inline]
[possible values: all, no-all, eta, no-eta, prune, no-prune, linearize-matches, linearize-matches-alt, no-linearize-matches, float-combinators, no-float-combinators, merge, no-merge, inline, no-inline, recursive-last, no-recursive-last]
For more information, try '--help'.

View File

@ -3,7 +3,7 @@ source: tests/golden_tests.rs
input_file: tests/golden_tests/cli/compile_wrong_opt.hvm
---
error: invalid value 'foo' for '-O <COMP_OPTS>'
[possible values: all, no-all, eta, no-eta, prune, no-prune, linearize-matches, linearize-matches-extra, no-linearize-matches, float-combinators, no-float-combinators, merge, no-merge, inline, no-inline]
[possible values: all, no-all, eta, no-eta, prune, no-prune, linearize-matches, linearize-matches-alt, no-linearize-matches, float-combinators, no-float-combinators, merge, no-merge, inline, no-inline, recursive-last, no-recursive-last]
tip: a similar value exists: 'float-combinators'

View File

@ -3,6 +3,6 @@ source: tests/golden_tests.rs
input_file: tests/golden_tests/cli/desugar_bool_scott.hvm
---
error: invalid value 'adt-scott' for '-O <COMP_OPTS>'
[possible values: all, no-all, eta, no-eta, prune, no-prune, linearize-matches, linearize-matches-extra, no-linearize-matches, float-combinators, no-float-combinators, merge, no-merge, inline, no-inline]
[possible values: all, no-all, eta, no-eta, prune, no-prune, linearize-matches, linearize-matches-alt, no-linearize-matches, float-combinators, no-float-combinators, merge, no-merge, inline, no-inline, recursive-last, no-recursive-last]
For more information, try '--help'.

View File

@ -3,6 +3,6 @@ source: tests/golden_tests.rs
input_file: tests/golden_tests/cli/desugar_bool_tagged.hvm
---
error: invalid value 'adt-tagged-scott' for '-O <COMP_OPTS>'
[possible values: all, no-all, eta, no-eta, prune, no-prune, linearize-matches, linearize-matches-extra, no-linearize-matches, float-combinators, no-float-combinators, merge, no-merge, inline, no-inline]
[possible values: all, no-all, eta, no-eta, prune, no-prune, linearize-matches, linearize-matches-alt, no-linearize-matches, float-combinators, no-float-combinators, merge, no-merge, inline, no-inline, recursive-last, no-recursive-last]
For more information, try '--help'.

View File

@ -2,4 +2,4 @@
source: tests/golden_tests.rs
input_file: tests/golden_tests/cli/desugar_linearize_matches.hvm
---
(main) = λa switch a { 0: λb b; _: λ* λc c; }
(main) = λa λb λc (switch a { 0: λd λ* d; _: λ* λ* λe e; } b c)

View File

@ -0,0 +1,5 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/cli/desugar_linearize_matches_alt.hvm
---
(main) = λa switch a { 0: λb b; _: λ* λc c; }

View File

@ -18,8 +18,8 @@ input_file: tests/golden_tests/compile_file/redex_order_recursive.hvm
@main = *
@tail_recursive = ((@tail_recursive__C0 (0 a)) a)
@tail_recursive = ((@tail_recursive__C0 ((* 0) a)) a)
@tail_recursive__C0 = (a c)
@tail_recursive__C0 = (a (b d))
& @tail_recursive ~ (a (c d))
& $(b c) ~ [+1]
& @tail_recursive ~ (a b)

View File

@ -7,5 +7,3 @@ In compiled inet 'disconnected_self_lam':
Found term that compiles into an inet with a vicious cycle
In compiled inet 'dup_self':
Found term that compiles into an inet with a vicious cycle
@main = (@dup_self @disconnected_self_lam)

View File

@ -16,8 +16,8 @@ input_file: tests/golden_tests/compile_file_o_all/ex2.hvm
& @low ~ a
@decO = (a c)
& @I ~ (b c)
& @dec ~ (a b)
& @I ~ (b c)
@low = ((@lowO (@lowI (@E a))) a)

View File

@ -11,8 +11,8 @@ input_file: tests/golden_tests/compile_file_o_all/list_merge_sort.hvm
@Map = ((@Map__C0 ((* @False__M_Nil) a)) a)
@Map__C0 = (a (c ({(a b) d} f)))
& @Cons ~ (b (e f))
& @Map ~ (c (d e))
& @Cons ~ (b (e f))
@Merge = (b ((@Merge__C2 ((* (a a)) (b c))) c))
@ -22,9 +22,9 @@ input_file: tests/golden_tests/compile_file_o_all/list_merge_sort.hvm
& @Cons ~ (a (@False__M_Nil b))
@MergePair__C1 = (c (f ({a e} (b h))))
& @Cons ~ (d (g h))
& @Merge ~ (a (b (c d)))
& @MergePair ~ (e (f g))
& @Cons ~ (d (g h))
@MergePair__C2 = (b ((@MergePair__C1 (@MergePair__C0 (a (b c)))) (a c)))
@ -36,12 +36,12 @@ input_file: tests/golden_tests/compile_file_o_all/list_merge_sort.hvm
& @Cons ~ a
@Merge__C1 = ({b {g l}} ({h q} ({(a (b c)) {e m}} ({a {d n}} ({f o} t)))))
& @Merge ~ (e (f (i j)))
& @Merge ~ (m (p (q r)))
& @If ~ (c (k (s t)))
& @Cons ~ (d (j k))
& @Merge ~ (e (f (i j)))
& @Cons ~ (g (h i))
& @Cons ~ (l (r s))
& @Merge ~ (m (p (q r)))
& @Cons ~ (n (o p))
@Merge__C2 = (b (c (a ((@Merge__C1 (@Merge__C0 (a (b (c d))))) d))))

View File

@ -5,8 +5,8 @@ input_file: tests/golden_tests/compile_file_o_all/list_reverse.hvm
@concat = ((@concat__C0 ((a a) b)) b)
@concat__C0 = (a (b (c e)))
& @cons ~ (a (d e))
& @concat ~ (b (c d))
& @cons ~ (a (d e))
@cons = (a (b ((a (b c)) (* c))))

View File

@ -5,8 +5,8 @@ input_file: tests/golden_tests/mutual_recursion/len.hvm
@Len = ((@Len__C0 (0 a)) a)
@Len__C0 = (* (a c))
& $(b c) ~ [+1]
& @Len ~ (a b)
& $(b c) ~ [+1]
@List.cons = (a (b ((a (b c)) (* c))))