diff --git a/.llvmenv b/.llvmenv index 95c4e8d271..4044f90867 100644 --- a/.llvmenv +++ b/.llvmenv @@ -1 +1 @@ -10.0.0 \ No newline at end of file +12.0.0 diff --git a/BUILDING_FROM_SOURCE.md b/BUILDING_FROM_SOURCE.md index d6640af464..d055e8612c 100644 --- a/BUILDING_FROM_SOURCE.md +++ b/BUILDING_FROM_SOURCE.md @@ -40,23 +40,41 @@ sudo apt-get install libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev ``` ### Zig -**version: 0.7.x** +**version: 0.8.0** -If you're on MacOS, you can install with `brew install zig` -If you're on Ubuntu and use Snap, you can install with `snap install zig --classic --beta` -For any other OS, checkout the [Zig installation page](https://github.com/ziglang/zig/wiki/Install-Zig-from-a-Package-Manager) +For any OS, you can use [`zigup`](https://github.com/marler8997/zigup) to manage zig installations. + +If you prefer a package manager, you can try the following: +- For MacOS, you can install with `brew install zig` +- For, Ubuntu, you can use Snap, you can install with `snap install zig --classic --beta` +- For other systems, checkout this [page](https://github.com/ziglang/zig/wiki/Install-Zig-from-a-Package-Manager) + +If you want to install it manually, you can also download Zig directly [here](https://ziglang.org/download/). Just make sure you download the right version, the bleeding edge master build is the first download link on this page. ### LLVM -**version: 10.0.x** +**version: 12.0.x** + +For macOS, you can install LLVM 12 using `brew install llvm@12` and then adding +`/usr/local/opt/llvm/bin` to your `PATH`. You can confirm this worked by +running `llc --version` - it should mention "LLVM version 12.0.0" at the top. For Ubuntu and Debian, you can use the `Automatic installation script` at [apt.llvm.org](https://apt.llvm.org): ``` sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ``` -For macOS, check the troubleshooting section below. +If you use this script, you'll need to add `clang` and `llvm-as` to your `PATH`. +By default, the script installs them as `llvm-as-12` and `clang-12`, +respectively. You can address this with symlinks like so: -There are also plenty of alternative options at http://releases.llvm.org/download.html +``` +sudo ln -s /usr/bin/clang-12 /usr/bin/clang +``` +``` +sudo ln -s /usr/bin/llvm-as-12 /usr/bin/llvm-as +```` + +There are also alternative installation options at http://releases.llvm.org/download.html ## Using Nix @@ -138,31 +156,15 @@ If you encounter `cannot find -lz` run `sudo apt install zlib1g-dev`. ### LLVM installation on macOS -By default homebrew will try to install llvm 11, which is currently -unsupported. You need to install an older version (10.0.0_3) by doing: - -``` -$ brew edit llvm - -# Replace the contents of the file with https://raw.githubusercontent.com/Homebrew/homebrew-core/6616d50fb0b24dbe30f5e975210bdad63257f517/Formula/llvm.rb - -# we expect llvm-as-10 to be present -$ ln -s /usr/local/opt/llvm/bin/{llvm-as,llvm-as-10} - -# "pinning" ensures that homebrew doesn't update it automatically -$ brew pin llvm -``` +If installing LLVM fails, it might help to run `sudo xcode-select -r` before installing again. It might also be useful to add these exports to your shell: ``` -export PATH="/usr/local/opt/llvm/bin:$PATH" export LDFLAGS="-L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib" export CPPFLAGS="-I/usr/local/opt/llvm/include" ``` -If installing LLVM still fails, it might help to run `sudo xcode-select -r` before installing again. - ### LLVM installation on Windows Installing LLVM's prebuilt binaries doesn't seem to be enough for the `llvm-sys` crate that Roc depends on, so I had to build LLVM from source diff --git a/Cargo.lock b/Cargo.lock index a4b14f1473..5a68dbd35f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,7 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 - [[package]] name = "ab_glyph" version = "0.2.11" @@ -20,9 +18,9 @@ checksum = "d9fe5e32de01730eb1f6b7f5b51c17e03e2325bf40a74f754f04f130043affff" [[package]] name = "addr2line" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03345e98af8f3d786b6d9f656ccfa6ac316d954e92bc4841f0bba20789d5fb5a" +checksum = "e7a2e47a1fbe209ee101dd6d61285226744c6c8d3c21c8dc878ba6cb9f467f3a" dependencies = [ "gimli", ] @@ -99,6 +97,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "approx" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "072df7202e63b127ab55acfe16ce97013d5b97bf160489336d3f1840fd78e99e" +dependencies = [ + "num-traits", +] + [[package]] name = "arena-pool" version = "0.1.0" @@ -155,16 +162,16 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4717cfcbfaa661a0fd48f8453951837ae7e8f81e481fbb136e3202d72805a744" +checksum = "b7815ea54e4d821e791162e078acbebfd6d8c8939cd559c9335dceb1c8ca7282" dependencies = [ "addr2line", "cc", "cfg-if 1.0.0", "libc", "miniz_oxide", - "object", + "object 0.25.2", "rustc-demangle", ] @@ -689,7 +696,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.4", + "crossbeam-utils 0.8.5", ] [[package]] @@ -710,8 +717,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" dependencies = [ "cfg-if 1.0.0", - "crossbeam-epoch 0.9.4", - "crossbeam-utils 0.8.4", + "crossbeam-epoch 0.9.5", + "crossbeam-utils 0.8.5", ] [[package]] @@ -731,12 +738,12 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52fb27eab85b17fbb9f6fd667089e07d6a2eb8743d02639ee7f6a7a7729c9c94" +checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.4", + "crossbeam-utils 0.8.5", "lazy_static", "memoffset 0.6.4", "scopeguard", @@ -766,11 +773,10 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278" +checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" dependencies = [ - "autocfg 1.0.1", "cfg-if 1.0.0", "lazy_static", ] @@ -1407,12 +1413,12 @@ dependencies = [ [[package]] name = "glyph_brush_layout" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10bc06d530bf20c1902f1b02799ab7372ff43f6119770c49b0bc3f21bd148820" +checksum = "15cf18cf985bd942f05e14552b63c9d08f7d0ed1ec79a977eb9747c9e065f497" dependencies = [ "ab_glyph", - "approx 0.4.0", + "approx 0.5.0", "xi-unicode", ] @@ -1482,9 +1488,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" dependencies = [ "unicode-segmentation", ] @@ -1612,13 +1618,13 @@ dependencies = [ name = "inkwell" version = "0.1.0" dependencies = [ - "inkwell 0.1.0 (git+https://github.com/rtfeldman/inkwell?tag=llvm12-0.release2)", + "inkwell 0.1.0 (git+https://github.com/rtfeldman/inkwell?tag=llvm12-0.release4)", ] [[package]] name = "inkwell" version = "0.1.0" -source = "git+https://github.com/rtfeldman/inkwell?tag=llvm12-0.release2#2f9bfb728cb5713b39fe527838969dcc8e184c4d" +source = "git+https://github.com/rtfeldman/inkwell?tag=llvm12-0.release4#8d7174fc8da4d2e6f2555f9ec2b3f7464ec5026b" dependencies = [ "either", "inkwell_internals", @@ -1632,7 +1638,7 @@ dependencies = [ [[package]] name = "inkwell_internals" version = "0.3.0" -source = "git+https://github.com/rtfeldman/inkwell?tag=llvm12-0.release2#2f9bfb728cb5713b39fe527838969dcc8e184c4d" +source = "git+https://github.com/rtfeldman/inkwell?tag=llvm12-0.release4#8d7174fc8da4d2e6f2555f9ec2b3f7464ec5026b" dependencies = [ "proc-macro2 1.0.27", "quote 1.0.9", @@ -1789,15 +1795,15 @@ checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "llvm-sys" -version = "100.2.1" +version = "120.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d9c00ce56221b2150e2d4d51887ff139fce5a0e50346c744861d1e66d2f7c4" +checksum = "7b883556196140c6b6e7a18b19236b9a699c8611aad2e48a0a6403cf1123945a" dependencies = [ "cc", "lazy_static", "libc", "regex", - "semver 0.9.0", + "semver", ] [[package]] @@ -2165,6 +2171,15 @@ dependencies = [ "indexmap", ] +[[package]] +name = "object" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8bc1d42047cf336f0f939c99e97183cf31551bf0f2865a2ec9c8d91fd4ffb5e" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.7.2" @@ -2191,12 +2206,11 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "ordered-float" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809348965973b261c3e504c8d0434e465274f78c880e10039914f2c5dcf49461" +checksum = "f100fcfb41e5385e0991f74981732049f9b896821542a219420491046baafdc2" dependencies = [ "num-traits", - "rand 0.8.3", ] [[package]] @@ -2850,7 +2864,7 @@ checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" dependencies = [ "crossbeam-channel 0.5.1", "crossbeam-deque 0.8.0", - "crossbeam-utils 0.8.4", + "crossbeam-utils 0.8.5", "lazy_static", "num_cpus", ] @@ -2902,12 +2916,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" -dependencies = [ - "byteorder", -] +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" @@ -3171,7 +3182,7 @@ dependencies = [ "libc", "libloading 0.6.7", "maplit", - "object", + "object 0.24.0", "pretty_assertions 0.5.1", "quickcheck 0.8.5", "quickcheck_macros 0.8.0", @@ -3457,7 +3468,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" dependencies = [ - "semver 0.11.0", + "semver", ] [[package]] @@ -3524,30 +3535,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser 0.7.0", -] - [[package]] name = "semver" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ - "semver-parser 0.10.2", + "semver-parser", ] -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "semver-parser" version = "0.10.2" diff --git a/Earthfile b/Earthfile index 2322243d0d..4799b6df1d 100644 --- a/Earthfile +++ b/Earthfile @@ -13,17 +13,18 @@ install-other-libs: install-zig-llvm-valgrind-clippy-rustfmt: FROM +install-other-libs # zig - RUN wget -c https://ziglang.org/download/0.7.1/zig-linux-x86_64-0.7.1.tar.xz --no-check-certificate - RUN tar -xf zig-linux-x86_64-0.7.1.tar.xz - RUN ln -s /earthbuild/zig-linux-x86_64-0.7.1/zig /usr/bin/zig + RUN wget -c https://ziglang.org/download/0.8.0/zig-linux-x86_64-0.8.0.tar.xz --no-check-certificate + RUN tar -xf zig-linux-x86_64-0.8.0.tar.xz + RUN ln -s /earthbuild/zig-linux-x86_64-0.8.0/zig /usr/bin/zig # llvm RUN apt -y install lsb-release software-properties-common gnupg RUN wget https://apt.llvm.org/llvm.sh RUN chmod +x llvm.sh - RUN ./llvm.sh 10 - RUN ln -s /usr/bin/clang-10 /usr/bin/clang + RUN ./llvm.sh 12 + RUN ln -s /usr/bin/clang-12 /usr/bin/clang + RUN ln -s /usr/bin/llvm-as-12 /usr/bin/llvm-as # use lld as linker - RUN ln -s /usr/bin/lld-10 /usr/bin/ld.lld + RUN ln -s /usr/bin/lld-12 /usr/bin/ld.lld ENV RUSTFLAGS="-C link-arg=-fuse-ld=lld -C target-cpu=native" # valgrind RUN apt -y install autotools-dev cmake automake libc6-dbg diff --git a/cli/tests/fixtures/multi-dep-str/platform/host.zig b/cli/tests/fixtures/multi-dep-str/platform/host.zig index 2d335ec0f7..e60688a037 100644 --- a/cli/tests/fixtures/multi-dep-str/platform/host.zig +++ b/cli/tests/fixtures/multi-dep-str/platform/host.zig @@ -59,7 +59,7 @@ pub export fn main() i32 { roc__mainForHost_1_exposed(&callresult); // stdout the result - stdout.print("{}\n", .{callresult.content.asSlice()}) catch unreachable; + stdout.print("{s}\n", .{callresult.content.asSlice()}) catch unreachable; callresult.content.deinit(); diff --git a/cli/tests/fixtures/multi-dep-thunk/platform/host.zig b/cli/tests/fixtures/multi-dep-thunk/platform/host.zig index 2d335ec0f7..e60688a037 100644 --- a/cli/tests/fixtures/multi-dep-thunk/platform/host.zig +++ b/cli/tests/fixtures/multi-dep-thunk/platform/host.zig @@ -59,7 +59,7 @@ pub export fn main() i32 { roc__mainForHost_1_exposed(&callresult); // stdout the result - stdout.print("{}\n", .{callresult.content.asSlice()}) catch unreachable; + stdout.print("{s}\n", .{callresult.content.asSlice()}) catch unreachable; callresult.content.deinit(); diff --git a/compiler/build/src/program.rs b/compiler/build/src/program.rs index 28be0802f5..1dc5156184 100644 --- a/compiler/build/src/program.rs +++ b/compiler/build/src/program.rs @@ -204,7 +204,7 @@ pub fn gen_from_mono_module( } // assemble the .ll into a .bc - let _ = Command::new("llvm-as-10") + let _ = Command::new("llvm-as") .env_clear() .args(&[ app_ll_dbg_file.to_str().unwrap(), @@ -216,7 +216,7 @@ pub fn gen_from_mono_module( // write the .o file. Note that this builds the .o for the local machine, // and ignores the `target_machine` entirely. - let _ = Command::new("llc-10") + let _ = Command::new("llc-12") .env_clear() .args(&[ "-filetype=obj", diff --git a/compiler/builtins/bitcode/build.zig b/compiler/builtins/bitcode/build.zig index 9d3b0456a7..e9835e0db5 100644 --- a/compiler/builtins/bitcode/build.zig +++ b/compiler/builtins/bitcode/build.zig @@ -1,16 +1,15 @@ -const builtin = @import("builtin"); const std = @import("std"); const mem = std.mem; const Builder = std.build.Builder; pub fn build(b: *Builder) void { - // b.setPreferredReleaseMode(builtin.Mode.Debug); - b.setPreferredReleaseMode(builtin.Mode.ReleaseFast); + // b.setPreferredReleaseMode(builtin.Mode.Debug + b.setPreferredReleaseMode(.ReleaseFast); const mode = b.standardReleaseOptions(); // Options const fallback_main_path = "./src/main.zig"; - const main_path_desc = b.fmt("Override path to main.zig. Used by \"ir\" and \"test\". Defaults to \"{}\". ", .{fallback_main_path}); + const main_path_desc = b.fmt("Override path to main.zig. Used by \"ir\" and \"test\". Defaults to \"{s}\". ", .{fallback_main_path}); const main_path = b.option([]const u8, "main-path", main_path_desc) orelse fallback_main_path; // Tests diff --git a/compiler/builtins/bitcode/src/dec.zig b/compiler/builtins/bitcode/src/dec.zig index 79f2eb0aeb..1fdf363910 100644 --- a/compiler/builtins/bitcode/src/dec.zig +++ b/compiler/builtins/bitcode/src/dec.zig @@ -8,6 +8,8 @@ pub const RocDec = struct { num: i128, pub const decimal_places: comptime u32 = 18; + pub const whole_number_places: comptime u32 = 21; + const max_digits: comptime u32 = decimal_places + whole_number_places; pub const min: comptime RocDec = .{ .num = math.minInt(i128) }; pub const max: comptime RocDec = .{ .num = math.maxInt(i128) }; @@ -16,10 +18,10 @@ pub const RocDec = struct { pub const one_point_zero: comptime RocDec = .{ .num = one_point_zero_i128 }; pub fn fromU64(num: u64) RocDec { - return .{ .num = @intCast(i128, num) * one_point_zero_i128 }; + return .{ .num = num * one_point_zero_i128 }; } - pub fn fromString(roc_str: RocStr) ?RocDec { + pub fn fromStr(roc_str: RocStr) ?RocDec { if (roc_str.isEmpty()) { return null; } @@ -101,6 +103,7 @@ pub const RocDec = struct { return dec; } + // TODO: Replace this with https://github.com/rtfeldman/roc/pull/1365/files#r643580738 fn isDigit(c: u8) bool { return switch (c) { '0'...'9' => true, @@ -108,6 +111,92 @@ pub const RocDec = struct { }; } + pub fn toStr(self: RocDec) ?RocStr { + // Check if this Dec is negative, and if so convert to positive + // We will handle adding the '-' later + const is_negative = self.num < 0; + const num = if (is_negative) std.math.negate(self.num) catch { + std.debug.panic("TODO runtime exception failing to negate", .{}); + } else self.num; + + // Format the backing i128 into an array of digits (u8s) + var digit_bytes: [max_digits + 1]u8 = undefined; + var num_digits_formatted = std.fmt.formatIntBuf(digit_bytes[0..], num, 10, false, .{}); + + // If self < 1, then pad digit_bytes with '0' to be at least 18 digits + if (num_digits_formatted < decimal_places) { + var diff = decimal_places - num_digits_formatted; + var padded_digit_bytes: [max_digits + 1]u8 = undefined; + var index: usize = 0; + + while (index < decimal_places) { + if (index < diff) { + padded_digit_bytes[index] = '0'; + } else { + padded_digit_bytes[index] = digit_bytes[index - diff]; + } + index += 1; + } + num_digits_formatted = num_digits_formatted + diff; + digit_bytes = padded_digit_bytes; + } + + // Get the slice of the part before the decimal + // If this is empty, then hardcode a '0' + var before_digits_num_raw: usize = undefined; + var before_digits_slice: []const u8 = undefined; + if (num_digits_formatted > decimal_places) { + before_digits_num_raw = num_digits_formatted - decimal_places; + before_digits_slice = digit_bytes[0..before_digits_num_raw]; + } else { + before_digits_num_raw = 0; + before_digits_slice = "0"; + } + + // Figure out the index where the trailing zeros start + var index = decimal_places - 1; + var trim_index: ?usize = null; + var is_consecutive_zero = true; + while (index != 0) { + var digit = digit_bytes[before_digits_num_raw + index]; + // 48 => '0', 170 => '' + if ((digit == 48 or digit == 170) and is_consecutive_zero) { + trim_index = index; + } else { + is_consecutive_zero = false; + } + index -= 1; + } + + // Get the slice of the part afterthe decimal + var after_digits_slice: []const u8 = undefined; + after_digits_slice = digit_bytes[before_digits_num_raw..(before_digits_num_raw + if (trim_index) |i| i else decimal_places)]; + + // Make the RocStr + + var sign_len: usize = if (is_negative) 1 else 0; + var dot_len: usize = 1; + var str_len: usize = sign_len + before_digits_slice.len + dot_len + after_digits_slice.len; + + // TODO: Ideally we'd use [str_len]u8 here, but Zig gives an error if we do that. + // [max_digits + 2]u8 here to account for '.' and '-', aka the max possible length of the string + var str_bytes: [max_digits + 2]u8 = undefined; + + // Join the whole number slice & the decimal slice together + // The format template arg in bufPrint is `comptime`, so we have to repeate the whole statement in each branch + if (is_negative) { + _ = std.fmt.bufPrint(str_bytes[0 .. str_len + 1], "-{s}.{s}", .{ before_digits_slice, after_digits_slice }) catch { + std.debug.panic("TODO runtime exception failing to print slices", .{}); + }; + } else { + _ = std.fmt.bufPrint(str_bytes[0 .. str_len + 1], "{s}.{s}", .{ before_digits_slice, after_digits_slice }) catch { + std.debug.panic("TODO runtime exception failing to print slices", .{}); + }; + } + + return RocStr.init(&str_bytes, str_len); + } + pub fn negate(self: RocDec) ?RocDec { var negated = math.negate(self.num) catch null; return if (negated) |n| .{ .num = n } else null; @@ -319,144 +408,264 @@ fn mul_u128(a: u128, b: u128) U256 { const testing = std.testing; const expectEqual = testing.expectEqual; +const expectEqualSlices = testing.expectEqualSlices; +const expect = testing.expect; test "fromU64" { var dec = RocDec.fromU64(25); - expectEqual(RocDec{ .num = 25000000000000000000 }, dec); + try expectEqual(RocDec{ .num = 25000000000000000000 }, dec); } -test "fromString: empty" { +test "fromStr: empty" { var roc_str = RocStr.init("", 0); - var dec = RocDec.fromString(roc_str); + var dec = RocDec.fromStr(roc_str); - expectEqual(dec, null); + try expectEqual(dec, null); } -test "fromString: 0" { +test "fromStr: 0" { var roc_str = RocStr.init("0", 1); - var dec = RocDec.fromString(roc_str); + var dec = RocDec.fromStr(roc_str); - expectEqual(RocDec{ .num = 0 }, dec.?); + try expectEqual(RocDec{ .num = 0 }, dec.?); } -test "fromString: 1" { +test "fromStr: 1" { var roc_str = RocStr.init("1", 1); - var dec = RocDec.fromString(roc_str); + var dec = RocDec.fromStr(roc_str); - expectEqual(RocDec.one_point_zero, dec.?); + try expectEqual(RocDec.one_point_zero, dec.?); } -test "fromString: 123.45" { +test "fromStr: 123.45" { var roc_str = RocStr.init("123.45", 6); - var dec = RocDec.fromString(roc_str); + var dec = RocDec.fromStr(roc_str); - expectEqual(RocDec{ .num = 123450000000000000000 }, dec.?); + try expectEqual(RocDec{ .num = 123450000000000000000 }, dec.?); } -test "fromString: .45" { +test "fromStr: .45" { var roc_str = RocStr.init(".45", 3); - var dec = RocDec.fromString(roc_str); + var dec = RocDec.fromStr(roc_str); - expectEqual(RocDec{ .num = 450000000000000000 }, dec.?); + try expectEqual(RocDec{ .num = 450000000000000000 }, dec.?); } -test "fromString: 0.45" { +test "fromStr: 0.45" { var roc_str = RocStr.init("0.45", 4); - var dec = RocDec.fromString(roc_str); + var dec = RocDec.fromStr(roc_str); - expectEqual(RocDec{ .num = 450000000000000000 }, dec.?); + try expectEqual(RocDec{ .num = 450000000000000000 }, dec.?); } -test "fromString: 123" { +test "fromStr: 123" { var roc_str = RocStr.init("123", 3); - var dec = RocDec.fromString(roc_str); + var dec = RocDec.fromStr(roc_str); - expectEqual(RocDec{ .num = 123000000000000000000 }, dec.?); + try expectEqual(RocDec{ .num = 123000000000000000000 }, dec.?); } -test "fromString: -.45" { +test "fromStr: -.45" { var roc_str = RocStr.init("-.45", 4); - var dec = RocDec.fromString(roc_str); + var dec = RocDec.fromStr(roc_str); - expectEqual(RocDec{ .num = -450000000000000000 }, dec.?); + try expectEqual(RocDec{ .num = -450000000000000000 }, dec.?); } -test "fromString: -0.45" { +test "fromStr: -0.45" { var roc_str = RocStr.init("-0.45", 5); - var dec = RocDec.fromString(roc_str); + var dec = RocDec.fromStr(roc_str); - expectEqual(RocDec{ .num = -450000000000000000 }, dec.?); + try expectEqual(RocDec{ .num = -450000000000000000 }, dec.?); } -test "fromString: -123" { +test "fromStr: -123" { var roc_str = RocStr.init("-123", 4); - var dec = RocDec.fromString(roc_str); + var dec = RocDec.fromStr(roc_str); - expectEqual(RocDec{ .num = -123000000000000000000 }, dec.?); + try expectEqual(RocDec{ .num = -123000000000000000000 }, dec.?); } -test "fromString: -123.45" { +test "fromStr: -123.45" { var roc_str = RocStr.init("-123.45", 7); - var dec = RocDec.fromString(roc_str); + var dec = RocDec.fromStr(roc_str); - expectEqual(RocDec{ .num = -123450000000000000000 }, dec.?); + try expectEqual(RocDec{ .num = -123450000000000000000 }, dec.?); } -test "fromString: abc" { +test "fromStr: abc" { var roc_str = RocStr.init("abc", 3); - var dec = RocDec.fromString(roc_str); + var dec = RocDec.fromStr(roc_str); - expectEqual(dec, null); + try expectEqual(dec, null); } -test "fromString: 123.abc" { +test "fromStr: 123.abc" { var roc_str = RocStr.init("123.abc", 7); - var dec = RocDec.fromString(roc_str); + var dec = RocDec.fromStr(roc_str); - expectEqual(dec, null); + try expectEqual(dec, null); } -test "fromString: abc.123" { +test "fromStr: abc.123" { var roc_str = RocStr.init("abc.123", 7); - var dec = RocDec.fromString(roc_str); + var dec = RocDec.fromStr(roc_str); - expectEqual(dec, null); + try expectEqual(dec, null); } -test "fromString: .123.1" { +test "fromStr: .123.1" { var roc_str = RocStr.init(".123.1", 6); - var dec = RocDec.fromString(roc_str); + var dec = RocDec.fromStr(roc_str); - expectEqual(dec, null); + try expectEqual(dec, null); +} + +test "toStr: 123.45" { + var dec: RocDec = .{ .num = 123450000000000000000 }; + var res_roc_str = dec.toStr(); + + const res_slice: []const u8 = "123.45"[0..]; + try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice()); +} + +test "toStr: -123.45" { + var dec: RocDec = .{ .num = -123450000000000000000 }; + var res_roc_str = dec.toStr(); + + const res_slice: []const u8 = "-123.45"[0..]; + try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice()); +} + +test "toStr: 123.0" { + var dec: RocDec = .{ .num = 123000000000000000000 }; + var res_roc_str = dec.toStr(); + + const res_slice: []const u8 = "123.0"[0..]; + try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice()); +} + +test "toStr: -123.0" { + var dec: RocDec = .{ .num = -123000000000000000000 }; + var res_roc_str = dec.toStr(); + + const res_slice: []const u8 = "-123.0"[0..]; + try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice()); +} + +test "toStr: 0.45" { + var dec: RocDec = .{ .num = 450000000000000000 }; + var res_roc_str = dec.toStr(); + + const res_slice: []const u8 = "0.45"[0..]; + try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice()); +} + +test "toStr: -0.45" { + var dec: RocDec = .{ .num = -450000000000000000 }; + var res_roc_str = dec.toStr(); + + const res_slice: []const u8 = "-0.45"[0..]; + try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice()); +} + +test "toStr: 0.00045" { + var dec: RocDec = .{ .num = 000450000000000000 }; + var res_roc_str = dec.toStr(); + + const res_slice: []const u8 = "0.00045"[0..]; + try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice()); +} + +test "toStr: -0.00045" { + var dec: RocDec = .{ .num = -000450000000000000 }; + var res_roc_str = dec.toStr(); + + const res_slice: []const u8 = "-0.00045"[0..]; + try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice()); +} + +test "toStr: -111.123456789" { + var dec: RocDec = .{ .num = -111123456789000000000 }; + var res_roc_str = dec.toStr(); + + const res_slice: []const u8 = "-111.123456789"[0..]; + try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice()); +} + +test "toStr: 123.1111111" { + var dec: RocDec = .{ .num = 123111111100000000000 }; + var res_roc_str = dec.toStr(); + + const res_slice: []const u8 = "123.1111111"[0..]; + try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice()); +} + +test "toStr: 123.1111111111111 (big str)" { + var dec: RocDec = .{ .num = 123111111111111000000 }; + var res_roc_str = dec.toStr(); + errdefer res_roc_str.?.deinit(); + defer res_roc_str.?.deinit(); + + const res_slice: []const u8 = "123.111111111111"[0..]; + try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice()); +} + +test "toStr: 123.111111111111444444 (max number of decimal places)" { + var dec: RocDec = .{ .num = 123111111111111444444 }; + var res_roc_str = dec.toStr(); + errdefer res_roc_str.?.deinit(); + defer res_roc_str.?.deinit(); + + const res_slice: []const u8 = "123.111111111111444444"[0..]; + try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice()); +} + +test "toStr: 12345678912345678912.111111111111111111 (max number of digits)" { + var dec: RocDec = .{ .num = 12345678912345678912111111111111111111 }; + var res_roc_str = dec.toStr(); + errdefer res_roc_str.?.deinit(); + defer res_roc_str.?.deinit(); + + const res_slice: []const u8 = "12345678912345678912.111111111111111111"[0..]; + try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice()); +} + +test "toStr: 0" { + var dec: RocDec = .{ .num = 0 }; + var res_roc_str = dec.toStr(); + + const res_slice: []const u8 = "0.0"[0..]; + try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice()); } test "add: 0" { var dec: RocDec = .{ .num = 0 }; - expectEqual(RocDec{ .num = 0 }, dec.add(.{ .num = 0 })); + try expectEqual(RocDec{ .num = 0 }, dec.add(.{ .num = 0 })); } test "add: 1" { var dec: RocDec = .{ .num = 0 }; - expectEqual(RocDec{ .num = 1 }, dec.add(.{ .num = 1 })); + try expectEqual(RocDec{ .num = 1 }, dec.add(.{ .num = 1 })); } test "mul: by 0" { var dec: RocDec = .{ .num = 0 }; - expectEqual(RocDec{ .num = 0 }, dec.mul(.{ .num = 0 })); + try expectEqual(RocDec{ .num = 0 }, dec.mul(.{ .num = 0 })); } test "mul: by 1" { var dec: RocDec = RocDec.fromU64(15); - expectEqual(RocDec.fromU64(15), dec.mul(RocDec.fromU64(1))); + try expectEqual(RocDec.fromU64(15), dec.mul(RocDec.fromU64(1))); } test "mul: by 2" { var dec: RocDec = RocDec.fromU64(15); - expectEqual(RocDec.fromU64(30), dec.mul(RocDec.fromU64(2))); + try expectEqual(RocDec.fromU64(30), dec.mul(RocDec.fromU64(2))); } diff --git a/compiler/builtins/bitcode/src/dict.zig b/compiler/builtins/bitcode/src/dict.zig index 84f7bf6980..2780652f1b 100644 --- a/compiler/builtins/bitcode/src/dict.zig +++ b/compiler/builtins/bitcode/src/dict.zig @@ -20,13 +20,9 @@ const Slot = packed enum(u8) { PreviouslyFilled, }; -const MaybeIndexTag = enum { - index, not_found -}; +const MaybeIndexTag = enum { index, not_found }; -const MaybeIndex = union(MaybeIndexTag) { - index: usize, not_found: void -}; +const MaybeIndex = union(MaybeIndexTag) { index: usize, not_found: void }; fn nextSeed(seed: u64) u64 { // TODO is this a valid way to get a new seed? are there better ways? @@ -795,9 +791,7 @@ pub fn dictWalk( caller(data, key, value, b2, b1); - const temp = b1; - b2 = b1; - b1 = temp; + std.mem.swap([*]u8, &b1, &b2); }, else => {}, } diff --git a/compiler/builtins/bitcode/src/hash.zig b/compiler/builtins/bitcode/src/hash.zig index 45414e68f3..1ceedadd82 100644 --- a/compiler/builtins/bitcode/src/hash.zig +++ b/compiler/builtins/bitcode/src/hash.zig @@ -202,13 +202,13 @@ const expectEqual = std.testing.expectEqual; test "test vectors" { const hash = Wyhash.hash; - expectEqual(hash(0, ""), 0x0); - expectEqual(hash(1, "a"), 0xbed235177f41d328); - expectEqual(hash(2, "abc"), 0xbe348debe59b27c3); - expectEqual(hash(3, "message digest"), 0x37320f657213a290); - expectEqual(hash(4, "abcdefghijklmnopqrstuvwxyz"), 0xd0b270e1d8a7019c); - expectEqual(hash(5, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 0x602a1894d3bbfe7f); - expectEqual(hash(6, "12345678901234567890123456789012345678901234567890123456789012345678901234567890"), 0x829e9c148b75970e); + try expectEqual(hash(0, ""), 0x0); + try expectEqual(hash(1, "a"), 0xbed235177f41d328); + try expectEqual(hash(2, "abc"), 0xbe348debe59b27c3); + try expectEqual(hash(3, "message digest"), 0x37320f657213a290); + try expectEqual(hash(4, "abcdefghijklmnopqrstuvwxyz"), 0xd0b270e1d8a7019c); + try expectEqual(hash(5, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 0x602a1894d3bbfe7f); + try expectEqual(hash(6, "12345678901234567890123456789012345678901234567890123456789012345678901234567890"), 0x829e9c148b75970e); } test "test vectors streaming" { @@ -216,19 +216,19 @@ test "test vectors streaming" { for ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") |e| { wh.update(mem.asBytes(&e)); } - expectEqual(wh.final(), 0x602a1894d3bbfe7f); + try expectEqual(wh.final(), 0x602a1894d3bbfe7f); const pattern = "1234567890"; const count = 8; const result = 0x829e9c148b75970e; - expectEqual(Wyhash.hash(6, pattern ** 8), result); + try expectEqual(Wyhash.hash(6, pattern ** 8), result); wh = Wyhash.init(6); var i: u32 = 0; while (i < count) : (i += 1) { wh.update(pattern); } - expectEqual(wh.final(), result); + try expectEqual(wh.final(), result); } test "iterative non-divisible update" { @@ -250,6 +250,6 @@ test "iterative non-divisible update" { } const iterative_hash = wy.final(); - std.testing.expectEqual(iterative_hash, non_iterative_hash); + try std.testing.expectEqual(iterative_hash, non_iterative_hash); } } diff --git a/compiler/builtins/bitcode/src/helpers/grapheme.zig b/compiler/builtins/bitcode/src/helpers/grapheme.zig index 252873cb4e..36cd2c4418 100644 --- a/compiler/builtins/bitcode/src/helpers/grapheme.zig +++ b/compiler/builtins/bitcode/src/helpers/grapheme.zig @@ -42,7 +42,7 @@ pub const BoundClass = enum(u8) { }; test "Bound Class" { - expectEqual(0, @enumToInt(BoundClass.START)); + try expectEqual(0, @enumToInt(BoundClass.START)); } // https://github.com/JuliaStrings/utf8proc/blob/master/utf8proc.c#L261 @@ -112,7 +112,7 @@ fn unsafeCodepointToBoundClass(codepoint: u21) *const BoundClass { } test "unsafeCodepointToBoundClass: valid" { - expectEqual(BoundClass.CONTROL, unsafeCodepointToBoundClass(8).*); + try expectEqual(BoundClass.CONTROL, unsafeCodepointToBoundClass(8).*); } // https://github.com/JuliaStrings/utf8proc/blob/master/utf8proc.c#L242 @@ -125,11 +125,11 @@ fn codepointToBoundClass(codepoint: u21) *const BoundClass { } test "codepointToBoundClass: valid" { - expectEqual(BoundClass.CONTROL, codepointToBoundClass(8).*); + try expectEqual(BoundClass.CONTROL, codepointToBoundClass(8).*); } test "codepointToBoundClass: invalid" { - expectEqual(BoundClass.OTHER, codepointToBoundClass(codepoint_max + 5).*); + try expectEqual(BoundClass.OTHER, codepointToBoundClass(codepoint_max + 5).*); } // https://github.com/JuliaStrings/utf8proc/blob/master/utf8proc.c#L319 diff --git a/compiler/builtins/bitcode/src/list.zig b/compiler/builtins/bitcode/src/list.zig index c35484077b..b4b8a17217 100644 --- a/compiler/builtins/bitcode/src/list.zig +++ b/compiler/builtins/bitcode/src/list.zig @@ -542,9 +542,7 @@ pub fn listWalk( const element = source_ptr + i * element_width; caller(data, element, b2, b1); - const temp = b1; - b2 = b1; - b1 = temp; + std.mem.swap([*]u8, &b1, &b2); } } @@ -591,9 +589,7 @@ pub fn listWalkBackwards( const element = source_ptr + i * element_width; caller(data, element, b2, b1); - const temp = b1; - b2 = b1; - b1 = temp; + std.mem.swap([*]u8, &b1, &b2); } } @@ -781,43 +777,19 @@ pub fn listDrop( } pub fn listRange(width: utils.IntWidth, low: Opaque, high: Opaque) callconv(.C) RocList { - const IntWidth = utils.IntWidth; - - switch (width) { - IntWidth.U8 => { - return helper1(u8, low, high); - }, - IntWidth.U16 => { - return helper1(u16, low, high); - }, - IntWidth.U32 => { - return helper1(u32, low, high); - }, - IntWidth.U64 => { - return helper1(u64, low, high); - }, - IntWidth.U128 => { - return helper1(u128, low, high); - }, - IntWidth.I8 => { - return helper1(i8, low, high); - }, - IntWidth.I16 => { - return helper1(i16, low, high); - }, - IntWidth.I32 => { - return helper1(i32, low, high); - }, - IntWidth.I64 => { - return helper1(i64, low, high); - }, - IntWidth.I128 => { - return helper1(i128, low, high); - }, - IntWidth.Usize => { - return helper1(usize, low, high); - }, - } + return switch (width) { + .U8 => helper1(u8, low, high), + .U16 => helper1(u16, low, high), + .U32 => helper1(u32, low, high), + .U64 => helper1(u64, low, high), + .U128 => helper1(u128, low, high), + .I8 => helper1(i8, low, high), + .I16 => helper1(i16, low, high), + .I32 => helper1(i32, low, high), + .I64 => helper1(i64, low, high), + .I128 => helper1(i128, low, high), + .Usize => helper1(usize, low, high), + }; } fn helper1(comptime T: type, low: Opaque, high: Opaque) RocList { diff --git a/compiler/builtins/bitcode/src/str.zig b/compiler/builtins/bitcode/src/str.zig index 4423d83df8..845fd2b853 100644 --- a/compiler/builtins/bitcode/src/str.zig +++ b/compiler/builtins/bitcode/src/str.zig @@ -273,7 +273,7 @@ pub const RocStr = extern struct { const str2_ptr: [*]u8 = &str2; var roc_str2 = RocStr.init(str2_ptr, str2_len); - expect(roc_str1.eq(roc_str2)); + try expect(roc_str1.eq(roc_str2)); roc_str1.deinit(); roc_str2.deinit(); @@ -295,7 +295,7 @@ pub const RocStr = extern struct { roc_str2.deinit(); } - expect(!roc_str1.eq(roc_str2)); + try expect(!roc_str1.eq(roc_str2)); } test "RocStr.eq: not equal same length" { @@ -314,7 +314,7 @@ pub const RocStr = extern struct { roc_str2.deinit(); } - expect(!roc_str1.eq(roc_str2)); + try expect(!roc_str1.eq(roc_str2)); } }; @@ -449,8 +449,8 @@ test "strSplitInPlace: no delimiter" { delimiter.deinit(); } - expectEqual(array.len, expected.len); - expect(array[0].eq(expected[0])); + try expectEqual(array.len, expected.len); + try expect(array[0].eq(expected[0])); } test "strSplitInPlace: empty end" { @@ -490,10 +490,10 @@ test "strSplitInPlace: empty end" { delimiter.deinit(); } - expectEqual(array.len, expected.len); - expect(array[0].eq(expected[0])); - expect(array[1].eq(expected[1])); - expect(array[2].eq(expected[2])); + try expectEqual(array.len, expected.len); + try expect(array[0].eq(expected[0])); + try expect(array[1].eq(expected[1])); + try expect(array[2].eq(expected[2])); } test "strSplitInPlace: delimiter on sides" { @@ -532,10 +532,10 @@ test "strSplitInPlace: delimiter on sides" { delimiter.deinit(); } - expectEqual(array.len, expected.len); - expect(array[0].eq(expected[0])); - expect(array[1].eq(expected[1])); - expect(array[2].eq(expected[2])); + try expectEqual(array.len, expected.len); + try expect(array[0].eq(expected[0])); + try expect(array[1].eq(expected[1])); + try expect(array[2].eq(expected[2])); } test "strSplitInPlace: three pieces" { @@ -573,10 +573,10 @@ test "strSplitInPlace: three pieces" { delimiter.deinit(); } - expectEqual(expected_array.len, array.len); - expect(array[0].eq(expected_array[0])); - expect(array[1].eq(expected_array[1])); - expect(array[2].eq(expected_array[2])); + try expectEqual(expected_array.len, array.len); + try expect(array[0].eq(expected_array[0])); + try expect(array[1].eq(expected_array[1])); + try expect(array[2].eq(expected_array[2])); } // This is used for `Str.split : Str, Str -> Array Str @@ -639,7 +639,7 @@ test "countSegments: long delimiter" { } const segments_count = countSegments(str, delimiter); - expectEqual(segments_count, 1); + try expectEqual(segments_count, 1); } test "countSegments: delimiter at start" { @@ -658,7 +658,7 @@ test "countSegments: delimiter at start" { const segments_count = countSegments(str, delimiter); - expectEqual(segments_count, 2); + try expectEqual(segments_count, 2); } test "countSegments: delimiter interspered" { @@ -677,7 +677,7 @@ test "countSegments: delimiter interspered" { const segments_count = countSegments(str, delimiter); - expectEqual(segments_count, 3); + try expectEqual(segments_count, 3); } // Str.countGraphemeClusters @@ -721,7 +721,7 @@ fn rocStrFromLiteral(bytes_arr: *const []u8) RocStr {} test "countGraphemeClusters: empty string" { const count = countGraphemeClusters(RocStr.empty()); - expectEqual(count, 0); + try expectEqual(count, 0); } test "countGraphemeClusters: ascii characters" { @@ -731,7 +731,7 @@ test "countGraphemeClusters: ascii characters" { defer str.deinit(); const count = countGraphemeClusters(str); - expectEqual(count, 4); + try expectEqual(count, 4); } test "countGraphemeClusters: utf8 characters" { @@ -741,7 +741,7 @@ test "countGraphemeClusters: utf8 characters" { defer str.deinit(); const count = countGraphemeClusters(str); - expectEqual(count, 3); + try expectEqual(count, 3); } test "countGraphemeClusters: emojis" { @@ -751,7 +751,7 @@ test "countGraphemeClusters: emojis" { defer str.deinit(); const count = countGraphemeClusters(str); - expectEqual(count, 3); + try expectEqual(count, 3); } test "countGraphemeClusters: emojis and ut8 characters" { @@ -761,7 +761,7 @@ test "countGraphemeClusters: emojis and ut8 characters" { defer str.deinit(); const count = countGraphemeClusters(str); - expectEqual(count, 6); + try expectEqual(count, 6); } test "countGraphemeClusters: emojis, ut8, and ascii characters" { @@ -771,7 +771,7 @@ test "countGraphemeClusters: emojis, ut8, and ascii characters" { defer str.deinit(); const count = countGraphemeClusters(str); - expectEqual(count, 10); + try expectEqual(count, 10); } // Str.startsWith @@ -821,27 +821,27 @@ pub fn startsWithCodePoint(string: RocStr, prefix: u32) callconv(.C) bool { test "startsWithCodePoint: ascii char" { const whole = RocStr.init("foobar", 6); const prefix = 'f'; - expect(startsWithCodePoint(whole, prefix)); + try expect(startsWithCodePoint(whole, prefix)); } test "startsWithCodePoint: emoji" { const yes = RocStr.init("πŸ’–foobar", 10); const no = RocStr.init("foobar", 6); const prefix = 'πŸ’–'; - expect(startsWithCodePoint(yes, prefix)); - expect(!startsWithCodePoint(no, prefix)); + try expect(startsWithCodePoint(yes, prefix)); + try expect(!startsWithCodePoint(no, prefix)); } test "startsWith: foo starts with fo" { const foo = RocStr.init("foo", 3); const fo = RocStr.init("fo", 2); - expect(startsWith(foo, fo)); + try expect(startsWith(foo, fo)); } test "startsWith: 123456789123456789 starts with 123456789123456789" { const str = RocStr.init("123456789123456789", 18); defer str.deinit(); - expect(startsWith(str, str)); + try expect(startsWith(str, str)); } test "startsWith: 12345678912345678910 starts with 123456789123456789" { @@ -850,7 +850,7 @@ test "startsWith: 12345678912345678910 starts with 123456789123456789" { const prefix = RocStr.init("123456789123456789", 18); defer prefix.deinit(); - expect(startsWith(str, prefix)); + try expect(startsWith(str, prefix)); } // Str.endsWith @@ -882,13 +882,13 @@ test "endsWith: foo ends with oo" { defer foo.deinit(); defer oo.deinit(); - expect(endsWith(foo, oo)); + try expect(endsWith(foo, oo)); } test "endsWith: 123456789123456789 ends with 123456789123456789" { const str = RocStr.init("123456789123456789", 18); defer str.deinit(); - expect(endsWith(str, str)); + try expect(endsWith(str, str)); } test "endsWith: 12345678912345678910 ends with 345678912345678910" { @@ -897,7 +897,7 @@ test "endsWith: 12345678912345678910 ends with 345678912345678910" { defer str.deinit(); defer suffix.deinit(); - expect(endsWith(str, suffix)); + try expect(endsWith(str, suffix)); } test "endsWith: hello world ends with world" { @@ -906,7 +906,7 @@ test "endsWith: hello world ends with world" { defer str.deinit(); defer suffix.deinit(); - expect(endsWith(str, suffix)); + try expect(endsWith(str, suffix)); } // Str.concat @@ -978,7 +978,7 @@ test "RocStr.concat: small concat small" { defer result.deinit(); - expect(roc_str3.eq(result)); + try expect(roc_str3.eq(result)); } pub const RocListStr = extern struct { @@ -1057,7 +1057,7 @@ test "RocStr.joinWith: result is big" { defer result.deinit(); - expect(roc_result.eq(result)); + try expect(roc_result.eq(result)); } // Str.toBytes @@ -1191,8 +1191,8 @@ fn validateUtf8BytesX(str: RocList) FromUtf8Result { return fromUtf8(str); } -fn expectOk(result: FromUtf8Result) void { - expectEqual(result.is_ok, true); +fn expectOk(result: FromUtf8Result) !void { + try expectEqual(result.is_ok, true); } fn sliceHelp(bytes: [*]const u8, length: usize) RocList { @@ -1217,7 +1217,7 @@ test "validateUtf8Bytes: ascii" { const ptr: [*]const u8 = @ptrCast([*]const u8, raw); const list = sliceHelp(ptr, raw.len); - expectOk(validateUtf8BytesX(list)); + try expectOk(validateUtf8BytesX(list)); } test "validateUtf8Bytes: unicode Ε“" { @@ -1225,7 +1225,7 @@ test "validateUtf8Bytes: unicode Ε“" { const ptr: [*]const u8 = @ptrCast([*]const u8, raw); const list = sliceHelp(ptr, raw.len); - expectOk(validateUtf8BytesX(list)); + try expectOk(validateUtf8BytesX(list)); } test "validateUtf8Bytes: unicode βˆ†" { @@ -1233,7 +1233,7 @@ test "validateUtf8Bytes: unicode βˆ†" { const ptr: [*]const u8 = @ptrCast([*]const u8, raw); const list = sliceHelp(ptr, raw.len); - expectOk(validateUtf8BytesX(list)); + try expectOk(validateUtf8BytesX(list)); } test "validateUtf8Bytes: emoji" { @@ -1241,7 +1241,7 @@ test "validateUtf8Bytes: emoji" { const ptr: [*]const u8 = @ptrCast([*]const u8, raw); const list = sliceHelp(ptr, raw.len); - expectOk(validateUtf8BytesX(list)); + try expectOk(validateUtf8BytesX(list)); } test "validateUtf8Bytes: unicode βˆ† in middle of array" { @@ -1249,15 +1249,15 @@ test "validateUtf8Bytes: unicode βˆ† in middle of array" { const ptr: [*]const u8 = @ptrCast([*]const u8, raw); const list = sliceHelp(ptr, raw.len); - expectOk(validateUtf8BytesX(list)); + try expectOk(validateUtf8BytesX(list)); } -fn expectErr(list: RocList, index: usize, err: Utf8DecodeError, problem: Utf8ByteProblem) void { +fn expectErr(list: RocList, index: usize, err: Utf8DecodeError, problem: Utf8ByteProblem) !void { const str_ptr = @ptrCast([*]u8, list.bytes); const str_len = list.length; - expectError(err, numberOfNextCodepointBytes(str_ptr, str_len, index)); - expectEqual(toErrUtf8ByteResponse(index, problem), validateUtf8Bytes(str_ptr, str_len)); + try expectError(err, numberOfNextCodepointBytes(str_ptr, str_len, index)); + try expectEqual(toErrUtf8ByteResponse(index, problem), validateUtf8Bytes(str_ptr, str_len)); } test "validateUtf8Bytes: invalid start byte" { @@ -1266,7 +1266,7 @@ test "validateUtf8Bytes: invalid start byte" { const ptr: [*]const u8 = @ptrCast([*]const u8, raw); const list = sliceHelp(ptr, raw.len); - expectErr(list, 2, error.Utf8InvalidStartByte, Utf8ByteProblem.InvalidStartByte); + try expectErr(list, 2, error.Utf8InvalidStartByte, Utf8ByteProblem.InvalidStartByte); } test "validateUtf8Bytes: unexpected eof for 2 byte sequence" { @@ -1275,7 +1275,7 @@ test "validateUtf8Bytes: unexpected eof for 2 byte sequence" { const ptr: [*]const u8 = @ptrCast([*]const u8, raw); const list = sliceHelp(ptr, raw.len); - expectErr(list, 3, error.UnexpectedEof, Utf8ByteProblem.UnexpectedEndOfSequence); + try expectErr(list, 3, error.UnexpectedEof, Utf8ByteProblem.UnexpectedEndOfSequence); } test "validateUtf8Bytes: expected continuation for 2 byte sequence" { @@ -1284,7 +1284,7 @@ test "validateUtf8Bytes: expected continuation for 2 byte sequence" { const ptr: [*]const u8 = @ptrCast([*]const u8, raw); const list = sliceHelp(ptr, raw.len); - expectErr(list, 3, error.Utf8ExpectedContinuation, Utf8ByteProblem.ExpectedContinuation); + try expectErr(list, 3, error.Utf8ExpectedContinuation, Utf8ByteProblem.ExpectedContinuation); } test "validateUtf8Bytes: unexpected eof for 3 byte sequence" { @@ -1293,7 +1293,7 @@ test "validateUtf8Bytes: unexpected eof for 3 byte sequence" { const ptr: [*]const u8 = @ptrCast([*]const u8, raw); const list = sliceHelp(ptr, raw.len); - expectErr(list, 3, error.UnexpectedEof, Utf8ByteProblem.UnexpectedEndOfSequence); + try expectErr(list, 3, error.UnexpectedEof, Utf8ByteProblem.UnexpectedEndOfSequence); } test "validateUtf8Bytes: expected continuation for 3 byte sequence" { @@ -1302,7 +1302,7 @@ test "validateUtf8Bytes: expected continuation for 3 byte sequence" { const ptr: [*]const u8 = @ptrCast([*]const u8, raw); const list = sliceHelp(ptr, raw.len); - expectErr(list, 3, error.Utf8ExpectedContinuation, Utf8ByteProblem.ExpectedContinuation); + try expectErr(list, 3, error.Utf8ExpectedContinuation, Utf8ByteProblem.ExpectedContinuation); } test "validateUtf8Bytes: unexpected eof for 4 byte sequence" { @@ -1311,7 +1311,7 @@ test "validateUtf8Bytes: unexpected eof for 4 byte sequence" { const ptr: [*]const u8 = @ptrCast([*]const u8, raw); const list = sliceHelp(ptr, raw.len); - expectErr(list, 3, error.UnexpectedEof, Utf8ByteProblem.UnexpectedEndOfSequence); + try expectErr(list, 3, error.UnexpectedEof, Utf8ByteProblem.UnexpectedEndOfSequence); } test "validateUtf8Bytes: expected continuation for 4 byte sequence" { @@ -1320,7 +1320,7 @@ test "validateUtf8Bytes: expected continuation for 4 byte sequence" { const ptr: [*]const u8 = @ptrCast([*]const u8, raw); const list = sliceHelp(ptr, raw.len); - expectErr(list, 3, error.Utf8ExpectedContinuation, Utf8ByteProblem.ExpectedContinuation); + try expectErr(list, 3, error.Utf8ExpectedContinuation, Utf8ByteProblem.ExpectedContinuation); } test "validateUtf8Bytes: overlong" { @@ -1329,7 +1329,7 @@ test "validateUtf8Bytes: overlong" { const ptr: [*]const u8 = @ptrCast([*]const u8, raw); const list = sliceHelp(ptr, raw.len); - expectErr(list, 3, error.Utf8OverlongEncoding, Utf8ByteProblem.OverlongEncoding); + try expectErr(list, 3, error.Utf8OverlongEncoding, Utf8ByteProblem.OverlongEncoding); } test "validateUtf8Bytes: codepoint out too large" { @@ -1338,7 +1338,7 @@ test "validateUtf8Bytes: codepoint out too large" { const ptr: [*]const u8 = @ptrCast([*]const u8, raw); const list = sliceHelp(ptr, raw.len); - expectErr(list, 3, error.Utf8CodepointTooLarge, Utf8ByteProblem.CodepointTooLarge); + try expectErr(list, 3, error.Utf8CodepointTooLarge, Utf8ByteProblem.CodepointTooLarge); } test "validateUtf8Bytes: surrogate halves" { @@ -1347,5 +1347,5 @@ test "validateUtf8Bytes: surrogate halves" { const ptr: [*]const u8 = @ptrCast([*]const u8, raw); const list = sliceHelp(ptr, raw.len); - expectErr(list, 3, error.Utf8EncodesSurrogateHalf, Utf8ByteProblem.EncodesSurrogateHalf); + try expectErr(list, 3, error.Utf8EncodesSurrogateHalf, Utf8ByteProblem.EncodesSurrogateHalf); } diff --git a/compiler/builtins/bitcode/src/utils.zig b/compiler/builtins/bitcode/src/utils.zig index ee08aeeacf..be99cab009 100644 --- a/compiler/builtins/bitcode/src/utils.zig +++ b/compiler/builtins/bitcode/src/utils.zig @@ -71,44 +71,6 @@ pub const IntWidth = enum(u8) { Usize, }; -pub fn intWidth(width: IntWidth) anytype { - switch (width) { - IntWidth.U8 => { - return u8; - }, - IntWidth.U16 => { - return u16; - }, - IntWidth.U32 => { - return u32; - }, - IntWidth.U64 => { - return u64; - }, - IntWidth.U128 => { - return u128; - }, - IntWidth.I8 => { - return i8; - }, - IntWidth.I16 => { - return i16; - }, - IntWidth.I32 => { - return i32; - }, - IntWidth.I64 => { - return i64; - }, - IntWidth.I128 => { - return i128; - }, - IntWidth.Usize => { - return usize; - }, - } -} - pub fn decref( bytes_or_null: ?[*]u8, data_bytes: usize, diff --git a/compiler/builtins/build.rs b/compiler/builtins/build.rs index 8b42e59835..05f5aa284c 100644 --- a/compiler/builtins/build.rs +++ b/compiler/builtins/build.rs @@ -56,11 +56,7 @@ fn main() { let dest_bc = dest_bc_path.to_str().expect("Invalid dest bc path"); println!("Compiling bitcode to: {}", dest_bc); - run_command( - build_script_dir_path, - "llvm-as-10", - &[dest_ir, "-o", dest_bc], - ); + run_command(build_script_dir_path, "llvm-as", &[dest_ir, "-o", dest_bc]); get_zig_files(bitcode_path.as_path(), &|path| { let path: &Path = path; diff --git a/compiler/gen_llvm/src/llvm/bitcode.rs b/compiler/gen_llvm/src/llvm/bitcode.rs index a2d98cd868..b9cd56ff58 100644 --- a/compiler/gen_llvm/src/llvm/bitcode.rs +++ b/compiler/gen_llvm/src/llvm/bitcode.rs @@ -110,6 +110,9 @@ fn build_transform_caller_help<'a, 'ctx, 'env>( &(bumpalo::vec![ in env.arena; BasicTypeEnum::PointerType(arg_type); argument_layouts.len() + 2 ]), ); + // called from zig, must use C calling convention + function_value.set_call_conventions(C_CALL_CONV); + let kind_id = Attribute::get_named_enum_kind_id("alwaysinline"); debug_assert!(kind_id > 0); let attr = env.context.create_enum_attribute(kind_id, 1); @@ -303,6 +306,9 @@ fn build_rc_wrapper<'a, 'ctx, 'env>( ), }; + // called from zig, must use C calling convention + function_value.set_call_conventions(C_CALL_CONV); + let kind_id = Attribute::get_named_enum_kind_id("alwaysinline"); debug_assert!(kind_id > 0); let attr = env.context.create_enum_attribute(kind_id, 1); @@ -381,6 +387,9 @@ pub fn build_eq_wrapper<'a, 'ctx, 'env>( &[arg_type.into(), arg_type.into()], ); + // called from zig, must use C calling convention + function_value.set_call_conventions(C_CALL_CONV); + let kind_id = Attribute::get_named_enum_kind_id("alwaysinline"); debug_assert!(kind_id > 0); let attr = env.context.create_enum_attribute(kind_id, 1); @@ -455,6 +464,9 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>( &[arg_type.into(), arg_type.into(), arg_type.into()], ); + // called from zig, must use C calling convention + function_value.set_call_conventions(C_CALL_CONV); + // we expose this function to zig; must use c calling convention function_value.set_call_conventions(C_CALL_CONV); diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index d8ef35063d..3d84e2c3ad 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -301,6 +301,8 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> { /* dwo_id */ 0, /* split_debug_inling */ false, /* debug_info_for_profiling */ false, + "", + "", ) } diff --git a/examples/benchmarks/platform/host.zig b/examples/benchmarks/platform/host.zig index 56461d93e6..fdeb1a0ef5 100644 --- a/examples/benchmarks/platform/host.zig +++ b/examples/benchmarks/platform/host.zig @@ -163,7 +163,7 @@ pub export fn roc_fx_getInt() GetInt { } fn roc_fx_getInt_help() !i64 { - const stdin = std.io.getStdIn().inStream(); + const stdin = std.io.getStdIn().reader(); var buf: [40]u8 = undefined; const line: []u8 = (try stdin.readUntilDelimiterOrEof(&buf, '\n')) orelse ""; diff --git a/examples/hello-world/platform/host.zig b/examples/hello-world/platform/host.zig index 1419ddd15e..d1a563a68e 100644 --- a/examples/hello-world/platform/host.zig +++ b/examples/hello-world/platform/host.zig @@ -59,7 +59,7 @@ pub export fn main() i32 { roc__mainForHost_1_exposed(&callresult); // stdout the result - stdout.print("{}\n", .{callresult.content.asSlice()}) catch unreachable; + stdout.print("{s}\n", .{callresult.content.asSlice()}) catch unreachable; callresult.content.deinit(); diff --git a/nix/bin/llvm-as-10 b/nix/bin/llvm-as-10 deleted file mode 100755 index 65839a9b5a..0000000000 --- a/nix/bin/llvm-as-10 +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -llvm-as "$@" diff --git a/nix/zig-unstable.nix b/nix/zig-unstable.nix deleted file mode 100644 index dce910d0c4..0000000000 --- a/nix/zig-unstable.nix +++ /dev/null @@ -1,50 +0,0 @@ -{ pkgs }: - -let - # system helpers - splitSystem = builtins.split "-" builtins.currentSystem; - arch = builtins.elemAt splitSystem 0; - isAarch64 = arch == "aarch64"; - setForSystem = { darwin, darwinAarch64, linux, linuxAarch64 }: - if pkgs.stdenv.isDarwin - then ( - if isAarch64 - then darwinAarch64 - else darwin - ) - else ( - if isAarch64 - then linuxAarch64 - else linux - ); - - version = "0.8.0-dev.2711+11ae6c42c"; - osName = - if pkgs.stdenv.isDarwin - then "macos" else "linux"; - archiveName = "zig-${osName}-${arch}-${version}"; - sha256 = setForSystem { - darwin = "bf2a4cd1516d202cfbbcaa7b1308d36aa21a9f9284b39297e70f98c003f479e3"; - darwinAarch64 = "6bc35c3b40b853cd351c890c94c4a6043f5ca492ff6d704bdb1544fe1fe54d9a"; - linux = "b443cc2259fe7712ffc954745266e3ec846e27854713d817bcec35fefd655a8c"; - linuxAarch64 = "229830e6dc92f641a1106af3a8ee96fdef379ffd3a3d7db7ed62d2b46bd8ed45"; - }; -in -pkgs.stdenv.mkDerivation { - pname = "zig-unstable"; - version = version; - src = pkgs.fetchurl { - inherit sha256; - name = "${archiveName}.tar.xz"; - url = "https://ziglang.org/builds/${archiveName}.tar.xz"; - }; - phases = [ "unpackPhase" ]; - unpackPhase = '' - mkdir -p $out/bin - tar -xf $src - cp ${archiveName}/zig $out/zig - cp -r ${archiveName}/lib $out/lib - ln -s "$out/zig" "$out/bin/zig" - chmod +x $out/bin/zig - ''; -} diff --git a/nix/zig.nix b/nix/zig.nix index b431275b83..0f18ce1672 100644 --- a/nix/zig.nix +++ b/nix/zig.nix @@ -1,28 +1,48 @@ { pkgs }: -if pkgs.stdenv.isDarwin then - let - version = "0.7.1"; - archiveName = "zig-macos-x86_64-${version}"; - sha256 = "845cb17562978af0cf67e3993f4e33330525eaf01ead9386df9105111e3bc519"; - in - pkgs.stdenv.mkDerivation { - pname = "zig"; - version = version; - src = pkgs.fetchurl { - inherit sha256; - name = "${archiveName}.tar.xz"; - url = "https://ziglang.org/download/${version}/${archiveName}.tar.xz"; - }; - phases = [ "unpackPhase" ]; - unpackPhase = '' - mkdir -p $out/bin - tar -xf $src - cp ${archiveName}/zig $out/zig - cp -r ${archiveName}/lib $out/lib - ln -s "$out/zig" "$out/bin/zig" - chmod +x $out/bin/zig - ''; - } -else - pkgs.zig +let + version = "0.8.0"; + + osName = + if pkgs.stdenv.isDarwin then + "macos" + else + "linux"; + + splitSystem = builtins.split "-" builtins.currentSystem; + arch = builtins.elemAt splitSystem 0; + isAarch64 = arch == "aarch64"; + + archiveName = "zig-${osName}-${arch}-${version}"; + + # If you're system is not aarch64, we assume it's x86_64 + sha256 = + if pkgs.stdenv.isDarwin then + if isAarch64 then + "b32d13f66d0e1ff740b3326d66a469ee6baddbd7211fa111c066d3bd57683111" + else + "279f9360b5cb23103f0395dc4d3d0d30626e699b1b4be55e98fd985b62bc6fbe" + else + if isAarch64 then + "ee204ca2c2037952cf3f8b10c609373a08a291efa4af7b3c73be0f2b27720470" + else + "502625d3da3ae595c5f44a809a87714320b7a40e6dff4a895b5fa7df3391d01e"; +in +pkgs.stdenv.mkDerivation { + pname = "zig"; + version = version; + src = pkgs.fetchurl { + inherit sha256; + name = "${archiveName}.tar.xz"; + url = "https://ziglang.org/download/${version}/${archiveName}.tar.xz"; + }; + phases = [ "unpackPhase" ]; + unpackPhase = '' + mkdir -p $out/bin + tar -xf $src + cp ${archiveName}/zig $out/zig + cp -r ${archiveName}/lib $out/lib + ln -s "$out/zig" "$out/bin/zig" + chmod +x $out/bin/zig + ''; +} diff --git a/shell.nix b/shell.nix index d19c8a7c22..43dee8500f 100644 --- a/shell.nix +++ b/shell.nix @@ -42,9 +42,8 @@ let xorg.libxcb ]; - llvmPkgs = pkgs.llvmPackages_10; + llvmPkgs = pkgs.llvmPackages_12; - # zig = import ./nix/zig-unstable.nix { inherit pkgs; }; zig = import ./nix/zig.nix { inherit pkgs; }; inputs = with pkgs;[ @@ -80,7 +79,7 @@ pkgs.mkShell buildInputs = inputs ++ darwinInputs ++ linuxInputs; # Additional Env vars - LLVM_SYS_100_PREFIX = "${llvmPkgs.llvm}"; + LLVM_SYS_120_PREFIX = "${llvmPkgs.llvm}"; LD_LIBRARY_PATH = with pkgs; lib.makeLibraryPath @@ -97,11 +96,4 @@ pkgs.mkShell ] ++ linuxInputs ); - - # Non Nix llvm installs names the bin llvm-as-${version}, so we - # alias `llvm` to `llvm-as-${version}` here. - # This the name of the file in nix/bin will need to be updated whenever llvm is updated - shellHook = '' - export PATH="$PATH:$PWD/nix/bin" - ''; } diff --git a/vendor/inkwell/Cargo.toml b/vendor/inkwell/Cargo.toml index 289eec8845..85af15fec2 100644 --- a/vendor/inkwell/Cargo.toml +++ b/vendor/inkwell/Cargo.toml @@ -23,7 +23,7 @@ edition = "2018" # commit of TheDan64/inkwell, push a new tag which points to the latest commit, # change the tag value in this Cargo.toml to point to that tag, and `cargo update`. # This way, GitHub Actions works and nobody's builds get broken. -inkwell = { git = "https://github.com/rtfeldman/inkwell", tag = "llvm12-0.release2", features = [ "llvm10-0" ] } +inkwell = { git = "https://github.com/rtfeldman/inkwell", tag = "llvm12-0.release4", features = [ "llvm12-0" ] } [features] target-arm = []