mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 08:34:33 +00:00
Merge branch 'trunk' into decision-tree-remove-clone
This commit is contained in:
commit
f49bd04e68
21 changed files with 463 additions and 491 deletions
|
@ -899,42 +899,6 @@ pub fn listSublist(
|
||||||
return RocList.empty();
|
return RocList.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listDrop(
|
|
||||||
list: RocList,
|
|
||||||
alignment: u32,
|
|
||||||
element_width: usize,
|
|
||||||
drop_count: usize,
|
|
||||||
dec: Dec,
|
|
||||||
) callconv(.C) RocList {
|
|
||||||
if (list.bytes) |source_ptr| {
|
|
||||||
const size = list.len();
|
|
||||||
const keep_count = size - drop_count;
|
|
||||||
|
|
||||||
var i: usize = 0;
|
|
||||||
const iterations = std.math.min(drop_count, size);
|
|
||||||
|
|
||||||
while (i < iterations) : (i += 1) {
|
|
||||||
const element = source_ptr + i * element_width;
|
|
||||||
dec(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drop_count >= size) {
|
|
||||||
return RocList.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = RocList.allocate(alignment, keep_count, element_width);
|
|
||||||
const target_ptr = output.bytes orelse unreachable;
|
|
||||||
|
|
||||||
@memcpy(target_ptr, source_ptr + drop_count * element_width, keep_count * element_width);
|
|
||||||
|
|
||||||
utils.decref(list.bytes, size * element_width, alignment);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
} else {
|
|
||||||
return RocList.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn listDropAt(
|
pub fn listDropAt(
|
||||||
list: RocList,
|
list: RocList,
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
|
|
|
@ -46,7 +46,6 @@ comptime {
|
||||||
exportListFn(list.listSortWith, "sort_with");
|
exportListFn(list.listSortWith, "sort_with");
|
||||||
exportListFn(list.listConcat, "concat");
|
exportListFn(list.listConcat, "concat");
|
||||||
exportListFn(list.listSublist, "sublist");
|
exportListFn(list.listSublist, "sublist");
|
||||||
exportListFn(list.listDrop, "drop");
|
|
||||||
exportListFn(list.listDropAt, "drop_at");
|
exportListFn(list.listDropAt, "drop_at");
|
||||||
exportListFn(list.listSet, "set");
|
exportListFn(list.listSet, "set");
|
||||||
exportListFn(list.listSetInPlace, "set_in_place");
|
exportListFn(list.listSetInPlace, "set_in_place");
|
||||||
|
|
|
@ -185,7 +185,6 @@ pub const LIST_REPEAT: &str = "roc_builtins.list.repeat";
|
||||||
pub const LIST_APPEND: &str = "roc_builtins.list.append";
|
pub const LIST_APPEND: &str = "roc_builtins.list.append";
|
||||||
pub const LIST_PREPEND: &str = "roc_builtins.list.prepend";
|
pub const LIST_PREPEND: &str = "roc_builtins.list.prepend";
|
||||||
pub const LIST_SUBLIST: &str = "roc_builtins.list.sublist";
|
pub const LIST_SUBLIST: &str = "roc_builtins.list.sublist";
|
||||||
pub const LIST_DROP: &str = "roc_builtins.list.drop";
|
|
||||||
pub const LIST_DROP_AT: &str = "roc_builtins.list.drop_at";
|
pub const LIST_DROP_AT: &str = "roc_builtins.list.drop_at";
|
||||||
pub const LIST_SWAP: &str = "roc_builtins.list.swap";
|
pub const LIST_SWAP: &str = "roc_builtins.list.swap";
|
||||||
pub const LIST_SINGLE: &str = "roc_builtins.list.single";
|
pub const LIST_SINGLE: &str = "roc_builtins.list.single";
|
||||||
|
|
|
@ -2150,20 +2150,33 @@ fn list_sublist(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
/// List.drop : List elem, Nat -> List elem
|
/// List.drop : List elem, Nat -> List elem
|
||||||
fn list_drop(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
fn list_drop(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let list_var = var_store.fresh();
|
let list_var = var_store.fresh();
|
||||||
let index_var = var_store.fresh();
|
let len_var = var_store.fresh();
|
||||||
|
|
||||||
|
let get_list_len = RunLowLevel {
|
||||||
|
op: LowLevel::ListLen,
|
||||||
|
args: vec![(list_var, Var(Symbol::ARG_1))],
|
||||||
|
ret_var: len_var,
|
||||||
|
};
|
||||||
|
|
||||||
|
let get_len = RunLowLevel {
|
||||||
|
op: LowLevel::NumSubWrap,
|
||||||
|
args: vec![(len_var, get_list_len), (len_var, Var(Symbol::ARG_2))],
|
||||||
|
ret_var: len_var,
|
||||||
|
};
|
||||||
|
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
op: LowLevel::ListDrop,
|
op: LowLevel::ListSublist,
|
||||||
args: vec![
|
args: vec![
|
||||||
(list_var, Var(Symbol::ARG_1)),
|
(list_var, Var(Symbol::ARG_1)),
|
||||||
(index_var, Var(Symbol::ARG_2)),
|
(len_var, Var(Symbol::ARG_2)),
|
||||||
|
(len_var, get_len),
|
||||||
],
|
],
|
||||||
ret_var: list_var,
|
ret_var: list_var,
|
||||||
};
|
};
|
||||||
|
|
||||||
defn(
|
defn(
|
||||||
symbol,
|
symbol,
|
||||||
vec![(list_var, Symbol::ARG_1), (index_var, Symbol::ARG_2)],
|
vec![(list_var, Symbol::ARG_1), (len_var, Symbol::ARG_2)],
|
||||||
var_store,
|
var_store,
|
||||||
body,
|
body,
|
||||||
list_var,
|
list_var,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::spaces::{fmt_spaces, INDENT};
|
use crate::spaces::{fmt_spaces, INDENT};
|
||||||
use bumpalo::collections::{String, Vec};
|
use bumpalo::collections::String;
|
||||||
use roc_parse::ast::Module;
|
use roc_parse::ast::{Collection, Module};
|
||||||
use roc_parse::header::{AppHeader, ExposesEntry, ImportsEntry, InterfaceHeader, PlatformHeader};
|
use roc_parse::header::{AppHeader, ExposesEntry, ImportsEntry, InterfaceHeader, PlatformHeader};
|
||||||
use roc_region::all::Located;
|
use roc_region::all::Located;
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ pub fn fmt_interface_header<'a>(buf: &mut String<'a>, header: &'a InterfaceHeade
|
||||||
fmt_spaces(buf, header.after_imports.iter(), indent);
|
fmt_spaces(buf, header.after_imports.iter(), indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt_imports(buf, &header.imports, indent);
|
fmt_imports(buf, header.imports, indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt_app_header<'a>(buf: &mut String<'a>, header: &'a AppHeader<'a>) {
|
pub fn fmt_app_header<'a>(buf: &mut String<'a>, header: &'a AppHeader<'a>) {
|
||||||
|
@ -76,7 +76,7 @@ pub fn fmt_app_header<'a>(buf: &mut String<'a>, header: &'a AppHeader<'a>) {
|
||||||
buf.push_str("imports");
|
buf.push_str("imports");
|
||||||
|
|
||||||
fmt_spaces(buf, header.before_imports.iter(), indent);
|
fmt_spaces(buf, header.before_imports.iter(), indent);
|
||||||
fmt_imports(buf, &header.imports, indent);
|
fmt_imports(buf, header.imports, indent);
|
||||||
fmt_spaces(buf, header.after_imports.iter(), indent);
|
fmt_spaces(buf, header.after_imports.iter(), indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ pub fn fmt_platform_header<'a>(_buf: &mut String<'a>, _header: &'a PlatformHeade
|
||||||
|
|
||||||
fn fmt_imports<'a>(
|
fn fmt_imports<'a>(
|
||||||
buf: &mut String<'a>,
|
buf: &mut String<'a>,
|
||||||
loc_entries: &'a Vec<'a, Located<ImportsEntry<'a>>>,
|
loc_entries: Collection<'a, Located<ImportsEntry<'a>>>,
|
||||||
indent: u16,
|
indent: u16,
|
||||||
) {
|
) {
|
||||||
buf.push('[');
|
buf.push('[');
|
||||||
|
@ -112,7 +112,7 @@ fn fmt_imports<'a>(
|
||||||
|
|
||||||
fn fmt_exposes<'a>(
|
fn fmt_exposes<'a>(
|
||||||
buf: &mut String<'a>,
|
buf: &mut String<'a>,
|
||||||
loc_entries: &'a Vec<'a, Located<ExposesEntry<'a, &'a str>>>,
|
loc_entries: &'a Collection<'a, Located<ExposesEntry<'a, &'a str>>>,
|
||||||
indent: u16,
|
indent: u16,
|
||||||
) {
|
) {
|
||||||
buf.push('[');
|
buf.push('[');
|
||||||
|
|
|
@ -227,88 +227,18 @@ where
|
||||||
ret_layout,
|
ret_layout,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
// For most builtins instead of calling a function, we can just inline the low level.
|
// If this function is just a lowlevel wrapper, then inline it
|
||||||
match *func_sym {
|
if let Some(lowlevel) = LowLevel::from_inlined_wrapper(*func_sym) {
|
||||||
Symbol::NUM_ABS => self.build_run_low_level(
|
self.build_run_low_level(
|
||||||
sym,
|
sym,
|
||||||
&LowLevel::NumAbs,
|
&lowlevel,
|
||||||
arguments,
|
arguments,
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
ret_layout,
|
ret_layout,
|
||||||
),
|
)
|
||||||
Symbol::NUM_ADD => self.build_run_low_level(
|
} else if func_sym
|
||||||
sym,
|
|
||||||
&LowLevel::NumAdd,
|
|
||||||
arguments,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout,
|
|
||||||
),
|
|
||||||
Symbol::NUM_ACOS => self.build_run_low_level(
|
|
||||||
sym,
|
|
||||||
&LowLevel::NumAcos,
|
|
||||||
arguments,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout,
|
|
||||||
),
|
|
||||||
Symbol::NUM_ASIN => self.build_run_low_level(
|
|
||||||
sym,
|
|
||||||
&LowLevel::NumAsin,
|
|
||||||
arguments,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout,
|
|
||||||
),
|
|
||||||
Symbol::NUM_ATAN => self.build_run_low_level(
|
|
||||||
sym,
|
|
||||||
&LowLevel::NumAtan,
|
|
||||||
arguments,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout,
|
|
||||||
),
|
|
||||||
Symbol::NUM_MUL => self.build_run_low_level(
|
|
||||||
sym,
|
|
||||||
&LowLevel::NumMul,
|
|
||||||
arguments,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout,
|
|
||||||
),
|
|
||||||
Symbol::NUM_POW_INT => self.build_run_low_level(
|
|
||||||
sym,
|
|
||||||
&LowLevel::NumPowInt,
|
|
||||||
arguments,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout,
|
|
||||||
),
|
|
||||||
Symbol::NUM_SUB => self.build_run_low_level(
|
|
||||||
sym,
|
|
||||||
&LowLevel::NumSub,
|
|
||||||
arguments,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout,
|
|
||||||
),
|
|
||||||
Symbol::NUM_ROUND => self.build_run_low_level(
|
|
||||||
sym,
|
|
||||||
&LowLevel::NumRound,
|
|
||||||
arguments,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout,
|
|
||||||
),
|
|
||||||
Symbol::BOOL_EQ => self.build_run_low_level(
|
|
||||||
sym,
|
|
||||||
&LowLevel::Eq,
|
|
||||||
arguments,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout,
|
|
||||||
),
|
|
||||||
Symbol::STR_CONCAT => self.build_run_low_level(
|
|
||||||
sym,
|
|
||||||
&LowLevel::StrConcat,
|
|
||||||
arguments,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout,
|
|
||||||
),
|
|
||||||
x if x
|
|
||||||
.module_string(&self.env().interns)
|
.module_string(&self.env().interns)
|
||||||
.starts_with(ModuleName::APP) =>
|
.starts_with(ModuleName::APP)
|
||||||
{
|
{
|
||||||
let fn_name = LayoutIds::default()
|
let fn_name = LayoutIds::default()
|
||||||
.get(*func_sym, layout)
|
.get(*func_sym, layout)
|
||||||
|
@ -316,8 +246,11 @@ where
|
||||||
// Now that the arguments are needed, load them if they are literals.
|
// Now that the arguments are needed, load them if they are literals.
|
||||||
self.load_literal_symbols(arguments)?;
|
self.load_literal_symbols(arguments)?;
|
||||||
self.build_fn_call(sym, fn_name, arguments, arg_layouts, ret_layout)
|
self.build_fn_call(sym, fn_name, arguments, arg_layouts, ret_layout)
|
||||||
}
|
} else {
|
||||||
x => Err(format!("the function, {:?}, is not yet implemented", x)),
|
Err(format!(
|
||||||
|
"the function, {:?}, is not yet implemented",
|
||||||
|
func_sym
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,10 @@ use crate::llvm::build_dict::{
|
||||||
use crate::llvm::build_hash::generic_hash;
|
use crate::llvm::build_hash::generic_hash;
|
||||||
use crate::llvm::build_list::{
|
use crate::llvm::build_list::{
|
||||||
self, allocate_list, empty_list, empty_polymorphic_list, list_any, list_append, list_concat,
|
self, allocate_list, empty_list, empty_polymorphic_list, list_any, list_append, list_concat,
|
||||||
list_contains, list_drop, list_drop_at, list_find_trivial_not_found, list_find_unsafe,
|
list_contains, list_drop_at, list_find_trivial_not_found, list_find_unsafe, list_get_unsafe,
|
||||||
list_get_unsafe, list_join, list_keep_errs, list_keep_if, list_keep_oks, list_len, list_map,
|
list_join, list_keep_errs, list_keep_if, list_keep_oks, list_len, list_map, list_map2,
|
||||||
list_map2, list_map3, list_map4, list_map_with_index, list_prepend, list_range, list_repeat,
|
list_map3, list_map4, list_map_with_index, list_prepend, list_range, list_repeat, list_reverse,
|
||||||
list_reverse, list_set, list_single, list_sort_with, list_sublist, list_swap,
|
list_set, list_single, list_sort_with, list_sublist, list_swap,
|
||||||
};
|
};
|
||||||
use crate::llvm::build_str::{
|
use crate::llvm::build_str::{
|
||||||
empty_str, str_concat, str_count_graphemes, str_ends_with, str_from_float, str_from_int,
|
empty_str, str_concat, str_count_graphemes, str_ends_with, str_from_float, str_from_int,
|
||||||
|
@ -5490,27 +5490,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
_ => unreachable!("Invalid layout {:?} in List.sublist", list_layout),
|
_ => unreachable!("Invalid layout {:?} in List.sublist", list_layout),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ListDrop => {
|
|
||||||
// List.drop : List elem, Nat -> List elem
|
|
||||||
debug_assert_eq!(args.len(), 2);
|
|
||||||
|
|
||||||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
|
||||||
let original_wrapper = list.into_struct_value();
|
|
||||||
|
|
||||||
let count = load_symbol(scope, &args[1]);
|
|
||||||
|
|
||||||
match list_layout {
|
|
||||||
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
|
||||||
Layout::Builtin(Builtin::List(element_layout)) => list_drop(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
original_wrapper,
|
|
||||||
count.into_int_value(),
|
|
||||||
element_layout,
|
|
||||||
),
|
|
||||||
_ => unreachable!("Invalid layout {:?} in List.drop", list_layout),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ListDropAt => {
|
ListDropAt => {
|
||||||
// List.dropAt : List elem, Nat -> List elem
|
// List.dropAt : List elem, Nat -> List elem
|
||||||
debug_assert_eq!(args.len(), 2);
|
debug_assert_eq!(args.len(), 2);
|
||||||
|
|
|
@ -328,28 +328,6 @@ pub fn list_sublist<'a, 'ctx, 'env>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List.drop : List elem, Nat -> List elem
|
|
||||||
pub fn list_drop<'a, 'ctx, 'env>(
|
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
|
||||||
layout_ids: &mut LayoutIds<'a>,
|
|
||||||
original_wrapper: StructValue<'ctx>,
|
|
||||||
count: IntValue<'ctx>,
|
|
||||||
element_layout: &Layout<'a>,
|
|
||||||
) -> BasicValueEnum<'ctx> {
|
|
||||||
let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout);
|
|
||||||
call_bitcode_fn_returns_list(
|
|
||||||
env,
|
|
||||||
&[
|
|
||||||
pass_list_cc(env, original_wrapper.into()),
|
|
||||||
env.alignment_intvalue(element_layout),
|
|
||||||
layout_width(env, element_layout),
|
|
||||||
count.into(),
|
|
||||||
dec_element_fn.as_global_value().as_pointer_value().into(),
|
|
||||||
],
|
|
||||||
bitcode::LIST_DROP,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// List.dropAt : List elem, Nat -> List elem
|
/// List.dropAt : List elem, Nat -> List elem
|
||||||
pub fn list_drop_at<'a, 'ctx, 'env>(
|
pub fn list_drop_at<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
|
|
|
@ -2,12 +2,13 @@ use bumpalo::{self, collections::Vec};
|
||||||
|
|
||||||
use code_builder::Align;
|
use code_builder::Align;
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
|
use roc_module::low_level::LowLevel;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_mono::ir::{CallType, Expr, JoinPointId, Literal, Proc, Stmt};
|
use roc_mono::ir::{CallType, Expr, JoinPointId, Literal, Proc, Stmt};
|
||||||
use roc_mono::layout::{Builtin, Layout, LayoutIds};
|
use roc_mono::layout::{Builtin, Layout, LayoutIds};
|
||||||
|
|
||||||
use crate::layout::WasmLayout;
|
use crate::layout::WasmLayout;
|
||||||
use crate::low_level::{build_call_low_level, LowlevelBuildResult};
|
use crate::low_level::{decode_low_level, LowlevelBuildResult};
|
||||||
use crate::storage::{Storage, StoredValue, StoredValueKind};
|
use crate::storage::{Storage, StoredValue, StoredValueKind};
|
||||||
use crate::wasm_module::linking::{
|
use crate::wasm_module::linking::{
|
||||||
DataSymbol, LinkingSection, RelocationSection, WasmObjectSymbol, WASM_SYM_BINDING_WEAK,
|
DataSymbol, LinkingSection, RelocationSection, WasmObjectSymbol, WASM_SYM_BINDING_WEAK,
|
||||||
|
@ -22,8 +23,8 @@ use crate::wasm_module::{
|
||||||
LocalId, Signature, SymInfo, ValueType,
|
LocalId, Signature, SymInfo, ValueType,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
copy_memory, CopyMemoryConfig, Env, BUILTINS_IMPORT_MODULE_NAME, MEMORY_NAME, PTR_TYPE,
|
copy_memory, CopyMemoryConfig, Env, BUILTINS_IMPORT_MODULE_NAME, MEMORY_NAME, PTR_SIZE,
|
||||||
STACK_POINTER_GLOBAL_ID, STACK_POINTER_NAME,
|
PTR_TYPE, STACK_POINTER_GLOBAL_ID, STACK_POINTER_NAME,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The memory address where the constants data will be loaded during module instantiation.
|
/// The memory address where the constants data will be loaded during module instantiation.
|
||||||
|
@ -469,6 +470,11 @@ impl<'a> WasmBackend<'a> {
|
||||||
arguments,
|
arguments,
|
||||||
}) => match call_type {
|
}) => match call_type {
|
||||||
CallType::ByName { name: func_sym, .. } => {
|
CallType::ByName { name: func_sym, .. } => {
|
||||||
|
// If this function is just a lowlevel wrapper, then inline it
|
||||||
|
if let Some(lowlevel) = LowLevel::from_inlined_wrapper(*func_sym) {
|
||||||
|
return self.build_low_level(lowlevel, arguments, wasm_layout);
|
||||||
|
}
|
||||||
|
|
||||||
let mut wasm_args_tmp: Vec<Symbol>;
|
let mut wasm_args_tmp: Vec<Symbol>;
|
||||||
let (wasm_args, has_return_val) = match wasm_layout {
|
let (wasm_args, has_return_val) = match wasm_layout {
|
||||||
WasmLayout::StackMemory { .. } => {
|
WasmLayout::StackMemory { .. } => {
|
||||||
|
@ -511,10 +517,50 @@ impl<'a> WasmBackend<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
CallType::LowLevel { op: lowlevel, .. } => {
|
CallType::LowLevel { op: lowlevel, .. } => {
|
||||||
let return_layout = WasmLayout::new(layout);
|
self.build_low_level(*lowlevel, arguments, wasm_layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
x => Err(format!("the call type, {:?}, is not yet implemented", x)),
|
||||||
|
},
|
||||||
|
|
||||||
|
Expr::Struct(fields) => self.create_struct(sym, layout, fields),
|
||||||
|
|
||||||
|
Expr::StructAtIndex {
|
||||||
|
index,
|
||||||
|
field_layouts,
|
||||||
|
structure,
|
||||||
|
} => {
|
||||||
|
if let StoredValue::StackMemory { location, .. } = self.storage.get(structure) {
|
||||||
|
let (local_id, mut offset) =
|
||||||
|
location.local_and_offset(self.storage.stack_frame_pointer);
|
||||||
|
for field in field_layouts.iter().take(*index as usize) {
|
||||||
|
offset += field.stack_size(PTR_SIZE);
|
||||||
|
}
|
||||||
|
self.storage.copy_value_from_memory(
|
||||||
|
&mut self.code_builder,
|
||||||
|
*sym,
|
||||||
|
local_id,
|
||||||
|
offset,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
unreachable!("Unexpected storage for {:?}", structure)
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
x => Err(format!("Expression is not yet implemented {:?}", x)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_low_level(
|
||||||
|
&mut self,
|
||||||
|
lowlevel: LowLevel,
|
||||||
|
arguments: &'a [Symbol],
|
||||||
|
return_layout: WasmLayout,
|
||||||
|
) -> Result<(), String> {
|
||||||
self.storage.load_symbols(&mut self.code_builder, arguments);
|
self.storage.load_symbols(&mut self.code_builder, arguments);
|
||||||
|
|
||||||
let build_result = build_call_low_level(
|
let build_result = decode_low_level(
|
||||||
&mut self.code_builder,
|
&mut self.code_builder,
|
||||||
&mut self.storage,
|
&mut self.storage,
|
||||||
lowlevel,
|
lowlevel,
|
||||||
|
@ -535,14 +581,6 @@ impl<'a> WasmBackend<'a> {
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x => Err(format!("the call type, {:?}, is not yet implemented", x)),
|
|
||||||
},
|
|
||||||
|
|
||||||
Expr::Struct(fields) => self.create_struct(sym, layout, fields),
|
|
||||||
|
|
||||||
x => Err(format!("Expression is not yet implemented {:?}", x)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_literal(
|
fn load_literal(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -741,14 +779,15 @@ impl<'a> WasmBackend<'a> {
|
||||||
};
|
};
|
||||||
self.module.import.entries.push(import);
|
self.module.import.entries.push(import);
|
||||||
|
|
||||||
let sym_idx = self.linker_symbols.len() as u32;
|
let sym_idx = self.linker_symbols.len();
|
||||||
let sym_info = SymInfo::Function(WasmObjectSymbol::Imported {
|
let sym_info = SymInfo::Function(WasmObjectSymbol::Imported {
|
||||||
flags: WASM_SYM_UNDEFINED,
|
flags: WASM_SYM_UNDEFINED,
|
||||||
index: import_index,
|
index: import_index,
|
||||||
});
|
});
|
||||||
self.linker_symbols.push(sym_info);
|
self.linker_symbols.push(sym_info);
|
||||||
|
self.builtin_sym_index_map.insert(name, sym_idx);
|
||||||
|
|
||||||
(import_index, sym_idx)
|
(import_index, sym_idx as u32)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.code_builder.call(
|
self.code_builder.call(
|
||||||
|
|
|
@ -15,10 +15,10 @@ pub enum LowlevelBuildResult {
|
||||||
NotImplemented,
|
NotImplemented,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_call_low_level<'a>(
|
pub fn decode_low_level<'a>(
|
||||||
code_builder: &mut CodeBuilder<'a>,
|
code_builder: &mut CodeBuilder<'a>,
|
||||||
storage: &mut Storage<'a>,
|
storage: &mut Storage<'a>,
|
||||||
lowlevel: &LowLevel,
|
lowlevel: LowLevel,
|
||||||
args: &'a [Symbol],
|
args: &'a [Symbol],
|
||||||
ret_layout: &WasmLayout,
|
ret_layout: &WasmLayout,
|
||||||
) -> LowlevelBuildResult {
|
) -> LowlevelBuildResult {
|
||||||
|
@ -34,9 +34,9 @@ pub fn build_call_low_level<'a>(
|
||||||
| ListConcat | ListContains | ListAppend | ListPrepend | ListJoin | ListRange | ListMap
|
| ListConcat | ListContains | ListAppend | ListPrepend | ListJoin | ListRange | ListMap
|
||||||
| ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListKeepIf | ListWalk
|
| ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListKeepIf | ListWalk
|
||||||
| ListWalkUntil | ListWalkBackwards | ListKeepOks | ListKeepErrs | ListSortWith
|
| ListWalkUntil | ListWalkBackwards | ListKeepOks | ListKeepErrs | ListSortWith
|
||||||
| ListSublist | ListDrop | ListDropAt | ListSwap | ListAny | ListFindUnsafe | DictSize
|
| ListSublist | ListDropAt | ListSwap | ListAny | ListFindUnsafe | DictSize | DictEmpty
|
||||||
| DictEmpty | DictInsert | DictRemove | DictContains | DictGetUnsafe | DictKeys
|
| DictInsert | DictRemove | DictContains | DictGetUnsafe | DictKeys | DictValues
|
||||||
| DictValues | DictUnion | DictIntersection | DictDifference | DictWalk | SetFromList => {
|
| DictUnion | DictIntersection | DictDifference | DictWalk | SetFromList => {
|
||||||
return NotImplemented;
|
return NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,6 +129,9 @@ pub fn build_call_low_level<'a>(
|
||||||
NumIsMultipleOf => return NotImplemented,
|
NumIsMultipleOf => return NotImplemented,
|
||||||
NumAbs => match ret_layout.value_type() {
|
NumAbs => match ret_layout.value_type() {
|
||||||
I32 => {
|
I32 => {
|
||||||
|
let arg_storage = storage.get(&args[0]).to_owned();
|
||||||
|
storage.ensure_value_has_local(code_builder, args[0], arg_storage);
|
||||||
|
storage.load_symbols(code_builder, args);
|
||||||
code_builder.i32_const(0);
|
code_builder.i32_const(0);
|
||||||
storage.load_symbols(code_builder, args);
|
storage.load_symbols(code_builder, args);
|
||||||
code_builder.i32_sub();
|
code_builder.i32_sub();
|
||||||
|
@ -138,6 +141,9 @@ pub fn build_call_low_level<'a>(
|
||||||
code_builder.select();
|
code_builder.select();
|
||||||
}
|
}
|
||||||
I64 => {
|
I64 => {
|
||||||
|
let arg_storage = storage.get(&args[0]).to_owned();
|
||||||
|
storage.ensure_value_has_local(code_builder, args[0], arg_storage);
|
||||||
|
storage.load_symbols(code_builder, args);
|
||||||
code_builder.i64_const(0);
|
code_builder.i64_const(0);
|
||||||
storage.load_symbols(code_builder, args);
|
storage.load_symbols(code_builder, args);
|
||||||
code_builder.i64_sub();
|
code_builder.i64_sub();
|
||||||
|
|
|
@ -319,6 +319,67 @@ impl<'a> Storage<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate code to copy a StoredValue from an arbitrary memory location
|
||||||
|
/// (defined by a pointer and offset).
|
||||||
|
pub fn copy_value_from_memory(
|
||||||
|
&mut self,
|
||||||
|
code_builder: &mut CodeBuilder,
|
||||||
|
to_symbol: Symbol,
|
||||||
|
from_ptr: LocalId,
|
||||||
|
from_offset: u32,
|
||||||
|
) -> u32 {
|
||||||
|
let to_storage = self.get(&to_symbol).to_owned();
|
||||||
|
match to_storage {
|
||||||
|
StoredValue::StackMemory {
|
||||||
|
location,
|
||||||
|
size,
|
||||||
|
alignment_bytes,
|
||||||
|
} => {
|
||||||
|
let (to_ptr, to_offset) = location.local_and_offset(self.stack_frame_pointer);
|
||||||
|
copy_memory(
|
||||||
|
code_builder,
|
||||||
|
CopyMemoryConfig {
|
||||||
|
from_ptr,
|
||||||
|
from_offset,
|
||||||
|
to_ptr,
|
||||||
|
to_offset,
|
||||||
|
size,
|
||||||
|
alignment_bytes,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
size
|
||||||
|
}
|
||||||
|
|
||||||
|
StoredValue::VirtualMachineStack {
|
||||||
|
value_type, size, ..
|
||||||
|
}
|
||||||
|
| StoredValue::Local {
|
||||||
|
value_type, size, ..
|
||||||
|
} => {
|
||||||
|
use crate::wasm_module::Align::*;
|
||||||
|
|
||||||
|
code_builder.get_local(from_ptr);
|
||||||
|
match (value_type, size) {
|
||||||
|
(ValueType::I64, 8) => code_builder.i64_load(Bytes8, from_offset),
|
||||||
|
(ValueType::I32, 4) => code_builder.i32_load(Bytes4, from_offset),
|
||||||
|
(ValueType::I32, 2) => code_builder.i32_load16_s(Bytes2, from_offset),
|
||||||
|
(ValueType::I32, 1) => code_builder.i32_load8_s(Bytes1, from_offset),
|
||||||
|
(ValueType::F32, 4) => code_builder.f32_load(Bytes4, from_offset),
|
||||||
|
(ValueType::F64, 8) => code_builder.f64_load(Bytes8, from_offset),
|
||||||
|
_ => {
|
||||||
|
panic!("Cannot store {:?} with alignment of {:?}", value_type, size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let StoredValue::Local { local_id, .. } = to_storage {
|
||||||
|
code_builder.set_local(local_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generate code to copy from one StoredValue to another
|
/// Generate code to copy from one StoredValue to another
|
||||||
/// Copies the _entire_ value. For struct fields etc., see `copy_value_to_memory`
|
/// Copies the _entire_ value. For struct fields etc., see `copy_value_to_memory`
|
||||||
pub fn clone_value(
|
pub fn clone_value(
|
||||||
|
|
|
@ -2608,8 +2608,8 @@ fn parse_header<'a>(
|
||||||
opt_shorthand,
|
opt_shorthand,
|
||||||
header_src,
|
header_src,
|
||||||
packages: &[],
|
packages: &[],
|
||||||
exposes: header.exposes.into_bump_slice(),
|
exposes: header.exposes.items,
|
||||||
imports: header.imports.into_bump_slice(),
|
imports: header.imports.items,
|
||||||
to_platform: None,
|
to_platform: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2642,8 +2642,8 @@ fn parse_header<'a>(
|
||||||
opt_shorthand,
|
opt_shorthand,
|
||||||
header_src,
|
header_src,
|
||||||
packages,
|
packages,
|
||||||
exposes: header.provides.into_bump_slice(),
|
exposes: header.provides.items,
|
||||||
imports: header.imports.into_bump_slice(),
|
imports: header.imports.items,
|
||||||
to_platform: Some(header.to.value.clone()),
|
to_platform: Some(header.to.value.clone()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3236,7 +3236,7 @@ fn send_header_two<'a>(
|
||||||
|
|
||||||
let extra = HeaderFor::PkgConfig {
|
let extra = HeaderFor::PkgConfig {
|
||||||
config_shorthand: shorthand,
|
config_shorthand: shorthand,
|
||||||
platform_main_type: requires[0].value.clone(),
|
platform_main_type: requires[0].value,
|
||||||
main_for_host,
|
main_for_host,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3409,8 +3409,7 @@ fn fabricate_pkg_config_module<'a>(
|
||||||
header_src: &'a str,
|
header_src: &'a str,
|
||||||
module_timing: ModuleTiming,
|
module_timing: ModuleTiming,
|
||||||
) -> (ModuleId, Msg<'a>) {
|
) -> (ModuleId, Msg<'a>) {
|
||||||
let provides: &'a [Located<ExposesEntry<'a, &'a str>>] =
|
let provides: &'a [Located<ExposesEntry<'a, &'a str>>] = header.provides.items;
|
||||||
header.provides.clone().into_bump_slice();
|
|
||||||
|
|
||||||
let info = PlatformHeaderInfo {
|
let info = PlatformHeaderInfo {
|
||||||
filename,
|
filename,
|
||||||
|
@ -3420,8 +3419,8 @@ fn fabricate_pkg_config_module<'a>(
|
||||||
app_module_id,
|
app_module_id,
|
||||||
packages: &[],
|
packages: &[],
|
||||||
provides,
|
provides,
|
||||||
requires: arena.alloc([header.requires.signature.clone()]),
|
requires: arena.alloc([header.requires.signature]),
|
||||||
imports: header.imports.clone().into_bump_slice(),
|
imports: header.imports.items,
|
||||||
};
|
};
|
||||||
|
|
||||||
send_header_two(
|
send_header_two(
|
||||||
|
@ -3467,7 +3466,7 @@ fn fabricate_effects_module<'a>(
|
||||||
{
|
{
|
||||||
let mut module_ids = (*module_ids).lock();
|
let mut module_ids = (*module_ids).lock();
|
||||||
|
|
||||||
for exposed in header.exposes {
|
for exposed in header.exposes.iter() {
|
||||||
if let ExposesEntry::Exposed(module_name) = exposed.value {
|
if let ExposesEntry::Exposed(module_name) = exposed.value {
|
||||||
module_ids.get_or_insert(&PQModuleName::Qualified(
|
module_ids.get_or_insert(&PQModuleName::Qualified(
|
||||||
shorthand,
|
shorthand,
|
||||||
|
@ -3886,7 +3885,7 @@ fn exposed_from_import<'a>(entry: &ImportsEntry<'a>) -> (QualifiedModuleName<'a>
|
||||||
Module(module_name, exposes) => {
|
Module(module_name, exposes) => {
|
||||||
let mut exposed = Vec::with_capacity(exposes.len());
|
let mut exposed = Vec::with_capacity(exposes.len());
|
||||||
|
|
||||||
for loc_entry in exposes {
|
for loc_entry in exposes.iter() {
|
||||||
exposed.push(ident_from_exposed(&loc_entry.value));
|
exposed.push(ident_from_exposed(&loc_entry.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3901,7 +3900,7 @@ fn exposed_from_import<'a>(entry: &ImportsEntry<'a>) -> (QualifiedModuleName<'a>
|
||||||
Package(package_name, module_name, exposes) => {
|
Package(package_name, module_name, exposes) => {
|
||||||
let mut exposed = Vec::with_capacity(exposes.len());
|
let mut exposed = Vec::with_capacity(exposes.len());
|
||||||
|
|
||||||
for loc_entry in exposes {
|
for loc_entry in exposes.iter() {
|
||||||
exposed.push(ident_from_exposed(&loc_entry.value));
|
exposed.push(ident_from_exposed(&loc_entry.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use crate::symbol::Symbol;
|
||||||
|
|
||||||
/// Low-level operations that get translated directly into e.g. LLVM instructions.
|
/// Low-level operations that get translated directly into e.g. LLVM instructions.
|
||||||
/// These are always wrapped when exposed to end users, and can only make it
|
/// These are always wrapped when exposed to end users, and can only make it
|
||||||
/// into an Expr when added directly by can::builtins
|
/// into an Expr when added directly by can::builtins
|
||||||
|
@ -45,7 +47,6 @@ pub enum LowLevel {
|
||||||
ListKeepErrs,
|
ListKeepErrs,
|
||||||
ListSortWith,
|
ListSortWith,
|
||||||
ListSublist,
|
ListSublist,
|
||||||
ListDrop,
|
|
||||||
ListDropAt,
|
ListDropAt,
|
||||||
ListSwap,
|
ListSwap,
|
||||||
ListAny,
|
ListAny,
|
||||||
|
@ -115,106 +116,6 @@ pub enum LowLevel {
|
||||||
ExpectTrue,
|
ExpectTrue,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! first_order {
|
|
||||||
() => {
|
|
||||||
StrConcat
|
|
||||||
| StrJoinWith
|
|
||||||
| StrIsEmpty
|
|
||||||
| StrStartsWith
|
|
||||||
| StrStartsWithCodePt
|
|
||||||
| StrEndsWith
|
|
||||||
| StrSplit
|
|
||||||
| StrCountGraphemes
|
|
||||||
| StrFromInt
|
|
||||||
| StrFromUtf8
|
|
||||||
| StrFromUtf8Range
|
|
||||||
| StrToUtf8
|
|
||||||
| StrRepeat
|
|
||||||
| StrTrim
|
|
||||||
| StrTrimLeft
|
|
||||||
| StrTrimRight
|
|
||||||
| StrFromFloat
|
|
||||||
| ListLen
|
|
||||||
| ListGetUnsafe
|
|
||||||
| ListSet
|
|
||||||
| ListSublist
|
|
||||||
| ListDrop
|
|
||||||
| ListDropAt
|
|
||||||
| ListSingle
|
|
||||||
| ListRepeat
|
|
||||||
| ListReverse
|
|
||||||
| ListConcat
|
|
||||||
| ListContains
|
|
||||||
| ListAppend
|
|
||||||
| ListPrepend
|
|
||||||
| ListJoin
|
|
||||||
| ListRange
|
|
||||||
| ListSwap
|
|
||||||
| DictSize
|
|
||||||
| DictEmpty
|
|
||||||
| DictInsert
|
|
||||||
| DictRemove
|
|
||||||
| DictContains
|
|
||||||
| DictGetUnsafe
|
|
||||||
| DictKeys
|
|
||||||
| DictValues
|
|
||||||
| DictUnion
|
|
||||||
| DictIntersection
|
|
||||||
| DictDifference
|
|
||||||
| SetFromList
|
|
||||||
| NumAdd
|
|
||||||
| NumAddWrap
|
|
||||||
| NumAddChecked
|
|
||||||
| NumSub
|
|
||||||
| NumSubWrap
|
|
||||||
| NumSubChecked
|
|
||||||
| NumMul
|
|
||||||
| NumMulWrap
|
|
||||||
| NumMulChecked
|
|
||||||
| NumGt
|
|
||||||
| NumGte
|
|
||||||
| NumLt
|
|
||||||
| NumLte
|
|
||||||
| NumCompare
|
|
||||||
| NumDivUnchecked
|
|
||||||
| NumDivCeilUnchecked
|
|
||||||
| NumRemUnchecked
|
|
||||||
| NumIsMultipleOf
|
|
||||||
| NumAbs
|
|
||||||
| NumNeg
|
|
||||||
| NumSin
|
|
||||||
| NumCos
|
|
||||||
| NumSqrtUnchecked
|
|
||||||
| NumLogUnchecked
|
|
||||||
| NumRound
|
|
||||||
| NumToFloat
|
|
||||||
| NumPow
|
|
||||||
| NumCeiling
|
|
||||||
| NumPowInt
|
|
||||||
| NumFloor
|
|
||||||
| NumIsFinite
|
|
||||||
| NumAtan
|
|
||||||
| NumAcos
|
|
||||||
| NumAsin
|
|
||||||
| NumBitwiseAnd
|
|
||||||
| NumBitwiseXor
|
|
||||||
| NumBitwiseOr
|
|
||||||
| NumShiftLeftBy
|
|
||||||
| NumShiftRightBy
|
|
||||||
| NumBytesToU16
|
|
||||||
| NumBytesToU32
|
|
||||||
| NumShiftRightZfBy
|
|
||||||
| NumIntCast
|
|
||||||
| Eq
|
|
||||||
| NotEq
|
|
||||||
| And
|
|
||||||
| Or
|
|
||||||
| Not
|
|
||||||
| Hash
|
|
||||||
| ExpectTrue
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! higher_order {
|
macro_rules! higher_order {
|
||||||
() => {
|
() => {
|
||||||
ListMap
|
ListMap
|
||||||
|
@ -241,17 +142,13 @@ impl LowLevel {
|
||||||
pub fn is_higher_order(&self) -> bool {
|
pub fn is_higher_order(&self) -> bool {
|
||||||
use LowLevel::*;
|
use LowLevel::*;
|
||||||
|
|
||||||
match self {
|
matches!(self, higher_order!())
|
||||||
first_order!() => false,
|
|
||||||
higher_order!() => true,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn function_argument_position(&self) -> usize {
|
pub fn function_argument_position(&self) -> usize {
|
||||||
use LowLevel::*;
|
use LowLevel::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
first_order!() => unreachable!(),
|
|
||||||
ListMap => 1,
|
ListMap => 1,
|
||||||
ListMap2 => 2,
|
ListMap2 => 2,
|
||||||
ListMap3 => 3,
|
ListMap3 => 3,
|
||||||
|
@ -267,6 +164,127 @@ impl LowLevel {
|
||||||
ListAny => 1,
|
ListAny => 1,
|
||||||
ListFindUnsafe => 1,
|
ListFindUnsafe => 1,
|
||||||
DictWalk => 2,
|
DictWalk => 2,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used in dev backends to inline some lowlevel wrapper functions
|
||||||
|
/// For wrappers that contain logic, we return None to prevent inlining
|
||||||
|
/// (Mention each explicitly rather than using `_`, to show they have not been forgotten)
|
||||||
|
pub fn from_inlined_wrapper(symbol: Symbol) -> Option<LowLevel> {
|
||||||
|
use LowLevel::*;
|
||||||
|
|
||||||
|
match symbol {
|
||||||
|
Symbol::STR_CONCAT => Some(StrConcat),
|
||||||
|
Symbol::STR_JOIN_WITH => Some(StrJoinWith),
|
||||||
|
Symbol::STR_IS_EMPTY => Some(StrIsEmpty),
|
||||||
|
Symbol::STR_STARTS_WITH => Some(StrStartsWith),
|
||||||
|
Symbol::STR_STARTS_WITH_CODE_PT => Some(StrStartsWithCodePt),
|
||||||
|
Symbol::STR_ENDS_WITH => Some(StrEndsWith),
|
||||||
|
Symbol::STR_SPLIT => Some(StrSplit),
|
||||||
|
Symbol::STR_COUNT_GRAPHEMES => Some(StrCountGraphemes),
|
||||||
|
Symbol::STR_FROM_INT => Some(StrFromInt),
|
||||||
|
Symbol::STR_FROM_UTF8 => None,
|
||||||
|
Symbol::STR_FROM_UTF8_RANGE => None,
|
||||||
|
Symbol::STR_TO_UTF8 => Some(StrToUtf8),
|
||||||
|
Symbol::STR_REPEAT => Some(StrRepeat),
|
||||||
|
Symbol::STR_FROM_FLOAT => Some(StrFromFloat),
|
||||||
|
Symbol::STR_TRIM => Some(StrTrim),
|
||||||
|
Symbol::STR_TRIM_LEFT => Some(StrTrimLeft),
|
||||||
|
Symbol::STR_TRIM_RIGHT => Some(StrTrimRight),
|
||||||
|
Symbol::LIST_LEN => Some(ListLen),
|
||||||
|
Symbol::LIST_GET => None,
|
||||||
|
Symbol::LIST_SET => None,
|
||||||
|
Symbol::LIST_SINGLE => Some(ListSingle),
|
||||||
|
Symbol::LIST_REPEAT => Some(ListRepeat),
|
||||||
|
Symbol::LIST_REVERSE => Some(ListReverse),
|
||||||
|
Symbol::LIST_CONCAT => Some(ListConcat),
|
||||||
|
Symbol::LIST_CONTAINS => Some(ListContains),
|
||||||
|
Symbol::LIST_APPEND => Some(ListAppend),
|
||||||
|
Symbol::LIST_PREPEND => Some(ListPrepend),
|
||||||
|
Symbol::LIST_JOIN => Some(ListJoin),
|
||||||
|
Symbol::LIST_RANGE => Some(ListRange),
|
||||||
|
Symbol::LIST_MAP => Some(ListMap),
|
||||||
|
Symbol::LIST_MAP2 => Some(ListMap2),
|
||||||
|
Symbol::LIST_MAP3 => Some(ListMap3),
|
||||||
|
Symbol::LIST_MAP4 => Some(ListMap4),
|
||||||
|
Symbol::LIST_MAP_WITH_INDEX => Some(ListMapWithIndex),
|
||||||
|
Symbol::LIST_KEEP_IF => Some(ListKeepIf),
|
||||||
|
Symbol::LIST_WALK => Some(ListWalk),
|
||||||
|
Symbol::LIST_WALK_UNTIL => Some(ListWalkUntil),
|
||||||
|
Symbol::LIST_WALK_BACKWARDS => Some(ListWalkBackwards),
|
||||||
|
Symbol::LIST_KEEP_OKS => Some(ListKeepOks),
|
||||||
|
Symbol::LIST_KEEP_ERRS => Some(ListKeepErrs),
|
||||||
|
Symbol::LIST_SORT_WITH => Some(ListSortWith),
|
||||||
|
Symbol::LIST_SUBLIST => Some(ListSublist),
|
||||||
|
Symbol::LIST_DROP_AT => Some(ListDropAt),
|
||||||
|
Symbol::LIST_SWAP => Some(ListSwap),
|
||||||
|
Symbol::LIST_ANY => Some(ListAny),
|
||||||
|
Symbol::LIST_FIND => None,
|
||||||
|
Symbol::DICT_LEN => Some(DictSize),
|
||||||
|
Symbol::DICT_EMPTY => Some(DictEmpty),
|
||||||
|
Symbol::DICT_INSERT => Some(DictInsert),
|
||||||
|
Symbol::DICT_REMOVE => Some(DictRemove),
|
||||||
|
Symbol::DICT_CONTAINS => Some(DictContains),
|
||||||
|
Symbol::DICT_GET => None,
|
||||||
|
Symbol::DICT_KEYS => Some(DictKeys),
|
||||||
|
Symbol::DICT_VALUES => Some(DictValues),
|
||||||
|
Symbol::DICT_UNION => Some(DictUnion),
|
||||||
|
Symbol::DICT_INTERSECTION => Some(DictIntersection),
|
||||||
|
Symbol::DICT_DIFFERENCE => Some(DictDifference),
|
||||||
|
Symbol::DICT_WALK => Some(DictWalk),
|
||||||
|
Symbol::SET_FROM_LIST => Some(SetFromList),
|
||||||
|
Symbol::NUM_ADD => Some(NumAdd),
|
||||||
|
Symbol::NUM_ADD_WRAP => Some(NumAddWrap),
|
||||||
|
Symbol::NUM_ADD_CHECKED => None,
|
||||||
|
Symbol::NUM_SUB => Some(NumSub),
|
||||||
|
Symbol::NUM_SUB_WRAP => Some(NumSubWrap),
|
||||||
|
Symbol::NUM_SUB_CHECKED => None,
|
||||||
|
Symbol::NUM_MUL => Some(NumMul),
|
||||||
|
Symbol::NUM_MUL_WRAP => Some(NumMulWrap),
|
||||||
|
Symbol::NUM_MUL_CHECKED => None,
|
||||||
|
Symbol::NUM_GT => Some(NumGt),
|
||||||
|
Symbol::NUM_GTE => Some(NumGte),
|
||||||
|
Symbol::NUM_LT => Some(NumLt),
|
||||||
|
Symbol::NUM_LTE => Some(NumLte),
|
||||||
|
Symbol::NUM_COMPARE => Some(NumCompare),
|
||||||
|
Symbol::NUM_DIV_FLOAT => None,
|
||||||
|
Symbol::NUM_DIV_CEIL => None,
|
||||||
|
Symbol::NUM_REM => None,
|
||||||
|
Symbol::NUM_IS_MULTIPLE_OF => Some(NumIsMultipleOf),
|
||||||
|
Symbol::NUM_ABS => Some(NumAbs),
|
||||||
|
Symbol::NUM_NEG => Some(NumNeg),
|
||||||
|
Symbol::NUM_SIN => Some(NumSin),
|
||||||
|
Symbol::NUM_COS => Some(NumCos),
|
||||||
|
Symbol::NUM_SQRT => None,
|
||||||
|
Symbol::NUM_LOG => None,
|
||||||
|
Symbol::NUM_ROUND => Some(NumRound),
|
||||||
|
Symbol::NUM_TO_FLOAT => Some(NumToFloat),
|
||||||
|
Symbol::NUM_POW => Some(NumPow),
|
||||||
|
Symbol::NUM_CEILING => Some(NumCeiling),
|
||||||
|
Symbol::NUM_POW_INT => Some(NumPowInt),
|
||||||
|
Symbol::NUM_FLOOR => Some(NumFloor),
|
||||||
|
// => Some(NumIsFinite),
|
||||||
|
Symbol::NUM_ATAN => Some(NumAtan),
|
||||||
|
Symbol::NUM_ACOS => Some(NumAcos),
|
||||||
|
Symbol::NUM_ASIN => Some(NumAsin),
|
||||||
|
Symbol::NUM_BYTES_TO_U16 => None,
|
||||||
|
Symbol::NUM_BYTES_TO_U32 => None,
|
||||||
|
Symbol::NUM_BITWISE_AND => Some(NumBitwiseAnd),
|
||||||
|
Symbol::NUM_BITWISE_XOR => Some(NumBitwiseXor),
|
||||||
|
Symbol::NUM_BITWISE_OR => Some(NumBitwiseOr),
|
||||||
|
Symbol::NUM_SHIFT_LEFT => Some(NumShiftLeftBy),
|
||||||
|
Symbol::NUM_SHIFT_RIGHT => Some(NumShiftRightBy),
|
||||||
|
Symbol::NUM_SHIFT_RIGHT_ZERO_FILL => Some(NumShiftRightZfBy),
|
||||||
|
Symbol::NUM_INT_CAST => Some(NumIntCast),
|
||||||
|
Symbol::BOOL_EQ => Some(Eq),
|
||||||
|
Symbol::BOOL_NEQ => Some(NotEq),
|
||||||
|
Symbol::BOOL_AND => Some(And),
|
||||||
|
Symbol::BOOL_OR => Some(Or),
|
||||||
|
Symbol::BOOL_NOT => Some(Not),
|
||||||
|
// => Some(Hash),
|
||||||
|
// => Some(ExpectTrue),
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -968,7 +968,6 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
|
||||||
// List.append should own its first argument
|
// List.append should own its first argument
|
||||||
ListAppend => arena.alloc_slice_copy(&[owned, owned]),
|
ListAppend => arena.alloc_slice_copy(&[owned, owned]),
|
||||||
ListSublist => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]),
|
ListSublist => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]),
|
||||||
ListDrop => arena.alloc_slice_copy(&[owned, irrelevant]),
|
|
||||||
ListDropAt => arena.alloc_slice_copy(&[owned, irrelevant]),
|
ListDropAt => arena.alloc_slice_copy(&[owned, irrelevant]),
|
||||||
ListSwap => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]),
|
ListSwap => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]),
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,6 @@ enum FirstOrder {
|
||||||
ListGetUnsafe,
|
ListGetUnsafe,
|
||||||
ListSet,
|
ListSet,
|
||||||
ListSublist,
|
ListSublist,
|
||||||
ListDrop,
|
|
||||||
ListDropAt,
|
ListDropAt,
|
||||||
ListSingle,
|
ListSingle,
|
||||||
ListRepeat,
|
ListRepeat,
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub enum PackageOrPath<'a> {
|
||||||
Path(StrLiteral<'a>),
|
Path(StrLiteral<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
pub struct ModuleName<'a>(&'a str);
|
pub struct ModuleName<'a>(&'a str);
|
||||||
|
|
||||||
impl<'a> From<ModuleName<'a>> for &'a str {
|
impl<'a> From<ModuleName<'a>> for &'a str {
|
||||||
|
@ -60,8 +60,8 @@ impl<'a> ModuleName<'a> {
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct InterfaceHeader<'a> {
|
pub struct InterfaceHeader<'a> {
|
||||||
pub name: Loc<ModuleName<'a>>,
|
pub name: Loc<ModuleName<'a>>,
|
||||||
pub exposes: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>,
|
pub exposes: Collection<'a, Loc<ExposesEntry<'a, &'a str>>>,
|
||||||
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
|
pub imports: Collection<'a, Loc<ImportsEntry<'a>>>,
|
||||||
|
|
||||||
// Potential comments and newlines - these will typically all be empty.
|
// Potential comments and newlines - these will typically all be empty.
|
||||||
pub before_header: &'a [CommentOrNewline<'a>],
|
pub before_header: &'a [CommentOrNewline<'a>],
|
||||||
|
@ -82,8 +82,8 @@ pub enum To<'a> {
|
||||||
pub struct AppHeader<'a> {
|
pub struct AppHeader<'a> {
|
||||||
pub name: Loc<StrLiteral<'a>>,
|
pub name: Loc<StrLiteral<'a>>,
|
||||||
pub packages: Collection<'a, Loc<PackageEntry<'a>>>,
|
pub packages: Collection<'a, Loc<PackageEntry<'a>>>,
|
||||||
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
|
pub imports: Collection<'a, Loc<ImportsEntry<'a>>>,
|
||||||
pub provides: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>,
|
pub provides: Collection<'a, Loc<ExposesEntry<'a, &'a str>>>,
|
||||||
pub to: Loc<To<'a>>,
|
pub to: Loc<To<'a>>,
|
||||||
|
|
||||||
// Potential comments and newlines - these will typically all be empty.
|
// Potential comments and newlines - these will typically all be empty.
|
||||||
|
@ -117,7 +117,7 @@ pub struct PackageHeader<'a> {
|
||||||
pub after_imports: &'a [CommentOrNewline<'a>],
|
pub after_imports: &'a [CommentOrNewline<'a>],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum PlatformRigid<'a> {
|
pub enum PlatformRigid<'a> {
|
||||||
Entry { rigid: &'a str, alias: &'a str },
|
Entry { rigid: &'a str, alias: &'a str },
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ impl<'a> Spaceable<'a> for PlatformRigid<'a> {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct PlatformRequires<'a> {
|
pub struct PlatformRequires<'a> {
|
||||||
pub rigids: Vec<'a, Loc<PlatformRigid<'a>>>,
|
pub rigids: Collection<'a, Loc<PlatformRigid<'a>>>,
|
||||||
pub signature: Loc<TypedIdent<'a>>,
|
pub signature: Loc<TypedIdent<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,10 +145,10 @@ pub struct PlatformRequires<'a> {
|
||||||
pub struct PlatformHeader<'a> {
|
pub struct PlatformHeader<'a> {
|
||||||
pub name: Loc<PackageName<'a>>,
|
pub name: Loc<PackageName<'a>>,
|
||||||
pub requires: PlatformRequires<'a>,
|
pub requires: PlatformRequires<'a>,
|
||||||
pub exposes: Vec<'a, Loc<ExposesEntry<'a, ModuleName<'a>>>>,
|
pub exposes: Collection<'a, Loc<ExposesEntry<'a, ModuleName<'a>>>>,
|
||||||
pub packages: Collection<'a, Loc<PackageEntry<'a>>>,
|
pub packages: Collection<'a, Loc<PackageEntry<'a>>>,
|
||||||
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
|
pub imports: Collection<'a, Loc<ImportsEntry<'a>>>,
|
||||||
pub provides: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>,
|
pub provides: Collection<'a, Loc<ExposesEntry<'a, &'a str>>>,
|
||||||
pub effects: Effects<'a>,
|
pub effects: Effects<'a>,
|
||||||
|
|
||||||
// Potential comments and newlines - these will typically all be empty.
|
// Potential comments and newlines - these will typically all be empty.
|
||||||
|
@ -177,7 +177,7 @@ pub struct Effects<'a> {
|
||||||
pub entries: &'a [Loc<TypedIdent<'a>>],
|
pub entries: &'a [Loc<TypedIdent<'a>>],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum ExposesEntry<'a, T> {
|
pub enum ExposesEntry<'a, T> {
|
||||||
/// e.g. `Task`
|
/// e.g. `Task`
|
||||||
Exposed(T),
|
Exposed(T),
|
||||||
|
@ -196,16 +196,19 @@ impl<'a, T> Spaceable<'a> for ExposesEntry<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum ImportsEntry<'a> {
|
pub enum ImportsEntry<'a> {
|
||||||
/// e.g. `Task` or `Task.{ Task, after }`
|
/// e.g. `Task` or `Task.{ Task, after }`
|
||||||
Module(ModuleName<'a>, Vec<'a, Loc<ExposesEntry<'a, &'a str>>>),
|
Module(
|
||||||
|
ModuleName<'a>,
|
||||||
|
Collection<'a, Loc<ExposesEntry<'a, &'a str>>>,
|
||||||
|
),
|
||||||
|
|
||||||
/// e.g. `base.Task` or `base.Task.{ after }` or `base.{ Task.{ Task, after } }`
|
/// e.g. `base.Task` or `base.Task.{ after }` or `base.{ Task.{ Task, after } }`
|
||||||
Package(
|
Package(
|
||||||
&'a str,
|
&'a str,
|
||||||
ModuleName<'a>,
|
ModuleName<'a>,
|
||||||
Vec<'a, Loc<ExposesEntry<'a, &'a str>>>,
|
Collection<'a, Loc<ExposesEntry<'a, &'a str>>>,
|
||||||
),
|
),
|
||||||
|
|
||||||
// Spaces
|
// Spaces
|
||||||
|
@ -224,7 +227,7 @@ impl<'a> ExposesEntry<'a, &'a str> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum TypedIdent<'a> {
|
pub enum TypedIdent<'a> {
|
||||||
/// e.g.
|
/// e.g.
|
||||||
///
|
///
|
||||||
|
|
|
@ -220,11 +220,11 @@ fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
let opt_imports: Option<(
|
let opt_imports: Option<(
|
||||||
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
||||||
Vec<'a, Located<ImportsEntry<'a>>>,
|
Collection<'a, Located<ImportsEntry<'a>>>,
|
||||||
)> = opt_imports;
|
)> = opt_imports;
|
||||||
|
|
||||||
let ((before_imports, after_imports), imports) =
|
let ((before_imports, after_imports), imports) =
|
||||||
opt_imports.unwrap_or_else(|| ((&[] as _, &[] as _), Vec::new_in(arena)));
|
opt_imports.unwrap_or_else(|| ((&[] as _, &[] as _), Collection::empty()));
|
||||||
let provides: ProvidesTo<'a> = provides; // rustc must be told the type here
|
let provides: ProvidesTo<'a> = provides; // rustc must be told the type here
|
||||||
|
|
||||||
let header = AppHeader {
|
let header = AppHeader {
|
||||||
|
@ -303,7 +303,7 @@ fn platform_header<'a>() -> impl Parser<'a, PlatformHeader<'a>, EHeader<'a>> {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ProvidesTo<'a> {
|
struct ProvidesTo<'a> {
|
||||||
entries: Vec<'a, Located<ExposesEntry<'a, &'a str>>>,
|
entries: Collection<'a, Located<ExposesEntry<'a, &'a str>>>,
|
||||||
to: Located<To<'a>>,
|
to: Located<To<'a>>,
|
||||||
|
|
||||||
before_provides_keyword: &'a [CommentOrNewline<'a>],
|
before_provides_keyword: &'a [CommentOrNewline<'a>],
|
||||||
|
@ -362,7 +362,7 @@ fn provides_without_to<'a>() -> impl Parser<
|
||||||
'a,
|
'a,
|
||||||
(
|
(
|
||||||
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
||||||
Vec<'a, Located<ExposesEntry<'a, &'a str>>>,
|
Collection<'a, Located<ExposesEntry<'a, &'a str>>>,
|
||||||
),
|
),
|
||||||
EProvides<'a>,
|
EProvides<'a>,
|
||||||
> {
|
> {
|
||||||
|
@ -376,14 +376,16 @@ fn provides_without_to<'a>() -> impl Parser<
|
||||||
EProvides::IndentProvides,
|
EProvides::IndentProvides,
|
||||||
EProvides::IndentListStart
|
EProvides::IndentListStart
|
||||||
),
|
),
|
||||||
collection_e!(
|
collection_trailing_sep_e!(
|
||||||
word1(b'[', EProvides::ListStart),
|
word1(b'[', EProvides::ListStart),
|
||||||
exposes_entry(EProvides::Identifier),
|
exposes_entry(EProvides::Identifier),
|
||||||
word1(b',', EProvides::ListEnd),
|
word1(b',', EProvides::ListEnd),
|
||||||
word1(b']', EProvides::ListEnd),
|
word1(b']', EProvides::ListEnd),
|
||||||
min_indent,
|
min_indent,
|
||||||
|
EProvides::Open,
|
||||||
EProvides::Space,
|
EProvides::Space,
|
||||||
EProvides::IndentListEnd
|
EProvides::IndentListEnd,
|
||||||
|
ExposesEntry::SpaceBefore
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -442,15 +444,17 @@ fn platform_requires<'a>() -> impl Parser<'a, PlatformRequires<'a>, ERequires<'a
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn requires_rigids<'a>(
|
fn requires_rigids<'a>(
|
||||||
min_indent: u16,
|
min_indent: u16,
|
||||||
) -> impl Parser<'a, Vec<'a, Located<PlatformRigid<'a>>>, ERequires<'a>> {
|
) -> impl Parser<'a, Collection<'a, Located<PlatformRigid<'a>>>, ERequires<'a>> {
|
||||||
collection_e!(
|
collection_trailing_sep_e!(
|
||||||
word1(b'{', ERequires::ListStart),
|
word1(b'{', ERequires::ListStart),
|
||||||
specialize(|_, r, c| ERequires::Rigid(r, c), loc!(requires_rigid())),
|
specialize(|_, r, c| ERequires::Rigid(r, c), loc!(requires_rigid())),
|
||||||
word1(b',', ERequires::ListEnd),
|
word1(b',', ERequires::ListEnd),
|
||||||
word1(b'}', ERequires::ListEnd),
|
word1(b'}', ERequires::ListEnd),
|
||||||
min_indent,
|
min_indent,
|
||||||
|
ERequires::Open,
|
||||||
ERequires::Space,
|
ERequires::Space,
|
||||||
ERequires::IndentListEnd
|
ERequires::IndentListEnd,
|
||||||
|
PlatformRigid::SpaceBefore
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,7 +491,7 @@ fn exposes_values<'a>() -> impl Parser<
|
||||||
'a,
|
'a,
|
||||||
(
|
(
|
||||||
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
||||||
Vec<'a, Located<ExposesEntry<'a, &'a str>>>,
|
Collection<'a, Located<ExposesEntry<'a, &'a str>>>,
|
||||||
),
|
),
|
||||||
EExposes,
|
EExposes,
|
||||||
> {
|
> {
|
||||||
|
@ -502,14 +506,16 @@ fn exposes_values<'a>() -> impl Parser<
|
||||||
EExposes::IndentExposes,
|
EExposes::IndentExposes,
|
||||||
EExposes::IndentListStart
|
EExposes::IndentListStart
|
||||||
),
|
),
|
||||||
collection_e!(
|
collection_trailing_sep_e!(
|
||||||
word1(b'[', EExposes::ListStart),
|
word1(b'[', EExposes::ListStart),
|
||||||
exposes_entry(EExposes::Identifier),
|
exposes_entry(EExposes::Identifier),
|
||||||
word1(b',', EExposes::ListEnd),
|
word1(b',', EExposes::ListEnd),
|
||||||
word1(b']', EExposes::ListEnd),
|
word1(b']', EExposes::ListEnd),
|
||||||
min_indent,
|
min_indent,
|
||||||
|
EExposes::Open,
|
||||||
EExposes::Space,
|
EExposes::Space,
|
||||||
EExposes::IndentListEnd
|
EExposes::IndentListEnd,
|
||||||
|
ExposesEntry::SpaceBefore
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -539,7 +545,7 @@ fn exposes_modules<'a>() -> impl Parser<
|
||||||
'a,
|
'a,
|
||||||
(
|
(
|
||||||
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
||||||
Vec<'a, Located<ExposesEntry<'a, ModuleName<'a>>>>,
|
Collection<'a, Located<ExposesEntry<'a, ModuleName<'a>>>>,
|
||||||
),
|
),
|
||||||
EExposes,
|
EExposes,
|
||||||
> {
|
> {
|
||||||
|
@ -554,14 +560,16 @@ fn exposes_modules<'a>() -> impl Parser<
|
||||||
EExposes::IndentExposes,
|
EExposes::IndentExposes,
|
||||||
EExposes::IndentListStart
|
EExposes::IndentListStart
|
||||||
),
|
),
|
||||||
collection_e!(
|
collection_trailing_sep_e!(
|
||||||
word1(b'[', EExposes::ListStart),
|
word1(b'[', EExposes::ListStart),
|
||||||
exposes_module(EExposes::Identifier),
|
exposes_module(EExposes::Identifier),
|
||||||
word1(b',', EExposes::ListEnd),
|
word1(b',', EExposes::ListEnd),
|
||||||
word1(b']', EExposes::ListEnd),
|
word1(b']', EExposes::ListEnd),
|
||||||
min_indent,
|
min_indent,
|
||||||
|
EExposes::Open,
|
||||||
EExposes::Space,
|
EExposes::Space,
|
||||||
EExposes::IndentListEnd
|
EExposes::IndentListEnd,
|
||||||
|
ExposesEntry::SpaceBefore
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -631,7 +639,7 @@ fn imports<'a>() -> impl Parser<
|
||||||
'a,
|
'a,
|
||||||
(
|
(
|
||||||
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
||||||
Vec<'a, Located<ImportsEntry<'a>>>,
|
Collection<'a, Located<ImportsEntry<'a>>>,
|
||||||
),
|
),
|
||||||
EImports,
|
EImports,
|
||||||
> {
|
> {
|
||||||
|
@ -646,14 +654,16 @@ fn imports<'a>() -> impl Parser<
|
||||||
EImports::IndentImports,
|
EImports::IndentImports,
|
||||||
EImports::IndentListStart
|
EImports::IndentListStart
|
||||||
),
|
),
|
||||||
collection_e!(
|
collection_trailing_sep_e!(
|
||||||
word1(b'[', EImports::ListStart),
|
word1(b'[', EImports::ListStart),
|
||||||
loc!(imports_entry()),
|
loc!(imports_entry()),
|
||||||
word1(b',', EImports::ListEnd),
|
word1(b',', EImports::ListEnd),
|
||||||
word1(b']', EImports::ListEnd),
|
word1(b']', EImports::ListEnd),
|
||||||
min_indent,
|
min_indent,
|
||||||
|
EImports::Open,
|
||||||
EImports::Space,
|
EImports::Space,
|
||||||
EImports::IndentListEnd
|
EImports::IndentListEnd,
|
||||||
|
ImportsEntry::SpaceBefore
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -687,14 +697,16 @@ fn effects<'a>() -> impl Parser<'a, Effects<'a>, EEffects<'a>> {
|
||||||
space0_e(min_indent, EEffects::Space, EEffects::IndentListStart)
|
space0_e(min_indent, EEffects::Space, EEffects::IndentListStart)
|
||||||
)
|
)
|
||||||
.parse(arena, state)?;
|
.parse(arena, state)?;
|
||||||
let (_, entries, state) = collection_e!(
|
let (_, entries, state) = collection_trailing_sep_e!(
|
||||||
word1(b'{', EEffects::ListStart),
|
word1(b'{', EEffects::ListStart),
|
||||||
specialize(EEffects::TypedIdent, loc!(typed_ident())),
|
specialize(EEffects::TypedIdent, loc!(typed_ident())),
|
||||||
word1(b',', EEffects::ListEnd),
|
word1(b',', EEffects::ListEnd),
|
||||||
word1(b'}', EEffects::ListEnd),
|
word1(b'}', EEffects::ListEnd),
|
||||||
min_indent,
|
min_indent,
|
||||||
|
EEffects::Open,
|
||||||
EEffects::Space,
|
EEffects::Space,
|
||||||
EEffects::IndentListEnd
|
EEffects::IndentListEnd,
|
||||||
|
TypedIdent::SpaceBefore
|
||||||
)
|
)
|
||||||
.parse(arena, state)?;
|
.parse(arena, state)?;
|
||||||
|
|
||||||
|
@ -706,7 +718,7 @@ fn effects<'a>() -> impl Parser<'a, Effects<'a>, EEffects<'a>> {
|
||||||
spaces_after_type_name,
|
spaces_after_type_name,
|
||||||
effect_shortname: type_shortname,
|
effect_shortname: type_shortname,
|
||||||
effect_type_name: type_name,
|
effect_type_name: type_name,
|
||||||
entries: entries.into_bump_slice(),
|
entries: entries.items,
|
||||||
},
|
},
|
||||||
state,
|
state,
|
||||||
))
|
))
|
||||||
|
@ -768,7 +780,7 @@ fn imports_entry<'a>() -> impl Parser<'a, ImportsEntry<'a>, EImports> {
|
||||||
|
|
||||||
type Temp<'a> = (
|
type Temp<'a> = (
|
||||||
(Option<&'a str>, ModuleName<'a>),
|
(Option<&'a str>, ModuleName<'a>),
|
||||||
Option<Vec<'a, Located<ExposesEntry<'a, &'a str>>>>,
|
Option<Collection<'a, Located<ExposesEntry<'a, &'a str>>>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
map_with_arena!(
|
map_with_arena!(
|
||||||
|
@ -785,19 +797,21 @@ fn imports_entry<'a>() -> impl Parser<'a, ImportsEntry<'a>, EImports> {
|
||||||
// e.g. `.{ Task, after}`
|
// e.g. `.{ Task, after}`
|
||||||
maybe!(skip_first!(
|
maybe!(skip_first!(
|
||||||
word1(b'.', EImports::ExposingDot),
|
word1(b'.', EImports::ExposingDot),
|
||||||
collection_e!(
|
collection_trailing_sep_e!(
|
||||||
word1(b'{', EImports::SetStart),
|
word1(b'{', EImports::SetStart),
|
||||||
exposes_entry(EImports::Identifier),
|
exposes_entry(EImports::Identifier),
|
||||||
word1(b',', EImports::SetEnd),
|
word1(b',', EImports::SetEnd),
|
||||||
word1(b'}', EImports::SetEnd),
|
word1(b'}', EImports::SetEnd),
|
||||||
min_indent,
|
min_indent,
|
||||||
|
EImports::Open,
|
||||||
EImports::Space,
|
EImports::Space,
|
||||||
EImports::IndentSetEnd
|
EImports::IndentSetEnd,
|
||||||
|
ExposesEntry::SpaceBefore
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
),
|
),
|
||||||
|arena, ((opt_shortname, module_name), opt_values): Temp<'a>| {
|
|_arena, ((opt_shortname, module_name), opt_values): Temp<'a>| {
|
||||||
let exposed_values = opt_values.unwrap_or_else(|| Vec::new_in(arena));
|
let exposed_values = opt_values.unwrap_or_else(Collection::empty);
|
||||||
|
|
||||||
match opt_shortname {
|
match opt_shortname {
|
||||||
Some(shortname) => ImportsEntry::Package(shortname, module_name, exposed_values),
|
Some(shortname) => ImportsEntry::Package(shortname, module_name, exposed_values),
|
||||||
|
|
|
@ -214,6 +214,7 @@ pub enum EHeader<'a> {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum EProvides<'a> {
|
pub enum EProvides<'a> {
|
||||||
Provides(Row, Col),
|
Provides(Row, Col),
|
||||||
|
Open(Row, Col),
|
||||||
To(Row, Col),
|
To(Row, Col),
|
||||||
IndentProvides(Row, Col),
|
IndentProvides(Row, Col),
|
||||||
IndentTo(Row, Col),
|
IndentTo(Row, Col),
|
||||||
|
@ -230,6 +231,7 @@ pub enum EProvides<'a> {
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum EExposes {
|
pub enum EExposes {
|
||||||
Exposes(Row, Col),
|
Exposes(Row, Col),
|
||||||
|
Open(Row, Col),
|
||||||
IndentExposes(Row, Col),
|
IndentExposes(Row, Col),
|
||||||
IndentListStart(Row, Col),
|
IndentListStart(Row, Col),
|
||||||
IndentListEnd(Row, Col),
|
IndentListEnd(Row, Col),
|
||||||
|
@ -242,6 +244,7 @@ pub enum EExposes {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum ERequires<'a> {
|
pub enum ERequires<'a> {
|
||||||
Requires(Row, Col),
|
Requires(Row, Col),
|
||||||
|
Open(Row, Col),
|
||||||
IndentRequires(Row, Col),
|
IndentRequires(Row, Col),
|
||||||
IndentListStart(Row, Col),
|
IndentListStart(Row, Col),
|
||||||
IndentListEnd(Row, Col),
|
IndentListEnd(Row, Col),
|
||||||
|
@ -302,6 +305,7 @@ pub enum EPackageEntry<'a> {
|
||||||
pub enum EEffects<'a> {
|
pub enum EEffects<'a> {
|
||||||
Space(BadInputError, Row, Col),
|
Space(BadInputError, Row, Col),
|
||||||
Effects(Row, Col),
|
Effects(Row, Col),
|
||||||
|
Open(Row, Col),
|
||||||
IndentEffects(Row, Col),
|
IndentEffects(Row, Col),
|
||||||
ListStart(Row, Col),
|
ListStart(Row, Col),
|
||||||
ListEnd(Row, Col),
|
ListEnd(Row, Col),
|
||||||
|
@ -315,6 +319,7 @@ pub enum EEffects<'a> {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum EImports {
|
pub enum EImports {
|
||||||
|
Open(Row, Col),
|
||||||
Imports(Row, Col),
|
Imports(Row, Col),
|
||||||
IndentImports(Row, Col),
|
IndentImports(Row, Col),
|
||||||
IndentListStart(Row, Col),
|
IndentListStart(Row, Col),
|
||||||
|
@ -1183,83 +1188,6 @@ macro_rules! collection {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! collection_e {
|
|
||||||
($opening_brace:expr, $elem:expr, $delimiter:expr, $closing_brace:expr, $min_indent:expr, $space_problem:expr, $indent_problem:expr) => {
|
|
||||||
skip_first!(
|
|
||||||
$opening_brace,
|
|
||||||
skip_first!(
|
|
||||||
// We specifically allow space characters inside here, so that
|
|
||||||
// `[ ]` can be successfully parsed as an empty list, and then
|
|
||||||
// changed by the formatter back into `[]`.
|
|
||||||
//
|
|
||||||
// We don't allow newlines or comments in the middle of empty
|
|
||||||
// roc_collections because those are normally stored in an Expr,
|
|
||||||
// and there's no Expr in which to store them in an empty collection!
|
|
||||||
//
|
|
||||||
// We could change the AST to add extra storage specifically to
|
|
||||||
// support empty literals containing newlines or comments, but this
|
|
||||||
// does not seem worth even the tiniest regression in compiler performance.
|
|
||||||
zero_or_more!($crate::parser::word1(b' ', |row, col| $space_problem(
|
|
||||||
crate::parser::BadInputError::LineTooLong,
|
|
||||||
row,
|
|
||||||
col
|
|
||||||
))),
|
|
||||||
skip_second!(
|
|
||||||
$crate::parser::sep_by0(
|
|
||||||
$delimiter,
|
|
||||||
$crate::blankspace::space0_around_ee(
|
|
||||||
$elem,
|
|
||||||
$min_indent,
|
|
||||||
$space_problem,
|
|
||||||
$indent_problem,
|
|
||||||
$indent_problem
|
|
||||||
)
|
|
||||||
),
|
|
||||||
$closing_brace
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse zero or more elements between two braces (e.g. square braces).
|
|
||||||
/// Elements can be optionally surrounded by spaces, and are separated by a
|
|
||||||
/// delimiter (e.g comma-separated) with optionally a trailing delimiter.
|
|
||||||
/// Braces and delimiters get discarded.
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! collection_trailing_sep {
|
|
||||||
($opening_brace:expr, $elem:expr, $delimiter:expr, $closing_brace:expr, $min_indent:expr) => {
|
|
||||||
skip_first!(
|
|
||||||
$opening_brace,
|
|
||||||
skip_first!(
|
|
||||||
// We specifically allow space characters inside here, so that
|
|
||||||
// `[ ]` can be successfully parsed as an empty list, and then
|
|
||||||
// changed by the formatter back into `[]`.
|
|
||||||
//
|
|
||||||
// We don't allow newlines or comments in the middle of empty
|
|
||||||
// roc_collections because those are normally stored in an Expr,
|
|
||||||
// and there's no Expr in which to store them in an empty collection!
|
|
||||||
//
|
|
||||||
// We could change the AST to add extra storage specifically to
|
|
||||||
// support empty literals containing newlines or comments, but this
|
|
||||||
// does not seem worth even the tiniest regression in compiler performance.
|
|
||||||
zero_or_more!($crate::parser::ascii_char(b' ')),
|
|
||||||
skip_second!(
|
|
||||||
and!(
|
|
||||||
$crate::parser::trailing_sep_by0(
|
|
||||||
$delimiter,
|
|
||||||
$crate::blankspace::space0_around($elem, $min_indent)
|
|
||||||
),
|
|
||||||
$crate::blankspace::space0($min_indent)
|
|
||||||
),
|
|
||||||
$closing_brace
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! collection_trailing_sep_e {
|
macro_rules! collection_trailing_sep_e {
|
||||||
($opening_brace:expr, $elem:expr, $delimiter:expr, $closing_brace:expr, $min_indent:expr, $open_problem:expr, $space_problem:expr, $indent_problem:expr, $space_before:expr) => {
|
($opening_brace:expr, $elem:expr, $delimiter:expr, $closing_brace:expr, $min_indent:expr, $open_problem:expr, $space_problem:expr, $indent_problem:expr, $space_before:expr) => {
|
||||||
|
|
|
@ -3077,8 +3077,8 @@ mod test_parse {
|
||||||
fn empty_app_header() {
|
fn empty_app_header() {
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let packages = Collection::empty();
|
let packages = Collection::empty();
|
||||||
let imports = Vec::new_in(&arena);
|
let imports = Collection::empty();
|
||||||
let provides = Vec::new_in(&arena);
|
let provides = Collection::empty();
|
||||||
let module_name = StrLiteral::PlainLine("test-app");
|
let module_name = StrLiteral::PlainLine("test-app");
|
||||||
let header = AppHeader {
|
let header = AppHeader {
|
||||||
name: Located::new(0, 0, 4, 14, module_name),
|
name: Located::new(0, 0, 4, 14, module_name),
|
||||||
|
@ -3117,8 +3117,8 @@ mod test_parse {
|
||||||
|
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let packages = Collection::empty();
|
let packages = Collection::empty();
|
||||||
let imports = Vec::new_in(&arena);
|
let imports = Collection::empty();
|
||||||
let provides = Vec::new_in(&arena);
|
let provides = Collection::empty();
|
||||||
let module_name = StrLiteral::PlainLine("test-app");
|
let module_name = StrLiteral::PlainLine("test-app");
|
||||||
let header = AppHeader {
|
let header = AppHeader {
|
||||||
before_header: &[],
|
before_header: &[],
|
||||||
|
@ -3166,11 +3166,11 @@ mod test_parse {
|
||||||
let loc_pkg_entry = Located::new(1, 1, 15, 33, pkg_entry);
|
let loc_pkg_entry = Located::new(1, 1, 15, 33, pkg_entry);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let packages = Collection::with_items(arena.alloc([loc_pkg_entry]));
|
let packages = Collection::with_items(arena.alloc([loc_pkg_entry]));
|
||||||
let import = ImportsEntry::Package("foo", ModuleName::new("Bar.Baz"), Vec::new_in(&arena));
|
let import = ImportsEntry::Package("foo", ModuleName::new("Bar.Baz"), Collection::empty());
|
||||||
let loc_import = Located::new(2, 2, 14, 25, import);
|
let loc_import = Located::new(2, 2, 14, 25, import);
|
||||||
let imports = bumpalo::vec![in &arena; loc_import];
|
let imports = Collection::with_items(arena.alloc([loc_import]));
|
||||||
let provide_entry = Located::new(3, 3, 15, 24, Exposed("quicksort"));
|
let provide_entry = Located::new(3, 3, 15, 24, Exposed("quicksort"));
|
||||||
let provides = bumpalo::vec![in &arena; provide_entry];
|
let provides = Collection::with_items(arena.alloc([provide_entry]));
|
||||||
let module_name = StrLiteral::PlainLine("quicksort");
|
let module_name = StrLiteral::PlainLine("quicksort");
|
||||||
|
|
||||||
let header = AppHeader {
|
let header = AppHeader {
|
||||||
|
@ -3222,11 +3222,40 @@ mod test_parse {
|
||||||
let loc_pkg_entry = Located::new(1, 1, 15, 33, pkg_entry);
|
let loc_pkg_entry = Located::new(1, 1, 15, 33, pkg_entry);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let packages = Collection::with_items(arena.alloc([loc_pkg_entry]));
|
let packages = Collection::with_items(arena.alloc([loc_pkg_entry]));
|
||||||
let import = ImportsEntry::Package("foo", ModuleName::new("Bar.Baz"), Vec::new_in(&arena));
|
let import = ImportsEntry::Package(
|
||||||
let loc_import = Located::new(2, 2, 14, 25, import);
|
"foo",
|
||||||
let imports = bumpalo::vec![in &arena; loc_import];
|
ModuleName::new("Bar"),
|
||||||
let provide_entry = Located::new(3, 3, 15, 24, Exposed("quicksort"));
|
Collection::with_items_and_comments(
|
||||||
let provides = bumpalo::vec![in &arena; provide_entry];
|
&arena,
|
||||||
|
arena.alloc([
|
||||||
|
Located::new(
|
||||||
|
3,
|
||||||
|
3,
|
||||||
|
8,
|
||||||
|
11,
|
||||||
|
ExposesEntry::SpaceBefore(
|
||||||
|
arena.alloc(ExposesEntry::Exposed("Baz")),
|
||||||
|
arena.alloc([Newline]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Located::new(
|
||||||
|
4,
|
||||||
|
4,
|
||||||
|
8,
|
||||||
|
17,
|
||||||
|
ExposesEntry::SpaceBefore(
|
||||||
|
arena.alloc(ExposesEntry::Exposed("FourtyTwo")),
|
||||||
|
arena.alloc([Newline]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
arena.alloc([Newline, LineComment(" I'm a happy comment")]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
let loc_import = Located::new(2, 6, 14, 5, import);
|
||||||
|
let imports = Collection::with_items(arena.alloc([loc_import]));
|
||||||
|
let provide_entry = Located::new(7, 7, 15, 24, Exposed("quicksort"));
|
||||||
|
let provides = Collection::with_items(arena.alloc([provide_entry]));
|
||||||
let module_name = StrLiteral::PlainLine("quicksort");
|
let module_name = StrLiteral::PlainLine("quicksort");
|
||||||
|
|
||||||
let header = AppHeader {
|
let header = AppHeader {
|
||||||
|
@ -3235,7 +3264,7 @@ mod test_parse {
|
||||||
packages,
|
packages,
|
||||||
imports,
|
imports,
|
||||||
provides,
|
provides,
|
||||||
to: Located::new(3, 3, 30, 34, To::ExistingPackage("base")),
|
to: Located::new(7, 7, 31, 35, To::ExistingPackage("base")),
|
||||||
after_app_keyword: &[],
|
after_app_keyword: &[],
|
||||||
before_packages: newlines,
|
before_packages: newlines,
|
||||||
after_packages: &[],
|
after_packages: &[],
|
||||||
|
@ -3253,8 +3282,12 @@ mod test_parse {
|
||||||
r#"
|
r#"
|
||||||
app "quicksort"
|
app "quicksort"
|
||||||
packages { base: "./platform", }
|
packages { base: "./platform", }
|
||||||
imports [ foo.Bar.Baz ]
|
imports [ foo.Bar.{
|
||||||
provides [ quicksort ] to base
|
Baz,
|
||||||
|
FourtyTwo,
|
||||||
|
# I'm a happy comment
|
||||||
|
} ]
|
||||||
|
provides [ quicksort, ] to base
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -3285,7 +3318,7 @@ mod test_parse {
|
||||||
let region2 = Region::new(0, 0, 45, 47);
|
let region2 = Region::new(0, 0, 45, 47);
|
||||||
|
|
||||||
PlatformRequires {
|
PlatformRequires {
|
||||||
rigids: Vec::new_in(&arena),
|
rigids: Collection::empty(),
|
||||||
signature: Located::at(
|
signature: Located::at(
|
||||||
region1,
|
region1,
|
||||||
TypedIdent::Entry {
|
TypedIdent::Entry {
|
||||||
|
@ -3307,10 +3340,10 @@ mod test_parse {
|
||||||
before_header: &[],
|
before_header: &[],
|
||||||
name: Located::new(0, 0, 9, 23, pkg_name),
|
name: Located::new(0, 0, 9, 23, pkg_name),
|
||||||
requires,
|
requires,
|
||||||
exposes: Vec::new_in(&arena),
|
exposes: Collection::empty(),
|
||||||
packages: Collection::empty(),
|
packages: Collection::empty(),
|
||||||
imports: Vec::new_in(&arena),
|
imports: Collection::empty(),
|
||||||
provides: Vec::new_in(&arena),
|
provides: Collection::empty(),
|
||||||
effects,
|
effects,
|
||||||
after_platform_keyword: &[],
|
after_platform_keyword: &[],
|
||||||
before_requires: &[],
|
before_requires: &[],
|
||||||
|
@ -3352,9 +3385,9 @@ mod test_parse {
|
||||||
let loc_pkg_entry = Located::new(3, 3, 15, 27, pkg_entry);
|
let loc_pkg_entry = Located::new(3, 3, 15, 27, pkg_entry);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let packages = Collection::with_items(arena.alloc([loc_pkg_entry]));
|
let packages = Collection::with_items(arena.alloc([loc_pkg_entry]));
|
||||||
let imports = Vec::new_in(&arena);
|
let imports = Collection::empty();
|
||||||
let provide_entry = Located::new(5, 5, 15, 26, Exposed("mainForHost"));
|
let provide_entry = Located::new(5, 5, 15, 26, Exposed("mainForHost"));
|
||||||
let provides = bumpalo::vec![in &arena; provide_entry];
|
let provides = Collection::with_items(arena.alloc([provide_entry]));
|
||||||
let effects = Effects {
|
let effects = Effects {
|
||||||
effect_type_name: "Effect",
|
effect_type_name: "Effect",
|
||||||
effect_shortname: "fx",
|
effect_shortname: "fx",
|
||||||
|
@ -3370,7 +3403,13 @@ mod test_parse {
|
||||||
let region3 = Region::new(1, 1, 14, 26);
|
let region3 = Region::new(1, 1, 14, 26);
|
||||||
|
|
||||||
PlatformRequires {
|
PlatformRequires {
|
||||||
rigids: bumpalo::vec![ in &arena; Located::at(region3, PlatformRigid::Entry { alias: "Model", rigid: "model" }) ],
|
rigids: Collection::with_items(arena.alloc([Located::at(
|
||||||
|
region3,
|
||||||
|
PlatformRigid::Entry {
|
||||||
|
alias: "Model",
|
||||||
|
rigid: "model",
|
||||||
|
},
|
||||||
|
)])),
|
||||||
signature: Located::at(
|
signature: Located::at(
|
||||||
region1,
|
region1,
|
||||||
TypedIdent::Entry {
|
TypedIdent::Entry {
|
||||||
|
@ -3392,7 +3431,7 @@ mod test_parse {
|
||||||
before_header: &[],
|
before_header: &[],
|
||||||
name: Located::new(0, 0, 9, 19, pkg_name),
|
name: Located::new(0, 0, 9, 19, pkg_name),
|
||||||
requires,
|
requires,
|
||||||
exposes: Vec::new_in(&arena),
|
exposes: Collection::empty(),
|
||||||
packages,
|
packages,
|
||||||
imports,
|
imports,
|
||||||
provides,
|
provides,
|
||||||
|
@ -3432,8 +3471,8 @@ mod test_parse {
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_interface_header() {
|
fn empty_interface_header() {
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let exposes = Vec::new_in(&arena);
|
let exposes = Collection::empty();
|
||||||
let imports = Vec::new_in(&arena);
|
let imports = Collection::empty();
|
||||||
let module_name = ModuleName::new("Foo");
|
let module_name = ModuleName::new("Foo");
|
||||||
let header = InterfaceHeader {
|
let header = InterfaceHeader {
|
||||||
before_header: &[],
|
before_header: &[],
|
||||||
|
@ -3464,8 +3503,8 @@ mod test_parse {
|
||||||
#[test]
|
#[test]
|
||||||
fn nested_module() {
|
fn nested_module() {
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let exposes = Vec::new_in(&arena);
|
let exposes = Collection::empty();
|
||||||
let imports = Vec::new_in(&arena);
|
let imports = Collection::empty();
|
||||||
let module_name = ModuleName::new("Foo.Bar.Baz");
|
let module_name = ModuleName::new("Foo.Bar.Baz");
|
||||||
let header = InterfaceHeader {
|
let header = InterfaceHeader {
|
||||||
before_header: &[],
|
before_header: &[],
|
||||||
|
|
|
@ -3093,6 +3093,7 @@ fn to_provides_report<'a>(
|
||||||
use roc_parse::parser::EProvides;
|
use roc_parse::parser::EProvides;
|
||||||
|
|
||||||
match *parse_problem {
|
match *parse_problem {
|
||||||
|
EProvides::ListEnd(row, col) | // TODO: give this its own error message
|
||||||
EProvides::Identifier(row, col) => {
|
EProvides::Identifier(row, col) => {
|
||||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||||
let region = Region::from_row_col(row, col);
|
let region = Region::from_row_col(row, col);
|
||||||
|
@ -3158,6 +3159,7 @@ fn to_exposes_report<'a>(
|
||||||
use roc_parse::parser::EExposes;
|
use roc_parse::parser::EExposes;
|
||||||
|
|
||||||
match *parse_problem {
|
match *parse_problem {
|
||||||
|
EExposes::ListEnd(row, col) | // TODO: give this its own error message
|
||||||
EExposes::Identifier(row, col) => {
|
EExposes::Identifier(row, col) => {
|
||||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||||
let region = Region::from_row_col(row, col);
|
let region = Region::from_row_col(row, col);
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::helpers::wasm::assert_evals_to;
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn basic_record() {
|
fn basic_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -45,7 +45,7 @@ fn basic_record() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn f64_record() {
|
fn f64_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -137,7 +137,7 @@ fn fn_record() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn def_record() {
|
fn def_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -192,7 +192,7 @@ fn when_on_record() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn when_record_with_guard_pattern() {
|
fn when_record_with_guard_pattern() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -207,7 +207,7 @@ fn when_record_with_guard_pattern() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn let_with_record_pattern() {
|
fn let_with_record_pattern() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -223,7 +223,7 @@ fn let_with_record_pattern() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn record_guard_pattern() {
|
fn record_guard_pattern() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -239,7 +239,7 @@ fn record_guard_pattern() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn twice_record_access() {
|
fn twice_record_access() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -254,7 +254,7 @@ fn twice_record_access() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn empty_record() {
|
fn empty_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -873,7 +873,7 @@ fn update_single_element_record() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn booleans_in_record() {
|
fn booleans_in_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!("{ x: 1 == 1, y: 1 == 1 }"),
|
indoc!("{ x: 1 == 1, y: 1 == 1 }"),
|
||||||
|
@ -908,7 +908,7 @@ fn alignment_in_record() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn blue_and_present() {
|
fn blue_and_present() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -927,7 +927,7 @@ fn blue_and_present() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn blue_and_absent() {
|
fn blue_and_absent() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue