diff --git a/tests/programs/fail/is_not.vi b/tests/programs/fail/is_not.vi new file mode 100644 index 00000000..be6c2479 --- /dev/null +++ b/tests/programs/fail/is_not.vi @@ -0,0 +1,8 @@ + +fn main(x) { + if x is y {} else { y } + if !(x is y) { y } + if x is y || y is z { (y, z) } + while x is y {} + y +} diff --git a/tests/programs/logic.vi b/tests/programs/logic.vi new file mode 100644 index 00000000..756f1e36 --- /dev/null +++ b/tests/programs/logic.vi @@ -0,0 +1,30 @@ + +use std::{io::println, bool::{true, false}}; + +fn main(&io) { + io.print_bool(true); + io.print_bool(true && true); + io.print_bool(true || true); + io.print_bool(true || false); + io.print_bool(false || true); + io.print_bool(!false); + io.print_bool(!!true); + io.println("---"); + io.print_bool(false); + io.print_bool(false || false); + io.print_bool(true && false); + io.print_bool(false && true); + io.print_bool(false && false); + io.print_bool(!true); + io.print_bool(!!false); + + // Test short-circuiting behavior; `()` is an eraser node, + // so would erase `io` if it was evaluated. + io.println("---"); + io.print_bool(true || ()); + io.print_bool(false && ()); +} + +fn print_bool(&io, bool) { + io.println(if bool { "true" } else { "false" }) +} diff --git a/tests/programs/option_party.vi b/tests/programs/option_party.vi index acf17df7..02adc3bc 100644 --- a/tests/programs/option_party.vi +++ b/tests/programs/option_party.vi @@ -12,10 +12,6 @@ use std::{ and_then, or, unwrap_or, - is_some, - is_none, - is_some_and, - is_none_or, unwrap, } }; @@ -58,17 +54,17 @@ fn main(io) { io.print_u32(Some(1).unwrap_or(0)); io.println("is_some:"); - io.print_bool(None.is_some()); - io.print_bool(Some(()).is_some()); + io.print_bool(None is Some(_)); + io.print_bool(Some(()) is Some(_)); io.println("is_none:"); - io.print_bool(None.is_none()); - io.print_bool(Some(()).is_none()); + io.print_bool(None is None); + io.print_bool(Some(()) is None); io.println("is_some_and:"); - io.print_bool(None.is_some_and(fn(x) x > 0)); - io.print_bool(Some(0).is_some_and(fn(x) x > 0)); - io.print_bool(Some(1).is_some_and(fn(x) x > 0)); + io.print_bool(None is Some(x) && x > 0); + io.print_bool(Some(0) is Some(x) && x > 0); + io.print_bool(Some(1) is Some(x) && x > 0); io.println("is_none_or:"); io.print_bool(None.is_none_or(fn(x) x > 0)); @@ -106,3 +102,10 @@ fn increment_option(&option) { fn add_options(a, b) { a.and_then(fn(a) b.map(fn(b) a + b)) } + +fn is_none_or(&move self, f) { + match self { + Some(val) => f(val), + None => true, + } +} diff --git a/tests/snaps/vine/basic_diverge/compiled.iv b/tests/snaps/vine/basic_diverge/compiled.iv index b1afea75..63f869c0 100644 --- a/tests/snaps/vine/basic_diverge/compiled.iv +++ b/tests/snaps/vine/basic_diverge/compiled.iv @@ -45,17 +45,17 @@ ::std::str::concat { fn(tup(@add(n0 n1) fn(n3 n4)) fn(tup(n0 fn(n2 n3)) tup(n1 fn(n2 n4)))) } -::std::u32::to_string { fn(dup152(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } +::std::u32::to_string { fn(dup122(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } ::std::u32::to_string::1 { x(n1 n2) ::std::u32::to_string::2 = x(n1 x(tup(0 fn(n0 n0)) n2)) } -::std::u32::to_string::2 { x(dup152(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } +::std::u32::to_string::2 { x(dup122(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } ::std::u32::to_string::3 { - x(dup152(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) + x(dup122(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) 48 = @add(n1 n2) ::std::u32::to_string::2 = x(n5 x(tup(n0 fn(n3 tup(n2 n4))) n6)) } diff --git a/tests/snaps/vine/fail/is_not.txt b/tests/snaps/vine/fail/is_not.txt new file mode 100644 index 00000000..f88a6e28 --- /dev/null +++ b/tests/snaps/vine/fail/is_not.txt @@ -0,0 +1,6 @@ +error tests/programs/fail/is_not.vi:3:23 - cannot find `y` in `::is_not::main` +error tests/programs/fail/is_not.vi:4:18 - cannot find `y` in `::is_not::main` +error tests/programs/fail/is_not.vi:5:16 - cannot find `y` in `::is_not::main` +error tests/programs/fail/is_not.vi:5:26 - cannot find `y` in `::is_not::main` +error tests/programs/fail/is_not.vi:5:29 - cannot find `z` in `::is_not::main` +error tests/programs/fail/is_not.vi:7:3 - cannot find `y` in `::is_not::main` diff --git a/tests/snaps/vine/fib/compiled.iv b/tests/snaps/vine/fib/compiled.iv index c5764432..7062c0ad 100644 --- a/tests/snaps/vine/fib/compiled.iv +++ b/tests/snaps/vine/fib/compiled.iv @@ -45,17 +45,17 @@ ::std::str::concat { fn(tup(@add(n0 n1) fn(n3 n4)) fn(tup(n0 fn(n2 n3)) tup(n1 fn(n2 n4)))) } -::std::u32::to_string { fn(dup150(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } +::std::u32::to_string { fn(dup120(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } ::std::u32::to_string::1 { x(n1 n2) ::std::u32::to_string::2 = x(n1 x(tup(0 fn(n0 n0)) n2)) } -::std::u32::to_string::2 { x(dup150(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } +::std::u32::to_string::2 { x(dup120(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } ::std::u32::to_string::3 { - x(dup150(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) + x(dup120(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) 48 = @add(n1 n2) ::std::u32::to_string::2 = x(n5 x(tup(n0 fn(n3 tup(n2 n4))) n6)) } diff --git a/tests/snaps/vine/fib_repl/compiled.iv b/tests/snaps/vine/fib_repl/compiled.iv index cdc9b3dc..3e922f7c 100644 --- a/tests/snaps/vine/fib_repl/compiled.iv +++ b/tests/snaps/vine/fib_repl/compiled.iv @@ -27,10 +27,10 @@ ::fib_repl::fib::1 = x(n0 x(0 x(n1 1))) } -::fib_repl::fib::1 { x(dup13(?(::fib_repl::fib::3 ::fib_repl::fib::2 x(n3 n0)) n3) n0) } +::fib_repl::fib::1 { x(dup12(?(::fib_repl::fib::3 ::fib_repl::fib::2 x(n3 n0)) n3) n0) } ::fib_repl::fib::2 { - x(@sub(1 n3) x(@add(n2 n0) x(n5 dup15(n1 n2)))) + x(@sub(1 n3) x(@add(n2 n0) x(n5 dup14(n1 n2)))) tup(n1 n0) = tup(n4 n6) ::fib_repl::fib::1 = x(n3 x(n4 x(n5 n6))) } @@ -48,7 +48,7 @@ ::std::io::print::1 = x(n0 x(n1 x(n2 n3))) } -::std::io::print::1 { x(n0 x(n1 x(dup26(?(::std::io::print::3 ::std::io::print::2 x(n0 x(n1 x(n3 n2)))) n3) n2))) } +::std::io::print::1 { x(n0 x(n1 x(dup25(?(::std::io::print::3 ::std::io::print::2 x(n0 x(n1 x(n3 n2)))) n3) n2))) } ::std::io::print::2 { x(n1 x(n3 x(@sub(1 n4) tup(n0 n5)))) @@ -71,11 +71,11 @@ ::std::io::read_line { fn(ref(n0 n2) n3) - ::std::io::read_byte = fn(ref(n0 n1) fn(0 dup45(?(::std::io::read_line::9 ::std::io::read_line::1 x(n1 x(n2 x(n4 n3)))) n4))) + ::std::io::read_byte = fn(ref(n0 n1) fn(0 dup44(?(::std::io::read_line::9 ::std::io::read_line::1 x(n1 x(n2 x(n4 n3)))) n4))) } ::std::io::read_line::1 { - x(n1 x(n2 x(dup45(@eq(10 ?(::std::io::read_line::3 ::std::io::read_line::2 x(n1 x(n2 x(n4 n3))))) n4) n0))) + x(n1 x(n2 x(dup44(@eq(10 ?(::std::io::read_line::3 ::std::io::read_line::2 x(n1 x(n2 x(n4 n3))))) n4) n0))) ::std::option::Option::Some = fn(n3 n0) } @@ -89,7 +89,7 @@ ::std::io::read_line::4 { x(n0 x(n2 n3)) - ::std::io::read_byte = fn(ref(n0 n1) fn(10 dup45(@ne(10 ?(::std::io::read_line::6 ::std::io::read_line::5 x(n1 x(n2 x(n5 n3))))) n5))) + ::std::io::read_byte = fn(ref(n0 n1) fn(10 dup44(@ne(10 ?(::std::io::read_line::6 ::std::io::read_line::5 x(n1 x(n2 x(n5 n3))))) n5))) } ::std::io::read_line::5 { @@ -113,17 +113,17 @@ ::std::str::single { fn(n0 tup(1 fn(n1 tup(n0 n1)))) } -::std::u32::to_string { fn(dup160(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } +::std::u32::to_string { fn(dup129(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } ::std::u32::to_string::1 { x(n1 n2) ::std::u32::to_string::2 = x(n1 x(tup(0 fn(n0 n0)) n2)) } -::std::u32::to_string::2 { x(dup160(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } +::std::u32::to_string::2 { x(dup129(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } ::std::u32::to_string::3 { - x(dup160(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) + x(dup129(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) 48 = @add(n1 n2) ::std::u32::to_string::2 = x(n5 x(tup(n0 fn(n3 tup(n2 n4))) n6)) } @@ -132,11 +132,11 @@ ::std::u32::to_string::5 { x(_ tup(1 fn(n0 tup(48 n0)))) } -::std::u32::parse { fn(tup(dup170(@eq(0 ?(::std::u32::parse::2 ::std::u32::parse::1 x(n2 x(n0 n1)))) n2) n0) n1) } +::std::u32::parse { fn(tup(dup139(@eq(0 ?(::std::u32::parse::2 ::std::u32::parse::1 x(n2 x(n0 n1)))) n2) n0) n1) } ::std::u32::parse::1 { x(_ x(_ n0)) - ::std::u32::parse::12 = x(n0 ::std::option::Option::None) + ::std::u32::parse::11 = x(n0 ::std::option::Option::None) } ::std::u32::parse::2 { @@ -144,27 +144,27 @@ ::std::u32::parse::3 = x(n0 x(n1 x(0 n2))) } -::std::u32::parse::3 { x(dup170(?(::std::u32::parse::9 ::std::u32::parse::4 x(n3 n0)) n3) n0) } +::std::u32::parse::3 { x(dup139(?(::std::u32::parse::9 ::std::u32::parse::4 x(n3 n0)) n3) n0) } ::std::u32::parse::4 { - x(n2 x(tup(dup174(dup(n0 @le(57 n1)) n6) n3) x(n4 n5))) - 48 = @le(n0 @u32_and(n1 @ne(1 ?(::std::u32::parse::8 ::std::u32::parse::5 x(n2 x(n3 x(n4 x(n6 n5)))))))) + x(n2 x(tup(dup143(dup(n0 @le(57 n1)) n6) n3) x(n4 n5))) + 48 = @le(n0 @u32_and(n1 ?(::std::u32::parse::6 ::std::u32::parse::8 x(n2 x(n3 x(n4 x(n6 n5))))))) } -::std::u32::parse::5 { x(_ x(_ x(_ x(_ ::std::option::Option::None)))) } +::std::u32::parse::6 { x(_ x(_ x(_ x(_ ::std::option::Option::None)))) } ::std::u32::parse::8 { x(@sub(1 n1) x(n2 x(@mul(10 @add(n0 n3)) x(@sub(48 n0) n4)))) ::std::u32::parse::3 = x(n1 x(n2 x(n3 n4))) } -::std::u32::parse::9 { x(_ x(_ ::std::u32::parse::11)) } +::std::u32::parse::9 { x(_ x(_ ::std::u32::parse::10)) } -::std::u32::parse::11 { +::std::u32::parse::10 { x(n0 n1) ::std::option::Option::Some = fn(n0 n2) - ::std::u32::parse::12 = x(n1 n2) + ::std::u32::parse::11 = x(n1 n2) } -::std::u32::parse::12 { x(n0 n0) } +::std::u32::parse::11 { x(n0 n0) } diff --git a/tests/snaps/vine/fib_repl/stats.txt b/tests/snaps/vine/fib_repl/stats.txt index 84d4f514..ccf805bf 100644 --- a/tests/snaps/vine/fib_repl/stats.txt +++ b/tests/snaps/vine/fib_repl/stats.txt @@ -1,15 +1,15 @@ Interactions - Total 14_008_829 + Total 14_008_806 Annihilate 6_004_137 Commute 0 Copy 2_000_867 Erase 1_000_873 Expand 2_001_376 - Call 2_001_063 + Call 2_001_040 Branch 1_000_513 Memory Heap 720 B - Allocated 272_172_832 B - Freed 272_172_832 B + Allocated 272_172_464 B + Freed 272_172_464 B diff --git a/tests/snaps/vine/fizzbuzz/compiled.iv b/tests/snaps/vine/fizzbuzz/compiled.iv index 75884438..c65ae86b 100644 --- a/tests/snaps/vine/fizzbuzz/compiled.iv +++ b/tests/snaps/vine/fizzbuzz/compiled.iv @@ -55,17 +55,17 @@ ::std::io::print_char { fn(ref(@io_print_char(char io) io) fn(char _)) } -::std::u32::to_string { fn(dup156(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } +::std::u32::to_string { fn(dup126(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } ::std::u32::to_string::1 { x(n1 n2) ::std::u32::to_string::2 = x(n1 x(tup(0 fn(n0 n0)) n2)) } -::std::u32::to_string::2 { x(dup156(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } +::std::u32::to_string::2 { x(dup126(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } ::std::u32::to_string::3 { - x(dup156(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) + x(dup126(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) 48 = @add(n1 n2) ::std::u32::to_string::2 = x(n5 x(tup(n0 fn(n3 tup(n2 n4))) n6)) } diff --git a/tests/snaps/vine/inverse/compiled.iv b/tests/snaps/vine/inverse/compiled.iv index 41a1a994..de6da720 100644 --- a/tests/snaps/vine/inverse/compiled.iv +++ b/tests/snaps/vine/inverse/compiled.iv @@ -93,17 +93,17 @@ ::std::str::concat { fn(tup(@add(n0 n1) fn(n3 n4)) fn(tup(n0 fn(n2 n3)) tup(n1 fn(n2 n4)))) } -::std::u32::to_string { fn(dup176(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } +::std::u32::to_string { fn(dup146(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } ::std::u32::to_string::1 { x(n1 n2) ::std::u32::to_string::2 = x(n1 x(tup(0 fn(n0 n0)) n2)) } -::std::u32::to_string::2 { x(dup176(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } +::std::u32::to_string::2 { x(dup146(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } ::std::u32::to_string::3 { - x(dup176(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) + x(dup146(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) 48 = @add(n1 n2) ::std::u32::to_string::2 = x(n5 x(tup(n0 fn(n3 tup(n2 n4))) n6)) } diff --git a/tests/snaps/vine/logic/compiled.iv b/tests/snaps/vine/logic/compiled.iv new file mode 100644 index 00000000..6a259298 --- /dev/null +++ b/tests/snaps/vine/logic/compiled.iv @@ -0,0 +1,121 @@ + +::main { ::logic::main } + +::logic::main { + fn(ref(n0 n33) _) + ::logic::print_bool = fn(ref(n0 n1) fn(1 _)) + ::logic::print_bool = fn(ref(n1 n3) fn(n2 _)) + 1 = ?(0 ::logic::main::2 n2) + ::logic::print_bool = fn(ref(n3 n5) fn(n4 _)) + 1 = ?(::logic::main::8 1 n4) + ::logic::print_bool = fn(ref(n5 n7) fn(n6 _)) + 1 = ?(::logic::main::13 1 n6) + ::logic::print_bool = fn(ref(n7 n9) fn(n8 _)) + 0 = ?(::logic::main::18 1 n8) + ::logic::print_bool = fn(ref(n9 n11) fn(n10 _)) + 0 = ?(1 0 n10) + ::logic::print_bool = fn(ref(n11 n13) fn(n12 _)) + 1 = ?(0 1 n12) + ::std::io::println = fn(ref(n13 n15) fn(tup(3 fn(n14 tup(45 tup(45 tup(45 n14))))) _)) + ::logic::print_bool = fn(ref(n15 n16) fn(0 _)) + ::logic::print_bool = fn(ref(n16 n18) fn(n17 _)) + 0 = ?(::logic::main::27 1 n17) + ::logic::print_bool = fn(ref(n18 n20) fn(n19 _)) + 1 = ?(0 ::logic::main::31 n19) + ::logic::print_bool = fn(ref(n20 n22) fn(n21 _)) + 0 = ?(0 ::logic::main::36 n21) + ::logic::print_bool = fn(ref(n22 n24) fn(n23 _)) + 0 = ?(0 ::logic::main::41 n23) + ::logic::print_bool = fn(ref(n24 n26) fn(n25 _)) + 1 = ?(1 0 n25) + ::logic::print_bool = fn(ref(n26 n28) fn(n27 _)) + 0 = ?(0 1 n27) + ::std::io::println = fn(ref(n28 n30) fn(tup(3 fn(n29 tup(45 tup(45 tup(45 n29))))) _)) + ::logic::print_bool = fn(ref(n30 n32) fn(n31 _)) + 1 = ?(::logic::main::51 1 n31) + ::logic::print_bool = fn(ref(n32 n33) fn(n34 _)) + 0 = ?(0 ::logic::main::55 n34) +} + +::logic::main::2 { + n0 + 1 = ?(0 1 n0) +} + +::logic::main::8 { + n0 + 1 = ?(0 1 n0) +} + +::logic::main::13 { + n0 + 0 = ?(0 1 n0) +} + +::logic::main::18 { + n0 + 1 = ?(0 1 n0) +} + +::logic::main::27 { + n0 + 0 = ?(0 1 n0) +} + +::logic::main::31 { + n0 + 0 = ?(0 1 n0) +} + +::logic::main::36 { + n0 + 1 = ?(0 1 n0) +} + +::logic::main::41 { + n0 + 0 = ?(0 1 n0) +} + +::logic::main::51 { + n0 + _ = ?(0 1 n0) +} + +::logic::main::55 { + n0 + _ = ?(0 1 n0) +} + +::logic::print_bool { + fn(n0 fn(?(::logic::print_bool::2 ::logic::print_bool::1 n2) n3)) + ::std::io::println = fn(n0 fn(n2 n3)) +} + +::logic::print_bool::1 { tup(4 fn(n0 tup(116 tup(114 tup(117 tup(101 n0)))))) } + +::logic::print_bool::2 { tup(5 fn(n0 tup(102 tup(97 tup(108 tup(115 tup(101 n0))))))) } + +::std::io::println { + fn(ref(n0 n3) fn(n1 _)) + ::std::io::print = fn(ref(n0 n2) fn(n1 _)) + ::std::io::print_char = fn(ref(n2 n3) fn(10 _)) +} + +::std::io::print { + fn(ref(n0 n1) fn(tup(n2 fn(_ n3)) _)) + ::std::io::print::1 = x(n0 x(n1 x(n2 n3))) +} + +::std::io::print::1 { x(n0 x(n1 x(dup31(?(::std::io::print::3 ::std::io::print::2 x(n0 x(n1 x(n3 n2)))) n3) n2))) } + +::std::io::print::2 { + x(n1 x(n3 x(@sub(1 n4) tup(n0 n5)))) + ::std::io::print_char = fn(ref(n1 n2) fn(n0 _)) + ::std::io::print::1 = x(n2 x(n3 x(n4 n5))) +} + +::std::io::print::3 { x(n0 x(n0 _)) } + +::std::io::print_char { fn(ref(@io_print_char(char io) io) fn(char _)) } + diff --git a/tests/snaps/vine/logic/output.txt b/tests/snaps/vine/logic/output.txt new file mode 100644 index 00000000..75e32ae6 --- /dev/null +++ b/tests/snaps/vine/logic/output.txt @@ -0,0 +1,18 @@ +true +true +true +true +true +true +true +--- +false +false +false +false +false +false +false +--- +true +false diff --git a/tests/snaps/vine/logic/stats.txt b/tests/snaps/vine/logic/stats.txt new file mode 100644 index 00000000..105a7ee3 --- /dev/null +++ b/tests/snaps/vine/logic/stats.txt @@ -0,0 +1,15 @@ + +Interactions + Total 2_312 + Annihilate 1_230 + Commute 0 + Copy 116 + Erase 300 + Expand 362 + Call 174 + Branch 130 + +Memory + Heap 1_808 B + Allocated 46_080 B + Freed 46_080 B diff --git a/tests/snaps/vine/loop_vi_loop/compiled.iv b/tests/snaps/vine/loop_vi_loop/compiled.iv index 015c9b92..d1112bd8 100644 --- a/tests/snaps/vine/loop_vi_loop/compiled.iv +++ b/tests/snaps/vine/loop_vi_loop/compiled.iv @@ -48,17 +48,17 @@ ::std::io::print_char { fn(ref(@io_print_char(char io) io) fn(char _)) } -::std::u32::to_string { fn(dup149(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } +::std::u32::to_string { fn(dup119(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } ::std::u32::to_string::1 { x(n1 n2) ::std::u32::to_string::2 = x(n1 x(tup(0 fn(n0 n0)) n2)) } -::std::u32::to_string::2 { x(dup149(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } +::std::u32::to_string::2 { x(dup119(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } ::std::u32::to_string::3 { - x(dup149(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) + x(dup119(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) 48 = @add(n1 n2) ::std::u32::to_string::2 = x(n5 x(tup(n0 fn(n3 tup(n2 n4))) n6)) } diff --git a/tests/snaps/vine/mandelbrot_sixel/compiled.iv b/tests/snaps/vine/mandelbrot_sixel/compiled.iv index 2c783a4c..8ac80c33 100644 --- a/tests/snaps/vine/mandelbrot_sixel/compiled.iv +++ b/tests/snaps/vine/mandelbrot_sixel/compiled.iv @@ -123,17 +123,17 @@ ::std::io::flush { fn(ref(@io_flush(0 io) io) _) } -::std::u32::to_string { fn(dup171(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } +::std::u32::to_string { fn(dup141(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } ::std::u32::to_string::1 { x(n1 n2) ::std::u32::to_string::2 = x(n1 x(tup(0 fn(n0 n0)) n2)) } -::std::u32::to_string::2 { x(dup171(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } +::std::u32::to_string::2 { x(dup141(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } ::std::u32::to_string::3 { - x(dup171(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) + x(dup141(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) 48 = @add(n1 n2) ::std::u32::to_string::2 = x(n5 x(tup(n0 fn(n3 tup(n2 n4))) n6)) } diff --git a/tests/snaps/vine/option_party/compiled.iv b/tests/snaps/vine/option_party/compiled.iv index d75f85ee..0f2c6472 100644 --- a/tests/snaps/vine/option_party/compiled.iv +++ b/tests/snaps/vine/option_party/compiled.iv @@ -16,9 +16,9 @@ ::option_party::increment_option = fn(ref(::std::option::Option::None n16) _) ::option_party::print_option_u32 = fn(ref(n15 n18) fn(n16 _)) ::std::option::Option::Some = fn(0 n17) - ::option_party::increment_option = fn(ref(n17 dup5(n116 n117)) _) - ::option_party::print_option_u32 = fn(ref(n18 n19) fn(n116 _)) - ::option_party::increment_option = fn(ref(n117 n20) _) + ::option_party::increment_option = fn(ref(n17 dup5(n109 n110)) _) + ::option_party::print_option_u32 = fn(ref(n18 n19) fn(n109 _)) + ::option_party::increment_option = fn(ref(n110 n20) _) ::option_party::print_option_u32 = fn(ref(n19 n21) fn(n20 _)) ::std::io::println = fn(ref(n21 n23) fn(tup(8 fn(n22 tup(102 tup(108 tup(97 tup(116 tup(116 tup(101 tup(110 tup(58 n22)))))))))) _)) ::option_party::print_option_u32 = fn(ref(n23 n25) fn(n24 _)) @@ -64,43 +64,53 @@ ::std::option::Option::unwrap_or = fn(ref(n65 _) fn(0 n66)) ::std::io::println = fn(ref(n67 n69) fn(tup(8 fn(n68 tup(105 tup(115 tup(95 tup(115 tup(111 tup(109 tup(101 tup(58 n68)))))))))) _)) ::option_party::print_bool = fn(ref(n69 n71) fn(n70 _)) - ::std::option::Option::is_some = fn(ref(::std::option::Option::None _) n70) - ::option_party::print_bool = fn(ref(n71 n74) fn(n73 _)) - ::std::option::Option::Some = fn(_ n72) - ::std::option::Option::is_some = fn(ref(n72 _) n73) - ::std::io::println = fn(ref(n74 n76) fn(tup(8 fn(n75 tup(105 tup(115 tup(95 tup(110 tup(111 tup(110 tup(101 tup(58 n75)))))))))) _)) - ::option_party::print_bool = fn(ref(n76 n78) fn(n77 _)) - ::std::option::Option::is_none = fn(ref(::std::option::Option::None _) n77) - ::option_party::print_bool = fn(ref(n78 n81) fn(n80 _)) - ::std::option::Option::Some = fn(_ n79) - ::std::option::Option::is_none = fn(ref(n79 _) n80) - ::std::io::println = fn(ref(n81 n83) fn(tup(12 fn(n82 tup(105 tup(115 tup(95 tup(115 tup(111 tup(109 tup(101 tup(95 tup(97 tup(110 tup(100 tup(58 n82)))))))))))))) _)) - ::option_party::print_bool = fn(ref(n83 n86) fn(n85 _)) - ::std::option::Option::is_some_and = fn(ref(::std::option::Option::None _) fn(fn(@lt$(0 n84) n84) n85)) - ::option_party::print_bool = fn(ref(n86 n90) fn(n89 _)) - ::std::option::Option::Some = fn(0 n87) - ::std::option::Option::is_some_and = fn(ref(n87 _) fn(fn(@lt$(0 n88) n88) n89)) - ::option_party::print_bool = fn(ref(n90 n94) fn(n93 _)) - ::std::option::Option::Some = fn(1 n91) - ::std::option::Option::is_some_and = fn(ref(n91 _) fn(fn(@lt$(0 n92) n92) n93)) - ::std::io::println = fn(ref(n94 n96) fn(tup(11 fn(n95 tup(105 tup(115 tup(95 tup(110 tup(111 tup(110 tup(101 tup(95 tup(111 tup(114 tup(58 n95))))))))))))) _)) - ::option_party::print_bool = fn(ref(n96 n99) fn(n98 _)) - ::std::option::Option::is_none_or = fn(ref(::std::option::Option::None _) fn(fn(@lt$(0 n97) n97) n98)) - ::option_party::print_bool = fn(ref(n99 n103) fn(n102 _)) - ::std::option::Option::Some = fn(0 n100) - ::std::option::Option::is_none_or = fn(ref(n100 _) fn(fn(@lt$(0 n101) n101) n102)) - ::option_party::print_bool = fn(ref(n103 n107) fn(n106 _)) - ::std::option::Option::Some = fn(1 n104) - ::std::option::Option::is_none_or = fn(ref(n104 _) fn(fn(@lt$(0 n105) n105) n106)) - ::std::io::println = fn(ref(n107 n109) fn(tup(7 fn(n108 tup(117 tup(110 tup(119 tup(114 tup(97 tup(112 tup(58 n108))))))))) _)) - ::option_party::print_u32 = fn(ref(n109 n112) fn(n111 _)) - ::std::option::Option::Some = fn(42 n110) - ::std::option::Option::unwrap = fn(ref(n110 _) n111) - ::option_party::print_u32 = fn(ref(n112 n114) fn(n113 _)) - ::std::option::Option::unwrap = fn(ref(::std::option::Option::None _) n113) - ::std::io::println = fn(ref(n114 _) fn(tup(27 fn(n115 tup(105 tup(111 tup(32 tup(119 tup(105 tup(108 tup(108 tup(32 tup(110 tup(101 tup(118 tup(101 tup(114 tup(32 tup(119 tup(111 tup(114 tup(107 tup(32 tup(97 tup(103 tup(97 tup(105 tup(110 tup(32 tup(58 tup(40 n115))))))))))))))))))))))))))))) _)) + ::std::option::Option::None = enum(::option_party::main::1 enum(0 n70)) + ::option_party::print_bool = fn(ref(n71 n73) fn(n72 _)) + ::std::option::Option::Some = fn(_ enum(::option_party::main::3 enum(0 n72))) + ::std::io::println = fn(ref(n73 n75) fn(tup(8 fn(n74 tup(105 tup(115 tup(95 tup(110 tup(111 tup(110 tup(101 tup(58 n74)))))))))) _)) + ::option_party::print_bool = fn(ref(n75 n77) fn(n76 _)) + ::std::option::Option::None = enum(::option_party::main::5 enum(1 n76)) + ::option_party::print_bool = fn(ref(n77 n79) fn(n78 _)) + ::std::option::Option::Some = fn(_ enum(::option_party::main::7 enum(1 n78))) + ::std::io::println = fn(ref(n79 n81) fn(tup(12 fn(n80 tup(105 tup(115 tup(95 tup(115 tup(111 tup(109 tup(101 tup(95 tup(97 tup(110 tup(100 tup(58 n80)))))))))))))) _)) + ::option_party::print_bool = fn(ref(n81 n83) fn(n82 _)) + ::std::option::Option::None = enum(::option_party::main::10 enum(0 n82)) + ::option_party::print_bool = fn(ref(n83 n85) fn(n84 _)) + ::std::option::Option::Some = fn(0 enum(::option_party::main::15 enum(0 n84))) + ::option_party::print_bool = fn(ref(n85 n87) fn(n86 _)) + ::std::option::Option::Some = fn(1 enum(::option_party::main::20 enum(0 n86))) + ::std::io::println = fn(ref(n87 n89) fn(tup(11 fn(n88 tup(105 tup(115 tup(95 tup(110 tup(111 tup(110 tup(101 tup(95 tup(111 tup(114 tup(58 n88))))))))))))) _)) + ::option_party::print_bool = fn(ref(n89 n92) fn(n91 _)) + ::option_party::is_none_or = fn(ref(::std::option::Option::None _) fn(fn(@lt$(0 n90) n90) n91)) + ::option_party::print_bool = fn(ref(n92 n96) fn(n95 _)) + ::std::option::Option::Some = fn(0 n93) + ::option_party::is_none_or = fn(ref(n93 _) fn(fn(@lt$(0 n94) n94) n95)) + ::option_party::print_bool = fn(ref(n96 n100) fn(n99 _)) + ::std::option::Option::Some = fn(1 n97) + ::option_party::is_none_or = fn(ref(n97 _) fn(fn(@lt$(0 n98) n98) n99)) + ::std::io::println = fn(ref(n100 n102) fn(tup(7 fn(n101 tup(117 tup(110 tup(119 tup(114 tup(97 tup(112 tup(58 n101))))))))) _)) + ::option_party::print_u32 = fn(ref(n102 n105) fn(n104 _)) + ::std::option::Option::Some = fn(42 n103) + ::std::option::Option::unwrap = fn(ref(n103 _) n104) + ::option_party::print_u32 = fn(ref(n105 n107) fn(n106 _)) + ::std::option::Option::unwrap = fn(ref(::std::option::Option::None _) n106) + ::std::io::println = fn(ref(n107 _) fn(tup(27 fn(n108 tup(105 tup(111 tup(32 tup(119 tup(105 tup(108 tup(108 tup(32 tup(110 tup(101 tup(118 tup(101 tup(114 tup(32 tup(119 tup(111 tup(114 tup(107 tup(32 tup(97 tup(103 tup(97 tup(105 tup(110 tup(32 tup(58 tup(40 n108))))))))))))))))))))))))))))) _)) } +::option_party::main::1 { enum(_ 1) } + +::option_party::main::3 { enum(_ 1) } + +::option_party::main::5 { enum(_ 0) } + +::option_party::main::7 { enum(_ 0) } + +::option_party::main::10 { enum(@lt$(0 ?(0 1 n0)) n0) } + +::option_party::main::15 { enum(@lt$(0 ?(0 1 n0)) n0) } + +::option_party::main::20 { enum(@lt$(0 ?(0 1 n0)) n0) } + ::option_party::print_option_u32 { fn(n0 fn(enum(::option_party::print_option_u32::1 enum(::option_party::print_option_u32::2 n3)) n5)) ::std::io::println = fn(n0 fn(n4 n5)) @@ -145,6 +155,12 @@ ::std::option::Option::map = fn(ref(n1 _) fn(fn(n2 n3) n4)) } +::option_party::is_none_or { fn(ref(enum(::option_party::is_none_or::1 enum(::option_party::is_none_or::2 x(n0 n1))) _) fn(n0 n1)) } + +::option_party::is_none_or::1 { enum(n0 x(fn(n0 n1) n1)) } + +::option_party::is_none_or::2 { x(_ 1) } + ::std::io::println { fn(ref(n0 n3) fn(n1 _)) ::std::io::print = fn(ref(n0 n2) fn(n1 _)) @@ -156,7 +172,7 @@ ::std::io::print::1 = x(n0 x(n1 x(n2 n3))) } -::std::io::print::1 { x(n0 x(n1 x(dup64(?(::std::io::print::3 ::std::io::print::2 x(n0 x(n1 x(n3 n2)))) n3) n2))) } +::std::io::print::1 { x(n0 x(n1 x(dup90(?(::std::io::print::3 ::std::io::print::2 x(n0 x(n1 x(n3 n2)))) n3) n2))) } ::std::io::print::2 { x(n1 x(n3 x(@sub(1 n4) tup(n0 n5)))) @@ -181,14 +197,14 @@ ::std::option::Option::map::2 { x(_ ::std::option::Option::None) } -::std::option::Option::as_ref { fn(ref(enum(::std::option::Option::as_ref::1 enum(::std::option::Option::as_ref::2 x(n2 n3))) n2) n3) } +::std::option::Option::as_ref { fn(ref(enum(::std::option::Option::as_ref::1 enum(::std::option::Option::as_ref::2 x(n2 n3))) n3) n2) } ::std::option::Option::as_ref::1 { - enum(n0 x(enum(enum(n1 n2) enum(_ n2)) n3)) + enum(n0 x(n3 enum(enum(n1 n2) enum(_ n2)))) ::std::option::Option::Some = fn(ref(n0 n1) n3) } -::std::option::Option::as_ref::2 { x(enum(_ enum(n0 n0)) ::std::option::Option::None) } +::std::option::Option::as_ref::2 { x(::std::option::Option::None enum(_ enum(n0 n0))) } ::std::option::Option::flatten { fn(ref(enum(::std::option::Option::flatten::2 enum(::std::option::Option::None n0)) _) n0) } @@ -217,47 +233,23 @@ ::std::option::Option::unwrap_or::2 { x(n0 n0) } -::std::option::Option::is_some { fn(ref(enum(::std::option::Option::is_some::1 enum(::std::option::Option::is_some::2 x(n2 n3))) n2) n3) } - -::std::option::Option::is_some::1 { enum(n0 x(enum(enum(n0 n1) enum(_ n1)) 1)) } - -::std::option::Option::is_some::2 { x(enum(_ enum(n0 n0)) 0) } - -::std::option::Option::is_none { fn(ref(enum(::std::option::Option::is_none::1 enum(::std::option::Option::is_none::2 x(n2 n3))) n2) n3) } - -::std::option::Option::is_none::1 { enum(n0 x(enum(enum(n0 n1) enum(_ n1)) 0)) } - -::std::option::Option::is_none::2 { x(enum(_ enum(n0 n0)) 1) } - -::std::option::Option::is_some_and { fn(ref(enum(::std::option::Option::is_some_and::1 enum(::std::option::Option::is_some_and::2 x(n0 n1))) _) fn(n0 n1)) } - -::std::option::Option::is_some_and::1 { enum(n0 x(fn(n0 n1) n1)) } - -::std::option::Option::is_some_and::2 { x(_ 0) } - -::std::option::Option::is_none_or { fn(ref(enum(::std::option::Option::is_none_or::1 enum(::std::option::Option::is_none_or::2 x(n0 n1))) _) fn(n0 n1)) } - -::std::option::Option::is_none_or::1 { enum(n0 x(fn(n0 n1) n1)) } - -::std::option::Option::is_none_or::2 { x(_ 1) } - ::std::option::Option::unwrap { fn(ref(enum(::std::option::Option::unwrap::1 enum(_ n0)) _) n0) } ::std::option::Option::unwrap::1 { enum(n0 n0) } ::std::str::concat { fn(tup(@add(n0 n1) fn(n3 n4)) fn(tup(n0 fn(n2 n3)) tup(n1 fn(n2 n4)))) } -::std::u32::to_string { fn(dup198(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } +::std::u32::to_string { fn(dup194(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } ::std::u32::to_string::1 { x(n1 n2) ::std::u32::to_string::2 = x(n1 x(tup(0 fn(n0 n0)) n2)) } -::std::u32::to_string::2 { x(dup198(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } +::std::u32::to_string::2 { x(dup194(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } ::std::u32::to_string::3 { - x(dup198(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) + x(dup194(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) 48 = @add(n1 n2) ::std::u32::to_string::2 = x(n5 x(tup(n0 fn(n3 tup(n2 n4))) n6)) } diff --git a/tests/snaps/vine/option_party/stats.txt b/tests/snaps/vine/option_party/stats.txt index a866aaa5..1e498821 100644 --- a/tests/snaps/vine/option_party/stats.txt +++ b/tests/snaps/vine/option_party/stats.txt @@ -1,15 +1,15 @@ Interactions - Total 9_737 - Annihilate 5_254 + Total 9_682 + Annihilate 5_230 Commute 3 - Copy 550 - Erase 1_164 - Expand 1_545 + Copy 538 + Erase 1_153 + Expand 1_535 Call 795 - Branch 426 + Branch 428 Memory - Heap 6_768 B - Allocated 197_152 B - Freed 197_152 B + Heap 6_624 B + Allocated 196_224 B + Freed 196_224 B diff --git a/tests/snaps/vine/pretty_div/compiled.iv b/tests/snaps/vine/pretty_div/compiled.iv index 8d43d030..1420629f 100644 --- a/tests/snaps/vine/pretty_div/compiled.iv +++ b/tests/snaps/vine/pretty_div/compiled.iv @@ -61,17 +61,17 @@ ::std::str::concat { fn(tup(@add(n0 n1) fn(n3 n4)) fn(tup(n0 fn(n2 n3)) tup(n1 fn(n2 n4)))) } -::std::u32::to_string { fn(dup153(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } +::std::u32::to_string { fn(dup123(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } ::std::u32::to_string::1 { x(n1 n2) ::std::u32::to_string::2 = x(n1 x(tup(0 fn(n0 n0)) n2)) } -::std::u32::to_string::2 { x(dup153(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } +::std::u32::to_string::2 { x(dup123(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } ::std::u32::to_string::3 { - x(dup153(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) + x(dup123(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) 48 = @add(n1 n2) ::std::u32::to_string::2 = x(n5 x(tup(n0 fn(n3 tup(n2 n4))) n6)) } diff --git a/tests/snaps/vine/so_random/compiled.iv b/tests/snaps/vine/so_random/compiled.iv index 40ae5701..cd567219 100644 --- a/tests/snaps/vine/so_random/compiled.iv +++ b/tests/snaps/vine/so_random/compiled.iv @@ -40,7 +40,7 @@ ::std::io::print_char { fn(ref(@io_print_char(char io) io) fn(char _)) } ::std::rng::new { - fn(n1 fn(@u32_or(n0 dup122(n5 dup122(n6 n7))) tup(n4 n7))) + fn(n1 fn(@u32_or(n0 dup92(n5 dup92(n6 n7))) tup(n4 n7))) ::std::u64::from_u32 = fn(1 n0) ::std::u64::add = fn(n1 fn(n5 n2)) ::std::u64::mul = fn(n2 fn(::std::rng::multiplier n3)) @@ -55,23 +55,23 @@ ::std::rng::multiplier { tup(1284865837 1481765933) } ::std::rng::gen_u32 { - fn(ref(tup(dup127(tup(@u32_shr(27 n3) dup130(@u32_shr(13 @u32_xor(n2 @u32_xor(n3 n4))) dup130(@u32_shl(5 n2) @u32_shr(27 n5)))) n7) dup128(n8 n9)) tup(n1 n9)) n6) + fn(ref(tup(dup97(tup(@u32_shr(27 n3) dup100(@u32_shr(13 @u32_xor(n2 @u32_xor(n3 n4))) dup100(@u32_shl(5 n2) @u32_shr(27 n5)))) n7) dup98(n8 n9)) tup(n1 n9)) n6) ::std::u64::mul = fn(n7 fn(::std::rng::multiplier n0)) ::std::u64::add = fn(n0 fn(n8 n1)) ::std::u32::rotate_right = fn(n4 fn(n5 n6)) } -::std::u32::to_string { fn(dup148(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } +::std::u32::to_string { fn(dup118(?(::std::u32::to_string::5 ::std::u32::to_string::1 x(n1 n0)) n1) n0) } ::std::u32::to_string::1 { x(n1 n2) ::std::u32::to_string::2 = x(n1 x(tup(0 fn(n0 n0)) n2)) } -::std::u32::to_string::2 { x(dup148(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } +::std::u32::to_string::2 { x(dup118(?(::std::u32::to_string::4 ::std::u32::to_string::3 x(n2 n0)) n2) n0) } ::std::u32::to_string::3 { - x(dup148(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) + x(dup118(@rem(10 n1) @div(10 n5)) x(tup(@add(1 n0) fn(n3 n4)) n6)) 48 = @add(n1 n2) ::std::u32::to_string::2 = x(n5 x(tup(n0 fn(n3 tup(n2 n4))) n6)) } diff --git a/tests/tests.rs b/tests/tests.rs index cb553858..5618770d 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -38,6 +38,7 @@ fn tests(t: &mut DynTester) { test_vi(t, "tests/programs/basic_diverge.vi", b"", ".txt"); test_vi(t, "tests/programs/inverse.vi", b"", ".txt"); + test_vi(t, "tests/programs/logic.vi", b"", ".txt"); test_vi(t, "tests/programs/loop_vi_loop.vi", b"", ".txt"); test_vi(t, "tests/programs/maybe_set.vi", b"", ".txt"); test_vi(t, "tests/programs/move_it_move_it.vi", b"", ".txt"); @@ -48,6 +49,7 @@ fn tests(t: &mut DynTester) { t.group("fail", |t| { test_vi_fail(t, "tests/programs/fail/hallo_world.vi"); test_vi_fail(t, "tests/programs/fail/informal.vi"); + test_vi_fail(t, "tests/programs/fail/is_not.vi"); test_vi_fail(t, "tests/programs/fail/missing_no.vi"); }); }); diff --git a/vine/examples/fib_repl.vi b/vine/examples/fib_repl.vi index 2351c8d3..8ee9f0a1 100644 --- a/vine/examples/fib_repl.vi +++ b/vine/examples/fib_repl.vi @@ -2,7 +2,7 @@ use std::{io::{prompt, println}, u32, option::Option::{Some, None}}; fn main(io) { - while let Some(line) = io.prompt("> ") { + while io.prompt("> ") is Some(line) { let num = u32::parse(line); io.println(match num { Some(num) => u32::to_string(fib(num)), diff --git a/vine/src/ast.rs b/vine/src/ast.rs index ca96295a..5637c173 100644 --- a/vine/src/ast.rs +++ b/vine/src/ast.rs @@ -146,8 +146,6 @@ pub enum ExprKind { If(B, Block, B), #[class(value)] While(B, Block), - #[class(value, sugar)] - WhileLet(B, B, Block), #[class(value)] Loop(Block), #[class(value)] @@ -177,10 +175,14 @@ pub enum ExprKind { #[class(value)] Call(B, Vec), #[class(value)] - UnaryOp(UnaryOp, B), + Neg(B), #[class(value)] BinaryOp(BinaryOp, B, B), - #[class(value)] + #[class(value, cond)] + Not(B), + #[class(value, cond)] + Is(B, B), + #[class(value, cond)] LogicalOp(LogicalOp, B, B), #[class(value)] ComparisonOp(B, Vec<(ComparisonOp, Expr)>), @@ -237,12 +239,6 @@ pub enum PatKind { Error(ErrorGuaranteed), } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum UnaryOp { - Neg, - Not, -} - #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum BinaryOp { Range, diff --git a/vine/src/compile/build_stages.rs b/vine/src/compile/build_stages.rs index 35518ac5..ba7cca8d 100644 --- a/vine/src/compile/build_stages.rs +++ b/vine/src/compile/build_stages.rs @@ -65,13 +65,9 @@ impl Compiler<'_> { let f = self.lower_expr_value(f); self.apply_combs("fn", f, args, Self::lower_expr_value) } - ExprKind::UnaryOp(op, rhs) => { - let (f, lhs) = match op { - UnaryOp::Neg => (ExtFnKind::sub, Port::U32(0)), - UnaryOp::Not => (ExtFnKind::u32_xor, Port::U32(u32::MAX)), - }; + ExprKind::Neg(rhs) => { let rhs = self.lower_expr_value(rhs); - self.ext_fn(f.into(), lhs, rhs) + self.ext_fn(ExtFnKind::sub.into(), Port::U32(0), rhs) } ExprKind::BinaryOp(op, lhs, rhs) => { let lhs = self.lower_expr_value(lhs); @@ -139,7 +135,17 @@ impl Compiler<'_> { ExprKind::Return(r) => self.lower_return(r), ExprKind::Break => self.lower_break(), - ExprKind::Match(value, arms) => self.lower_match(value, arms), + ExprKind::Match(value, arms) => { + let result = self.new_local(); + self.new_fork(|self_| { + self_.lower_match(value, arms.iter().map(|(p, a)| (p, a)), |self_, expr| { + let r = self_.lower_expr_value(expr); + self_.set_local_to(result, r); + true + }); + }); + self.move_local(result) + } ExprKind::CopyLocal(l) => self.get_local(*l), ExprKind::MoveLocal(l) => self.move_local(*l), @@ -151,8 +157,23 @@ impl Compiler<'_> { a } + ExprKind![cond] => { + let result = self.new_local(); + self.lower_cond( + expr, + &|self_| { + self_.set_local_to(result, Port::U32(1)); + true + }, + &|self_| { + self_.set_local_to(result, Port::U32(0)); + true + }, + ); + self.move_local(result) + } + ExprKind::For(..) => todo!(), - ExprKind::LogicalOp(..) => todo!(), } } diff --git a/vine/src/compile/build_stages/control_flow.rs b/vine/src/compile/build_stages/control_flow.rs index abe651f0..9c98c40c 100644 --- a/vine/src/compile/build_stages/control_flow.rs +++ b/vine/src/compile/build_stages/control_flow.rs @@ -33,30 +33,20 @@ impl Compiler<'_> { pub(super) fn lower_if(&mut self, cond: &Expr, then: &Block, els: &Expr) -> Port { let val = self.new_local(); - let cond = self.lower_expr_value(cond); - self.new_fork(|self_| { - let i = self_.new_interface(); - let then = self_.new_stage(i, |self_, _| { - let then = self_.lower_block(then); - self_.set_local_to(val, then); - true - }); - - let els = self_.new_stage(i, |self_, _| { - let els = self_.lower_expr_value(els); - self_.set_local_to(val, els); - true - }); - - let r = self_.net.new_wire(); - self_.cur.agents.push(Agent::Branch( + self_.lower_cond( cond, - self_.stage_port(els), - self_.stage_port(then), - r.0, - )); - self_.cur.steps.push_back(Step::Call(i, r.1)); + &|self_| { + let then = self_.lower_block(then); + self_.set_local_to(val, then); + true + }, + &|self_| { + let els = self_.lower_expr_value(els); + self_.set_local_to(val, els); + true + }, + ); }); self.get_local(val) @@ -85,29 +75,17 @@ impl Compiler<'_> { let i = self_.new_interface(); let start = self_.new_stage(i, move |self_, start| { - let cond = self_.lower_expr_value(cond); - - self_.new_fork(|self_| { - let j = self_.new_interface(); - let body = self_.new_stage(j, |self_, _| { + self_.lower_cond( + cond, + &|self_| { self_.lower_block_erase(body); self_.goto(start); false - }); - - let end = self_.new_stage(j, |_, _| true); - - let r = self_.net.new_wire(); - self_.cur.agents.push(Agent::Branch( - cond, - self_.stage_port(end), - self_.stage_port(body), - r.0, - )); - self_.cur.steps.push_back(Step::Call(j, r.1)); - }); + }, + &|_| true, + ); - true + false }); self_.break_target = old_break; @@ -122,4 +100,60 @@ impl Compiler<'_> { self.diverge(self.break_target.unwrap()); Port::Erase } + + pub(super) fn lower_cond( + &mut self, + expr: &Expr, + yay: &dyn Fn(&mut Self) -> bool, + nay: &dyn Fn(&mut Self) -> bool, + ) { + match &expr.kind { + ExprKind![!cond] => { + let bool = self.lower_expr_value(expr); + let i = self.new_interface(); + let yay = self.new_stage(i, |self_, _| yay(self_)); + let nay = self.new_stage(i, |self_, _| nay(self_)); + let r = self.net.new_wire(); + self.cur.agents.push(Agent::Branch(bool, self.stage_port(nay), self.stage_port(yay), r.0)); + self.cur.steps.push_back(Step::Call(i, r.1)); + } + ExprKind::Is(expr, pat) => { + self.lower_match( + expr, + [(&**pat, yay), (&Pat { span: Span::NONE, kind: PatKind::Hole }, nay)], + |self_, f| f(self_), + ); + } + ExprKind::Not(cond) => { + self.lower_cond(cond, nay, yay); + } + ExprKind::LogicalOp(LogicalOp::LogicalAnd, a, b) => { + let nay = self.share_dyn_stage(nay); + self.lower_cond( + a, + &|self_| { + self_.lower_cond(b, yay, &nay); + false + }, + &nay, + ); + } + ExprKind::LogicalOp(LogicalOp::LogicalOr, a, b) => { + let yay = self.share_dyn_stage(yay); + self.lower_cond(a, &yay, &|self_| { + self_.lower_cond(b, &yay, nay); + false + }); + } + } + } + + fn share_dyn_stage(&mut self, nay: &dyn Fn(&mut Self) -> bool) -> impl Fn(&mut Self) -> bool { + let i = self.new_interface(); + let stage = self.new_stage(i, |self_, _| nay(self_)); + move |self_| { + self_.goto(stage); + false + } + } } diff --git a/vine/src/compile/build_stages/pattern_matching.rs b/vine/src/compile/build_stages/pattern_matching.rs index 39a1761f..960ce18e 100644 --- a/vine/src/compile/build_stages/pattern_matching.rs +++ b/vine/src/compile/build_stages/pattern_matching.rs @@ -1,58 +1,56 @@ use std::{collections::HashMap, ops::Range}; use crate::{ - compile::{Local, Port, StageId}, + compile::{Local, StageId}, resolve::NodeId, }; use super::{Compiler, Expr, Node, Pat, PatKind, Step}; impl Compiler<'_> { - pub(super) fn lower_match(&mut self, value: &Expr, arms: &[(Pat, Expr)]) -> Port { + pub(super) fn lower_match<'p, A>( + &mut self, + value: &Expr, + arms: impl IntoIterator + Clone, + mut f: impl FnMut(&mut Self, A) -> bool, + ) { let value = self.lower_expr_value(value); let initial = self.new_match_var(false); self.set_local_to(initial.local, value); - let mut arm_counts = vec![0; arms.len()]; let rows = arms - .iter() + .clone() + .into_iter() .enumerate() .map(|(i, arm)| Row { - cells: vec![Cell { var: initial, pattern: &arm.0 }], + cells: vec![Cell { var: initial, pattern: arm.0 }], body: Body { aliases: vec![], arm: i }, }) - .collect(); + .collect::>(); + let mut arm_counts = vec![0; rows.len()]; let tree = self.build_decision_tree(rows, &mut arm_counts); - let result = self.new_local(); - - self.new_fork(|self_| { - let arms = arms - .iter() - .zip(arm_counts) - .map(|((_, body), count)| { - if count <= 1 { - Arm::Unique(body) - } else { - let i = self_.new_interface(); - Arm::Shared(self_.new_stage(i, |self_, _| { - let r = self_.lower_expr_value(body); - self_.set_local_to(result, r); - true - })) - } - }) - .collect::>(); - - self_.lower_decision_tree(&arms, result, tree); - }); - - let r = self.net.new_wire(); - self.cur.steps.push_back(Step::Move(result, r.0)); + let mut arms = arms + .into_iter() + .zip(arm_counts) + .map(|((_, a), count)| { + if count <= 1 { + Arm::Unique(Some(a)) + } else { + let i = self.new_interface(); + Arm::Shared(self.new_stage(i, |self_, _| f(self_, a))) + } + }) + .collect::>(); - r.1 + self.lower_decision_tree(&mut arms, tree, &mut f); } - fn lower_decision_tree(&mut self, arms: &[Arm], result: Local, tree: DecisionTree) -> bool { + fn lower_decision_tree( + &mut self, + arms: &mut [Arm], + tree: DecisionTree, + f: &mut impl FnMut(&mut Self, A) -> bool, + ) -> bool { match tree { DecisionTree::Leaf(body) => { for (a, b) in body.aliases { @@ -64,16 +62,12 @@ impl Compiler<'_> { self.set_local_to(b.local, y); } } - match arms[body.arm] { + match &mut arms[body.arm] { Arm::Shared(stage) => { - self.goto(stage); + self.goto(*stage); false } - Arm::Unique(expr) => { - let r = self.lower_expr_value(expr); - self.set_local_to(result, r); - true - } + Arm::Unique(a) => f(self, a.take().unwrap()), } } DecisionTree::Missing => false, @@ -84,7 +78,7 @@ impl Compiler<'_> { let a = self.tuple(t, Self::fin_move_local); self.set_local_to(v.local, a); } - self.lower_decision_tree(arms, result, *next) + self.lower_decision_tree(arms, *next, f) } DecisionTree::Deref(r, v, next) => { let v0 = self.net.new_wire(); @@ -99,7 +93,7 @@ impl Compiler<'_> { } else { self.cur.fin.push(Step::Move(v.local, v2.1)); } - self.lower_decision_tree(arms, result, *next) + self.lower_decision_tree(arms, *next, f) } DecisionTree::Switch(var, adt, cases, fallback) => { let adt = self.nodes[adt].adt.as_ref().unwrap(); @@ -110,7 +104,7 @@ impl Compiler<'_> { if fallback.is_some() && cases.iter().filter(|x| x.body.is_none()).count() > 1 { fallback.take().map(|tree| { let i = self.new_interface(); - self.new_stage(i, |self_, _| self_.lower_decision_tree(arms, result, *tree)) + self.new_stage(i, |self_, _| self_.lower_decision_tree(arms, *tree, f)) }) } else { None @@ -127,7 +121,7 @@ impl Compiler<'_> { let should_fallback = case.body.is_none(); let mut end = false; if let Some(tree) = case.body { - end = self_.lower_decision_tree(arms, result, tree); + end = self_.lower_decision_tree(arms, tree, f); } if var.is_place || should_fallback && fallback_needs_var { let r = self_.make_enum(adt, v, case.vars.clone(), Self::fin_move_local); @@ -138,7 +132,7 @@ impl Compiler<'_> { if let Some(stage) = fallback_stage { self_.goto(stage); } else if let Some(tree) = fallback.take() { - end = self_.lower_decision_tree(arms, result, *tree); + end = self_.lower_decision_tree(arms, *tree, f); } } end @@ -159,9 +153,9 @@ impl Compiler<'_> { } #[derive(Debug)] -enum Arm<'t> { +enum Arm { Shared(StageId), - Unique(&'t Expr), + Unique(Option), } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/vine/src/desugar.rs b/vine/src/desugar.rs index 259d9c6a..699864db 100644 --- a/vine/src/desugar.rs +++ b/vine/src/desugar.rs @@ -1,7 +1,7 @@ use std::mem::take; use crate::{ - ast::{Block, Expr, ExprKind, Pat, PatKind, Span, Stmt, StmtKind}, + ast::{Expr, ExprKind}, resolve::Node, visit::VisitMut, }; @@ -34,33 +34,6 @@ impl VisitMut<'_> for Desugar { ), })) } - ExprKind::WhileLet(pat, value, body) => { - let pat = take(&mut **pat); - let value = take(&mut **value); - let body = take(body); - expr.kind = ExprKind::Loop(Block { - span: expr.span, - stmts: vec![Stmt { - span: expr.span, - kind: StmtKind::Expr( - Expr { - span: expr.span, - kind: ExprKind::Match( - Box::new(value), - vec![ - (pat, Expr { span: body.span, kind: ExprKind::Block(body) }), - ( - Pat { span: Span::NONE, kind: PatKind::Hole }, - Expr { span: Span::NONE, kind: ExprKind::Break }, - ), - ], - ), - }, - true, - ), - }], - }); - } ExprKind![!sugar] => {} } self._visit_expr(expr) diff --git a/vine/src/lexer.rs b/vine/src/lexer.rs index bb2e9f94..da19b167 100644 --- a/vine/src/lexer.rs +++ b/vine/src/lexer.rs @@ -118,6 +118,8 @@ pub enum Token { Defer, #[token("in")] In, + #[token("is")] + Is, #[token("return")] Return, #[token("yield")] diff --git a/vine/src/parser.rs b/vine/src/parser.rs index ce1f9998..383359a6 100644 --- a/vine/src/parser.rs +++ b/vine/src/parser.rs @@ -9,8 +9,8 @@ use vine_util::{ use crate::{ ast::{ BinaryOp, Block, ComparisonOp, ConstItem, Enum, Expr, ExprKind, FnItem, Ident, InlineIvy, Item, - ItemKind, LetStmt, ModItem, ModKind, Pat, PatKind, Path, PatternItem, Span, Stmt, StmtKind, - Struct, UnaryOp, UseTree, + ItemKind, LetStmt, LogicalOp, ModItem, ModKind, Pat, PatKind, Path, PatternItem, Span, Stmt, + StmtKind, Struct, UseTree, }, diag::Diag, lexer::Token, @@ -271,10 +271,10 @@ impl<'ctx, 'src> VineParser<'ctx, 'src> { return Ok(ExprKind::Inverse(Box::new(self.parse_expr_bp(BP::Prefix)?))); } if self.eat(Token::Minus)? { - return Ok(ExprKind::UnaryOp(UnaryOp::Neg, Box::new(self.parse_expr_bp(BP::Prefix)?))); + return Ok(ExprKind::Neg(Box::new(self.parse_expr_bp(BP::Prefix)?))); } if self.eat(Token::Bang)? { - return Ok(ExprKind::UnaryOp(UnaryOp::Not, Box::new(self.parse_expr_bp(BP::Prefix)?))); + return Ok(ExprKind::Not(Box::new(self.parse_expr_bp(BP::Prefix)?))); } if self.check(Token::Num) { return self.parse_num(); @@ -324,17 +324,9 @@ impl<'ctx, 'src> VineParser<'ctx, 'src> { return Ok(ExprKind::If(Box::new(cond), then, Box::new(else_))); } if self.eat(Token::While)? { - if self.eat(Token::Let)? { - let pat = self.parse_pat()?; - self.expect(Token::Eq)?; - let value = self.parse_expr()?; - let body = self.parse_block()?; - return Ok(ExprKind::WhileLet(Box::new(pat), Box::new(value), body)); - } else { - let cond = self.parse_expr()?; - let body = self.parse_block()?; - return Ok(ExprKind::While(Box::new(cond), body)); - } + let cond = self.parse_expr()?; + let body = self.parse_block()?; + return Ok(ExprKind::While(Box::new(cond), body)); } if self.eat(Token::Loop)? { let body = self.parse_block()?; @@ -384,6 +376,21 @@ impl<'ctx, 'src> VineParser<'ctx, 'src> { } } + if bp.permits(BP::LogicalAnd) && self.eat(Token::AndAnd)? { + let rhs = self.parse_expr_bp(BP::LogicalAnd)?; + return Ok(Ok(ExprKind::LogicalOp(LogicalOp::LogicalAnd, Box::new(lhs), Box::new(rhs)))); + } + + if bp.permits(BP::LogicalOr) && self.eat(Token::OrOr)? { + let rhs = self.parse_expr_bp(BP::LogicalOr)?; + return Ok(Ok(ExprKind::LogicalOp(LogicalOp::LogicalOr, Box::new(lhs), Box::new(rhs)))); + } + + if bp.permits(BP::Is) && self.eat(Token::Is)? { + let rhs = self.parse_pat()?; + return Ok(Ok(ExprKind::Is(Box::new(lhs), Box::new(rhs)))); + } + if bp.permits(BP::Comparison) { let mut rhs = Vec::new(); 'main: loop { @@ -554,6 +561,7 @@ enum BP { Range, LogicalOr, LogicalAnd, + Is, Comparison, BitOr, BitXor, diff --git a/vine/src/resolve/resolve_exprs.rs b/vine/src/resolve/resolve_exprs.rs index 8d6a4595..22126f77 100644 --- a/vine/src/resolve/resolve_exprs.rs +++ b/vine/src/resolve/resolve_exprs.rs @@ -4,7 +4,7 @@ use std::{ }; use crate::{ - ast::{Expr, ExprKind, Ident, Pat, PatKind, Path}, + ast::{Expr, ExprKind, Ident, LogicalOp, Pat, PatKind, Path}, diag::Diag, visit::{VisitMut, Visitee}, }; @@ -128,23 +128,45 @@ impl VisitMut<'_> for ResolveVisitor<'_> { } fn visit_expr(&mut self, expr: &mut Expr) { - let result = match &mut expr.kind { - ExprKind::Path(path) => { - if let Some(ident) = path.as_ident() { - if let Some(bind) = self.scope.get(&ident).and_then(|x| x.last()) { - expr.kind = ExprKind::Local(bind.local); - return; + match &mut expr.kind { + ExprKind![cond] => { + self.enter_scope(); + self.visit_cond(expr); + self.exit_scope(); + } + ExprKind::If(cond, block, els) => { + self.enter_scope(); + self.visit_cond(cond); + self.visit_block(block); + self.exit_scope(); + self.visit_expr(els); + } + ExprKind::While(cond, block) => { + self.enter_scope(); + self.visit_cond(cond); + self.visit_block(block); + self.exit_scope(); + } + _ => { + let result = match &mut expr.kind { + ExprKind::Path(path) => { + if let Some(ident) = path.as_ident() { + if let Some(bind) = self.scope.get(&ident).and_then(|x| x.last()) { + expr.kind = ExprKind::Local(bind.local); + return; + } + } + self.visit_path(path) } + ExprKind::Field(_, p) => self.visit_path(p), + ExprKind::Method(_, p, _) => self.visit_path(p), + _ => Ok(()), + }; + self._visit_expr(expr); + if let Err(diag) = result { + expr.kind = ExprKind::Error(self.resolver.diags.add(diag)); } - self.visit_path(path) } - ExprKind::Field(_, p) => self.visit_path(p), - ExprKind::Method(_, p, _) => self.visit_path(p), - _ => Ok(()), - }; - self._visit_expr(expr); - if let Err(diag) = result { - expr.kind = ExprKind::Error(self.resolver.diags.add(diag)); } } } @@ -156,4 +178,31 @@ impl<'a> ResolveVisitor<'a> { debug_assert!(path.absolute && path.resolved.is_some()); Ok(()) } + + fn visit_cond(&mut self, cond: &mut Expr) { + match &mut cond.kind { + ExprKind![!cond] => self.visit_expr(cond), + ExprKind::Not(e) => { + self.enter_scope(); + self.visit_cond(e); + self.exit_scope(); + } + ExprKind::Is(e, p) => { + self.visit_expr(e); + self.visit_pat(p); + } + ExprKind::LogicalOp(LogicalOp::LogicalAnd, a, b) => { + self.visit_cond(a); + self.visit_cond(b); + } + ExprKind::LogicalOp(LogicalOp::LogicalOr, a, b) => { + self.enter_scope(); + self.visit_cond(a); + self.exit_scope(); + self.enter_scope(); + self.visit_cond(b); + self.exit_scope(); + } + } + } } diff --git a/vine/src/validate.rs b/vine/src/validate.rs index 074a8c31..f154b9cb 100644 --- a/vine/src/validate.rs +++ b/vine/src/validate.rs @@ -188,16 +188,12 @@ impl Validate { | ExprKind::Return(..) | ExprKind::List(..) | ExprKind::Call(..) - | ExprKind::UnaryOp(..) + | ExprKind::Neg(..) | ExprKind::BinaryOp(..) + | ExprKind::Not(..) | ExprKind::LogicalOp(..) | ExprKind::ComparisonOp(..) => self._visit_expr(expr), - ExprKind::WhileLet(p, v, b) => { - self.expect_pat(p, Form::Value, true); - self.expect_expr(v, Form::Value); - self.visit_block(b); - } ExprKind::Match(s, a) => { self.expect_expr(s, Form::Value); for (p, v) in a { @@ -205,6 +201,10 @@ impl Validate { self.expect_expr(v, Form::Value); } } + ExprKind::Is(e, p) => { + self.expect_expr(e, Form::Value); + self.expect_pat(p, Form::Value, true); + } ExprKind::Assign(s, v) => { self.expect_expr(s, Form::Space); self.expect_expr(v, Form::Value); diff --git a/vine/src/visit.rs b/vine/src/visit.rs index 8e468225..be70d0c2 100644 --- a/vine/src/visit.rs +++ b/vine/src/visit.rs @@ -54,7 +54,8 @@ pub trait VisitMut<'a> { | ExprKind::Deref(a) | ExprKind::Move(a) | ExprKind::Field(a, _) - | ExprKind::UnaryOp(_, a) + | ExprKind::Neg(a) + | ExprKind::Not(a) | ExprKind::Return(a) | ExprKind::Inverse(a) | ExprKind::Copy(a) @@ -87,11 +88,6 @@ pub trait VisitMut<'a> { self.visit_expr(a); self.visit_block(b); } - ExprKind::WhileLet(a, b, c) => { - self.visit_pat(a); - self.visit_expr(b); - self.visit_block(c); - } ExprKind::For(a, b, c) => { self.enter_scope(); self.visit_expr(b); @@ -124,6 +120,10 @@ pub trait VisitMut<'a> { self.visit_expr(t); } } + ExprKind::Is(e, p) => { + self.visit_expr(e); + self.visit_pat(p); + } } } diff --git a/vine/std/option.vi b/vine/std/option.vi index e728be9b..da7539b7 100644 --- a/vine/std/option.vi +++ b/vine/std/option.vi @@ -46,34 +46,6 @@ mod Option { } } - fn is_some(&self) { - match &self { - &Some(_) => true, - &None => false, - } - } - - fn is_none(&self) { - match &self { - &Some(_) => false, - &None => true, - } - } - - fn is_some_and(&move self, f) { - match self { - Some(val) => f(val), - None => false, - } - } - - fn is_none_or(&move self, f) { - match self { - Some(val) => f(val), - None => true, - } - } - fn unwrap(&move self) { match self { Some(val) => val } } diff --git a/vine/std/u32.vi b/vine/std/u32.vi index d07bb1ef..b54b6899 100644 --- a/vine/std/u32.vi +++ b/vine/std/u32.vi @@ -25,7 +25,7 @@ fn parse(str) { while len { let char; (char, chars) = chars; - if ('0' <= char <= '9') != 1 { + if !('0' <= char <= '9') { return None; } num *= 10;