Merge branch 'main' of https://github.com/roc-lang/roc into windows-final-cli-tests

This commit is contained in:
Anton-4 2022-11-15 17:40:05 +01:00
commit 5a447a9fcc
No known key found for this signature in database
GPG key ID: A13F4A6E21141925
120 changed files with 6844 additions and 3696 deletions

View file

@ -115,7 +115,7 @@ For any OS, you can use [`zigup`](https://github.com/marler8997/zigup) to manage
If you prefer a package manager, you can try the following:
- For MacOS, you can install with `brew install zig`
- For MacOS, you can install with `brew install zig@0.9.1`
- For, Ubuntu, you can use Snap, you can install with `snap install zig --classic --beta`
- For other systems, checkout this [page](https://github.com/ziglang/zig/wiki/Install-Zig-from-a-Package-Manager)

19
Cargo.lock generated
View file

@ -1769,13 +1769,6 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adab1eaa3408fb7f0c777a73e7465fd5656136fc93b670eb6df3c88c2c1344e3"
[[package]]
name = "inkwell"
version = "0.1.0"
dependencies = [
"inkwell 0.1.0 (git+https://github.com/roc-lang/inkwell?branch=master)",
]
[[package]]
name = "inkwell"
version = "0.1.0"
@ -3322,7 +3315,7 @@ name = "roc_build"
version = "0.0.1"
dependencies = [
"bumpalo",
"inkwell 0.1.0",
"inkwell",
"libloading",
"roc_builtins",
"roc_can",
@ -3395,7 +3388,7 @@ dependencies = [
"criterion",
"errno",
"indoc",
"inkwell 0.1.0",
"inkwell",
"libc",
"libloading",
"mimalloc",
@ -3649,7 +3642,7 @@ name = "roc_gen_llvm"
version = "0.0.1"
dependencies = [
"bumpalo",
"inkwell 0.1.0",
"inkwell",
"morphic_lib",
"roc_alias_analysis",
"roc_builtins",
@ -3903,7 +3896,7 @@ version = "0.0.1"
dependencies = [
"bumpalo",
"const_format",
"inkwell 0.1.0",
"inkwell",
"libloading",
"roc_build",
"roc_builtins",
@ -3953,7 +3946,7 @@ version = "0.0.1"
dependencies = [
"bumpalo",
"indoc",
"inkwell 0.1.0",
"inkwell",
"libc",
"libloading",
"pretty_assertions",
@ -4843,7 +4836,7 @@ dependencies = [
"bumpalo",
"criterion",
"indoc",
"inkwell 0.1.0",
"inkwell",
"lazy_static",
"libc",
"libloading",

View file

@ -43,6 +43,80 @@ exclude = [
# workspace, and without `resolver = "2"` here, you can't use `-p` like this.
resolver = "2"
[workspace.dependencies]
# NOTE: roc-lang/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 roc-lang/inkwell fork which points to
# a particular "release" of Inkwell.
#
# When we want to update Inkwell, we can sync up roc-lang/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/roc-lang/inkwell", branch = "master", features = [ "llvm13-0" ] }
arrayvec = "0.7.2"
bincode = "1.3.3"
bitvec = "1.0.1"
bumpalo = { version = "3.11.0", features = ["collections"] }
capstone = "0.11.0"
clap = { version = "3.2.20", default-features = false, features = ["std", "color", "suggestions"] }
const_format = { version = "0.2.23", features = ["const_generics"] }
criterion = { git = "https://github.com/Anton-4/criterion.rs", features = ["html_reports"]}
crossbeam = "0.8.2"
distance = "0.4.0"
encode_unicode = "1.0.0"
errno = "0.2.8"
fnv = "1.0.7"
hashbrown = { version = "0.12.3", features = [ "bumpalo" ] }
iced-x86 = { version = "1.15.0", default-features = false, features = ["std", "decoder", "op_code_info", "instr_info"] }
im = "15.0.0"
im-rc = "15.0.0"
indoc = "1.0.7"
insta = "1.20.0"
lazy_static = "1.4.0"
libc = "0.2.135"
libloading = "0.7.1"
mach_object = "0.1"
maplit = "1.0.2"
memmap2 = "0.5.7"
mimalloc = { version = "0.1.26", default-features = false }
packed_struct = "0.10.0"
page_size = "0.4.2"
parking_lot = "0.12"
peg = "0.8.1"
pretty_assertions = "1.3.0"
quickcheck = "1.0.3"
quickcheck_macros = "1.0.0"
regex = "1.5.5"
rustyline = {git = "https://github.com/roc-lang/rustyline", rev = "e74333c"}
rustyline-derive = {git = "https://github.com/roc-lang/rustyline", rev = "e74333c"}
serde = { version = "1.0.144", features = ["derive"] }
signal-hook = "0.3.14"
snafu = { version = "0.7.1", features = ["backtraces"] }
static_assertions = "1.1.0"
strip-ansi-escapes = "0.1.1"
strum = { version = "0.24.1", features = ["derive"] }
target-lexicon = "0.12.3"
tempfile = "3.2.0"
unicode-segmentation = "1.10.0"
walkdir = "2.3.2"
wasm3 = { git = "https://github.com/roc-lang/wasm3-rs", rev = "f0f807d1fc0a50d1d68e5799e54ee62c05af00f5" }
wyhash = "0.5.0"
# TODO: Deal with the update of object to 0.27.
# It looks like it breaks linking the generated objects.
# Probably just need to specify an extra field that used to be implicit or something.
object = { version = "0.29.0", features = ["read", "write"] }
# Optimizations based on https://deterministic.space/high-performance-rust.html
[profile.release]
lto = "thin"

View file

@ -21,15 +21,17 @@ roc_load = { path = "../compiler/load" }
roc_target = { path = "../compiler/roc_target" }
roc_error_macros = { path = "../error_macros" }
roc_reporting = { path = "../reporting" }
arrayvec = "0.7.2"
bumpalo = { version = "3.11.0", features = ["collections"] }
page_size = "0.4.2"
snafu = { version = "0.7.1", features = ["backtraces"] }
ven_graph = { path = "../vendor/pathfinding" }
libc = "0.2.135"
arrayvec.workspace = true
bumpalo.workspace = true
page_size.workspace = true
snafu.workspace = true
libc.workspace = true
[dev-dependencies]
indoc = "1.0.7"
indoc.workspace = true
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.9", features = ["memoryapi"]}

View file

@ -278,7 +278,7 @@ pub fn expr_to_expr2<'a>(
}
}
Access(record_expr, field) => {
RecordAccess(record_expr, field) => {
// TODO
let region = ZERO;
let (record_expr_id, output) = to_expr_id(env, scope, record_expr, region);
@ -295,7 +295,7 @@ pub fn expr_to_expr2<'a>(
)
}
AccessorFunction(field) => (
RecordAccessorFunction(field) => (
Expr2::Accessor {
function_var: env.var_store.fresh(),
record_var: env.var_store.fresh(),

View file

@ -447,6 +447,7 @@ pub fn to_pattern2<'a>(
unreachable!("should have been handled in RecordDestructure");
}
Tuple(..) => todo!(),
List(..) => todo!(),
ListRest => todo!(),

View file

@ -1,5 +1,6 @@
use bumpalo::Bump;
use roc_load::{ExecutionMode, LoadConfig, LoadedModule, Threading};
use roc_reporting::report::DEFAULT_PALETTE;
use roc_target::TargetInfo;
use std::path::Path;
@ -9,6 +10,7 @@ pub fn load_module(src_file: &Path, threading: Threading) -> LoadedModule {
let load_config = LoadConfig {
target_info: TargetInfo::default_x86_64(), // editor only needs type info, so this is unused
render: roc_reporting::report::RenderTarget::ColorTerminal,
palette: DEFAULT_PALETTE,
threading,
exec_mode: ExecutionMode::Check,
};

View file

@ -61,22 +61,25 @@ roc_linker = { path = "../linker" }
roc_repl_cli = { path = "../repl_cli", optional = true }
roc_tracing = { path = "../tracing" }
roc_intern = { path = "../compiler/intern" }
clap = { version = "3.2.20", default-features = false, features = ["std", "color", "suggestions"] }
const_format = { version = "0.2.23", features = ["const_generics"] }
bumpalo = { version = "3.11.0", features = ["collections"] }
mimalloc = { version = "0.1.26", default-features = false }
libc = "0.2.135"
errno = "0.2.8"
roc_gen_llvm = {path = "../compiler/gen_llvm"}
ven_pretty = { path = "../vendor/pretty" }
target-lexicon = "0.12.3"
tempfile = "3.2.0"
wasmer-wasi = { version = "2.2.1", optional = true }
strum = { version = "0.24.1", features = ["derive"] }
libloading = "0.7.1"
roc_gen_llvm = {path = "../compiler/gen_llvm"}
inkwell = {path = "../vendor/inkwell"}
signal-hook = "0.3.14"
clap.workspace = true
const_format.workspace = true
mimalloc.workspace = true
bumpalo.workspace = true
libc.workspace = true
errno.workspace = true
target-lexicon.workspace = true
tempfile.workspace = true
strum.workspace = true
libloading.workspace = true
signal-hook.workspace = true
inkwell.workspace = true
# for now, uses unix/libc functions that windows does not support
[target.'cfg(not(windows))'.dependencies]

View file

@ -9,7 +9,7 @@ use roc_load::{
LoadingProblem, Threading,
};
use roc_mono::ir::OptLevel;
use roc_reporting::report::RenderTarget;
use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE};
use roc_target::TargetInfo;
use std::time::{Duration, Instant};
use std::{path::PathBuf, thread::JoinHandle};
@ -81,6 +81,7 @@ pub fn build_file<'a>(
target_info,
// TODO: expose this from CLI?
render: RenderTarget::ColorTerminal,
palette: DEFAULT_PALETTE,
threading,
exec_mode,
};
@ -469,6 +470,7 @@ pub fn check_file(
target_info,
// TODO: expose this from CLI?
render: RenderTarget::ColorTerminal,
palette: DEFAULT_PALETTE,
threading,
exec_mode: ExecutionMode::Check,
};

View file

@ -408,6 +408,7 @@ pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result<i32> {
target_info,
// TODO: expose this from CLI?
render: roc_reporting::report::RenderTarget::ColorTerminal,
palette: roc_reporting::report::DEFAULT_PALETTE,
threading,
exec_mode: ExecutionMode::Test,
};

View file

@ -805,7 +805,12 @@ mod cli_run {
&[],
);
assert!(compile_out.status.success(), "bad status {:?}", compile_out);
assert!(
compile_out.status.success(),
"bad status stderr:\n{}\nstdout:\n{}",
compile_out.stderr,
compile_out.stdout
);
let mut path = file.with_file_name(executable_filename);
path.set_extension("wasm");

View file

@ -15,6 +15,7 @@ roc_reporting = { path = "../reporting" }
roc_load = { path = "../compiler/load" }
roc_module = { path = "../compiler/module" }
roc_utils = { path = "../utils" }
bumpalo = { version = "3.8.0", features = ["collections"] }
criterion = { git = "https://github.com/Anton-4/criterion.rs"}
serde = { version = "1.0.130", features = ["derive"] }

View file

@ -28,13 +28,15 @@ roc_reporting = { path = "../../reporting" }
roc_error_macros = { path = "../../error_macros" }
roc_std = { path = "../../roc_std" }
roc_utils = { path = "../../utils" }
bumpalo = { version = "3.11.0", features = ["collections"] }
libloading = "0.7.1"
tempfile = "3.2.0"
inkwell = { path = "../../vendor/inkwell" }
target-lexicon = "0.12.3"
wasi_libc_sys = { path = "../../wasi-libc-sys" }
bumpalo.workspace = true
libloading.workspace = true
tempfile.workspace = true
target-lexicon.workspace = true
inkwell.workspace = true
[target.'cfg(target_os = "macos")'.dependencies]
serde_json = "1.0.85"

View file

@ -1,6 +1,5 @@
use inkwell::memory_buffer::MemoryBuffer;
use roc_error_macros::internal_error;
pub use roc_gen_llvm::llvm::build::FunctionIterator;
use roc_gen_llvm::llvm::build::{module_from_builtins, LlvmBackendMode};
use roc_gen_llvm::llvm::externs::add_default_roc_externs;
use roc_load::{EntryPoint, ExpectMetadata, LoadedModule, MonomorphizedModule};
@ -256,7 +255,7 @@ fn gen_from_mono_module_llvm<'a>(
debug_assert!(kind_id > 0);
let enum_attr = context.create_enum_attribute(kind_id, 1);
for function in FunctionIterator::from_module(module) {
for function in module.get_functions() {
let name = function.get_name().to_str().unwrap();
// mark our zig-defined builtins as internal

View file

@ -16,10 +16,11 @@ roc_parse = { path = "../parse" }
roc_problem = { path = "../problem" }
roc_types = { path = "../types" }
roc_serialize = { path = "../serialize" }
bumpalo = { version = "3.11.0", features = ["collections"] }
static_assertions = "1.1.0"
bitvec = "1"
bumpalo.workspace = true
static_assertions.workspace = true
bitvec.workspace = true
[dev-dependencies]
pretty_assertions = "1.3.0"
indoc = "1.0.7"
pretty_assertions.workspace = true
indoc.workspace = true

View file

@ -8,11 +8,10 @@ use roc_module::ident::TagName;
use roc_module::symbol::{ModuleId, Symbol};
use roc_region::all::{Loc, Region};
use roc_types::subs::{ExhaustiveMark, IllegalCycleMark, Variable};
use roc_types::types::{Category, PatternCategory, Type};
use roc_types::types::{Category, PatternCategory, TypeTag, Types};
pub struct Constraints {
pub constraints: Vec<Constraint>,
pub types: Vec<Cell<Type>>,
pub type_slices: Vec<TypeOrVar>,
pub variables: Vec<Variable>,
pub loc_symbols: Vec<(Symbol, Region)>,
@ -60,12 +59,11 @@ impl Default for Constraints {
pub type ExpectedTypeIndex = Index<Expected<TypeOrVar>>;
pub type PExpectedTypeIndex = Index<PExpected<TypeOrVar>>;
pub type TypeOrVar = EitherIndex<Cell<Type>, Variable>;
pub type TypeOrVar = EitherIndex<TypeTag, Variable>;
impl Constraints {
pub fn new() -> Self {
let constraints = Vec::new();
let mut types = Vec::new();
let type_slices = Vec::with_capacity(16);
let variables = Vec::new();
let loc_symbols = Vec::new();
@ -81,12 +79,6 @@ impl Constraints {
let pattern_eq = Vec::new();
let cycles = Vec::new();
types.extend([
Cell::new(Type::EmptyRec),
Cell::new(Type::EmptyTagUnion),
Cell::new(Type::Apply(Symbol::STR_STR, vec![], Region::zero())),
]);
categories.extend([
Category::Record,
Category::ForeignCall,
@ -120,7 +112,6 @@ impl Constraints {
Self {
constraints,
types,
type_slices,
variables,
loc_symbols,
@ -138,9 +129,9 @@ impl Constraints {
}
}
pub const EMPTY_RECORD: Index<Cell<Type>> = Index::new(0);
pub const EMPTY_TAG_UNION: Index<Cell<Type>> = Index::new(1);
pub const STR: Index<Cell<Type>> = Index::new(2);
pub const EMPTY_RECORD: Index<Cell<Index<TypeTag>>> = Index::new(0);
pub const EMPTY_TAG_UNION: Index<Cell<Index<TypeTag>>> = Index::new(1);
pub const STR: Index<Cell<Index<TypeTag>>> = Index::new(2);
pub const CATEGORY_RECORD: Index<Category> = Index::new(0);
pub const CATEGORY_FOREIGNCALL: Index<Category> = Index::new(1);
@ -170,18 +161,11 @@ impl Constraints {
pub const PCATEGORY_CHARACTER: Index<PatternCategory> = Index::new(10);
#[inline(always)]
pub fn push_type(&mut self, typ: Type) -> EitherIndex<Cell<Type>, Variable> {
match typ {
Type::EmptyRec => EitherIndex::from_left(Self::EMPTY_RECORD),
Type::EmptyTagUnion => EitherIndex::from_left(Self::EMPTY_TAG_UNION),
Type::Apply(Symbol::STR_STR, args, _) if args.is_empty() => {
EitherIndex::from_left(Self::STR)
}
Type::Variable(var) => Self::push_type_variable(var),
other => {
let index: Index<Cell<Type>> = Index::push_new(&mut self.types, Cell::new(other));
EitherIndex::from_left(index)
}
pub fn push_type(&mut self, types: &Types, typ: Index<TypeTag>) -> TypeOrVar {
if let TypeTag::Variable(var) = types[typ] {
Self::push_type_variable(var)
} else {
EitherIndex::from_left(typ)
}
}
@ -193,7 +177,6 @@ impl Constraints {
writeln!(buf, "Constraints statistics for module {:?}:", module_id)?;
writeln!(buf, " constraints length: {}:", self.constraints.len())?;
writeln!(buf, " types length: {}:", self.types.len())?;
writeln!(
buf,
" let_constraints length: {}:",
@ -205,6 +188,11 @@ impl Constraints {
Ok(buf)
}
#[inline(always)]
pub const fn push_variable(&self, var: Variable) -> TypeOrVar {
Self::push_type_variable(var)
}
#[inline(always)]
const fn push_type_variable(var: Variable) -> TypeOrVar {
// that's right, we use the variable's integer value as the index

View file

@ -2236,7 +2236,7 @@ fn canonicalize_pending_body<'a>(
ident: defined_symbol,
..
},
ast::Expr::AccessorFunction(field),
ast::Expr::RecordAccessorFunction(field),
) => {
let (loc_can_expr, can_output) = (
Loc::at(

View file

@ -596,6 +596,9 @@ pub fn canonicalize_expr<'a>(
}
}
}
ast::Expr::Tuple(_fields) => {
todo!("canonicalize tuple");
}
ast::Expr::RecordUpdate {
fields,
update: loc_update,
@ -918,7 +921,7 @@ pub fn canonicalize_expr<'a>(
(expr, output)
}
ast::Expr::Access(record_expr, field) => {
ast::Expr::RecordAccess(record_expr, field) => {
let (loc_expr, output) = canonicalize_expr(env, var_store, scope, region, record_expr);
(
@ -932,7 +935,7 @@ pub fn canonicalize_expr<'a>(
output,
)
}
ast::Expr::AccessorFunction(field) => (
ast::Expr::RecordAccessorFunction(field) => (
Accessor(AccessorData {
name: scope.gen_unique_symbol(),
function_var: var_store.fresh(),
@ -944,6 +947,8 @@ pub fn canonicalize_expr<'a>(
}),
Output::default(),
),
ast::Expr::TupleAccess(_record_expr, _field) => todo!("handle TupleAccess"),
ast::Expr::TupleAccessorFunction(_) => todo!("handle TupleAccessorFunction"),
ast::Expr::Tag(tag) => {
let variant_var = var_store.fresh();
let ext_var = var_store.fresh();
@ -2065,7 +2070,7 @@ fn flatten_str_literal<'a>(
pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
match expr {
ast::Expr::Var { .. } => true,
ast::Expr::Access(sub_expr, _) => is_valid_interpolation(sub_expr),
ast::Expr::RecordAccess(sub_expr, _) => is_valid_interpolation(sub_expr),
_ => false,
}
}

View file

@ -120,7 +120,8 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc<Expr<'a>>) -> &'a Loc
| NonBase10Int { .. }
| Str(_)
| SingleQuote(_)
| AccessorFunction(_)
| RecordAccessorFunction(_)
| TupleAccessorFunction(_)
| Var { .. }
| Underscore { .. }
| MalformedIdent(_, _)
@ -129,13 +130,14 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc<Expr<'a>>) -> &'a Loc
| Tag(_)
| OpaqueRef(_) => loc_expr,
Access(sub_expr, paths) => {
TupleAccess(_sub_expr, _paths) => todo!("Handle TupleAccess"),
RecordAccess(sub_expr, paths) => {
let region = loc_expr.region;
let loc_sub_expr = Loc {
region,
value: **sub_expr,
};
let value = Access(&desugar_expr(arena, arena.alloc(loc_sub_expr)).value, paths);
let value = RecordAccess(&desugar_expr(arena, arena.alloc(loc_sub_expr)).value, paths);
arena.alloc(Loc { region, value })
}
@ -163,7 +165,9 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc<Expr<'a>>) -> &'a Loc
}
})),
}),
Tuple(_fields) => {
todo!("desugar_expr: Tuple");
}
RecordUpdate { fields, update } => {
// NOTE the `update` field is always a `Var { .. }`, we only desugar it to get rid of
// any spaces before/after

View file

@ -529,6 +529,11 @@ pub fn canonicalize_pattern<'a>(
permit_shadows,
)
}
Tuple(_patterns) => {
todo!("canonicalize_pattern: Tuple")
}
RecordDestructure(patterns) => {
let ext_var = var_store.fresh();
let whole_var = var_store.fresh();

View file

@ -7,10 +7,10 @@ edition = "2021"
description = "Domain-specific collections created for the needs of the compiler."
[dependencies]
fnv = "1.0.7"
im = "15.0.0"
im-rc = "15.0.0"
wyhash = "0.5.0"
bumpalo = { version = "3.11.0", features = ["collections"] }
hashbrown = { version = "0.12.3", features = [ "bumpalo" ] }
bitvec = "1"
fnv.workspace = true
im.workspace = true
im-rc.workspace = true
wyhash.workspace = true
bumpalo.workspace = true
hashbrown.workspace = true
bitvec.workspace = true

View file

@ -88,15 +88,15 @@ impl<T> std::fmt::Debug for Slice<T> {
impl<T> Default for Slice<T> {
fn default() -> Self {
Self {
start: Default::default(),
length: Default::default(),
_marker: Default::default(),
}
Self::empty()
}
}
impl<T> Slice<T> {
pub const fn empty() -> Self {
Self::new(0, 0)
}
pub const fn new(start: u32, length: u16) -> Self {
Self {
start,

View file

@ -1,3 +1,5 @@
#![allow(clippy::too_many_arguments)]
use arrayvec::ArrayVec;
use roc_can::constraint::{Constraint, Constraints, ExpectedTypeIndex};
use roc_can::expected::Expected::{self, *};
@ -7,11 +9,12 @@ use roc_region::all::{Loc, Region};
use roc_types::num::{NumericRange, SingleQuoteBound};
use roc_types::subs::Variable;
use roc_types::types::Type::{self, *};
use roc_types::types::{AliasKind, Category};
use roc_types::types::{AliasKind, Category, Types};
use roc_types::types::{OptAbleType, Reason};
#[inline(always)]
pub fn add_numeric_bound_constr(
pub(crate) fn add_numeric_bound_constr(
types: &mut Types,
constraints: &mut Constraints,
num_constraints: &mut impl Extend<Constraint>,
num_var: Variable,
@ -30,9 +33,9 @@ pub fn add_numeric_bound_constr(
num_num(Variable(num_var))
}
NumericBound::FloatExact(width) => {
let actual_type = constraints.push_type(Variable(float_width_to_variable(width)));
let actual_type = constraints.push_variable(float_width_to_variable(width));
let expected = Expected::ForReason(Reason::NumericLiteralSuffix, actual_type, region);
let type_index = constraints.push_type(Variable(num_var));
let type_index = constraints.push_variable(num_var);
let expected_index = constraints.push_expected_type(expected);
let because_suffix =
constraints.equal_types(type_index, expected_index, category, region);
@ -42,9 +45,9 @@ pub fn add_numeric_bound_constr(
Variable(num_var)
}
NumericBound::IntExact(width) => {
let actual_type = constraints.push_type(Variable(int_lit_width_to_variable(width)));
let actual_type = constraints.push_variable(int_lit_width_to_variable(width));
let expected = Expected::ForReason(Reason::NumericLiteralSuffix, actual_type, region);
let type_index = constraints.push_type(Variable(num_var));
let type_index = constraints.push_variable(num_var);
let expected_index = constraints.push_expected_type(expected);
let because_suffix =
constraints.equal_types(type_index, expected_index, category, region);
@ -54,8 +57,11 @@ pub fn add_numeric_bound_constr(
Variable(num_var)
}
NumericBound::Range(range) => {
let precision_type = constraints.push_type(Variable(precision_var));
let expected = Expected::NoExpectation(constraints.push_type(RangedNumber(range)));
let precision_type = constraints.push_variable(precision_var);
let expected = {
let typ = types.from_old_type(&RangedNumber(range));
Expected::NoExpectation(constraints.push_type(types, typ))
};
let expected_index = constraints.push_expected_type(expected);
let constr = constraints.equal_types(precision_type, expected_index, category, region);
@ -67,7 +73,8 @@ pub fn add_numeric_bound_constr(
}
#[inline(always)]
pub fn int_literal(
pub(crate) fn int_literal(
types: &mut Types,
constraints: &mut Constraints,
num_var: Variable,
precision_var: Variable,
@ -80,6 +87,7 @@ pub fn int_literal(
// Always add the bound first; this improves the resolved type quality in case it's an alias like "U8".
let mut constrs = ArrayVec::<_, 3>::new();
let num_type = add_numeric_bound_constr(
types,
constraints,
&mut constrs,
num_var,
@ -89,8 +97,14 @@ pub fn int_literal(
Category::Num,
);
let num_type_index = constraints.push_type(num_type);
let int_precision_type = constraints.push_type(num_int(Type::Variable(precision_var)));
let num_type_index = {
let typ = types.from_old_type(&num_type);
constraints.push_type(types, typ)
};
let int_precision_type = {
let typ = types.from_old_type(&num_int(Type::Variable(precision_var)));
constraints.push_type(types, typ)
};
let expect_precision_var =
constraints.push_expected_type(ForReason(reason, int_precision_type, region));
@ -105,7 +119,8 @@ pub fn int_literal(
constraints.exists([num_var], and_constraint)
}
pub fn single_quote_literal(
pub(crate) fn single_quote_literal(
types: &mut Types,
constraints: &mut Constraints,
num_var: Variable,
precision_var: Variable,
@ -118,6 +133,7 @@ pub fn single_quote_literal(
// Always add the bound first; this improves the resolved type quality in case it's an alias like "U8".
let mut constrs = ArrayVec::<_, 3>::new();
let num_type = add_numeric_bound_constr(
types,
constraints,
&mut constrs,
num_var,
@ -127,8 +143,14 @@ pub fn single_quote_literal(
Category::Character,
);
let num_type_index = constraints.push_type(num_type);
let int_precision_type = constraints.push_type(num_int(Type::Variable(precision_var)));
let num_type_index = {
let typ = types.from_old_type(&num_type);
constraints.push_type(types, typ)
};
let int_precision_type = {
let typ = types.from_old_type(&num_int(Type::Variable(precision_var)));
constraints.push_type(types, typ)
};
let expect_precision_var =
constraints.push_expected_type(ForReason(reason, int_precision_type, region));
@ -148,7 +170,8 @@ pub fn single_quote_literal(
}
#[inline(always)]
pub fn float_literal(
pub(crate) fn float_literal(
types: &mut Types,
constraints: &mut Constraints,
num_var: Variable,
precision_var: Variable,
@ -160,6 +183,7 @@ pub fn float_literal(
let mut constrs = ArrayVec::<_, 3>::new();
let num_type = add_numeric_bound_constr(
types,
constraints,
&mut constrs,
num_var,
@ -169,8 +193,14 @@ pub fn float_literal(
Category::Frac,
);
let num_type_index = constraints.push_type(num_type);
let float_precision_type = constraints.push_type(num_float(Type::Variable(precision_var)));
let num_type_index = {
let typ = types.from_old_type(&num_type);
constraints.push_type(types, typ)
};
let float_precision_type = {
let typ = types.from_old_type(&num_float(Type::Variable(precision_var)));
constraints.push_type(types, typ)
};
let expect_precision_var =
constraints.push_expected_type(ForReason(reason, float_precision_type, region));
@ -185,7 +215,8 @@ pub fn float_literal(
}
#[inline(always)]
pub fn num_literal(
pub(crate) fn num_literal(
types: &mut Types,
constraints: &mut Constraints,
num_var: Variable,
expected: ExpectedTypeIndex,
@ -194,6 +225,7 @@ pub fn num_literal(
) -> Constraint {
let mut constrs = ArrayVec::<_, 2>::new();
let num_type = add_numeric_bound_constr(
types,
constraints,
&mut constrs,
num_var,
@ -203,7 +235,10 @@ pub fn num_literal(
Category::Num,
);
let type_index = constraints.push_type(num_type);
let type_index = {
let typ = types.from_old_type(&num_type);
constraints.push_type(types, typ)
};
constrs.extend([constraints.equal_types(type_index, expected, Category::Num, region)]);
let and_constraint = constraints.and_constraint(constrs);
@ -214,7 +249,7 @@ pub fn num_literal(
// Inlining these tiny leaf functions can lead to death by a thousand cuts,
// where we end up with huge stack frames in non-tail-recursive functions.
#[cfg_attr(not(debug_assertions), inline(always))]
pub fn builtin_type(symbol: Symbol, args: Vec<Type>) -> Type {
pub(crate) fn builtin_type(symbol: Symbol, args: Vec<Type>) -> Type {
Type::Apply(
symbol,
args.into_iter().map(Loc::at_zero).collect(),
@ -223,20 +258,15 @@ pub fn builtin_type(symbol: Symbol, args: Vec<Type>) -> Type {
}
#[cfg_attr(not(debug_assertions), inline(always))]
pub fn empty_list_type(var: Variable) -> Type {
pub(crate) fn empty_list_type(var: Variable) -> Type {
list_type(Type::Variable(var))
}
#[cfg_attr(not(debug_assertions), inline(always))]
pub fn list_type(typ: Type) -> Type {
pub(crate) fn list_type(typ: Type) -> Type {
builtin_type(Symbol::LIST_LIST, vec![typ])
}
#[cfg_attr(not(debug_assertions), inline(always))]
pub fn str_type() -> Type {
builtin_type(Symbol::STR_STR, Vec::new())
}
#[cfg_attr(not(debug_assertions), inline(always))]
fn builtin_num_alias(
symbol: Symbol,
@ -255,7 +285,7 @@ fn builtin_num_alias(
}
#[cfg_attr(not(debug_assertions), inline(always))]
pub fn num_float(range: Type) -> Type {
pub(crate) fn num_float(range: Type) -> Type {
builtin_num_alias(
Symbol::NUM_FRAC,
vec![OptAbleType::unbound(range.clone())],
@ -265,7 +295,7 @@ pub fn num_float(range: Type) -> Type {
}
#[cfg_attr(not(debug_assertions), inline(always))]
pub fn num_floatingpoint(range: Type) -> Type {
pub(crate) fn num_floatingpoint(range: Type) -> Type {
builtin_num_alias(
Symbol::NUM_FLOATINGPOINT,
vec![OptAbleType::unbound(range.clone())],
@ -275,37 +305,7 @@ pub fn num_floatingpoint(range: Type) -> Type {
}
#[cfg_attr(not(debug_assertions), inline(always))]
pub fn num_u32() -> Type {
builtin_num_alias(
Symbol::NUM_U32,
vec![],
Box::new(num_int(num_unsigned32())),
AliasKind::Structural,
)
}
#[cfg_attr(not(debug_assertions), inline(always))]
fn num_unsigned32() -> Type {
builtin_num_alias(
Symbol::NUM_UNSIGNED32,
vec![],
Box::new(Type::EmptyTagUnion),
AliasKind::Opaque,
)
}
#[cfg_attr(not(debug_assertions), inline(always))]
pub fn num_binary64() -> Type {
builtin_num_alias(
Symbol::NUM_BINARY64,
vec![],
Box::new(Type::EmptyTagUnion),
AliasKind::Opaque,
)
}
#[cfg_attr(not(debug_assertions), inline(always))]
pub fn num_int(range: Type) -> Type {
pub(crate) fn num_int(range: Type) -> Type {
builtin_num_alias(
Symbol::NUM_INT,
vec![OptAbleType::unbound(range.clone())],
@ -315,17 +315,7 @@ pub fn num_int(range: Type) -> Type {
}
#[cfg_attr(not(debug_assertions), inline(always))]
pub fn num_signed64() -> Type {
builtin_num_alias(
Symbol::NUM_SIGNED64,
vec![],
Box::new(Type::EmptyTagUnion),
AliasKind::Opaque,
)
}
#[cfg_attr(not(debug_assertions), inline(always))]
pub fn num_integer(range: Type) -> Type {
pub(crate) fn num_integer(range: Type) -> Type {
builtin_num_alias(
Symbol::NUM_INTEGER,
vec![OptAbleType::unbound(range.clone())],
@ -335,7 +325,7 @@ pub fn num_integer(range: Type) -> Type {
}
#[cfg_attr(not(debug_assertions), inline(always))]
pub fn num_num(typ: Type) -> Type {
pub(crate) fn num_num(typ: Type) -> Type {
builtin_num_alias(
Symbol::NUM_NUM,
vec![OptAbleType::unbound(typ.clone())],

File diff suppressed because it is too large Load diff

View file

@ -6,19 +6,26 @@ use roc_can::expr::Declarations;
use roc_can::pattern::Pattern;
use roc_module::symbol::{ModuleId, Symbol};
use roc_region::all::{Loc, Region};
use roc_types::types::{AnnotationSource, Category, Type};
use roc_types::types::{AnnotationSource, Category, Type, Types};
pub fn constrain_module(
types: &mut Types,
constraints: &mut Constraints,
symbols_from_requires: Vec<(Loc<Symbol>, Loc<Type>)>,
abilities_store: &PendingAbilitiesStore,
declarations: &Declarations,
home: ModuleId,
) -> Constraint {
let constraint = crate::expr::constrain_decls(constraints, home, declarations);
let constraint = crate::expr::constrain_decls(types, constraints, home, declarations);
let constraint = constrain_symbols_from_requires(
types,
constraints,
symbols_from_requires,
home,
constraint,
);
let constraint =
constrain_symbols_from_requires(constraints, symbols_from_requires, home, constraint);
let constraint = frontload_ability_constraints(constraints, abilities_store, home, constraint);
frontload_ability_constraints(types, constraints, abilities_store, home, constraint);
// The module constraint should always save the environment at the end.
debug_assert!(constraints.contains_save_the_environment(&constraint));
@ -27,6 +34,7 @@ pub fn constrain_module(
}
fn constrain_symbols_from_requires(
types: &mut Types,
constraints: &mut Constraints,
symbols_from_requires: Vec<(Loc<Symbol>, Loc<Type>)>,
home: ModuleId,
@ -50,9 +58,12 @@ fn constrain_symbols_from_requires(
};
let pattern = Loc::at_zero(roc_can::pattern::Pattern::Identifier(loc_symbol.value));
let type_index = constraints.push_type(loc_type.value);
let type_index = {
let typ = types.from_old_type(&loc_type.value);
constraints.push_type(types, typ)
};
let def_pattern_state =
constrain_def_pattern(constraints, &mut env, &pattern, type_index);
constrain_def_pattern(types, constraints, &mut env, &pattern, type_index);
debug_assert!(env.resolutions_to_make.is_empty());
@ -71,7 +82,10 @@ fn constrain_symbols_from_requires(
// provided by the app is in fact what the package module requires.
let arity = loc_type.value.arity();
let typ = loc_type.value;
let type_index = constraints.push_type(typ);
let type_index = {
let typ = types.from_old_type(&typ);
constraints.push_type(types, typ)
};
let expected = constraints.push_expected_type(Expected::FromAnnotation(
loc_symbol.map(|&s| Pattern::Identifier(s)),
arity,
@ -88,6 +102,7 @@ fn constrain_symbols_from_requires(
}
pub fn frontload_ability_constraints(
types: &mut Types,
constraints: &mut Constraints,
abilities_store: &PendingAbilitiesStore,
home: ModuleId,
@ -109,10 +124,13 @@ pub fn frontload_ability_constraints(
};
let pattern = Loc::at_zero(roc_can::pattern::Pattern::Identifier(*member_name));
let signature_index = constraints.push_type(signature.clone());
let signature_index = {
let typ = types.from_old_type(&signature.clone());
constraints.push_type(types, typ)
};
let mut def_pattern_state =
constrain_def_pattern(constraints, &mut env, &pattern, signature_index);
constrain_def_pattern(types, constraints, &mut env, &pattern, signature_index);
debug_assert!(env.resolutions_to_make.is_empty());

View file

@ -12,7 +12,7 @@ use roc_region::all::{Loc, Region};
use roc_types::subs::Variable;
use roc_types::types::{
AliasKind, Category, OptAbleType, PReason, PatternCategory, Reason, RecordField, Type,
TypeExtension,
TypeExtension, TypeTag, Types,
};
#[derive(Default, Debug)]
@ -31,6 +31,7 @@ pub struct PatternState {
/// Would add `x => <42>` to the headers (i.e., symbol points to a type variable). If the
/// definition has an annotation, we instead now add `x => Int`.
pub fn headers_from_annotation(
types: &mut Types,
constraints: &mut Constraints,
pattern: &Pattern,
annotation: &Loc<&Type>,
@ -40,7 +41,7 @@ pub fn headers_from_annotation(
// in such incorrect cases we don't put the full annotation in headers, just a variable, and let
// inference generate a proper error.
let is_structurally_valid =
headers_from_annotation_help(constraints, pattern, annotation, &mut headers);
headers_from_annotation_help(types, constraints, pattern, annotation, &mut headers);
if is_structurally_valid {
Some(headers)
@ -50,6 +51,7 @@ pub fn headers_from_annotation(
}
fn headers_from_annotation_help(
types: &mut Types,
constraints: &mut Constraints,
pattern: &Pattern,
annotation: &Loc<&Type>,
@ -63,7 +65,7 @@ fn headers_from_annotation_help(
ident: symbol,
specializes: _,
} => {
let annotation_index = constraints.push_type(annotation.value.clone());
let annotation_index = { let typ = types.from_old_type(annotation.value); constraints.push_type(types, typ) };
let typ = Loc::at(annotation.region, annotation_index);
headers.insert(*symbol, typ);
true
@ -91,7 +93,7 @@ fn headers_from_annotation_help(
// `{ x ? 0 } = rec` or `{ x: 5 } -> ...` in all cases
// the type of `x` within the binding itself is the same.
if let Some(field_type) = fields.get(&destruct.label) {
let field_type_index = constraints.push_type(field_type.as_inner().clone());
let field_type_index = { let typ = types.from_old_type(&field_type.as_inner().clone()); constraints.push_type(types, typ) };
headers.insert(
destruct.symbol,
Loc::at(annotation.region, field_type_index),
@ -130,6 +132,7 @@ fn headers_from_annotation_help(
.zip(arg_types.iter())
.all(|(arg_pattern, arg_type)| {
headers_from_annotation_help(
types,
constraints,
&arg_pattern.1.value,
&Loc::at(annotation.region, arg_type),
@ -162,13 +165,14 @@ fn headers_from_annotation_help(
&& type_arguments.len() == pat_type_arguments.len()
&& lambda_set_variables.len() == pat_lambda_set_variables.len() =>
{
let annotation_index = constraints.push_type(annotation.value.clone());
let annotation_index = { let typ = types.from_old_type(annotation.value); constraints.push_type(types, typ) };
let typ = Loc::at(annotation.region, annotation_index);
headers.insert(*opaque, typ);
let (_, argument_pat) = &**argument;
headers_from_annotation_help(
constraints,
types,
constraints,
&argument_pat.value,
&Loc::at(annotation.region, actual),
headers,
@ -183,6 +187,7 @@ fn headers_from_annotation_help(
/// initialize the Vecs in PatternState using with_capacity
/// based on its knowledge of their lengths.
pub fn constrain_pattern(
types: &mut Types,
constraints: &mut Constraints,
env: &mut Env,
pattern: &Pattern,
@ -199,7 +204,7 @@ pub fn constrain_pattern(
// _ -> ""
// so, we know that "x" (in this case, a tag union) must be open.
let expected_type = *constraints[expected].get_type_ref();
if could_be_a_tag_union(constraints, expected_type) {
if could_be_a_tag_union(types, expected_type) {
state
.delayed_is_open_constraints
.push(constraints.is_open_type(expected_type));
@ -213,7 +218,7 @@ pub fn constrain_pattern(
let expected = &constraints[expected];
let type_index = *expected.get_type_ref();
if could_be_a_tag_union(constraints, type_index) {
if could_be_a_tag_union(types, type_index) {
state
.delayed_is_open_constraints
.push(constraints.is_open_type(type_index));
@ -235,7 +240,7 @@ pub fn constrain_pattern(
let expected = &constraints[expected];
let type_index = *expected.get_type_ref();
if could_be_a_tag_union(constraints, type_index) {
if could_be_a_tag_union(types, type_index) {
state.constraints.push(constraints.is_open_type(type_index));
}
@ -252,6 +257,7 @@ pub fn constrain_pattern(
state.vars.push(precision_var);
let num_type = builtins::add_numeric_bound_constr(
types,
constraints,
&mut state.constraints,
precision_var,
@ -260,7 +266,10 @@ pub fn constrain_pattern(
region,
Category::Num,
);
let num_type = constraints.push_type(num_type);
let num_type = {
let typ = types.from_old_type(&num_type);
constraints.push_type(types, typ)
};
state.constraints.push(constraints.equal_pattern_types(
num_type,
@ -274,6 +283,7 @@ pub fn constrain_pattern(
// First constraint on the free num var; this improves the resolved type quality in
// case the bound is an alias.
let num_type = builtins::add_numeric_bound_constr(
types,
constraints,
&mut state.constraints,
num_precision_var,
@ -282,10 +292,16 @@ pub fn constrain_pattern(
region,
Category::Int,
);
let num_type = constraints.push_type(num_type);
let num_type = {
let typ = types.from_old_type(&num_type);
constraints.push_type(types, typ)
};
// Link the free num var with the int var and our expectation.
let int_type = constraints.push_type(builtins::num_int(Type::Variable(precision_var)));
let int_type = {
let typ = types.from_old_type(&builtins::num_int(Type::Variable(precision_var)));
constraints.push_type(types, typ)
};
state.constraints.push({
let expected_index =
@ -306,6 +322,7 @@ pub fn constrain_pattern(
// First constraint on the free num var; this improves the resolved type quality in
// case the bound is an alias.
let num_type = builtins::add_numeric_bound_constr(
types,
constraints,
&mut state.constraints,
num_precision_var,
@ -314,11 +331,16 @@ pub fn constrain_pattern(
region,
Category::Frac,
);
let num_type_index = constraints.push_type(num_type); // TODO check me if something breaks!
let num_type_index = {
let typ = types.from_old_type(&num_type);
constraints.push_type(types, typ)
}; // NOTE: check me if something breaks!
// Link the free num var with the float var and our expectation.
let float_type =
constraints.push_type(builtins::num_float(Type::Variable(precision_var)));
let float_type = {
let typ = types.from_old_type(&builtins::num_float(Type::Variable(precision_var)));
constraints.push_type(types, typ)
};
state.constraints.push({
let expected_index =
@ -336,7 +358,7 @@ pub fn constrain_pattern(
}
StrLiteral(_) => {
let str_type = constraints.push_type(builtins::str_type());
let str_type = constraints.push_type(types, Types::STR);
state.constraints.push(constraints.equal_pattern_types(
str_type,
expected,
@ -349,6 +371,7 @@ pub fn constrain_pattern(
// First constraint on the free num var; this improves the resolved type quality in
// case the bound is an alias.
let num_type = builtins::add_numeric_bound_constr(
types,
constraints,
&mut state.constraints,
num_var,
@ -358,10 +381,16 @@ pub fn constrain_pattern(
Category::Int,
);
let num_type_index = constraints.push_type(num_type);
let num_type_index = {
let typ = types.from_old_type(&num_type);
constraints.push_type(types, typ)
};
// Link the free num var with the int var and our expectation.
let int_type = constraints.push_type(builtins::num_int(Type::Variable(precision_var)));
let int_type = {
let typ = types.from_old_type(&builtins::num_int(Type::Variable(precision_var)));
constraints.push_type(types, typ)
};
state.constraints.push({
let expected_index =
@ -406,7 +435,7 @@ pub fn constrain_pattern(
} in destructs
{
let pat_type = Type::Variable(*var);
let pat_type_index = constraints.push_type(pat_type.clone());
let pat_type_index = constraints.push_variable(*var);
let expected =
constraints.push_pat_expected_type(PExpected::NoExpectation(pat_type_index));
@ -418,7 +447,7 @@ pub fn constrain_pattern(
let field_type = match typ {
DestructType::Guard(guard_var, loc_guard) => {
let guard_type = constraints.push_type(Type::Variable(*guard_var));
let guard_type = constraints.push_variable(*guard_var);
let expected_pat =
constraints.push_pat_expected_type(PExpected::ForReason(
PReason::PatternGuard,
@ -435,6 +464,7 @@ pub fn constrain_pattern(
state.vars.push(*guard_var);
constrain_pattern(
types,
constraints,
env,
&loc_guard.value,
@ -446,7 +476,7 @@ pub fn constrain_pattern(
RecordField::Demanded(pat_type)
}
DestructType::Optional(expr_var, loc_expr) => {
let expr_type = constraints.push_type(Type::Variable(*expr_var));
let expr_type = constraints.push_variable(*expr_var);
let expected_pat =
constraints.push_pat_expected_type(PExpected::ForReason(
PReason::OptionalField,
@ -470,6 +500,7 @@ pub fn constrain_pattern(
));
let expr_con = constrain_expr(
types,
constraints,
env,
loc_expr.region,
@ -491,12 +522,15 @@ pub fn constrain_pattern(
state.vars.push(*var);
}
let record_type = constraints.push_type(Type::Record(
field_types,
TypeExtension::from_type(ext_type),
));
let record_type = {
let typ = types.from_old_type(&Type::Record(
field_types,
TypeExtension::from_type(ext_type),
));
constraints.push_type(types, typ)
};
let whole_var_index = constraints.push_type(Type::Variable(*whole_var));
let whole_var_index = constraints.push_variable(*whole_var);
let expected_record =
constraints.push_expected_type(Expected::NoExpectation(record_type));
let whole_con = constraints.equal_types(
@ -526,7 +560,7 @@ pub fn constrain_pattern(
opt_rest: _,
},
} => {
let elem_var_index = constraints.push_type(Type::Variable(*elem_var));
let elem_var_index = constraints.push_variable(*elem_var);
for loc_pat in patterns.iter() {
let expected = constraints.push_pat_expected_type(PExpected::ForReason(
@ -536,6 +570,7 @@ pub fn constrain_pattern(
));
constrain_pattern(
types,
constraints,
env,
&loc_pat.value,
@ -545,12 +580,15 @@ pub fn constrain_pattern(
);
}
let list_var_index = constraints.push_type(Type::Variable(*list_var));
let solved_list = constraints.push_type(Type::Apply(
Symbol::LIST_LIST,
vec![Loc::at(region, Type::Variable(*elem_var))],
region,
));
let list_var_index = constraints.push_variable(*list_var);
let solved_list = {
let typ = types.from_old_type(&Type::Apply(
Symbol::LIST_LIST,
vec![Loc::at(region, Type::Variable(*elem_var))],
region,
));
constraints.push_type(types, typ)
};
let store_solved_list = constraints.store(solved_list, *list_var, file!(), line!());
let expected_constraint = constraints.pattern_presence(
@ -577,7 +615,7 @@ pub fn constrain_pattern(
for (index, (pattern_var, loc_pattern)) in arguments.iter().enumerate() {
state.vars.push(*pattern_var);
let pattern_type = constraints.push_type(Type::Variable(*pattern_var));
let pattern_type = constraints.push_variable(*pattern_var);
let expected = constraints.push_pat_expected_type(PExpected::ForReason(
PReason::TagArg {
@ -588,6 +626,7 @@ pub fn constrain_pattern(
region,
));
constrain_pattern(
types,
constraints,
env,
&loc_pattern.value,
@ -608,7 +647,7 @@ pub fn constrain_pattern(
region,
);
let whole_type = constraints.push_type(Type::Variable(*whole_var));
let whole_type = constraints.push_variable(*whole_var);
let tag_con = constraints.pattern_presence(whole_type, expected, pat_category, region);
@ -628,28 +667,31 @@ pub fn constrain_pattern(
} => {
// Suppose we are constraining the pattern \@Id who, where Id n := [Id U64 n]
let (arg_pattern_var, loc_arg_pattern) = &**argument;
let arg_pattern_type = Type::Variable(*arg_pattern_var);
let arg_pattern_type_index = constraints.push_type(Type::Variable(*arg_pattern_var));
let arg_pattern_type_index = constraints.push_variable(*arg_pattern_var);
let opaque_type = constraints.push_type(Type::Alias {
symbol: *opaque,
type_arguments: type_arguments
.iter()
.map(|v| OptAbleType {
typ: Type::Variable(v.var),
opt_abilities: v.opt_abilities.clone(),
})
.collect(),
lambda_set_variables: lambda_set_variables.clone(),
infer_ext_in_output_types: vec![],
actual: Box::new(arg_pattern_type.clone()),
kind: AliasKind::Opaque,
});
let opaque_type = {
let typ = types.from_old_type(&Type::Alias {
symbol: *opaque,
type_arguments: type_arguments
.iter()
.map(|v| OptAbleType {
typ: Type::Variable(v.var),
opt_abilities: v.opt_abilities.clone(),
})
.collect(),
lambda_set_variables: lambda_set_variables.clone(),
infer_ext_in_output_types: vec![],
actual: Box::new(Type::Variable(*arg_pattern_var)),
kind: AliasKind::Opaque,
});
constraints.push_type(types, typ)
};
// First, add a constraint for the argument "who"
let arg_pattern_expected = constraints
.push_pat_expected_type(PExpected::NoExpectation(arg_pattern_type_index));
constrain_pattern(
types,
constraints,
env,
&loc_arg_pattern.value,
@ -659,7 +701,7 @@ pub fn constrain_pattern(
);
// Next, link `whole_var` to the opaque type of "@Id who"
let whole_var_index = constraints.push_type(Type::Variable(*whole_var));
let whole_var_index = constraints.push_variable(*whole_var);
let expected_opaque =
constraints.push_expected_type(Expected::NoExpectation(opaque_type));
let whole_con = constraints.equal_types(
@ -682,8 +724,11 @@ pub fn constrain_pattern(
// This must **always** be a presence constraint, that is enforcing
// `[A k1, B k1] += typeof (A s)`, because we are in a destructure position and not
// all constructors are covered in this branch!
let arg_pattern_type = constraints.push_type(arg_pattern_type);
let specialized_type_index = constraints.push_type((**specialized_def_type).clone());
let arg_pattern_type = constraints.push_variable(*arg_pattern_var);
let specialized_type_index = {
let typ = types.from_old_type(&(**specialized_def_type));
constraints.push_type(types, typ)
};
let specialized_type_expected = constraints
.push_pat_expected_type(PExpected::NoExpectation(specialized_type_index));
@ -695,7 +740,7 @@ pub fn constrain_pattern(
);
// Next, link `whole_var` (the type of "@Id who") to the expected type
let whole_type = constraints.push_type(Type::Variable(*whole_var));
let whole_type = constraints.push_variable(*whole_var);
let opaque_pattern_con = constraints.pattern_presence(
whole_type,
expected,
@ -721,15 +766,12 @@ pub fn constrain_pattern(
}
}
fn could_be_a_tag_union(constraints: &mut Constraints, typ: TypeOrVar) -> bool {
fn could_be_a_tag_union(types: &Types, typ: TypeOrVar) -> bool {
match typ.split() {
Ok(typ_index) => {
let typ_cell = &mut constraints.types[typ_index.index()];
!matches!(
typ_cell.get_mut(),
Type::Apply(..) | Type::Function(..) | Type::Record(..)
)
}
Ok(typ_index) => !matches!(
types[typ_index],
TypeTag::Apply { .. } | TypeTag::Function(..) | TypeTag::Record(..)
),
Err(_) => {
// Variables are opaque at this point, assume yes
true

View file

@ -15,7 +15,7 @@ roc_module = { path = "../module" }
roc_types = { path = "../types" }
roc_can = { path = "../can" }
roc_unify = { path = "../unify" }
bumpalo = { version = "3.8.0", features = ["collections"] }
bumpalo.workspace = true
[features]
default = []

View file

@ -11,10 +11,11 @@ roc_collections = { path = "../collections" }
roc_region = { path = "../region" }
roc_module = { path = "../module" }
roc_parse = { path = "../parse" }
bumpalo = { version = "3.11.0", features = ["collections"] }
bumpalo.workspace = true
[dev-dependencies]
pretty_assertions = "1.3.0"
indoc = "1.0.7"
roc_test_utils = { path = "../../test_utils" }
walkdir = "2.3.2"
pretty_assertions.workspace = true
indoc.workspace = true
walkdir.workspace = true

View file

@ -34,8 +34,10 @@ impl<'a> Formattable for Expr<'a> {
| Num(..)
| NonBase10Int { .. }
| SingleQuote(_)
| Access(_, _)
| AccessorFunction(_)
| RecordAccess(_, _)
| RecordAccessorFunction(_)
| TupleAccess(_, _)
| TupleAccessorFunction(_)
| Var { .. }
| Underscore { .. }
| MalformedIdent(_, _)
@ -106,6 +108,7 @@ impl<'a> Formattable for Expr<'a> {
}
Record(fields) => fields.iter().any(|loc_field| loc_field.is_multiline()),
Tuple(fields) => fields.iter().any(|loc_field| loc_field.is_multiline()),
RecordUpdate { fields, .. } => fields.iter().any(|loc_field| loc_field.is_multiline()),
}
}
@ -323,6 +326,9 @@ impl<'a> Formattable for Expr<'a> {
Record(fields) => {
fmt_record(buf, None, *fields, indent);
}
Tuple(_fields) => {
todo!("format tuple");
}
RecordUpdate { update, fields } => {
fmt_record(buf, Some(*update), *fields, indent);
}
@ -395,12 +401,22 @@ impl<'a> Formattable for Expr<'a> {
sub_expr.format_with_options(buf, Parens::InApply, newlines, indent);
}
AccessorFunction(key) => {
RecordAccessorFunction(key) => {
buf.indent(indent);
buf.push('.');
buf.push_str(key);
}
Access(expr, key) => {
RecordAccess(expr, key) => {
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
buf.push('.');
buf.push_str(key);
}
TupleAccessorFunction(key) => {
buf.indent(indent);
buf.push('.');
buf.push_str(key);
}
TupleAccess(expr, key) => {
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
buf.push('.');
buf.push_str(key);

View file

@ -43,7 +43,9 @@ impl<'a> Formattable for Pattern<'a> {
| Pattern::QualifiedIdentifier { .. }
| Pattern::ListRest => false,
Pattern::List(patterns) => patterns.iter().any(|p| p.is_multiline()),
Pattern::Tuple(patterns) | Pattern::List(patterns) => {
patterns.iter().any(|p| p.is_multiline())
}
}
}
@ -162,6 +164,22 @@ impl<'a> Formattable for Pattern<'a> {
buf.push('_');
buf.push_str(name);
}
Tuple(loc_patterns) => {
buf.indent(indent);
buf.push_str("(");
let mut it = loc_patterns.iter().peekable();
while let Some(loc_pattern) = it.next() {
loc_pattern.format(buf, indent);
if it.peek().is_some() {
buf.push_str(",");
buf.spaces(1);
}
}
buf.push_str(")");
}
List(loc_patterns) => {
buf.indent(indent);
buf.push_str("[");

View file

@ -640,14 +640,17 @@ impl<'a> RemoveSpaces<'a> for Expr<'a> {
is_negative,
},
Expr::Str(a) => Expr::Str(a.remove_spaces(arena)),
Expr::Access(a, b) => Expr::Access(arena.alloc(a.remove_spaces(arena)), b),
Expr::AccessorFunction(a) => Expr::AccessorFunction(a),
Expr::RecordAccess(a, b) => Expr::RecordAccess(arena.alloc(a.remove_spaces(arena)), b),
Expr::RecordAccessorFunction(a) => Expr::RecordAccessorFunction(a),
Expr::TupleAccess(a, b) => Expr::TupleAccess(arena.alloc(a.remove_spaces(arena)), b),
Expr::TupleAccessorFunction(a) => Expr::TupleAccessorFunction(a),
Expr::List(a) => Expr::List(a.remove_spaces(arena)),
Expr::RecordUpdate { update, fields } => Expr::RecordUpdate {
update: arena.alloc(update.remove_spaces(arena)),
fields: fields.remove_spaces(arena),
},
Expr::Record(a) => Expr::Record(a.remove_spaces(arena)),
Expr::Tuple(a) => Expr::Tuple(a.remove_spaces(arena)),
Expr::Var { module_name, ident } => Expr::Var { module_name, ident },
Expr::Underscore(a) => Expr::Underscore(a),
Expr::Tag(a) => Expr::Tag(a),
@ -750,6 +753,7 @@ impl<'a> RemoveSpaces<'a> for Pattern<'a> {
Pattern::SpaceAfter(a, _) => a.remove_spaces(arena),
Pattern::SingleQuote(a) => Pattern::SingleQuote(a),
Pattern::List(pats) => Pattern::List(pats.remove_spaces(arena)),
Pattern::Tuple(pats) => Pattern::Tuple(pats.remove_spaces(arena)),
Pattern::ListRest => Pattern::ListRest,
}
}

View file

@ -5134,7 +5134,7 @@ mod test_fmt {
r#"
Task.fromResult
(
a, b <- binaryOp ctx
b <- binaryOp ctx
if a == b then
-1
else
@ -5147,7 +5147,7 @@ mod test_fmt {
indoc!(
r#"
Task.fromResult
(a, b <- binaryOp ctx
(b <- binaryOp ctx
if a == b then
-1
else
@ -5159,7 +5159,7 @@ mod test_fmt {
r#"
Task.fromResult
(
a, b <- binaryOp ctx
b <- binaryOp ctx
if a == b then
-1
else
@ -5173,7 +5173,7 @@ mod test_fmt {
indoc!(
r#"
Task.fromResult
(a, b <- binaryOp ctx
(b <- binaryOp ctx
if a == b then
-1
else
@ -5184,7 +5184,7 @@ mod test_fmt {
r#"
Task.fromResult
(
a, b <- binaryOp ctx
b <- binaryOp ctx
if a == b then
-1
else

View file

@ -19,21 +19,19 @@ roc_solve = { path = "../solve" }
roc_mono = { path = "../mono" }
roc_target = { path = "../roc_target" }
roc_error_macros = { path = "../../error_macros" }
bumpalo = { version = "3.11.0", features = ["collections"] }
target-lexicon = "0.12.3"
# TODO: Deal with the update of object to 0.27.
# It looks like it breaks linking the generated objects.
# Probably just need to specify an extra field that used to be implicit or something.
# When fixed also update the version of object in the linker.
object = { version = "0.29.0", features = ["write"] }
packed_struct = "0.10.0"
bumpalo.workspace = true
target-lexicon.workspace = true
object.workspace = true
packed_struct.workspace = true
[dev-dependencies]
roc_can = { path = "../can" }
roc_parse = { path = "../parse" }
roc_std = { path = "../../roc_std" }
bumpalo = { version = "3.11.0", features = ["collections"] }
capstone = "0.11.0"
bumpalo.workspace = true
capstone.workspace = true
[features]
target-aarch64 = []

View file

@ -18,6 +18,7 @@ roc_std = { path = "../../roc_std" }
roc_debug_flags = { path = "../debug_flags" }
roc_region = { path = "../region" }
morphic_lib = { path = "../../vendor/morphic_lib" }
bumpalo = { version = "3.11.0", features = ["collections"] }
inkwell = { path = "../../vendor/inkwell" }
target-lexicon = "0.12.3"
bumpalo.workspace = true
target-lexicon.workspace = true
inkwell.workspace = true

File diff suppressed because it is too large Load diff

View file

@ -13,8 +13,9 @@ use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_module::symbol::Symbol;
use roc_mono::layout::{Builtin, Layout, LayoutIds, UnionLayout};
use super::build::{dec_binop_with_unchecked, load_roc_value, use_roc_value};
use super::build::{load_roc_value, use_roc_value};
use super::convert::argument_type_from_union_layout;
use super::lowlevel::dec_binop_with_unchecked;
#[derive(Clone, Debug)]
enum WhenRecursive<'a> {

View file

@ -7,7 +7,8 @@ use inkwell::values::BasicValue;
use inkwell::AddressSpace;
use roc_builtins::bitcode;
use super::build::{get_sjlj_buffer, LLVM_LONGJMP};
use super::build::get_sjlj_buffer;
use super::intrinsics::LLVM_LONGJMP;
/// Define functions for roc_alloc, roc_realloc, and roc_dealloc
/// which use libc implementations (malloc, realloc, and free)

View file

@ -0,0 +1,197 @@
use inkwell::{
context::Context,
module::{Linkage, Module},
types::FunctionType,
values::FunctionValue,
AddressSpace,
};
use roc_builtins::{
bitcode::{FloatWidth, IntWidth, IntrinsicName},
float_intrinsic, llvm_int_intrinsic,
};
use super::build::{add_func, FunctionSpec};
fn add_float_intrinsic<'ctx, F>(
ctx: &'ctx Context,
module: &Module<'ctx>,
name: &IntrinsicName,
construct_type: F,
) where
F: Fn(inkwell::types::FloatType<'ctx>) -> inkwell::types::FunctionType<'ctx>,
{
macro_rules! check {
($width:expr, $typ:expr) => {
let full_name = &name[$width];
if let Some(_) = module.get_function(full_name) {
// zig defined this function already
} else {
add_intrinsic(ctx, module, full_name, construct_type($typ));
}
};
}
check!(FloatWidth::F32, ctx.f32_type());
check!(FloatWidth::F64, ctx.f64_type());
// check!(IntWidth::F128, ctx.i128_type());
}
fn add_int_intrinsic<'ctx, F>(
ctx: &'ctx Context,
module: &Module<'ctx>,
name: &IntrinsicName,
construct_type: F,
) where
F: Fn(inkwell::types::IntType<'ctx>) -> inkwell::types::FunctionType<'ctx>,
{
macro_rules! check {
($width:expr, $typ:expr) => {
let full_name = &name[$width];
if let Some(_) = module.get_function(full_name) {
// zig defined this function already
} else {
add_intrinsic(ctx, module, full_name, construct_type($typ));
}
};
}
check!(IntWidth::U8, ctx.i8_type());
check!(IntWidth::U16, ctx.i16_type());
check!(IntWidth::U32, ctx.i32_type());
check!(IntWidth::U64, ctx.i64_type());
check!(IntWidth::U128, ctx.i128_type());
check!(IntWidth::I8, ctx.i8_type());
check!(IntWidth::I16, ctx.i16_type());
check!(IntWidth::I32, ctx.i32_type());
check!(IntWidth::I64, ctx.i64_type());
check!(IntWidth::I128, ctx.i128_type());
}
pub(crate) fn add_intrinsics<'ctx>(ctx: &'ctx Context, module: &Module<'ctx>) {
// List of all supported LLVM intrinsics:
//
// https://releases.llvm.org/10.0.0/docs/LangRef.html#standard-c-library-intrinsics
let i1_type = ctx.bool_type();
let i8_type = ctx.i8_type();
let i8_ptr_type = i8_type.ptr_type(AddressSpace::Generic);
let i32_type = ctx.i32_type();
let void_type = ctx.void_type();
if let Some(func) = module.get_function("__muloti4") {
func.set_linkage(Linkage::WeakAny);
}
add_intrinsic(
ctx,
module,
LLVM_SETJMP,
i32_type.fn_type(&[i8_ptr_type.into()], false),
);
add_intrinsic(
ctx,
module,
LLVM_LONGJMP,
void_type.fn_type(&[i8_ptr_type.into()], false),
);
add_intrinsic(
ctx,
module,
LLVM_FRAME_ADDRESS,
i8_ptr_type.fn_type(&[i32_type.into()], false),
);
add_intrinsic(
ctx,
module,
LLVM_STACK_SAVE,
i8_ptr_type.fn_type(&[], false),
);
add_float_intrinsic(ctx, module, &LLVM_LOG, |t| t.fn_type(&[t.into()], false));
add_float_intrinsic(ctx, module, &LLVM_POW, |t| {
t.fn_type(&[t.into(), t.into()], false)
});
add_float_intrinsic(ctx, module, &LLVM_FABS, |t| t.fn_type(&[t.into()], false));
add_float_intrinsic(ctx, module, &LLVM_SIN, |t| t.fn_type(&[t.into()], false));
add_float_intrinsic(ctx, module, &LLVM_COS, |t| t.fn_type(&[t.into()], false));
add_float_intrinsic(ctx, module, &LLVM_CEILING, |t| {
t.fn_type(&[t.into()], false)
});
add_float_intrinsic(ctx, module, &LLVM_FLOOR, |t| t.fn_type(&[t.into()], false));
add_int_intrinsic(ctx, module, &LLVM_ADD_WITH_OVERFLOW, |t| {
let fields = [t.into(), i1_type.into()];
ctx.struct_type(&fields, false)
.fn_type(&[t.into(), t.into()], false)
});
add_int_intrinsic(ctx, module, &LLVM_SUB_WITH_OVERFLOW, |t| {
let fields = [t.into(), i1_type.into()];
ctx.struct_type(&fields, false)
.fn_type(&[t.into(), t.into()], false)
});
add_int_intrinsic(ctx, module, &LLVM_MUL_WITH_OVERFLOW, |t| {
let fields = [t.into(), i1_type.into()];
ctx.struct_type(&fields, false)
.fn_type(&[t.into(), t.into()], false)
});
add_int_intrinsic(ctx, module, &LLVM_ADD_SATURATED, |t| {
t.fn_type(&[t.into(), t.into()], false)
});
add_int_intrinsic(ctx, module, &LLVM_SUB_SATURATED, |t| {
t.fn_type(&[t.into(), t.into()], false)
});
}
pub const LLVM_POW: IntrinsicName = float_intrinsic!("llvm.pow");
pub const LLVM_FABS: IntrinsicName = float_intrinsic!("llvm.fabs");
pub static LLVM_SQRT: IntrinsicName = float_intrinsic!("llvm.sqrt");
pub static LLVM_LOG: IntrinsicName = float_intrinsic!("llvm.log");
pub static LLVM_SIN: IntrinsicName = float_intrinsic!("llvm.sin");
pub static LLVM_COS: IntrinsicName = float_intrinsic!("llvm.cos");
pub static LLVM_CEILING: IntrinsicName = float_intrinsic!("llvm.ceil");
pub static LLVM_FLOOR: IntrinsicName = float_intrinsic!("llvm.floor");
pub static LLVM_ROUND: IntrinsicName = float_intrinsic!("llvm.round");
pub static LLVM_MEMSET_I64: &str = "llvm.memset.p0i8.i64";
pub static LLVM_MEMSET_I32: &str = "llvm.memset.p0i8.i32";
pub static LLVM_FRAME_ADDRESS: &str = "llvm.frameaddress.p0i8";
pub static LLVM_STACK_SAVE: &str = "llvm.stacksave";
pub static LLVM_SETJMP: &str = "llvm.eh.sjlj.setjmp";
pub static LLVM_LONGJMP: &str = "llvm.eh.sjlj.longjmp";
pub const LLVM_ADD_WITH_OVERFLOW: IntrinsicName =
llvm_int_intrinsic!("llvm.sadd.with.overflow", "llvm.uadd.with.overflow");
pub const LLVM_SUB_WITH_OVERFLOW: IntrinsicName =
llvm_int_intrinsic!("llvm.ssub.with.overflow", "llvm.usub.with.overflow");
pub const LLVM_MUL_WITH_OVERFLOW: IntrinsicName =
llvm_int_intrinsic!("llvm.smul.with.overflow", "llvm.umul.with.overflow");
pub const LLVM_ADD_SATURATED: IntrinsicName = llvm_int_intrinsic!("llvm.sadd.sat", "llvm.uadd.sat");
pub const LLVM_SUB_SATURATED: IntrinsicName = llvm_int_intrinsic!("llvm.ssub.sat", "llvm.usub.sat");
fn add_intrinsic<'ctx>(
context: &Context,
module: &Module<'ctx>,
intrinsic_name: &str,
fn_type: FunctionType<'ctx>,
) -> FunctionValue<'ctx> {
add_func(
context,
module,
intrinsic_name,
FunctionSpec::intrinsic(fn_type),
Linkage::External,
)
}

File diff suppressed because it is too large Load diff

View file

@ -6,4 +6,6 @@ pub mod compare;
pub mod convert;
mod expect;
pub mod externs;
mod intrinsics;
mod lowlevel;
pub mod refcounting;

View file

@ -7,8 +7,6 @@ license = "UPL-1.0"
description = "Provides the WASM backend to generate Roc binaries."
[dependencies]
bitvec = "1"
bumpalo = { version = "3.11.0", features = ["collections"] }
roc_builtins = { path = "../builtins" }
roc_collections = { path = "../collections" }
roc_intern = { path = "../intern" }
@ -17,3 +15,6 @@ roc_mono = { path = "../mono" }
roc_target = { path = "../roc_target" }
roc_std = { path = "../../roc_std" }
roc_error_macros = { path = "../../error_macros" }
bitvec.workspace = true
bumpalo.workspace = true

View file

@ -15,4 +15,5 @@ roc_unify = { path = "../unify" }
roc_solve = { path = "../solve" }
roc_collections = { path = "../collections" }
roc_error_macros = { path = "../../error_macros" }
bumpalo = { version = "3.11.0", features = ["collections"] }
bumpalo.workspace = true

View file

@ -8,7 +8,6 @@ description = "Used to load a .roc file and coordinate the compiler pipeline, in
[dependencies]
roc_load_internal = { path = "../load_internal" }
bumpalo = { version = "3.11.0", features = ["collections"] }
roc_target = { path = "../roc_target" }
roc_can = { path = "../can" }
roc_types = { path = "../types" }
@ -16,13 +15,16 @@ roc_module = { path = "../module" }
roc_collections = { path = "../collections" }
roc_reporting = { path = "../../reporting" }
bumpalo.workspace = true
[build-dependencies]
roc_builtins = { path = "../builtins" }
roc_module = { path = "../module" }
roc_reporting = { path = "../../reporting" }
roc_target = { path = "../roc_target" }
roc_can = { path = "../can" }
bumpalo = { version = "3.11.0", features = ["collections"] }
bumpalo.workspace = true
[target.'cfg(not(windows))'.build-dependencies]
roc_load_internal = { path = "../load_internal" }

View file

@ -86,6 +86,7 @@ fn write_types_for_module_real(module_id: ModuleId, filename: &str, output_path:
Default::default(),
target_info,
roc_reporting::report::RenderTarget::ColorTerminal,
roc_reporting::report::DEFAULT_PALETTE,
Threading::AllAvailable,
);

View file

@ -4,7 +4,7 @@ use bumpalo::Bump;
use roc_can::module::{ExposedByModule, TypeState};
use roc_collections::all::MutMap;
use roc_module::symbol::ModuleId;
use roc_reporting::report::RenderTarget;
use roc_reporting::report::{Palette, RenderTarget};
use roc_target::TargetInfo;
use std::path::PathBuf;
@ -40,6 +40,7 @@ pub fn load_single_threaded<'a>(
exposed_types: ExposedByModule,
target_info: TargetInfo,
render: RenderTarget,
palette: Palette,
exec_mode: ExecutionMode,
) -> Result<LoadResult<'a>, LoadingProblem<'a>> {
let cached_subs = read_cached_types();
@ -51,6 +52,7 @@ pub fn load_single_threaded<'a>(
target_info,
cached_subs,
render,
palette,
exec_mode,
)
}
@ -105,7 +107,8 @@ pub fn load_and_monomorphize(
) -> Result<MonomorphizedModule<'_>, LoadMonomorphizedError<'_>> {
use LoadResult::*;
let load_start = LoadStart::from_path(arena, filename, load_config.render)?;
let load_start =
LoadStart::from_path(arena, filename, load_config.render, load_config.palette)?;
match load(arena, load_start, exposed_types, load_config)? {
Monomorphized(module) => Ok(module),
@ -121,7 +124,8 @@ pub fn load_and_typecheck(
) -> Result<LoadedModule, LoadingProblem<'_>> {
use LoadResult::*;
let load_start = LoadStart::from_path(arena, filename, load_config.render)?;
let load_start =
LoadStart::from_path(arena, filename, load_config.render, load_config.palette)?;
match load(arena, load_start, exposed_types, load_config)? {
Monomorphized(_) => unreachable!(""),
@ -129,6 +133,7 @@ pub fn load_and_typecheck(
}
}
#[allow(clippy::too_many_arguments)]
pub fn load_and_typecheck_str<'a>(
arena: &'a Bump,
filename: PathBuf,
@ -137,6 +142,7 @@ pub fn load_and_typecheck_str<'a>(
exposed_types: ExposedByModule,
target_info: TargetInfo,
render: RenderTarget,
palette: Palette,
) -> Result<LoadedModule, LoadingProblem<'a>> {
use LoadResult::*;
@ -151,6 +157,7 @@ pub fn load_and_typecheck_str<'a>(
exposed_types,
target_info,
render,
palette,
ExecutionMode::Check,
)? {
Monomorphized(_) => unreachable!(""),

View file

@ -29,13 +29,16 @@ roc_target = { path = "../roc_target" }
roc_tracing = { path = "../../tracing" }
roc_reporting = { path = "../../reporting" }
roc_debug_flags = { path = "../debug_flags" }
ven_pretty = { path = "../../vendor/pretty" }
bumpalo = { version = "3.11.0", features = ["collections"] }
parking_lot = "0.12"
crossbeam = "0.8.2"
bumpalo.workspace = true
parking_lot.workspace = true
crossbeam.workspace = true
[dev-dependencies]
pretty_assertions = "1.3.0"
maplit = "1.0.2"
indoc = "1.0.7"
roc_test_utils = { path = "../../test_utils" }
pretty_assertions.workspace = true
indoc.workspace = true
maplit.workspace = true

View file

@ -44,12 +44,12 @@ use roc_parse::ident::UppercaseIdent;
use roc_parse::module::module_defs;
use roc_parse::parser::{FileError, Parser, SourceError, SyntaxError};
use roc_region::all::{LineInfo, Loc, Region};
use roc_reporting::report::{Annotation, RenderTarget};
use roc_reporting::report::{Annotation, Palette, RenderTarget};
use roc_solve::module::{extract_module_owned_implementations, Solved, SolvedModule};
use roc_solve_problem::TypeError;
use roc_target::TargetInfo;
use roc_types::subs::{ExposedTypesStorageSubs, Subs, VarStore, Variable};
use roc_types::types::{Alias, AliasKind};
use roc_types::types::{Alias, Types};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::HashMap;
use std::env::current_dir;
@ -88,6 +88,7 @@ macro_rules! log {
pub struct LoadConfig {
pub target_info: TargetInfo,
pub render: RenderTarget,
pub palette: Palette,
pub threading: Threading,
pub exec_mode: ExecutionMode,
}
@ -384,6 +385,7 @@ fn start_phase<'a>(
declarations,
dep_idents,
pending_derives,
types,
..
} = constrained;
@ -393,6 +395,7 @@ fn start_phase<'a>(
module,
ident_ids,
module_timing,
types,
constraints,
constraint,
pending_derives,
@ -646,6 +649,7 @@ struct ConstrainedModule {
var_store: VarStore,
dep_idents: IdentIdsByModule,
module_timing: ModuleTiming,
types: Types,
// Rather than adding pending derives as constraints, hand them directly to solve because they
// must be solved at the end of a module.
pending_derives: PendingDerives,
@ -930,6 +934,7 @@ struct State<'a> {
pub layout_caches: std::vec::Vec<LayoutCache<'a>>,
pub render: RenderTarget,
pub palette: Palette,
pub exec_mode: ExecutionMode,
/// All abilities across all modules.
@ -959,6 +964,7 @@ impl<'a> State<'a> {
ident_ids_by_module: SharedIdentIdsByModule,
cached_types: MutMap<ModuleId, TypeState>,
render: RenderTarget,
palette: Palette,
number_of_workers: usize,
exec_mode: ExecutionMode,
) -> Self {
@ -990,6 +996,7 @@ impl<'a> State<'a> {
layout_caches: std::vec::Vec::with_capacity(number_of_workers),
cached_types: Arc::new(Mutex::new(cached_types)),
render,
palette,
exec_mode,
make_specializations_pass: MakeSpecializationsPass::Pass(1),
world_abilities: Default::default(),
@ -1095,6 +1102,7 @@ enum BuildTask<'a> {
ident_ids: IdentIds,
exposed_for_module: ExposedForModule,
module_timing: ModuleTiming,
types: Types,
constraints: Constraints,
constraint: ConstraintSoa,
pending_derives: PendingDerives,
@ -1199,6 +1207,7 @@ pub fn load_and_typecheck_str<'a>(
exposed_types: ExposedByModule,
target_info: TargetInfo,
render: RenderTarget,
palette: Palette,
threading: Threading,
) -> Result<LoadedModule, LoadingProblem<'a>> {
use LoadResult::*;
@ -1212,6 +1221,7 @@ pub fn load_and_typecheck_str<'a>(
let load_config = LoadConfig {
target_info,
render,
palette,
threading,
exec_mode: ExecutionMode::Check,
};
@ -1241,6 +1251,7 @@ impl<'a> LoadStart<'a> {
arena: &'a Bump,
filename: PathBuf,
render: RenderTarget,
palette: Palette,
) -> Result<Self, LoadingProblem<'a>> {
let arc_modules = Arc::new(Mutex::new(PackageModuleIds::default()));
let root_exposed_ident_ids = IdentIds::exposed_builtins(0);
@ -1305,6 +1316,7 @@ impl<'a> LoadStart<'a> {
module_ids,
root_exposed_ident_ids,
render,
palette,
);
return Err(LoadingProblem::FormattedReport(buf));
}
@ -1501,6 +1513,7 @@ pub fn load<'a>(
load_config.target_info,
cached_types,
load_config.render,
load_config.palette,
load_config.exec_mode,
),
Threads::Many(threads) => load_multi_threaded(
@ -1510,6 +1523,7 @@ pub fn load<'a>(
load_config.target_info,
cached_types,
load_config.render,
load_config.palette,
threads,
load_config.exec_mode,
),
@ -1525,6 +1539,7 @@ pub fn load_single_threaded<'a>(
target_info: TargetInfo,
cached_types: MutMap<ModuleId, TypeState>,
render: RenderTarget,
palette: Palette,
exec_mode: ExecutionMode,
) -> Result<LoadResult<'a>, LoadingProblem<'a>> {
let LoadStart {
@ -1551,6 +1566,7 @@ pub fn load_single_threaded<'a>(
ident_ids_by_module,
cached_types,
render,
palette,
number_of_workers,
exec_mode,
);
@ -1666,6 +1682,7 @@ fn state_thread_step<'a>(
module_ids,
state.constrained_ident_ids,
state.render,
state.palette,
);
Err(LoadingProblem::FormattedReport(buf))
}
@ -1691,6 +1708,7 @@ fn state_thread_step<'a>(
let arc_modules = state.arc_modules.clone();
let render = state.render;
let palette = state.palette;
let res_state = update(
state,
@ -1720,6 +1738,7 @@ fn state_thread_step<'a>(
module_ids,
root_exposed_ident_ids,
render,
palette,
);
Err(LoadingProblem::FormattedReport(buf))
}
@ -1773,6 +1792,7 @@ fn load_multi_threaded<'a>(
target_info: TargetInfo,
cached_types: MutMap<ModuleId, TypeState>,
render: RenderTarget,
palette: Palette,
available_threads: usize,
exec_mode: ExecutionMode,
) -> Result<LoadResult<'a>, LoadingProblem<'a>> {
@ -1815,6 +1835,7 @@ fn load_multi_threaded<'a>(
ident_ids_by_module,
cached_types,
render,
palette,
num_workers,
exec_mode,
);
@ -4194,6 +4215,7 @@ impl<'a> BuildTask<'a> {
module: Module,
ident_ids: IdentIds,
module_timing: ModuleTiming,
types: Types,
constraints: Constraints,
constraint: ConstraintSoa,
pending_derives: PendingDerives,
@ -4215,6 +4237,7 @@ impl<'a> BuildTask<'a> {
module,
ident_ids,
exposed_for_module,
types,
constraints,
constraint,
pending_derives,
@ -4276,8 +4299,6 @@ pub fn add_imports(
def_types: &mut Vec<(Symbol, Loc<TypeOrVar>)>,
rigid_vars: &mut Vec<Variable>,
) -> (Vec<Variable>, AbilitiesStore) {
use roc_types::types::Type;
let mut import_variables = Vec::new();
let mut cached_symbol_vars = VecMap::default();
@ -4302,7 +4323,7 @@ pub fn add_imports(
};
let copied_import = exposed_types.storage_subs.export_variable_to($subs, variable);
let copied_import_index = constraints.push_type(Type::Variable(copied_import.variable));
let copied_import_index = constraints.push_variable(copied_import.variable);
def_types.push((
$symbol,
@ -4337,7 +4358,7 @@ pub fn add_imports(
if my_module == ModuleId::NUM {
// Num needs List.len, but List imports Num.
let list_len_type_var = synth_list_len_type(subs);
let list_len_type_index = constraints.push_type(Type::Variable(list_len_type_var));
let list_len_type_index = constraints.push_variable(list_len_type_var);
def_types.push((Symbol::LIST_LEN, Loc::at_zero(list_len_type_index)));
import_variables.push(list_len_type_var);
}
@ -4403,6 +4424,7 @@ pub fn add_imports(
#[allow(clippy::complexity)]
fn run_solve_solve(
exposed_for_module: ExposedForModule,
mut types: Types,
mut constraints: Constraints,
constraint: ConstraintSoa,
pending_derives: PendingDerives,
@ -4442,10 +4464,9 @@ fn run_solve_solve(
let actual_constraint =
constraints.let_import_constraint(rigid_vars, def_types, constraint, &import_variables);
let mut solve_aliases = default_aliases();
let mut solve_aliases = roc_solve::solve::Aliases::with_capacity(aliases.len());
for (name, (_, alias)) in aliases.iter() {
solve_aliases.insert(*name, alias.clone());
solve_aliases.insert(&mut types, *name, alias.clone());
}
let (solved_subs, solved_implementations, exposed_vars_by_symbol, problems, abilities_store) = {
@ -4453,6 +4474,7 @@ fn run_solve_solve(
let (solved_subs, solved_env, problems, abilities_store) = roc_solve::module::run_solve(
module_id,
types,
&constraints,
actual_constraint,
rigid_variables,
@ -4511,6 +4533,7 @@ fn run_solve<'a>(
ident_ids: IdentIds,
mut module_timing: ModuleTiming,
exposed_for_module: ExposedForModule,
types: Types,
constraints: Constraints,
constraint: ConstraintSoa,
pending_derives: PendingDerives,
@ -4536,6 +4559,7 @@ fn run_solve<'a>(
match cached_types.lock().remove(&module_id) {
None => run_solve_solve(
exposed_for_module,
types,
constraints,
constraint,
pending_derives,
@ -4559,6 +4583,7 @@ fn run_solve<'a>(
} else {
run_solve_solve(
exposed_for_module,
types,
constraints,
constraint,
pending_derives,
@ -4703,6 +4728,7 @@ fn canonicalize_and_constrain<'a>(
&symbols_from_requires,
&mut var_store,
);
let mut types = Types::new();
// _after has an underscore because it's unused in --release builds
let _after = roc_types::types::get_type_clone_count();
@ -4746,6 +4772,7 @@ fn canonicalize_and_constrain<'a>(
roc_can::constraint::Constraint::True
} else {
constrain_module(
&mut types,
&mut constraints,
module_output.symbols_from_requires,
&module_output.scope.abilities_store,
@ -4817,6 +4844,7 @@ fn canonicalize_and_constrain<'a>(
ident_ids: module_output.scope.locals.ident_ids,
dep_idents,
module_timing,
types,
pending_derives: module_output.pending_derives,
};
@ -5587,6 +5615,7 @@ fn run_task<'a>(
module,
module_timing,
exposed_for_module,
types,
constraints,
constraint,
pending_derives,
@ -5601,6 +5630,7 @@ fn run_task<'a>(
ident_ids,
module_timing,
exposed_for_module,
types,
constraints,
constraint,
pending_derives,
@ -5867,8 +5897,9 @@ fn to_parse_problem_report<'a>(
mut module_ids: ModuleIds,
all_ident_ids: IdentIdsByModule,
render: RenderTarget,
palette: Palette,
) -> String {
use roc_reporting::report::{parse_problem, RocDocAllocator, DEFAULT_PALETTE};
use roc_reporting::report::{parse_problem, RocDocAllocator};
// TODO this is not in fact safe
let src = unsafe { from_utf8_unchecked(problem.problem.bytes) };
@ -5899,7 +5930,6 @@ fn to_parse_problem_report<'a>(
);
let mut buf = String::new();
let palette = DEFAULT_PALETTE;
report.render(render, &mut buf, &alloc, &palette);
@ -5989,46 +6019,3 @@ fn to_missing_platform_report(module_id: ModuleId, other: PlatformPath) -> Strin
buf
}
/// Builtin aliases that are not covered by type checker optimizations
///
/// Types like `F64` and `I32` are hardcoded into Subs and therefore we don't define them here.
/// Generic number types (Num, Int, Float, etc.) are treated as `DelayedAlias`es resolved during
/// type solving.
/// All that remains are Signed8, Signed16, etc.
pub fn default_aliases() -> roc_solve::solve::Aliases {
use roc_types::types::Type;
let mut solve_aliases = roc_solve::solve::Aliases::default();
let mut zero_opaque = |alias_name: Symbol| {
let alias = Alias {
region: Region::zero(),
type_variables: vec![],
lambda_set_variables: Default::default(),
recursion_variables: Default::default(),
infer_ext_in_output_variables: Default::default(),
typ: Type::EmptyTagUnion,
kind: AliasKind::Opaque,
};
solve_aliases.insert(alias_name, alias);
};
zero_opaque(Symbol::NUM_SIGNED8);
zero_opaque(Symbol::NUM_SIGNED16);
zero_opaque(Symbol::NUM_SIGNED32);
zero_opaque(Symbol::NUM_SIGNED64);
zero_opaque(Symbol::NUM_SIGNED128);
zero_opaque(Symbol::NUM_UNSIGNED8);
zero_opaque(Symbol::NUM_UNSIGNED16);
zero_opaque(Symbol::NUM_UNSIGNED32);
zero_opaque(Symbol::NUM_UNSIGNED64);
zero_opaque(Symbol::NUM_UNSIGNED128);
zero_opaque(Symbol::NUM_BINARY32);
zero_opaque(Symbol::NUM_BINARY64);
solve_aliases
}

View file

@ -23,9 +23,9 @@ use roc_module::ident::ModuleName;
use roc_module::symbol::{Interns, ModuleId};
use roc_problem::can::Problem;
use roc_region::all::LineInfo;
use roc_reporting::report::can_problem;
use roc_reporting::report::RenderTarget;
use roc_reporting::report::RocDocAllocator;
use roc_reporting::report::{can_problem, DEFAULT_PALETTE};
use roc_target::TargetInfo;
use roc_types::pretty_print::name_and_print_var;
use roc_types::pretty_print::DebugPrint;
@ -40,10 +40,11 @@ fn load_and_typecheck(
) -> Result<LoadedModule, LoadingProblem> {
use LoadResult::*;
let load_start = LoadStart::from_path(arena, filename, RenderTarget::Generic)?;
let load_start = LoadStart::from_path(arena, filename, RenderTarget::Generic, DEFAULT_PALETTE)?;
let load_config = LoadConfig {
target_info,
render: RenderTarget::Generic,
palette: DEFAULT_PALETTE,
threading: Threading::Single,
exec_mode: ExecutionMode::Check,
};

View file

@ -11,9 +11,9 @@ roc_region = { path = "../region" }
roc_ident = { path = "../ident" }
roc_collections = { path = "../collections" }
roc_error_macros = {path = "../../error_macros"}
bumpalo = { version = "3.11.0", features = ["collections"] }
static_assertions = "1.1.0"
snafu = { version = "0.7.1", features = ["backtraces"] }
bumpalo.workspace = true
static_assertions.workspace = true
snafu.workspace = true
[features]
default = []

View file

@ -25,7 +25,8 @@ roc_error_macros = {path="../../error_macros"}
roc_debug_flags = {path="../debug_flags"}
roc_tracing = { path = "../../tracing" }
ven_pretty = { path = "../../vendor/pretty" }
bumpalo = { version = "3.11.0", features = ["collections"] }
hashbrown = { version = "0.12.3", features = [ "bumpalo" ] }
static_assertions = "1.1.0"
bitvec = "1.0.1"
bumpalo.workspace = true
hashbrown.workspace = true
static_assertions.workspace = true
bitvec.workspace = true

View file

@ -13,17 +13,19 @@ description = "Implements the Roc parser, which transforms a textual representat
roc_collections = { path = "../collections" }
roc_region = { path = "../region" }
roc_module = { path = "../module" }
bumpalo = { version = "3.11.0", features = ["collections"] }
encode_unicode = "1.0.0"
bumpalo.workspace = true
encode_unicode.workspace = true
[dev-dependencies]
criterion = { git = "https://github.com/Anton-4/criterion.rs", features = ["html_reports"]}
pretty_assertions = "1.3.0"
indoc = "1.0.7"
quickcheck = "1.0.3"
quickcheck_macros = "1.0.0"
roc_test_utils = { path = "../../test_utils" }
criterion.workspace = true
pretty_assertions.workspace = true
indoc.workspace = true
quickcheck.workspace = true
quickcheck_macros.workspace = true
[[bench]]
name = "bench_parse"
harness = false

View file

@ -163,13 +163,19 @@ pub enum Expr<'a> {
// String Literals
Str(StrLiteral<'a>), // string without escapes in it
/// Look up exactly one field on a record, e.g. (expr).foo.
Access(&'a Expr<'a>, &'a str),
/// e.g. `.foo`
AccessorFunction(&'a str),
/// eg 'b'
SingleQuote(&'a str),
/// Look up exactly one field on a record, e.g. `x.foo`.
RecordAccess(&'a Expr<'a>, &'a str),
/// e.g. `.foo`
RecordAccessorFunction(&'a str),
/// Look up exactly one field on a tuple, e.g. `(x, y).1`.
TupleAccess(&'a Expr<'a>, &'a str),
/// e.g. `.1`
TupleAccessorFunction(&'a str),
// Collection Literals
List(Collection<'a, &'a Loc<Expr<'a>>>),
@ -180,6 +186,8 @@ pub enum Expr<'a> {
Record(Collection<'a, Loc<AssignedField<'a, Expr<'a>>>>),
Tuple(Collection<'a, &'a Loc<Expr<'a>>>),
// Lookups
Var {
module_name: &'a str, // module_name will only be filled if the original Roc code stated something like `5 + SomeModule.myVar`, module_name will be blank if it was `5 + myVar`
@ -661,6 +669,9 @@ pub enum Pattern<'a> {
Underscore(&'a str),
SingleQuote(&'a str),
/// A tuple pattern, e.g. (Just x, 1)
Tuple(Collection<'a, Loc<Pattern<'a>>>),
/// A list pattern like [_, x, ..]
List(Collection<'a, Loc<Pattern<'a>>>),
@ -729,7 +740,8 @@ impl<'a> Pattern<'a> {
Pattern::Malformed(buf.into_bump_str())
}
}
Ident::AccessorFunction(string) => Pattern::Malformed(string),
Ident::RecordAccessorFunction(string) => Pattern::Malformed(string),
Ident::TupleAccessorFunction(string) => Pattern::Malformed(string),
Ident::Malformed(string, _problem) => Pattern::Malformed(string),
}
}

View file

@ -12,7 +12,7 @@ use crate::parser::{
self, backtrackable, increment_min_indent, line_min_indent, optional, reset_min_indent,
sep_by1, sep_by1_e, set_min_indent, specialize, specialize_ref, then, trailing_sep_by0, word1,
word1_indent, word2, EClosure, EExpect, EExpr, EIf, EInParens, EList, ENumber, EPattern,
ERecord, EString, EType, EWhen, Either, ParseResult, Parser,
ERecord, EString, ETuple, EType, EWhen, Either, ParseResult, Parser,
};
use crate::pattern::{loc_closure_param, loc_has_parser};
use crate::state::State;
@ -81,72 +81,79 @@ pub fn expr_help<'a>() -> impl Parser<'a, Expr<'a>, EExpr<'a>> {
}
fn loc_expr_in_parens_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EInParens<'a>> {
move |arena, state, min_indent| {
let (_, loc_expr, state) =
loc_expr_in_parens_help_help().parse(arena, state, min_indent)?;
Ok((
MadeProgress,
Loc {
region: loc_expr.region,
value: Expr::ParensAround(arena.alloc(loc_expr.value)),
},
state,
))
}
}
fn loc_expr_in_parens_help_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EInParens<'a>> {
between!(
word1(b'(', EInParens::Open),
space0_around_ee(
specialize_ref(EInParens::Expr, loc_expr()),
EInParens::IndentOpen,
then(
loc!(collection_trailing_sep_e!(
word1(b'(', EInParens::Open),
specialize_ref(EInParens::Expr, loc_expr_no_multi_backpassing()),
word1(b',', EInParens::End),
word1(b')', EInParens::End),
EInParens::Open,
EInParens::IndentEnd,
),
word1(b')', EInParens::End)
Expr::SpaceBefore
)),
move |arena, state, _, loc_elements| {
let elements = loc_elements.value;
let region = loc_elements.region;
if elements.len() > 1 {
Ok((
MadeProgress,
Loc::at(region, Expr::Tuple(elements.ptrify_items(arena))),
state,
))
} else if elements.is_empty() {
Err((NoProgress, EInParens::Empty(state.pos()), state))
} else {
// TODO: don't discard comments before/after
// (stored in the Collection)
Ok((
MadeProgress,
Loc::at(
elements.items[0].region,
Expr::ParensAround(&elements.items[0].value),
),
state,
))
}
},
)
.trace("in_parens")
}
fn loc_expr_in_parens_etc_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
move |arena, state: State<'a>, min_indent: u32| {
let parser = loc!(and!(
map_with_arena!(
loc!(and!(
specialize(EExpr::InParens, loc_expr_in_parens_help()),
one_of![record_field_access_chain(), |a, s, _m| Ok((
NoProgress,
Vec::new_in(a),
s
))]
));
let (
_,
Loc {
)),
move |arena: &'a Bump, value: Loc<(Loc<Expr<'a>>, Vec<'a, &'a str>)>| {
let Loc {
mut region,
value: (loc_expr, field_accesses),
},
state,
) = parser.parse(arena, state, min_indent)?;
} = value;
let mut value = loc_expr.value;
let mut value = loc_expr.value;
// if there are field accesses, include the parentheses in the region
// otherwise, don't include the parentheses
if field_accesses.is_empty() {
region = loc_expr.region;
} else {
for field in field_accesses {
// Wrap the previous answer in the new one, so we end up
// with a nested Expr. That way, `foo.bar.baz` gets represented
// in the AST as if it had been written (foo.bar).baz all along.
value = Expr::Access(arena.alloc(value), field);
// if there are field accesses, include the parentheses in the region
// otherwise, don't include the parentheses
if field_accesses.is_empty() {
region = loc_expr.region;
} else {
for field in field_accesses {
// Wrap the previous answer in the new one, so we end up
// with a nested Expr. That way, `foo.bar.baz` gets represented
// in the AST as if it had been written (foo.bar).baz all along.
value = Expr::RecordAccess(arena.alloc(value), field);
}
}
Loc::at(region, value)
}
let loc_expr = Loc::at(region, value);
Ok((MadeProgress, loc_expr, state))
}
)
}
fn record_field_access_chain<'a>() -> impl Parser<'a, Vec<'a, &'a str>, EExpr<'a>> {
@ -1845,6 +1852,16 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
Ok(Pattern::RecordDestructure(patterns))
}
Expr::Tuple(fields) => Ok(Pattern::Tuple(fields.map_items_result(
arena,
|loc_expr| {
Ok(Loc {
region: loc_expr.region,
value: expr_to_pattern_help(arena, &loc_expr.value)?,
})
},
)?)),
&Expr::Float(string) => Ok(Pattern::FloatLiteral(string)),
&Expr::Num(string) => Ok(Pattern::NumLiteral(string)),
Expr::NonBase10Int {
@ -1857,8 +1874,10 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
is_negative: *is_negative,
}),
// These would not have parsed as patterns
Expr::AccessorFunction(_)
| Expr::Access(_, _)
Expr::RecordAccessorFunction(_)
| Expr::RecordAccess(_, _)
| Expr::TupleAccessorFunction(_)
| Expr::TupleAccess(_, _)
| Expr::List { .. }
| Expr::Closure(_, _)
| Expr::Backpassing(_, _, _)
@ -2406,12 +2425,13 @@ fn ident_to_expr<'a>(arena: &'a Bump, src: Ident<'a>) -> Expr<'a> {
// Wrap the previous answer in the new one, so we end up
// with a nested Expr. That way, `foo.bar.baz` gets represented
// in the AST as if it had been written (foo.bar).baz all along.
answer = Expr::Access(arena.alloc(answer), field);
answer = Expr::RecordAccess(arena.alloc(answer), field);
}
answer
}
Ident::AccessorFunction(string) => Expr::AccessorFunction(string),
Ident::RecordAccessorFunction(string) => Expr::RecordAccessorFunction(string),
Ident::TupleAccessorFunction(string) => Expr::TupleAccessorFunction(string),
Ident::Malformed(string, problem) => Expr::MalformedIdent(string, problem),
}
}
@ -2435,6 +2455,13 @@ fn list_literal_help<'a>() -> impl Parser<'a, Expr<'a>, EList<'a>> {
.trace("list_literal")
}
pub fn tuple_value_field<'a>() -> impl Parser<'a, Loc<Expr<'a>>, ETuple<'a>> {
space0_before_e(
specialize_ref(ETuple::Expr, loc_expr_no_multi_backpassing()),
ETuple::IndentEnd,
)
}
pub fn record_value_field<'a>() -> impl Parser<'a, AssignedField<'a, Expr<'a>>, ERecord<'a>> {
use AssignedField::*;
@ -2577,7 +2604,7 @@ fn record_literal_help<'a>() -> impl Parser<'a, Expr<'a>, EExpr<'a>> {
// Wrap the previous answer in the new one, so we end up
// with a nested Expr. That way, `foo.bar.baz` gets represented
// in the AST as if it had been written (foo.bar).baz all along.
value = Expr::Access(arena.alloc(value), field);
value = Expr::RecordAccess(arena.alloc(value), field);
}
}

View file

@ -44,7 +44,9 @@ pub enum Ident<'a> {
parts: &'a [&'a str],
},
/// .foo { foo: 42 }
AccessorFunction(&'a str),
RecordAccessorFunction(&'a str),
/// .1 (1, 2, 3)
TupleAccessorFunction(&'a str),
/// .Foo or foo. or something like foo.Bar
Malformed(&'a str, BadIdent),
}
@ -69,7 +71,8 @@ impl<'a> Ident<'a> {
len - 1
}
AccessorFunction(string) => string.len(),
RecordAccessorFunction(string) => string.len(),
TupleAccessorFunction(string) => string.len(),
Malformed(string, _) => string.len(),
}
}
@ -134,10 +137,7 @@ pub fn uppercase_ident<'a>() -> impl Parser<'a, &'a str, ()> {
}
pub fn unqualified_ident<'a>() -> impl Parser<'a, &'a str, ()> {
move |_, state: State<'a>, _min_indent: u32| match chomp_part(
|c| c.is_alphabetic(),
state.bytes(),
) {
move |_, state: State<'a>, _min_indent: u32| match chomp_anycase_part(state.bytes()) {
Err(progress) => Err((progress, (), state)),
Ok(ident) => {
if crate::keyword::KEYWORDS.iter().any(|kw| &ident == kw) {
@ -234,18 +234,35 @@ pub enum BadIdent {
BadOpaqueRef(Position),
}
fn is_alnum(ch: char) -> bool {
ch.is_alphabetic() || ch.is_ascii_digit()
}
fn chomp_lowercase_part(buffer: &[u8]) -> Result<&str, Progress> {
chomp_part(|c: char| c.is_lowercase(), buffer)
chomp_part(char::is_lowercase, is_alnum, buffer)
}
fn chomp_uppercase_part(buffer: &[u8]) -> Result<&str, Progress> {
chomp_part(|c: char| c.is_uppercase(), buffer)
chomp_part(char::is_uppercase, is_alnum, buffer)
}
fn chomp_anycase_part(buffer: &[u8]) -> Result<&str, Progress> {
chomp_part(char::is_alphabetic, is_alnum, buffer)
}
fn chomp_integer_part(buffer: &[u8]) -> Result<&str, Progress> {
chomp_part(
|ch| char::is_ascii_digit(&ch),
|ch| char::is_ascii_digit(&ch),
buffer,
)
}
#[inline(always)]
fn chomp_part<F>(leading_is_good: F, buffer: &[u8]) -> Result<&str, Progress>
fn chomp_part<F, G>(leading_is_good: F, rest_is_good: G, buffer: &[u8]) -> Result<&str, Progress>
where
F: Fn(char) -> bool,
G: Fn(char) -> bool,
{
use encode_unicode::CharExt;
@ -260,7 +277,7 @@ where
}
while let Ok((ch, width)) = char::from_utf8_slice_start(&buffer[chomped..]) {
if ch.is_alphabetic() || ch.is_ascii_digit() {
if rest_is_good(ch) {
chomped += width;
} else {
// we're done
@ -277,8 +294,13 @@ where
}
}
/// a `.foo` accessor function
fn chomp_accessor(buffer: &[u8], pos: Position) -> Result<&str, BadIdent> {
pub enum Accessor<'a> {
RecordField(&'a str),
TupleIndex(&'a str),
}
/// a `.foo` or `.1` accessor function
fn chomp_accessor(buffer: &[u8], pos: Position) -> Result<Accessor, BadIdent> {
// assumes the leading `.` has been chomped already
use encode_unicode::CharExt;
@ -289,12 +311,25 @@ fn chomp_accessor(buffer: &[u8], pos: Position) -> Result<&str, BadIdent> {
if let Ok(('.', _)) = char::from_utf8_slice_start(&buffer[chomped..]) {
Err(BadIdent::WeirdAccessor(pos))
} else {
Ok(name)
Ok(Accessor::RecordField(name))
}
}
Err(_) => {
// we've already made progress with the initial `.`
Err(BadIdent::StrayDot(pos.bump_column(1)))
match chomp_integer_part(buffer) {
Ok(name) => {
let chomped = name.len();
if let Ok(('.', _)) = char::from_utf8_slice_start(&buffer[chomped..]) {
Err(BadIdent::WeirdAccessor(pos))
} else {
Ok(Accessor::TupleIndex(name))
}
}
Err(_) => {
// we've already made progress with the initial `.`
Err(BadIdent::StrayDot(pos.bump_column(1)))
}
}
}
}
}
@ -335,10 +370,13 @@ fn chomp_identifier_chain<'a>(
match char::from_utf8_slice_start(&buffer[chomped..]) {
Ok((ch, width)) => match ch {
'.' => match chomp_accessor(&buffer[1..], pos) {
Ok(accessor) => {
Ok(Accessor::RecordField(accessor)) => {
let bytes_parsed = 1 + accessor.len();
return Ok((bytes_parsed as u32, Ident::AccessorFunction(accessor)));
return Ok((bytes_parsed as u32, Ident::RecordAccessorFunction(accessor)));
}
Ok(Accessor::TupleIndex(accessor)) => {
let bytes_parsed = 1 + accessor.len();
return Ok((bytes_parsed as u32, Ident::TupleAccessorFunction(accessor)));
}
Err(fail) => return Err((1, fail)),
},

View file

@ -108,7 +108,8 @@ impl_space_problem! {
EAbility<'a>,
PInParens<'a>,
PRecord<'a>,
PList<'a>
PList<'a>,
ETuple<'a>
}
#[derive(Debug, Clone, PartialEq, Eq)]
@ -360,6 +361,7 @@ pub enum EExpr<'a> {
InParens(EInParens<'a>, Position),
Record(ERecord<'a>, Position),
Tuple(ETuple<'a>, Position),
Str(EString<'a>, Position),
SingleQuote(EString<'a>, Position),
Number(ENumber, Position),
@ -414,10 +416,43 @@ pub enum ERecord<'a> {
IndentEnd(Position),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ETuple<'a> {
// Empty tuples are not allowed
Empty(Position),
// Single element tuples are not allowed
Single(Position),
End(Position),
Open(Position),
Updateable(Position),
Field(Position),
Colon(Position),
QuestionMark(Position),
Bar(Position),
Ampersand(Position),
Expr(&'a EExpr<'a>, Position),
Space(BadInputError, Position),
IndentOpen(Position),
IndentColon(Position),
IndentBar(Position),
IndentAmpersand(Position),
IndentEnd(Position),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EInParens<'a> {
End(Position),
Open(Position),
/// Empty parens, e.g. () is not allowed
Empty(Position),
///
Expr(&'a EExpr<'a>, Position),
@ -570,6 +605,7 @@ pub enum PList<'a> {
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PInParens<'a> {
Empty(Position),
End(Position),
Open(Position),
Pattern(&'a EPattern<'a>, Position),

View file

@ -1,5 +1,5 @@
use crate::ast::{Has, Pattern};
use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
use crate::blankspace::{space0_before_e, space0_e};
use crate::ident::{lowercase_ident, parse_ident, Ident};
use crate::parser::Progress::{self, *};
use crate::parser::{
@ -147,15 +147,37 @@ fn loc_parse_tag_pattern_arg<'a>(
}
fn loc_pattern_in_parens_help<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, PInParens<'a>> {
between!(
word1(b'(', PInParens::Open),
space0_around_ee(
then(
loc!(collection_trailing_sep_e!(
word1(b'(', PInParens::Open),
specialize_ref(PInParens::Pattern, loc_pattern_help()),
word1(b',', PInParens::End),
word1(b')', PInParens::End),
PInParens::Open,
PInParens::IndentOpen,
PInParens::IndentEnd,
),
word1(b')', PInParens::End)
Pattern::SpaceBefore
)),
move |_arena, state, _, loc_elements| {
let elements = loc_elements.value;
let region = loc_elements.region;
if elements.len() > 1 {
Ok((
MadeProgress,
Loc::at(region, Pattern::Tuple(elements)),
state,
))
} else if elements.is_empty() {
Err((NoProgress, PInParens::Empty(state.pos()), state))
} else {
// TODO: don't discard comments before/after
// (stored in the Collection)
// TODO: add Pattern::ParensAround to faithfully represent the input
Ok((MadeProgress, elements.items[0], state))
}
},
)
.trace("pat_in_parens")
}
fn number_pattern_help<'a>() -> impl Parser<'a, Pattern<'a>, EPattern<'a>> {
@ -340,7 +362,7 @@ fn loc_ident_pattern_help<'a>(
))
}
}
Ident::AccessorFunction(string) => Ok((
Ident::RecordAccessorFunction(string) | Ident::TupleAccessorFunction(string) => Ok((
MadeProgress,
Loc {
region: loc_ident.region,

View file

@ -0,0 +1,87 @@
Defs(
Defs {
tags: [
Index(2147483649),
],
regions: [
@0-41,
],
space_before: [
Slice(start = 0, length = 0),
],
space_after: [
Slice(start = 0, length = 0),
],
spaces: [],
type_defs: [],
value_defs: [
Annotation(
@0-8 Tuple(
[
@2-3 Identifier(
"x",
),
@5-6 Identifier(
"y",
),
],
),
@11-14 Apply(
"",
"Foo",
[],
),
),
AnnotatedBody {
ann_pattern: @0-8 Tuple(
[
@2-3 Identifier(
"x",
),
@5-6 Identifier(
"y",
),
],
),
ann_type: @11-14 Apply(
"",
"Foo",
[],
),
comment: None,
body_pattern: @15-23 Tuple(
[
@17-18 Identifier(
"x",
),
@20-21 Identifier(
"y",
),
],
),
body_expr: @26-41 Tuple(
[
@28-33 Str(
PlainLine(
"foo",
),
),
@35-39 Float(
"3.14",
),
],
),
},
],
},
@43-44 SpaceBefore(
Var {
module_name: "",
ident: "x",
},
[
Newline,
Newline,
],
),
)

View file

@ -0,0 +1,4 @@
( x, y ) : Foo
( x, y ) = ( "foo", 3.14 )
x

View file

@ -1,4 +1,4 @@
Access(
RecordAccess(
Var {
module_name: "",
ident: "rec",

View file

@ -0,0 +1,13 @@
Tuple(
[
@1-2 Num(
"1",
),
@4-5 Num(
"2",
),
@7-8 Num(
"3",
),
],
)

View file

@ -0,0 +1 @@
(1, 2, 3)

View file

@ -1,6 +1,6 @@
Access(
Access(
Access(
RecordAccess(
RecordAccess(
RecordAccess(
Var {
module_name: "",
ident: "rec",

View file

@ -1,4 +1,4 @@
Access(
RecordAccess(
ParensAround(
Var {
module_name: "",

View file

@ -1,4 +1,4 @@
Access(
RecordAccess(
ParensAround(
Var {
module_name: "One.Two",

View file

@ -1,6 +1,6 @@
Access(
Access(
Access(
RecordAccess(
RecordAccess(
RecordAccess(
Var {
module_name: "One.Two",
ident: "rec",

View file

@ -0,0 +1,21 @@
Apply(
@0-2 TupleAccessorFunction(
"1",
),
[
@3-12 Tuple(
[
@4-5 Num(
"1",
),
@7-8 Num(
"2",
),
@10-11 Num(
"3",
),
],
),
],
Space,
)

View file

@ -0,0 +1 @@
.1 (1, 2, 3)

View file

@ -1,5 +1,5 @@
UnaryOp(
@1-11 Access(
@1-11 RecordAccess(
Var {
module_name: "",
ident: "rec1",

View file

@ -0,0 +1,94 @@
When(
@5-18 Record(
[
@6-17 RequiredValue(
@6-9 "foo",
[],
@11-17 Tuple(
[
@12-13 Num(
"1",
),
@15-16 Num(
"2",
),
],
),
),
],
),
[
WhenBranch {
patterns: [
@23-36 SpaceBefore(
RecordDestructure(
[
@24-35 RequiredField(
"foo",
@29-35 Tuple(
[
@30-31 NumLiteral(
"1",
),
@33-34 Identifier(
"x",
),
],
),
),
],
),
[
Newline,
],
),
],
value: @40-41 Var {
module_name: "",
ident: "x",
},
guard: None,
},
WhenBranch {
patterns: [
@43-56 SpaceBefore(
RecordDestructure(
[
@44-55 RequiredField(
"foo",
@49-55 Tuple(
[
@50-51 Underscore(
"",
),
@53-54 Identifier(
"b",
),
],
),
),
],
),
[
Newline,
],
),
],
value: @60-65 BinOps(
[
(
@60-61 Num(
"3",
),
@62-63 Plus,
),
],
@64-65 Var {
module_name: "",
ident: "b",
},
),
guard: None,
},
],
)

View file

@ -0,0 +1,3 @@
when {foo: (1, 2)} is
{foo: (1, x)} -> x
{foo: (_, b)} -> 3 + b

View file

@ -0,0 +1,72 @@
When(
@5-11 Tuple(
[
@6-7 Num(
"1",
),
@9-10 Num(
"2",
),
],
),
[
WhenBranch {
patterns: [
@16-22 SpaceBefore(
Tuple(
[
@17-18 NumLiteral(
"1",
),
@20-21 Identifier(
"x",
),
],
),
[
Newline,
],
),
],
value: @26-27 Var {
module_name: "",
ident: "x",
},
guard: None,
},
WhenBranch {
patterns: [
@29-35 SpaceBefore(
Tuple(
[
@30-31 Underscore(
"",
),
@33-34 Identifier(
"b",
),
],
),
[
Newline,
],
),
],
value: @39-44 BinOps(
[
(
@39-40 Num(
"3",
),
@41-42 Plus,
),
],
@43-44 Var {
module_name: "",
ident: "b",
},
),
guard: None,
},
],
)

View file

@ -0,0 +1,3 @@
when (1, 2) is
(1, x) -> x
(_, b) -> 3 + b

View file

@ -279,6 +279,7 @@ mod test_parse {
pass/underscore_backpassing.expr,
pass/underscore_in_assignment_pattern.expr,
pass/var_else.expr,
pass/tuple_accessor_function.expr,
pass/var_if.expr,
pass/var_is.expr,
pass/var_minus_two.expr,
@ -303,6 +304,10 @@ mod test_parse {
pass/where_clause_on_newline.expr,
pass/zero_float.expr,
pass/zero_int.expr,
pass/basic_tuple.expr,
pass/when_with_tuples.expr,
pass/when_with_tuple_in_record.expr,
pass/annotated_tuple_destructure.expr,
}
fn snapshot_test(

View file

@ -20,8 +20,9 @@ roc_problem = { path = "../problem" }
roc_solve_problem = { path = "../solve_problem" }
roc_unify = { path = "../unify" }
roc_debug_flags = { path = "../debug_flags" }
arrayvec = "0.7.2"
bumpalo = { version = "3.11.0", features = ["collections"] }
arrayvec.workspace = true
bumpalo.workspace = true
[dev-dependencies]
roc_load = { path = "../load" }
@ -32,10 +33,11 @@ roc_solve = { path = "../solve" }
roc_target = { path = "../roc_target" }
roc_reporting = { path = "../../reporting" }
roc_derive = { path = "../derive", features = ["debug-derived-symbols"] }
pretty_assertions = "1.3.0"
indoc = "1.0.7"
tempfile = "3.2.0"
bumpalo = { version = "3.11.0", features = ["collections"] }
regex = "1.5.5"
lazy_static = "1.4.0"
insta = "1.20.0"
pretty_assertions.workspace = true
indoc.workspace = true
tempfile.workspace = true
bumpalo.workspace = true
regex.workspace = true
lazy_static.workspace = true
insta.workspace = true

View file

@ -13,7 +13,7 @@ use roc_types::subs::{
instantiate_rigids, Content, FlatType, GetSubsSlice, Rank, RecordFields, Subs, SubsSlice,
Variable,
};
use roc_types::types::{AliasKind, Category, MemberImpl, PatternCategory, Polarity};
use roc_types::types::{AliasKind, Category, MemberImpl, PatternCategory, Polarity, Types};
use roc_unify::unify::{Env, MustImplementConstraints};
use roc_unify::unify::{MustImplementAbility, Obligated};
@ -53,6 +53,7 @@ pub struct PendingDerivesTable(
impl PendingDerivesTable {
pub fn new(
subs: &mut Subs,
types: &mut Types,
aliases: &mut Aliases,
pending_derives: PendingDerives,
problems: &mut Vec<TypeError>,
@ -74,6 +75,7 @@ impl PendingDerivesTable {
let derive_key = RequestedDeriveKey { opaque, ability };
// Neither rank nor pools should matter here.
let typ = types.from_old_type(&typ);
let opaque_var = type_to_var(
subs,
Rank::toplevel(),
@ -81,8 +83,9 @@ impl PendingDerivesTable {
abilities_store,
obligation_cache,
&mut Pools::default(),
types,
aliases,
&typ,
typ,
);
let real_var = match subs.get_content_without_compacting(opaque_var) {
Content::Alias(_, _, real_var, AliasKind::Opaque) => real_var,

View file

@ -10,7 +10,7 @@ use roc_error_macros::internal_error;
use roc_module::symbol::{ModuleId, Symbol};
use roc_solve_problem::TypeError;
use roc_types::subs::{Content, ExposedTypesStorageSubs, FlatType, StorageSubs, Subs, Variable};
use roc_types::types::{Alias, MemberImpl};
use roc_types::types::{Alias, MemberImpl, Types};
/// A marker that a given Subs has been solved.
/// The only way to obtain a Solved<Subs> is by running the solver on it.
@ -56,6 +56,7 @@ pub struct SolvedModule {
#[allow(clippy::too_many_arguments)] // TODO: put params in a context/env var
pub fn run_solve(
home: ModuleId,
types: Types,
constraints: &Constraints,
constraint: ConstraintSoa,
rigid_variables: RigidVariables,
@ -85,6 +86,7 @@ pub fn run_solve(
// Run the solver to populate Subs.
let (solved_subs, solved_env) = solve::run(
home,
types,
constraints,
&mut problems,
subs,

View file

@ -138,12 +138,19 @@ impl DelayedAliasVariables {
#[derive(Debug, Default)]
pub struct Aliases {
aliases: Vec<(Symbol, Type, DelayedAliasVariables, AliasKind)>,
aliases: Vec<(Symbol, Index<TypeTag>, DelayedAliasVariables, AliasKind)>,
variables: Vec<OptAbleVar>,
}
impl Aliases {
pub fn insert(&mut self, symbol: Symbol, alias: Alias) {
pub fn with_capacity(cap: usize) -> Self {
Self {
aliases: Vec::with_capacity(cap),
variables: Vec::with_capacity(cap * 2),
}
}
pub fn insert(&mut self, types: &mut Types, symbol: Symbol, alias: Alias) {
let alias_variables =
{
let start = self.variables.len() as _;
@ -188,8 +195,11 @@ impl Aliases {
}
};
// TODO: can we construct Aliases from TypeTag directly?
let alias_typ = types.from_old_type(&alias.typ);
self.aliases
.push((symbol, alias.typ, alias_variables, alias.kind));
.push((symbol, alias_typ, alias_variables, alias.kind));
}
fn instantiate_result_result(
@ -287,6 +297,18 @@ impl Aliases {
Some((num_content_var, AliasKind::Structural))
}
Symbol::NUM_SIGNED8 => Some((Variable::SIGNED8, AliasKind::Opaque)),
Symbol::NUM_SIGNED16 => Some((Variable::SIGNED16, AliasKind::Opaque)),
Symbol::NUM_SIGNED32 => Some((Variable::SIGNED32, AliasKind::Opaque)),
Symbol::NUM_SIGNED64 => Some((Variable::SIGNED64, AliasKind::Opaque)),
Symbol::NUM_SIGNED128 => Some((Variable::SIGNED128, AliasKind::Opaque)),
Symbol::NUM_UNSIGNED8 => Some((Variable::UNSIGNED8, AliasKind::Opaque)),
Symbol::NUM_UNSIGNED16 => Some((Variable::UNSIGNED16, AliasKind::Opaque)),
Symbol::NUM_UNSIGNED32 => Some((Variable::UNSIGNED32, AliasKind::Opaque)),
Symbol::NUM_UNSIGNED64 => Some((Variable::UNSIGNED64, AliasKind::Opaque)),
Symbol::NUM_UNSIGNED128 => Some((Variable::UNSIGNED128, AliasKind::Opaque)),
Symbol::NUM_BINARY32 => Some((Variable::BINARY32, AliasKind::Opaque)),
Symbol::NUM_BINARY64 => Some((Variable::BINARY64, AliasKind::Opaque)),
_ => None,
}
}
@ -316,19 +338,16 @@ impl Aliases {
return (var, kind);
}
let (typ, delayed_variables, &mut kind) =
match self.aliases.iter_mut().find(|(s, _, _, _)| *s == symbol) {
let (typ, delayed_variables, kind) =
match self.aliases.iter().find(|(s, _, _, _)| *s == symbol) {
None => internal_error!(
"Alias {:?} not registered in delayed aliases! {:?}",
symbol,
&self.aliases
),
Some((_, typ, delayed_variables, kind)) => (typ, delayed_variables, kind),
Some(&(_, typ, delayed_variables, kind)) => (typ, delayed_variables, kind),
};
// TODO(types-soa) store SoA type in aliases directly
let typ = types.from_old_type(typ);
let mut substitutions: MutMap<_, _> = Default::default();
let old_type_variables = delayed_variables.type_variables(&mut self.variables);
@ -507,6 +526,7 @@ struct State {
#[allow(clippy::too_many_arguments)] // TODO: put params in a context/env var
pub fn run(
home: ModuleId,
types: Types,
constraints: &Constraints,
problems: &mut Vec<TypeError>,
mut subs: Subs,
@ -519,6 +539,7 @@ pub fn run(
) -> (Solved<Subs>, Env) {
let env = run_in_place(
home,
types,
constraints,
problems,
&mut subs,
@ -537,6 +558,7 @@ pub fn run(
#[allow(clippy::too_many_arguments)] // TODO: put params in a context/env var
fn run_in_place(
_home: ModuleId, // TODO: remove me?
mut types: Types,
constraints: &Constraints,
problems: &mut Vec<TypeError>,
subs: &mut Subs,
@ -561,6 +583,7 @@ fn run_in_place(
let pending_derives = PendingDerivesTable::new(
subs,
&mut types,
aliases,
pending_derives,
problems,
@ -580,6 +603,7 @@ fn run_in_place(
let state = solve(
&arena,
types,
constraints,
state,
rank,
@ -636,6 +660,7 @@ enum Work<'a> {
#[allow(clippy::too_many_arguments)]
fn solve(
arena: &Bump,
mut can_types: Types,
constraints: &Constraints,
mut state: State,
rank: Rank,
@ -694,6 +719,7 @@ fn solve(
problems,
abilities_store,
obligation_cache,
&mut can_types,
aliases,
subs,
let_con.def_types,
@ -757,6 +783,7 @@ fn solve(
problems,
abilities_store,
obligation_cache,
&mut can_types,
aliases,
subs,
let_con.def_types,
@ -869,26 +896,26 @@ fn solve(
let category = &constraints.categories[category_index.index()];
let actual = either_type_index_to_var(
constraints,
subs,
rank,
pools,
problems,
abilities_store,
obligation_cache,
&mut can_types,
aliases,
*type_index,
);
let expectation = &constraints.expectations[expectation_index.index()];
let expected = either_type_index_to_var(
constraints,
subs,
rank,
pools,
problems,
abilities_store,
obligation_cache,
&mut can_types,
aliases,
*expectation.get_type_ref(),
);
@ -951,13 +978,13 @@ fn solve(
// a special version of Eq that is used to store types in the AST.
// IT DOES NOT REPORT ERRORS!
let actual = either_type_index_to_var(
constraints,
subs,
rank,
pools,
&mut vec![], // don't report any extra errors
abilities_store,
obligation_cache,
&mut can_types,
aliases,
*source_index,
);
@ -994,13 +1021,13 @@ fn solve(
let expectation = &constraints.expectations[expectation_index.index()];
let expected = either_type_index_to_var(
constraints,
subs,
rank,
pools,
problems,
abilities_store,
obligation_cache,
&mut can_types,
aliases,
*expectation.get_type_ref(),
);
@ -1088,26 +1115,26 @@ fn solve(
let category = &constraints.pattern_categories[category_index.index()];
let actual = either_type_index_to_var(
constraints,
subs,
rank,
pools,
problems,
abilities_store,
obligation_cache,
&mut can_types,
aliases,
*type_index,
);
let expectation = &constraints.pattern_expectations[expectation_index.index()];
let expected = either_type_index_to_var(
constraints,
subs,
rank,
pools,
problems,
abilities_store,
obligation_cache,
&mut can_types,
aliases,
*expectation.get_type_ref(),
);
@ -1267,13 +1294,13 @@ fn solve(
}
IsOpenType(type_index) => {
let actual = either_type_index_to_var(
constraints,
subs,
rank,
pools,
problems,
abilities_store,
obligation_cache,
&mut can_types,
aliases,
*type_index,
);
@ -1296,13 +1323,13 @@ fn solve(
let pattern_category = &constraints.pattern_categories[pattern_category.index()];
let actual = either_type_index_to_var(
constraints,
subs,
rank,
pools,
problems,
abilities_store,
obligation_cache,
&mut can_types,
aliases,
*type_index,
);
@ -1312,10 +1339,10 @@ fn solve(
.map(|v| Type::Variable(*v))
.collect();
let tag_ty = Type::TagUnion(
let tag_ty = can_types.from_old_type(&Type::TagUnion(
vec![(tag_name.clone(), payload_types)],
TypeExtension::Closed,
);
));
let includes = type_to_var(
subs,
rank,
@ -1323,8 +1350,9 @@ fn solve(
abilities_store,
obligation_cache,
pools,
&mut can_types,
aliases,
&tag_ty,
tag_ty,
);
match unify(
@ -1428,25 +1456,25 @@ fn solve(
};
let real_var = either_type_index_to_var(
constraints,
subs,
rank,
pools,
problems,
abilities_store,
obligation_cache,
&mut can_types,
aliases,
real_var,
);
let branches_var = either_type_index_to_var(
constraints,
subs,
rank,
pools,
problems,
abilities_store,
obligation_cache,
&mut can_types,
aliases,
branches_var,
);
@ -2132,6 +2160,7 @@ impl LocalDefVarsVec<(Symbol, Loc<Variable>)> {
problems: &mut Vec<TypeError>,
abilities_store: &mut AbilitiesStore,
obligation_cache: &mut ObligationCache,
types: &mut Types,
aliases: &mut Aliases,
subs: &mut Subs,
def_types_slice: roc_can::constraint::DefTypes,
@ -2143,13 +2172,13 @@ impl LocalDefVarsVec<(Symbol, Loc<Variable>)> {
for (&(symbol, region), typ_index) in (loc_symbols_slice.iter()).zip(type_indices_slice) {
let var = either_type_index_to_var(
constraints,
subs,
rank,
pools,
problems,
abilities_store,
obligation_cache,
types,
aliases,
*typ_index,
);
@ -2161,7 +2190,7 @@ impl LocalDefVarsVec<(Symbol, Loc<Variable>)> {
}
}
use std::cell::{Cell, RefCell};
use std::cell::RefCell;
use std::ops::ControlFlow;
std::thread_local! {
/// Scratchpad arena so we don't need to allocate a new one all the time
@ -2179,30 +2208,35 @@ fn put_scratchpad(scratchpad: bumpalo::Bump) {
}
fn either_type_index_to_var(
constraints: &Constraints,
subs: &mut Subs,
rank: Rank,
pools: &mut Pools,
problems: &mut Vec<TypeError>,
abilities_store: &mut AbilitiesStore,
obligation_cache: &mut ObligationCache,
types: &mut Types,
aliases: &mut Aliases,
either_type_index: TypeOrVar,
) -> Variable {
match either_type_index.split() {
Ok(type_index) => {
let typ_cell = &constraints.types[type_index.index()];
type_cell_to_var(
// Converts the celled type to a variable, emplacing the new variable for re-use.
let var = type_to_var(
subs,
rank,
problems,
abilities_store,
obligation_cache,
pools,
types,
aliases,
typ_cell,
)
type_index,
);
unsafe {
types.emplace_variable(type_index, var);
}
var
}
Err(var_index) => {
// we cheat, and store the variable directly in the index
@ -2211,32 +2245,6 @@ fn either_type_index_to_var(
}
}
/// Converts a type in a cell to a variable, leaving the converted variable behind for re-use.
fn type_cell_to_var(
subs: &mut Subs,
rank: Rank,
problems: &mut Vec<TypeError>,
abilities_store: &mut AbilitiesStore,
obligation_cache: &mut ObligationCache,
pools: &mut Pools,
aliases: &mut Aliases,
typ_cell: &Cell<Type>,
) -> Variable {
let typ = typ_cell.replace(Type::EmptyTagUnion);
let var = type_to_var(
subs,
rank,
problems,
abilities_store,
obligation_cache,
pools,
aliases,
&typ,
);
typ_cell.replace(Type::Variable(var));
var
}
pub(crate) fn type_to_var(
subs: &mut Subs,
rank: Rank,
@ -2244,15 +2252,14 @@ pub(crate) fn type_to_var(
abilities_store: &mut AbilitiesStore,
obligation_cache: &mut ObligationCache,
pools: &mut Pools,
types: &mut Types,
aliases: &mut Aliases,
typ: &Type,
typ: Index<TypeTag>,
) -> Variable {
if let Type::Variable(var) = typ {
*var
if let TypeTag::Variable(var) = types[typ] {
var
} else {
let mut arena = take_scratchpad();
let mut types = Types::new();
let typ = types.from_old_type(typ);
let var = type_to_variable(
subs,
@ -2263,7 +2270,7 @@ pub(crate) fn type_to_var(
obligation_cache,
&arena,
aliases,
&mut types,
types,
typ,
false,
);

View file

@ -108,6 +108,7 @@ mod solve_expr {
exposed_types,
roc_target::TargetInfo::default_x86_64(),
roc_reporting::report::RenderTarget::Generic,
roc_reporting::report::DEFAULT_PALETTE,
);
dir.close()?;

View file

@ -25,8 +25,10 @@ roc_constrain = { path = "../constrain" }
roc_region = { path = "../region" }
roc_solve = { path = "../solve" }
roc_debug_flags = { path = "../debug_flags" }
bumpalo = { version = "3.11.0", features = ["collections"] }
indoc = "1.0.7"
ven_pretty = { path = "../../vendor/pretty" }
pretty_assertions = "1.3.0"
insta = "1.20.0"
bumpalo.workspace = true
indoc.workspace = true
pretty_assertions.workspace = true
insta.workspace = true

View file

@ -20,13 +20,14 @@ use roc_constrain::expr::constrain_decls;
use roc_debug_flags::dbg_do;
use roc_derive::DerivedModule;
use roc_derive_key::{DeriveBuiltin, DeriveError, DeriveKey, Derived};
use roc_load_internal::file::{add_imports, default_aliases, LoadedModule, Threading};
use roc_load_internal::file::{add_imports, LoadedModule, Threading};
use roc_module::symbol::{IdentIds, Interns, ModuleId, Symbol};
use roc_region::all::LineInfo;
use roc_reporting::report::{type_problem, RocDocAllocator};
use roc_types::{
pretty_print::{name_and_print_var, DebugPrint},
subs::{ExposedTypesStorageSubs, Subs, Variable},
types::Types,
};
const DERIVED_MODULE: ModuleId = ModuleId::DERIVED_SYNTH;
@ -343,11 +344,12 @@ fn check_derived_typechecks_and_golden(
check_golden: impl Fn(&str),
) {
// constrain the derived
let mut types = Types::new();
let mut constraints = Constraints::new();
let def_var = derived_def.expr_var;
let mut decls = Declarations::new();
decls.push_def(derived_def);
let constr = constrain_decls(&mut constraints, test_module, &decls);
let constr = constrain_decls(&mut types, &mut constraints, test_module, &decls);
// the derived implementation on stuff from the builtin module, so
// - we need to add those dependencies as imported on the constraint
@ -394,11 +396,12 @@ fn check_derived_typechecks_and_golden(
);
let (mut solved_subs, _, problems, _) = roc_solve::module::run_solve(
test_module,
types,
&constraints,
constr,
RigidVariables::default(),
test_subs,
default_aliases(),
Default::default(),
abilities_store,
Default::default(),
&exposed_for_module.exposed_by_module,
@ -486,6 +489,7 @@ where
Default::default(),
target_info,
roc_reporting::report::RenderTarget::ColorTerminal,
roc_reporting::report::DEFAULT_PALETTE,
Threading::AllAvailable,
)
.unwrap();

View file

@ -39,16 +39,18 @@ roc_target = { path = "../roc_target" }
roc_error_macros = { path = "../../error_macros" }
roc_std = { path = "../../roc_std" }
roc_debug_flags = {path="../debug_flags"}
bumpalo = { version = "3.11.0", features = ["collections"] }
libc = "0.2.135"
inkwell = { path = "../../vendor/inkwell" }
target-lexicon = "0.12.3"
libloading = "0.7.1"
tempfile = "3.2.0"
indoc = "1.0.7"
criterion = { git = "https://github.com/Anton-4/criterion.rs" }
wasm3 = { git = "https://github.com/roc-lang/wasm3-rs", rev = "f0f807d1fc0a50d1d68e5799e54ee62c05af00f5" }
lazy_static = "1.4.0"
bumpalo.workspace = true
libc.workspace = true
libloading.workspace = true
criterion.workspace = true
tempfile.workspace = true
indoc.workspace = true
wasm3.workspace = true
lazy_static.workspace = true
inkwell.workspace = true
target-lexicon.workspace = true
[features]
default = ["gen-llvm"]

View file

@ -4029,25 +4029,6 @@ fn mutually_recursive_captures() {
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn monomorphization_sees_polymorphic_recursion() {
assert_evals_to!(
indoc!(
r#"
foo : a, Bool -> Str
foo = \in, b -> if b then "done" else bar in
bar = \_ -> foo {} Bool.true
foo "" Bool.false
"#
),
RocStr::from("done"),
RocStr
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn int_let_generalization() {

View file

@ -53,6 +53,7 @@ pub fn helper(
let load_config = LoadConfig {
target_info: roc_target::TargetInfo::default_x86_64(),
render: roc_reporting::report::RenderTarget::ColorTerminal,
palette: roc_reporting::report::DEFAULT_PALETTE,
threading: Threading::Single,
exec_mode: ExecutionMode::Executable,
};

View file

@ -4,14 +4,13 @@ use std::path::PathBuf;
use inkwell::module::Module;
use libloading::Library;
use roc_build::link::llvm_module_to_dylib;
use roc_build::program::FunctionIterator;
use roc_collections::all::MutSet;
use roc_gen_llvm::llvm::externs::add_default_roc_externs;
use roc_gen_llvm::{llvm::build::LlvmBackendMode, run_roc::RocCallResult};
use roc_load::{EntryPoint, ExecutionMode, LoadConfig, Threading};
use roc_mono::ir::OptLevel;
use roc_region::all::LineInfo;
use roc_reporting::report::RenderTarget;
use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE};
use roc_utils::zig;
use target_lexicon::Triple;
@ -71,6 +70,7 @@ fn create_llvm_module<'a>(
let load_config = LoadConfig {
target_info,
render: RenderTarget::ColorTerminal,
palette: DEFAULT_PALETTE,
threading: Threading::Single,
exec_mode: ExecutionMode::Executable,
};
@ -106,7 +106,7 @@ fn create_llvm_module<'a>(
let mut delayed_errors = Vec::new();
for (home, (module_path, src)) in loaded.sources {
use roc_reporting::report::{can_problem, type_problem, RocDocAllocator, DEFAULT_PALETTE};
use roc_reporting::report::{can_problem, type_problem, RocDocAllocator};
let can_problems = loaded.can_problems.remove(&home).unwrap_or_default();
let type_problems = loaded.type_problems.remove(&home).unwrap_or_default();
@ -192,7 +192,7 @@ fn create_llvm_module<'a>(
debug_assert!(kind_id > 0);
let attr = context.create_enum_attribute(kind_id, 1);
for function in FunctionIterator::from_module(module) {
for function in module.get_functions() {
let name = function.get_name().to_str().unwrap();
if name.starts_with("roc_builtins") {
if name.starts_with("roc_builtins.expect") {

View file

@ -5,6 +5,7 @@ use roc_gen_wasm::wasm32_result::Wasm32Result;
use roc_gen_wasm::wasm_module::{Export, ExportType};
use roc_gen_wasm::DEBUG_SETTINGS;
use roc_load::{ExecutionMode, LoadConfig, Threading};
use roc_reporting::report::DEFAULT_PALETTE_HTML;
use std::marker::PhantomData;
use std::path::PathBuf;
use std::rc::Rc;
@ -87,6 +88,7 @@ fn compile_roc_to_wasm_bytes<'a, T: Wasm32Result>(
let load_config = LoadConfig {
target_info: roc_target::TargetInfo::default_wasm32(),
render: roc_reporting::report::RenderTarget::ColorTerminal,
palette: DEFAULT_PALETTE_HTML,
threading: Threading::Single,
exec_mode: ExecutionMode::Executable,
};

View file

@ -20,6 +20,8 @@ roc_mono = { path = "../mono" }
roc_target = { path = "../roc_target" }
roc_reporting = { path = "../../reporting" }
roc_tracing = { path = "../../tracing" }
test_mono_macros = { path = "../test_mono_macros" }
bumpalo = { version = "3.11.0", features = ["collections"] }
indoc = "1.0.7"
bumpalo.workspace = true
indoc.workspace = true

View file

@ -98,6 +98,7 @@ fn compiles_to_ir(test_name: &str, src: &str) {
target_info: TARGET_INFO,
threading: Threading::Single,
render: roc_reporting::report::RenderTarget::Generic,
palette: roc_reporting::report::DEFAULT_PALETTE,
exec_mode: ExecutionMode::Executable,
};
let loaded = roc_load::load_and_monomorphize_from_str(

View file

@ -13,6 +13,8 @@ roc_module = { path = "../module" }
roc_error_macros = {path="../../error_macros"}
roc_debug_flags = {path="../debug_flags"}
roc_serialize = {path="../serialize"}
bumpalo = { version = "3.11.0", features = ["collections"] }
static_assertions = "1.1.0"
ven_pretty = { path = "../../vendor/pretty" }
bumpalo.workspace = true
static_assertions.workspace = true

View file

@ -365,6 +365,7 @@ impl std::ops::Neg for Polarity {
}
}
#[derive(Debug)]
pub struct AliasShared {
pub symbol: Symbol,
pub type_argument_abilities: Slice<AbilitySet>,
@ -374,7 +375,7 @@ pub struct AliasShared {
}
/// The tag (head constructor) of a canonical type stored in [Types].
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Copy)]
pub enum TypeTag {
EmptyRecord,
EmptyTagUnion,
@ -456,6 +457,7 @@ impl AsideTypeSlice {
/// the [type solving representation][crate::subs::Content] of types.
///
/// See [TypeTag].
#[derive(Debug)]
pub struct Types {
// main storage. Each type is represented by a tag, which is identified by its index.
// `tags_slices` is a parallel array (so these two vectors always have the same size), that
@ -494,11 +496,31 @@ impl Default for Types {
}
impl Types {
pub const EMPTY_RECORD: Index<TypeTag> = Index::new(0);
const EMPTY_RECORD_TAG: TypeTag = TypeTag::Variable(Variable::EMPTY_RECORD);
const EMPTY_RECORD_ARGS: Slice<TypeTag> = Slice::empty();
pub const EMPTY_TAG_UNION: Index<TypeTag> = Index::new(1);
const EMPTY_TAG_UNION_TAG: TypeTag = TypeTag::Variable(Variable::EMPTY_TAG_UNION);
const EMPTY_TAG_UNION_ARGS: Slice<TypeTag> = Slice::empty();
pub const STR: Index<TypeTag> = Index::new(2);
const STR_TAG: TypeTag = TypeTag::Variable(Variable::STR);
const STR_ARGS: Slice<TypeTag> = Slice::empty();
pub fn new() -> Self {
Self {
// tags.len() == tags_slices.len()
tags: vec![TypeTag::EmptyRecord, TypeTag::EmptyTagUnion],
tags_slices: vec![Default::default(), Default::default()],
tags: vec![
Self::EMPTY_RECORD_TAG,
Self::EMPTY_TAG_UNION_TAG,
Self::STR_TAG,
],
tags_slices: vec![
Self::EMPTY_RECORD_ARGS,
Self::EMPTY_TAG_UNION_ARGS,
Self::STR_ARGS,
],
aside_types_slices: Default::default(),
@ -560,6 +582,13 @@ impl Types {
(tags, payload_slices)
}
/// # Safety
///
/// May only be called if `var` is known to represent the type at `index`.
pub unsafe fn emplace_variable(&mut self, index: Index<TypeTag>, var: Variable) {
self.tags[index.index()] = TypeTag::Variable(var);
}
fn reserve_type_tags(&mut self, length: usize) -> Slice<TypeTag> {
use std::iter::repeat;
@ -587,11 +616,18 @@ impl Types {
}
#[allow(clippy::wrong_self_convention)]
fn from_old_type_slice(&mut self, old: &[Type]) -> Slice<TypeTag> {
pub fn from_old_type_slice<B>(
&mut self,
// evil, but allows us to emulate reference-polymorphism
old: impl ExactSizeIterator<Item = B>,
) -> Slice<TypeTag>
where
B: std::borrow::Borrow<Type>,
{
let slice = self.reserve_type_tags(old.len());
for (index, argument) in slice.into_iter().zip(old) {
self.from_old_type_at(index, argument);
self.from_old_type_at(index, argument.borrow());
}
slice
@ -612,7 +648,7 @@ impl Types {
);
for (slice_index, (_, types)) in type_slices.indices().zip(tags) {
self.aside_types_slices[slice_index] = self.from_old_type_slice(types);
self.aside_types_slices[slice_index] = self.from_old_type_slice(types.iter());
}
let union_tags = UnionTags {
@ -686,6 +722,19 @@ impl Types {
index
}
pub fn function(
&mut self,
arguments: Slice<TypeTag>,
lambda_set: Index<TypeTag>,
ret: Index<TypeTag>,
) -> Index<TypeTag> {
let index = self.reserve_type_tag();
let tag = TypeTag::Function(lambda_set, ret);
self.set_type_tag(index, tag, arguments);
index
}
#[allow(clippy::wrong_self_convention)]
fn from_old_type_at(&mut self, index: Index<TypeTag>, old: &Type) {
match old {
@ -694,7 +743,7 @@ impl Types {
self.set_type_tag(index, TypeTag::EmptyTagUnion, Slice::default())
}
Type::Function(arguments, lambda_set, return_type) => {
let argument_slice = self.from_old_type_slice(arguments);
let argument_slice = self.from_old_type_slice(arguments.iter());
let tag = TypeTag::Function(
self.from_old_type(lambda_set),
@ -795,7 +844,7 @@ impl Types {
captures,
ambient_function,
} => {
let type_slice = self.from_old_type_slice(captures);
let type_slice = self.from_old_type_slice(captures.iter());
let tag = TypeTag::ClosureTag {
name: *name,
@ -909,7 +958,7 @@ impl Types {
actual_var,
actual,
} => {
let type_arguments_slice = self.from_old_type_slice(type_arguments);
let type_arguments_slice = self.from_old_type_slice(type_arguments.iter());
let lambda_set_slice = {
let slice = self.reserve_type_tags(lambda_set_variables.len());

View file

@ -21,9 +21,9 @@ roc_target = { path = "../compiler/roc_target" }
roc_collections = { path = "../compiler/collections" }
roc_highlight = { path = "../highlight"}
roc_reporting = { path = "../reporting"}
bumpalo = { version = "3.11.0", features = ["collections"] }
snafu = { version = "0.7.1", features = ["backtraces"] }
peg = "0.8.1"
bumpalo.workspace = true
snafu.workspace = true
peg.workspace = true
[dev-dependencies]
pretty_assertions = "1.3.0"
pretty_assertions.workspace = true

View file

@ -458,6 +458,7 @@ pub fn load_modules_for_files(filenames: Vec<PathBuf>) -> Vec<LoadedModule> {
let load_config = LoadConfig {
target_info: roc_target::TargetInfo::default_x86_64(), // This is just type-checking for docs, so "target" doesn't matter
render: roc_reporting::report::RenderTarget::ColorTerminal,
palette: roc_reporting::report::DEFAULT_PALETTE,
threading: Threading::AllAvailable,
exec_mode: ExecutionMode::Check,
};

View file

@ -22,4 +22,4 @@ roc_docs = { path = "../docs" }
clap = { version = "3.2.20", default-features = false, features = ["std", "color", "suggestions", "derive"] }
[target.'cfg(windows)'.dependencies]
libc = "0.2.135"
libc.workspace = true

View file

@ -3,7 +3,7 @@ use crate::types::{Env, Types};
use bumpalo::Bump;
use roc_intern::GlobalInterner;
use roc_load::{ExecutionMode, LoadConfig, LoadedModule, LoadingProblem, Threading};
use roc_reporting::report::RenderTarget;
use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE};
use roc_target::{Architecture, OperatingSystem, TargetInfo};
use std::fs::File;
use std::io::{self, ErrorKind, Write};
@ -100,6 +100,7 @@ pub fn load_types(
LoadConfig {
target_info,
render: RenderTarget::Generic,
palette: DEFAULT_PALETTE,
threading,
exec_mode: ExecutionMode::Check,
},

View file

@ -18,17 +18,18 @@ roc_collections = { path = "../compiler/collections" }
roc_error_macros = { path = "../error_macros" }
roc_load = { path = "../compiler/load" }
roc_reporting = { path = "../reporting" }
bumpalo = { version = "3.11.0", features = ["collections"] }
iced-x86 = { version = "1.15.0", default-features = false, features = ["std", "decoder", "op_code_info", "instr_info"] }
memmap2 = "0.5.7"
object = { version = "0.29.0", features = ["read", "write"] }
mach_object = "0.1"
serde = { version = "1.0.144", features = ["derive"] }
bincode = "1.3.3"
target-lexicon = "0.12.3"
tempfile = "3.2.0"
bumpalo.workspace = true
iced-x86.workspace = true
memmap2.workspace = true
object.workspace = true
mach_object.workspace = true
serde.workspace = true
bincode.workspace = true
target-lexicon.workspace = true
tempfile.workspace = true
[dev-dependencies]
indoc = "1.0.7"
libc = "0.2.135"
indoc.workspace = true
libc.workspace = true

View file

@ -9,7 +9,7 @@ use roc_build::link::{rebuild_host, LinkType};
use roc_error_macros::internal_error;
use roc_load::{EntryPoint, ExecutionMode, LoadConfig, Threading};
use roc_mono::ir::OptLevel;
use roc_reporting::report::RenderTarget;
use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE};
use std::cmp::Ordering;
use std::mem;
use std::path::{Path, PathBuf};
@ -117,6 +117,7 @@ pub fn generate_stub_lib(input_path: &Path, triple: &Triple) -> std::io::Result<
LoadConfig {
target_info,
render: RenderTarget::Generic,
palette: DEFAULT_PALETTE,
threading: Threading::AllAvailable,
exec_mode: ExecutionMode::Executable,
},

View file

@ -16,14 +16,14 @@ target-x86 = ["roc_build/target-x86"]
target-x86_64 = ["roc_build/target-x86_64"]
[dependencies]
bumpalo = {version = "3.11.0", features = ["collections"]}
const_format = { version = "0.2.23", features = ["const_generics"] }
inkwell = {path = "../vendor/inkwell"}
libloading = "0.7.1"
rustyline = {git = "https://github.com/roc-lang/rustyline", rev = "e74333c"}
rustyline-derive = {git = "https://github.com/roc-lang/rustyline", rev = "e74333c"}
target-lexicon = "0.12.2"
unicode-segmentation = "1.10.0"
inkwell.workspace = true
bumpalo.workspace = true
const_format.workspace = true
libloading.workspace = true
rustyline.workspace = true
rustyline-derive.workspace = true
target-lexicon.workspace = true
unicode-segmentation.workspace = true
roc_build = {path = "../compiler/build"}
roc_builtins = {path = "../compiler/builtins"}

View file

@ -9,7 +9,7 @@ description = "Provides the functionality for the REPL to evaluate Roc expressio
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bumpalo = { version = "3.11.0", features = ["collections"] }
bumpalo.workspace = true
roc_builtins = {path = "../compiler/builtins"}
roc_can = {path = "../compiler/can"}
@ -24,4 +24,4 @@ roc_region = {path = "../compiler/region"}
roc_reporting = {path = "../reporting"}
roc_std = {path = "../roc_std"}
roc_target = {path = "../compiler/roc_target"}
roc_types = {path = "../compiler/types"}
roc_types = {path = "../compiler/types"}

View file

@ -62,6 +62,7 @@ pub fn compile_to_mono<'a, 'i, I: Iterator<Item = &'i str>>(
LoadConfig {
target_info,
render: roc_reporting::report::RenderTarget::ColorTerminal,
palette,
threading: Threading::Single,
exec_mode: ExecutionMode::Executable,
},

View file

@ -7,8 +7,12 @@ license = "UPL-1.0"
description = "Supports evaluating expect and printing contextual information when they fail."
[dependencies]
bumpalo = {version = "3.11.0", features = ["collections"]}
target-lexicon = "0.12.2"
bumpalo.workspace = true
target-lexicon.workspace = true
libloading.workspace = true
signal-hook.workspace = true
libc.workspace = true
inkwell.workspace = true
roc_builtins = {path = "../compiler/builtins"}
roc_can = {path = "../compiler/can"}
@ -28,18 +32,14 @@ roc_region = { path = "../compiler/region" }
roc_build = { path = "../compiler/build" }
roc_error_macros = { path = "../error_macros" }
libloading = "0.7.1"
inkwell = { path = "../vendor/inkwell" }
signal-hook = "0.3.14"
libc = "0.2.135"
[dev-dependencies]
test_gen = { path = "../compiler/test_gen" }
roc_build = { path = "../compiler/build", features = ["target-aarch64", "target-x86_64"] }
tempfile = "3.2.0"
indoc = "1.0.7"
pretty_assertions = "1.3.0"
strip-ansi-escapes = "0.1.1"
tempfile.workspace = true
indoc.workspace = true
pretty_assertions.workspace = true
strip-ansi-escapes.workspace = true
[lib]

View file

@ -88,7 +88,7 @@ mod test {
use pretty_assertions::assert_eq;
use roc_gen_llvm::{llvm::build::LlvmBackendMode, run_roc::RocCallResult, run_roc_dylib};
use roc_load::{ExecutionMode, LoadConfig, Threading};
use roc_reporting::report::RenderTarget;
use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE};
use target_lexicon::Triple;
use crate::run::expect_mono_module_to_dylib;
@ -114,6 +114,7 @@ mod test {
let load_config = LoadConfig {
target_info,
render: RenderTarget::ColorTerminal,
palette: DEFAULT_PALETTE,
threading: Threading::Single,
exec_mode: ExecutionMode::Test,
};

Some files were not shown because too many files have changed in this diff Show more