[sc-670] Add priority redexes and order dups correctly in compilation

This commit is contained in:
Nicolas Abril 2024-05-10 18:22:05 +02:00
parent 0308f5b09e
commit 2f8a12bceb
132 changed files with 561 additions and 343 deletions

61
Cargo.lock generated
View File

@ -21,47 +21,48 @@ dependencies = [
[[package]]
name = "anstream"
version = "0.6.13"
version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.6"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
[[package]]
name = "anstyle-parse"
version = "0.2.3"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.2"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.2"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
dependencies = [
"anstyle",
"windows-sys",
@ -75,9 +76,9 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]]
name = "autocfg"
version = "1.2.0"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "bend"
@ -106,9 +107,9 @@ checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "cc"
version = "1.0.95"
version = "1.0.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b"
checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
[[package]]
name = "cfg-if"
@ -158,9 +159,9 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "colorchoice"
version = "1.0.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]]
name = "console"
@ -213,7 +214,7 @@ checksum = "809e18805660d7b6b2e2b9f316a5099521b5998d5cba4dda11b5157a21aaef03"
[[package]]
name = "hvm-core"
version = "0.2.24"
source = "git+https://github.com/HigherOrderCO/hvm-core.git?branch=hvm32-compat#8bc55acaa14bb18d889e2c80a300a2fadb400d03"
source = "git+https://github.com/HigherOrderCO/hvm-core.git?branch=hvm32-compat#389b3be2d0c0dbe23623adda9175c622dd9ce0b8"
dependencies = [
"TSPL 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"arrayvec",
@ -252,6 +253,12 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8c60687056b35a996f2213287048a7092d801b61df5fee3bd5bd9bf6f17a2d0"
[[package]]
name = "is_terminal_polyfill"
version = "1.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
[[package]]
name = "itertools"
version = "0.11.0"
@ -269,9 +276,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.153"
version = "0.2.154"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
[[package]]
name = "linked-hash-map"
@ -326,9 +333,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.81"
version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
dependencies = [
"unicode-ident",
]
@ -414,9 +421,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.60"
version = "2.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9"
dependencies = [
"proc-macro2",
"quote",
@ -425,18 +432,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.59"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.59"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524"
dependencies = [
"proc-macro2",
"quote",

View File

@ -6,12 +6,10 @@
| `-Ono-all` | Disabled | Disables all compiler passes |
| `-Oeta` `-Ono-eta` | Disabled | [eta-reduction](#eta-reduction) |
| `-Oprune` `-Ono-prune` | Disabled | [definition-pruning](#definition-pruning) |
| `-Opre-reduce` `-Ono-pre-reduce` | Disabled | [pre-reduce](#pre-reduce) |
| `-Olinearize-matches` `-Olinearize-matches-extra` `-Ono-linearize-matches` | Enabled | [linearize-matches](#linearize-matches) |
| `-Olinearize-matches` `-Olinearize-matches-alt` `-Ono-linearize-matches` | Enabled | [linearize-matches](#linearize-matches) |
| `-Ofloat_combinators` `-Ono-float_combinators` | Enabled | [float-combinators](#float-combinators) |
| `-Omerge` `-Ono-merge` | Disabled | [definition-merging](#definition-merging) |
| `-Oinline` `-Ono-inline` | Disabled | [inline](#inline) |
| `-e` `--entrypoint` | `Main \| main` | [entrypoint](#entrypoint) |
## Eta-reduction

View File

@ -409,9 +409,9 @@ impl<'a> TermParser<'a> {
// Match
if self.try_consume_keyword("match") {
unexpected_tag(self)?;
let (bnd, arg, with) = self.parse_match_arg()?;
let (bnd, arg, with) = self.parse_match_header()?;
let arms = self.list_like(|p| p.parse_match_arm(), "{", "}", ";", false, 1)?;
return Ok(Term::Mat { arg: Box::new(arg), bnd: Some(bnd), with, arms });
return Ok(Term::Mat { arg: Box::new(arg), bnd, with, arms });
}
// Switch
@ -433,9 +433,9 @@ impl<'a> TermParser<'a> {
// Fold
if self.try_consume_keyword("fold") {
unexpected_tag(self)?;
let (bnd, arg, with) = self.parse_match_arg()?;
let (bnd, arg, with) = self.parse_match_header()?;
let arms = self.list_like(|p| p.parse_match_arm(), "{", "}", ";", false, 1)?;
return Ok(Term::Fold { arg: Box::new(arg), bnd: Some(bnd), with, arms });
return Ok(Term::Fold { arg: Box::new(arg), bnd, with, arms });
}
// Bend
@ -545,9 +545,25 @@ impl<'a> TermParser<'a> {
}))
}
fn parse_match_arg(&mut self) -> Result<(Name, Term, Vec<Name>), String> {
let bnd = self.parse_bend_name()?;
let arg = if self.try_consume("=") { self.parse_term()? } else { Term::Var { nam: bnd.clone() } };
fn parse_match_arg(&mut self) -> Result<(Option<Name>, Term), String> {
let ini_idx = *self.index();
let mut arg = self.parse_term()?;
let end_idx = *self.index();
self.skip_trivia();
match (&mut arg, self.starts_with("=")) {
(Term::Var { nam }, true) => {
self.consume("=")?;
Ok((Some(std::mem::take(nam)), self.parse_term()?))
}
(Term::Var { nam }, false) => Ok((Some(nam.clone()), Term::Var { nam: std::mem::take(nam) })),
(_, true) => self.expected_spanned("argument name", ini_idx, end_idx),
(arg, false) => Ok((Some(Name::new("%arg")), std::mem::take(arg))),
}
}
fn parse_match_header(&mut self) -> Result<(Option<Name>, Term, Vec<Name>), String> {
let (bnd, arg) = self.parse_match_arg()?;
let with = if self.try_consume_keyword("with") {
let mut with = vec![self.parse_bend_name()?];
while !self.skip_starts_with("{") {
@ -570,7 +586,7 @@ impl<'a> TermParser<'a> {
}
fn parse_switch(&mut self) -> Result<Term, String> {
let (bnd, arg, with) = self.parse_match_arg()?;
let (bnd, arg, with) = self.parse_match_header()?;
self.consume("{")?;
let mut expected_num = 0;
let mut arms = vec![];
@ -600,9 +616,9 @@ impl<'a> TermParser<'a> {
self.try_consume(";");
expected_num += 1;
}
let pred = Some(Name::new(format!("{}-{}", bnd, arms.len() - 1)));
let pred = Some(Name::new(format!("{}-{}", bnd.as_ref().unwrap(), arms.len() - 1)));
self.consume("}")?;
Ok(Term::Swt { arg: Box::new(arg), bnd: Some(bnd), with, pred, arms })
Ok(Term::Swt { arg: Box::new(arg), bnd, with, pred, arms })
}
fn num_range_err<T>(&mut self, ini_idx: usize, typ: &str) -> Result<T, String> {

View File

@ -51,6 +51,7 @@ pub fn term_to_net(term: &Term, labels: &mut Labels) -> Result<Net, String> {
let mut net = Net::default();
let mut state = EncodeTermState {
lets: Default::default(),
vars: Default::default(),
wires: Default::default(),
redexes: Default::default(),
@ -74,9 +75,10 @@ pub fn term_to_net(term: &Term, labels: &mut Labels) -> Result<Net, String> {
#[derive(Debug)]
struct EncodeTermState<'t, 'l> {
lets: Vec<(&'t Pattern, &'t Term)>,
vars: HashMap<(bool, Name), Place<'t>>,
wires: Vec<Option<Place<'t>>>,
redexes: Vec<LoanedMut<'t, (Tree, Tree)>>,
redexes: Vec<LoanedMut<'t, (bool, Tree, Tree)>>,
name_idx: u64,
created_nodes: usize,
labels: &'l mut Labels,
@ -101,7 +103,7 @@ impl<'t, 'l> EncodeTermState<'t, 'l> {
/// `vars` has the information of which ports the variables are declared and used in.
/// `global_vars` has the same information for global lambdas. Must be linked outside this function.
/// Expects variables to be linear, refs to be stored as Refs and all names to be bound.
fn encode_term(&mut self, term: &Term, up: Place<'t>) {
fn encode_term(&mut self, term: &'t Term, up: Place<'t>) {
maybe_grow(|| {
match term {
Term::Era => self.link(up, Place::Tree(LoanedMut::new(Tree::Era))),
@ -155,10 +157,9 @@ impl<'t, 'l> EncodeTermState<'t, 'l> {
self.link(up, Place::Hole(out));
}
Term::Let { pat, val, nxt } => {
let wire = self.new_wire();
self.encode_term(val, Place::Wire(wire));
self.encode_pat(pat, Place::Wire(wire));
// Dups/tup eliminators are not actually scoped like other terms.
// They are depended on
self.lets.push((pat, val));
self.encode_term(nxt, up);
}
Term::Fan { fan, tag, els } => {
@ -213,6 +214,11 @@ impl<'t, 'l> EncodeTermState<'t, 'l> {
| Term::List { .. } // Removed in encode_list
| Term::Err => unreachable!(),
}
while let Some((pat, val)) = self.lets.pop() {
let wire = self.new_wire();
self.encode_term(val, Place::Wire(wire));
self.encode_pat(pat, Place::Wire(wire));
}
})
}
@ -232,8 +238,8 @@ impl<'t, 'l> EncodeTermState<'t, 'l> {
fn link(&mut self, a: Place<'t>, b: Place<'t>) {
match (a, b) {
(Place::Tree(a), Place::Tree(b)) => self.redexes.push(LoanedMut::merge(Default::default(), |r, m| {
m.place(b, &mut r.0);
m.place(a, &mut r.1);
m.place(b, &mut r.1);
m.place(a, &mut r.2);
})),
(Place::Tree(t), Place::Hole(h)) | (Place::Hole(h), Place::Tree(t)) => {
t.place(h);

View File

@ -1,55 +1,58 @@
use crate::maybe_grow;
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) {
pub fn add_recursive_priority(book: &mut Book) {
// Direct dependencies
let deps = book.iter().map(|(nam, net)| (nam.clone(), dependencies(net))).collect::<HashMap<_, _>>();
// Recursive cycles
let cycles = cycles(&deps);
// 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));
for cycle in cycles {
// For each function in the cycle, if there are redexes with the
// next ref in the cycle, add a priority to one of those redexes.
for i in 0 .. cycle.len() {
let cur = book.get_mut(&cycle[i]).unwrap();
let nxt = &cycle[(i + 1) % cycle.len()];
add_priority_next_in_cycle(cur, nxt);
}
}
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;
fn add_priority_next_in_cycle(net: &mut Net, nxt: &String) {
let mut count = 0;
// Count the number of recursive refs
for (_, a, b) in net.redexes.iter() {
if let Tree::Ref { nam } = a {
if nam == nxt {
count += 1;
}
}
if let Tree::Ref { nam } = b {
if nam == nxt {
count += 1;
}
}
}
// If there are more than one recursive ref, add a priority to the last (first to execute).
if count > 1 {
for (pri, a, b) in net.redexes.iter_mut().rev() {
if let Tree::Ref { nam } = a {
if nam == nxt {
*pri = true;
break;
}
}
if let Tree::Ref { nam } = b {
if nam == nxt {
*pri = true;
break;
}
}
false
}
})
}
}
type DepGraph = HashMap<String, HashSet<String>>;
@ -102,7 +105,7 @@ fn find_cycles(
fn dependencies(net: &Net) -> HashSet<String> {
let mut deps = HashSet::new();
dependencies_tree(&net.root, &mut deps);
for (a, b) in &net.redexes {
for (_, a, b) in &net.redexes {
dependencies_tree(a, &mut deps);
dependencies_tree(b, &mut deps);
}
@ -110,7 +113,7 @@ fn dependencies(net: &Net) -> HashSet<String> {
}
fn dependencies_tree(tree: &Tree, deps: &mut HashSet<String>) {
if let Tree::Ref { nam } = tree {
if let Tree::Ref { nam, .. } = tree {
deps.insert(nam.clone());
} else {
for subtree in tree.children() {

View File

@ -23,7 +23,7 @@ pub fn check_net_sizes(book: &Book, diagnostics: &mut Diagnostics) -> Result<(),
pub fn count_nodes<'l>(net: &'l hvmc::ast::Net) -> usize {
let mut visit: Vec<&'l hvmc::ast::Tree> = vec![&net.root];
let mut count = 0usize;
for (l, r) in &net.redexes {
for (_, l, r) in &net.redexes {
visit.push(l);
visit.push(r);
}

View File

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

View File

@ -107,7 +107,7 @@ impl Graph {
/// Collect active refs from the tree.
fn collect_refs(current: Ref, tree: &Tree, graph: &mut Graph) {
maybe_grow(|| match tree {
Tree::Ref { nam } => graph.add(current, nam.clone()),
Tree::Ref { nam, .. } => graph.add(current, nam.clone()),
Tree::Ctr { ports, .. } => {
if let Some(last) = ports.last() {
collect_refs(current, last, graph);
@ -130,11 +130,11 @@ impl From<&Book> for Graph {
collect_refs(r#ref.clone(), &net.root, &mut graph);
// Collect active refs from redexes.
for (left, right) in net.redexes.iter() {
if let Tree::Ref { nam } = left {
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 {
if let Tree::Ref { nam, .. } = right {
graph.add(r#ref.clone(), nam.clone());
}
}

View File

@ -3,18 +3,18 @@
use crate::fun::{book_to_nets, net_to_term::net_to_term, term_to_net::Labels, Book, Ctx, Term};
use diagnostics::{Diagnostics, DiagnosticsConfig, ERR_INDENT_SIZE};
use hvmc::ast::Net;
use hvmc_net::{
use hvm::{
add_recursive_priority::add_recursive_priority,
check_net_size::{check_net_sizes, MAX_NET_SIZE},
mutual_recursion,
reorder_redexes::reorder_redexes_recursive_last,
};
use hvmc::ast::Net;
use net::hvmc_to_net::hvmc_to_net;
use std::{process::Output, str::FromStr};
pub mod diagnostics;
pub mod fun;
pub mod hvmc_net;
pub mod hvm;
pub mod imp;
pub mod net;
@ -41,20 +41,20 @@ pub fn compile_book(
) -> 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)?;
let (mut hvm_book, labels) = book_to_nets(book, &mut diagnostics)?;
if opts.eta {
core_book.values_mut().for_each(Net::eta_reduce);
hvm_book.values_mut().for_each(Net::eta_reduce);
}
mutual_recursion::check_cycles(&core_book, &mut diagnostics)?;
mutual_recursion::check_cycles(&hvm_book, &mut diagnostics)?;
if opts.eta {
core_book.values_mut().for_each(Net::eta_reduce);
hvm_book.values_mut().for_each(Net::eta_reduce);
}
if opts.inline {
diagnostics.start_pass();
if let Err(e) = core_book.inline() {
if let Err(e) = hvm_book.inline() {
diagnostics.add_book_error(format!("During inlining:\n{:ERR_INDENT_SIZE$}{}", "", e));
}
diagnostics.fatal(())?;
@ -62,16 +62,14 @@ pub fn compile_book(
if opts.prune {
let prune_entrypoints = vec![book.hvmc_entrypoint().to_string()];
core_book.prune(&prune_entrypoints);
hvm_book.prune(&prune_entrypoints);
}
check_net_sizes(&core_book, &mut diagnostics)?;
check_net_sizes(&hvm_book, &mut diagnostics)?;
if opts.recursive_last {
reorder_redexes_recursive_last(&mut core_book);
}
add_recursive_priority(&mut hvm_book);
Ok(CompileResult { core_book, labels, diagnostics })
Ok(CompileResult { core_book: hvm_book, labels, diagnostics })
}
pub fn desugar_book(
@ -238,9 +236,6 @@ pub struct CompileOpts {
/// Enables [fun::transform::inline].
pub inline: bool,
/// Enables [hvmc_net::reorder_redexes::reorder_redexes_recursive_last].
pub recursive_last: bool,
}
impl CompileOpts {
@ -253,7 +248,6 @@ impl CompileOpts {
float_combinators: true,
merge: true,
inline: true,
recursive_last: true,
linearize_matches: OptLevel::Enabled,
}
}
@ -268,7 +262,6 @@ impl CompileOpts {
float_combinators: false,
merge: false,
inline: false,
recursive_last: false,
}
}
@ -296,7 +289,6 @@ impl Default for CompileOpts {
float_combinators: true,
merge: false,
inline: false,
recursive_last: true,
}
}
}

View File

@ -161,8 +161,6 @@ pub enum OptArgs {
NoMerge,
Inline,
NoInline,
RecursiveLast,
NoRecursiveLast,
}
fn compile_opts_from_cli(args: &Vec<OptArgs>) -> CompileOpts {
@ -183,8 +181,6 @@ fn compile_opts_from_cli(args: &Vec<OptArgs>) -> 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,
LinearizeMatchesAlt => opts.linearize_matches = OptLevel::Alt,

View File

@ -22,7 +22,7 @@ fn hvmc_to_inodes(net: &Net) -> INodes {
}
// Convert all the trees forming active pairs.
for (i, (tree1, tree2)) in net.redexes.iter().enumerate() {
for (i, (_, tree1, tree2)) in net.redexes.iter().enumerate() {
let tree_root = format!("a{i}");
let mut tree1 = tree_to_inodes(tree1, tree_root.clone(), net_root, &mut n_vars);
inodes.append(&mut tree1);

View File

@ -1,10 +1,7 @@
use bend::{
compile_book, desugar_book,
diagnostics::{Diagnostics, DiagnosticsConfig, Severity},
fun::{
load_book::do_parse_core_book, net_to_term::net_to_term, parser::TermParser, term_to_net::Labels, Book,
Ctx, Name,
},
fun::{load_book::do_parse_core_book, net_to_term::net_to_term, term_to_net::Labels, Book, Ctx, Name},
net::hvmc_to_net::hvmc_to_net,
run_book, CompileOpts, RunOpts,
};
@ -93,25 +90,6 @@ fn run_golden_test_dir_multiple(test_name: &str, run: &[&RunFn]) {
and what to save as a snapshot.
*/
#[test]
fn compile_term() {
run_golden_test_dir(function_name!(), &|code, _| {
let mut term = TermParser::new(code).parse_term()?;
let mut vec = Vec::new();
term.check_unbound_vars(&mut HashMap::new(), &mut vec);
if !vec.is_empty() {
return Err(vec.into_iter().map(|e| e.to_string()).join("\n").into());
}
term.make_var_names_unique();
term.linearize_vars();
let net = bend::fun::term_to_net(&term, &mut Default::default()).map_err(|e| e.to_string())?;
Ok(format!("{}", net))
})
}
#[test]
fn compile_file() {
run_golden_test_dir(function_name!(), &|code, path| {

View File

@ -0,0 +1 @@
main = (λx (+ (+ 1 1) x) 8)

View File

@ -0,0 +1 @@
main = (λk λs λz let {s0 s1} = s; (s0 ((k s1) z)) λq λw w)

View File

@ -0,0 +1 @@
main = λs λz z

View File

@ -0,0 +1 @@
main = let {x1 x2} = ($a $b); λy let {y1 y2} = y; (λ$a (y1 x1) λ$b (y2 x2))

View File

@ -0,0 +1 @@
main = λa ($a λ$a a)

View File

@ -0,0 +1 @@
main = λa let {a1 a2} = a; (a1 a2)

View File

@ -0,0 +1 @@
main = let {x1 x2} = $a; ((λ$a λb b) (x1 x2))

View File

@ -0,0 +1 @@
main = λa let {a1 a2} = a; a2

View File

@ -0,0 +1 @@
main = (/ (* +124.0928 1.24) (+ 0.0 -235.12235))

View File

@ -1,3 +1,4 @@
main =
let fst = (@t let (f, *) = t; f);
let snd = (@t let (*, s) = t; s);
(snd (fst ((1, 3), 2)))

View File

@ -0,0 +1 @@
main = ((λ$a λa a) $a)

View File

@ -0,0 +1 @@
main = (* (+ +1 -1) (- -12 +14))

View File

@ -0,0 +1 @@
main = λa a

View File

@ -0,0 +1 @@
main = λa (a a)

View File

@ -0,0 +1 @@
main = let x = λa (a a); x

View File

@ -0,0 +1 @@
main = let tup = (@x@y x, @x@y y); tup

View File

@ -1,3 +1,4 @@
main =
let a0 = λx0 x0;
let a1 = λx1 x1;
let a2 = λx2 x2;

View File

@ -0,0 +1,4 @@
main = switch x = (+ 0 1) {
0: λt λf t
_: λt λf f
}

View File

@ -1,3 +1,4 @@
main =
let (a, b) = ((2, 4), (3, 6));
let (a1, a2) = a;
let (b1, b2) = b;

View File

@ -0,0 +1 @@
main = 0x10000000

View File

@ -0,0 +1 @@
main = (+ 0xFF_FFFF (+ 0b101 1_000))

View File

@ -0,0 +1 @@
main = (% (+ (- (* (/ (< (> (| (& (== (!= 0 1) 2) 3) 4) 5) 6) 7) 8) 9) 10) 11)

View File

@ -1,3 +1,5 @@
data Tree = (Tree.node lft rgt) | (Tree.leaf val)
tail_recursive = @x (x @pred @acc (tail_recursive pred (+ 1 acc)) @acc 0)
fold_ = @bm (bm
@ -10,4 +12,91 @@ add = @a (a
@b b
)
List.sum xs acc = match xs {
List.nil: acc
List.cons: (List.sum xs.tail (+ xs.head acc))
}
List.len xs = match xs {
List.nil: 0
List.cons: (+ 1 (List.len xs.tail))
}
List.len_tr xs acc = match xs {
List.nil: acc
List.cons: (List.len_tr xs.tail (+ 1 acc))
}
List.map xs f = match xs {
List.nil: List.nil
List.cons: (List.cons (f xs.head) (List.map xs.tail f))
}
List.concat xs ys = match xs {
List.nil: ys
List.cons: (List.cons xs.head (List.concat xs.tail ys))
}
List.reverse_bad xs = match xs {
List.nil: List.nil
List.cons: (List.concat (List.reverse_bad xs.tail) (List.cons xs.head List.nil))
}
List.reverse_tr xs acc = (List.reverse_over xs List.nil)
List.fold xs c n = match xs {
List.nil: n
List.cons: (c xs.head (List.fold xs.tail c n))
}
List.reduce xs f acc = match xs {
List.nil: acc
List.cons: (List.reduce xs.tail f (f acc xs.head))
}
List.reverse_over xs ys = match xs {
List.nil: ys
List.cons: (List.reverse_over xs.tail (List.cons xs.head ys))
}
Tree.leaves tree = match tree {
Tree.leaf: 1
Tree.node: (+ (Tree.leaves tree.lft) (Tree.leaves tree.rgt))
}
Tree.nodes tree = match tree {
Tree.leaf: 0
Tree.node: (+ 1 (+ (Tree.nodes tree.lft) (Tree.nodes tree.rgt)))
}
Tree.height tree = match tree {
Tree.leaf: 0
Tree.node: (+ 1 (max (Tree.height tree.lft) (Tree.height tree.rgt)))
}
Tree.map tree f = match tree {
Tree.leaf: (Tree.leaf (f tree.val))
Tree.node: (Tree.node (Tree.map tree.lft f) (Tree.map tree.rgt f))
}
max a b = switch (> a b) {
0: b
_: a
}
Tree.flip tree = match tree {
Tree.leaf: tree
Tree.node: (Tree.node (Tree.flip tree.rgt) (Tree.flip tree.lft))
}
calc =
let n0 = 1
let n1 = (* n0 n0)
let n2 = (* n1 n1)
let n3 = (* n2 n2)
let n4 = (* n3 n3)
let n5 = (* n4 n4)
(Foo (+ n0 n1) (+ n2 n3) (+ n4 n5))
Foo = @a @b @c @x (x a b c)
main = *

View File

@ -0,0 +1 @@
main = (0, 42)

View File

@ -0,0 +1 @@
main = let x = ((1, 4), (2, 3)); x

View File

@ -0,0 +1 @@
main = let (a, b) = (1, 2); (+ a b)

View File

@ -0,0 +1 @@
main = a

View File

@ -1,3 +1,3 @@
// Fully parenthesized, this is (λa ((λb b) b)).
// Since applications must have (), the second 'b' is not in scope
λa (λb b b)
main = λa (λb b b)

View File

@ -0,0 +1 @@
main = (+ 0b012345 0FA)

View File

@ -0,0 +1 @@
main = (String.cons '\u{1' "\u2}\u{zxcx}")

View File

@ -1 +0,0 @@
(λx (+ (+ 1 1) x) 8)

View File

@ -1 +0,0 @@
(λk λs λz let {s0 s1} = s; (s0 ((k s1) z)) λq λw w)

View File

@ -1 +0,0 @@
λs λz z

View File

@ -1 +0,0 @@
let {x1 x2} = ($a $b); λy let {y1 y2} = y; (λ$a (y1 x1) λ$b (y2 x2))

View File

@ -1 +0,0 @@
λa ($a λ$a a)

View File

@ -1 +0,0 @@
λa let {a1 a2} = a; (a1 a2)

View File

@ -1 +0,0 @@
let {x1 x2} = $a; ((λ$a λb b) (x1 x2))

View File

@ -1 +0,0 @@
λa let {a1 a2} = a; a2

View File

@ -1 +0,0 @@
(/ (* +124.0928 1.24) (+ 0.0 -235.12235))

View File

@ -1 +0,0 @@
((λ$a λa a) $a)

View File

@ -1 +0,0 @@
(* (+ +1 -1) (- -12 +14))

View File

@ -1 +0,0 @@
λa a

View File

@ -1 +0,0 @@
λa (a a)

View File

@ -1 +0,0 @@
let x = λa (a a); x

View File

@ -1 +0,0 @@
let tup = (@x@y x, @x@y y); tup

View File

@ -1,4 +0,0 @@
switch x = (+ 0 1) {
0: λt λf t
_: λ* λt λf f // The term to hvmc function assumes the pred variable is already detached from the match
}

View File

@ -1 +0,0 @@
0x10000000

View File

@ -1 +0,0 @@
(+ 0xFF_FFFF (+ 0b101 1_000))

View File

@ -1 +0,0 @@
(+ (- (* (/ (< (> (| (& 1 2) 3) 4) 5) 6) 7) 8) 9)

View File

@ -1 +0,0 @@
(0, 42)

View File

@ -1 +0,0 @@
let x = ((1, 4), (2, 3)); x

View File

@ -1 +0,0 @@
let (a, b) = (1, 2); (+ a b)

View File

@ -1 +0,0 @@
(+ 0b012345 0FA)

View File

@ -1 +0,0 @@
(String.cons '\u{1' "\u2}\u{zxcx}")

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-alt, no-linearize-matches, float-combinators, no-float-combinators, merge, no-merge, inline, no-inline, recursive-last, no-recursive-last]
[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]
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-alt, no-linearize-matches, float-combinators, no-float-combinators, merge, no-merge, inline, no-inline, recursive-last, no-recursive-last]
[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]
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-alt, no-linearize-matches, float-combinators, no-float-combinators, merge, no-merge, inline, no-inline, recursive-last, no-recursive-last]
[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]
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-alt, no-linearize-matches, float-combinators, no-float-combinators, merge, no-merge, inline, no-inline, recursive-last, no-recursive-last]
[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]
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-alt, no-linearize-matches, float-combinators, no-float-combinators, merge, no-merge, inline, no-inline, recursive-last, no-recursive-last]
[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]
For more information, try '--help'.

View File

@ -0,0 +1,9 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/addition.hvm
---
@main = a
& @main__C0 ~ (8 a)
@main__C0 = (a b)
& $(1 $(:[+] $(a b))) ~ [+1]

View File

@ -0,0 +1,8 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/church_one.hvm
---
@main = b
& @main__C0 ~ ((* (a a)) b)
@main__C0 = ((a (b c)) ({(c d) a} (b d)))

View File

@ -0,0 +1,5 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/church_zero.hvm
---
@main = (* (a a))

View File

@ -0,0 +1,6 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/complicated_dup.hvm
---
@main = ({(a b) (d e)} f)
& ((c {a d}) b) ~ ((c e) f)

View File

@ -0,0 +1,7 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/cyclic_global_lam.hvm
---
Errors:
In compiled inet 'main':
Found term that compiles into an inet with a vicious cycle

View File

@ -0,0 +1,5 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/dup_apply.hvm
---
@main = ({(a b) a} b)

View File

@ -0,0 +1,6 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/dup_global_lam.hvm
---
@main = d
& ({(b c) b} (a a)) ~ (c d)

View File

@ -0,0 +1,5 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/erased_dup.hvm
---
@main = ({* a} a)

View File

@ -1,7 +1,7 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_term/f24_oper.hvm
input_file: tests/golden_tests/compile_file/f24_oper.hvm
---
b
@main = b
& $(1.240 $(:[/] $(a b))) ~ [*4583519]
& $(-235.121 a) ~ [+0]

View File

@ -0,0 +1,13 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/fst_snd.hvm
---
@main = a
& @main__C2 ~ (@main__C1 a)
@main__C0 = ((a *) a)
@main__C1 = a
& @main__C0 ~ (((1 3) 2) a)
@main__C2 = ((* a) a)

View File

@ -0,0 +1,6 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/global_lam.hvm
---
@main = c
& (b (a a)) ~ (b c)

View File

@ -1,7 +1,7 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_term/i24_oper.hvm
input_file: tests/golden_tests/compile_file/i24_oper.hvm
---
b
@main = b
& $(-1 $(:[*] $(a b))) ~ [+1]
& $(+14 a) ~ [-16777204]

View File

@ -0,0 +1,5 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/id.hvm
---
@main = (a a)

View File

@ -0,0 +1,5 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/infer_dup.hvm
---
@main = ({(a b) a} b)

View File

@ -0,0 +1,5 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/let_substitution.hvm
---
@main = ({(a b) a} b)

View File

@ -0,0 +1,5 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/let_tup.hvm
---
@main = ((a (* a)) (* (b b)))

View File

@ -0,0 +1,12 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/lets.hvm
---
@main = @main__C0
& (a a) ~ *
@main__C0 = n
& (a a) ~ (f (i (m n)))
& (d d) ~ {(e f) e}
& (c c) ~ {(g (h i)) {g h}}
& (b b) ~ {(j (k (l m))) {j {k l}}}

View File

@ -1,6 +1,6 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_term/match.hvm
input_file: tests/golden_tests/compile_file/match.hvm
---
c
@main = c
& $(1 ?(((a (* a)) (* (* (b b)))) c)) ~ [+0]

View File

@ -0,0 +1,6 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/nested_let.hvm
---
@main = a
& ((2 4) (3 6)) ~ (* (a *))

View File

@ -0,0 +1,8 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/number_too_large.hvm
---
Errors:
In tests/golden_tests/compile_file/number_too_large.hvm :
Number literal outside of range for U24.
 1 | main = 0x10000000

View File

@ -1,7 +1,7 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_term/nums.hvm
input_file: tests/golden_tests/compile_file/nums.hvm
---
b
@main = b
& $(a b) ~ [+16777215]
& $(1000 a) ~ [+5]

View File

@ -0,0 +1,6 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/op2.hvm
---
@main = a
& $(1 $([=2] $([&3] $([|4] $([>5] $([<6] $([/7] $([*8] $([-9] $([+10] $([%11] a))))))))))) ~ [!0]

View File

@ -2,11 +2,121 @@
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/redex_order_recursive.hvm
---
@Foo = (a (b (c ((a (b (c d))) d))))
@List.concat = ((@List.concat__C0 ((a a) b)) b)
@List.concat__C0 = (a (b (c e)))
& @List.cons ~ (a (d e))
& @List.concat ~ (b (c d))
@List.cons = (a (b ((a (b c)) (* c))))
@List.fold = ((@List.fold__C0 ((a (* a)) (b (c d)))) (c (b d)))
@List.fold__C0 = (a (b (d ({(a (e f)) c} f))))
& @List.fold ~ (b (c (d e)))
@List.len = ((@List.len__C0 (0 a)) a)
@List.len__C0 = (* (a c))
& $(b c) ~ [+1]
& @List.len ~ (a b)
@List.len_tr = ((@List.len_tr__C0 ((a a) b)) b)
@List.len_tr__C0 = (* (a (b d)))
& @List.len_tr ~ (a (c d))
& $(b c) ~ [+1]
@List.map = ((@List.map__C0 ((* @List.nil) a)) a)
@List.map__C0 = (a (c ({(a b) d} f)))
& @List.cons ~ (b (e f))
& @List.map ~ (c (d e))
@List.nil = (* (a a))
@List.reduce = ((@List.reduce__C0 ((a (* a)) (b (c d)))) (c (b d)))
@List.reduce__C0 = (d (a (c ({b (c (d e))} f))))
& @List.reduce ~ (a (b (e f)))
@List.reverse_bad = ((@List.reverse_bad__C0 (@List.nil a)) a)
@List.reverse_bad__C0 = (c (a e))
& @List.concat ~ (b (d e))
& @List.reverse_bad ~ (a b)
& @List.cons ~ (c (@List.nil d))
@List.reverse_over = ((@List.reverse_over__C0 ((a a) b)) b)
@List.reverse_over__C0 = (b (a (c e)))
& @List.reverse_over ~ (a (d e))
& @List.cons ~ (b (c d))
@List.reverse_tr = (a (* b))
& @List.reverse_over ~ (a (@List.nil b))
@List.sum = ((@List.sum__C0 ((a a) b)) b)
@List.sum__C0 = ($(:[+] $(b c)) (a (b d)))
& @List.sum ~ (a (c d))
@Tree.flip = ((@Tree.flip__C1 (@Tree.flip__C0 a)) a)
@Tree.flip__C0 = a
& @Tree.leaf ~ a
@Tree.flip__C1 = (c (a e))
& @Tree.node ~ (b (d e))
& @Tree.flip ~ (a b)
&! @Tree.flip ~ (c d)
@Tree.height = ((@Tree.height__C0 ((* 0) a)) a)
@Tree.height__C0 = (a (c f))
& $(e f) ~ [+1]
& @max ~ (b (d e))
& @Tree.height ~ (a b)
&! @Tree.height ~ (c d)
@Tree.leaf = (a (* ((a b) b)))
@Tree.leaves = ((@Tree.leaves__C0 ((* 1) a)) a)
@Tree.leaves__C0 = (a (b d))
& @Tree.leaves ~ (a $(:[+] $(c d)))
&! @Tree.leaves ~ (b c)
@Tree.map = ((@Tree.map__C1 (@Tree.map__C0 a)) a)
@Tree.map__C0 = (a ((a b) c))
& @Tree.leaf ~ (b c)
@Tree.map__C1 = (a (d ({b e} g)))
& @Tree.node ~ (c (f g))
& @Tree.map ~ (a (b c))
&! @Tree.map ~ (d (e f))
@Tree.node = (a (b ((a (b c)) (* c))))
@Tree.nodes = ((@Tree.nodes__C0 ((* 0) a)) a)
@Tree.nodes__C0 = (a (b e))
& $(d e) ~ [+1]
& @Tree.nodes ~ (a $(:[+] $(c d)))
&! @Tree.nodes ~ (b c)
@add = ((@add__C0 ((a a) b)) b)
@add__C0 = (a (b d))
& @add ~ (a (((b c) (* c)) d))
@calc = l
& @Foo ~ (f (h (k l)))
& 1 ~ {$(:[+] $(e f)) {$(:[*] $(a {e {$(:[*] $(b {$(:[+] $(g h)) {$(:[*] $(c {g {$(:[*] $(d {$(:[+] $(j k)) {$(:[*] $(i j)) i}})) d}})) c}})) b}})) a}}
@fold_ = ((@fold___C1 (@fold___C0 a)) a)
@fold___C0 = (((* (a a)) b) (* b))
@ -14,10 +124,12 @@ input_file: tests/golden_tests/compile_file/redex_order_recursive.hvm
@fold___C1 = (a (c e))
& @add ~ (b (d e))
& @fold_ ~ (a b)
& @fold_ ~ (c d)
&! @fold_ ~ (c d)
@main = *
@max = ({$(:[>] $(a ?(((b (* b)) (* (* (c c)))) (d (e f))))) e} ({a d} f))
@tail_recursive = ((@tail_recursive__C0 ((* 0) a)) a)
@tail_recursive__C0 = (a (b d))

View File

@ -0,0 +1,5 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/simple_tup.hvm
---
@main = (0 42)

View File

@ -0,0 +1,5 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/tup.hvm
---
@main = ((1 4) (2 3))

View File

@ -1,6 +1,6 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_term/tup_add.hvm
input_file: tests/golden_tests/compile_file/tup_add.hvm
---
b
@main = b
& (1 2) ~ ($(:[+] $(a b)) a)

View File

@ -0,0 +1,7 @@
---
source: tests/golden_tests.rs
input_file: tests/golden_tests/compile_file/unbound_var.hvm
---
Errors:
In definition 'main':
Unbound variable 'a'.

Some files were not shown because too many files have changed in this diff Show More