mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 20:28:02 +00:00
Merge branch 'main' of https://github.com/roc-lang/roc into windows-final-cli-tests
This commit is contained in:
commit
5a447a9fcc
120 changed files with 6844 additions and 3696 deletions
|
@ -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
19
Cargo.lock
generated
|
@ -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",
|
||||
|
|
74
Cargo.toml
74
Cargo.toml
|
@ -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"
|
||||
|
|
|
@ -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"]}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -447,6 +447,7 @@ pub fn to_pattern2<'a>(
|
|||
unreachable!("should have been handled in RecordDestructure");
|
||||
}
|
||||
|
||||
Tuple(..) => todo!(),
|
||||
List(..) => todo!(),
|
||||
ListRest => todo!(),
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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"] }
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
@ -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());
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = []
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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("[");
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = []
|
||||
|
|
|
@ -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
|
@ -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> {
|
||||
|
|
|
@ -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)
|
||||
|
|
197
crates/compiler/gen_llvm/src/llvm/intrinsics.rs
Normal file
197
crates/compiler/gen_llvm/src/llvm/intrinsics.rs
Normal 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,
|
||||
)
|
||||
}
|
2454
crates/compiler/gen_llvm/src/llvm/lowlevel.rs
Normal file
2454
crates/compiler/gen_llvm/src/llvm/lowlevel.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -6,4 +6,6 @@ pub mod compare;
|
|||
pub mod convert;
|
||||
mod expect;
|
||||
pub mod externs;
|
||||
mod intrinsics;
|
||||
mod lowlevel;
|
||||
pub mod refcounting;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
||||
|
|
|
@ -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!(""),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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 = []
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)),
|
||||
},
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
],
|
||||
),
|
||||
)
|
|
@ -0,0 +1,4 @@
|
|||
( x, y ) : Foo
|
||||
( x, y ) = ( "foo", 3.14 )
|
||||
|
||||
x
|
|
@ -1,4 +1,4 @@
|
|||
Access(
|
||||
RecordAccess(
|
||||
Var {
|
||||
module_name: "",
|
||||
ident: "rec",
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
Tuple(
|
||||
[
|
||||
@1-2 Num(
|
||||
"1",
|
||||
),
|
||||
@4-5 Num(
|
||||
"2",
|
||||
),
|
||||
@7-8 Num(
|
||||
"3",
|
||||
),
|
||||
],
|
||||
)
|
|
@ -0,0 +1 @@
|
|||
(1, 2, 3)
|
|
@ -1,6 +1,6 @@
|
|||
Access(
|
||||
Access(
|
||||
Access(
|
||||
RecordAccess(
|
||||
RecordAccess(
|
||||
RecordAccess(
|
||||
Var {
|
||||
module_name: "",
|
||||
ident: "rec",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Access(
|
||||
RecordAccess(
|
||||
ParensAround(
|
||||
Var {
|
||||
module_name: "",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Access(
|
||||
RecordAccess(
|
||||
ParensAround(
|
||||
Var {
|
||||
module_name: "One.Two",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Access(
|
||||
Access(
|
||||
Access(
|
||||
RecordAccess(
|
||||
RecordAccess(
|
||||
RecordAccess(
|
||||
Var {
|
||||
module_name: "One.Two",
|
||||
ident: "rec",
|
||||
|
|
|
@ -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,
|
||||
)
|
|
@ -0,0 +1 @@
|
|||
.1 (1, 2, 3)
|
|
@ -1,5 +1,5 @@
|
|||
UnaryOp(
|
||||
@1-11 Access(
|
||||
@1-11 RecordAccess(
|
||||
Var {
|
||||
module_name: "",
|
||||
ident: "rec1",
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
],
|
||||
)
|
|
@ -0,0 +1,3 @@
|
|||
when {foo: (1, 2)} is
|
||||
{foo: (1, x)} -> x
|
||||
{foo: (_, b)} -> 3 + b
|
|
@ -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,
|
||||
},
|
||||
],
|
||||
)
|
|
@ -0,0 +1,3 @@
|
|||
when (1, 2) is
|
||||
(1, x) -> x
|
||||
(_, b) -> 3 + b
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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()?;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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") {
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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"}
|
||||
|
|
|
@ -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"}
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue