mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Merge branch 'trunk' into morphic-static-strings
This commit is contained in:
commit
d263016a84
35 changed files with 917 additions and 589 deletions
2
.envrc
2
.envrc
|
@ -93,7 +93,7 @@ use_nix() {
|
|||
fi
|
||||
|
||||
log_status "use nix: updating cache"
|
||||
nix-shell --pure "${drv}" --show-trace --run "$(join_args "$direnv" dump bash)" > "${dump}"
|
||||
nix-shell "${drv}" --show-trace --run "$(join_args "$direnv" dump bash)" > "${dump}"
|
||||
if [[ "${?}" -ne 0 ]] || [[ ! -f "${dump}" ]] || ! grep -q IN_NIX_SHELL "${dump}"; then
|
||||
rm -rf "${wd}"
|
||||
fail "use nix: was not able to update the cache of the environment. Please run 'direnv reload' to try again."
|
||||
|
|
|
@ -20,7 +20,7 @@ For debugging LLVM IR, we use [DebugIR](https://github.com/vaivaswatha/debugir).
|
|||
|
||||
### libunwind & libc++-dev
|
||||
|
||||
MacOS systems should already have `libunwind`, but other systems will need to install it (On Ubuntu, this can be donw with `sudo apt-get install libunwind-dev`).
|
||||
MacOS systems should already have `libunwind`, but other systems will need to install it (On Ubuntu, this can be done with `sudo apt-get install libunwind-dev`).
|
||||
Some systems may already have `libc++-dev` on them, but if not, you may need to install it. (On Ubuntu, this can be done with `sudo apt-get install libc++-dev`.)
|
||||
|
||||
### libcxb libraries
|
||||
|
|
391
Cargo.lock
generated
391
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -14,6 +14,8 @@ members = [
|
|||
"compiler/reporting",
|
||||
"compiler/fmt",
|
||||
"compiler/mono",
|
||||
"compiler/test_mono_macros",
|
||||
"compiler/test_mono",
|
||||
"compiler/load",
|
||||
"compiler/gen",
|
||||
"compiler/gen_dev",
|
||||
|
@ -21,6 +23,7 @@ members = [
|
|||
"compiler/arena_pool",
|
||||
"compiler/test_gen",
|
||||
"vendor/ena",
|
||||
"vendor/inkwell",
|
||||
"vendor/pathfinding",
|
||||
"vendor/pretty",
|
||||
"editor",
|
||||
|
|
|
@ -62,24 +62,7 @@ inlinable_string = "0.1"
|
|||
libc = "0.2"
|
||||
libloading = "0.6"
|
||||
|
||||
# NOTE: rtfeldman/inkwell is a fork of TheDan64/inkwell which does not change anything.
|
||||
#
|
||||
# The reason for this fork is that the way Inkwell is designed, you have to use
|
||||
# a particular branch (e.g. "llvm8-0") in Cargo.toml. That would be fine, except that
|
||||
# breaking changes get pushed directly to that branch, which breaks our build
|
||||
# without warning.
|
||||
#
|
||||
# We tried referencing a specific rev on TheDan64/inkwell directly (instead of branch),
|
||||
# but although that worked locally, it did not work on GitHub Actions. (After a few
|
||||
# hours of investigation, gave up trying to figure out why.) So this is the workaround:
|
||||
# having an immutable tag on the rtfeldman/inkwell fork which points to
|
||||
# a particular "release" of Inkwell.
|
||||
#
|
||||
# When we want to update Inkwell, we can sync up rtfeldman/inkwell to the latest
|
||||
# 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 = "llvm10-0.release4", features = [ "llvm10-0" ] }
|
||||
inkwell = { path = "../vendor/inkwell" }
|
||||
target-lexicon = "0.10"
|
||||
tempfile = "3.1.0"
|
||||
|
||||
|
|
|
@ -28,24 +28,7 @@ inlinable_string = "0.1.0"
|
|||
libloading = "0.6"
|
||||
tempfile = "3.1.0"
|
||||
serde_json = "1.0"
|
||||
# NOTE: rtfeldman/inkwell is a fork of TheDan64/inkwell which does not change anything.
|
||||
#
|
||||
# The reason for this fork is that the way Inkwell is designed, you have to use
|
||||
# a particular branch (e.g. "llvm8-0") in Cargo.toml. That would be fine, except that
|
||||
# breaking changes get pushed directly to that branch, which breaks our build
|
||||
# without warning.
|
||||
#
|
||||
# We tried referencing a specific rev on TheDan64/inkwell directly (instead of branch),
|
||||
# but although that worked locally, it did not work on GitHub Actions. (After a few
|
||||
# hours of investigation, gave up trying to figure out why.) So this is the workaround:
|
||||
# having an immutable tag on the rtfeldman/inkwell fork which points to
|
||||
# a particular "release" of Inkwell.
|
||||
#
|
||||
# When we want to update Inkwell, we can sync up rtfeldman/inkwell to the latest
|
||||
# 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 = "llvm10-0.release4", features = [ "llvm10-0" ] }
|
||||
inkwell = { path = "../../vendor/inkwell" }
|
||||
target-lexicon = "0.10"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -100,20 +100,22 @@ pub fn gen_from_mono_module(
|
|||
|
||||
let kind_id = Attribute::get_named_enum_kind_id("alwaysinline");
|
||||
debug_assert!(kind_id > 0);
|
||||
let attr = context.create_enum_attribute(kind_id, 1);
|
||||
let enum_attr = context.create_enum_attribute(kind_id, 1);
|
||||
|
||||
for function in FunctionIterator::from_module(module) {
|
||||
let name = function.get_name().to_str().unwrap();
|
||||
|
||||
// mark our zig-defined builtins as internal
|
||||
if name.starts_with("roc_builtins") {
|
||||
function.set_linkage(Linkage::Internal);
|
||||
}
|
||||
|
||||
if name.starts_with("roc_builtins.dict") || name.starts_with("dict.RocDict") {
|
||||
function.add_attribute(AttributeLoc::Function, attr);
|
||||
}
|
||||
|
||||
if name.starts_with("roc_builtins.list") || name.starts_with("list.RocList") {
|
||||
function.add_attribute(AttributeLoc::Function, attr);
|
||||
if name.starts_with("roc_builtins.dict")
|
||||
|| name.starts_with("dict.RocDict")
|
||||
|| name.starts_with("roc_builtins.list")
|
||||
|| name.starts_with("list.RocList")
|
||||
{
|
||||
function.add_attribute(AttributeLoc::Function, enum_attr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
5
compiler/builtins/bitcode/build.sh
Executable file
5
compiler/builtins/bitcode/build.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
zig build-obj src/main.zig -O ReleaseFast -femit-llvm-ir=builtins.ll -femit-bin=builtins.o --strip
|
|
@ -10,15 +10,29 @@ use std::str;
|
|||
fn main() {
|
||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||
|
||||
let big_sur_path = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib";
|
||||
let use_build_script = Path::new(big_sur_path).exists();
|
||||
|
||||
// "." is relative to where "build.rs" is
|
||||
let build_script_dir_path = fs::canonicalize(Path::new(".")).unwrap();
|
||||
let bitcode_path = build_script_dir_path.join("bitcode");
|
||||
|
||||
let src_obj_path = bitcode_path.join("builtins.o");
|
||||
let src_obj = src_obj_path.to_str().expect("Invalid src object path");
|
||||
println!("Compiling zig object to: {}", src_obj);
|
||||
|
||||
run_command(&bitcode_path, "zig", &["build", "object", "-Drelease=true"]);
|
||||
let dest_ir_path = bitcode_path.join("builtins.ll");
|
||||
let dest_ir = dest_ir_path.to_str().expect("Invalid dest ir path");
|
||||
|
||||
if use_build_script {
|
||||
println!("Compiling zig object & ir to: {} and {}", src_obj, dest_ir);
|
||||
run_command_with_no_args(&bitcode_path, "./build.sh");
|
||||
} else {
|
||||
println!("Compiling zig object to: {}", src_obj);
|
||||
run_command(&bitcode_path, "zig", &["build", "object", "-Drelease=true"]);
|
||||
|
||||
println!("Compiling ir to: {}", dest_ir);
|
||||
run_command(&bitcode_path, "zig", &["build", "ir", "-Drelease=true"]);
|
||||
}
|
||||
|
||||
let dest_obj_path = Path::new(&out_dir).join("builtins.o");
|
||||
let dest_obj = dest_obj_path.to_str().expect("Invalid dest object path");
|
||||
|
@ -26,12 +40,6 @@ fn main() {
|
|||
|
||||
run_command(&bitcode_path, "mv", &[src_obj, dest_obj]);
|
||||
|
||||
let dest_ir_path = bitcode_path.join("builtins.ll");
|
||||
let dest_ir = dest_ir_path.to_str().expect("Invalid dest ir path");
|
||||
println!("Compiling ir to: {}", dest_ir);
|
||||
|
||||
run_command(&bitcode_path, "zig", &["build", "ir", "-Drelease=true"]);
|
||||
|
||||
let dest_bc_path = bitcode_path.join("builtins.bc");
|
||||
let dest_bc = dest_bc_path.to_str().expect("Invalid dest bc path");
|
||||
println!("Compiling bitcode to: {}", dest_bc);
|
||||
|
@ -78,6 +86,25 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn run_command_with_no_args<P: AsRef<Path>>(path: P, command_str: &str) {
|
||||
let output_result = Command::new(OsStr::new(&command_str))
|
||||
.current_dir(path)
|
||||
.output();
|
||||
match output_result {
|
||||
Ok(output) => match output.status.success() {
|
||||
true => (),
|
||||
false => {
|
||||
let error_str = match str::from_utf8(&output.stderr) {
|
||||
Ok(stderr) => stderr.to_string(),
|
||||
Err(_) => format!("Failed to run \"{}\"", command_str),
|
||||
};
|
||||
panic!("{} failed: {}", command_str, error_str);
|
||||
}
|
||||
},
|
||||
Err(reason) => panic!("{} failed: {}", command_str, reason),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_zig_files(dir: &Path, cb: &dyn Fn(&Path)) -> io::Result<()> {
|
||||
if dir.is_dir() {
|
||||
for entry in fs::read_dir(dir)? {
|
||||
|
|
|
@ -20,24 +20,7 @@ im-rc = "14" # im and im-rc should always have the same version!
|
|||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
inlinable_string = "0.1"
|
||||
either = "1.6.1"
|
||||
# NOTE: rtfeldman/inkwell is a fork of TheDan64/inkwell which does not change anything.
|
||||
#
|
||||
# The reason for this fork is that the way Inkwell is designed, you have to use
|
||||
# a particular branch (e.g. "llvm8-0") in Cargo.toml. That would be fine, except that
|
||||
# breaking changes get pushed directly to that branch, which breaks our build
|
||||
# without warning.
|
||||
#
|
||||
# We tried referencing a specific rev on TheDan64/inkwell directly (instead of branch),
|
||||
# but although that worked locally, it did not work on GitHub Actions. (After a few
|
||||
# hours of investigation, gave up trying to figure out why.) So this is the workaround:
|
||||
# having an immutable tag on the rtfeldman/inkwell fork which points to
|
||||
# a particular "release" of Inkwell.
|
||||
#
|
||||
# When we want to update Inkwell, we can sync up rtfeldman/inkwell to the latest
|
||||
# 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 = "llvm10-0.release4", features = [ "llvm10-0" ] }
|
||||
inkwell = { path = "../../vendor/inkwell" }
|
||||
target-lexicon = "0.10"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -5791,7 +5791,7 @@ fn get_gxx_personality_v0<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> Function
|
|||
None => {
|
||||
let personality_func = add_func(
|
||||
module,
|
||||
"__gxx_personality_v0",
|
||||
name,
|
||||
context.i64_type().fn_type(&[], false),
|
||||
Linkage::External,
|
||||
C_CALL_CONV,
|
||||
|
@ -5843,7 +5843,7 @@ fn cxa_begin_catch<'a, 'ctx, 'env>(
|
|||
|
||||
let cxa_begin_catch = add_func(
|
||||
module,
|
||||
"__cxa_begin_catch",
|
||||
name,
|
||||
u8_ptr.fn_type(&[u8_ptr.into()], false),
|
||||
Linkage::External,
|
||||
C_CALL_CONV,
|
||||
|
|
|
@ -5928,35 +5928,48 @@ fn reuse_function_symbol<'a>(
|
|||
) -> Stmt<'a> {
|
||||
match procs.partial_procs.get(&original) {
|
||||
None => {
|
||||
let is_imported = env.is_imported_symbol(original);
|
||||
|
||||
match arg_var {
|
||||
Some(arg_var) if is_imported => {
|
||||
Some(arg_var) if env.is_imported_symbol(original) => {
|
||||
let layout = layout_cache
|
||||
.from_var(env.arena, arg_var, env.subs)
|
||||
.expect("creating layout does not fail");
|
||||
|
||||
let top_level = TopLevelFunctionLayout::from_layout(env.arena, layout);
|
||||
if procs.imported_module_thunks.contains(&original) {
|
||||
let top_level = TopLevelFunctionLayout::new(env.arena, &[], layout);
|
||||
procs.insert_passed_by_name(
|
||||
env,
|
||||
arg_var,
|
||||
original,
|
||||
top_level,
|
||||
layout_cache,
|
||||
);
|
||||
|
||||
procs.insert_passed_by_name(env, arg_var, original, top_level, layout_cache);
|
||||
force_thunk(env, original, layout, symbol, env.arena.alloc(result))
|
||||
} else {
|
||||
let top_level = TopLevelFunctionLayout::from_layout(env.arena, layout);
|
||||
procs.insert_passed_by_name(
|
||||
env,
|
||||
arg_var,
|
||||
original,
|
||||
top_level,
|
||||
layout_cache,
|
||||
);
|
||||
|
||||
// an imported symbol is either a function, or a top-level 0-argument thunk
|
||||
// it never has closure data, so we use the empty struct
|
||||
return let_empty_struct(symbol, env.arena.alloc(result));
|
||||
let_empty_struct(symbol, env.arena.alloc(result))
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
// danger: a foreign symbol may not be specialized!
|
||||
debug_assert!(
|
||||
!is_imported,
|
||||
!env.is_imported_symbol(original),
|
||||
"symbol {:?} while processing module {:?}",
|
||||
original,
|
||||
(env.home, &arg_var),
|
||||
);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
Some(partial_proc) => {
|
||||
|
|
|
@ -276,7 +276,8 @@ impl<'a> LambdaSet<'a> {
|
|||
|
||||
use UnionVariant::*;
|
||||
match variant {
|
||||
Never | Unit | UnitWithArguments => Layout::Struct(&[]),
|
||||
Never => Layout::Union(UnionLayout::NonRecursive(&[])),
|
||||
Unit | UnitWithArguments => Layout::Struct(&[]),
|
||||
BoolUnion { .. } => Layout::Builtin(Builtin::Int1),
|
||||
ByteUnion(_) => Layout::Builtin(Builtin::Int8),
|
||||
Unwrapped(_tag_name, layouts) => Layout::Struct(layouts.into_bump_slice()),
|
||||
|
|
|
@ -270,11 +270,12 @@ mod test_mono {
|
|||
indoc!(
|
||||
r#"
|
||||
procedure Test.0 ():
|
||||
let Test.11 = 1i64;
|
||||
let Test.9 = 1i64;
|
||||
let Test.10 = 2i64;
|
||||
let Test.5 = These Test.11 Test.9 Test.10;
|
||||
switch Test.5:
|
||||
let Test.12 = 1i64;
|
||||
let Test.10 = 1i64;
|
||||
let Test.11 = 2i64;
|
||||
let Test.5 = These Test.12 Test.10 Test.11;
|
||||
let Test.9 = Index 0 Test.5;
|
||||
switch Test.9:
|
||||
case 2:
|
||||
let Test.2 = Index 1 Test.5;
|
||||
ret Test.2;
|
||||
|
|
|
@ -30,24 +30,7 @@ inlinable_string = "0.1"
|
|||
either = "1.6.1"
|
||||
indoc = "0.3.3"
|
||||
libc = "0.2"
|
||||
# NOTE: rtfeldman/inkwell is a fork of TheDan64/inkwell which does not change anything.
|
||||
#
|
||||
# The reason for this fork is that the way Inkwell is designed, you have to use
|
||||
# a particular branch (e.g. "llvm8-0") in Cargo.toml. That would be fine, except that
|
||||
# breaking changes get pushed directly to that branch, which breaks our build
|
||||
# without warning.
|
||||
#
|
||||
# We tried referencing a specific rev on TheDan64/inkwell directly (instead of branch),
|
||||
# but although that worked locally, it did not work on GitHub Actions. (After a few
|
||||
# hours of investigation, gave up trying to figure out why.) So this is the workaround:
|
||||
# having an immutable tag on the rtfeldman/inkwell fork which points to
|
||||
# a particular "release" of Inkwell.
|
||||
#
|
||||
# When we want to update Inkwell, we can sync up rtfeldman/inkwell to the latest
|
||||
# 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 = "llvm10-0.release4", features = [ "llvm10-0" ] }
|
||||
inkwell = { path = "../../vendor/inkwell" }
|
||||
target-lexicon = "0.10"
|
||||
libloading = "0.6"
|
||||
|
||||
|
|
40
compiler/test_mono/Cargo.toml
Normal file
40
compiler/test_mono/Cargo.toml
Normal file
|
@ -0,0 +1,40 @@
|
|||
[package]
|
||||
name = "test_mono"
|
||||
version = "0.1.0"
|
||||
authors = ["The Roc Contributors"]
|
||||
license = "UPL-1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
roc_collections = { path = "../collections" }
|
||||
roc_region = { path = "../region" }
|
||||
roc_module = { path = "../module" }
|
||||
roc_problem = { path = "../problem" }
|
||||
roc_types = { path = "../types" }
|
||||
roc_builtins = { path = "../builtins" }
|
||||
roc_constrain = { path = "../constrain" }
|
||||
roc_unify = { path = "../unify" }
|
||||
roc_solve = { path = "../solve" }
|
||||
roc_reporting = { path = "../reporting" }
|
||||
roc_load = { path = "../load" }
|
||||
roc_can = { path = "../can" }
|
||||
roc_parse = { path = "../parse" }
|
||||
roc_build = { path = "../build" }
|
||||
roc_mono = { path = "../mono" }
|
||||
test_mono_macros = { path = "../test_mono_macros" }
|
||||
im = "14" # im and im-rc should always have the same version!
|
||||
im-rc = "14" # im and im-rc should always have the same version!
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
inlinable_string = "0.1"
|
||||
either = "1.6.1"
|
||||
indoc = "0.3.3"
|
||||
libc = "0.2"
|
||||
target-lexicon = "0.10"
|
||||
libloading = "0.6"
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = "0.5.1"
|
||||
indoc = "0.3.3"
|
||||
quickcheck = "0.8"
|
||||
quickcheck_macros = "0.8"
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
25
compiler/test_mono/generated/ir_int_add.txt
Normal file
25
compiler/test_mono/generated/ir_int_add.txt
Normal file
|
@ -0,0 +1,25 @@
|
|||
procedure List.7 (#Attr.2):
|
||||
let Test.6 = lowlevel ListLen #Attr.2;
|
||||
ret Test.6;
|
||||
|
||||
procedure Num.24 (#Attr.2, #Attr.3):
|
||||
let Test.5 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Test.5;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.11 = 1i64;
|
||||
let Test.12 = 2i64;
|
||||
let Test.1 = Array [Test.11, Test.12];
|
||||
let Test.9 = 5i64;
|
||||
let Test.10 = 4i64;
|
||||
invoke Test.7 = CallByName Num.24 Test.9 Test.10 catch
|
||||
dec Test.1;
|
||||
unreachable;
|
||||
let Test.8 = 3i64;
|
||||
invoke Test.3 = CallByName Num.24 Test.7 Test.8 catch
|
||||
dec Test.1;
|
||||
unreachable;
|
||||
let Test.4 = CallByName List.7 Test.1;
|
||||
dec Test.1;
|
||||
let Test.2 = CallByName Num.24 Test.3 Test.4;
|
||||
ret Test.2;
|
3
compiler/test_mono/generated/ir_int_literal.txt
Normal file
3
compiler/test_mono/generated/ir_int_literal.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
procedure Test.0 ():
|
||||
let Test.1 = 5i64;
|
||||
ret Test.1;
|
184
compiler/test_mono/src/lib.rs
Normal file
184
compiler/test_mono/src/lib.rs
Normal file
|
@ -0,0 +1,184 @@
|
|||
#![cfg(test)]
|
||||
#![warn(clippy::dbg_macro)]
|
||||
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
|
||||
#![allow(clippy::large_enum_variant)]
|
||||
// we actually want to compare against the literal float bits
|
||||
#![allow(clippy::clippy::float_cmp)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate pretty_assertions;
|
||||
|
||||
use test_mono_macros::*;
|
||||
|
||||
use roc_can::builtins::builtin_defs_map;
|
||||
use roc_collections::all::MutMap;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::ir::Proc;
|
||||
|
||||
use roc_mono::ir::TopLevelFunctionLayout;
|
||||
|
||||
fn promote_expr_to_module(src: &str) -> String {
|
||||
let mut buffer = String::from("app \"test\" provides [ main ] to \"./platform\"\n\nmain =\n");
|
||||
|
||||
for line in src.lines() {
|
||||
// indent the body!
|
||||
buffer.push_str(" ");
|
||||
buffer.push_str(line);
|
||||
buffer.push('\n');
|
||||
}
|
||||
|
||||
buffer
|
||||
}
|
||||
|
||||
fn compiles_to_ir(test_name: &str, src: &str) {
|
||||
use bumpalo::Bump;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
let arena = &Bump::new();
|
||||
|
||||
// let stdlib = roc_builtins::unique::uniq_stdlib();
|
||||
let stdlib = roc_builtins::std::standard_stdlib();
|
||||
let filename = PathBuf::from("Test.roc");
|
||||
let src_dir = Path::new("fake/test/path");
|
||||
|
||||
let module_src;
|
||||
let temp;
|
||||
if src.starts_with("app") {
|
||||
// this is already a module
|
||||
module_src = src;
|
||||
} else {
|
||||
// this is an expression, promote it to a module
|
||||
temp = promote_expr_to_module(src);
|
||||
module_src = &temp;
|
||||
}
|
||||
|
||||
let exposed_types = MutMap::default();
|
||||
|
||||
let loaded = roc_load::file::load_and_monomorphize_from_str(
|
||||
arena,
|
||||
filename,
|
||||
&module_src,
|
||||
&stdlib,
|
||||
src_dir,
|
||||
exposed_types,
|
||||
8,
|
||||
builtin_defs_map,
|
||||
);
|
||||
|
||||
let mut loaded = match loaded {
|
||||
Ok(x) => x,
|
||||
Err(roc_load::file::LoadingProblem::FormattedReport(report)) => {
|
||||
println!("{}", report);
|
||||
panic!();
|
||||
}
|
||||
Err(e) => panic!("{:?}", e),
|
||||
};
|
||||
|
||||
use roc_load::file::MonomorphizedModule;
|
||||
let MonomorphizedModule {
|
||||
module_id: home,
|
||||
procedures,
|
||||
exposed_to_host,
|
||||
..
|
||||
} = loaded;
|
||||
|
||||
let can_problems = loaded.can_problems.remove(&home).unwrap_or_default();
|
||||
let type_problems = loaded.type_problems.remove(&home).unwrap_or_default();
|
||||
let mono_problems = loaded.mono_problems.remove(&home).unwrap_or_default();
|
||||
|
||||
if !can_problems.is_empty() {
|
||||
println!("Ignoring {} canonicalization problems", can_problems.len());
|
||||
}
|
||||
|
||||
assert_eq!(type_problems, Vec::new());
|
||||
assert_eq!(mono_problems, Vec::new());
|
||||
|
||||
debug_assert_eq!(exposed_to_host.len(), 1);
|
||||
|
||||
let main_fn_symbol = exposed_to_host.keys().copied().next().unwrap();
|
||||
|
||||
verify_procedures(test_name, procedures, main_fn_symbol);
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
fn verify_procedures(
|
||||
test_name: &str,
|
||||
procedures: MutMap<(Symbol, TopLevelFunctionLayout<'_>), Proc<'_>>,
|
||||
main_fn_symbol: Symbol,
|
||||
) {
|
||||
let index = procedures
|
||||
.keys()
|
||||
.position(|(s, _)| *s == main_fn_symbol)
|
||||
.unwrap();
|
||||
|
||||
let mut procs_string = procedures
|
||||
.values()
|
||||
.map(|proc| proc.to_pretty(200))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let main_fn = procs_string.swap_remove(index);
|
||||
|
||||
procs_string.sort();
|
||||
procs_string.push(main_fn);
|
||||
|
||||
let result = procs_string.join("\n");
|
||||
|
||||
let path = format!("generated/{}.txt", test_name);
|
||||
std::fs::create_dir_all("generated").unwrap();
|
||||
std::fs::write(&path, result).unwrap();
|
||||
|
||||
use std::process::Command;
|
||||
let is_tracked = Command::new("git")
|
||||
.args(&["ls-files", "--error-unmatch", &path])
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
if !is_tracked.status.success() {
|
||||
panic!(
|
||||
"The file {:?} is not tracked by git. Try using `git add` on it",
|
||||
&path
|
||||
);
|
||||
}
|
||||
|
||||
let has_changes = Command::new("git")
|
||||
.args(&["diff", "--color=always", &path])
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
if !has_changes.status.success() {
|
||||
eprintln!("`git diff {:?}` failed", &path);
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
if !has_changes.stdout.is_empty() {
|
||||
println!("{}", std::str::from_utf8(&has_changes.stdout).unwrap());
|
||||
panic!("Output changed: resolve conflicts and `git add` the file.");
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE because the Show instance of module names is different in --release mode,
|
||||
// these tests would all fail. In the future, when we do interesting optimizations,
|
||||
// we'll likely want some tests for --release too.
|
||||
#[cfg(not(debug_assertions))]
|
||||
fn verify_procedures(
|
||||
_expected: &str,
|
||||
_procedures: MutMap<(Symbol, TopLevelFunctionLayout<'_>), Proc<'_>>,
|
||||
_main_fn_symbol: Symbol,
|
||||
) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
#[mono_test]
|
||||
fn ir_int_literal() {
|
||||
r#"
|
||||
5
|
||||
"#
|
||||
}
|
||||
|
||||
#[mono_test]
|
||||
fn ir_int_add() {
|
||||
r#"
|
||||
x = [ 1,2 ]
|
||||
5 + 4 + 3 + List.len x
|
||||
"#
|
||||
}
|
15
compiler/test_mono_macros/Cargo.toml
Normal file
15
compiler/test_mono_macros/Cargo.toml
Normal file
|
@ -0,0 +1,15 @@
|
|||
[package]
|
||||
name = "test_mono_macros"
|
||||
version = "0.1.0"
|
||||
authors = ["The Roc Contributors"]
|
||||
license = "UPL-1.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
syn = { version = "1.0.39", features = ["full", "extra-traits"] }
|
||||
quote = "1.0.7"
|
||||
darling = "0.10.2"
|
||||
proc-macro2 = "1.0.24"
|
26
compiler/test_mono_macros/src/lib.rs
Normal file
26
compiler/test_mono_macros/src/lib.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
extern crate proc_macro;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn mono_test(_args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let task_fn = syn::parse_macro_input!(item as syn::ItemFn);
|
||||
|
||||
let args = task_fn.sig.inputs.clone();
|
||||
|
||||
let name = task_fn.sig.ident.clone();
|
||||
let name_str = name.to_string();
|
||||
let body = task_fn.block.clone();
|
||||
|
||||
let visibility = &task_fn.vis;
|
||||
|
||||
let result = quote! {
|
||||
#[test]
|
||||
#visibility fn #name(#args) -> () {
|
||||
compiles_to_ir(#name_str, #body);
|
||||
|
||||
}
|
||||
};
|
||||
result.into()
|
||||
}
|
|
@ -119,10 +119,10 @@ pub enum Expr2 {
|
|||
elems: PoolVec<Expr2>, // 8B
|
||||
},
|
||||
If {
|
||||
cond_var: Variable, // 4B
|
||||
expr_var: Variable, // 4B
|
||||
branches: PoolVec<(Expr2, Expr2)>, // 8B
|
||||
final_else: NodeId<Expr2>, // 4B
|
||||
cond_var: Variable, // 4B
|
||||
expr_var: Variable, // 4B
|
||||
branches: PoolVec<(NodeId<Expr2>, NodeId<Expr2>)>, // 8B
|
||||
final_else: NodeId<Expr2>, // 4B
|
||||
},
|
||||
When {
|
||||
cond_var: Variable, // 4B
|
||||
|
|
|
@ -13,7 +13,7 @@ use roc_module::{ident::TagName, symbol::Symbol};
|
|||
use roc_region::all::{Located, Region};
|
||||
use roc_types::{
|
||||
subs::Variable,
|
||||
types,
|
||||
types::{self, AnnotationSource},
|
||||
types::{Category, Reason},
|
||||
};
|
||||
|
||||
|
@ -479,6 +479,157 @@ pub fn constrain_expr<'a>(
|
|||
|
||||
exists(arena, flex_vars, And(and_constraints))
|
||||
}
|
||||
Expr2::If {
|
||||
cond_var,
|
||||
expr_var,
|
||||
branches,
|
||||
final_else,
|
||||
} => {
|
||||
let expect_bool = |region| {
|
||||
let bool_type = Type2::Variable(Variable::BOOL);
|
||||
Expected::ForReason(Reason::IfCondition, bool_type, region)
|
||||
};
|
||||
|
||||
let mut branch_cons = BumpVec::with_capacity_in(2 * branches.len() + 3, arena);
|
||||
|
||||
// TODO why does this cond var exist? is it for error messages?
|
||||
// let first_cond_region = branches[0].0.region;
|
||||
let cond_var_is_bool_con = Eq(
|
||||
Type2::Variable(*cond_var),
|
||||
expect_bool(region),
|
||||
Category::If,
|
||||
region,
|
||||
);
|
||||
|
||||
branch_cons.push(cond_var_is_bool_con);
|
||||
|
||||
let final_else_expr = env.pool.get(*final_else);
|
||||
|
||||
let mut flex_vars = BumpVec::with_capacity_in(2, arena);
|
||||
|
||||
flex_vars.push(*cond_var);
|
||||
flex_vars.push(*expr_var);
|
||||
|
||||
match expected {
|
||||
Expected::FromAnnotation(name, arity, _, tipe) => {
|
||||
let num_branches = branches.len() + 1;
|
||||
|
||||
for (index, branch_id) in branches.iter_node_ids().enumerate() {
|
||||
let (cond_id, body_id) = env.pool.get(branch_id);
|
||||
|
||||
let cond = env.pool.get(*cond_id);
|
||||
let body = env.pool.get(*body_id);
|
||||
|
||||
let cond_con =
|
||||
constrain_expr(arena, env, cond, expect_bool(region), region);
|
||||
|
||||
let then_con = constrain_expr(
|
||||
arena,
|
||||
env,
|
||||
body,
|
||||
Expected::FromAnnotation(
|
||||
name.clone(),
|
||||
arity,
|
||||
AnnotationSource::TypedIfBranch {
|
||||
index: Index::zero_based(index),
|
||||
num_branches,
|
||||
},
|
||||
tipe.shallow_clone(),
|
||||
),
|
||||
region,
|
||||
);
|
||||
|
||||
branch_cons.push(cond_con);
|
||||
branch_cons.push(then_con);
|
||||
}
|
||||
|
||||
let else_con = constrain_expr(
|
||||
arena,
|
||||
env,
|
||||
final_else_expr,
|
||||
Expected::FromAnnotation(
|
||||
name,
|
||||
arity,
|
||||
AnnotationSource::TypedIfBranch {
|
||||
index: Index::zero_based(branches.len()),
|
||||
num_branches,
|
||||
},
|
||||
tipe.shallow_clone(),
|
||||
),
|
||||
region,
|
||||
);
|
||||
|
||||
let ast_con = Eq(
|
||||
Type2::Variable(*expr_var),
|
||||
Expected::NoExpectation(tipe),
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
region,
|
||||
);
|
||||
|
||||
branch_cons.push(ast_con);
|
||||
branch_cons.push(else_con);
|
||||
|
||||
exists(arena, flex_vars, And(branch_cons))
|
||||
}
|
||||
_ => {
|
||||
for (index, branch_id) in branches.iter_node_ids().enumerate() {
|
||||
let (cond_id, body_id) = env.pool.get(branch_id);
|
||||
|
||||
let cond = env.pool.get(*cond_id);
|
||||
let body = env.pool.get(*body_id);
|
||||
|
||||
let cond_con =
|
||||
constrain_expr(arena, env, cond, expect_bool(region), region);
|
||||
|
||||
let then_con = constrain_expr(
|
||||
arena,
|
||||
env,
|
||||
body,
|
||||
Expected::ForReason(
|
||||
Reason::IfBranch {
|
||||
index: Index::zero_based(index),
|
||||
total_branches: branches.len(),
|
||||
},
|
||||
Type2::Variable(*expr_var),
|
||||
// should be from body
|
||||
region,
|
||||
),
|
||||
region,
|
||||
);
|
||||
|
||||
branch_cons.push(cond_con);
|
||||
branch_cons.push(then_con);
|
||||
}
|
||||
|
||||
let else_con = constrain_expr(
|
||||
arena,
|
||||
env,
|
||||
final_else_expr,
|
||||
Expected::ForReason(
|
||||
Reason::IfBranch {
|
||||
index: Index::zero_based(branches.len()),
|
||||
total_branches: branches.len() + 1,
|
||||
},
|
||||
Type2::Variable(*expr_var),
|
||||
// should come from final_else
|
||||
region,
|
||||
),
|
||||
region,
|
||||
);
|
||||
|
||||
branch_cons.push(Eq(
|
||||
Type2::Variable(*expr_var),
|
||||
expected,
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
region,
|
||||
));
|
||||
|
||||
branch_cons.push(else_con);
|
||||
|
||||
exists(arena, flex_vars, And(branch_cons))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => todo!("implement constaints for {:?}", expr),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -516,7 +516,7 @@ pub fn to_expr2<'a>(
|
|||
output.references.union_mut(cond_output.references);
|
||||
output.references.union_mut(then_output.references);
|
||||
|
||||
new_branches.push((cond, then_expr));
|
||||
new_branches.push((env.pool.add(cond), env.pool.add(then_expr)));
|
||||
}
|
||||
|
||||
let (else_expr, else_output) =
|
||||
|
|
|
@ -274,3 +274,15 @@ fn constrain_access() {
|
|||
"Str",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn constrain_if() {
|
||||
infer_eq(
|
||||
indoc!(
|
||||
r#"
|
||||
if True then Green else Red
|
||||
"#
|
||||
),
|
||||
"[ Green, Red ]*",
|
||||
)
|
||||
}
|
||||
|
|
1
examples/balance/.gitignore
vendored
1
examples/balance/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
main
|
|
@ -1,7 +0,0 @@
|
|||
app "main" imports [ Effect ] provides [ rocMain ] to "./platform"
|
||||
|
||||
|
||||
rocMain : Effect.Effect {} as Fx
|
||||
rocMain =
|
||||
when List.len (Str.split "hello" "JJJJ there") is
|
||||
_ -> Effect.putLine "Yay"
|
23
examples/balance/platform/Cargo.lock
generated
23
examples/balance/platform/Cargo.lock
generated
|
@ -1,23 +0,0 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "host"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"roc_std 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "roc_std"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libc 0.2.79 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum libc 0.2.79 (registry+https://github.com/rust-lang/crates.io-index)" = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743"
|
|
@ -1,14 +0,0 @@
|
|||
[package]
|
||||
name = "host"
|
||||
version = "0.1.0"
|
||||
authors = ["The Roc Contributors"]
|
||||
license = "UPL-1.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
roc_std = { path = "../../../roc_std" }
|
||||
|
||||
[workspace]
|
|
@ -1,15 +0,0 @@
|
|||
platform folkertdev/foo
|
||||
requires { rocMain : Effect {} }
|
||||
exposes []
|
||||
packages {}
|
||||
imports []
|
||||
provides [ mainForHost ]
|
||||
effects Effect
|
||||
{
|
||||
putChar : Int -> Effect {},
|
||||
putLine : Str -> Effect {},
|
||||
getLine : Effect Str
|
||||
}
|
||||
|
||||
mainForHost : Effect {} as Fx
|
||||
mainForHost = rocMain
|
|
@ -1,7 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
extern int rust_main();
|
||||
|
||||
int main() {
|
||||
return rust_main();
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
#![allow(non_snake_case)]
|
||||
|
||||
use roc_std::alloca;
|
||||
use roc_std::RocCallResult;
|
||||
use roc_std::RocStr;
|
||||
use std::alloc::Layout;
|
||||
use std::ffi::c_void;
|
||||
use std::time::SystemTime;
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "roc__rocMain_1_exposed"]
|
||||
fn roc_main(output: *mut u8) -> ();
|
||||
|
||||
#[link_name = "roc__rocMain_1_size"]
|
||||
fn roc_main_size() -> i64;
|
||||
|
||||
#[link_name = "roc__rocMain_1_Fx_caller"]
|
||||
fn call_Fx(function_pointer: *const u8, closure_data: *const u8, output: *mut u8) -> ();
|
||||
|
||||
#[link_name = "roc__rocMain_1_Fx_size"]
|
||||
fn size_Fx() -> i64;
|
||||
|
||||
fn malloc(size: usize) -> *mut c_void;
|
||||
fn realloc(c_ptr: *mut c_void, size: usize) -> *mut c_void;
|
||||
fn free(c_ptr: *mut c_void);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn roc_realloc(
|
||||
c_ptr: *mut c_void,
|
||||
new_size: usize,
|
||||
_old_size: usize,
|
||||
_alignment: u32,
|
||||
) -> *mut c_void {
|
||||
return realloc(c_ptr, new_size);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn roc_dealloc(c_ptr: *mut c_void, _alignment: u32) {
|
||||
return free(c_ptr);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn roc_fx_putChar(foo: i64) -> () {
|
||||
let character = foo as u8 as char;
|
||||
print!("{}", character);
|
||||
|
||||
()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn roc_fx_putLine(line: RocStr) -> () {
|
||||
let bytes = line.as_slice();
|
||||
let string = unsafe { std::str::from_utf8_unchecked(bytes) };
|
||||
println!("{}", string);
|
||||
|
||||
()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn roc_fx_getLine() -> RocStr {
|
||||
use std::io::{self, BufRead};
|
||||
|
||||
let stdin = io::stdin();
|
||||
let line1 = stdin.lock().lines().next().unwrap().unwrap();
|
||||
|
||||
RocStr::from_slice_with_capacity(line1.as_bytes(), line1.len())
|
||||
}
|
||||
|
||||
unsafe fn call_the_closure(function_pointer: *const u8, closure_data_ptr: *const u8) -> i64 {
|
||||
let size = size_Fx() as usize;
|
||||
|
||||
alloca::with_stack_bytes(size, |buffer| {
|
||||
let buffer: *mut std::ffi::c_void = buffer;
|
||||
let buffer: *mut u8 = buffer as *mut u8;
|
||||
|
||||
call_Fx(
|
||||
function_pointer,
|
||||
closure_data_ptr as *const u8,
|
||||
buffer as *mut u8,
|
||||
);
|
||||
|
||||
let output = &*(buffer as *mut RocCallResult<i64>);
|
||||
|
||||
match output.into() {
|
||||
Ok(_) => 0,
|
||||
Err(e) => panic!("failed with {}", e),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn rust_main() -> isize {
|
||||
println!("Running Roc closure");
|
||||
let start_time = SystemTime::now();
|
||||
|
||||
let size = unsafe { roc_main_size() } as usize;
|
||||
let layout = Layout::array::<u8>(size).unwrap();
|
||||
let answer = unsafe {
|
||||
let buffer = std::alloc::alloc(layout);
|
||||
|
||||
roc_main(buffer);
|
||||
|
||||
let output = &*(buffer as *mut RocCallResult<()>);
|
||||
|
||||
match output.into() {
|
||||
Ok(()) => {
|
||||
let function_pointer = {
|
||||
// this is a pointer to the location where the function pointer is stored
|
||||
// we pass just the function pointer
|
||||
let temp = buffer.offset(8) as *const i64;
|
||||
|
||||
(*temp) as *const u8
|
||||
};
|
||||
|
||||
let closure_data_ptr = buffer.offset(16);
|
||||
|
||||
let result =
|
||||
call_the_closure(function_pointer as *const u8, closure_data_ptr as *const u8);
|
||||
|
||||
std::alloc::dealloc(buffer, layout);
|
||||
|
||||
result
|
||||
}
|
||||
Err(msg) => {
|
||||
std::alloc::dealloc(buffer, layout);
|
||||
|
||||
panic!("Roc failed with message: {}", msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
let end_time = SystemTime::now();
|
||||
let duration = end_time.duration_since(start_time).unwrap();
|
||||
|
||||
println!(
|
||||
"Roc execution took {:.4} ms",
|
||||
duration.as_secs_f64() * 1000.0,
|
||||
);
|
||||
|
||||
// Exit code
|
||||
0
|
||||
}
|
198
shell.nix
198
shell.nix
|
@ -1,116 +1,116 @@
|
|||
{ }:
|
||||
{}:
|
||||
|
||||
let
|
||||
splitSystem = builtins.split "-" builtins.currentSystem;
|
||||
currentArch = builtins.elemAt splitSystem 0;
|
||||
currentOS = builtins.elemAt splitSystem 2;
|
||||
in with {
|
||||
# Look here for information about how pin version of nixpkgs
|
||||
# → https://nixos.wiki/wiki/FAQ/Pinning_Nixpkgs
|
||||
pkgs = import (builtins.fetchGit {
|
||||
name = "nixpkgs-2021-04-23";
|
||||
url = "https://github.com/nixos/nixpkgs/";
|
||||
ref = "refs/heads/nixpkgs-unstable";
|
||||
rev = "8d0340aee5caac3807c58ad7fa4ebdbbdd9134d6";
|
||||
}) { };
|
||||
|
||||
isMacOS = currentOS == "darwin";
|
||||
isLinux = currentOS == "linux";
|
||||
isAarch64 = currentArch == "aarch64";
|
||||
};
|
||||
|
||||
with (pkgs);
|
||||
|
||||
let
|
||||
darwin-inputs =
|
||||
if isMacOS then
|
||||
with pkgs.darwin.apple_sdk.frameworks; [
|
||||
AppKit
|
||||
CoreFoundation
|
||||
CoreServices
|
||||
CoreVideo
|
||||
Foundation
|
||||
Metal
|
||||
Security
|
||||
]
|
||||
else
|
||||
[ ];
|
||||
|
||||
linux-inputs =
|
||||
if isLinux then
|
||||
[
|
||||
valgrind
|
||||
vulkan-headers
|
||||
vulkan-loader
|
||||
vulkan-tools
|
||||
vulkan-validation-layers
|
||||
xorg.libX11
|
||||
xorg.libXcursor
|
||||
xorg.libXrandr
|
||||
xorg.libXi
|
||||
xorg.libxcb
|
||||
]
|
||||
else
|
||||
[ ];
|
||||
|
||||
nixos-env =
|
||||
if isLinux && builtins.pathExists /etc/nixos/configuration.nix then
|
||||
{ XDG_DATA_DIRS = "/run/opengl-driver/share:$XDG_DATA_DIRS";
|
||||
in
|
||||
with {
|
||||
# Look here for information about how pin version of nixpkgs
|
||||
# → https://nixos.wiki/wiki/FAQ/Pinning_Nixpkgs
|
||||
pkgs = import (
|
||||
builtins.fetchGit {
|
||||
# name = "nixpkgs-2021-04-23";
|
||||
url = "https://github.com/nixos/nixpkgs/";
|
||||
ref = "refs/heads/nixpkgs-unstable";
|
||||
rev = "8d0340aee5caac3807c58ad7fa4ebdbbdd9134d6";
|
||||
}
|
||||
else
|
||||
{ };
|
||||
) {};
|
||||
|
||||
llvmPkgs = pkgs.llvmPackages_10;
|
||||
zig = import ./nix/zig.nix { inherit pkgs isMacOS isAarch64; };
|
||||
inputs = [
|
||||
# build libraries
|
||||
rustc
|
||||
cargo
|
||||
clippy
|
||||
rustfmt
|
||||
cmake
|
||||
git
|
||||
python3
|
||||
llvmPkgs.llvm
|
||||
llvmPkgs.clang
|
||||
pkg-config
|
||||
zig
|
||||
# lib deps
|
||||
llvmPkgs.libcxx
|
||||
llvmPkgs.libcxxabi
|
||||
libffi
|
||||
libunwind
|
||||
libxml2
|
||||
ncurses
|
||||
zlib
|
||||
libiconv
|
||||
# faster builds - see https://github.com/rtfeldman/roc/blob/trunk/BUILDING_FROM_SOURCE.md#use-lld-for-the-linker
|
||||
llvmPkgs.lld
|
||||
# dev tools
|
||||
# rust-analyzer
|
||||
# (import ./nix/zls.nix { inherit pkgs zig; })
|
||||
];
|
||||
isMacOS = currentOS == "darwin";
|
||||
isLinux = currentOS == "linux";
|
||||
isAarch64 = currentArch == "aarch64";
|
||||
};
|
||||
|
||||
in mkShell (nixos-env // {
|
||||
buildInputs = inputs ++ darwin-inputs ++ linux-inputs;
|
||||
with (pkgs);
|
||||
|
||||
# Additional Env vars
|
||||
LLVM_SYS_100_PREFIX = "${llvmPkgs.llvm}";
|
||||
LD_LIBRARY_PATH = stdenv.lib.makeLibraryPath
|
||||
([
|
||||
let
|
||||
darwin-inputs =
|
||||
if isMacOS then
|
||||
with pkgs.darwin.apple_sdk.frameworks; [
|
||||
AppKit
|
||||
CoreFoundation
|
||||
CoreServices
|
||||
CoreVideo
|
||||
Foundation
|
||||
Metal
|
||||
Security
|
||||
]
|
||||
else
|
||||
[];
|
||||
|
||||
linux-inputs =
|
||||
if isLinux then
|
||||
[
|
||||
valgrind
|
||||
vulkan-headers
|
||||
vulkan-loader
|
||||
vulkan-tools
|
||||
vulkan-validation-layers
|
||||
xorg.libX11
|
||||
xorg.libXcursor
|
||||
xorg.libXrandr
|
||||
xorg.libXi
|
||||
xorg.libxcb
|
||||
]
|
||||
else
|
||||
[];
|
||||
|
||||
llvmPkgs = pkgs.llvmPackages_10;
|
||||
zig = import ./nix/zig.nix { inherit pkgs isMacOS isAarch64; };
|
||||
inputs = [
|
||||
# build libraries
|
||||
rustc
|
||||
cargo
|
||||
clippy
|
||||
rustfmt
|
||||
cmake
|
||||
git
|
||||
python3
|
||||
llvmPkgs.llvm
|
||||
llvmPkgs.clang
|
||||
pkg-config
|
||||
stdenv.cc.cc.lib
|
||||
zig
|
||||
# lib deps
|
||||
llvmPkgs.libcxx
|
||||
llvmPkgs.libcxxabi
|
||||
libunwind
|
||||
libffi
|
||||
libunwind
|
||||
libxml2
|
||||
ncurses
|
||||
zlib
|
||||
] ++ linux-inputs);
|
||||
libiconv
|
||||
# faster builds - see https://github.com/rtfeldman/roc/blob/trunk/BUILDING_FROM_SOURCE.md#use-lld-for-the-linker
|
||||
llvmPkgs.lld
|
||||
# dev tools
|
||||
# rust-analyzer
|
||||
# (import ./nix/zls.nix { inherit pkgs zig; })
|
||||
];
|
||||
|
||||
# Aliases don't work cross shell, so we do this
|
||||
shellHook = ''
|
||||
export PATH="$PATH:$PWD/nix/bin"
|
||||
'';
|
||||
})
|
||||
in
|
||||
mkShell (
|
||||
{
|
||||
buildInputs = inputs ++ darwin-inputs ++ linux-inputs;
|
||||
|
||||
# Additional Env vars
|
||||
LLVM_SYS_100_PREFIX = "${llvmPkgs.llvm}";
|
||||
LD_LIBRARY_PATH = stdenv.lib.makeLibraryPath
|
||||
(
|
||||
[
|
||||
pkg-config
|
||||
stdenv.cc.cc.lib
|
||||
llvmPkgs.libcxx
|
||||
llvmPkgs.libcxxabi
|
||||
libunwind
|
||||
libffi
|
||||
ncurses
|
||||
zlib
|
||||
] ++ linux-inputs
|
||||
);
|
||||
|
||||
# Aliases don't work cross shell, so we do this
|
||||
shellHook = ''
|
||||
export PATH="$PATH:$PWD/nix/bin"
|
||||
'';
|
||||
}
|
||||
)
|
||||
|
|
31
vendor/inkwell/Cargo.toml
vendored
Normal file
31
vendor/inkwell/Cargo.toml
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
[package]
|
||||
name = "inkwell"
|
||||
version = "0.1.0"
|
||||
authors = ["The Roc Contributors"]
|
||||
license = "UPL-1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
# NOTE: rtfeldman/inkwell is a fork of TheDan64/inkwell which does not change anything.
|
||||
#
|
||||
# The reason for this fork is that the way Inkwell is designed, you have to use
|
||||
# a particular branch (e.g. "llvm8-0") in Cargo.toml. That would be fine, except that
|
||||
# breaking changes get pushed directly to that branch, which breaks our build
|
||||
# without warning.
|
||||
#
|
||||
# We tried referencing a specific rev on TheDan64/inkwell directly (instead of branch),
|
||||
# but although that worked locally, it did not work on GitHub Actions. (After a few
|
||||
# hours of investigation, gave up trying to figure out why.) So this is the workaround:
|
||||
# having an immutable tag on the rtfeldman/inkwell fork which points to
|
||||
# a particular "release" of Inkwell.
|
||||
#
|
||||
# When we want to update Inkwell, we can sync up rtfeldman/inkwell to the latest
|
||||
# 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 = "llvm10-0.release4", features = [ "llvm10-0" ] }
|
||||
|
||||
[features]
|
||||
target-arm = []
|
||||
target-aarch64 = []
|
||||
target-webassembly = []
|
4
vendor/inkwell/src/lib.rs
vendored
Normal file
4
vendor/inkwell/src/lib.rs
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
#![cfg(not(doctest))]
|
||||
// re-export all inkwell members. This way we can switch
|
||||
// inkwell versions by making changes in just one place.
|
||||
pub use inkwell::*;
|
Loading…
Add table
Add a link
Reference in a new issue