Merge branch 'trunk' into str_trim

This commit is contained in:
Dan Gieschen Knutson 2021-10-27 18:01:29 -05:00 committed by GitHub
commit 02117ba512
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 233 additions and 158 deletions

View file

@ -14,7 +14,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: install earthly - name: install earthly
run: /bin/sh -c 'wget https://github.com/earthly/earthly/releases/latest/download/earthly-linux-amd64 -O /usr/local/bin/earthly && chmod +x /usr/local/bin/earthly && /usr/local/bin/earthly bootstrap --with-autocomplete' run: "sudo /bin/sh -c 'wget https://github.com/earthly/earthly/releases/latest/download/earthly-linux-amd64 -O /usr/local/bin/earthly && chmod +x /usr/local/bin/earthly && /usr/local/bin/earthly bootstrap --with-autocomplete'"
- name: Earthly print version - name: Earthly print version
run: earthly --version run: earthly --version
- name: install dependencies, build, run tests, build release - name: install dependencies, build, run tests, build release

View file

@ -39,3 +39,5 @@ Chelsea Troy <chelsea.dommert@gmail.com>
Shritesh Bhattarai <shr@ite.sh> Shritesh Bhattarai <shr@ite.sh>
Kevin Sjöberg <mail@kevinsjoberg.com> Kevin Sjöberg <mail@kevinsjoberg.com>
Viktor Fröberg <vikfroberg@gmail.com> Viktor Fröberg <vikfroberg@gmail.com>
Locria Cyber <locriacyber@noreply.users.github.com>
Matthias Beyer <mail@beyermatthias.de>

60
Cargo.lock generated
View file

