diff --git a/examples/hello_world.bend b/examples/hello_world.bend index a1e3ce631..81ad13e50 100644 --- a/examples/hello_world.bend +++ b/examples/hello_world.bend @@ -1,4 +1,4 @@ def main(): with IO: - * <- IO/print("Hello, world!") + * <- IO/print("Hello, world!\n") return wrap(0) \ No newline at end of file diff --git a/src/hvm/check_net_size.rs b/src/hvm/check_net_size.rs index ff733be60..f524ff121 100644 --- a/src/hvm/check_net_size.rs +++ b/src/hvm/check_net_size.rs @@ -1,17 +1,27 @@ use super::tree_children; -use crate::{diagnostics::Diagnostics, fun::Name}; +use crate::{diagnostics::Diagnostics, fun::Name, CompilerTarget}; use hvm::ast::{Book, Net, Tree}; -pub const MAX_NET_SIZE: usize = 64; +pub const MAX_NET_SIZE_C: usize = 4095; +pub const MAX_NET_SIZE_CUDA: usize = 64; + +pub fn check_net_sizes( + book: &Book, + diagnostics: &mut Diagnostics, + target: &CompilerTarget, +) -> Result<(), Diagnostics> { + let (net_size_bound, target_lang) = match target { + CompilerTarget::Cuda => (MAX_NET_SIZE_CUDA, "Cuda"), + _ => (MAX_NET_SIZE_C, "C"), + }; -pub fn check_net_sizes(book: &Book, diagnostics: &mut Diagnostics) -> Result<(), Diagnostics> { diagnostics.start_pass(); for (name, net) in &book.defs { let nodes = count_nodes(net); - if nodes > MAX_NET_SIZE { + if nodes > net_size_bound { diagnostics.add_rule_error( - format!("Definition is too large for hvm (size={nodes}, max size={MAX_NET_SIZE}). Please break it into smaller pieces."), + format!("Definition is too large for HVM {target_lang} (size={nodes}, max size={net_size_bound}). Please break it into smaller pieces."), Name::new(name), ); } diff --git a/src/lib.rs b/src/lib.rs index 2af6bf988..209d32bf2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,7 @@ use crate::{ fun::{book_to_hvm, net_to_term::net_to_term, term_to_net::Labels, Book, Ctx, Term}, hvm::{ add_recursive_priority::add_recursive_priority, - check_net_size::{check_net_sizes, MAX_NET_SIZE}, + check_net_size::{check_net_sizes, MAX_NET_SIZE_CUDA}, eta_reduce::eta_reduce_hvm_net, hvm_book_show_pretty, inline::inline_hvm_book, @@ -73,7 +73,7 @@ pub fn compile_book( } if opts.check_net_size { - check_net_sizes(&hvm_book, &mut diagnostics)?; + check_net_sizes(&hvm_book, &mut diagnostics, &opts.target_architecture)?; } add_recursive_priority(&mut hvm_book); @@ -143,7 +143,7 @@ pub fn desugar_book( ctx.check_unbound_vars()?; if opts.float_combinators { - ctx.book.float_combinators(MAX_NET_SIZE); + ctx.book.float_combinators(MAX_NET_SIZE_CUDA); } // sanity check ctx.check_unbound_refs()?; @@ -329,8 +329,18 @@ impl OptLevel { } } +#[derive(Clone, Debug)] +pub enum CompilerTarget { + C, + Cuda, + Unknown, +} + #[derive(Clone, Debug)] pub struct CompileOpts { + /// The Compiler target architecture + pub target_architecture: CompilerTarget, + /// Enables [hvm::eta_reduce]. pub eta: bool, @@ -361,6 +371,7 @@ impl CompileOpts { #[must_use] pub fn set_all(self) -> Self { Self { + target_architecture: self.target_architecture, eta: true, prune: true, float_combinators: true, @@ -376,6 +387,7 @@ impl CompileOpts { #[must_use] pub fn set_no_all(self) -> Self { Self { + target_architecture: self.target_architecture, eta: false, prune: false, linearize_matches: OptLevel::Disabled, @@ -406,13 +418,14 @@ impl Default for CompileOpts { /// Uses num-scott ADT encoding. fn default() -> Self { Self { + target_architecture: CompilerTarget::Unknown, eta: true, prune: false, linearize_matches: OptLevel::Enabled, float_combinators: true, merge: false, inline: false, - check_net_size: false, + check_net_size: true, adt_encoding: AdtEncoding::NumScott, } } diff --git a/src/main.rs b/src/main.rs index 82f3cc230..02f5b2743 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ use bend::{ fun::{Book, Name}, hvm::hvm_book_show_pretty, imports::DefaultLoader, - load_file_to_book, run_book, AdtEncoding, CompileOpts, OptLevel, RunOpts, + load_file_to_book, run_book, AdtEncoding, CompileOpts, CompilerTarget, OptLevel, RunOpts, }; use clap::{Args, CommandFactory, Parser, Subcommand}; use std::{ @@ -190,9 +190,9 @@ pub enum OptArgs { AdtNumScott, } -fn compile_opts_from_cli(args: &Vec) -> CompileOpts { +fn compile_opts_from_cli(args: &Vec, compiler_target: CompilerTarget) -> CompileOpts { use OptArgs::*; - let mut opts = CompileOpts::default(); + let mut opts = CompileOpts { target_architecture: compiler_target, ..CompileOpts::default() }; for arg in args { match arg { @@ -288,10 +288,18 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Diagnostics> { _ => "run-c", }; + let compiler_target = match &cli.mode { + Mode::RunC(..) => CompilerTarget::C, + Mode::GenC(..) => CompilerTarget::C, + Mode::RunCu(..) => CompilerTarget::Cuda, + Mode::GenCu(..) => CompilerTarget::Cuda, + _ => CompilerTarget::Unknown, + }; + match cli.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 compile_opts = compile_opts_from_cli(&comp_opts, compiler_target); let mut book = load_book(&path, diagnostics_cfg)?; let diagnostics = check_book(&mut book, diagnostics_cfg, compile_opts)?; @@ -300,7 +308,7 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Diagnostics> { Mode::GenHvm(GenArgs { comp_opts, warn_opts, path, .. }) => { let diagnostics_cfg = set_warning_cfg_from_cli(DiagnosticsConfig::default(), warn_opts); - let opts = compile_opts_from_cli(&comp_opts); + let opts = compile_opts_from_cli(&comp_opts, compiler_target); let mut book = load_book(&path, diagnostics_cfg)?; let compile_res = compile_book(&mut book, opts, diagnostics_cfg, None)?; @@ -317,7 +325,7 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Diagnostics> { let diagnostics_cfg = set_warning_cfg_from_cli(DiagnosticsConfig::new(Severity::Allow, arg_verbose), warn_opts); - let compile_opts = compile_opts_from_cli(&comp_opts); + let compile_opts = compile_opts_from_cli(&comp_opts, compiler_target); compile_opts.check_for_strict(); @@ -342,7 +350,7 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Diagnostics> { Mode::GenC(GenArgs { comp_opts, warn_opts, path }) | Mode::GenCu(GenArgs { comp_opts, warn_opts, path }) => { let diagnostics_cfg = set_warning_cfg_from_cli(DiagnosticsConfig::default(), warn_opts); - let opts = compile_opts_from_cli(&comp_opts); + let opts = compile_opts_from_cli(&comp_opts, compiler_target); let mut book = load_book(&path, diagnostics_cfg)?; let compile_res = compile_book(&mut book, opts, diagnostics_cfg, None)?; @@ -373,7 +381,7 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Diagnostics> { 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); + let opts = compile_opts_from_cli(&comp_opts, compiler_target); let mut book = load_book(&path, diagnostics_cfg)?; let diagnostics = desugar_book(&mut book, opts, diagnostics_cfg, None)?; diff --git a/tests/snapshots/cli__net_size_too_large.bend.snap b/tests/snapshots/cli__net_size_too_large.bend.snap index 0d3f91caf..60d1eeacc 100644 --- a/tests/snapshots/cli__net_size_too_large.bend.snap +++ b/tests/snapshots/cli__net_size_too_large.bend.snap @@ -2,6 +2,170 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/cli/net_size_too_large.bend --- -Errors: -In definition 'Radix': - Definition is too large for hvm (size=120, max size=64). Please break it into smaller pieces. +@Arr/Leaf = (a ((@Arr/Leaf/tag (a b)) b)) + +@Arr/Leaf/tag = 1 + +@Arr/Node = (a (b ((@Arr/Node/tag (a (b c))) c))) + +@Arr/Node/tag = 2 + +@Arr/Null = ((@Arr/Null/tag a) a) + +@Arr/Null/tag = 0 + +@Gen = (a b) + & @Gen.go ~ (a (0 b)) + +@Gen.go = (?((@Gen.go__C0 @Gen.go__C1) a) a) + +@Gen.go__C0 = a + & @Arr/Leaf ~ a + +@Gen.go__C1 = ({a d} ({$([*0x0000002] $([|0x0000001] e)) $([*0x0000002] b)} g)) + & @Arr/Node ~ (c (f g)) + &!@Gen.go ~ (a (b c)) + &!@Gen.go ~ (d (e f)) + +@Map_/Both = (a (b ((@Map_/Both/tag (a (b c))) c))) + +@Map_/Both/tag = 2 + +@Map_/Free = ((@Map_/Free/tag a) a) + +@Map_/Free/tag = 0 + +@Map_/Used = ((@Map_/Used/tag a) a) + +@Map_/Used/tag = 1 + +@Merge = ((@Merge__C13 a) a) + +@Merge__C0 = (* a) + & @Map_/Both ~ a + +@Merge__C1 = (?((@Map_/Used @Merge__C0) a) a) + +@Merge__C10 = (* (a (b ((@Merge__C8 (a (b c))) c)))) + +@Merge__C11 = ((@Merge__C2 a) a) + +@Merge__C12 = (?((@Merge__C9 @Merge__C10) a) a) + +@Merge__C13 = (?((@Merge__C11 @Merge__C12) a) a) + +@Merge__C2 = (?((@Map_/Free @Merge__C1) a) a) + +@Merge__C3 = (?((@Map_/Used *) a) a) + +@Merge__C4 = (?((@Map_/Used @Merge__C3) a) a) + +@Merge__C5 = (* (b (e (a (d g))))) + & @Map_/Both ~ (c (f g)) + &!@Merge ~ (a (b c)) + &!@Merge ~ (d (e f)) + +@Merge__C6 = a + & @Map_/Both ~ a + +@Merge__C7 = (?((* @Merge__C5) a) a) + +@Merge__C8 = (?((@Merge__C6 @Merge__C7) a) a) + +@Merge__C9 = ((@Merge__C4 a) a) + +@Radix = ({$([&0x0800000] a) {$([&0x0400000] b) {$([&0x0200000] c) {$([&0x0100000] d) {$([&0x0080000] e) {$([&0x0040000] f) {$([&0x0020000] g) {$([&0x0010000] h) {$([&0x0008000] i) {$([&0x0004000] j) {$([&0x0002000] k) {$([&0x0001000] l) {$([&0x0000800] m) {$([&0x0000400] n) {$([&0x0000200] o) {$([&0x0000100] p) {$([&0x0000080] q) {$([&0x0000040] r) {$([&0x0000020] s) {$([&0x0000010] t) {$([&0x0000008] u) {$([&0x0000004] v) {$([&0x0000002] w) $([&0x0000001] x)}}}}}}}}}}}}}}}}}}}}}}} vb) + & @Swap ~ (a (ub (@Map_/Free vb))) + & @Swap ~ (b (tb (@Map_/Free ub))) + & @Swap ~ (c (sb (@Map_/Free tb))) + & @Swap ~ (d (rb (@Map_/Free sb))) + & @Swap ~ (e (qb (@Map_/Free rb))) + & @Swap ~ (f (pb (@Map_/Free qb))) + & @Swap ~ (g (ob (@Map_/Free pb))) + & @Swap ~ (h (nb (@Map_/Free ob))) + & @Swap ~ (i (mb (@Map_/Free nb))) + & @Swap ~ (j (lb (@Map_/Free mb))) + & @Swap ~ (k (kb (@Map_/Free lb))) + & @Swap ~ (l (jb (@Map_/Free kb))) + & @Swap ~ (m (ib (@Map_/Free jb))) + & @Swap ~ (n (hb (@Map_/Free ib))) + & @Swap ~ (o (gb (@Map_/Free hb))) + & @Swap ~ (p (fb (@Map_/Free gb))) + & @Swap ~ (q (eb (@Map_/Free fb))) + & @Swap ~ (r (db (@Map_/Free eb))) + & @Swap ~ (s (cb (@Map_/Free db))) + & @Swap ~ (t (bb (@Map_/Free cb))) + & @Swap ~ (u (ab (@Map_/Free bb))) + & @Swap ~ (v (z (@Map_/Free ab))) + & @Swap ~ (w (y (@Map_/Free z))) + & @Swap ~ (x (@Map_/Used (@Map_/Free y))) + +@Reverse = ((@Reverse__C3 a) a) + +@Reverse__C0 = a + & @Arr/Leaf ~ a + +@Reverse__C1 = (* (c (a e))) + & @Arr/Node ~ (b (d e)) + &!@Reverse ~ (a b) + &!@Reverse ~ (c d) + +@Reverse__C2 = (?((@Reverse__C0 @Reverse__C1) a) a) + +@Reverse__C3 = (?((@Arr/Null @Reverse__C2) a) a) + +@Sort = (a c) + & @ToArr ~ (0 (b c)) + & @ToMap ~ (a b) + +@Sum = ((@Sum__C2 a) a) + +@Sum__C0 = (* (a (b d))) + &!@Sum ~ (a $([+] $(c d))) + &!@Sum ~ (b c) + +@Sum__C1 = (?(((a a) @Sum__C0) b) b) + +@Sum__C2 = (?((0 @Sum__C1) a) a) + +@Swap = (?((@Swap__C0 @Swap__C1) a) a) + +@Swap__C0 = a + & @Map_/Both ~ a + +@Swap__C1 = (* (b (a c))) + & @Map_/Both ~ (a (b c)) + +@ToArr = (a ((@ToArr__C3 (a b)) b)) + +@ToArr__C0 = a + & @Arr/Leaf ~ a + +@ToArr__C1 = (* (b (e ({$([*0x0000002] $([+0x0000001] d)) $([*0x0000002] $([+0x0000000] a))} g)))) + & @Arr/Node ~ (c (f g)) + &!@ToArr ~ (a (b c)) + &!@ToArr ~ (d (e f)) + +@ToArr__C2 = (?((@ToArr__C0 @ToArr__C1) a) a) + +@ToArr__C3 = (?(((* @Arr/Null) @ToArr__C2) a) a) + +@ToMap = ((@ToMap__C3 a) a) + +@ToMap__C0 = a + & @Radix ~ a + +@ToMap__C1 = (* (a (c e))) + & @Merge ~ (b (d e)) + &!@ToMap ~ (a b) + &!@ToMap ~ (c d) + +@ToMap__C2 = (?((@ToMap__C0 @ToMap__C1) a) a) + +@ToMap__C3 = (?((@Map_/Free @ToMap__C2) a) a) + +@main = d + & @Sum ~ (c d) + & @Sort ~ (b c) + & @Reverse ~ (a b) + & @Gen ~ (4 a) diff --git a/tests/snapshots/compile_long__huge_tree.bend.snap b/tests/snapshots/compile_long__huge_tree.bend.snap index d5a8a014d..ee6c230f5 100644 --- a/tests/snapshots/compile_long__huge_tree.bend.snap +++ b/tests/snapshots/compile_long__huge_tree.bend.snap @@ -2,4 +2,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_long/huge_tree.bend --- -Compiled +Errors: +In definition 'main': + Definition is too large for HVM C (size=120002, max size=4095). Please break it into smaller pieces. diff --git a/tests/snapshots/compile_long__long_str_file.bend.snap b/tests/snapshots/compile_long__long_str_file.bend.snap index 5f780d9ea..b4e9f10d8 100644 --- a/tests/snapshots/compile_long__long_str_file.bend.snap +++ b/tests/snapshots/compile_long__long_str_file.bend.snap @@ -2,4 +2,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_long/long_str_file.bend --- -Compiled +Errors: +In definition 'main': + Definition is too large for HVM C (size=1461028, max size=4095). Please break it into smaller pieces.