mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 22:34:45 +00:00
Merge branch 'trunk' into builtins-refactor-list-take
This commit is contained in:
commit
4359dcff73
29 changed files with 593 additions and 424 deletions
1
AUTHORS
1
AUTHORS
|
@ -51,3 +51,4 @@ Eric Newbury <enewbury@users.noreply.github.com>
|
|||
Ayaz Hafiz <ayaz.hafiz.1@gmail.com>
|
||||
Johannes Maas <github@j-maas.de>
|
||||
Takeshi Sato <doublequotation@gmail.com>
|
||||
Joost Baas <joost@joostbaas.eu>
|
||||
|
|
|
@ -395,7 +395,8 @@ pub fn to_type2<'a>(
|
|||
Type2::Variable(var)
|
||||
}
|
||||
Record { fields, ext, .. } => {
|
||||
let field_types_map = can_assigned_fields(env, scope, references, fields, region);
|
||||
let field_types_map =
|
||||
can_assigned_fields(env, scope, references, &fields.items, region);
|
||||
|
||||
let field_types = PoolVec::with_capacity(field_types_map.len() as u32, env.pool);
|
||||
|
||||
|
|
|
@ -863,6 +863,7 @@ fn get_macos_version() -> String {
|
|||
.expect("Failed to convert output of command 'sw_vers -productVersion' into a utf8 string");
|
||||
|
||||
full_version_string
|
||||
.trim_end()
|
||||
.split('.')
|
||||
.take(2)
|
||||
.collect::<Vec<&str>>()
|
||||
|
|
|
@ -1388,6 +1388,13 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
|||
Box::new(flex(TVAR1)),
|
||||
);
|
||||
|
||||
// isOk : Result * * -> bool
|
||||
add_top_level_function_type!(
|
||||
Symbol::RESULT_IS_OK,
|
||||
vec![result_type(flex(TVAR1), flex(TVAR3))],
|
||||
Box::new(bool_type()),
|
||||
);
|
||||
|
||||
types
|
||||
}
|
||||
|
||||
|
|
|
@ -389,7 +389,7 @@ fn can_annotation_help(
|
|||
Record { fields, ext, .. } => {
|
||||
let field_types = can_assigned_fields(
|
||||
env,
|
||||
fields,
|
||||
&fields.items,
|
||||
region,
|
||||
scope,
|
||||
var_store,
|
||||
|
|
|
@ -194,6 +194,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
|
|||
RESULT_MAP_ERR => result_map_err,
|
||||
RESULT_AFTER => result_after,
|
||||
RESULT_WITH_DEFAULT => result_with_default,
|
||||
RESULT_IS_OK => result_is_ok,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4162,6 +4163,83 @@ fn result_with_default(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
)
|
||||
}
|
||||
|
||||
fn result_is_ok(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
let ret_var = var_store.fresh();
|
||||
let result_var = var_store.fresh();
|
||||
|
||||
let mut branches = vec![];
|
||||
|
||||
{
|
||||
// ok branch
|
||||
let tag_name = TagName::Global("Ok".into());
|
||||
|
||||
let pattern = Pattern::AppliedTag {
|
||||
whole_var: result_var,
|
||||
ext_var: var_store.fresh(),
|
||||
tag_name,
|
||||
arguments: vec![(var_store.fresh(), no_region(Pattern::Underscore))],
|
||||
};
|
||||
|
||||
let true_expr = Tag {
|
||||
variant_var: var_store.fresh(),
|
||||
ext_var: var_store.fresh(),
|
||||
name: TagName::Global("True".into()),
|
||||
arguments: vec![],
|
||||
};
|
||||
|
||||
let branch = WhenBranch {
|
||||
patterns: vec![no_region(pattern)],
|
||||
value: no_region(true_expr),
|
||||
guard: None,
|
||||
};
|
||||
|
||||
branches.push(branch);
|
||||
}
|
||||
|
||||
{
|
||||
// err branch
|
||||
let tag_name = TagName::Global("Err".into());
|
||||
|
||||
let pattern = Pattern::AppliedTag {
|
||||
whole_var: result_var,
|
||||
ext_var: var_store.fresh(),
|
||||
tag_name,
|
||||
arguments: vec![(var_store.fresh(), no_region(Pattern::Underscore))],
|
||||
};
|
||||
|
||||
let false_expr = Tag {
|
||||
variant_var: var_store.fresh(),
|
||||
ext_var: var_store.fresh(),
|
||||
name: TagName::Global("False".into()),
|
||||
arguments: vec![],
|
||||
};
|
||||
|
||||
let branch = WhenBranch {
|
||||
patterns: vec![no_region(pattern)],
|
||||
value: no_region(false_expr),
|
||||
guard: None,
|
||||
};
|
||||
|
||||
branches.push(branch);
|
||||
}
|
||||
|
||||
let body = When {
|
||||
cond_var: result_var,
|
||||
expr_var: ret_var,
|
||||
region: Region::zero(),
|
||||
loc_cond: Box::new(no_region(Var(Symbol::ARG_1))),
|
||||
branches,
|
||||
};
|
||||
|
||||
defn(
|
||||
symbol,
|
||||
vec![(result_var, Symbol::ARG_1)],
|
||||
var_store,
|
||||
body,
|
||||
ret_var,
|
||||
)
|
||||
}
|
||||
|
||||
fn result_after(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
let ret_var = var_store.fresh();
|
||||
let func_var = var_store.fresh();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::spaces::{fmt_comments_only, fmt_spaces, newline, NewlineAt, INDENT};
|
||||
use bumpalo::collections::String;
|
||||
use roc_parse::ast::{AssignedField, Expr, Tag, TypeAnnotation};
|
||||
use roc_parse::ast::{AssignedField, Collection, Expr, Tag, TypeAnnotation};
|
||||
use roc_region::all::Located;
|
||||
|
||||
/// Does an AST node need parens around it?
|
||||
|
@ -183,17 +183,13 @@ impl<'a> Formattable<'a> for TypeAnnotation<'a> {
|
|||
Apply(_, _, args) => args.iter().any(|loc_arg| loc_arg.value.is_multiline()),
|
||||
As(lhs, _, rhs) => lhs.value.is_multiline() || rhs.value.is_multiline(),
|
||||
|
||||
Record {
|
||||
fields,
|
||||
ext,
|
||||
final_comments: _,
|
||||
} => {
|
||||
Record { fields, ext } => {
|
||||
match ext {
|
||||
Some(ann) if ann.value.is_multiline() => return true,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
fields.iter().any(|field| field.value.is_multiline())
|
||||
fields.items.iter().any(|field| field.value.is_multiline())
|
||||
}
|
||||
|
||||
TagUnion {
|
||||
|
@ -296,16 +292,19 @@ impl<'a> Formattable<'a> for TypeAnnotation<'a> {
|
|||
}
|
||||
|
||||
Record {
|
||||
fields,
|
||||
ext,
|
||||
fields:
|
||||
Collection {
|
||||
items,
|
||||
final_comments,
|
||||
},
|
||||
ext,
|
||||
} => {
|
||||
format_sequence!(
|
||||
buf,
|
||||
indent,
|
||||
'{',
|
||||
'}',
|
||||
fields,
|
||||
items,
|
||||
final_comments,
|
||||
newlines,
|
||||
AssignedField
|
||||
|
|
|
@ -4,7 +4,7 @@ use code_builder::Align;
|
|||
use roc_collections::all::MutMap;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::ir::{CallType, Expr, JoinPointId, Literal, Proc, Stmt};
|
||||
use roc_mono::layout::{Layout, LayoutIds};
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds};
|
||||
|
||||
use crate::layout::WasmLayout;
|
||||
use crate::low_level::{build_call_low_level, LowlevelBuildResult};
|
||||
|
@ -294,16 +294,17 @@ impl<'a> WasmBackend<'a> {
|
|||
|
||||
_ => {
|
||||
self.storage.load_symbols(&mut self.code_builder, &[*sym]);
|
||||
self.code_builder.br(self.block_depth); // jump to end of function (for stack frame pop)
|
||||
}
|
||||
}
|
||||
// jump to the "stack frame pop" code at the end of the function
|
||||
self.code_builder.br(self.block_depth - 1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Stmt::Switch {
|
||||
cond_symbol,
|
||||
cond_layout: _,
|
||||
cond_layout,
|
||||
branches,
|
||||
default_branch,
|
||||
ret_layout: _,
|
||||
|
@ -321,21 +322,45 @@ impl<'a> WasmBackend<'a> {
|
|||
cond_storage,
|
||||
);
|
||||
|
||||
// create (number_of_branches - 1) new blocks.
|
||||
// create a block for each branch except the default
|
||||
for _ in 0..branches.len() {
|
||||
self.start_block(BlockType::NoResult)
|
||||
}
|
||||
|
||||
let is_bool = matches!(cond_layout, Layout::Builtin(Builtin::Int1));
|
||||
let cond_type = WasmLayout::new(cond_layout).value_type();
|
||||
|
||||
// then, we jump whenever the value under scrutiny is equal to the value of a branch
|
||||
for (i, (value, _, _)) in branches.iter().enumerate() {
|
||||
// put the cond_symbol on the top of the stack
|
||||
self.storage
|
||||
.load_symbols(&mut self.code_builder, &[*cond_symbol]);
|
||||
|
||||
if is_bool {
|
||||
// We already have a bool, don't need to compare against a const to get one
|
||||
if *value == 0 {
|
||||
self.code_builder.i32_eqz();
|
||||
}
|
||||
} else {
|
||||
match cond_type {
|
||||
ValueType::I32 => {
|
||||
self.code_builder.i32_const(*value as i32);
|
||||
|
||||
// compare the 2 topmost values
|
||||
self.code_builder.i32_eq();
|
||||
}
|
||||
ValueType::I64 => {
|
||||
self.code_builder.i64_const(*value as i64);
|
||||
self.code_builder.i64_eq();
|
||||
}
|
||||
ValueType::F32 => {
|
||||
self.code_builder.f32_const(f32::from_bits(*value as u32));
|
||||
self.code_builder.f32_eq();
|
||||
}
|
||||
ValueType::F64 => {
|
||||
self.code_builder.f64_const(f64::from_bits(*value as u64));
|
||||
self.code_builder.f64_eq();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "break" out of `i` surrounding blocks
|
||||
self.code_builder.br_if(i as u32);
|
||||
|
|
|
@ -202,10 +202,10 @@ impl<'a> CodeBuilder<'a> {
|
|||
true
|
||||
}
|
||||
|
||||
fn add_insertion(&mut self, insert_at: usize, opcode: u8, immediate: u32) {
|
||||
fn add_insertion(&mut self, insert_at: usize, opcode: OpCode, immediate: u32) {
|
||||
let start = self.insert_bytes.len();
|
||||
|
||||
self.insert_bytes.push(opcode);
|
||||
self.insert_bytes.push(opcode as u8);
|
||||
self.insert_bytes.encode_u32(immediate);
|
||||
|
||||
self.insertions.push(Insertion {
|
||||
|
@ -213,6 +213,8 @@ impl<'a> CodeBuilder<'a> {
|
|||
start,
|
||||
end: self.insert_bytes.len(),
|
||||
});
|
||||
|
||||
// println!("insert {:?} {} at byte offset {} ", opcode, immediate, insert_at);
|
||||
}
|
||||
|
||||
/// Load a Symbol that is stored in the VM stack
|
||||
|
@ -244,14 +246,14 @@ impl<'a> CodeBuilder<'a> {
|
|||
// Symbol is not on top of the stack. Find it.
|
||||
if let Some(found_index) = self.vm_stack.iter().rposition(|&s| s == symbol) {
|
||||
// Insert a local.set where the value was created
|
||||
self.add_insertion(pushed_at, SETLOCAL as u8, next_local_id.0);
|
||||
self.add_insertion(pushed_at, SETLOCAL, next_local_id.0);
|
||||
|
||||
// Take the value out of the stack where local.set was inserted
|
||||
self.vm_stack.remove(found_index);
|
||||
|
||||
// Insert a local.get at the current position
|
||||
self.get_local(next_local_id);
|
||||
self.vm_stack.push(symbol);
|
||||
self.set_top_symbol(symbol);
|
||||
|
||||
// This Symbol is no longer stored in the VM stack, but in a local
|
||||
None
|
||||
|
@ -267,11 +269,11 @@ impl<'a> CodeBuilder<'a> {
|
|||
Popped { pushed_at } => {
|
||||
// This Symbol is being used for a second time
|
||||
// Insert a local.tee where it was pushed, so we don't interfere with the first usage
|
||||
self.add_insertion(pushed_at, TEELOCAL as u8, next_local_id.0);
|
||||
self.add_insertion(pushed_at, TEELOCAL, next_local_id.0);
|
||||
|
||||
// Insert a local.get at the current position
|
||||
self.get_local(next_local_id);
|
||||
self.vm_stack.push(symbol);
|
||||
self.set_top_symbol(symbol);
|
||||
|
||||
// This symbol has been promoted to a Local
|
||||
// Tell the caller it no longer has a VirtualMachineSymbolState
|
||||
|
@ -437,10 +439,12 @@ impl<'a> CodeBuilder<'a> {
|
|||
let new_len = self.vm_stack.len() - pops as usize;
|
||||
self.vm_stack.truncate(new_len);
|
||||
if push {
|
||||
self.vm_stack.push(Symbol::WASM_ANONYMOUS_STACK_VALUE);
|
||||
self.vm_stack.push(Symbol::WASM_TMP);
|
||||
}
|
||||
|
||||
self.code.push(opcode as u8);
|
||||
|
||||
// println!("{:10}\t{:?}", format!("{:?}", opcode), &self.vm_stack);
|
||||
}
|
||||
|
||||
fn inst_imm8(&mut self, opcode: OpCode, pops: usize, push: bool, immediate: u8) {
|
||||
|
@ -516,25 +520,14 @@ impl<'a> CodeBuilder<'a> {
|
|||
n_args: usize,
|
||||
has_return_val: bool,
|
||||
) {
|
||||
let stack_depth = self.vm_stack.len();
|
||||
if n_args > stack_depth {
|
||||
panic!(
|
||||
"Trying to call to call function {:?} with {:?} values but only {:?} on the VM stack\n{:?}",
|
||||
function_index, n_args, stack_depth, self
|
||||
);
|
||||
}
|
||||
self.vm_stack.truncate(stack_depth - n_args);
|
||||
if has_return_val {
|
||||
self.vm_stack.push(Symbol::WASM_ANONYMOUS_STACK_VALUE);
|
||||
}
|
||||
self.code.push(CALL as u8);
|
||||
self.inst(CALL, n_args, has_return_val);
|
||||
|
||||
// Write the index of the function to be called.
|
||||
// Also make a RelocationEntry so the linker can see that this byte offset relates to a function by name.
|
||||
// Here we initialise the offset to an index of self.code. After completing the function, we'll add
|
||||
// other factors to make it relative to the code section. (All insertions will be known then.)
|
||||
let offset = self.code.len() as u32;
|
||||
self.code.encode_padded_u32(function_index);
|
||||
|
||||
// Make a RelocationEntry so the linker can see that this byte offset relates to a function by name.
|
||||
// Here we initialise the offset to an index of self.code. After completing the function, we'll add
|
||||
// other factors to make it relative to the code section. (All insertions will be known then.)
|
||||
self.relocations.push(RelocationEntry::Index {
|
||||
type_id: IndexRelocType::FunctionIndexLeb,
|
||||
offset,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#[repr(u8)]
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum OpCode {
|
||||
UNREACHABLE = 0x00,
|
||||
NOP = 0x01,
|
||||
|
|
|
@ -293,16 +293,12 @@ fn type_to_docs(in_func_type_ann: bool, type_annotation: ast::TypeAnnotation) ->
|
|||
|
||||
Apply { name, parts }
|
||||
}
|
||||
ast::TypeAnnotation::Record {
|
||||
fields,
|
||||
ext,
|
||||
final_comments: _,
|
||||
} => {
|
||||
ast::TypeAnnotation::Record { fields, ext } => {
|
||||
let mut doc_fields = Vec::new();
|
||||
|
||||
let mut any_fields_include_private_tags = false;
|
||||
|
||||
for field in fields {
|
||||
for field in fields.items {
|
||||
match record_field_to_doc(in_func_type_ann, field.value) {
|
||||
None => {
|
||||
any_fields_include_private_tags = true;
|
||||
|
|
|
@ -2630,7 +2630,7 @@ fn parse_header<'a>(
|
|||
std::str::from_utf8_unchecked(&src_bytes[..chomped])
|
||||
};
|
||||
|
||||
let packages = header.packages.into_bump_slice();
|
||||
let packages = header.packages.items;
|
||||
|
||||
let info = HeaderInfo {
|
||||
loc_name: Located {
|
||||
|
|
|
@ -875,8 +875,8 @@ define_builtins! {
|
|||
// used by the dev backend to store the pointer to where to store large return types
|
||||
23 RET_POINTER: "#ret_pointer"
|
||||
|
||||
// used in wasm dev backend to mark values in the VM stack that have no other Symbol
|
||||
24 WASM_ANONYMOUS_STACK_VALUE: "#wasm_anonymous_stack_value"
|
||||
// used in wasm dev backend to mark temporary values in the VM stack
|
||||
24 WASM_TMP: "#wasm_tmp"
|
||||
}
|
||||
1 NUM: "Num" => {
|
||||
0 NUM_NUM: "Num" imported // the Num.Num type alias
|
||||
|
@ -1082,6 +1082,7 @@ define_builtins! {
|
|||
2 RESULT_MAP_ERR: "mapErr"
|
||||
3 RESULT_WITH_DEFAULT: "withDefault"
|
||||
4 RESULT_AFTER: "after"
|
||||
5 RESULT_IS_OK: "isOk"
|
||||
}
|
||||
6 DICT: "Dict" => {
|
||||
0 DICT_DICT: "Dict" imported // the Dict.Dict type alias
|
||||
|
|
|
@ -5,6 +5,28 @@ use bumpalo::Bump;
|
|||
use roc_module::operator::{BinOp, CalledVia, UnaryOp};
|
||||
use roc_region::all::{Loc, Position, Region};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub struct Collection<'a, T> {
|
||||
pub items: &'a [T],
|
||||
pub final_comments: &'a [CommentOrNewline<'a>],
|
||||
}
|
||||
|
||||
impl<'a, T> Collection<'a, T> {
|
||||
pub fn empty() -> Collection<'a, T> {
|
||||
Collection {
|
||||
items: &[],
|
||||
final_comments: &[],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_items(items: &'a [T]) -> Collection<'a, T> {
|
||||
Collection {
|
||||
items,
|
||||
final_comments: &[],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Module<'a> {
|
||||
Interface { header: InterfaceHeader<'a> },
|
||||
|
@ -231,11 +253,11 @@ pub enum TypeAnnotation<'a> {
|
|||
),
|
||||
|
||||
Record {
|
||||
fields: &'a [Loc<AssignedField<'a, TypeAnnotation<'a>>>],
|
||||
fields: Collection<'a, Loc<AssignedField<'a, TypeAnnotation<'a>>>>,
|
||||
/// The row type variable in an open record, e.g. the `r` in `{ name: Str }r`.
|
||||
/// This is None if it's a closed record annotation like `{ name: Str }`.
|
||||
ext: Option<&'a Loc<TypeAnnotation<'a>>>,
|
||||
final_comments: &'a [CommentOrNewline<'a>],
|
||||
// final_comments: &'a [CommentOrNewline<'a>],
|
||||
},
|
||||
|
||||
/// A tag union, e.g. `[
|
||||
|
|
|
@ -4,8 +4,8 @@ use crate::ident::{lowercase_ident, parse_ident, Ident};
|
|||
use crate::keyword;
|
||||
use crate::parser::{
|
||||
self, backtrackable, optional, sep_by1, sep_by1_e, specialize, specialize_ref, then,
|
||||
trailing_sep_by0, word1, word2, EExpr, EInParens, ELambda, EPattern, ERecord, EString, Either,
|
||||
Expect, If, List, Number, ParseResult, Parser, State, Type, When,
|
||||
trailing_sep_by0, word1, word2, EExpect, EExpr, EIf, EInParens, ELambda, EList, ENumber,
|
||||
EPattern, ERecord, EString, EType, EWhen, Either, ParseResult, Parser, State,
|
||||
};
|
||||
use crate::pattern::loc_closure_param;
|
||||
use crate::type_annotation;
|
||||
|
@ -801,7 +801,7 @@ fn parse_defs_end<'a>(
|
|||
Err((NoProgress, _, _)) => {
|
||||
let start = state.get_position();
|
||||
|
||||
match crate::parser::keyword_e(crate::keyword::EXPECT, Expect::Expect)
|
||||
match crate::parser::keyword_e(crate::keyword::EXPECT, EExpect::Expect)
|
||||
.parse(arena, state)
|
||||
{
|
||||
Err((_, _, _)) => {
|
||||
|
@ -861,8 +861,8 @@ fn parse_defs_end<'a>(
|
|||
space0_before_e(
|
||||
type_annotation::located_help(min_indent + 1),
|
||||
min_indent + 1,
|
||||
Type::TSpace,
|
||||
Type::TIndentStart,
|
||||
EType::TSpace,
|
||||
EType::TIndentStart,
|
||||
),
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
@ -1099,8 +1099,8 @@ fn parse_expr_operator<'a>(
|
|||
space0_before_e(
|
||||
type_annotation::located_help(indented_more),
|
||||
min_indent,
|
||||
Type::TSpace,
|
||||
Type::TIndentStart,
|
||||
EType::TSpace,
|
||||
EType::TIndentStart,
|
||||
),
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
@ -1126,8 +1126,8 @@ fn parse_expr_operator<'a>(
|
|||
space0_before_e(
|
||||
type_annotation::located_help(indented_more),
|
||||
min_indent,
|
||||
Type::TSpace,
|
||||
Type::TIndentStart,
|
||||
EType::TSpace,
|
||||
EType::TIndentStart,
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -1651,21 +1651,21 @@ mod when {
|
|||
pub fn expr_help<'a>(
|
||||
min_indent: u16,
|
||||
options: ExprParseOptions,
|
||||
) -> impl Parser<'a, Expr<'a>, When<'a>> {
|
||||
) -> impl Parser<'a, Expr<'a>, EWhen<'a>> {
|
||||
then(
|
||||
and!(
|
||||
when_with_indent(),
|
||||
skip_second!(
|
||||
space0_around_ee(
|
||||
specialize_ref(When::Condition, move |arena, state| {
|
||||
specialize_ref(EWhen::Condition, move |arena, state| {
|
||||
parse_loc_expr_with_options(min_indent, options, arena, state)
|
||||
}),
|
||||
min_indent,
|
||||
When::Space,
|
||||
When::IndentCondition,
|
||||
When::IndentIs,
|
||||
EWhen::Space,
|
||||
EWhen::IndentCondition,
|
||||
EWhen::IndentIs,
|
||||
),
|
||||
parser::keyword_e(keyword::IS, When::Is)
|
||||
parser::keyword_e(keyword::IS, EWhen::Is)
|
||||
)
|
||||
),
|
||||
move |arena, state, progress, (case_indent, loc_condition)| {
|
||||
|
@ -1673,7 +1673,7 @@ mod when {
|
|||
return Err((
|
||||
progress,
|
||||
// TODO maybe pass case_indent here?
|
||||
When::PatternAlignment(5, state.line, state.column),
|
||||
EWhen::PatternAlignment(5, state.line, state.column),
|
||||
state,
|
||||
));
|
||||
}
|
||||
|
@ -1693,9 +1693,9 @@ mod when {
|
|||
}
|
||||
|
||||
/// Parsing when with indentation.
|
||||
fn when_with_indent<'a>() -> impl Parser<'a, u16, When<'a>> {
|
||||
fn when_with_indent<'a>() -> impl Parser<'a, u16, EWhen<'a>> {
|
||||
move |arena, state: State<'a>| {
|
||||
parser::keyword_e(keyword::WHEN, When::When)
|
||||
parser::keyword_e(keyword::WHEN, EWhen::When)
|
||||
.parse(arena, state)
|
||||
.map(|(progress, (), state)| (progress, state.indent_col, state))
|
||||
}
|
||||
|
@ -1704,7 +1704,7 @@ mod when {
|
|||
fn branches<'a>(
|
||||
min_indent: u16,
|
||||
options: ExprParseOptions,
|
||||
) -> impl Parser<'a, Vec<'a, &'a WhenBranch<'a>>, When<'a>> {
|
||||
) -> impl Parser<'a, Vec<'a, &'a WhenBranch<'a>>, EWhen<'a>> {
|
||||
move |arena, state: State<'a>| {
|
||||
let when_indent = state.indent_col;
|
||||
|
||||
|
@ -1741,7 +1741,7 @@ mod when {
|
|||
let indent = pattern_indent_level - indent_col;
|
||||
Err((
|
||||
MadeProgress,
|
||||
When::PatternAlignment(indent, state.line, state.column),
|
||||
EWhen::PatternAlignment(indent, state.line, state.column),
|
||||
state,
|
||||
))
|
||||
}
|
||||
|
@ -1799,7 +1799,7 @@ mod when {
|
|||
(Col, Vec<'a, Located<Pattern<'a>>>),
|
||||
Option<Located<Expr<'a>>>,
|
||||
),
|
||||
When<'a>,
|
||||
EWhen<'a>,
|
||||
> {
|
||||
let options = ExprParseOptions {
|
||||
check_for_arrow: false,
|
||||
|
@ -1810,16 +1810,16 @@ mod when {
|
|||
one_of![
|
||||
map!(
|
||||
skip_first!(
|
||||
parser::keyword_e(keyword::IF, When::IfToken),
|
||||
parser::keyword_e(keyword::IF, EWhen::IfToken),
|
||||
// TODO we should require space before the expression but not after
|
||||
space0_around_ee(
|
||||
specialize_ref(When::IfGuard, move |arena, state| {
|
||||
specialize_ref(EWhen::IfGuard, move |arena, state| {
|
||||
parse_loc_expr_with_options(min_indent + 1, options, arena, state)
|
||||
}),
|
||||
min_indent,
|
||||
When::Space,
|
||||
When::IndentIfGuard,
|
||||
When::IndentArrow,
|
||||
EWhen::Space,
|
||||
EWhen::IndentIfGuard,
|
||||
EWhen::IndentArrow,
|
||||
)
|
||||
),
|
||||
Some
|
||||
|
@ -1831,17 +1831,17 @@ mod when {
|
|||
|
||||
fn branch_single_alternative<'a>(
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, Located<Pattern<'a>>, When<'a>> {
|
||||
) -> impl Parser<'a, Located<Pattern<'a>>, EWhen<'a>> {
|
||||
move |arena, state| {
|
||||
let (_, spaces, state) =
|
||||
backtrackable(space0_e(min_indent, When::Space, When::IndentPattern))
|
||||
backtrackable(space0_e(min_indent, EWhen::Space, EWhen::IndentPattern))
|
||||
.parse(arena, state)?;
|
||||
|
||||
let (_, loc_pattern, state) = space0_after_e(
|
||||
specialize(When::Pattern, crate::pattern::loc_pattern_help(min_indent)),
|
||||
specialize(EWhen::Pattern, crate::pattern::loc_pattern_help(min_indent)),
|
||||
min_indent,
|
||||
When::Space,
|
||||
When::IndentPattern,
|
||||
EWhen::Space,
|
||||
EWhen::IndentPattern,
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
||||
|
@ -1862,12 +1862,12 @@ mod when {
|
|||
fn branch_alternatives_help<'a>(
|
||||
min_indent: u16,
|
||||
pattern_indent_level: Option<u16>,
|
||||
) -> impl Parser<'a, (Col, Vec<'a, Located<Pattern<'a>>>), When<'a>> {
|
||||
) -> impl Parser<'a, (Col, Vec<'a, Located<Pattern<'a>>>), EWhen<'a>> {
|
||||
move |arena, state: State<'a>| {
|
||||
let initial = state;
|
||||
|
||||
// put no restrictions on the indent after the spaces; we'll check it manually
|
||||
match space0_e(0, When::Space, When::IndentPattern).parse(arena, state) {
|
||||
match space0_e(0, EWhen::Space, EWhen::IndentPattern).parse(arena, state) {
|
||||
Err((MadeProgress, fail, _)) => Err((NoProgress, fail, initial)),
|
||||
Err((NoProgress, fail, _)) => Err((NoProgress, fail, initial)),
|
||||
Ok((_progress, spaces, state)) => {
|
||||
|
@ -1876,7 +1876,7 @@ mod when {
|
|||
// this branch is indented too much
|
||||
Err((
|
||||
NoProgress,
|
||||
When::IndentPattern(state.line, state.column),
|
||||
EWhen::IndentPattern(state.line, state.column),
|
||||
initial,
|
||||
))
|
||||
}
|
||||
|
@ -1884,7 +1884,7 @@ mod when {
|
|||
let indent = wanted - state.column;
|
||||
Err((
|
||||
NoProgress,
|
||||
When::PatternAlignment(indent, state.line, state.column),
|
||||
EWhen::PatternAlignment(indent, state.line, state.column),
|
||||
initial,
|
||||
))
|
||||
}
|
||||
|
@ -1896,7 +1896,7 @@ mod when {
|
|||
let pattern_indent_col = state.column;
|
||||
|
||||
let parser = sep_by1(
|
||||
word1(b'|', When::Bar),
|
||||
word1(b'|', EWhen::Bar),
|
||||
branch_single_alternative(pattern_indent + 1),
|
||||
);
|
||||
|
||||
|
@ -1930,16 +1930,16 @@ mod when {
|
|||
}
|
||||
|
||||
/// Parsing the righthandside of a branch in a when conditional.
|
||||
fn branch_result<'a>(indent: u16) -> impl Parser<'a, Located<Expr<'a>>, When<'a>> {
|
||||
fn branch_result<'a>(indent: u16) -> impl Parser<'a, Located<Expr<'a>>, EWhen<'a>> {
|
||||
skip_first!(
|
||||
word2(b'-', b'>', When::Arrow),
|
||||
word2(b'-', b'>', EWhen::Arrow),
|
||||
space0_before_e(
|
||||
specialize_ref(When::Branch, move |arena, state| parse_loc_expr(
|
||||
specialize_ref(EWhen::Branch, move |arena, state| parse_loc_expr(
|
||||
indent, arena, state
|
||||
)),
|
||||
indent,
|
||||
When::Space,
|
||||
When::IndentBranch,
|
||||
EWhen::Space,
|
||||
EWhen::IndentBranch,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -1947,38 +1947,38 @@ mod when {
|
|||
|
||||
fn if_branch<'a>(
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, (Located<Expr<'a>>, Located<Expr<'a>>), If<'a>> {
|
||||
) -> impl Parser<'a, (Located<Expr<'a>>, Located<Expr<'a>>), EIf<'a>> {
|
||||
move |arena, state| {
|
||||
// NOTE: only parse spaces before the expression
|
||||
let (_, cond, state) = space0_around_ee(
|
||||
specialize_ref(If::Condition, move |arena, state| {
|
||||
specialize_ref(EIf::Condition, move |arena, state| {
|
||||
parse_loc_expr(min_indent, arena, state)
|
||||
}),
|
||||
min_indent,
|
||||
If::Space,
|
||||
If::IndentCondition,
|
||||
If::IndentThenToken,
|
||||
EIf::Space,
|
||||
EIf::IndentCondition,
|
||||
EIf::IndentThenToken,
|
||||
)
|
||||
.parse(arena, state)
|
||||
.map_err(|(_, f, s)| (MadeProgress, f, s))?;
|
||||
|
||||
let (_, _, state) = parser::keyword_e(keyword::THEN, If::Then)
|
||||
let (_, _, state) = parser::keyword_e(keyword::THEN, EIf::Then)
|
||||
.parse(arena, state)
|
||||
.map_err(|(_, f, s)| (MadeProgress, f, s))?;
|
||||
|
||||
let (_, then_branch, state) = space0_around_ee(
|
||||
specialize_ref(If::ThenBranch, move |arena, state| {
|
||||
specialize_ref(EIf::ThenBranch, move |arena, state| {
|
||||
parse_loc_expr(min_indent, arena, state)
|
||||
}),
|
||||
min_indent,
|
||||
If::Space,
|
||||
If::IndentThenBranch,
|
||||
If::IndentElseToken,
|
||||
EIf::Space,
|
||||
EIf::IndentThenBranch,
|
||||
EIf::IndentElseToken,
|
||||
)
|
||||
.parse(arena, state)
|
||||
.map_err(|(_, f, s)| (MadeProgress, f, s))?;
|
||||
|
||||
let (_, _, state) = parser::keyword_e(keyword::ELSE, If::Else)
|
||||
let (_, _, state) = parser::keyword_e(keyword::ELSE, EIf::Else)
|
||||
.parse(arena, state)
|
||||
.map_err(|(_, f, s)| (MadeProgress, f, s))?;
|
||||
|
||||
|
@ -1989,26 +1989,26 @@ fn if_branch<'a>(
|
|||
fn expect_help<'a>(
|
||||
min_indent: u16,
|
||||
options: ExprParseOptions,
|
||||
) -> impl Parser<'a, Expr<'a>, Expect<'a>> {
|
||||
) -> impl Parser<'a, Expr<'a>, EExpect<'a>> {
|
||||
move |arena: &'a Bump, state: State<'a>| {
|
||||
let start = state.get_position();
|
||||
|
||||
let (_, _, state) =
|
||||
parser::keyword_e(keyword::EXPECT, Expect::Expect).parse(arena, state)?;
|
||||
parser::keyword_e(keyword::EXPECT, EExpect::Expect).parse(arena, state)?;
|
||||
|
||||
let (_, condition, state) = space0_before_e(
|
||||
specialize_ref(Expect::Condition, move |arena, state| {
|
||||
specialize_ref(EExpect::Condition, move |arena, state| {
|
||||
parse_loc_expr_with_options(start.col + 1, options, arena, state)
|
||||
}),
|
||||
start.col + 1,
|
||||
Expect::Space,
|
||||
Expect::IndentCondition,
|
||||
EExpect::Space,
|
||||
EExpect::IndentCondition,
|
||||
)
|
||||
.parse(arena, state)
|
||||
.map_err(|(_, f, s)| (MadeProgress, f, s))?;
|
||||
|
||||
let parse_cont = specialize_ref(
|
||||
Expect::Continuation,
|
||||
EExpect::Continuation,
|
||||
space0_before_e(
|
||||
move |a, s| parse_loc_expr(min_indent, a, s),
|
||||
min_indent,
|
||||
|
@ -2028,9 +2028,9 @@ fn expect_help<'a>(
|
|||
fn if_expr_help<'a>(
|
||||
min_indent: u16,
|
||||
options: ExprParseOptions,
|
||||
) -> impl Parser<'a, Expr<'a>, If<'a>> {
|
||||
) -> impl Parser<'a, Expr<'a>, EIf<'a>> {
|
||||
move |arena: &'a Bump, state| {
|
||||
let (_, _, state) = parser::keyword_e(keyword::IF, If::If).parse(arena, state)?;
|
||||
let (_, _, state) = parser::keyword_e(keyword::IF, EIf::If).parse(arena, state)?;
|
||||
|
||||
let mut branches = Vec::with_capacity_in(1, arena);
|
||||
|
||||
|
@ -2044,8 +2044,8 @@ fn if_expr_help<'a>(
|
|||
// try to parse another `if`
|
||||
// NOTE this drops spaces between the `else` and the `if`
|
||||
let optional_if = and!(
|
||||
backtrackable(space0_e(min_indent, If::Space, If::IndentIf)),
|
||||
parser::keyword_e(keyword::IF, If::If)
|
||||
backtrackable(space0_e(min_indent, EIf::Space, EIf::IndentIf)),
|
||||
parser::keyword_e(keyword::IF, EIf::If)
|
||||
);
|
||||
|
||||
match optional_if.parse(arena, state) {
|
||||
|
@ -2058,12 +2058,12 @@ fn if_expr_help<'a>(
|
|||
};
|
||||
|
||||
let (_, else_branch, state) = space0_before_e(
|
||||
specialize_ref(If::ElseBranch, move |arena, state| {
|
||||
specialize_ref(EIf::ElseBranch, move |arena, state| {
|
||||
parse_loc_expr_with_options(min_indent, options, arena, state)
|
||||
}),
|
||||
min_indent,
|
||||
If::Space,
|
||||
If::IndentElseBranch,
|
||||
EIf::Space,
|
||||
EIf::IndentElseBranch,
|
||||
)
|
||||
.parse(arena, state_final_else)
|
||||
.map_err(|(_, f, s)| (MadeProgress, f, s))?;
|
||||
|
@ -2147,32 +2147,33 @@ fn ident_to_expr<'a>(arena: &'a Bump, src: Ident<'a>) -> Expr<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn list_literal_help<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, List<'a>> {
|
||||
fn list_literal_help<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, EList<'a>> {
|
||||
move |arena, state| {
|
||||
let (_, (parsed_elems, final_comments), state) = collection_trailing_sep_e!(
|
||||
word1(b'[', List::Open),
|
||||
specialize_ref(List::Expr, move |a, s| parse_loc_expr_no_multi_backpassing(
|
||||
min_indent, a, s
|
||||
)),
|
||||
word1(b',', List::End),
|
||||
word1(b']', List::End),
|
||||
let (_, elements, state) = collection_trailing_sep_e!(
|
||||
word1(b'[', EList::Open),
|
||||
specialize_ref(
|
||||
EList::Expr,
|
||||
move |a, s| parse_loc_expr_no_multi_backpassing(min_indent, a, s)
|
||||
),
|
||||
word1(b',', EList::End),
|
||||
word1(b']', EList::End),
|
||||
min_indent,
|
||||
List::Open,
|
||||
List::Space,
|
||||
List::IndentEnd,
|
||||
EList::Open,
|
||||
EList::Space,
|
||||
EList::IndentEnd,
|
||||
Expr::SpaceBefore
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
||||
let mut allocated = Vec::with_capacity_in(parsed_elems.len(), arena);
|
||||
let mut allocated = Vec::with_capacity_in(elements.items.len(), arena);
|
||||
|
||||
for parsed_elem in parsed_elems {
|
||||
allocated.push(&*arena.alloc(parsed_elem));
|
||||
for parsed_elem in elements.items {
|
||||
allocated.push(parsed_elem);
|
||||
}
|
||||
|
||||
let expr = Expr::List {
|
||||
items: allocated.into_bump_slice(),
|
||||
final_comments,
|
||||
final_comments: elements.final_comments,
|
||||
};
|
||||
|
||||
Ok((MadeProgress, expr, state))
|
||||
|
@ -2341,7 +2342,7 @@ fn string_literal_help<'a>() -> impl Parser<'a, Expr<'a>, EString<'a>> {
|
|||
map!(crate::string_literal::parse(), Expr::Str)
|
||||
}
|
||||
|
||||
fn positive_number_literal_help<'a>() -> impl Parser<'a, Expr<'a>, Number> {
|
||||
fn positive_number_literal_help<'a>() -> impl Parser<'a, Expr<'a>, ENumber> {
|
||||
map!(
|
||||
crate::number_literal::positive_number_literal(),
|
||||
|literal| {
|
||||
|
@ -2364,7 +2365,7 @@ fn positive_number_literal_help<'a>() -> impl Parser<'a, Expr<'a>, Number> {
|
|||
)
|
||||
}
|
||||
|
||||
fn number_literal_help<'a>() -> impl Parser<'a, Expr<'a>, Number> {
|
||||
fn number_literal_help<'a>() -> impl Parser<'a, Expr<'a>, ENumber> {
|
||||
map!(crate::number_literal::number_literal(), |literal| {
|
||||
use crate::number_literal::NumLiteral::*;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::ast::{CommentOrNewline, Spaceable, StrLiteral, TypeAnnotation};
|
||||
use crate::ast::{Collection, CommentOrNewline, Spaceable, StrLiteral, TypeAnnotation};
|
||||
use crate::blankspace::space0_e;
|
||||
use crate::ident::lowercase_ident;
|
||||
use crate::parser::Progress::{self, *};
|
||||
|
@ -81,7 +81,7 @@ pub enum To<'a> {
|
|||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct AppHeader<'a> {
|
||||
pub name: Loc<StrLiteral<'a>>,
|
||||
pub packages: Vec<'a, Loc<PackageEntry<'a>>>,
|
||||
pub packages: Collection<'a, Loc<PackageEntry<'a>>>,
|
||||
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
|
||||
pub provides: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>,
|
||||
pub to: Loc<To<'a>>,
|
||||
|
@ -146,7 +146,7 @@ pub struct PlatformHeader<'a> {
|
|||
pub name: Loc<PackageName<'a>>,
|
||||
pub requires: PlatformRequires<'a>,
|
||||
pub exposes: Vec<'a, Loc<ExposesEntry<'a, ModuleName<'a>>>>,
|
||||
pub packages: Vec<'a, Loc<PackageEntry<'a>>>,
|
||||
pub packages: Collection<'a, Loc<PackageEntry<'a>>>,
|
||||
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
|
||||
pub provides: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>,
|
||||
pub effects: Effects<'a>,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::ast::{CommentOrNewline, Def, Module};
|
||||
use crate::ast::{Collection, CommentOrNewline, Def, Module};
|
||||
use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
|
||||
use crate::header::{
|
||||
package_entry, package_name, package_or_path, AppHeader, Effects, ExposesEntry, ImportsEntry,
|
||||
|
@ -203,7 +203,7 @@ fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
|
|||
let (_, provides, state) =
|
||||
specialize(EHeader::Provides, provides_to()).parse(arena, state)?;
|
||||
|
||||
let (before_packages, after_packages, package_entries) = match opt_pkgs {
|
||||
let (before_packages, after_packages, packages) = match opt_pkgs {
|
||||
Some(pkgs) => {
|
||||
let pkgs: Packages<'a> = pkgs; // rustc must be told the type here
|
||||
|
||||
|
@ -213,7 +213,7 @@ fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
|
|||
pkgs.entries,
|
||||
)
|
||||
}
|
||||
None => (&[] as _, &[] as _, Vec::new_in(arena)),
|
||||
None => (&[] as _, &[] as _, Collection::empty()),
|
||||
};
|
||||
|
||||
// rustc must be told the type here
|
||||
|
@ -229,7 +229,7 @@ fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
|
|||
|
||||
let header = AppHeader {
|
||||
name,
|
||||
packages: package_entries,
|
||||
packages,
|
||||
imports,
|
||||
provides: provides.entries,
|
||||
to: provides.to,
|
||||
|
@ -582,11 +582,9 @@ where
|
|||
|
||||
#[derive(Debug)]
|
||||
struct Packages<'a> {
|
||||
entries: Vec<'a, Located<PackageEntry<'a>>>,
|
||||
|
||||
entries: Collection<'a, Located<PackageEntry<'a>>>,
|
||||
before_packages_keyword: &'a [CommentOrNewline<'a>],
|
||||
after_packages_keyword: &'a [CommentOrNewline<'a>],
|
||||
final_comments: &'a [CommentOrNewline<'a>],
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -615,12 +613,14 @@ fn packages<'a>() -> impl Parser<'a, Packages<'a>, EPackages<'a>> {
|
|||
PackageEntry::SpaceBefore
|
||||
)
|
||||
),
|
||||
|((before_packages_keyword, after_packages_keyword), (entries, final_comments))| {
|
||||
|((before_packages_keyword, after_packages_keyword), entries): (
|
||||
(_, _),
|
||||
Collection<'a, _>
|
||||
)| {
|
||||
Packages {
|
||||
entries,
|
||||
before_packages_keyword,
|
||||
after_packages_keyword,
|
||||
final_comments,
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::ast::Base;
|
||||
use crate::parser::{Number, ParseResult, Parser, Progress, State};
|
||||
use crate::parser::{ENumber, ParseResult, Parser, Progress, State};
|
||||
|
||||
pub enum NumLiteral<'a> {
|
||||
Float(&'a str),
|
||||
|
@ -11,7 +11,7 @@ pub enum NumLiteral<'a> {
|
|||
},
|
||||
}
|
||||
|
||||
pub fn positive_number_literal<'a>() -> impl Parser<'a, NumLiteral<'a>, Number> {
|
||||
pub fn positive_number_literal<'a>() -> impl Parser<'a, NumLiteral<'a>, ENumber> {
|
||||
move |_arena, state: State<'a>| {
|
||||
match state.bytes.get(0) {
|
||||
Some(first_byte) if (*first_byte as char).is_ascii_digit() => {
|
||||
|
@ -19,13 +19,13 @@ pub fn positive_number_literal<'a>() -> impl Parser<'a, NumLiteral<'a>, Number>
|
|||
}
|
||||
_ => {
|
||||
// this is not a number at all
|
||||
Err((Progress::NoProgress, Number::End, state))
|
||||
Err((Progress::NoProgress, ENumber::End, state))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn number_literal<'a>() -> impl Parser<'a, NumLiteral<'a>, Number> {
|
||||
pub fn number_literal<'a>() -> impl Parser<'a, NumLiteral<'a>, ENumber> {
|
||||
move |_arena, state: State<'a>| {
|
||||
match state.bytes.get(0) {
|
||||
Some(first_byte) if *first_byte == b'-' => {
|
||||
|
@ -37,7 +37,7 @@ pub fn number_literal<'a>() -> impl Parser<'a, NumLiteral<'a>, Number> {
|
|||
}
|
||||
_ => {
|
||||
// this is not a number at all
|
||||
Err((Progress::NoProgress, Number::End, state))
|
||||
Err((Progress::NoProgress, ENumber::End, state))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ fn parse_number_base<'a>(
|
|||
is_negated: bool,
|
||||
bytes: &'a [u8],
|
||||
state: State<'a>,
|
||||
) -> ParseResult<'a, NumLiteral<'a>, Number> {
|
||||
) -> ParseResult<'a, NumLiteral<'a>, ENumber> {
|
||||
match bytes.get(0..2) {
|
||||
Some(b"0b") => chomp_number_base(Base::Binary, is_negated, &bytes[2..], state),
|
||||
Some(b"0o") => chomp_number_base(Base::Octal, is_negated, &bytes[2..], state),
|
||||
|
@ -61,13 +61,13 @@ fn chomp_number_base<'a>(
|
|||
is_negative: bool,
|
||||
bytes: &'a [u8],
|
||||
state: State<'a>,
|
||||
) -> ParseResult<'a, NumLiteral<'a>, Number> {
|
||||
) -> ParseResult<'a, NumLiteral<'a>, ENumber> {
|
||||
let (_is_float, chomped) = chomp_number(bytes);
|
||||
|
||||
let string = unsafe { std::str::from_utf8_unchecked(&bytes[..chomped]) };
|
||||
|
||||
let new = state.advance_without_indenting_ee(chomped + 2 + is_negative as usize, |_, _| {
|
||||
Number::LineTooLong
|
||||
ENumber::LineTooLong
|
||||
})?;
|
||||
|
||||
Ok((
|
||||
|
@ -85,24 +85,25 @@ fn chomp_number_dec<'a>(
|
|||
is_negative: bool,
|
||||
bytes: &'a [u8],
|
||||
state: State<'a>,
|
||||
) -> ParseResult<'a, NumLiteral<'a>, Number> {
|
||||
) -> ParseResult<'a, NumLiteral<'a>, ENumber> {
|
||||
let (is_float, chomped) = chomp_number(bytes);
|
||||
|
||||
if is_negative && chomped == 0 {
|
||||
// we're probably actually looking at unary negation here
|
||||
return Err((Progress::NoProgress, Number::End, state));
|
||||
return Err((Progress::NoProgress, ENumber::End, state));
|
||||
}
|
||||
|
||||
if !bytes.get(0).copied().unwrap_or_default().is_ascii_digit() {
|
||||
// we're probably actually looking at unary negation here
|
||||
return Err((Progress::NoProgress, Number::End, state));
|
||||
return Err((Progress::NoProgress, ENumber::End, state));
|
||||
}
|
||||
|
||||
let string =
|
||||
unsafe { std::str::from_utf8_unchecked(&state.bytes[0..chomped + is_negative as usize]) };
|
||||
|
||||
let new = state
|
||||
.advance_without_indenting_ee(chomped + is_negative as usize, |_, _| Number::LineTooLong)?;
|
||||
let new = state.advance_without_indenting_ee(chomped + is_negative as usize, |_, _| {
|
||||
ENumber::LineTooLong
|
||||
})?;
|
||||
|
||||
Ok((
|
||||
Progress::MadeProgress,
|
||||
|
|
|
@ -186,7 +186,7 @@ pub enum SyntaxError<'a> {
|
|||
ArgumentsBeforeEquals(Region),
|
||||
NotYetImplemented(String),
|
||||
Todo,
|
||||
Type(Type<'a>),
|
||||
Type(EType<'a>),
|
||||
Pattern(EPattern<'a>),
|
||||
Expr(EExpr<'a>),
|
||||
Header(EHeader<'a>),
|
||||
|
@ -258,7 +258,7 @@ pub enum ETypedIdent<'a> {
|
|||
HasType(Row, Col),
|
||||
IndentHasType(Row, Col),
|
||||
Name(Row, Col),
|
||||
Type(Type<'a>, Row, Col),
|
||||
Type(EType<'a>, Row, Col),
|
||||
IndentType(Row, Col),
|
||||
Identifier(Row, Col),
|
||||
}
|
||||
|
@ -394,7 +394,7 @@ pub enum EExpr<'a> {
|
|||
|
||||
DefMissingFinalExpr(Row, Col),
|
||||
DefMissingFinalExpr2(&'a EExpr<'a>, Row, Col),
|
||||
Type(Type<'a>, Row, Col),
|
||||
Type(EType<'a>, Row, Col),
|
||||
Pattern(&'a EPattern<'a>, Row, Col),
|
||||
IndentDefBody(Row, Col),
|
||||
IndentEquals(Row, Col),
|
||||
|
@ -409,10 +409,10 @@ pub enum EExpr<'a> {
|
|||
BackpassComma(Row, Col),
|
||||
BackpassArrow(Row, Col),
|
||||
|
||||
When(When<'a>, Row, Col),
|
||||
If(If<'a>, Row, Col),
|
||||
When(EWhen<'a>, Row, Col),
|
||||
If(EIf<'a>, Row, Col),
|
||||
|
||||
Expect(Expect<'a>, Row, Col),
|
||||
Expect(EExpect<'a>, Row, Col),
|
||||
|
||||
Lambda(ELambda<'a>, Row, Col),
|
||||
Underscore(Row, Col),
|
||||
|
@ -420,15 +420,15 @@ pub enum EExpr<'a> {
|
|||
InParens(EInParens<'a>, Row, Col),
|
||||
Record(ERecord<'a>, Row, Col),
|
||||
Str(EString<'a>, Row, Col),
|
||||
Number(Number, Row, Col),
|
||||
List(List<'a>, Row, Col),
|
||||
Number(ENumber, Row, Col),
|
||||
List(EList<'a>, Row, Col),
|
||||
|
||||
IndentStart(Row, Col),
|
||||
IndentEnd(Row, Col),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Number {
|
||||
pub enum ENumber {
|
||||
End,
|
||||
LineTooLong,
|
||||
}
|
||||
|
@ -502,7 +502,7 @@ pub enum ELambda<'a> {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum List<'a> {
|
||||
pub enum EList<'a> {
|
||||
Open(Row, Col),
|
||||
End(Row, Col),
|
||||
Space(BadInputError, Row, Col),
|
||||
|
@ -514,7 +514,7 @@ pub enum List<'a> {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum When<'a> {
|
||||
pub enum EWhen<'a> {
|
||||
Space(BadInputError, Row, Col),
|
||||
When(Row, Col),
|
||||
Is(Row, Col),
|
||||
|
@ -538,7 +538,7 @@ pub enum When<'a> {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum If<'a> {
|
||||
pub enum EIf<'a> {
|
||||
Space(BadInputError, Row, Col),
|
||||
If(Row, Col),
|
||||
Then(Row, Col),
|
||||
|
@ -557,7 +557,7 @@ pub enum If<'a> {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Expect<'a> {
|
||||
pub enum EExpect<'a> {
|
||||
Space(BadInputError, Row, Col),
|
||||
Expect(Row, Col),
|
||||
Condition(&'a EExpr<'a>, Row, Col),
|
||||
|
@ -575,7 +575,7 @@ pub enum EPattern<'a> {
|
|||
Space(BadInputError, Row, Col),
|
||||
|
||||
PInParens(PInParens<'a>, Row, Col),
|
||||
NumLiteral(Number, Row, Col),
|
||||
NumLiteral(ENumber, Row, Col),
|
||||
|
||||
IndentStart(Row, Col),
|
||||
IndentEnd(Row, Col),
|
||||
|
@ -614,11 +614,11 @@ pub enum PInParens<'a> {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Type<'a> {
|
||||
TRecord(TRecord<'a>, Row, Col),
|
||||
TTagUnion(TTagUnion<'a>, Row, Col),
|
||||
TInParens(TInParens<'a>, Row, Col),
|
||||
TApply(TApply, Row, Col),
|
||||
pub enum EType<'a> {
|
||||
TRecord(ETypeRecord<'a>, Row, Col),
|
||||
TTagUnion(ETypeTagUnion<'a>, Row, Col),
|
||||
TInParens(ETypeInParens<'a>, Row, Col),
|
||||
TApply(ETypeApply, Row, Col),
|
||||
TBadTypeVariable(Row, Col),
|
||||
TWildcard(Row, Col),
|
||||
///
|
||||
|
@ -633,14 +633,14 @@ pub enum Type<'a> {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum TRecord<'a> {
|
||||
pub enum ETypeRecord<'a> {
|
||||
End(Row, Col),
|
||||
Open(Row, Col),
|
||||
|
||||
Field(Row, Col),
|
||||
Colon(Row, Col),
|
||||
Optional(Row, Col),
|
||||
Type(&'a Type<'a>, Row, Col),
|
||||
Type(&'a EType<'a>, Row, Col),
|
||||
|
||||
Space(BadInputError, Row, Col),
|
||||
|
||||
|
@ -651,11 +651,11 @@ pub enum TRecord<'a> {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum TTagUnion<'a> {
|
||||
pub enum ETypeTagUnion<'a> {
|
||||
End(Row, Col),
|
||||
Open(Row, Col),
|
||||
|
||||
Type(&'a Type<'a>, Row, Col),
|
||||
Type(&'a EType<'a>, Row, Col),
|
||||
|
||||
Space(BadInputError, Row, Col),
|
||||
|
||||
|
@ -664,11 +664,11 @@ pub enum TTagUnion<'a> {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum TInParens<'a> {
|
||||
pub enum ETypeInParens<'a> {
|
||||
End(Row, Col),
|
||||
Open(Row, Col),
|
||||
///
|
||||
Type(&'a Type<'a>, Row, Col),
|
||||
Type(&'a EType<'a>, Row, Col),
|
||||
|
||||
///
|
||||
Space(BadInputError, Row, Col),
|
||||
|
@ -678,7 +678,7 @@ pub enum TInParens<'a> {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum TApply {
|
||||
pub enum ETypeApply {
|
||||
///
|
||||
StartNotUppercase(Row, Col),
|
||||
End(Row, Col),
|
||||
|
@ -1300,7 +1300,12 @@ macro_rules! collection_trailing_sep_e {
|
|||
}
|
||||
}
|
||||
|
||||
Ok((MadeProgress, (parsed_elems, final_comments), state))
|
||||
let collection = $crate::ast::Collection {
|
||||
items: parsed_elems.into_bump_slice(),
|
||||
final_comments,
|
||||
};
|
||||
|
||||
Ok((MadeProgress, collection, state))
|
||||
}
|
||||
)
|
||||
};
|
||||
|
|
|
@ -316,7 +316,7 @@ fn lowercase_ident_pattern<'a>(
|
|||
#[inline(always)]
|
||||
fn record_pattern_help<'a>(min_indent: u16) -> impl Parser<'a, Pattern<'a>, PRecord<'a>> {
|
||||
move |arena, state| {
|
||||
let (_, (fields, final_comments), state) = collection_trailing_sep_e!(
|
||||
let (_, fields, state) = collection_trailing_sep_e!(
|
||||
// word1_check_indent!(b'{', PRecord::Open, min_indent, PRecord::IndentOpen),
|
||||
word1(b'{', PRecord::Open),
|
||||
record_pattern_field(min_indent),
|
||||
|
@ -332,9 +332,9 @@ fn record_pattern_help<'a>(min_indent: u16) -> impl Parser<'a, Pattern<'a>, PRec
|
|||
.parse(arena, state)?;
|
||||
|
||||
// TODO
|
||||
let _unused = final_comments;
|
||||
let _unused = fields.final_comments;
|
||||
|
||||
let result = Pattern::RecordDestructure(fields.into_bump_slice());
|
||||
let result = Pattern::RecordDestructure(fields.items);
|
||||
|
||||
Ok((MadeProgress, result, state))
|
||||
}
|
||||
|
|
|
@ -1,63 +1,67 @@
|
|||
use crate::ast::{AssignedField, Tag, TypeAnnotation};
|
||||
use crate::ast::{AssignedField, Collection, Tag, TypeAnnotation};
|
||||
use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
|
||||
use crate::keyword;
|
||||
use crate::parser::{
|
||||
allocated, backtrackable, optional, specialize, specialize_ref, word1, word2, ParseResult,
|
||||
Parser,
|
||||
allocated, backtrackable, optional, specialize, specialize_ref, word1, word2, EType,
|
||||
ETypeApply, ETypeInParens, ETypeRecord, ETypeTagUnion, ParseResult, Parser,
|
||||
Progress::{self, *},
|
||||
State, TApply, TInParens, TRecord, TTagUnion, Type,
|
||||
State,
|
||||
};
|
||||
use bumpalo::collections::vec::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_region::all::{Located, Region};
|
||||
|
||||
pub fn located_help<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>, Type<'a>> {
|
||||
pub fn located_help<'a>(
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, Located<TypeAnnotation<'a>>, EType<'a>> {
|
||||
expression(min_indent)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn tag_union_type<'a>(min_indent: u16) -> impl Parser<'a, TypeAnnotation<'a>, TTagUnion<'a>> {
|
||||
fn tag_union_type<'a>(min_indent: u16) -> impl Parser<'a, TypeAnnotation<'a>, ETypeTagUnion<'a>> {
|
||||
move |arena, state| {
|
||||
let (_, (tags, final_comments), state) = collection_trailing_sep_e!(
|
||||
word1(b'[', TTagUnion::Open),
|
||||
let (_, tags, state) = collection_trailing_sep_e!(
|
||||
word1(b'[', ETypeTagUnion::Open),
|
||||
loc!(tag_type(min_indent)),
|
||||
word1(b',', TTagUnion::End),
|
||||
word1(b']', TTagUnion::End),
|
||||
word1(b',', ETypeTagUnion::End),
|
||||
word1(b']', ETypeTagUnion::End),
|
||||
min_indent,
|
||||
TTagUnion::Open,
|
||||
TTagUnion::Space,
|
||||
TTagUnion::IndentEnd,
|
||||
ETypeTagUnion::Open,
|
||||
ETypeTagUnion::Space,
|
||||
ETypeTagUnion::IndentEnd,
|
||||
Tag::SpaceBefore
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
||||
// This could be an open tag union, e.g. `[ Foo, Bar ]a`
|
||||
let (_, ext, state) =
|
||||
optional(allocated(specialize_ref(TTagUnion::Type, term(min_indent))))
|
||||
let (_, ext, state) = optional(allocated(specialize_ref(
|
||||
ETypeTagUnion::Type,
|
||||
term(min_indent),
|
||||
)))
|
||||
.parse(arena, state)?;
|
||||
|
||||
let result = TypeAnnotation::TagUnion {
|
||||
tags: tags.into_bump_slice(),
|
||||
tags: tags.items,
|
||||
ext,
|
||||
final_comments,
|
||||
final_comments: tags.final_comments,
|
||||
};
|
||||
|
||||
Ok((MadeProgress, result, state))
|
||||
}
|
||||
}
|
||||
|
||||
fn fail_type_start<'a, T: 'a>() -> impl Parser<'a, T, Type<'a>> {
|
||||
|_arena, state: State<'a>| Err((NoProgress, Type::TStart(state.line, state.column), state))
|
||||
fn fail_type_start<'a, T: 'a>() -> impl Parser<'a, T, EType<'a>> {
|
||||
|_arena, state: State<'a>| Err((NoProgress, EType::TStart(state.line, state.column), state))
|
||||
}
|
||||
|
||||
fn term<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>, Type<'a>> {
|
||||
fn term<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>, EType<'a>> {
|
||||
map_with_arena!(
|
||||
and!(
|
||||
one_of!(
|
||||
loc_wildcard(),
|
||||
specialize(Type::TInParens, loc_type_in_parens(min_indent)),
|
||||
loc!(specialize(Type::TRecord, record_type(min_indent))),
|
||||
loc!(specialize(Type::TTagUnion, tag_union_type(min_indent))),
|
||||
specialize(EType::TInParens, loc_type_in_parens(min_indent)),
|
||||
loc!(specialize(EType::TRecord, record_type(min_indent))),
|
||||
loc!(specialize(EType::TTagUnion, tag_union_type(min_indent))),
|
||||
loc!(applied_type(min_indent)),
|
||||
loc!(parse_type_variable),
|
||||
fail_type_start(),
|
||||
|
@ -67,14 +71,14 @@ fn term<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>, Typ
|
|||
map!(
|
||||
and!(
|
||||
skip_second!(
|
||||
backtrackable(space0_e(min_indent, Type::TSpace, Type::TIndentEnd)),
|
||||
crate::parser::keyword_e(keyword::AS, Type::TEnd)
|
||||
backtrackable(space0_e(min_indent, EType::TSpace, EType::TIndentEnd)),
|
||||
crate::parser::keyword_e(keyword::AS, EType::TEnd)
|
||||
),
|
||||
space0_before_e(
|
||||
term(min_indent),
|
||||
min_indent,
|
||||
Type::TSpace,
|
||||
Type::TAsIndentStart
|
||||
EType::TSpace,
|
||||
EType::TAsIndentStart
|
||||
)
|
||||
),
|
||||
Some
|
||||
|
@ -103,24 +107,26 @@ fn term<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>, Typ
|
|||
}
|
||||
|
||||
/// The `*` type variable, e.g. in (List *) Wildcard,
|
||||
fn loc_wildcard<'a>() -> impl Parser<'a, Located<TypeAnnotation<'a>>, Type<'a>> {
|
||||
map!(loc!(word1(b'*', Type::TWildcard)), |loc_val: Located<()>| {
|
||||
fn loc_wildcard<'a>() -> impl Parser<'a, Located<TypeAnnotation<'a>>, EType<'a>> {
|
||||
map!(loc!(word1(b'*', EType::TWildcard)), |loc_val: Located<
|
||||
(),
|
||||
>| {
|
||||
loc_val.map(|_| TypeAnnotation::Wildcard)
|
||||
})
|
||||
}
|
||||
|
||||
fn loc_applied_arg<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>, Type<'a>> {
|
||||
fn loc_applied_arg<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>, EType<'a>> {
|
||||
use crate::ast::Spaceable;
|
||||
|
||||
map_with_arena!(
|
||||
and!(
|
||||
backtrackable(space0_e(min_indent, Type::TSpace, Type::TIndentStart)),
|
||||
backtrackable(space0_e(min_indent, EType::TSpace, EType::TIndentStart)),
|
||||
one_of!(
|
||||
loc_wildcard(),
|
||||
specialize(Type::TInParens, loc_type_in_parens(min_indent)),
|
||||
loc!(specialize(Type::TRecord, record_type(min_indent))),
|
||||
loc!(specialize(Type::TTagUnion, tag_union_type(min_indent))),
|
||||
loc!(specialize(Type::TApply, parse_concrete_type)),
|
||||
specialize(EType::TInParens, loc_type_in_parens(min_indent)),
|
||||
loc!(specialize(EType::TRecord, record_type(min_indent))),
|
||||
loc!(specialize(EType::TTagUnion, tag_union_type(min_indent))),
|
||||
loc!(specialize(EType::TApply, parse_concrete_type)),
|
||||
loc!(parse_type_variable)
|
||||
)
|
||||
),
|
||||
|
@ -137,28 +143,28 @@ fn loc_applied_arg<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotatio
|
|||
|
||||
fn loc_type_in_parens<'a>(
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, Located<TypeAnnotation<'a>>, TInParens<'a>> {
|
||||
) -> impl Parser<'a, Located<TypeAnnotation<'a>>, ETypeInParens<'a>> {
|
||||
between!(
|
||||
word1(b'(', TInParens::Open),
|
||||
word1(b'(', ETypeInParens::Open),
|
||||
space0_around_ee(
|
||||
move |arena, state| specialize_ref(TInParens::Type, expression(min_indent))
|
||||
move |arena, state| specialize_ref(ETypeInParens::Type, expression(min_indent))
|
||||
.parse(arena, state),
|
||||
min_indent,
|
||||
TInParens::Space,
|
||||
TInParens::IndentOpen,
|
||||
TInParens::IndentEnd,
|
||||
ETypeInParens::Space,
|
||||
ETypeInParens::IndentOpen,
|
||||
ETypeInParens::IndentEnd,
|
||||
),
|
||||
word1(b')', TInParens::IndentEnd)
|
||||
word1(b')', ETypeInParens::IndentEnd)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn tag_type<'a>(min_indent: u16) -> impl Parser<'a, Tag<'a>, TTagUnion<'a>> {
|
||||
fn tag_type<'a>(min_indent: u16) -> impl Parser<'a, Tag<'a>, ETypeTagUnion<'a>> {
|
||||
move |arena, state: State<'a>| {
|
||||
let (_, name, state) = loc!(parse_tag_name(TTagUnion::End)).parse(arena, state)?;
|
||||
let (_, name, state) = loc!(parse_tag_name(ETypeTagUnion::End)).parse(arena, state)?;
|
||||
|
||||
let (_, args, state) =
|
||||
specialize_ref(TTagUnion::Type, loc_applied_args_e(min_indent)).parse(arena, state)?;
|
||||
let (_, args, state) = specialize_ref(ETypeTagUnion::Type, loc_applied_args_e(min_indent))
|
||||
.parse(arena, state)?;
|
||||
|
||||
let result = if name.value.starts_with('@') {
|
||||
Tag::Private {
|
||||
|
@ -190,7 +196,7 @@ where
|
|||
|
||||
fn record_type_field<'a>(
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, AssignedField<'a, TypeAnnotation<'a>>, TRecord<'a>> {
|
||||
) -> impl Parser<'a, AssignedField<'a, TypeAnnotation<'a>>, ETypeRecord<'a>> {
|
||||
use crate::ident::lowercase_ident;
|
||||
use crate::parser::Either::*;
|
||||
use AssignedField::*;
|
||||
|
@ -201,29 +207,33 @@ fn record_type_field<'a>(
|
|||
let row = state.line;
|
||||
let col = state.column;
|
||||
let (progress, loc_label, state) = loc!(specialize(
|
||||
move |_, _, _| TRecord::Field(row, col),
|
||||
move |_, _, _| ETypeRecord::Field(row, col),
|
||||
lowercase_ident()
|
||||
))
|
||||
.parse(arena, state)?;
|
||||
debug_assert_eq!(progress, MadeProgress);
|
||||
|
||||
let (_, spaces, state) =
|
||||
space0_e(min_indent, TRecord::Space, TRecord::IndentEnd).parse(arena, state)?;
|
||||
space0_e(min_indent, ETypeRecord::Space, ETypeRecord::IndentEnd).parse(arena, state)?;
|
||||
|
||||
// Having a value is optional; both `{ email }` and `{ email: blah }` work.
|
||||
// (This is true in both literals and types.)
|
||||
let (_, opt_loc_val, state) = optional(either!(
|
||||
word1(b':', TRecord::Colon),
|
||||
word1(b'?', TRecord::Optional)
|
||||
word1(b':', ETypeRecord::Colon),
|
||||
word1(b'?', ETypeRecord::Optional)
|
||||
))
|
||||
.parse(arena, state)?;
|
||||
|
||||
let val_parser = specialize_ref(TRecord::Type, term(min_indent));
|
||||
let val_parser = specialize_ref(ETypeRecord::Type, term(min_indent));
|
||||
|
||||
match opt_loc_val {
|
||||
Some(First(_)) => {
|
||||
let (_, loc_val, state) =
|
||||
space0_before_e(val_parser, min_indent, TRecord::Space, TRecord::IndentColon)
|
||||
let (_, loc_val, state) = space0_before_e(
|
||||
val_parser,
|
||||
min_indent,
|
||||
ETypeRecord::Space,
|
||||
ETypeRecord::IndentColon,
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
||||
Ok((
|
||||
|
@ -236,8 +246,8 @@ fn record_type_field<'a>(
|
|||
let (_, loc_val, state) = space0_before_e(
|
||||
val_parser,
|
||||
min_indent,
|
||||
TRecord::Space,
|
||||
TRecord::IndentOptional,
|
||||
ETypeRecord::Space,
|
||||
ETypeRecord::IndentOptional,
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
||||
|
@ -263,42 +273,44 @@ fn record_type_field<'a>(
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn record_type<'a>(min_indent: u16) -> impl Parser<'a, TypeAnnotation<'a>, TRecord<'a>> {
|
||||
fn record_type<'a>(min_indent: u16) -> impl Parser<'a, TypeAnnotation<'a>, ETypeRecord<'a>> {
|
||||
use crate::type_annotation::TypeAnnotation::*;
|
||||
|
||||
move |arena, state| {
|
||||
let (_, (fields, final_comments), state) = collection_trailing_sep_e!(
|
||||
let (_, fields, state) = collection_trailing_sep_e!(
|
||||
// word1_check_indent!(b'{', TRecord::Open, min_indent, TRecord::IndentOpen),
|
||||
word1(b'{', TRecord::Open),
|
||||
word1(b'{', ETypeRecord::Open),
|
||||
loc!(record_type_field(min_indent)),
|
||||
word1(b',', TRecord::End),
|
||||
word1(b',', ETypeRecord::End),
|
||||
// word1_check_indent!(b'}', TRecord::End, min_indent, TRecord::IndentEnd),
|
||||
word1(b'}', TRecord::End),
|
||||
word1(b'}', ETypeRecord::End),
|
||||
min_indent,
|
||||
TRecord::Open,
|
||||
TRecord::Space,
|
||||
TRecord::IndentEnd,
|
||||
ETypeRecord::Open,
|
||||
ETypeRecord::Space,
|
||||
ETypeRecord::IndentEnd,
|
||||
AssignedField::SpaceBefore
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
||||
let field_term = specialize_ref(TRecord::Type, term(min_indent));
|
||||
let field_term = specialize_ref(ETypeRecord::Type, term(min_indent));
|
||||
let (_, ext, state) = optional(allocated(field_term)).parse(arena, state)?;
|
||||
|
||||
let result = Record {
|
||||
fields: fields.into_bump_slice(),
|
||||
fields: Collection {
|
||||
items: fields.items,
|
||||
final_comments: fields.final_comments,
|
||||
},
|
||||
ext,
|
||||
final_comments,
|
||||
};
|
||||
|
||||
Ok((MadeProgress, result, state))
|
||||
}
|
||||
}
|
||||
|
||||
fn applied_type<'a>(min_indent: u16) -> impl Parser<'a, TypeAnnotation<'a>, Type<'a>> {
|
||||
fn applied_type<'a>(min_indent: u16) -> impl Parser<'a, TypeAnnotation<'a>, EType<'a>> {
|
||||
map!(
|
||||
and!(
|
||||
specialize(Type::TApply, parse_concrete_type),
|
||||
specialize(EType::TApply, parse_concrete_type),
|
||||
// Optionally parse space-separated arguments for the constructor,
|
||||
// e.g. `Str Float` in `Map Str Float`
|
||||
loc_applied_args_e(min_indent)
|
||||
|
@ -322,33 +334,33 @@ fn applied_type<'a>(min_indent: u16) -> impl Parser<'a, TypeAnnotation<'a>, Type
|
|||
|
||||
fn loc_applied_args_e<'a>(
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, Vec<'a, Located<TypeAnnotation<'a>>>, Type<'a>> {
|
||||
) -> impl Parser<'a, Vec<'a, Located<TypeAnnotation<'a>>>, EType<'a>> {
|
||||
zero_or_more!(loc_applied_arg(min_indent))
|
||||
}
|
||||
|
||||
fn expression<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>, Type<'a>> {
|
||||
fn expression<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>, EType<'a>> {
|
||||
move |arena, state: State<'a>| {
|
||||
let (p1, first, state) = space0_before_e(
|
||||
term(min_indent),
|
||||
min_indent,
|
||||
Type::TSpace,
|
||||
Type::TIndentStart,
|
||||
EType::TSpace,
|
||||
EType::TIndentStart,
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
||||
let (p2, rest, state) = zero_or_more!(skip_first!(
|
||||
word1(b',', Type::TFunctionArgument),
|
||||
word1(b',', EType::TFunctionArgument),
|
||||
one_of![
|
||||
space0_around_ee(
|
||||
term(min_indent),
|
||||
min_indent,
|
||||
Type::TSpace,
|
||||
Type::TIndentStart,
|
||||
Type::TIndentEnd
|
||||
EType::TSpace,
|
||||
EType::TIndentStart,
|
||||
EType::TIndentEnd
|
||||
),
|
||||
|_, state: State<'a>| Err((
|
||||
NoProgress,
|
||||
Type::TFunctionArgument(state.line, state.column),
|
||||
EType::TFunctionArgument(state.line, state.column),
|
||||
state
|
||||
))
|
||||
]
|
||||
|
@ -358,8 +370,8 @@ fn expression<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>
|
|||
// TODO this space0 is dropped, so newlines just before the function arrow when there
|
||||
// is only one argument are not seen by the formatter. Can we do better?
|
||||
let (p3, is_function, state) = optional(skip_first!(
|
||||
space0_e(min_indent, Type::TSpace, Type::TIndentStart),
|
||||
word2(b'-', b'>', Type::TStart)
|
||||
space0_e(min_indent, EType::TSpace, EType::TIndentStart),
|
||||
word2(b'-', b'>', EType::TStart)
|
||||
))
|
||||
.parse(arena, state)?;
|
||||
|
||||
|
@ -367,8 +379,8 @@ fn expression<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>
|
|||
let (p4, return_type, state) = space0_before_e(
|
||||
term(min_indent),
|
||||
min_indent,
|
||||
Type::TSpace,
|
||||
Type::TIndentStart,
|
||||
EType::TSpace,
|
||||
EType::TIndentStart,
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
||||
|
@ -416,7 +428,7 @@ fn expression<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>
|
|||
fn parse_concrete_type<'a>(
|
||||
arena: &'a Bump,
|
||||
state: State<'a>,
|
||||
) -> ParseResult<'a, TypeAnnotation<'a>, TApply> {
|
||||
) -> ParseResult<'a, TypeAnnotation<'a>, ETypeApply> {
|
||||
let initial_bytes = state.bytes;
|
||||
|
||||
match crate::ident::concrete_type().parse(arena, state) {
|
||||
|
@ -426,7 +438,7 @@ fn parse_concrete_type<'a>(
|
|||
Ok((MadeProgress, answer, state))
|
||||
}
|
||||
Err((NoProgress, _, state)) => {
|
||||
Err((NoProgress, TApply::End(state.line, state.column), state))
|
||||
Err((NoProgress, ETypeApply::End(state.line, state.column), state))
|
||||
}
|
||||
Err((MadeProgress, _, mut state)) => {
|
||||
// we made some progress, but ultimately failed.
|
||||
|
@ -437,7 +449,7 @@ fn parse_concrete_type<'a>(
|
|||
unsafe { std::str::from_utf8_unchecked(&initial_bytes[..chomped + delta]) };
|
||||
|
||||
state = state.advance_without_indenting_ee(chomped, |r, c| {
|
||||
TApply::Space(crate::parser::BadInputError::LineTooLong, r, c)
|
||||
ETypeApply::Space(crate::parser::BadInputError::LineTooLong, r, c)
|
||||
})?;
|
||||
|
||||
Ok((MadeProgress, TypeAnnotation::Malformed(parsed_str), state))
|
||||
|
@ -448,7 +460,7 @@ fn parse_concrete_type<'a>(
|
|||
fn parse_type_variable<'a>(
|
||||
arena: &'a Bump,
|
||||
state: State<'a>,
|
||||
) -> ParseResult<'a, TypeAnnotation<'a>, Type<'a>> {
|
||||
) -> ParseResult<'a, TypeAnnotation<'a>, EType<'a>> {
|
||||
match crate::ident::lowercase_ident().parse(arena, state) {
|
||||
Ok((_, name, state)) => {
|
||||
let answer = TypeAnnotation::BoundVariable(name);
|
||||
|
@ -457,7 +469,7 @@ fn parse_type_variable<'a>(
|
|||
}
|
||||
Err((progress, _, state)) => Err((
|
||||
progress,
|
||||
Type::TBadTypeVariable(state.line, state.column),
|
||||
EType::TBadTypeVariable(state.line, state.column),
|
||||
state,
|
||||
)),
|
||||
}
|
||||
|
|
|
@ -23,7 +23,9 @@ mod test_parse {
|
|||
use roc_parse::ast::Pattern::{self, *};
|
||||
use roc_parse::ast::StrLiteral::{self, *};
|
||||
use roc_parse::ast::StrSegment::*;
|
||||
use roc_parse::ast::{self, Def, EscapedChar, Spaceable, TypeAnnotation, WhenBranch};
|
||||
use roc_parse::ast::{
|
||||
self, Collection, Def, EscapedChar, Spaceable, TypeAnnotation, WhenBranch,
|
||||
};
|
||||
use roc_parse::header::{
|
||||
AppHeader, Effects, ExposesEntry, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry,
|
||||
PackageName, PackageOrPath, PlatformHeader, PlatformRequires, PlatformRigid, To,
|
||||
|
@ -2281,9 +2283,8 @@ mod test_parse {
|
|||
6,
|
||||
TypeAnnotation::SpaceBefore(
|
||||
&TypeAnnotation::Record {
|
||||
fields: &[],
|
||||
fields: Collection::empty(),
|
||||
ext: None,
|
||||
final_comments: &[],
|
||||
},
|
||||
&[Newline],
|
||||
),
|
||||
|
@ -2320,9 +2321,8 @@ mod test_parse {
|
|||
6,
|
||||
TypeAnnotation::SpaceBefore(
|
||||
&TypeAnnotation::Record {
|
||||
fields: &[],
|
||||
fields: Collection::empty(),
|
||||
ext: None,
|
||||
final_comments: &[],
|
||||
},
|
||||
&[LineComment(" comment")],
|
||||
),
|
||||
|
@ -3091,7 +3091,7 @@ mod test_parse {
|
|||
#[test]
|
||||
fn empty_app_header() {
|
||||
let arena = Bump::new();
|
||||
let packages = Vec::new_in(&arena);
|
||||
let packages = Collection::empty();
|
||||
let imports = Vec::new_in(&arena);
|
||||
let provides = Vec::new_in(&arena);
|
||||
let module_name = StrLiteral::PlainLine("test-app");
|
||||
|
@ -3131,7 +3131,7 @@ mod test_parse {
|
|||
use PackageOrPath::Path;
|
||||
|
||||
let arena = Bump::new();
|
||||
let packages = Vec::new_in(&arena);
|
||||
let packages = Collection::empty();
|
||||
let imports = Vec::new_in(&arena);
|
||||
let provides = Vec::new_in(&arena);
|
||||
let module_name = StrLiteral::PlainLine("test-app");
|
||||
|
@ -3180,7 +3180,7 @@ mod test_parse {
|
|||
};
|
||||
let loc_pkg_entry = Located::new(1, 1, 15, 33, pkg_entry);
|
||||
let arena = Bump::new();
|
||||
let packages = bumpalo::vec![in &arena; 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 loc_import = Located::new(2, 2, 14, 25, import);
|
||||
let imports = bumpalo::vec![in &arena; loc_import];
|
||||
|
@ -3236,7 +3236,7 @@ mod test_parse {
|
|||
};
|
||||
let loc_pkg_entry = Located::new(1, 1, 15, 33, pkg_entry);
|
||||
let arena = Bump::new();
|
||||
let packages = bumpalo::vec![in &arena; 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 loc_import = Located::new(2, 2, 14, 25, import);
|
||||
let imports = bumpalo::vec![in &arena; loc_import];
|
||||
|
@ -3309,9 +3309,8 @@ mod test_parse {
|
|||
ann: Located::at(
|
||||
region2,
|
||||
TypeAnnotation::Record {
|
||||
fields: &[],
|
||||
fields: Collection::empty(),
|
||||
ext: None,
|
||||
final_comments: &[],
|
||||
},
|
||||
),
|
||||
},
|
||||
|
@ -3324,7 +3323,7 @@ mod test_parse {
|
|||
name: Located::new(0, 0, 9, 23, pkg_name),
|
||||
requires,
|
||||
exposes: Vec::new_in(&arena),
|
||||
packages: Vec::new_in(&arena),
|
||||
packages: Collection::empty(),
|
||||
imports: Vec::new_in(&arena),
|
||||
provides: Vec::new_in(&arena),
|
||||
effects,
|
||||
|
@ -3367,7 +3366,7 @@ mod test_parse {
|
|||
};
|
||||
let loc_pkg_entry = Located::new(3, 3, 15, 27, pkg_entry);
|
||||
let arena = Bump::new();
|
||||
let packages = bumpalo::vec![in &arena; loc_pkg_entry];
|
||||
let packages = Collection::with_items(arena.alloc([loc_pkg_entry]));
|
||||
let imports = Vec::new_in(&arena);
|
||||
let provide_entry = Located::new(5, 5, 15, 26, Exposed("mainForHost"));
|
||||
let provides = bumpalo::vec![in &arena; provide_entry];
|
||||
|
@ -3395,9 +3394,8 @@ mod test_parse {
|
|||
ann: Located::at(
|
||||
region2,
|
||||
TypeAnnotation::Record {
|
||||
fields: &[],
|
||||
fields: Collection::empty(),
|
||||
ext: None,
|
||||
final_comments: &[],
|
||||
},
|
||||
),
|
||||
},
|
||||
|
|
|
@ -1019,16 +1019,16 @@ fn to_list_report<'a>(
|
|||
alloc: &'a RocDocAllocator<'a>,
|
||||
filename: PathBuf,
|
||||
context: Context,
|
||||
parse_problem: &roc_parse::parser::List<'a>,
|
||||
parse_problem: &roc_parse::parser::EList<'a>,
|
||||
start_row: Row,
|
||||
start_col: Col,
|
||||
) -> Report<'a> {
|
||||
use roc_parse::parser::List;
|
||||
use roc_parse::parser::EList;
|
||||
|
||||
match *parse_problem {
|
||||
List::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||
EList::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||
|
||||
List::Expr(expr, row, col) => to_expr_report(
|
||||
EList::Expr(expr, row, col) => to_expr_report(
|
||||
alloc,
|
||||
filename,
|
||||
Context::InNode(Node::ListElement, start_row, start_col, Box::new(context)),
|
||||
|
@ -1037,7 +1037,7 @@ fn to_list_report<'a>(
|
|||
col,
|
||||
),
|
||||
|
||||
List::Open(row, col) | List::End(row, col) => {
|
||||
EList::Open(row, col) | EList::End(row, col) => {
|
||||
match what_is_next(alloc.src_lines, row, col) {
|
||||
Next::Other(Some(',')) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
|
@ -1098,7 +1098,7 @@ fn to_list_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
List::IndentOpen(row, col) | List::IndentEnd(row, col) => {
|
||||
EList::IndentOpen(row, col) | EList::IndentEnd(row, col) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
|
@ -1130,16 +1130,16 @@ fn to_if_report<'a>(
|
|||
alloc: &'a RocDocAllocator<'a>,
|
||||
filename: PathBuf,
|
||||
context: Context,
|
||||
parse_problem: &roc_parse::parser::If<'a>,
|
||||
parse_problem: &roc_parse::parser::EIf<'a>,
|
||||
start_row: Row,
|
||||
start_col: Col,
|
||||
) -> Report<'a> {
|
||||
use roc_parse::parser::If;
|
||||
use roc_parse::parser::EIf;
|
||||
|
||||
match *parse_problem {
|
||||
If::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||
EIf::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||
|
||||
If::Condition(expr, row, col) => to_expr_report(
|
||||
EIf::Condition(expr, row, col) => to_expr_report(
|
||||
alloc,
|
||||
filename,
|
||||
Context::InNode(Node::IfCondition, start_row, start_col, Box::new(context)),
|
||||
|
@ -1148,7 +1148,7 @@ fn to_if_report<'a>(
|
|||
col,
|
||||
),
|
||||
|
||||
If::ThenBranch(expr, row, col) => to_expr_report(
|
||||
EIf::ThenBranch(expr, row, col) => to_expr_report(
|
||||
alloc,
|
||||
filename,
|
||||
Context::InNode(Node::IfThenBranch, start_row, start_col, Box::new(context)),
|
||||
|
@ -1157,7 +1157,7 @@ fn to_if_report<'a>(
|
|||
col,
|
||||
),
|
||||
|
||||
If::ElseBranch(expr, row, col) => to_expr_report(
|
||||
EIf::ElseBranch(expr, row, col) => to_expr_report(
|
||||
alloc,
|
||||
filename,
|
||||
Context::InNode(Node::IfElseBranch, start_row, start_col, Box::new(context)),
|
||||
|
@ -1166,10 +1166,10 @@ fn to_if_report<'a>(
|
|||
col,
|
||||
),
|
||||
|
||||
If::If(_row, _col) => unreachable!("another branch would be taken"),
|
||||
If::IndentIf(_row, _col) => unreachable!("another branch would be taken"),
|
||||
EIf::If(_row, _col) => unreachable!("another branch would be taken"),
|
||||
EIf::IndentIf(_row, _col) => unreachable!("another branch would be taken"),
|
||||
|
||||
If::Then(row, col) | If::IndentThenBranch(row, col) | If::IndentThenToken(row, col) => {
|
||||
EIf::Then(row, col) | EIf::IndentThenBranch(row, col) | EIf::IndentThenToken(row, col) => {
|
||||
to_unfinished_if_report(
|
||||
alloc,
|
||||
filename,
|
||||
|
@ -1185,7 +1185,7 @@ fn to_if_report<'a>(
|
|||
)
|
||||
}
|
||||
|
||||
If::Else(row, col) | If::IndentElseBranch(row, col) | If::IndentElseToken(row, col) => {
|
||||
EIf::Else(row, col) | EIf::IndentElseBranch(row, col) | EIf::IndentElseToken(row, col) => {
|
||||
to_unfinished_if_report(
|
||||
alloc,
|
||||
filename,
|
||||
|
@ -1201,7 +1201,7 @@ fn to_if_report<'a>(
|
|||
)
|
||||
}
|
||||
|
||||
If::IndentCondition(row, col) => to_unfinished_if_report(
|
||||
EIf::IndentCondition(row, col) => to_unfinished_if_report(
|
||||
alloc,
|
||||
filename,
|
||||
row,
|
||||
|
@ -1249,14 +1249,14 @@ fn to_when_report<'a>(
|
|||
alloc: &'a RocDocAllocator<'a>,
|
||||
filename: PathBuf,
|
||||
context: Context,
|
||||
parse_problem: &roc_parse::parser::When<'a>,
|
||||
parse_problem: &roc_parse::parser::EWhen<'a>,
|
||||
start_row: Row,
|
||||
start_col: Col,
|
||||
) -> Report<'a> {
|
||||
use roc_parse::parser::When;
|
||||
use roc_parse::parser::EWhen;
|
||||
|
||||
match *parse_problem {
|
||||
When::IfGuard(nested, row, col) => match what_is_next(alloc.src_lines, row, col) {
|
||||
EWhen::IfGuard(nested, row, col) => match what_is_next(alloc.src_lines, row, col) {
|
||||
Next::Token("->") => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
@ -1287,7 +1287,7 @@ fn to_when_report<'a>(
|
|||
col,
|
||||
),
|
||||
},
|
||||
When::Arrow(row, col) => {
|
||||
EWhen::Arrow(row, col) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
|
@ -1310,9 +1310,9 @@ fn to_when_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
When::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||
EWhen::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||
|
||||
When::Branch(expr, row, col) => to_expr_report(
|
||||
EWhen::Branch(expr, row, col) => to_expr_report(
|
||||
alloc,
|
||||
filename,
|
||||
Context::InNode(Node::WhenBranch, start_row, start_col, Box::new(context)),
|
||||
|
@ -1321,7 +1321,7 @@ fn to_when_report<'a>(
|
|||
col,
|
||||
),
|
||||
|
||||
When::Condition(expr, row, col) => to_expr_report(
|
||||
EWhen::Condition(expr, row, col) => to_expr_report(
|
||||
alloc,
|
||||
filename,
|
||||
Context::InNode(Node::WhenCondition, start_row, start_col, Box::new(context)),
|
||||
|
@ -1330,7 +1330,7 @@ fn to_when_report<'a>(
|
|||
col,
|
||||
),
|
||||
|
||||
When::Bar(row, col) => to_unfinished_when_report(
|
||||
EWhen::Bar(row, col) => to_unfinished_when_report(
|
||||
alloc,
|
||||
filename,
|
||||
row,
|
||||
|
@ -1344,10 +1344,10 @@ fn to_when_report<'a>(
|
|||
]),
|
||||
),
|
||||
|
||||
When::IfToken(_row, _col) => unreachable!("the if-token is optional"),
|
||||
When::When(_row, _col) => unreachable!("another branch would be taken"),
|
||||
EWhen::IfToken(_row, _col) => unreachable!("the if-token is optional"),
|
||||
EWhen::When(_row, _col) => unreachable!("another branch would be taken"),
|
||||
|
||||
When::Is(row, col) | When::IndentIs(row, col) => to_unfinished_when_report(
|
||||
EWhen::Is(row, col) | EWhen::IndentIs(row, col) => to_unfinished_when_report(
|
||||
alloc,
|
||||
filename,
|
||||
row,
|
||||
|
@ -1361,7 +1361,7 @@ fn to_when_report<'a>(
|
|||
]),
|
||||
),
|
||||
|
||||
When::IndentCondition(row, col) => to_unfinished_when_report(
|
||||
EWhen::IndentCondition(row, col) => to_unfinished_when_report(
|
||||
alloc,
|
||||
filename,
|
||||
row,
|
||||
|
@ -1373,7 +1373,7 @@ fn to_when_report<'a>(
|
|||
]),
|
||||
),
|
||||
|
||||
When::IndentPattern(row, col) => to_unfinished_when_report(
|
||||
EWhen::IndentPattern(row, col) => to_unfinished_when_report(
|
||||
alloc,
|
||||
filename,
|
||||
row,
|
||||
|
@ -1383,7 +1383,7 @@ fn to_when_report<'a>(
|
|||
alloc.concat(vec![alloc.reflow(r"I was expecting to see a pattern next")]),
|
||||
),
|
||||
|
||||
When::IndentArrow(row, col) => to_unfinished_when_report(
|
||||
EWhen::IndentArrow(row, col) => to_unfinished_when_report(
|
||||
alloc,
|
||||
filename,
|
||||
row,
|
||||
|
@ -1397,7 +1397,7 @@ fn to_when_report<'a>(
|
|||
]),
|
||||
),
|
||||
|
||||
When::IndentIfGuard(row, col) => to_unfinished_when_report(
|
||||
EWhen::IndentIfGuard(row, col) => to_unfinished_when_report(
|
||||
alloc,
|
||||
filename,
|
||||
row,
|
||||
|
@ -1411,7 +1411,7 @@ fn to_when_report<'a>(
|
|||
]),
|
||||
),
|
||||
|
||||
When::IndentBranch(row, col) => to_unfinished_when_report(
|
||||
EWhen::IndentBranch(row, col) => to_unfinished_when_report(
|
||||
alloc,
|
||||
filename,
|
||||
row,
|
||||
|
@ -1424,7 +1424,7 @@ fn to_when_report<'a>(
|
|||
]),
|
||||
),
|
||||
|
||||
When::PatternAlignment(indent, row, col) => to_unfinished_when_report(
|
||||
EWhen::PatternAlignment(indent, row, col) => to_unfinished_when_report(
|
||||
alloc,
|
||||
filename,
|
||||
row,
|
||||
|
@ -1437,7 +1437,7 @@ fn to_when_report<'a>(
|
|||
alloc.reflow(" spaces)"),
|
||||
]),
|
||||
),
|
||||
When::Pattern(ref pat, row, col) => to_pattern_report(alloc, filename, pat, row, col),
|
||||
EWhen::Pattern(ref pat, row, col) => to_pattern_report(alloc, filename, pat, row, col),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2000,23 +2000,23 @@ fn to_pattern_in_parens_report<'a>(
|
|||
fn to_type_report<'a>(
|
||||
alloc: &'a RocDocAllocator<'a>,
|
||||
filename: PathBuf,
|
||||
parse_problem: &roc_parse::parser::Type<'a>,
|
||||
parse_problem: &roc_parse::parser::EType<'a>,
|
||||
start_row: Row,
|
||||
start_col: Col,
|
||||
) -> Report<'a> {
|
||||
use roc_parse::parser::Type;
|
||||
use roc_parse::parser::EType;
|
||||
|
||||
match parse_problem {
|
||||
Type::TRecord(record, row, col) => to_trecord_report(alloc, filename, record, *row, *col),
|
||||
Type::TTagUnion(tag_union, row, col) => {
|
||||
EType::TRecord(record, row, col) => to_trecord_report(alloc, filename, record, *row, *col),
|
||||
EType::TTagUnion(tag_union, row, col) => {
|
||||
to_ttag_union_report(alloc, filename, tag_union, *row, *col)
|
||||
}
|
||||
Type::TInParens(tinparens, row, col) => {
|
||||
EType::TInParens(tinparens, row, col) => {
|
||||
to_tinparens_report(alloc, filename, tinparens, *row, *col)
|
||||
}
|
||||
Type::TApply(tapply, row, col) => to_tapply_report(alloc, filename, tapply, *row, *col),
|
||||
EType::TApply(tapply, row, col) => to_tapply_report(alloc, filename, tapply, *row, *col),
|
||||
|
||||
Type::TFunctionArgument(row, col) => match what_is_next(alloc.src_lines, *row, *col) {
|
||||
EType::TFunctionArgument(row, col) => match what_is_next(alloc.src_lines, *row, *col) {
|
||||
Next::Other(Some(',')) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, *row, *col);
|
||||
let region = Region::from_row_col(*row, *col);
|
||||
|
@ -2037,7 +2037,7 @@ fn to_type_report<'a>(
|
|||
_ => todo!(),
|
||||
},
|
||||
|
||||
Type::TStart(row, col) => {
|
||||
EType::TStart(row, col) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, *row, *col);
|
||||
let region = Region::from_row_col(*row, *col);
|
||||
|
||||
|
@ -2061,7 +2061,7 @@ fn to_type_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
Type::TIndentStart(row, col) => {
|
||||
EType::TIndentStart(row, col) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, *row, *col);
|
||||
let region = Region::from_row_col(*row, *col);
|
||||
|
||||
|
@ -2079,7 +2079,7 @@ fn to_type_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
Type::TIndentEnd(row, col) => {
|
||||
EType::TIndentEnd(row, col) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, *row, *col);
|
||||
let region = Region::from_row_col(*row, *col);
|
||||
|
||||
|
@ -2097,7 +2097,7 @@ fn to_type_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
Type::TAsIndentStart(row, col) => {
|
||||
EType::TAsIndentStart(row, col) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, *row, *col);
|
||||
let region = Region::from_row_col(*row, *col);
|
||||
|
||||
|
@ -2115,7 +2115,7 @@ fn to_type_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
Type::TBadTypeVariable(row, col) => {
|
||||
EType::TBadTypeVariable(row, col) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, *row, *col);
|
||||
let region = Region::from_row_col(*row, *col);
|
||||
|
||||
|
@ -2139,14 +2139,14 @@ fn to_type_report<'a>(
|
|||
fn to_trecord_report<'a>(
|
||||
alloc: &'a RocDocAllocator<'a>,
|
||||
filename: PathBuf,
|
||||
parse_problem: &roc_parse::parser::TRecord<'a>,
|
||||
parse_problem: &roc_parse::parser::ETypeRecord<'a>,
|
||||
start_row: Row,
|
||||
start_col: Col,
|
||||
) -> Report<'a> {
|
||||
use roc_parse::parser::TRecord;
|
||||
use roc_parse::parser::ETypeRecord;
|
||||
|
||||
match *parse_problem {
|
||||
TRecord::Open(row, col) => match what_is_next(alloc.src_lines, row, col) {
|
||||
ETypeRecord::Open(row, col) => match what_is_next(alloc.src_lines, row, col) {
|
||||
Next::Keyword(keyword) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
let region = to_keyword_region(row, col, keyword);
|
||||
|
@ -2191,7 +2191,7 @@ fn to_trecord_report<'a>(
|
|||
}
|
||||
},
|
||||
|
||||
TRecord::End(row, col) => {
|
||||
ETypeRecord::End(row, col) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
|
@ -2237,7 +2237,7 @@ fn to_trecord_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
TRecord::Field(row, col) => match what_is_next(alloc.src_lines, row, col) {
|
||||
ETypeRecord::Field(row, col) => match what_is_next(alloc.src_lines, row, col) {
|
||||
Next::Keyword(keyword) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
let region = to_keyword_region(row, col, keyword);
|
||||
|
@ -2286,16 +2286,16 @@ fn to_trecord_report<'a>(
|
|||
}
|
||||
},
|
||||
|
||||
TRecord::Colon(_, _) => {
|
||||
ETypeRecord::Colon(_, _) => {
|
||||
unreachable!("because `{ foo }` is a valid field; the colon is not required")
|
||||
}
|
||||
TRecord::Optional(_, _) => {
|
||||
ETypeRecord::Optional(_, _) => {
|
||||
unreachable!("because `{ foo }` is a valid field; the question mark is not required")
|
||||
}
|
||||
|
||||
TRecord::Type(tipe, row, col) => to_type_report(alloc, filename, tipe, row, col),
|
||||
ETypeRecord::Type(tipe, row, col) => to_type_report(alloc, filename, tipe, row, col),
|
||||
|
||||
TRecord::IndentOpen(row, col) => {
|
||||
ETypeRecord::IndentOpen(row, col) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
|
@ -2318,7 +2318,7 @@ fn to_trecord_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
TRecord::IndentEnd(row, col) => {
|
||||
ETypeRecord::IndentEnd(row, col) => {
|
||||
match next_line_starts_with_close_curly(alloc.src_lines, row) {
|
||||
Some((curly_row, curly_col)) => {
|
||||
let surroundings =
|
||||
|
@ -2370,29 +2370,29 @@ fn to_trecord_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
TRecord::IndentColon(_, _) => {
|
||||
ETypeRecord::IndentColon(_, _) => {
|
||||
unreachable!("because `{ foo }` is a valid field; the colon is not required")
|
||||
}
|
||||
|
||||
TRecord::IndentOptional(_, _) => {
|
||||
ETypeRecord::IndentOptional(_, _) => {
|
||||
unreachable!("because `{ foo }` is a valid field; the question mark is not required")
|
||||
}
|
||||
|
||||
TRecord::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||
ETypeRecord::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_ttag_union_report<'a>(
|
||||
alloc: &'a RocDocAllocator<'a>,
|
||||
filename: PathBuf,
|
||||
parse_problem: &roc_parse::parser::TTagUnion<'a>,
|
||||
parse_problem: &roc_parse::parser::ETypeTagUnion<'a>,
|
||||
start_row: Row,
|
||||
start_col: Col,
|
||||
) -> Report<'a> {
|
||||
use roc_parse::parser::TTagUnion;
|
||||
use roc_parse::parser::ETypeTagUnion;
|
||||
|
||||
match *parse_problem {
|
||||
TTagUnion::Open(row, col) => match what_is_next(alloc.src_lines, row, col) {
|
||||
ETypeTagUnion::Open(row, col) => match what_is_next(alloc.src_lines, row, col) {
|
||||
Next::Keyword(keyword) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
let region = to_keyword_region(row, col, keyword);
|
||||
|
@ -2459,7 +2459,7 @@ fn to_ttag_union_report<'a>(
|
|||
}
|
||||
},
|
||||
|
||||
TTagUnion::End(row, col) => {
|
||||
ETypeTagUnion::End(row, col) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
|
@ -2523,9 +2523,9 @@ fn to_ttag_union_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
TTagUnion::Type(tipe, row, col) => to_type_report(alloc, filename, tipe, row, col),
|
||||
ETypeTagUnion::Type(tipe, row, col) => to_type_report(alloc, filename, tipe, row, col),
|
||||
|
||||
TTagUnion::IndentOpen(row, col) => {
|
||||
ETypeTagUnion::IndentOpen(row, col) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
|
@ -2548,7 +2548,7 @@ fn to_ttag_union_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
TTagUnion::IndentEnd(row, col) => {
|
||||
ETypeTagUnion::IndentEnd(row, col) => {
|
||||
match next_line_starts_with_close_square_bracket(alloc.src_lines, row) {
|
||||
Some((curly_row, curly_col)) => {
|
||||
let surroundings =
|
||||
|
@ -2600,21 +2600,21 @@ fn to_ttag_union_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
TTagUnion::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||
ETypeTagUnion::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_tinparens_report<'a>(
|
||||
alloc: &'a RocDocAllocator<'a>,
|
||||
filename: PathBuf,
|
||||
parse_problem: &roc_parse::parser::TInParens<'a>,
|
||||
parse_problem: &roc_parse::parser::ETypeInParens<'a>,
|
||||
start_row: Row,
|
||||
start_col: Col,
|
||||
) -> Report<'a> {
|
||||
use roc_parse::parser::TInParens;
|
||||
use roc_parse::parser::ETypeInParens;
|
||||
|
||||
match *parse_problem {
|
||||
TInParens::Open(row, col) => {
|
||||
ETypeInParens::Open(row, col) => {
|
||||
match what_is_next(alloc.src_lines, row, col) {
|
||||
Next::Keyword(keyword) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
|
@ -2686,7 +2686,7 @@ fn to_tinparens_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
TInParens::End(row, col) => {
|
||||
ETypeInParens::End(row, col) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
|
@ -2734,9 +2734,9 @@ fn to_tinparens_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
TInParens::Type(tipe, row, col) => to_type_report(alloc, filename, tipe, row, col),
|
||||
ETypeInParens::Type(tipe, row, col) => to_type_report(alloc, filename, tipe, row, col),
|
||||
|
||||
TInParens::IndentOpen(row, col) => {
|
||||
ETypeInParens::IndentOpen(row, col) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, row, col);
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
|
@ -2760,7 +2760,7 @@ fn to_tinparens_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
TInParens::IndentEnd(row, col) => {
|
||||
ETypeInParens::IndentEnd(row, col) => {
|
||||
match next_line_starts_with_close_parenthesis(alloc.src_lines, row) {
|
||||
Some((curly_row, curly_col)) => {
|
||||
let surroundings =
|
||||
|
@ -2812,21 +2812,21 @@ fn to_tinparens_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
TInParens::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||
ETypeInParens::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_tapply_report<'a>(
|
||||
alloc: &'a RocDocAllocator<'a>,
|
||||
filename: PathBuf,
|
||||
parse_problem: &roc_parse::parser::TApply,
|
||||
parse_problem: &roc_parse::parser::ETypeApply,
|
||||
_start_row: Row,
|
||||
_start_col: Col,
|
||||
) -> Report<'a> {
|
||||
use roc_parse::parser::TApply;
|
||||
use roc_parse::parser::ETypeApply;
|
||||
|
||||
match *parse_problem {
|
||||
TApply::DoubleDot(row, col) => {
|
||||
ETypeApply::DoubleDot(row, col) => {
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
let doc = alloc.stack(vec![
|
||||
|
@ -2842,7 +2842,7 @@ fn to_tapply_report<'a>(
|
|||
severity: Severity::RuntimeError,
|
||||
}
|
||||
}
|
||||
TApply::TrailingDot(row, col) => {
|
||||
ETypeApply::TrailingDot(row, col) => {
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
let doc = alloc.stack(vec![
|
||||
|
@ -2864,7 +2864,7 @@ fn to_tapply_report<'a>(
|
|||
severity: Severity::RuntimeError,
|
||||
}
|
||||
}
|
||||
TApply::StartIsNumber(row, col) => {
|
||||
ETypeApply::StartIsNumber(row, col) => {
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
let doc = alloc.stack(vec![
|
||||
|
@ -2886,7 +2886,7 @@ fn to_tapply_report<'a>(
|
|||
severity: Severity::RuntimeError,
|
||||
}
|
||||
}
|
||||
TApply::StartNotUppercase(row, col) => {
|
||||
ETypeApply::StartNotUppercase(row, col) => {
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
let doc = alloc.stack(vec![
|
||||
|
@ -2909,7 +2909,7 @@ fn to_tapply_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
TApply::End(row, col) => {
|
||||
ETypeApply::End(row, col) => {
|
||||
let region = Region::from_row_col(row, col);
|
||||
|
||||
let doc = alloc.stack(vec![
|
||||
|
@ -2927,7 +2927,7 @@ fn to_tapply_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
TApply::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||
ETypeApply::Space(error, row, col) => to_space_report(alloc, filename, &error, row, col),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
#![cfg(not(feature = "gen-wasm"))]
|
||||
|
||||
#[cfg(feature = "gen-llvm")]
|
||||
use crate::helpers::llvm::assert_evals_to;
|
||||
|
||||
#[cfg(feature = "gen-dev")]
|
||||
use crate::helpers::dev::assert_evals_to;
|
||||
|
||||
// #[cfg(feature = "gen-wasm")]
|
||||
// use crate::helpers::wasm::assert_evals_to;
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
use crate::helpers::wasm::assert_evals_to;
|
||||
|
||||
// use crate::assert_wasm_evals_to as assert_evals_to;
|
||||
use indoc::indoc;
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn eq_i64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -30,7 +27,7 @@ fn eq_i64() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn neq_i64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -47,7 +44,7 @@ fn neq_i64() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn eq_u64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -64,7 +61,7 @@ fn eq_u64() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn neq_u64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -81,7 +78,7 @@ fn neq_u64() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn eq_f64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -98,7 +95,7 @@ fn eq_f64() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn neq_f64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -115,7 +112,7 @@ fn neq_f64() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn eq_bool_tag() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -132,7 +129,7 @@ fn eq_bool_tag() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn neq_bool_tag() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -163,7 +160,7 @@ fn unit() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn newtype() {
|
||||
assert_evals_to!("Identity 42 == Identity 42", true, bool);
|
||||
assert_evals_to!("Identity 42 != Identity 42", false, bool);
|
||||
|
|
|
@ -571,7 +571,7 @@ fn abs_min_int_overflow() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn gen_if_fn() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
|
@ -85,7 +85,7 @@ fn branch_third_float() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn branch_first_int() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -101,7 +101,7 @@ fn branch_first_int() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn branch_second_int() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -134,7 +134,7 @@ fn branch_third_int() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn branch_store_variable() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -221,7 +221,7 @@ fn gen_when_one_branch() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn gen_large_when_int() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -243,31 +243,31 @@ fn gen_large_when_int() {
|
|||
);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// #[cfg(any(feature = "gen-llvm"))]
|
||||
// fn gen_large_when_float() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// foo = \num ->
|
||||
// when num is
|
||||
// 0.5 -> 200.1
|
||||
// -3.6 -> 111.2 # TODO adding more negative numbers reproduces parsing bugs here
|
||||
// 3.6 -> 789.5
|
||||
// 1.7 -> 123.3
|
||||
// 2.8 -> 456.4
|
||||
// _ -> 1000.6
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-wasm"))]
|
||||
fn gen_large_when_float() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
foo = \num ->
|
||||
when num is
|
||||
0.5 -> 200.1
|
||||
-3.6 -> 111.2 # TODO adding more negative numbers reproduces parsing bugs here
|
||||
3.6 -> 789.5
|
||||
1.7 -> 123.3
|
||||
2.8 -> 456.4
|
||||
_ -> 1000.6
|
||||
|
||||
// foo -3.6
|
||||
// "#
|
||||
// ),
|
||||
// 111.2,
|
||||
// f64
|
||||
// );
|
||||
// }
|
||||
foo -3.6
|
||||
"#
|
||||
),
|
||||
111.2,
|
||||
f64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn or_pattern() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -337,7 +337,7 @@ fn return_unnamed_fn() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn gen_when_fn() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -504,7 +504,7 @@ fn gen_multiple_defs() {
|
|||
// }
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn factorial() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
|
@ -159,3 +159,33 @@ fn err_empty_tag_union() {
|
|||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn is_ok() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
result : Result I64 {}
|
||||
result = Ok 2
|
||||
|
||||
Result.isOk result
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
result : Result I64 {}
|
||||
result = Err {}
|
||||
|
||||
Result.isOk result
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ pub fn helper_wasm<'a, T: Wasm32TestResult>(
|
|||
let src_hash = hash_state.finish();
|
||||
|
||||
// Filename contains a hash of the Roc test source code. Helpful when comparing across commits.
|
||||
let dir = "/tmp/roc/compiler/gen_wasm/output";
|
||||
let dir = "/tmp/roc/gen_wasm";
|
||||
std::fs::create_dir_all(dir).unwrap();
|
||||
let path = format!("{}/test-{:016x}.wasm", dir, src_hash);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ pub mod gen_list;
|
|||
pub mod gen_num;
|
||||
pub mod gen_primitives;
|
||||
pub mod gen_records;
|
||||
pub mod gen_result;
|
||||
pub mod gen_set;
|
||||
pub mod gen_str;
|
||||
pub mod gen_tags;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue