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

@ -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,15 +1779,17 @@ 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 (_, solved_type) in as_vec {
let name = *symbol;
for (name, solved_type) in symbol_solved_type.into_iter() {
let partial_proc = match procs.partial_procs.get(&name) { let partial_proc = match procs.partial_procs.get(&name) {
Some(v) => v.clone(), Some(v) => v.clone(),
None => { None => {
@ -1831,6 +1829,7 @@ fn specialize_all_help<'a>(
} }
} }
} }
}
fn generate_runtime_error_function<'a>( fn generate_runtime_error_function<'a>(
env: &mut Env<'a, '_>, env: &mut Env<'a, '_>,
@ -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);