@ -457,14 +457,16 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "3.0.0-beta.1" version = "3.0.0-beta.1"
source = "git+https://github.com/rtfeldman/clap?branch=master#e1d83a78804a271b053d4d21f69b67f7eb01ad01" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "860643c53f980f0d38a5e25dfab6c3c93b2cb3aa1fe192643d17a293c6c41936"
dependencies = [ dependencies = [
"atty", "atty",
"bitflags", "bitflags",
"clap_derive", "clap_derive",
"indexmap", "indexmap",
"lazy_static", "lazy_static",
"strsim 0.9.3", "os_str_bytes",
"strsim 0.10.0",
"termcolor", "termcolor",
"textwrap", "textwrap",
"unicode-width", "unicode-width",
@ -473,11 +475,12 @@ dependencies = [
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "3.0.0-beta.1" version = "3.0.0-beta.5"
source = "git+https://github.com/rtfeldman/clap?branch=master#e1d83a78804a271b053d4d21f69b67f7eb01ad01" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b15c6b4f786ffb6192ffe65a36855bc1fc2444bcd0945ae16748dcd6ed7d0d3"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro-error 0.4.12", "proc-macro-error",
"proc-macro2 1.0.29", "proc-macro2 1.0.29",
"quote 1.0.9", "quote 1.0.9",
"syn 1.0.76", "syn 1.0.76",
@ -2711,6 +2714,12 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "os_str_bytes"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85"
[[package]] [[package]]
name = "output_vt100" name = "output_vt100"
version = "0.1.2" version = "0.1.2"
@ -3016,45 +3025,19 @@ dependencies = [
"toml", "toml",
] ]
[[package]]
name = "proc-macro-error"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7"
dependencies = [
"proc-macro-error-attr 0.4.12",
"proc-macro2 1.0.29",
"quote 1.0.9",
"syn 1.0.76",
"version_check",
]
[[package]] [[package]]
name = "proc-macro-error" name = "proc-macro-error"
version = "1.0.4" version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [ dependencies = [
"proc-macro-error-attr 1.0.4", "proc-macro-error-attr",
"proc-macro2 1.0.29", "proc-macro2 1.0.29",
"quote 1.0.9", "quote 1.0.9",
"syn 1.0.76", "syn 1.0.76",
"version_check", "version_check",
] ]
[[package]]
name = "proc-macro-error-attr"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de"
dependencies = [
"proc-macro2 1.0.29",
"quote 1.0.9",
"syn 1.0.76",
"syn-mid",
"version_check",
]
[[package]] [[package]]
name = "proc-macro-error-attr" name = "proc-macro-error-attr"
version = "1.0.4" version = "1.0.4"
@ -4641,17 +4624,6 @@ dependencies = [
"unicode-xid 0.2.2", "unicode-xid 0.2.2",
] ]
[[package]]
name = "syn-mid"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baa8e7560a164edb1621a55d18a0c59abf49d360f47aa7b821061dd7eea7fac9"
dependencies = [
"proc-macro2 1.0.29",
"quote 1.0.9",
"syn 1.0.76",
]
[[package]] [[package]]
name = "synstructure" name = "synstructure"
version = "0.12.5" version = "0.12.5"
@ -5258,7 +5230,7 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ee7b351bcc1e782997c72dc0b5b328f3ddcad4813b8ce3cac3f25ae5a4ab56b" checksum = "1ee7b351bcc1e782997c72dc0b5b328f3ddcad4813b8ce3cac3f25ae5a4ab56b"
dependencies = [ dependencies = [
"proc-macro-error 1.0.4", "proc-macro-error",
"proc-macro2 1.0.29", "proc-macro2 1.0.29",
"quote 1.0.9", "quote 1.0.9",
"syn 1.0.76", "syn 1.0.76",

View file

@ -35,7 +35,7 @@ install-zig-llvm-valgrind-clippy-rustfmt:
RUN rustup component add rustfmt RUN rustup component add rustfmt
# criterion # criterion
RUN cargo install cargo-criterion RUN cargo install cargo-criterion
# wasm # editor
RUN apt -y install libxkbcommon-dev RUN apt -y install libxkbcommon-dev
# sccache # sccache
RUN apt -y install libssl-dev RUN apt -y install libssl-dev
@ -106,7 +106,7 @@ test-all:
build-nightly-release: build-nightly-release:
FROM +test-rust FROM +test-rust
COPY --dir .git ./ COPY --dir .git ./
# version.txt is used by the CLI: roc version # version.txt is used by the CLI: roc --version
RUN printf "nightly pre-release, built from commit " > version.txt RUN printf "nightly pre-release, built from commit " > version.txt
RUN git log --pretty=format:'%h' -n 1 >> version.txt RUN git log --pretty=format:'%h' -n 1 >> version.txt
RUN cargo build --release RUN cargo build --release

View file

@ -58,8 +58,7 @@ roc_fmt = { path = "../compiler/fmt" }
roc_reporting = { path = "../compiler/reporting" } roc_reporting = { path = "../compiler/reporting" }
roc_editor = { path = "../editor", optional = true } roc_editor = { path = "../editor", optional = true }
roc_linker = { path = "../linker" } roc_linker = { path = "../linker" }
# TODO switch to clap 3.0.0 once it's out. Tried adding clap = "~3.0.0-beta.1" and cargo wouldn't accept it clap = "= 3.0.0-beta.1"
clap = { git = "https://github.com/rtfeldman/clap", branch = "master" }
const_format = "0.2" const_format = "0.2"
rustyline = { git = "https://github.com/rtfeldman/rustyline", tag = "prompt-fix" } rustyline = { git = "https://github.com/rtfeldman/rustyline", tag = "prompt-fix" }
rustyline-derive = { git = "https://github.com/rtfeldman/rustyline", tag = "prompt-fix" } rustyline-derive = { git = "https://github.com/rtfeldman/rustyline", tag = "prompt-fix" }

View file

@ -45,25 +45,25 @@ pub fn build_app<'a>() -> App<'a> {
.about("Build a binary from the given .roc file, but don't run it") .about("Build a binary from the given .roc file, but don't run it")
.arg( .arg(
Arg::with_name(ROC_FILE) Arg::with_name(ROC_FILE)
.help("The .roc file to build") .about("The .roc file to build")
.required(true), .required(true),
) )
.arg( .arg(
Arg::with_name(FLAG_OPTIMIZE) Arg::with_name(FLAG_OPTIMIZE)
.long(FLAG_OPTIMIZE) .long(FLAG_OPTIMIZE)
.help("Optimize your compiled Roc program to run faster. (Optimization takes time to complete.)") .about("Optimize your compiled Roc program to run faster. (Optimization takes time to complete.)")
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(FLAG_DEV) Arg::with_name(FLAG_DEV)
.long(FLAG_DEV) .long(FLAG_DEV)
.help("Make compilation as fast as possible. (Runtime performance may suffer)") .about("Make compilation as fast as possible. (Runtime performance may suffer)")
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(FLAG_BACKEND) Arg::with_name(FLAG_BACKEND)
.long(FLAG_BACKEND) .long(FLAG_BACKEND)
.help("Choose a different backend") .about("Choose a different backend")
// .requires(BACKEND) // .requires(BACKEND)
.default_value(Backend::default().as_str()) .default_value(Backend::default().as_str())
.possible_values(Backend::OPTIONS) .possible_values(Backend::OPTIONS)
@ -72,31 +72,31 @@ pub fn build_app<'a>() -> App<'a> {
.arg( .arg(
Arg::with_name(FLAG_LIB) Arg::with_name(FLAG_LIB)
.long(FLAG_LIB) .long(FLAG_LIB)
.help("Build a C library instead of an executable.") .about("Build a C library instead of an executable.")
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(FLAG_DEBUG) Arg::with_name(FLAG_DEBUG)
.long(FLAG_DEBUG) .long(FLAG_DEBUG)
.help("Store LLVM debug information in the generated program") .about("Store LLVM debug information in the generated program")
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(FLAG_TIME) Arg::with_name(FLAG_TIME)
.long(FLAG_TIME) .long(FLAG_TIME)
.help("Prints detailed compilation time information.") .about("Prints detailed compilation time information.")
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(FLAG_LINK) Arg::with_name(FLAG_LINK)
.long(FLAG_LINK) .long(FLAG_LINK)
.help("Uses the roc linker instead of the system linker.") .about("Uses the roc linker instead of the system linker.")
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(FLAG_PRECOMPILED) Arg::with_name(FLAG_PRECOMPILED)
.long(FLAG_PRECOMPILED) .long(FLAG_PRECOMPILED)
.help("Assumes the host has been precompiled and skips recompiling the host.") .about("Assumes the host has been precompiled and skips recompiling the host.")
.required(false), .required(false),
) )
) )
@ -108,12 +108,12 @@ pub fn build_app<'a>() -> App<'a> {
.arg( .arg(
Arg::with_name(FLAG_TIME) Arg::with_name(FLAG_TIME)
.long(FLAG_TIME) .long(FLAG_TIME)
.help("Prints detailed compilation time information.") .about("Prints detailed compilation time information.")
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(ROC_FILE) Arg::with_name(ROC_FILE)
.help("The .roc file of an app to run") .about("The .roc file of an app to run")
.required(true), .required(true),
) )
) )
@ -124,7 +124,7 @@ pub fn build_app<'a>() -> App<'a> {
.index(1) .index(1)
.multiple(true) .multiple(true)
.required(false) .required(false)
.help("The directory or files to build documentation for") .about("The directory or files to build documentation for")
) )
) )
@ -132,45 +132,45 @@ pub fn build_app<'a>() -> App<'a> {
.arg( .arg(
Arg::with_name(FLAG_OPTIMIZE) Arg::with_name(FLAG_OPTIMIZE)
.long(FLAG_OPTIMIZE) .long(FLAG_OPTIMIZE)
.help("Optimize the compiled program to run faster. (Optimization takes time to complete.)") .about("Optimize the compiled program to run faster. (Optimization takes time to complete.)")
.requires(ROC_FILE) .requires(ROC_FILE)
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(FLAG_DEV) Arg::with_name(FLAG_DEV)
.long(FLAG_DEV) .long(FLAG_DEV)
.help("Make compilation as fast as possible. (Runtime performance may suffer)") .about("Make compilation as fast as possible. (Runtime performance may suffer)")
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(FLAG_DEBUG) Arg::with_name(FLAG_DEBUG)
.long(FLAG_DEBUG) .long(FLAG_DEBUG)
.help("Store LLVM debug information in the generated program") .about("Store LLVM debug information in the generated program")
.requires(ROC_FILE) .requires(ROC_FILE)
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(FLAG_TIME) Arg::with_name(FLAG_TIME)
.long(FLAG_TIME) .long(FLAG_TIME)
.help("Prints detailed compilation time information.") .about("Prints detailed compilation time information.")
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(FLAG_LINK) Arg::with_name(FLAG_LINK)
.long(FLAG_LINK) .long(FLAG_LINK)
.help("Uses the roc linker instead of the system linker.") .about("Uses the roc linker instead of the system linker.")
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(FLAG_PRECOMPILED) Arg::with_name(FLAG_PRECOMPILED)
.long(FLAG_PRECOMPILED) .long(FLAG_PRECOMPILED)
.help("Assumes the host has been precompiled and skips recompiling the host.") .about("Assumes the host has been precompiled and skips recompiling the host.")
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(FLAG_BACKEND) Arg::with_name(FLAG_BACKEND)
.long(FLAG_BACKEND) .long(FLAG_BACKEND)
.help("Choose a different backend") .about("Choose a different backend")
// .requires(BACKEND) // .requires(BACKEND)
.default_value(Backend::default().as_str()) .default_value(Backend::default().as_str())
.possible_values(Backend::OPTIONS) .possible_values(Backend::OPTIONS)
@ -178,12 +178,12 @@ pub fn build_app<'a>() -> App<'a> {
) )
.arg( .arg(
Arg::with_name(ROC_FILE) Arg::with_name(ROC_FILE)
.help("The .roc file of an app to build and run") .about("The .roc file of an app to build and run")
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(ARGS_FOR_APP) Arg::with_name(ARGS_FOR_APP)
.help("Arguments to pass into the app being run") .about("Arguments to pass into the app being run")
.requires(ROC_FILE) .requires(ROC_FILE)
.multiple(true), .multiple(true),
); );
@ -195,7 +195,7 @@ pub fn build_app<'a>() -> App<'a> {
.index(1) .index(1)
.multiple(true) .multiple(true)
.required(false) .required(false)
.help("(optional) The directory or files to open on launch."), .about("(optional) The directory or files to open on launch."),
), ),
) )
} else { } else {

View file

@ -205,6 +205,9 @@ mod cli_run {
example.use_valgrind, example.use_valgrind,
); );
// This is mostly because the false interpreter is still very slow -
// 25s for the cli tests is just not acceptable during development!
#[cfg(not(debug_assertions))]
check_output_with_stdin( check_output_with_stdin(
&file_name, &file_name,
example.stdin, example.stdin,

View file

@ -30,10 +30,7 @@ use roc_ast::{
env::Env, env::Env,
}, },
}; };
use roc_module::{ use roc_module::{module_err::ModuleResult, symbol::Interns};
module_err::ModuleResult,
symbol::{get_module_ident_ids, Interns},
};
// make Markup Nodes: generate String representation, assign Highlighting Style // make Markup Nodes: generate String representation, assign Highlighting Style
pub fn expr2_to_markup<'a>( pub fn expr2_to_markup<'a>(
@ -46,6 +43,9 @@ pub fn expr2_to_markup<'a>(
) -> ASTResult<MarkNodeId> { ) -> ASTResult<MarkNodeId> {
let ast_node_id = ASTNodeId::AExprId(expr2_node_id); let ast_node_id = ASTNodeId::AExprId(expr2_node_id);
// for debugging
//println!("EXPR2 {:?}", expr2);
let mark_node_id = match expr2 { let mark_node_id = match expr2 {
Expr2::SmallInt { text, .. } Expr2::SmallInt { text, .. }
| Expr2::I128 { text, .. } | Expr2::I128 { text, .. }
@ -112,8 +112,7 @@ pub fn expr2_to_markup<'a>(
mark_node_pool.add(call_node) mark_node_pool.add(call_node)
} }
Expr2::Var(symbol) => { Expr2::Var(symbol) => {
let text = get_module_ident_ids(&interns.all_ident_ids, &env.home)? let text = symbol.fully_qualified(interns, env.home);
.get_name_str_res(symbol.ident_id())?;
new_markup_node( new_markup_node(
text.to_string(), text.to_string(),

View file

@ -665,7 +665,7 @@ fn link_linux(
.args(&[ .args(&[
"--gc-sections", "--gc-sections",
"--eh-frame-hdr", "--eh-frame-hdr",
"-arch", "--arch",
arch_str(target), arch_str(target),
"-pie", "-pie",
libcrt_path.join("crti.o").to_str().unwrap(), libcrt_path.join("crti.o").to_str().unwrap(),
@ -674,7 +674,7 @@ fn link_linux(
.args(&base_args) .args(&base_args)
.args(&["-dynamic-linker", ld_linux]) .args(&["-dynamic-linker", ld_linux])
.args(input_paths) .args(input_paths)
// ld.lld requires this argument, and does not accept -arch // ld.lld requires this argument, and does not accept --arch
// .args(&["-L/usr/lib/x86_64-linux-gnu"]) // .args(&["-L/usr/lib/x86_64-linux-gnu"])
.args(&[ .args(&[
// Libraries - see https://github.com/rtfeldman/roc/pull/554#discussion_r496365925 // Libraries - see https://github.com/rtfeldman/roc/pull/554#discussion_r496365925

View file

@ -86,8 +86,8 @@ pub fn build(b: *Builder) void {
fn removeInstallSteps(b: *Builder) void { fn removeInstallSteps(b: *Builder) void {
for (b.top_level_steps.items) |top_level_step, i| { for (b.top_level_steps.items) |top_level_step, i| {
if (mem.eql(u8, top_level_step.step.name, "install") or mem.eql(u8, top_level_step.step.name, "uninstall")) { const name = top_level_step.step.name;
const name = top_level_step.step.name; if (mem.eql(u8, name, "install") or mem.eql(u8, name, "uninstall")) {
_ = b.top_level_steps.swapRemove(i); _ = b.top_level_steps.swapRemove(i);
} }
} }

View file

@ -160,7 +160,8 @@ fn exportUtilsFn(comptime func: anytype, comptime func_name: []const u8) void {
// Custom panic function, as builtin Zig version errors during LLVM verification // Custom panic function, as builtin Zig version errors during LLVM verification
pub fn panic(message: []const u8, stacktrace: ?*std.builtin.StackTrace) noreturn { pub fn panic(message: []const u8, stacktrace: ?*std.builtin.StackTrace) noreturn {
if (std.builtin.is_test) { const builtin = @import("builtin");
if (builtin.is_test) {
std.debug.print("{s}: {?}", .{ message, stacktrace }); std.debug.print("{s}: {?}", .{ message, stacktrace });
} else { } else {
_ = message; _ = message;

View file

@ -93,7 +93,7 @@ pub const RocStr = extern struct {
if (length < roc_str_size) { if (length < roc_str_size) {
return RocStr.empty(); return RocStr.empty();
} else { } else {
var new_bytes: []T = utils.alloc(length, RocStr.alignment) catch unreachable; var new_bytes = utils.alloc(length, RocStr.alignment) catch unreachable;
var new_bytes_ptr: [*]u8 = @ptrCast([*]u8, &new_bytes); var new_bytes_ptr: [*]u8 = @ptrCast([*]u8, &new_bytes);

View file

@ -19,8 +19,9 @@ extern fn roc_dealloc(c_ptr: *c_void, alignment: u32) callconv(.C) void;
extern fn roc_panic(c_ptr: *c_void, tag_id: u32) callconv(.C) void; extern fn roc_panic(c_ptr: *c_void, tag_id: u32) callconv(.C) void;
comptime { comptime {
const builtin = @import("builtin");
// During tetsts, use the testing allocators to satisfy these functions. // During tetsts, use the testing allocators to satisfy these functions.
if (std.builtin.is_test) { if (builtin.is_test) {
@export(testing_roc_alloc, .{ .name = "roc_alloc", .linkage = .Strong }); @export(testing_roc_alloc, .{ .name = "roc_alloc", .linkage = .Strong });
@export(testing_roc_realloc, .{ .name = "roc_realloc", .linkage = .Strong }); @export(testing_roc_realloc, .{ .name = "roc_realloc", .linkage = .Strong });
@export(testing_roc_dealloc, .{ .name = "roc_dealloc", .linkage = .Strong }); @export(testing_roc_dealloc, .{ .name = "roc_dealloc", .linkage = .Strong });
@ -257,7 +258,7 @@ pub const Ordering = enum(u8) {
LT = 2, LT = 2,
}; };
pub const UpdateMode = extern enum(u8) { pub const UpdateMode = enum(u8) {
Immutable = 0, Immutable = 0,
InPlace = 1, InPlace = 1,
}; };

View file

@ -3852,7 +3852,7 @@ fn build_procedures_help<'a, 'ctx, 'env>(
let it = procedures.iter().map(|x| x.1); let it = procedures.iter().map(|x| x.1);
let solutions = match roc_mono::alias_analysis::spec_program(entry_point, it) { let solutions = match roc_mono::alias_analysis::spec_program(opt_level, entry_point, it) {
Err(e) => panic!("Error in alias analysis: {}", e), Err(e) => panic!("Error in alias analysis: {}", e),
Ok(solutions) => solutions, Ok(solutions) => solutions,
}; };

View file

@ -4531,8 +4531,8 @@ fn to_missing_platform_report(module_id: ModuleId, other: PlatformPath) -> Strin
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow(r"The input file is a interface file, but only app modules can be ran."), alloc.reflow(r"The input file is a interface file, but only app modules can be ran."),
alloc.concat(vec![ alloc.concat(vec![
alloc.reflow(r"I will still parse and typecheck the input file and its dependencies,"), alloc.reflow(r"I will still parse and typecheck the input file and its dependencies, "),
alloc.reflow(r"but won't output any executable."), alloc.reflow(r"but won't output any executable."),
]) ])
]); ]);
@ -4547,8 +4547,8 @@ fn to_missing_platform_report(module_id: ModuleId, other: PlatformPath) -> Strin
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow(r"The input file is a package config file, but only app modules can be ran."), alloc.reflow(r"The input file is a package config file, but only app modules can be ran."),
alloc.concat(vec![ alloc.concat(vec![
alloc.reflow(r"I will still parse and typecheck the input file and its dependencies,"), alloc.reflow(r"I will still parse and typecheck the input file and its dependencies, "),
alloc.reflow(r"but won't output any executable."), alloc.reflow(r"but won't output any executable."),
]) ])
]); ]);

View file

@ -4,7 +4,7 @@ use std::fmt;
/// This could be uppercase or lowercase, qualified or unqualified. /// This could be uppercase or lowercase, qualified or unqualified.
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Ident(pub IdentStr); // Is IdentStr allowed to be pub? pub struct Ident(pub IdentStr);
impl Ident { impl Ident {
pub fn as_inline_str(&self) -> &IdentStr { pub fn as_inline_str(&self) -> &IdentStr {

View file

@ -10,7 +10,8 @@ use roc_module::symbol::Symbol;
use std::convert::TryFrom; use std::convert::TryFrom;
use crate::ir::{ use crate::ir::{
Call, CallType, Expr, HostExposedLayouts, ListLiteralElement, Literal, ModifyRc, Proc, Stmt, Call, CallType, Expr, HostExposedLayouts, ListLiteralElement, Literal, ModifyRc, OptLevel,
Proc, Stmt,
}; };
use crate::layout::{Builtin, Layout, ListLayout, RawFunctionLayout, UnionLayout}; use crate::layout::{Builtin, Layout, ListLayout, RawFunctionLayout, UnionLayout};
@ -109,6 +110,7 @@ fn bytes_as_ascii(bytes: &[u8]) -> String {
} }
pub fn spec_program<'a, I>( pub fn spec_program<'a, I>(
opt_level: OptLevel,
entry_point: crate::ir::EntryPoint<'a>, entry_point: crate::ir::EntryPoint<'a>,
procs: I, procs: I,
) -> Result<morphic_lib::Solutions> ) -> Result<morphic_lib::Solutions>
@ -239,7 +241,10 @@ where
eprintln!("{}", program.to_source_string()); eprintln!("{}", program.to_source_string());
} }
morphic_lib::solve(program) match opt_level {
OptLevel::Development | OptLevel::Normal => morphic_lib::solve_trivial(program),
OptLevel::Optimize => morphic_lib::solve(program),
}
} }
/// if you want an "escape hatch" which allows you construct "best-case scenario" values /// if you want an "escape hatch" which allows you construct "best-case scenario" values

View file

@ -1767,13 +1767,9 @@ fn specialize_all_help<'a>(
externals_others_need: ExternalSpecializations<'a>, externals_others_need: ExternalSpecializations<'a>,
layout_cache: &mut LayoutCache<'a>, layout_cache: &mut LayoutCache<'a>,
) { ) {
let mut symbol_solved_type = Vec::new_in(env.arena);
for (symbol, solved_types) in externals_others_need.specs.iter() { for (symbol, solved_types) in externals_others_need.specs.iter() {
// for some unclear reason, the MutSet does not deduplicate according to the hash // for some unclear reason, the MutSet does not deduplicate according to the hash
// instance. So we do it manually here // instance. So we do it manually here
let mut as_vec: std::vec::Vec<_> = solved_types.iter().collect();
use std::collections::hash_map::DefaultHasher; use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
@ -1783,50 +1779,53 @@ fn specialize_all_help<'a>(
hasher.finish() hasher.finish()
}; };
as_vec.sort_by_key(|x| hash_the_thing(x)); let mut as_vec = Vec::from_iter_in(
as_vec.dedup_by_key(|x| hash_the_thing(x)); solved_types.iter().map(|x| (hash_the_thing(x), x)),
env.arena,
);
for s in as_vec { as_vec.sort_by_key(|(k, _)| *k);
symbol_solved_type.push((*symbol, s.clone())); as_vec.dedup_by_key(|(k, _)| *k);
}
}
for (name, solved_type) in symbol_solved_type.into_iter() { for (_, solved_type) in as_vec {
let partial_proc = match procs.partial_procs.get(&name) { let name = *symbol;
Some(v) => v.clone(),
None => {
panic!("Cannot find a partial proc for {:?}", name);
}
};
// TODO I believe this sis also duplicated let partial_proc = match procs.partial_procs.get(&name) {
match specialize_solved_type( Some(v) => v.clone(),
env, None => {
procs, panic!("Cannot find a partial proc for {:?}", name);
name,
layout_cache,
solved_type,
BumpMap::new_in(env.arena),
partial_proc,
) {
Ok((proc, layout)) => {
let top_level = ProcLayout::from_raw(env.arena, layout);
if procs.is_module_thunk(name) {
debug_assert!(top_level.arguments.is_empty());
} }
};
procs.specialized.insert((name, top_level), Done(proc)); // TODO I believe this sis also duplicated
} match specialize_solved_type(
Err(SpecializeFailure { env,
problem: _, procs,
attempted_layout, name,
}) => { layout_cache,
let proc = generate_runtime_error_function(env, name, attempted_layout); solved_type,
BumpMap::new_in(env.arena),
partial_proc,
) {
Ok((proc, layout)) => {
let top_level = ProcLayout::from_raw(env.arena, layout);
let top_level = ProcLayout::from_raw(env.arena, attempted_layout); if procs.is_module_thunk(name) {
debug_assert!(top_level.arguments.is_empty());
}
procs.specialized.insert((name, top_level), Done(proc)); procs.specialized.insert((name, top_level), Done(proc));
}
Err(SpecializeFailure {
problem: _,
attempted_layout,
}) => {
let proc = generate_runtime_error_function(env, name, attempted_layout);
let top_level = ProcLayout::from_raw(env.arena, attempted_layout);
procs.specialized.insert((name, top_level), Done(proc));
}
} }
} }
} }
@ -2421,7 +2420,7 @@ fn specialize<'a>(
procs, procs,
proc_name, proc_name,
layout_cache, layout_cache,
solved_type, &solved_type,
host_exposed_aliases, host_exposed_aliases,
partial_proc, partial_proc,
) )
@ -2451,7 +2450,7 @@ fn specialize_solved_type<'a>(
procs: &mut Procs<'a>, procs: &mut Procs<'a>,
proc_name: Symbol, proc_name: Symbol,
layout_cache: &mut LayoutCache<'a>, layout_cache: &mut LayoutCache<'a>,
solved_type: SolvedType, solved_type: &SolvedType,
host_exposed_aliases: BumpMap<Symbol, SolvedType>, host_exposed_aliases: BumpMap<Symbol, SolvedType>,
partial_proc: PartialProc<'a>, partial_proc: PartialProc<'a>,
) -> Result<SpecializeSuccess<'a>, SpecializeFailure<'a>> { ) -> Result<SpecializeSuccess<'a>, SpecializeFailure<'a>> {
@ -2460,7 +2459,7 @@ fn specialize_solved_type<'a>(
procs, procs,
proc_name, proc_name,
layout_cache, layout_cache,
|env| introduce_solved_type_to_subs(env, &solved_type), |env| introduce_solved_type_to_subs(env, solved_type),
host_exposed_aliases, host_exposed_aliases,
partial_proc, partial_proc,
) )

View file

@ -151,16 +151,32 @@ main = "Hello, world!"
#[test] #[test]
fn top_level_def_value() { fn top_level_def_value() {
expect_html_def( expect_html_def(
r#"myFunction = "Hello, World!""#, r#"myVal = "Hello, World!""#,
"<span class=\"syntax-value\">myFunction</span><span class=\"syntax-operator\"> = </span><span class=\"syntax-string\">\"Hello, World!\"</span>\n\n", "<span class=\"syntax-value\">myVal</span><span class=\"syntax-operator\"> = </span><span class=\"syntax-string\">\"Hello, World!\"</span>\n\n",
);
}
#[test]
fn tld_newline_in_str() {
expect_html_def(
r#"myVal = "Hello, Newline!\n""#,
"<span class=\"syntax-value\">myVal</span><span class=\"syntax-operator\"> = </span><span class=\"syntax-string\">\"Hello, Newline!\n\"</span>\n\n",
); );
} }
#[test] #[test]
fn tld_list() { fn tld_list() {
expect_html_def( expect_html_def(
r#"myFunction = [ 1, 2, 3 ]"#, r#"myVal = [ 1, 2, 3 ]"#,
"<span class=\"syntax-value\">myFunction</span><span class=\"syntax-operator\"> = </span><span class=\"syntax-bracket\">[ </span><span class=\"syntax-number\">1</span><span class=\"syntax-comma\">, </span><span class=\"syntax-number\">2</span><span class=\"syntax-comma\">, </span><span class=\"syntax-number\">3</span><span class=\"syntax-bracket\"> ]</span>\n\n", "<span class=\"syntax-value\">myVal</span><span class=\"syntax-operator\"> = </span><span class=\"syntax-bracket\">[ </span><span class=\"syntax-number\">1</span><span class=\"syntax-comma\">, </span><span class=\"syntax-number\">2</span><span class=\"syntax-comma\">, </span><span class=\"syntax-number\">3</span><span class=\"syntax-bracket\"> ]</span>\n\n",
);
}
#[test]
fn call_builtin() {
expect_html_def(
r#"myVal = Str.fromInt 1234"#,
"<span class=\"syntax-value\">myVal</span><span class=\"syntax-operator\"> = </span><span class=\"syntax-value\">Str.fromInt</span><span class=\"syntax-blank\"> </span><span class=\"syntax-number\">1234</span>\n\n",
); );
} }

View file

@ -130,7 +130,7 @@ fn markup_to_wgpu_helper<'a>(
} => { } => {
let highlight_color = map_get(&code_style.ed_theme.syntax_high_map, syn_high_style)?; let highlight_color = map_get(&code_style.ed_theme.syntax_high_map, syn_high_style)?;
let full_content = markup_node.get_full_content(); let full_content = markup_node.get_full_content().replace("\n", "\\n"); // any \n left here should be escaped so that it can be shown as \n
let glyph_text = glyph_brush::OwnedText::new(full_content) let glyph_text = glyph_brush::OwnedText::new(full_content)
.with_color(colors::to_slice(*highlight_color)) .with_color(colors::to_slice(*highlight_color))

View file

@ -22,8 +22,7 @@ roc_mono = { path = "../compiler/mono" }
roc_build = { path = "../compiler/build", default-features = false } roc_build = { path = "../compiler/build", default-features = false }
roc_collections = { path = "../compiler/collections" } roc_collections = { path = "../compiler/collections" }
bumpalo = { version = "3.6", features = ["collections"] } bumpalo = { version = "3.6", features = ["collections"] }
# TODO switch to clap 3.0.0 once it's out. Tried adding clap = "~3.0.0-beta.1" and cargo wouldn't accept it clap = "= 3.0.0-beta.1"
clap = { git = "https://github.com/rtfeldman/clap", branch = "master" }
iced-x86 = "1.14" iced-x86 = "1.14"
memmap2 = "0.3" memmap2 = "0.3"
object = { version = "0.26", features = ["read", "write"] } object = { version = "0.26", features = ["read", "write"] }

View file

@ -59,36 +59,36 @@ pub fn build_app<'a>() -> App<'a> {
.about("Preprocesses a dynamically linked platform to prepare for linking.") .about("Preprocesses a dynamically linked platform to prepare for linking.")
.arg( .arg(
Arg::with_name(EXEC) Arg::with_name(EXEC)
.help("The dynamically linked platform executable") .about("The dynamically linked platform executable")
.required(true), .required(true),
) )
.arg( .arg(
Arg::with_name(METADATA) Arg::with_name(METADATA)
.help("Where to save the metadata from preprocessing") .about("Where to save the metadata from preprocessing")
.required(true), .required(true),
) )
.arg( .arg(
Arg::with_name(OUT) Arg::with_name(OUT)
.help("The modified version of the dynamically linked platform executable") .about("The modified version of the dynamically linked platform executable")
.required(true), .required(true),
) )
.arg( .arg(
Arg::with_name(SHARED_LIB) Arg::with_name(SHARED_LIB)
.help("The name of the shared library used in building the platform") .about("The name of the shared library used in building the platform")
.default_value("libapp.so"), .default_value("libapp.so"),
) )
.arg( .arg(
Arg::with_name(FLAG_VERBOSE) Arg::with_name(FLAG_VERBOSE)
.long(FLAG_VERBOSE) .long(FLAG_VERBOSE)
.short('v') .short('v')
.help("Enable verbose printing") .about("Enable verbose printing")
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(FLAG_TIME) Arg::with_name(FLAG_TIME)
.long(FLAG_TIME) .long(FLAG_TIME)
.short('t') .short('t')
.help("Print timing information") .about("Print timing information")
.required(false), .required(false),
), ),
) )
@ -97,17 +97,17 @@ pub fn build_app<'a>() -> App<'a> {
.about("Links a preprocessed platform with a Roc application.") .about("Links a preprocessed platform with a Roc application.")
.arg( .arg(
Arg::with_name(APP) Arg::with_name(APP)
.help("The Roc application object file waiting to be linked") .about("The Roc application object file waiting to be linked")
.required(true), .required(true),
) )
.arg( .arg(
Arg::with_name(METADATA) Arg::with_name(METADATA)
.help("The metadata created by preprocessing the platform") .about("The metadata created by preprocessing the platform")
.required(true), .required(true),
) )
.arg( .arg(
Arg::with_name(OUT) Arg::with_name(OUT)
.help( .about(
"The modified version of the dynamically linked platform. \ "The modified version of the dynamically linked platform. \
It will be consumed to make linking faster.", It will be consumed to make linking faster.",
) )
@ -117,14 +117,14 @@ pub fn build_app<'a>() -> App<'a> {
Arg::with_name(FLAG_VERBOSE) Arg::with_name(FLAG_VERBOSE)
.long(FLAG_VERBOSE) .long(FLAG_VERBOSE)
.short('v') .short('v')
.help("Enable verbose printing") .about("Enable verbose printing")
.required(false), .required(false),
) )
.arg( .arg(
Arg::with_name(FLAG_TIME) Arg::with_name(FLAG_TIME)
.long(FLAG_TIME) .long(FLAG_TIME)
.short('t') .short('t')
.help("Print timing information") .about("Print timing information")
.required(false), .required(false),
), ),
) )

View file

@ -28,6 +28,7 @@ let
xorg.libXrandr xorg.libXrandr
xorg.libXi xorg.libXi
xorg.libxcb xorg.libxcb
alsa-lib
]; ];
llvmPkgs = pkgs.llvmPackages_12; llvmPkgs = pkgs.llvmPackages_12;

View file

@ -1768,3 +1768,56 @@ pub(crate) fn analyze(tc: TypeCache, program: &ir::Program) -> ProgramSolutions
entry_points: entry_point_solutions, entry_points: entry_point_solutions,
} }
} }
// Utilities for producing "trivial" solutions, in which each function has exactly one
// specialization and all update modes are `Immutable`:
fn hash_func_id_trivial(func_id: FuncId) -> api::FuncSpec {
use sha2::{Digest, Sha256};
let mut hasher = Sha256::new();
hasher.update(&func_id.0.to_le_bytes());
api::FuncSpec(hasher.finalize().into())
}
fn func_solution_trivial(func_def: &ir::FuncDef) -> FuncSolution {
let update_modes = IdVec::filled_with(func_def.graph.update_mode_vars(), || {
api::UpdateMode::Immutable
});
let mut callee_specs = IdVec::filled_with(func_def.graph.callee_spec_vars(), || None);
for val_id in func_def.graph.values().count().iter() {
if let ir::ValueKind::Op(ir::OpKind::Call {
callee_spec_var,
callee,
}) = &func_def.graph.values().node(val_id).op.kind
{
replace_none(
&mut callee_specs[callee_spec_var],
hash_func_id_trivial(*callee),
)
.unwrap();
}
}
FuncSolution {
update_modes,
callee_specs: callee_specs.into_mapped(|_, spec| spec.unwrap()),
}
}
pub(crate) fn analyze_trivial(program: &ir::Program) -> ProgramSolutions {
let funcs = FuncSolutions {
solutions: program.funcs.map(|func_id, func_def| {
std::iter::once((
hash_func_id_trivial(func_id),
Some(func_solution_trivial(func_def)),
))
.collect()
}),
};
let entry_points = program
.entry_points
.map(|_, &func_id| hash_func_id_trivial(func_id));
ProgramSolutions {
funcs,
entry_points,
}
}

View file

@ -3,15 +3,16 @@ use smallvec::SmallVec;
use std::collections::{btree_map::Entry, BTreeMap}; use std::collections::{btree_map::Entry, BTreeMap};
use std::rc::Rc; use std::rc::Rc;
use crate::analyze;
use crate::preprocess; use crate::preprocess;
use crate::render_api_ir; use crate::render_api_ir;
use crate::type_cache::TypeCache;
use crate::util::blocks::Blocks; use crate::util::blocks::Blocks;
use crate::util::id_bi_map::IdBiMap; use crate::util::id_bi_map::IdBiMap;
use crate::util::id_type::Count; use crate::util::id_type::Count;
use crate::util::id_vec::IdVec; use crate::util::id_vec::IdVec;
use crate::util::op_graph::OpGraph; use crate::util::op_graph::OpGraph;
use crate::util::replace_none::replace_none; use crate::util::replace_none::replace_none;
use crate::{analyze, ir};
#[derive(Clone, thiserror::Error, Debug)] #[derive(Clone, thiserror::Error, Debug)]
#[non_exhaustive] #[non_exhaustive]
@ -1533,6 +1534,8 @@ impl Solutions {
} }
} }
// TODO: Remove this; it's only used in obsolete logic for populating const definitions with trivial
// solutions
fn populate_specs( fn populate_specs(
callee_spec_var_ids: Count<CalleeSpecVarId>, callee_spec_var_ids: Count<CalleeSpecVarId>,
vals: &OpGraph<ValueId, Op>, vals: &OpGraph<ValueId, Op>,
@ -1555,11 +1558,14 @@ fn populate_specs(
results.into_mapped(|_, spec| spec.unwrap()) results.into_mapped(|_, spec| spec.unwrap())
} }
pub fn solve(api_program: Program) -> Result<Solutions> { fn solve_with(
api_program: Program,
analysis: impl for<'a> FnOnce(TypeCache, &'a ir::Program) -> analyze::ProgramSolutions,
) -> Result<Solutions> {
let (nc, tc, program) = let (nc, tc, program) =
preprocess::preprocess(&api_program).map_err(ErrorKind::PreprocessError)?; preprocess::preprocess(&api_program).map_err(ErrorKind::PreprocessError)?;
let mut solutions = analyze::analyze(tc, &program); let mut solutions = analysis(tc, &program);
Ok(Solutions { Ok(Solutions {
mods: api_program mods: api_program
@ -1600,6 +1606,8 @@ pub fn solve(api_program: Program) -> Result<Solutions> {
.const_defs .const_defs
.into_iter() .into_iter()
.map(|(const_name, const_def)| { .map(|(const_name, const_def)| {
// TODO: This is left over from the original stub implementation, and
// generates incorrect callee specialization hashes!
let callee_specs = populate_specs( let callee_specs = populate_specs(
const_def.builder.expr_builder.callee_spec_vars.count(), const_def.builder.expr_builder.callee_spec_vars.count(),
&const_def.builder.expr_builder.vals, &const_def.builder.expr_builder.vals,
@ -1629,12 +1637,29 @@ pub fn solve(api_program: Program) -> Result<Solutions> {
}) })
} }
/// Solve for optimized update modes and function specializations
pub fn solve(api_program: Program) -> Result<Solutions> {
solve_with(api_program, analyze::analyze)
}
/// Return a "trivial" solution for the program, setting every update mode to `Immutable`.
///
/// This function does not perform any expensive analysis, but it does typecheck the input program,
/// so it can be useful for verifying the correctness of a generated program.
pub fn solve_trivial(api_program: Program) -> Result<Solutions> {
solve_with(api_program, |_, program| analyze::analyze_trivial(program))
}
// TODO: Remove this; it's only used in obsolete logic for populating const definitions with trivial
// solutions
fn hash_bstr(hasher: &mut Sha256, bstr: &[u8]) { fn hash_bstr(hasher: &mut Sha256, bstr: &[u8]) {
let header = (bstr.len() as u64).to_le_bytes(); let header = (bstr.len() as u64).to_le_bytes();
hasher.update(&header); hasher.update(&header);
hasher.update(bstr); hasher.update(bstr);
} }
// TODO: Remove this; it's only used in obsolete logic for populating const definitions with trivial
// solutions
fn hash_func_name(mod_: ModName, func: FuncName) -> FuncSpec { fn hash_func_name(mod_: ModName, func: FuncName) -> FuncSpec {
let mut hasher = Sha256::new(); let mut hasher = Sha256::new();
hash_bstr(&mut hasher, mod_.0); hash_bstr(&mut hasher, mod_.0);