mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Merge branch 'main' into specialize-exprs
This commit is contained in:
commit
2e96aca0fd
797 changed files with 17394 additions and 12632 deletions
|
@ -24,6 +24,8 @@ bitvec.workspace = true
|
|||
bumpalo.workspace = true
|
||||
static_assertions.workspace = true
|
||||
|
||||
soa.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
indoc.workspace = true
|
||||
insta.workspace = true
|
||||
|
|
|
@ -683,7 +683,7 @@ impl IAbilitiesStore<Pending> {
|
|||
}
|
||||
|
||||
mod serialize {
|
||||
use roc_collections::{MutMap, VecMap};
|
||||
use roc_collections::{soa::slice_extend_new, MutMap, VecMap};
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_region::all::Region;
|
||||
use roc_serialize::bytes;
|
||||
|
@ -1034,11 +1034,11 @@ mod serialize {
|
|||
specialization_lambda_sets,
|
||||
} in spec_info
|
||||
{
|
||||
let regions = SubsSlice::extend_new(
|
||||
let regions = slice_extend_new(
|
||||
&mut spec_lambda_sets_regions,
|
||||
specialization_lambda_sets.keys().copied(),
|
||||
);
|
||||
let vars = SubsSlice::extend_new(
|
||||
let vars = slice_extend_new(
|
||||
&mut spec_lambda_sets_vars,
|
||||
specialization_lambda_sets.values().copied(),
|
||||
);
|
||||
|
@ -1168,11 +1168,11 @@ mod serialize {
|
|||
symbol,
|
||||
specialization_lambda_sets,
|
||||
}) => {
|
||||
let regions = SubsSlice::extend_new(
|
||||
let regions = slice_extend_new(
|
||||
&mut spec_lambda_sets_regions,
|
||||
specialization_lambda_sets.keys().copied(),
|
||||
);
|
||||
let vars = SubsSlice::extend_new(
|
||||
let vars = slice_extend_new(
|
||||
&mut spec_lambda_sets_vars,
|
||||
specialization_lambda_sets.values().copied(),
|
||||
);
|
||||
|
|
|
@ -2,10 +2,12 @@ use crate::env::Env;
|
|||
use crate::procedure::{QualifiedReference, References};
|
||||
use crate::scope::{PendingAbilitiesInScope, Scope, SymbolLookup};
|
||||
use roc_collections::{ImMap, MutSet, SendMap, VecMap, VecSet};
|
||||
use roc_module::ident::{Ident, Lowercase, TagName};
|
||||
use roc_module::ident::{Ident, IdentSuffix, Lowercase, TagName};
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_parse::ast::{AssignedField, ExtractSpaces, Pattern, Tag, TypeAnnotation, TypeHeader};
|
||||
use roc_problem::can::ShadowKind;
|
||||
use roc_parse::ast::{
|
||||
AssignedField, ExtractSpaces, FunctionArrow, Pattern, Tag, TypeAnnotation, TypeHeader,
|
||||
};
|
||||
use roc_problem::can::{Problem, ShadowKind};
|
||||
use roc_region::all::{Loc, Region};
|
||||
use roc_types::subs::{VarStore, Variable};
|
||||
use roc_types::types::{
|
||||
|
@ -448,7 +450,7 @@ pub fn find_type_def_symbols(
|
|||
stack.push(&t.value);
|
||||
}
|
||||
}
|
||||
Function(arguments, result) => {
|
||||
Function(arguments, _arrow, result) => {
|
||||
for t in arguments.iter() {
|
||||
stack.push(&t.value);
|
||||
}
|
||||
|
@ -480,7 +482,6 @@ pub fn find_type_def_symbols(
|
|||
AssignedField::LabelOnly(_) => {}
|
||||
AssignedField::SpaceBefore(inner, _)
|
||||
| AssignedField::SpaceAfter(inner, _) => inner_stack.push(inner),
|
||||
AssignedField::Malformed(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -505,7 +506,6 @@ pub fn find_type_def_symbols(
|
|||
Tag::SpaceBefore(inner, _) | Tag::SpaceAfter(inner, _) => {
|
||||
inner_stack.push(inner)
|
||||
}
|
||||
Tag::Malformed(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -554,7 +554,7 @@ fn can_annotation_help(
|
|||
use roc_parse::ast::TypeAnnotation::*;
|
||||
|
||||
match annotation {
|
||||
Function(argument_types, return_type) => {
|
||||
Function(argument_types, arrow, return_type) => {
|
||||
let mut args = Vec::new();
|
||||
|
||||
for arg in *argument_types {
|
||||
|
@ -589,7 +589,12 @@ fn can_annotation_help(
|
|||
introduced_variables.insert_lambda_set(lambda_set);
|
||||
let closure = Type::Variable(lambda_set);
|
||||
|
||||
Type::Function(args, Box::new(closure), Box::new(ret))
|
||||
let fx_type = match arrow {
|
||||
FunctionArrow::Pure => Type::Pure,
|
||||
FunctionArrow::Effectful => Type::Effectful,
|
||||
};
|
||||
|
||||
Type::Function(args, Box::new(closure), Box::new(ret), Box::new(fx_type))
|
||||
}
|
||||
Apply(module_name, ident, type_arguments) => {
|
||||
let symbol = match make_apply_symbol(env, region, scope, module_name, ident, references)
|
||||
|
@ -1348,7 +1353,7 @@ fn can_assigned_fields<'a>(
|
|||
// field names we've seen so far in this record
|
||||
let mut seen = std::collections::HashMap::with_capacity(fields.len());
|
||||
|
||||
'outer: for loc_field in fields.iter() {
|
||||
for loc_field in fields.iter() {
|
||||
let mut field = &loc_field.value;
|
||||
|
||||
// use this inner loop to unwrap the SpaceAfter/SpaceBefore
|
||||
|
@ -1371,6 +1376,8 @@ fn can_assigned_fields<'a>(
|
|||
);
|
||||
|
||||
let label = Lowercase::from(field_name.value);
|
||||
check_record_field_suffix(env, label.suffix(), &field_type, &loc_field.region);
|
||||
|
||||
field_types.insert(label.clone(), RigidRequired(field_type));
|
||||
|
||||
break 'inner label;
|
||||
|
@ -1389,6 +1396,8 @@ fn can_assigned_fields<'a>(
|
|||
);
|
||||
|
||||
let label = Lowercase::from(field_name.value);
|
||||
check_record_field_suffix(env, label.suffix(), &field_type, &loc_field.region);
|
||||
|
||||
field_types.insert(label.clone(), RigidOptional(field_type));
|
||||
|
||||
break 'inner label;
|
||||
|
@ -1419,12 +1428,6 @@ fn can_assigned_fields<'a>(
|
|||
field = nested;
|
||||
continue 'inner;
|
||||
}
|
||||
Malformed(string) => {
|
||||
malformed(env, region, string);
|
||||
|
||||
// completely skip this element, advance to the next tag
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1443,6 +1446,23 @@ fn can_assigned_fields<'a>(
|
|||
field_types
|
||||
}
|
||||
|
||||
fn check_record_field_suffix(
|
||||
env: &mut Env,
|
||||
suffix: IdentSuffix,
|
||||
field_type: &Type,
|
||||
region: &Region,
|
||||
) {
|
||||
match (suffix, field_type) {
|
||||
(IdentSuffix::None, Type::Function(_, _, _, fx)) if **fx == Type::Effectful => env
|
||||
.problems
|
||||
.push(Problem::UnsuffixedEffectfulRecordField(*region)),
|
||||
(IdentSuffix::Bang, Type::Function(_, _, _, fx)) if **fx == Type::Pure => {
|
||||
env.problems.push(Problem::SuffixedPureRecordField(*region))
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO trim down these arguments!
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn can_assigned_tuple_elems(
|
||||
|
@ -1494,7 +1514,7 @@ fn can_tags<'a>(
|
|||
// tag names we've seen so far in this tag union
|
||||
let mut seen = std::collections::HashMap::with_capacity(tags.len());
|
||||
|
||||
'outer: for loc_tag in tags.iter() {
|
||||
for loc_tag in tags.iter() {
|
||||
let mut tag = &loc_tag.value;
|
||||
|
||||
// use this inner loop to unwrap the SpaceAfter/SpaceBefore
|
||||
|
@ -1533,12 +1553,6 @@ fn can_tags<'a>(
|
|||
tag = nested;
|
||||
continue 'inner;
|
||||
}
|
||||
Tag::Malformed(string) => {
|
||||
malformed(env, region, string);
|
||||
|
||||
// completely skip this element, advance to the next tag
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ map_symbol_to_lowlevel_and_arity! {
|
|||
StrIsEmpty; STR_IS_EMPTY; 1,
|
||||
StrStartsWith; STR_STARTS_WITH; 2,
|
||||
StrEndsWith; STR_ENDS_WITH; 2,
|
||||
StrSplit; STR_SPLIT; 2,
|
||||
StrSplitOn; STR_SPLIT_ON; 2,
|
||||
StrCountUtf8Bytes; STR_COUNT_UTF8_BYTES; 1,
|
||||
StrFromUtf8; STR_FROM_UTF8_LOWLEVEL; 1,
|
||||
StrToUtf8; STR_TO_UTF8; 1,
|
||||
|
@ -418,6 +418,7 @@ fn defn(
|
|||
expr_var: var_store.fresh(),
|
||||
pattern_vars: SendMap::default(),
|
||||
annotation: None,
|
||||
kind: crate::def::DefKind::Let,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -446,6 +447,8 @@ fn defn_help(
|
|||
function_type: var_store.fresh(),
|
||||
closure_type: var_store.fresh(),
|
||||
return_type: ret_var,
|
||||
fx_type: Variable::PURE,
|
||||
early_returns: vec![],
|
||||
name: fn_name,
|
||||
captured_symbols: Vec::new(),
|
||||
recursive: Recursive::NotRecursive,
|
||||
|
@ -546,6 +549,7 @@ fn to_num_checked(symbol: Symbol, var_store: &mut VarStore, lowlevel: LowLevel)
|
|||
expr_var: record_var,
|
||||
pattern_vars: SendMap::default(),
|
||||
annotation: None,
|
||||
kind: crate::def::DefKind::Let,
|
||||
};
|
||||
|
||||
let body = LetNonRec(Box::new(def), Box::new(no_region(cont)));
|
||||
|
|
|
@ -5,12 +5,13 @@ use std::sync::Arc;
|
|||
use crate::abilities::SpecializationId;
|
||||
use crate::exhaustive::{ExhaustiveContext, SketchedRows};
|
||||
use crate::expected::{Expected, PExpected};
|
||||
use roc_collections::soa::{EitherIndex, Index, Slice};
|
||||
use roc_module::ident::TagName;
|
||||
use roc_collections::soa::{index_push_new, slice_extend_new};
|
||||
use roc_module::ident::{IdentSuffix, TagName};
|
||||
use roc_module::symbol::{ModuleId, Symbol};
|
||||
use roc_region::all::{Loc, Region};
|
||||
use roc_types::subs::{ExhaustiveMark, IllegalCycleMark, Variable};
|
||||
use roc_types::types::{Category, PatternCategory, TypeTag, Types};
|
||||
use soa::{EitherIndex, Index, Slice};
|
||||
|
||||
pub struct Constraints {
|
||||
pub constraints: Vec<Constraint>,
|
||||
|
@ -28,6 +29,8 @@ pub struct Constraints {
|
|||
pub eq: Vec<Eq>,
|
||||
pub pattern_eq: Vec<PatternEq>,
|
||||
pub cycles: Vec<Cycle>,
|
||||
pub fx_call_constraints: Vec<FxCallConstraint>,
|
||||
pub fx_suffix_constraints: Vec<FxSuffixConstraint>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Constraints {
|
||||
|
@ -49,6 +52,8 @@ impl std::fmt::Debug for Constraints {
|
|||
.field("eq", &self.eq)
|
||||
.field("pattern_eq", &self.pattern_eq)
|
||||
.field("cycles", &self.cycles)
|
||||
.field("fx_call_constraints", &self.fx_call_constraints)
|
||||
.field("fx_suffix_constraints", &self.fx_suffix_constraints)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
@ -80,6 +85,8 @@ impl Constraints {
|
|||
let eq = Vec::new();
|
||||
let pattern_eq = Vec::new();
|
||||
let cycles = Vec::new();
|
||||
let fx_call_constraints = Vec::with_capacity(16);
|
||||
let fx_suffix_constraints = Vec::new();
|
||||
|
||||
categories.extend([
|
||||
Category::Record,
|
||||
|
@ -96,6 +103,7 @@ impl Constraints {
|
|||
Category::List,
|
||||
Category::Str,
|
||||
Category::Character,
|
||||
Category::Return,
|
||||
]);
|
||||
|
||||
pattern_categories.extend([
|
||||
|
@ -128,6 +136,8 @@ impl Constraints {
|
|||
eq,
|
||||
pattern_eq,
|
||||
cycles,
|
||||
fx_call_constraints,
|
||||
fx_suffix_constraints,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,6 +159,7 @@ impl Constraints {
|
|||
pub const CATEGORY_LIST: Index<Category> = Index::new(11);
|
||||
pub const CATEGORY_STR: Index<Category> = Index::new(12);
|
||||
pub const CATEGORY_CHARACTER: Index<Category> = Index::new(13);
|
||||
pub const CATEGORY_RETURN: Index<Category> = Index::new(14);
|
||||
|
||||
pub const PCATEGORY_RECORD: Index<PatternCategory> = Index::new(0);
|
||||
pub const PCATEGORY_EMPTYRECORD: Index<PatternCategory> = Index::new(1);
|
||||
|
@ -205,11 +216,11 @@ impl Constraints {
|
|||
}
|
||||
|
||||
pub fn push_expected_type(&mut self, expected: Expected<TypeOrVar>) -> ExpectedTypeIndex {
|
||||
Index::push_new(&mut self.expectations, expected)
|
||||
index_push_new(&mut self.expectations, expected)
|
||||
}
|
||||
|
||||
pub fn push_pat_expected_type(&mut self, expected: PExpected<TypeOrVar>) -> PExpectedTypeIndex {
|
||||
Index::push_new(&mut self.pattern_expectations, expected)
|
||||
index_push_new(&mut self.pattern_expectations, expected)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -229,7 +240,7 @@ impl Constraints {
|
|||
Category::List => Self::CATEGORY_LIST,
|
||||
Category::Str => Self::CATEGORY_STR,
|
||||
Category::Character => Self::CATEGORY_CHARACTER,
|
||||
other => Index::push_new(&mut self.categories, other),
|
||||
other => index_push_new(&mut self.categories, other),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,7 +258,7 @@ impl Constraints {
|
|||
PatternCategory::Int => Self::PCATEGORY_INT,
|
||||
PatternCategory::Float => Self::PCATEGORY_FLOAT,
|
||||
PatternCategory::Character => Self::PCATEGORY_CHARACTER,
|
||||
other => Index::push_new(&mut self.pattern_categories, other),
|
||||
other => index_push_new(&mut self.pattern_categories, other),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,7 +331,7 @@ impl Constraints {
|
|||
category: PatternCategory,
|
||||
region: Region,
|
||||
) -> Constraint {
|
||||
let category_index = Index::push_new(&mut self.pattern_categories, category);
|
||||
let category_index = index_push_new(&mut self.pattern_categories, category);
|
||||
|
||||
Constraint::PatternPresence(type_index, expected_index, category_index, region)
|
||||
}
|
||||
|
@ -337,7 +348,7 @@ impl Constraints {
|
|||
category: PatternCategory,
|
||||
region: Region,
|
||||
) -> Constraint {
|
||||
let category_index = Index::push_new(&mut self.pattern_categories, category);
|
||||
let category_index = index_push_new(&mut self.pattern_categories, category);
|
||||
|
||||
let includes_tag = IncludesTag {
|
||||
type_index,
|
||||
|
@ -347,7 +358,7 @@ impl Constraints {
|
|||
region,
|
||||
};
|
||||
|
||||
let includes_tag_index = Index::push_new(&mut self.includes_tags, includes_tag);
|
||||
let includes_tag_index = index_push_new(&mut self.includes_tags, includes_tag);
|
||||
|
||||
Constraint::IncludesTag(includes_tag_index)
|
||||
}
|
||||
|
@ -571,6 +582,59 @@ impl Constraints {
|
|||
Constraint::Lookup(symbol, expected_index, region)
|
||||
}
|
||||
|
||||
pub fn fx_call(
|
||||
&mut self,
|
||||
call_fx_var: Variable,
|
||||
call_kind: FxCallKind,
|
||||
call_region: Region,
|
||||
expectation: Option<FxExpectation>,
|
||||
) -> Constraint {
|
||||
let constraint = FxCallConstraint {
|
||||
call_fx_var,
|
||||
call_kind,
|
||||
call_region,
|
||||
expectation,
|
||||
};
|
||||
|
||||
let constraint_index = index_push_new(&mut self.fx_call_constraints, constraint);
|
||||
|
||||
Constraint::FxCall(constraint_index)
|
||||
}
|
||||
|
||||
pub fn fx_pattern_suffix(
|
||||
&mut self,
|
||||
symbol: Symbol,
|
||||
type_index: TypeOrVar,
|
||||
region: Region,
|
||||
) -> Constraint {
|
||||
let constraint = FxSuffixConstraint {
|
||||
kind: FxSuffixKind::Pattern(symbol),
|
||||
type_index,
|
||||
region,
|
||||
};
|
||||
|
||||
let constraint_index = index_push_new(&mut self.fx_suffix_constraints, constraint);
|
||||
|
||||
Constraint::FxSuffix(constraint_index)
|
||||
}
|
||||
|
||||
pub fn fx_record_field_unsuffixed(&mut self, variable: Variable, region: Region) -> Constraint {
|
||||
let type_index = Self::push_type_variable(variable);
|
||||
let constraint = FxSuffixConstraint {
|
||||
kind: FxSuffixKind::UnsuffixedRecordField,
|
||||
type_index,
|
||||
region,
|
||||
};
|
||||
|
||||
let constraint_index = index_push_new(&mut self.fx_suffix_constraints, constraint);
|
||||
|
||||
Constraint::FxSuffix(constraint_index)
|
||||
}
|
||||
|
||||
pub fn flex_to_pure(&mut self, fx_var: Variable) -> Constraint {
|
||||
Constraint::FlexToPure(fx_var)
|
||||
}
|
||||
|
||||
pub fn contains_save_the_environment(&self, constraint: &Constraint) -> bool {
|
||||
match constraint {
|
||||
Constraint::SaveTheEnvironment => true,
|
||||
|
@ -595,6 +659,10 @@ impl Constraints {
|
|||
| Constraint::Store(..)
|
||||
| Constraint::Lookup(..)
|
||||
| Constraint::Pattern(..)
|
||||
| Constraint::ExpectEffectful(..)
|
||||
| Constraint::FxCall(_)
|
||||
| Constraint::FxSuffix(_)
|
||||
| Constraint::FlexToPure(_)
|
||||
| Constraint::True
|
||||
| Constraint::IsOpenType(_)
|
||||
| Constraint::IncludesTag(_)
|
||||
|
@ -614,7 +682,7 @@ impl Constraints {
|
|||
filename: &'static str,
|
||||
line_number: u32,
|
||||
) -> Constraint {
|
||||
let string_index = Index::push_new(&mut self.strings, filename);
|
||||
let string_index = index_push_new(&mut self.strings, filename);
|
||||
|
||||
Constraint::Store(type_index, variable, string_index, line_number)
|
||||
}
|
||||
|
@ -632,19 +700,19 @@ impl Constraints {
|
|||
exhaustive: ExhaustiveMark,
|
||||
) -> Constraint {
|
||||
let real_var = Self::push_type_variable(real_var);
|
||||
let sketched_rows = Index::push_new(&mut self.sketched_rows, sketched_rows);
|
||||
let sketched_rows = index_push_new(&mut self.sketched_rows, sketched_rows);
|
||||
|
||||
let equality = match category_and_expectation {
|
||||
Ok((category, expected)) => {
|
||||
let category = Index::push_new(&mut self.categories, category);
|
||||
let category = index_push_new(&mut self.categories, category);
|
||||
let equality = Eq(real_var, expected, category, real_region);
|
||||
let equality = Index::push_new(&mut self.eq, equality);
|
||||
let equality = index_push_new(&mut self.eq, equality);
|
||||
Ok(equality)
|
||||
}
|
||||
Err((category, expected)) => {
|
||||
let category = Index::push_new(&mut self.pattern_categories, category);
|
||||
let category = index_push_new(&mut self.pattern_categories, category);
|
||||
let equality = PatternEq(real_var, expected, category, real_region);
|
||||
let equality = Index::push_new(&mut self.pattern_eq, equality);
|
||||
let equality = index_push_new(&mut self.pattern_eq, equality);
|
||||
Err(equality)
|
||||
}
|
||||
};
|
||||
|
@ -662,18 +730,18 @@ impl Constraints {
|
|||
I: IntoIterator<Item = (Symbol, Region)>,
|
||||
I1: IntoIterator<Item = Region>,
|
||||
{
|
||||
let def_names = Slice::extend_new(&mut self.loc_symbols, loc_symbols);
|
||||
let def_names = slice_extend_new(&mut self.loc_symbols, loc_symbols);
|
||||
|
||||
// we add a dummy symbol to these regions, so we can store the data in the loc_symbols vec
|
||||
let it = expr_regions.into_iter().map(|r| (Symbol::ATTR_ATTR, r));
|
||||
let expr_regions = Slice::extend_new(&mut self.loc_symbols, it);
|
||||
let expr_regions = slice_extend_new(&mut self.loc_symbols, it);
|
||||
let expr_regions = Slice::new(expr_regions.start() as _, expr_regions.len() as _);
|
||||
|
||||
let cycle = Cycle {
|
||||
def_names,
|
||||
expr_regions,
|
||||
};
|
||||
let cycle_index = Index::push_new(&mut self.cycles, cycle);
|
||||
let cycle_index = index_push_new(&mut self.cycles, cycle);
|
||||
|
||||
Constraint::CheckCycle(cycle_index, cycle_mark)
|
||||
}
|
||||
|
@ -767,6 +835,14 @@ pub enum Constraint {
|
|||
Index<PatternCategory>,
|
||||
Region,
|
||||
),
|
||||
/// Check call fx against enclosing function fx
|
||||
FxCall(Index<FxCallConstraint>),
|
||||
/// Require idents to be accurately suffixed
|
||||
FxSuffix(Index<FxSuffixConstraint>),
|
||||
/// Set an fx var as pure if flex (no effectful functions were called)
|
||||
FlexToPure(Variable),
|
||||
/// Expect statement or ignored def to be effectful
|
||||
ExpectEffectful(Variable, ExpectEffectfulReason, Region),
|
||||
/// Used for things that always unify, e.g. blanks and runtime errors
|
||||
True,
|
||||
SaveTheEnvironment,
|
||||
|
@ -839,6 +915,56 @@ pub struct Cycle {
|
|||
pub expr_regions: Slice<Region>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FxCallConstraint {
|
||||
pub call_fx_var: Variable,
|
||||
pub call_kind: FxCallKind,
|
||||
pub call_region: Region,
|
||||
pub expectation: Option<FxExpectation>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct FxExpectation {
|
||||
pub fx_var: Variable,
|
||||
pub ann_region: Option<Region>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum FxCallKind {
|
||||
Call(Option<Symbol>),
|
||||
Stmt,
|
||||
Ignored,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct FxSuffixConstraint {
|
||||
pub type_index: TypeOrVar,
|
||||
pub kind: FxSuffixKind,
|
||||
pub region: Region,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum FxSuffixKind {
|
||||
Let(Symbol),
|
||||
Pattern(Symbol),
|
||||
UnsuffixedRecordField,
|
||||
}
|
||||
|
||||
impl FxSuffixKind {
|
||||
pub fn suffix(&self) -> IdentSuffix {
|
||||
match self {
|
||||
Self::Let(symbol) | Self::Pattern(symbol) => symbol.suffix(),
|
||||
Self::UnsuffixedRecordField => IdentSuffix::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum ExpectEffectfulReason {
|
||||
Stmt,
|
||||
Ignored,
|
||||
}
|
||||
|
||||
/// Custom impl to limit vertical space used by the debug output
|
||||
impl std::fmt::Debug for Constraint {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
|
@ -855,6 +981,18 @@ impl std::fmt::Debug for Constraint {
|
|||
Self::Pattern(arg0, arg1, arg2, arg3) => {
|
||||
write!(f, "Pattern({arg0:?}, {arg1:?}, {arg2:?}, {arg3:?})")
|
||||
}
|
||||
Self::FxCall(arg0) => {
|
||||
write!(f, "FxCall({arg0:?})")
|
||||
}
|
||||
Self::FxSuffix(arg0) => {
|
||||
write!(f, "FxSuffix({arg0:?})")
|
||||
}
|
||||
Self::ExpectEffectful(arg0, arg1, arg2) => {
|
||||
write!(f, "EffectfulStmt({arg0:?}, {arg1:?}, {arg2:?})")
|
||||
}
|
||||
Self::FlexToPure(arg0) => {
|
||||
write!(f, "FlexToPure({arg0:?})")
|
||||
}
|
||||
Self::True => write!(f, "True"),
|
||||
Self::SaveTheEnvironment => write!(f, "SaveTheEnvironment"),
|
||||
Self::Let(arg0, arg1) => f.debug_tuple("Let").field(arg0).field(arg1).finish(),
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use crate::{
|
||||
def::Def,
|
||||
def::{Def, DefKind},
|
||||
expr::{
|
||||
ClosureData, Expr, Field, OpaqueWrapFunctionData, StructAccessorData, WhenBranchPattern,
|
||||
},
|
||||
pattern::{DestructType, ListPatterns, Pattern, RecordDestruct, TupleDestruct},
|
||||
};
|
||||
use roc_collections::soa::{index_push_new, slice_extend_new};
|
||||
use roc_module::{
|
||||
ident::{Lowercase, TagName},
|
||||
symbol::Symbol,
|
||||
|
@ -12,7 +13,7 @@ use roc_module::{
|
|||
use roc_types::{
|
||||
subs::{
|
||||
self, AliasVariables, Descriptor, GetSubsSlice, OptVariable, RecordFields, Subs, SubsIndex,
|
||||
SubsSlice, TupleElems, UnionLambdas, UnionTags, Variable, VariableSubsSlice,
|
||||
SubsSlice, TupleElems, UnionLambdas, UnionTags, Variable,
|
||||
},
|
||||
types::{RecordField, Uls},
|
||||
};
|
||||
|
@ -155,12 +156,12 @@ impl<'a> CopyEnv for AcrossSubs<'a> {
|
|||
|
||||
#[inline(always)]
|
||||
fn clone_name(&mut self, name: SubsIndex<Lowercase>) -> SubsIndex<Lowercase> {
|
||||
SubsIndex::push_new(&mut self.target.field_names, self.source[name].clone())
|
||||
index_push_new(&mut self.target.field_names, self.source[name].clone())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn clone_field_names(&mut self, field_names: SubsSlice<Lowercase>) -> SubsSlice<Lowercase> {
|
||||
SubsSlice::extend_new(
|
||||
slice_extend_new(
|
||||
&mut self.target.field_names,
|
||||
self.source.get_subs_slice(field_names).iter().cloned(),
|
||||
)
|
||||
|
@ -171,7 +172,7 @@ impl<'a> CopyEnv for AcrossSubs<'a> {
|
|||
&mut self,
|
||||
tuple_elem_indices: SubsSlice<usize>,
|
||||
) -> SubsSlice<usize> {
|
||||
SubsSlice::extend_new(
|
||||
slice_extend_new(
|
||||
&mut self.target.tuple_elem_indices,
|
||||
self.source
|
||||
.get_subs_slice(tuple_elem_indices)
|
||||
|
@ -182,7 +183,7 @@ impl<'a> CopyEnv for AcrossSubs<'a> {
|
|||
|
||||
#[inline(always)]
|
||||
fn clone_tag_names(&mut self, tag_names: SubsSlice<TagName>) -> SubsSlice<TagName> {
|
||||
SubsSlice::extend_new(
|
||||
slice_extend_new(
|
||||
&mut self.target.tag_names,
|
||||
self.source.get_subs_slice(tag_names).iter().cloned(),
|
||||
)
|
||||
|
@ -190,7 +191,7 @@ impl<'a> CopyEnv for AcrossSubs<'a> {
|
|||
|
||||
#[inline(always)]
|
||||
fn clone_lambda_names(&mut self, lambda_names: SubsSlice<Symbol>) -> SubsSlice<Symbol> {
|
||||
SubsSlice::extend_new(
|
||||
slice_extend_new(
|
||||
&mut self.target.symbol_names,
|
||||
self.source.get_subs_slice(lambda_names).iter().cloned(),
|
||||
)
|
||||
|
@ -201,7 +202,7 @@ impl<'a> CopyEnv for AcrossSubs<'a> {
|
|||
&mut self,
|
||||
record_fields: SubsSlice<RecordField<()>>,
|
||||
) -> SubsSlice<RecordField<()>> {
|
||||
SubsSlice::extend_new(
|
||||
slice_extend_new(
|
||||
&mut self.target.record_fields,
|
||||
self.source.get_subs_slice(record_fields).iter().copied(),
|
||||
)
|
||||
|
@ -377,6 +378,7 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
|
|||
expr_var,
|
||||
pattern_vars,
|
||||
annotation,
|
||||
kind,
|
||||
}| Def {
|
||||
loc_pattern: loc_pattern.map(|p| deep_copy_pattern_help(env, copied, p)),
|
||||
loc_expr: loc_expr.map(|e| go_help!(e)),
|
||||
|
@ -385,6 +387,11 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
|
|||
// Annotation should only be used in constraining, don't clone before
|
||||
// constraining :)
|
||||
annotation: annotation.clone(),
|
||||
kind: match kind {
|
||||
DefKind::Let => DefKind::Let,
|
||||
DefKind::Stmt(v) => DefKind::Stmt(sub!(*v)),
|
||||
DefKind::Ignored(v) => DefKind::Ignored(sub!(*v)),
|
||||
},
|
||||
},
|
||||
)
|
||||
.collect(),
|
||||
|
@ -398,6 +405,7 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
|
|||
expr_var,
|
||||
pattern_vars,
|
||||
annotation,
|
||||
kind,
|
||||
} = &**def;
|
||||
let def = Def {
|
||||
loc_pattern: loc_pattern.map(|p| deep_copy_pattern_help(env, copied, p)),
|
||||
|
@ -407,18 +415,20 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
|
|||
// Annotation should only be used in constraining, don't clone before
|
||||
// constraining :)
|
||||
annotation: annotation.clone(),
|
||||
kind: *kind,
|
||||
};
|
||||
LetNonRec(Box::new(def), Box::new(body.map(|e| go_help!(e))))
|
||||
}
|
||||
|
||||
Call(f, args, called_via) => {
|
||||
let (fn_var, fn_expr, clos_var, ret_var) = &**f;
|
||||
let (fn_var, fn_expr, clos_var, ret_var, fx_var) = &**f;
|
||||
Call(
|
||||
Box::new((
|
||||
sub!(*fn_var),
|
||||
fn_expr.map(|e| go_help!(e)),
|
||||
sub!(*clos_var),
|
||||
sub!(*ret_var),
|
||||
sub!(*fx_var),
|
||||
)),
|
||||
args.iter()
|
||||
.map(|(var, expr)| (sub!(*var), expr.map(|e| go_help!(e))))
|
||||
|
@ -455,6 +465,8 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
|
|||
function_type,
|
||||
closure_type,
|
||||
return_type,
|
||||
fx_type,
|
||||
early_returns,
|
||||
name,
|
||||
captured_symbols,
|
||||
recursive,
|
||||
|
@ -464,6 +476,11 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
|
|||
function_type: sub!(*function_type),
|
||||
closure_type: sub!(*closure_type),
|
||||
return_type: sub!(*return_type),
|
||||
fx_type: sub!(*fx_type),
|
||||
early_returns: early_returns
|
||||
.iter()
|
||||
.map(|(var, region)| (sub!(*var), *region))
|
||||
.collect(),
|
||||
name: *name,
|
||||
captured_symbols: captured_symbols
|
||||
.iter()
|
||||
|
@ -677,14 +694,12 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
|
|||
lookups_in_cond: lookups_in_cond.to_vec(),
|
||||
},
|
||||
|
||||
ExpectFx {
|
||||
loc_condition,
|
||||
loc_continuation,
|
||||
lookups_in_cond,
|
||||
} => ExpectFx {
|
||||
loc_condition: Box::new(loc_condition.map(|e| go_help!(e))),
|
||||
loc_continuation: Box::new(loc_continuation.map(|e| go_help!(e))),
|
||||
lookups_in_cond: lookups_in_cond.to_vec(),
|
||||
Return {
|
||||
return_value,
|
||||
return_var,
|
||||
} => Return {
|
||||
return_value: Box::new(return_value.map(|e| go_help!(e))),
|
||||
return_var: sub!(*return_var),
|
||||
},
|
||||
|
||||
Dbg {
|
||||
|
@ -919,8 +934,7 @@ fn deep_copy_type_vars<C: CopyEnv>(
|
|||
|
||||
macro_rules! clone_var_slice {
|
||||
($slice:expr) => {{
|
||||
let new_arguments =
|
||||
VariableSubsSlice::reserve_into_subs(env.target(), $slice.len());
|
||||
let new_arguments = env.target().reserve_into_vars($slice.len());
|
||||
for (target_index, var_index) in (new_arguments.indices()).zip($slice) {
|
||||
let var = env.source()[var_index];
|
||||
let copy_var = env.get_copy(var).into_variable().unwrap_or(var);
|
||||
|
@ -961,7 +975,7 @@ fn deep_copy_type_vars<C: CopyEnv>(
|
|||
|
||||
// Everything else is a mechanical descent.
|
||||
Structure(flat_type) => match flat_type {
|
||||
EmptyRecord | EmptyTuple | EmptyTagUnion => Structure(flat_type),
|
||||
EmptyRecord | EmptyTagUnion | EffectfulFunc => Structure(flat_type),
|
||||
Apply(symbol, arguments) => {
|
||||
descend_slice!(arguments);
|
||||
|
||||
|
@ -970,15 +984,21 @@ fn deep_copy_type_vars<C: CopyEnv>(
|
|||
Structure(Apply(symbol, new_arguments))
|
||||
})
|
||||
}
|
||||
Func(arguments, closure_var, ret_var) => {
|
||||
Func(arguments, closure_var, ret_var, fx_var) => {
|
||||
descend_slice!(arguments);
|
||||
|
||||
let new_closure_var = descend_var!(closure_var);
|
||||
let new_ret_var = descend_var!(ret_var);
|
||||
let new_fx_var = descend_var!(fx_var);
|
||||
|
||||
perform_clone!({
|
||||
let new_arguments = clone_var_slice!(arguments);
|
||||
Structure(Func(new_arguments, new_closure_var, new_ret_var))
|
||||
Structure(Func(
|
||||
new_arguments,
|
||||
new_closure_var,
|
||||
new_ret_var,
|
||||
new_fx_var,
|
||||
))
|
||||
})
|
||||
}
|
||||
Record(fields, ext_var) => {
|
||||
|
@ -994,9 +1014,9 @@ fn deep_copy_type_vars<C: CopyEnv>(
|
|||
let new_fields = {
|
||||
RecordFields {
|
||||
length: fields.length,
|
||||
field_names_start: new_field_names.start,
|
||||
variables_start: new_variables.start,
|
||||
field_types_start: new_record_fields.start,
|
||||
field_names_start: new_field_names.start(),
|
||||
variables_start: new_variables.start(),
|
||||
field_types_start: new_record_fields.start(),
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1015,8 +1035,8 @@ fn deep_copy_type_vars<C: CopyEnv>(
|
|||
let new_elems = {
|
||||
TupleElems {
|
||||
length: elems.length,
|
||||
variables_start: new_variables.start,
|
||||
elem_index_start: new_elem_indices.start,
|
||||
variables_start: new_variables.start(),
|
||||
elem_index_start: new_elem_indices.start(),
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1032,8 +1052,7 @@ fn deep_copy_type_vars<C: CopyEnv>(
|
|||
}
|
||||
|
||||
perform_clone!({
|
||||
let new_variable_slices =
|
||||
SubsSlice::reserve_variable_slices(env.target(), tags.len());
|
||||
let new_variable_slices = env.target().reserve_variable_slices(tags.len());
|
||||
let it = (new_variable_slices.indices()).zip(tags.variables());
|
||||
for (target_index, index) in it {
|
||||
let slice = env.source()[index];
|
||||
|
@ -1058,8 +1077,7 @@ fn deep_copy_type_vars<C: CopyEnv>(
|
|||
}
|
||||
|
||||
perform_clone!({
|
||||
let new_variable_slices =
|
||||
SubsSlice::reserve_variable_slices(env.target(), tags.len());
|
||||
let new_variable_slices = env.target().reserve_variable_slices(tags.len());
|
||||
let it = (new_variable_slices.indices()).zip(tags.variables());
|
||||
for (target_index, index) in it {
|
||||
let slice = env.source()[index];
|
||||
|
@ -1109,7 +1127,7 @@ fn deep_copy_type_vars<C: CopyEnv>(
|
|||
perform_clone!({
|
||||
let new_variables = clone_var_slice!(arguments.all_variables());
|
||||
let new_arguments = AliasVariables {
|
||||
variables_start: new_variables.start,
|
||||
variables_start: new_variables.start(),
|
||||
..arguments
|
||||
};
|
||||
|
||||
|
@ -1135,8 +1153,7 @@ fn deep_copy_type_vars<C: CopyEnv>(
|
|||
let new_ambient_function = descend_var!(ambient_function);
|
||||
|
||||
perform_clone!({
|
||||
let new_variable_slices =
|
||||
SubsSlice::reserve_variable_slices(env.target(), solved.len());
|
||||
let new_variable_slices = env.target().reserve_variable_slices(solved.len());
|
||||
let it = (new_variable_slices.indices()).zip(solved.variables());
|
||||
for (target_index, index) in it {
|
||||
let slice = env.source()[index];
|
||||
|
@ -1150,8 +1167,7 @@ fn deep_copy_type_vars<C: CopyEnv>(
|
|||
let new_solved =
|
||||
UnionLambdas::from_slices(new_solved_labels, new_variable_slices);
|
||||
|
||||
let new_unspecialized =
|
||||
SubsSlice::reserve_uls_slice(env.target(), unspecialized.len());
|
||||
let new_unspecialized = env.target().reserve_uls_slice(unspecialized.len());
|
||||
for (target_index, uls_index) in
|
||||
(new_unspecialized.into_iter()).zip(unspecialized.into_iter())
|
||||
{
|
||||
|
@ -1171,6 +1187,8 @@ fn deep_copy_type_vars<C: CopyEnv>(
|
|||
})
|
||||
}
|
||||
ErasedLambda => ErasedLambda,
|
||||
Pure => Pure,
|
||||
Effectful => Effectful,
|
||||
|
||||
RangedNumber(range) => {
|
||||
perform_clone!(RangedNumber(range))
|
||||
|
@ -1192,13 +1210,14 @@ mod test {
|
|||
};
|
||||
|
||||
use super::{deep_copy_expr_across_subs, deep_copy_type_vars};
|
||||
use roc_collections::soa::{index_push_new, slice_extend_new};
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::{ident::TagName, symbol::Symbol};
|
||||
use roc_region::all::Loc;
|
||||
use roc_types::{
|
||||
subs::{
|
||||
self, Content, Content::*, Descriptor, FlatType, GetSubsSlice, Mark, OptVariable, Rank,
|
||||
Subs, SubsIndex, SubsSlice, Variable,
|
||||
Subs, Variable,
|
||||
},
|
||||
types::Uls,
|
||||
};
|
||||
|
@ -1217,7 +1236,7 @@ mod test {
|
|||
fn copy_flex_var() {
|
||||
let mut subs = Subs::new();
|
||||
|
||||
let field_name = SubsIndex::push_new(&mut subs.field_names, "a".into());
|
||||
let field_name = index_push_new(&mut subs.field_names, "a".into());
|
||||
let var = new_var(&mut subs, FlexVar(Some(field_name)));
|
||||
|
||||
let mut copied = vec![];
|
||||
|
@ -1238,7 +1257,7 @@ mod test {
|
|||
fn copy_rigid_var() {
|
||||
let mut subs = Subs::new();
|
||||
|
||||
let field_name = SubsIndex::push_new(&mut subs.field_names, "a".into());
|
||||
let field_name = index_push_new(&mut subs.field_names, "a".into());
|
||||
let var = new_var(&mut subs, RigidVar(field_name));
|
||||
|
||||
let mut copied = vec![];
|
||||
|
@ -1259,8 +1278,8 @@ mod test {
|
|||
fn copy_flex_able_var() {
|
||||
let mut subs = Subs::new();
|
||||
|
||||
let field_name = SubsIndex::push_new(&mut subs.field_names, "a".into());
|
||||
let abilities = SubsSlice::extend_new(&mut subs.symbol_names, [Symbol::UNDERSCORE]);
|
||||
let field_name = index_push_new(&mut subs.field_names, "a".into());
|
||||
let abilities = slice_extend_new(&mut subs.symbol_names, [Symbol::UNDERSCORE]);
|
||||
let var = new_var(&mut subs, FlexAbleVar(Some(field_name), abilities));
|
||||
|
||||
let mut copied = vec![];
|
||||
|
@ -1282,8 +1301,8 @@ mod test {
|
|||
fn copy_rigid_able_var() {
|
||||
let mut subs = Subs::new();
|
||||
|
||||
let field_name = SubsIndex::push_new(&mut subs.field_names, "a".into());
|
||||
let abilities = SubsSlice::extend_new(&mut subs.symbol_names, [Symbol::UNDERSCORE]);
|
||||
let field_name = index_push_new(&mut subs.field_names, "a".into());
|
||||
let abilities = slice_extend_new(&mut subs.symbol_names, [Symbol::UNDERSCORE]);
|
||||
let var = new_var(&mut subs, RigidAbleVar(field_name, abilities));
|
||||
|
||||
let mut copied = vec![];
|
||||
|
@ -1304,8 +1323,8 @@ mod test {
|
|||
fn copy_deep_expr() {
|
||||
let mut subs = Subs::new();
|
||||
|
||||
let a = SubsIndex::push_new(&mut subs.field_names, "a".into());
|
||||
let b = SubsIndex::push_new(&mut subs.field_names, "b".into());
|
||||
let a = index_push_new(&mut subs.field_names, "a".into());
|
||||
let b = index_push_new(&mut subs.field_names, "b".into());
|
||||
let var1 = new_var(&mut subs, FlexVar(Some(a)));
|
||||
let var2 = new_var(&mut subs, FlexVar(Some(b)));
|
||||
|
||||
|
@ -1390,8 +1409,8 @@ mod test {
|
|||
let mut source = Subs::new();
|
||||
let mut target = Subs::new();
|
||||
|
||||
let a = SubsIndex::push_new(&mut source.field_names, "a".into());
|
||||
let b = SubsIndex::push_new(&mut source.field_names, "b".into());
|
||||
let a = index_push_new(&mut source.field_names, "a".into());
|
||||
let b = index_push_new(&mut source.field_names, "b".into());
|
||||
let var1 = new_var(&mut source, FlexVar(Some(a)));
|
||||
let var2 = new_var(&mut source, FlexVar(Some(b)));
|
||||
|
||||
|
@ -1472,7 +1491,7 @@ mod test {
|
|||
let mut target = Subs::new();
|
||||
|
||||
let a = new_var(&mut source, FlexVar(None));
|
||||
let uls = SubsSlice::extend_new(
|
||||
let uls = slice_extend_new(
|
||||
&mut source.unspecialized_lambda_sets,
|
||||
vec![Uls(a, Symbol::UNDERSCORE, 3)],
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Pretty-prints the canonical AST back to check our work - do things look reasonable?
|
||||
|
||||
use crate::def::Def;
|
||||
use crate::def::{Def, DefKind};
|
||||
use crate::expr::Expr::{self, *};
|
||||
use crate::expr::{
|
||||
ClosureData, DeclarationTag, Declarations, FunctionDef, OpaqueWrapFunctionData,
|
||||
|
@ -62,7 +62,6 @@ fn print_declarations_help<'a>(
|
|||
toplevel_function(c, f, symbol, function_def, &body.value)
|
||||
}
|
||||
DeclarationTag::Expectation => todo!(),
|
||||
DeclarationTag::ExpectationFx => todo!(),
|
||||
DeclarationTag::Destructure(_) => todo!(),
|
||||
DeclarationTag::MutualRecursion { .. } => {
|
||||
// the defs will be printed next
|
||||
|
@ -107,9 +106,14 @@ fn def<'a>(c: &Ctx, f: &'a Arena<'a>, d: &'a Def) -> DocBuilder<'a, Arena<'a>> {
|
|||
expr_var: _,
|
||||
pattern_vars: _,
|
||||
annotation: _,
|
||||
kind,
|
||||
} = d;
|
||||
|
||||
def_help(c, f, &loc_pattern.value, &loc_expr.value)
|
||||
match kind {
|
||||
DefKind::Let => def_help(c, f, &loc_pattern.value, &loc_expr.value),
|
||||
DefKind::Ignored(_) => def_help(c, f, &loc_pattern.value, &loc_expr.value),
|
||||
DefKind::Stmt(_) => expr(c, EPrec::Free, f, &loc_expr.value),
|
||||
}
|
||||
}
|
||||
|
||||
fn def_symbol_help<'a>(
|
||||
|
@ -267,7 +271,7 @@ fn expr<'a>(c: &Ctx, p: EPrec, f: &'a Arena<'a>, e: &'a Expr) -> DocBuilder<'a,
|
|||
.append(expr(c, Free, f, &body.value))
|
||||
.group(),
|
||||
Call(fun, args, _) => {
|
||||
let (_, fun, _, _) = &**fun;
|
||||
let (_, fun, _, _, _) = &**fun;
|
||||
maybe_paren!(
|
||||
Free,
|
||||
p,
|
||||
|
@ -448,7 +452,7 @@ fn expr<'a>(c: &Ctx, p: EPrec, f: &'a Arena<'a>, e: &'a Expr) -> DocBuilder<'a,
|
|||
),
|
||||
Dbg { .. } => todo!(),
|
||||
Expect { .. } => todo!(),
|
||||
ExpectFx { .. } => todo!(),
|
||||
Return { .. } => todo!(),
|
||||
TypedHole(_) => todo!(),
|
||||
RuntimeError(_) => todo!(),
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ use crate::annotation::IntroducedVariables;
|
|||
use crate::annotation::OwnedNamedOrAble;
|
||||
use crate::derive;
|
||||
use crate::env::Env;
|
||||
use crate::env::FxMode;
|
||||
use crate::expr::canonicalize_record;
|
||||
use crate::expr::get_lookup_symbols;
|
||||
use crate::expr::AnnotatedMark;
|
||||
|
@ -69,6 +70,7 @@ pub struct Def {
|
|||
pub expr_var: Variable,
|
||||
pub pattern_vars: SendMap<Symbol, Variable>,
|
||||
pub annotation: Option<Annotation>,
|
||||
pub kind: DefKind,
|
||||
}
|
||||
|
||||
impl Def {
|
||||
|
@ -89,6 +91,38 @@ impl Def {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum DefKind {
|
||||
/// A def that introduces identifiers
|
||||
Let,
|
||||
/// A standalone statement with an fx variable
|
||||
Stmt(Variable),
|
||||
/// Ignored result, must be effectful
|
||||
Ignored(Variable),
|
||||
}
|
||||
|
||||
impl DefKind {
|
||||
pub fn map_var<F: Fn(Variable) -> Variable>(self, f: F) -> Self {
|
||||
match self {
|
||||
DefKind::Let => DefKind::Let,
|
||||
DefKind::Stmt(v) => DefKind::Stmt(f(v)),
|
||||
DefKind::Ignored(v) => DefKind::Ignored(f(v)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_pattern(var_store: &mut VarStore, pattern: &Loc<Pattern>) -> Self {
|
||||
if BindingsFromPattern::new(pattern)
|
||||
.peekable()
|
||||
.peek()
|
||||
.is_none()
|
||||
{
|
||||
DefKind::Ignored(var_store.fresh())
|
||||
} else {
|
||||
DefKind::Let
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Annotation {
|
||||
pub signature: Type,
|
||||
|
@ -127,6 +161,7 @@ impl Annotation {
|
|||
arg_types,
|
||||
Box::new(Type::Variable(var_store.fresh())),
|
||||
Box::new(self.signature.clone()),
|
||||
Box::new(Type::Variable(var_store.fresh())),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -136,7 +171,6 @@ pub(crate) struct CanDefs {
|
|||
defs: Vec<Option<Def>>,
|
||||
dbgs: ExpectsOrDbgs,
|
||||
expects: ExpectsOrDbgs,
|
||||
expects_fx: ExpectsOrDbgs,
|
||||
def_ordering: DefOrdering,
|
||||
aliases: VecMap<Symbol, Alias>,
|
||||
}
|
||||
|
@ -194,22 +228,25 @@ enum PendingValueDef<'a> {
|
|||
Option<Loc<ast::TypeAnnotation<'a>>>,
|
||||
Loc<ast::StrLiteral<'a>>,
|
||||
),
|
||||
/// A standalone statement
|
||||
Stmt(&'a Loc<ast::Expr<'a>>),
|
||||
}
|
||||
|
||||
impl PendingValueDef<'_> {
|
||||
fn loc_pattern(&self) -> &Loc<Pattern> {
|
||||
fn loc_pattern(&self) -> Option<&Loc<Pattern>> {
|
||||
match self {
|
||||
PendingValueDef::AnnotationOnly(loc_pattern, _) => loc_pattern,
|
||||
PendingValueDef::Body(loc_pattern, _) => loc_pattern,
|
||||
PendingValueDef::TypedBody(_, loc_pattern, _, _) => loc_pattern,
|
||||
PendingValueDef::AnnotationOnly(loc_pattern, _) => Some(loc_pattern),
|
||||
PendingValueDef::Body(loc_pattern, _) => Some(loc_pattern),
|
||||
PendingValueDef::TypedBody(_, loc_pattern, _, _) => Some(loc_pattern),
|
||||
PendingValueDef::ImportParams {
|
||||
loc_pattern,
|
||||
symbol: _,
|
||||
variable: _,
|
||||
module_id: _,
|
||||
opt_provided: _,
|
||||
} => loc_pattern,
|
||||
PendingValueDef::IngestedFile(loc_pattern, _, _) => loc_pattern,
|
||||
} => Some(loc_pattern),
|
||||
PendingValueDef::IngestedFile(loc_pattern, _, _) => Some(loc_pattern),
|
||||
PendingValueDef::Stmt(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -305,7 +342,6 @@ pub enum Declaration {
|
|||
DeclareRec(Vec<Def>, IllegalCycleMark),
|
||||
Builtin(Def),
|
||||
Expects(ExpectsOrDbgs),
|
||||
ExpectsFx(ExpectsOrDbgs),
|
||||
/// If we know a cycle is illegal during canonicalization.
|
||||
/// Otherwise we will try to detect this during solving; see [`IllegalCycleMark`].
|
||||
InvalidCycle(Vec<CycleEntry>),
|
||||
|
@ -320,7 +356,6 @@ impl Declaration {
|
|||
InvalidCycle { .. } => 0,
|
||||
Builtin(_) => 0,
|
||||
Expects(_) => 0,
|
||||
ExpectsFx(_) => 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,7 +371,7 @@ impl Declaration {
|
|||
&cycles.first().unwrap().expr_region,
|
||||
&cycles.last().unwrap().expr_region,
|
||||
),
|
||||
Declaration::Expects(expects) | Declaration::ExpectsFx(expects) => Region::span_across(
|
||||
Declaration::Expects(expects) => Region::span_across(
|
||||
expects.regions.first().unwrap(),
|
||||
expects.regions.last().unwrap(),
|
||||
),
|
||||
|
@ -677,10 +712,6 @@ fn canonicalize_claimed_ability_impl<'a>(
|
|||
});
|
||||
Err(())
|
||||
}
|
||||
AssignedField::Malformed(_) => {
|
||||
// An error will already have been reported
|
||||
Err(())
|
||||
}
|
||||
AssignedField::SpaceBefore(_, _)
|
||||
| AssignedField::SpaceAfter(_, _)
|
||||
| AssignedField::IgnoredValue(_, _, _) => {
|
||||
|
@ -1136,7 +1167,6 @@ fn canonicalize_value_defs<'a>(
|
|||
let mut pending_value_defs = Vec::with_capacity(value_defs.len());
|
||||
let mut pending_dbgs = Vec::with_capacity(value_defs.len());
|
||||
let mut pending_expects = Vec::with_capacity(value_defs.len());
|
||||
let mut pending_expect_fx = Vec::with_capacity(value_defs.len());
|
||||
|
||||
let mut imports_introduced = Vec::with_capacity(value_defs.len());
|
||||
|
||||
|
@ -1156,9 +1186,6 @@ fn canonicalize_value_defs<'a>(
|
|||
PendingValue::Expect(pending_expect) => {
|
||||
pending_expects.push(pending_expect);
|
||||
}
|
||||
PendingValue::ExpectFx(pending_expect) => {
|
||||
pending_expect_fx.push(pending_expect);
|
||||
}
|
||||
PendingValue::ModuleImport(PendingModuleImport {
|
||||
module_id,
|
||||
region,
|
||||
|
@ -1181,19 +1208,18 @@ fn canonicalize_value_defs<'a>(
|
|||
}
|
||||
PendingValue::InvalidIngestedFile => { /* skip */ }
|
||||
PendingValue::ImportNameConflict => { /* skip */ }
|
||||
PendingValue::StmtAfterExpr => { /* skip */ }
|
||||
}
|
||||
}
|
||||
|
||||
let mut symbol_to_index: Vec<(IdentId, u32)> = Vec::with_capacity(pending_value_defs.len());
|
||||
|
||||
for (def_index, pending_def) in pending_value_defs.iter().enumerate() {
|
||||
let mut new_bindings = BindingsFromPattern::new(pending_def.loc_pattern()).peekable();
|
||||
let Some(loc_pattern) = pending_def.loc_pattern() else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if new_bindings.peek().is_none() {
|
||||
env.problem(Problem::NoIdentifiersIntroduced(
|
||||
pending_def.loc_pattern().region,
|
||||
));
|
||||
}
|
||||
let new_bindings = BindingsFromPattern::new(loc_pattern).peekable();
|
||||
|
||||
for (s, r) in new_bindings {
|
||||
// store the top-level defs, used to ensure that closures won't capture them
|
||||
|
@ -1230,6 +1256,14 @@ fn canonicalize_value_defs<'a>(
|
|||
|
||||
output = temp_output.output;
|
||||
|
||||
if let (PatternType::TopLevelDef, DefKind::Ignored(_)) =
|
||||
(pattern_type, temp_output.def.kind)
|
||||
{
|
||||
env.problems.push(Problem::NoIdentifiersIntroduced(
|
||||
temp_output.def.loc_pattern.region,
|
||||
))
|
||||
}
|
||||
|
||||
defs.push(Some(temp_output.def));
|
||||
|
||||
def_ordering.insert_symbol_references(def_id as u32, &temp_output.references)
|
||||
|
@ -1237,7 +1271,6 @@ fn canonicalize_value_defs<'a>(
|
|||
|
||||
let mut dbgs = ExpectsOrDbgs::with_capacity(pending_dbgs.len());
|
||||
let mut expects = ExpectsOrDbgs::with_capacity(pending_expects.len());
|
||||
let mut expects_fx = ExpectsOrDbgs::with_capacity(pending_expects.len());
|
||||
|
||||
for pending in pending_dbgs {
|
||||
let (loc_can_condition, can_output) = canonicalize_expr(
|
||||
|
@ -1267,25 +1300,10 @@ fn canonicalize_value_defs<'a>(
|
|||
output.union(can_output);
|
||||
}
|
||||
|
||||
for pending in pending_expect_fx {
|
||||
let (loc_can_condition, can_output) = canonicalize_expr(
|
||||
env,
|
||||
var_store,
|
||||
scope,
|
||||
pending.condition.region,
|
||||
&pending.condition.value,
|
||||
);
|
||||
|
||||
expects_fx.push(loc_can_condition, pending.preceding_comment);
|
||||
|
||||
output.union(can_output);
|
||||
}
|
||||
|
||||
let can_defs = CanDefs {
|
||||
defs,
|
||||
dbgs,
|
||||
expects,
|
||||
expects_fx,
|
||||
def_ordering,
|
||||
aliases,
|
||||
};
|
||||
|
@ -1681,7 +1699,7 @@ impl DefOrdering {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn sort_can_defs_new(
|
||||
pub(crate) fn sort_top_level_can_defs(
|
||||
env: &mut Env<'_>,
|
||||
scope: &mut Scope,
|
||||
var_store: &mut VarStore,
|
||||
|
@ -1693,7 +1711,6 @@ pub(crate) fn sort_can_defs_new(
|
|||
defs,
|
||||
dbgs: _,
|
||||
expects,
|
||||
expects_fx,
|
||||
def_ordering,
|
||||
aliases,
|
||||
} = defs;
|
||||
|
@ -1724,19 +1741,6 @@ pub(crate) fn sort_can_defs_new(
|
|||
declarations.push_expect(preceding_comment, name, Loc::at(region, condition));
|
||||
}
|
||||
|
||||
let it = expects_fx
|
||||
.conditions
|
||||
.into_iter()
|
||||
.zip(expects_fx.regions)
|
||||
.zip(expects_fx.preceding_comment);
|
||||
|
||||
for ((condition, region), preceding_comment) in it {
|
||||
// an `expect` does not have a user-defined name, but we'll need a name to call the expectation
|
||||
let name = scope.gen_unique_symbol();
|
||||
|
||||
declarations.push_expect_fx(preceding_comment, name, Loc::at(region, condition));
|
||||
}
|
||||
|
||||
for (symbol, alias) in aliases.into_iter() {
|
||||
output.aliases.insert(symbol, alias);
|
||||
}
|
||||
|
@ -1974,7 +1978,6 @@ pub(crate) fn sort_can_defs(
|
|||
mut defs,
|
||||
dbgs,
|
||||
expects,
|
||||
expects_fx,
|
||||
def_ordering,
|
||||
aliases,
|
||||
} = defs;
|
||||
|
@ -2108,10 +2111,6 @@ pub(crate) fn sort_can_defs(
|
|||
declarations.push(Declaration::Expects(expects));
|
||||
}
|
||||
|
||||
if !expects_fx.conditions.is_empty() {
|
||||
declarations.push(Declaration::ExpectsFx(expects_fx));
|
||||
}
|
||||
|
||||
(declarations, output)
|
||||
}
|
||||
|
||||
|
@ -2215,6 +2214,7 @@ fn single_can_def(
|
|||
expr_var: Variable,
|
||||
opt_loc_annotation: Option<Loc<crate::annotation::Annotation>>,
|
||||
pattern_vars: SendMap<Symbol, Variable>,
|
||||
kind: DefKind,
|
||||
) -> Def {
|
||||
let def_annotation = opt_loc_annotation.map(|loc_annotation| Annotation {
|
||||
signature: loc_annotation.value.typ,
|
||||
|
@ -2232,6 +2232,7 @@ fn single_can_def(
|
|||
},
|
||||
pattern_vars,
|
||||
annotation: def_annotation,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2354,6 +2355,8 @@ fn canonicalize_pending_value_def<'a>(
|
|||
function_type: var_store.fresh(),
|
||||
closure_type: var_store.fresh(),
|
||||
return_type: var_store.fresh(),
|
||||
fx_type: var_store.fresh(),
|
||||
early_returns: scope.early_returns.clone(),
|
||||
name: symbol,
|
||||
captured_symbols: Vec::new(),
|
||||
recursive: Recursive::NotRecursive,
|
||||
|
@ -2370,6 +2373,7 @@ fn canonicalize_pending_value_def<'a>(
|
|||
expr_var,
|
||||
Some(Loc::at(loc_ann.region, type_annotation)),
|
||||
vars_by_symbol.clone(),
|
||||
DefKind::Let,
|
||||
);
|
||||
|
||||
DefOutput {
|
||||
|
@ -2405,10 +2409,13 @@ fn canonicalize_pending_value_def<'a>(
|
|||
loc_can_pattern,
|
||||
loc_expr,
|
||||
Some(Loc::at(loc_ann.region, type_annotation)),
|
||||
DefKind::Let,
|
||||
)
|
||||
}
|
||||
Body(loc_can_pattern, loc_expr) => {
|
||||
//
|
||||
let def_kind = DefKind::from_pattern(var_store, &loc_can_pattern);
|
||||
|
||||
canonicalize_pending_body(
|
||||
env,
|
||||
output,
|
||||
|
@ -2417,6 +2424,20 @@ fn canonicalize_pending_value_def<'a>(
|
|||
loc_can_pattern,
|
||||
loc_expr,
|
||||
None,
|
||||
def_kind,
|
||||
)
|
||||
}
|
||||
Stmt(loc_expr) => {
|
||||
let fx_var = var_store.fresh();
|
||||
canonicalize_pending_body(
|
||||
env,
|
||||
output,
|
||||
scope,
|
||||
var_store,
|
||||
Loc::at(loc_expr.region, Pattern::Underscore),
|
||||
loc_expr,
|
||||
None,
|
||||
DefKind::Stmt(fx_var),
|
||||
)
|
||||
}
|
||||
ImportParams {
|
||||
|
@ -2457,6 +2478,7 @@ fn canonicalize_pending_value_def<'a>(
|
|||
var_store.fresh(),
|
||||
None,
|
||||
SendMap::default(),
|
||||
DefKind::Let,
|
||||
);
|
||||
|
||||
DefOutput {
|
||||
|
@ -2526,6 +2548,7 @@ fn canonicalize_pending_value_def<'a>(
|
|||
var_store.fresh(),
|
||||
opt_loc_can_ann,
|
||||
SendMap::default(),
|
||||
DefKind::Let,
|
||||
);
|
||||
|
||||
DefOutput {
|
||||
|
@ -2564,6 +2587,7 @@ fn canonicalize_pending_body<'a>(
|
|||
loc_expr: &'a Loc<ast::Expr>,
|
||||
|
||||
opt_loc_annotation: Option<Loc<crate::annotation::Annotation>>,
|
||||
kind: DefKind,
|
||||
) -> DefOutput {
|
||||
let mut loc_value = &loc_expr.value;
|
||||
|
||||
|
@ -2571,6 +2595,8 @@ fn canonicalize_pending_body<'a>(
|
|||
loc_value = value;
|
||||
}
|
||||
|
||||
let expr_var = var_store.fresh();
|
||||
|
||||
// We treat closure definitions `foo = \a, b -> ...` differently from other body expressions,
|
||||
// because they need more bookkeeping (for tail calls, closure captures, etc.)
|
||||
//
|
||||
|
@ -2602,9 +2628,15 @@ fn canonicalize_pending_body<'a>(
|
|||
env.tailcallable_symbol = outer_tailcallable;
|
||||
|
||||
// The closure is self tail recursive iff it tail calls itself (by defined name).
|
||||
let is_recursive = match can_output.tail_call {
|
||||
Some(tail_symbol) if tail_symbol == *defined_symbol => Recursive::TailRecursive,
|
||||
_ => Recursive::NotRecursive,
|
||||
let is_recursive = if !can_output.tail_calls.is_empty()
|
||||
&& can_output
|
||||
.tail_calls
|
||||
.iter()
|
||||
.all(|tail_symbol| tail_symbol == defined_symbol)
|
||||
{
|
||||
Recursive::TailRecursive
|
||||
} else {
|
||||
Recursive::NotRecursive
|
||||
};
|
||||
|
||||
closure_data.recursive = is_recursive;
|
||||
|
@ -2664,7 +2696,6 @@ fn canonicalize_pending_body<'a>(
|
|||
}
|
||||
};
|
||||
|
||||
let expr_var = var_store.fresh();
|
||||
let mut vars_by_symbol = SendMap::default();
|
||||
|
||||
pattern_to_vars_by_symbol(&mut vars_by_symbol, &loc_can_pattern.value, expr_var);
|
||||
|
@ -2675,6 +2706,7 @@ fn canonicalize_pending_body<'a>(
|
|||
expr_var,
|
||||
opt_loc_annotation,
|
||||
vars_by_symbol,
|
||||
kind,
|
||||
);
|
||||
|
||||
DefOutput {
|
||||
|
@ -2801,10 +2833,6 @@ fn decl_to_let(decl: Declaration, loc_ret: Loc<Expr>) -> Loc<Expr> {
|
|||
|
||||
loc_ret
|
||||
}
|
||||
Declaration::ExpectsFx(expects) => {
|
||||
// Expects should only be added to top-level decls, not to let-exprs!
|
||||
unreachable!("{:?}", &expects)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3004,11 +3032,11 @@ enum PendingValue<'a> {
|
|||
Def(PendingValueDef<'a>),
|
||||
Dbg(PendingExpectOrDbg<'a>),
|
||||
Expect(PendingExpectOrDbg<'a>),
|
||||
ExpectFx(PendingExpectOrDbg<'a>),
|
||||
ModuleImport(PendingModuleImport<'a>),
|
||||
SignatureDefMismatch,
|
||||
InvalidIngestedFile,
|
||||
ImportNameConflict,
|
||||
StmtAfterExpr,
|
||||
}
|
||||
|
||||
struct PendingExpectOrDbg<'a> {
|
||||
|
@ -3063,10 +3091,7 @@ fn to_pending_value_def<'a>(
|
|||
loc_pattern.region,
|
||||
);
|
||||
|
||||
PendingValue::Def(PendingValueDef::AnnotationOnly(
|
||||
loc_can_pattern,
|
||||
loc_ann,
|
||||
))
|
||||
PendingValue::Def(PendingValueDef::AnnotationOnly(loc_can_pattern, loc_ann))
|
||||
}
|
||||
Body(loc_pattern, loc_expr) => {
|
||||
// This takes care of checking for shadowing and adding idents to scope.
|
||||
|
@ -3146,14 +3171,6 @@ fn to_pending_value_def<'a>(
|
|||
preceding_comment: *preceding_comment,
|
||||
}),
|
||||
|
||||
ExpectFx {
|
||||
condition,
|
||||
preceding_comment,
|
||||
} => PendingValue::ExpectFx(PendingExpectOrDbg {
|
||||
condition,
|
||||
preceding_comment: *preceding_comment,
|
||||
}),
|
||||
|
||||
ModuleImport(module_import) => {
|
||||
let qualified_module_name: QualifiedModuleName = module_import.name.value.into();
|
||||
let module_name = qualified_module_name.module.clone();
|
||||
|
@ -3172,15 +3189,17 @@ fn to_pending_value_def<'a>(
|
|||
// Generate a symbol for the module params def
|
||||
// We do this even if params weren't provided so that solve can report if they are missing
|
||||
let params_sym = scope.gen_unique_symbol();
|
||||
let params_region = module_import.params.map(|p| p.params.region).unwrap_or(region);
|
||||
let params_region = module_import
|
||||
.params
|
||||
.map(|p| p.params.region)
|
||||
.unwrap_or(region);
|
||||
let params_var = var_store.fresh();
|
||||
let params =
|
||||
PendingModuleImportParams {
|
||||
symbol: params_sym,
|
||||
variable: params_var,
|
||||
loc_pattern: Loc::at(params_region, Pattern::Identifier(params_sym)),
|
||||
opt_provided: module_import.params.map(|p| p.params.value),
|
||||
};
|
||||
let params = PendingModuleImportParams {
|
||||
symbol: params_sym,
|
||||
variable: params_var,
|
||||
loc_pattern: Loc::at(params_region, Pattern::Identifier(params_sym)),
|
||||
opt_provided: module_import.params.map(|p| p.params.value),
|
||||
};
|
||||
let provided_params = if module_import.params.is_some() {
|
||||
// Only add params to scope if they are provided
|
||||
Some((params_var, params_sym))
|
||||
|
@ -3209,8 +3228,12 @@ fn to_pending_value_def<'a>(
|
|||
.map(|kw| kw.item.items)
|
||||
.unwrap_or_default();
|
||||
|
||||
if exposed_names.is_empty() && !env.home.is_builtin() && module_id.is_automatically_imported() {
|
||||
env.problems.push(Problem::ExplicitBuiltinImport(module_id, region));
|
||||
if exposed_names.is_empty()
|
||||
&& !env.home.is_builtin()
|
||||
&& module_id.is_automatically_imported()
|
||||
{
|
||||
env.problems
|
||||
.push(Problem::ExplicitBuiltinImport(module_id, region));
|
||||
}
|
||||
|
||||
let exposed_ids = env
|
||||
|
@ -3230,7 +3253,9 @@ fn to_pending_value_def<'a>(
|
|||
let symbol = Symbol::new(module_id, ident_id);
|
||||
exposed_symbols.push((symbol, loc_name.region));
|
||||
|
||||
if let Err((_shadowed_symbol, existing_symbol_region)) = scope.import_symbol(ident, symbol, loc_name.region) {
|
||||
if let Err((_shadowed_symbol, existing_symbol_region)) =
|
||||
scope.import_symbol(ident, symbol, loc_name.region)
|
||||
{
|
||||
if symbol.is_automatically_imported() {
|
||||
env.problem(Problem::ExplicitBuiltinTypeImport(
|
||||
symbol,
|
||||
|
@ -3245,14 +3270,12 @@ fn to_pending_value_def<'a>(
|
|||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
env.problem(Problem::RuntimeError(RuntimeError::ValueNotExposed {
|
||||
module_name: module_name.clone(),
|
||||
ident,
|
||||
region: loc_name.region,
|
||||
exposed_values: exposed_ids.exposed_values(),
|
||||
}))
|
||||
}
|
||||
None => env.problem(Problem::RuntimeError(RuntimeError::ValueNotExposed {
|
||||
module_name: module_name.clone(),
|
||||
ident,
|
||||
region: loc_name.region,
|
||||
exposed_values: exposed_ids.exposed_values(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3267,12 +3290,12 @@ fn to_pending_value_def<'a>(
|
|||
let loc_name = ingested_file.name.item;
|
||||
|
||||
let symbol = match scope.introduce(loc_name.value.into(), loc_name.region) {
|
||||
Ok(symbol ) => symbol,
|
||||
Ok(symbol) => symbol,
|
||||
Err((original, shadow, _)) => {
|
||||
env.problem(Problem::Shadowing {
|
||||
original_region: original.region,
|
||||
shadow,
|
||||
kind: ShadowKind::Variable
|
||||
kind: ShadowKind::Variable,
|
||||
});
|
||||
|
||||
return PendingValue::InvalidIngestedFile;
|
||||
|
@ -3281,9 +3304,20 @@ fn to_pending_value_def<'a>(
|
|||
|
||||
let loc_pattern = Loc::at(loc_name.region, Pattern::Identifier(symbol));
|
||||
|
||||
PendingValue::Def(PendingValueDef::IngestedFile(loc_pattern, ingested_file.annotation.map(|ann| ann.annotation), ingested_file.path))
|
||||
PendingValue::Def(PendingValueDef::IngestedFile(
|
||||
loc_pattern,
|
||||
ingested_file.annotation.map(|ann| ann.annotation),
|
||||
ingested_file.path,
|
||||
))
|
||||
}
|
||||
StmtAfterExpr => PendingValue::StmtAfterExpr,
|
||||
Stmt(expr) => {
|
||||
if env.fx_mode == FxMode::Task {
|
||||
internal_error!("a Stmt was not desugared correctly, should have been converted to a Body(...) in desguar")
|
||||
}
|
||||
|
||||
PendingValue::Def(PendingValueDef::Stmt(expr))
|
||||
}
|
||||
Stmt(_) => internal_error!("a Stmt was not desugared correctly, should have been converted to a Body(...) in desguar"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(clippy::manual_map)]
|
||||
|
||||
use crate::env::Env;
|
||||
use crate::env::{Env, FxMode};
|
||||
use crate::scope::Scope;
|
||||
use crate::suffixed::{apply_try_function, unwrap_suffixed_expression, EUnwrapped};
|
||||
use bumpalo::collections::Vec;
|
||||
|
@ -11,8 +11,8 @@ use roc_module::called_via::{BinOp, CalledVia};
|
|||
use roc_module::ident::ModuleName;
|
||||
use roc_parse::ast::Expr::{self, *};
|
||||
use roc_parse::ast::{
|
||||
AssignedField, Collection, Defs, ModuleImportParams, Pattern, StrLiteral, StrSegment,
|
||||
TypeAnnotation, ValueDef, WhenBranch,
|
||||
is_expr_suffixed, AssignedField, Collection, Defs, ModuleImportParams, Pattern, StrLiteral,
|
||||
StrSegment, TypeAnnotation, ValueDef, WhenBranch,
|
||||
};
|
||||
use roc_problem::can::Problem;
|
||||
use roc_region::all::{Loc, Region};
|
||||
|
@ -23,6 +23,10 @@ use roc_region::all::{Loc, Region};
|
|||
//
|
||||
// Thank you, Markus!
|
||||
|
||||
/// Desugar a single binary operation.
|
||||
///
|
||||
/// When using this function, don't desugar `left` and `right` before calling so that
|
||||
/// we can properly desugar `|> try` expressions!
|
||||
fn new_op_call_expr<'a>(
|
||||
env: &mut Env<'a>,
|
||||
scope: &mut Scope,
|
||||
|
@ -33,10 +37,43 @@ fn new_op_call_expr<'a>(
|
|||
let region = Region::span_across(&left.region, &right.region);
|
||||
|
||||
let value = match loc_op.value {
|
||||
// Rewrite the Pizza operator into an Apply
|
||||
Pizza => {
|
||||
// Rewrite the Pizza operator into an Apply
|
||||
// Allow `left |> try (optional)` to desugar to `try left (optional)`
|
||||
let right_without_spaces = without_spaces(&right.value);
|
||||
match right_without_spaces {
|
||||
Try => {
|
||||
let desugared_left = desugar_expr(env, scope, left);
|
||||
return desugar_try_expr(env, scope, desugared_left);
|
||||
}
|
||||
Apply(&Loc { value: Try, .. }, arguments, _called_via) => {
|
||||
let try_fn = desugar_expr(env, scope, arguments.first().unwrap());
|
||||
|
||||
match &right.value {
|
||||
let mut args = Vec::with_capacity_in(arguments.len(), env.arena);
|
||||
args.push(desugar_expr(env, scope, left));
|
||||
args.extend(
|
||||
arguments
|
||||
.iter()
|
||||
.skip(1)
|
||||
.map(|a| desugar_expr(env, scope, a)),
|
||||
);
|
||||
|
||||
return desugar_try_expr(
|
||||
env,
|
||||
scope,
|
||||
env.arena.alloc(Loc::at(
|
||||
right.region,
|
||||
Expr::Apply(try_fn, args.into_bump_slice(), CalledVia::Try),
|
||||
)),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let left = desugar_expr(env, scope, left);
|
||||
let right = desugar_expr(env, scope, right);
|
||||
|
||||
match right.value {
|
||||
Apply(function, arguments, _called_via) => {
|
||||
let mut args = Vec::with_capacity_in(1 + arguments.len(), env.arena);
|
||||
|
||||
|
@ -55,6 +92,9 @@ fn new_op_call_expr<'a>(
|
|||
}
|
||||
}
|
||||
binop => {
|
||||
let left = desugar_expr(env, scope, left);
|
||||
let right = desugar_expr(env, scope, right);
|
||||
|
||||
// This is a normal binary operator like (+), so desugar it
|
||||
// into the appropriate function call.
|
||||
let (module_name, ident) = binop_to_function(binop);
|
||||
|
@ -73,6 +113,13 @@ fn new_op_call_expr<'a>(
|
|||
Loc { region, value }
|
||||
}
|
||||
|
||||
fn without_spaces<'a>(expr: &'a Expr<'a>) -> &'a Expr<'a> {
|
||||
match expr {
|
||||
Expr::SpaceBefore(inner, _) | Expr::SpaceAfter(inner, _) => without_spaces(inner),
|
||||
_ => expr,
|
||||
}
|
||||
}
|
||||
|
||||
fn desugar_value_def<'a>(
|
||||
env: &mut Env<'a>,
|
||||
scope: &mut Scope,
|
||||
|
@ -120,16 +167,6 @@ fn desugar_value_def<'a>(
|
|||
preceding_comment: *preceding_comment,
|
||||
}
|
||||
}
|
||||
ExpectFx {
|
||||
condition,
|
||||
preceding_comment,
|
||||
} => {
|
||||
let desugared_condition = &*env.arena.alloc(desugar_expr(env, scope, condition));
|
||||
ExpectFx {
|
||||
condition: desugared_condition,
|
||||
preceding_comment: *preceding_comment,
|
||||
}
|
||||
}
|
||||
ModuleImport(roc_parse::ast::ModuleImport {
|
||||
before_name,
|
||||
name,
|
||||
|
@ -153,11 +190,29 @@ fn desugar_value_def<'a>(
|
|||
}
|
||||
IngestedFileImport(_) => *def,
|
||||
|
||||
StmtAfterExpr => internal_error!(
|
||||
"StmtAfterExpression is only created during desugaring, so it shouldn't exist here."
|
||||
),
|
||||
|
||||
Stmt(stmt_expr) => {
|
||||
if env.fx_mode == FxMode::PurityInference {
|
||||
// In purity inference mode, statements aren't fully desugared here
|
||||
// so we can provide better errors
|
||||
return Stmt(desugar_expr(env, scope, stmt_expr));
|
||||
}
|
||||
|
||||
// desugar `stmt_expr!` to
|
||||
// _ : {}
|
||||
// _ = stmt_expr!
|
||||
|
||||
let desugared_expr = desugar_expr(env, scope, stmt_expr);
|
||||
|
||||
if !is_expr_suffixed(&desugared_expr.value) {
|
||||
env.problems.push(Problem::StmtAfterExpr(stmt_expr.region));
|
||||
|
||||
return ValueDef::StmtAfterExpr;
|
||||
}
|
||||
|
||||
let region = stmt_expr.region;
|
||||
let new_pat = env
|
||||
.arena
|
||||
|
@ -174,7 +229,7 @@ fn desugar_value_def<'a>(
|
|||
)),
|
||||
lines_between: &[],
|
||||
body_pattern: new_pat,
|
||||
body_expr: desugar_expr(env, scope, stmt_expr),
|
||||
body_expr: desugared_expr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -248,8 +303,7 @@ pub fn desugar_value_def_suffixed<'a>(arena: &'a Bump, value_def: ValueDef<'a>)
|
|||
body_pattern,
|
||||
body_expr,
|
||||
} => {
|
||||
// note called_from_def is passed as `false` as this is a top_level_def
|
||||
match unwrap_suffixed_expression(arena, body_expr, None) {
|
||||
match unwrap_suffixed_expression(arena, body_expr, Some(ann_pattern)) {
|
||||
Ok(new_expr) => AnnotatedBody {
|
||||
ann_pattern,
|
||||
ann_type,
|
||||
|
@ -280,6 +334,19 @@ pub fn desugar_value_def_suffixed<'a>(arena: &'a Bump, value_def: ValueDef<'a>)
|
|||
),
|
||||
},
|
||||
),
|
||||
// When the last expression is suffixed, it will try to unwrap the def, but because we
|
||||
// have an annotated def we can simply ignore the try and return it as is without
|
||||
// creating an intermediate identifier
|
||||
Err(EUnwrapped::UnwrappedDefExpr { loc_expr, .. }) => desugar_value_def_suffixed(
|
||||
arena,
|
||||
AnnotatedBody {
|
||||
ann_pattern,
|
||||
ann_type,
|
||||
lines_between,
|
||||
body_pattern,
|
||||
body_expr: loc_expr,
|
||||
},
|
||||
),
|
||||
Err(..) => AnnotatedBody {
|
||||
ann_pattern,
|
||||
ann_type,
|
||||
|
@ -290,9 +357,22 @@ pub fn desugar_value_def_suffixed<'a>(arena: &'a Bump, value_def: ValueDef<'a>)
|
|||
}
|
||||
}
|
||||
|
||||
// TODO support desugaring of Dbg, Expect, and ExpectFx
|
||||
Dbg { .. } | Expect { .. } | ExpectFx { .. } => value_def,
|
||||
ModuleImport { .. } | IngestedFileImport(_) => value_def,
|
||||
Expect {
|
||||
condition,
|
||||
preceding_comment,
|
||||
} => match unwrap_suffixed_expression(arena, condition, None) {
|
||||
Ok(new_condition) => ValueDef::Expect {
|
||||
condition: new_condition,
|
||||
preceding_comment,
|
||||
},
|
||||
Err(..) => {
|
||||
internal_error!("Unable to desugar the suffix inside an Expect value def");
|
||||
}
|
||||
},
|
||||
|
||||
// TODO support desugaring of Dbg
|
||||
Dbg { .. } => value_def,
|
||||
ModuleImport { .. } | IngestedFileImport(_) | StmtAfterExpr => value_def,
|
||||
|
||||
Stmt(..) => {
|
||||
internal_error!(
|
||||
|
@ -315,10 +395,8 @@ pub fn desugar_expr<'a>(
|
|||
| NonBase10Int { .. }
|
||||
| SingleQuote(_)
|
||||
| AccessorFunction(_)
|
||||
| Var { .. }
|
||||
| Underscore { .. }
|
||||
| MalformedIdent(_, _)
|
||||
| MalformedClosure
|
||||
| MalformedSuffixed(..)
|
||||
| PrecedenceConflict { .. }
|
||||
| EmptyRecordBuilder(_)
|
||||
|
@ -326,7 +404,25 @@ pub fn desugar_expr<'a>(
|
|||
| OptionalFieldInRecordBuilder { .. }
|
||||
| Tag(_)
|
||||
| OpaqueRef(_)
|
||||
| Crash => loc_expr,
|
||||
| Crash
|
||||
| Try => loc_expr,
|
||||
|
||||
Var { module_name, ident } => {
|
||||
if env.fx_mode == FxMode::Task && ident.ends_with('!') {
|
||||
env.arena.alloc(Loc::at(
|
||||
Region::new(loc_expr.region.start(), loc_expr.region.end().sub(1)),
|
||||
TrySuffix {
|
||||
expr: env.arena.alloc(Var {
|
||||
module_name,
|
||||
ident: ident.trim_end_matches('!'),
|
||||
}),
|
||||
target: roc_parse::ast::TryTarget::Task,
|
||||
},
|
||||
))
|
||||
} else {
|
||||
loc_expr
|
||||
}
|
||||
}
|
||||
|
||||
Str(str_literal) => match str_literal {
|
||||
StrLiteral::PlainLine(_) => loc_expr,
|
||||
|
@ -605,7 +701,6 @@ pub fn desugar_expr<'a>(
|
|||
AssignedField::SpaceBefore(_, _) | AssignedField::SpaceAfter(_, _) => {
|
||||
unreachable!("Should have been desugared in `desugar_field`")
|
||||
}
|
||||
AssignedField::Malformed(_name) => continue,
|
||||
};
|
||||
|
||||
field_data.push(FieldData {
|
||||
|
@ -845,6 +940,31 @@ pub fn desugar_expr<'a>(
|
|||
})
|
||||
}
|
||||
}
|
||||
Apply(
|
||||
Loc {
|
||||
value: Try,
|
||||
region: _,
|
||||
},
|
||||
loc_args,
|
||||
_called_via,
|
||||
) => {
|
||||
let result_expr = if loc_args.len() == 1 {
|
||||
desugar_expr(env, scope, loc_args[0])
|
||||
} else {
|
||||
let function = desugar_expr(env, scope, loc_args.first().unwrap());
|
||||
let mut desugared_args = Vec::with_capacity_in(loc_args.len() - 1, env.arena);
|
||||
for loc_arg in &loc_args[1..] {
|
||||
desugared_args.push(desugar_expr(env, scope, loc_arg));
|
||||
}
|
||||
|
||||
env.arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
Expr::Apply(function, desugared_args.into_bump_slice(), CalledVia::Try),
|
||||
))
|
||||
};
|
||||
|
||||
env.arena.alloc(desugar_try_expr(env, scope, result_expr))
|
||||
}
|
||||
Apply(loc_fn, loc_args, called_via) => {
|
||||
let mut desugared_args = Vec::with_capacity_in(loc_args.len(), env.arena);
|
||||
|
||||
|
@ -980,21 +1100,12 @@ pub fn desugar_expr<'a>(
|
|||
region: loc_expr.region,
|
||||
})
|
||||
}
|
||||
Expect(condition, continuation) => {
|
||||
let desugared_condition = &*env.arena.alloc(desugar_expr(env, scope, condition));
|
||||
let desugared_continuation = &*env.arena.alloc(desugar_expr(env, scope, continuation));
|
||||
env.arena.alloc(Loc {
|
||||
value: Expect(desugared_condition, desugared_continuation),
|
||||
region: loc_expr.region,
|
||||
})
|
||||
}
|
||||
Dbg => {
|
||||
// Allow naked dbg, necessary for piping values into dbg with the `Pizza` binop
|
||||
loc_expr
|
||||
}
|
||||
DbgStmt(condition, continuation) => {
|
||||
let desugared_condition = &*env.arena.alloc(desugar_expr(env, scope, condition));
|
||||
|
||||
let desugared_continuation = &*env.arena.alloc(desugar_expr(env, scope, continuation));
|
||||
|
||||
env.arena.alloc(Loc {
|
||||
|
@ -1002,12 +1113,87 @@ pub fn desugar_expr<'a>(
|
|||
region: loc_expr.region,
|
||||
})
|
||||
}
|
||||
Return(return_value, after_return) => {
|
||||
let desugared_return_value = &*env.arena.alloc(desugar_expr(env, scope, return_value));
|
||||
|
||||
env.arena.alloc(Loc {
|
||||
// Do not desugar after_return since it isn't run anyway
|
||||
value: Return(desugared_return_value, *after_return),
|
||||
region: loc_expr.region,
|
||||
})
|
||||
}
|
||||
|
||||
// note this only exists after desugaring
|
||||
LowLevelDbg(_, _, _) => loc_expr,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn desugar_try_expr<'a>(
|
||||
env: &mut Env<'a>,
|
||||
scope: &mut Scope,
|
||||
result_expr: &'a Loc<Expr<'a>>,
|
||||
) -> Loc<Expr<'a>> {
|
||||
let region = result_expr.region;
|
||||
let ok_symbol = env.arena.alloc(scope.gen_unique_symbol_name().to_string());
|
||||
let err_symbol = env.arena.alloc(scope.gen_unique_symbol_name().to_string());
|
||||
|
||||
let ok_branch = env.arena.alloc(WhenBranch {
|
||||
patterns: env.arena.alloc([Loc::at(
|
||||
region,
|
||||
Pattern::Apply(
|
||||
env.arena.alloc(Loc::at(region, Pattern::Tag("Ok"))),
|
||||
env.arena
|
||||
.alloc([Loc::at(region, Pattern::Identifier { ident: ok_symbol })]),
|
||||
),
|
||||
)]),
|
||||
value: Loc::at(
|
||||
region,
|
||||
Expr::Var {
|
||||
module_name: "",
|
||||
ident: ok_symbol,
|
||||
},
|
||||
),
|
||||
guard: None,
|
||||
});
|
||||
|
||||
let err_branch = env.arena.alloc(WhenBranch {
|
||||
patterns: env.arena.alloc([Loc::at(
|
||||
region,
|
||||
Pattern::Apply(
|
||||
env.arena.alloc(Loc::at(region, Pattern::Tag("Err"))),
|
||||
env.arena
|
||||
.alloc([Loc::at(region, Pattern::Identifier { ident: err_symbol })]),
|
||||
),
|
||||
)]),
|
||||
value: Loc::at(
|
||||
region,
|
||||
Expr::Return(
|
||||
env.arena.alloc(Loc::at(
|
||||
region,
|
||||
Expr::Apply(
|
||||
env.arena.alloc(Loc::at(region, Expr::Tag("Err"))),
|
||||
&*env.arena.alloc([&*env.arena.alloc(Loc::at(
|
||||
region,
|
||||
Expr::Var {
|
||||
module_name: "",
|
||||
ident: err_symbol,
|
||||
},
|
||||
))]),
|
||||
CalledVia::Try,
|
||||
),
|
||||
)),
|
||||
None,
|
||||
),
|
||||
),
|
||||
guard: None,
|
||||
});
|
||||
|
||||
Loc::at(
|
||||
region,
|
||||
Expr::When(result_expr, &*env.arena.alloc([&*ok_branch, &*err_branch])),
|
||||
)
|
||||
}
|
||||
|
||||
fn desugar_str_segments<'a>(
|
||||
env: &mut Env<'a>,
|
||||
scope: &mut Scope,
|
||||
|
@ -1020,20 +1206,6 @@ fn desugar_str_segments<'a>(
|
|||
StrSegment::Plaintext(_) | StrSegment::Unicode(_) | StrSegment::EscapedChar(_) => {
|
||||
*segment
|
||||
}
|
||||
StrSegment::DeprecatedInterpolated(loc_expr) => {
|
||||
let loc_desugared = desugar_expr(
|
||||
env,
|
||||
scope,
|
||||
env.arena.alloc(Loc {
|
||||
region: loc_expr.region,
|
||||
value: *loc_expr.value,
|
||||
}),
|
||||
);
|
||||
StrSegment::DeprecatedInterpolated(Loc {
|
||||
region: loc_desugared.region,
|
||||
value: env.arena.alloc(loc_desugared.value),
|
||||
})
|
||||
}
|
||||
StrSegment::Interpolated(loc_expr) => {
|
||||
let loc_desugared = desugar_expr(
|
||||
env,
|
||||
|
@ -1123,8 +1295,6 @@ fn desugar_field<'a>(
|
|||
}
|
||||
SpaceBefore(field, _spaces) => desugar_field(env, scope, field),
|
||||
SpaceAfter(field, _spaces) => desugar_field(env, scope, field),
|
||||
|
||||
Malformed(string) => Malformed(string),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1387,7 +1557,7 @@ fn desugar_bin_ops<'a>(
|
|||
let mut op_stack: Vec<Loc<BinOp>> = Vec::with_capacity_in(lefts.len(), env.arena);
|
||||
|
||||
for (loc_expr, loc_op) in lefts {
|
||||
arg_stack.push(desugar_expr(env, scope, loc_expr));
|
||||
arg_stack.push(loc_expr);
|
||||
match run_binop_step(
|
||||
env,
|
||||
scope,
|
||||
|
@ -1401,7 +1571,7 @@ fn desugar_bin_ops<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
let mut expr = desugar_expr(env, scope, right);
|
||||
let mut expr = right;
|
||||
|
||||
for (left, loc_op) in arg_stack.into_iter().zip(op_stack.into_iter()).rev() {
|
||||
expr = env
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::def::Def;
|
||||
use crate::def::{Def, DefKind};
|
||||
use crate::expr::{AnnotatedMark, ClosureData, Expr, Recursive};
|
||||
use crate::pattern::Pattern;
|
||||
use crate::scope::Scope;
|
||||
|
@ -33,7 +33,7 @@ pub fn build_host_exposed_def(
|
|||
|
||||
let def_body = {
|
||||
match typ.shallow_structural_dealias() {
|
||||
Type::Function(args, _, _) => {
|
||||
Type::Function(args, _, _, fx) if **fx == Type::Pure => {
|
||||
for i in 0..args.len() {
|
||||
let name = format!("closure_arg_{ident}_{i}");
|
||||
|
||||
|
@ -72,6 +72,8 @@ pub fn build_host_exposed_def(
|
|||
function_type: var_store.fresh(),
|
||||
closure_type: var_store.fresh(),
|
||||
return_type: var_store.fresh(),
|
||||
fx_type: var_store.fresh(),
|
||||
early_returns: vec![],
|
||||
name: task_closure_symbol,
|
||||
captured_symbols,
|
||||
recursive: Recursive::NotRecursive,
|
||||
|
@ -98,6 +100,8 @@ pub fn build_host_exposed_def(
|
|||
function_type: var_store.fresh(),
|
||||
closure_type: var_store.fresh(),
|
||||
return_type: var_store.fresh(),
|
||||
fx_type: var_store.fresh(),
|
||||
early_returns: vec![],
|
||||
name: symbol,
|
||||
captured_symbols: std::vec::Vec::new(),
|
||||
recursive: Recursive::NotRecursive,
|
||||
|
@ -105,6 +109,47 @@ pub fn build_host_exposed_def(
|
|||
loc_body: Box::new(Loc::at_zero(body)),
|
||||
})
|
||||
}
|
||||
Type::Function(args, _, _, fx) if **fx == Type::Effectful => {
|
||||
for i in 0..args.len() {
|
||||
let name = format!("{ident}_arg_{i}");
|
||||
|
||||
let arg_symbol = {
|
||||
let ident = name.clone().into();
|
||||
scope.introduce(ident, Region::zero()).unwrap()
|
||||
};
|
||||
|
||||
let arg_var = var_store.fresh();
|
||||
|
||||
arguments.push((
|
||||
arg_var,
|
||||
AnnotatedMark::new(var_store),
|
||||
Loc::at_zero(Pattern::Identifier(arg_symbol)),
|
||||
));
|
||||
|
||||
linked_symbol_arguments.push((arg_var, Expr::Var(arg_symbol, arg_var)));
|
||||
}
|
||||
|
||||
let ident_without_bang = ident.trim_end_matches('!');
|
||||
let foreign_symbol_name = format!("roc_fx_{ident_without_bang}");
|
||||
let foreign_call = Expr::ForeignCall {
|
||||
foreign_symbol: foreign_symbol_name.into(),
|
||||
args: linked_symbol_arguments,
|
||||
ret_var: var_store.fresh(),
|
||||
};
|
||||
|
||||
Expr::Closure(ClosureData {
|
||||
function_type: var_store.fresh(),
|
||||
closure_type: var_store.fresh(),
|
||||
return_type: var_store.fresh(),
|
||||
fx_type: var_store.fresh(),
|
||||
early_returns: vec![],
|
||||
name: symbol,
|
||||
captured_symbols: std::vec::Vec::new(),
|
||||
recursive: Recursive::NotRecursive,
|
||||
arguments,
|
||||
loc_body: Box::new(Loc::at_zero(foreign_call)),
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
// not a function
|
||||
|
||||
|
@ -126,6 +171,8 @@ pub fn build_host_exposed_def(
|
|||
function_type: var_store.fresh(),
|
||||
closure_type: var_store.fresh(),
|
||||
return_type: var_store.fresh(),
|
||||
fx_type: var_store.fresh(),
|
||||
early_returns: vec![],
|
||||
name: task_closure_symbol,
|
||||
captured_symbols,
|
||||
recursive: Recursive::NotRecursive,
|
||||
|
@ -164,6 +211,7 @@ pub fn build_host_exposed_def(
|
|||
expr_var,
|
||||
pattern_vars,
|
||||
annotation: Some(def_annotation),
|
||||
kind: DefKind::Let,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,11 +223,13 @@ fn build_fresh_opaque_variables(
|
|||
let ok_var = var_store.fresh();
|
||||
let err_var = var_store.fresh();
|
||||
let result_var = var_store.fresh();
|
||||
let fx_var = var_store.fresh();
|
||||
|
||||
let actual = Type::Function(
|
||||
vec![Type::EmptyRec],
|
||||
Box::new(Type::Variable(closure_var)),
|
||||
Box::new(Type::Variable(result_var)),
|
||||
Box::new(Type::Variable(fx_var)),
|
||||
);
|
||||
|
||||
let type_arguments = vec![
|
|
@ -45,6 +45,8 @@ pub struct Env<'a> {
|
|||
|
||||
pub opt_shorthand: Option<&'a str>,
|
||||
|
||||
pub fx_mode: FxMode,
|
||||
|
||||
pub src: &'a str,
|
||||
|
||||
/// Lazily calculated line info. This data is only needed if the code contains calls to `dbg`,
|
||||
|
@ -54,6 +56,7 @@ pub struct Env<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Env<'a> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
arena: &'a Bump,
|
||||
src: &'a str,
|
||||
|
@ -62,6 +65,7 @@ impl<'a> Env<'a> {
|
|||
dep_idents: &'a IdentIdsByModule,
|
||||
qualified_module_ids: &'a PackageModuleIds<'a>,
|
||||
opt_shorthand: Option<&'a str>,
|
||||
fx_mode: FxMode,
|
||||
) -> Env<'a> {
|
||||
Env {
|
||||
arena,
|
||||
|
@ -79,6 +83,7 @@ impl<'a> Env<'a> {
|
|||
home_params_record: None,
|
||||
opt_shorthand,
|
||||
line_info: arena.alloc(None),
|
||||
fx_mode,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,3 +242,9 @@ impl<'a> Env<'a> {
|
|||
self.line_info.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum FxMode {
|
||||
PurityInference,
|
||||
Task,
|
||||
}
|
||||
|
|
|
@ -141,7 +141,9 @@ fn index_var(
|
|||
| Content::RigidAbleVar(_, _)
|
||||
| Content::LambdaSet(_)
|
||||
| Content::ErasedLambda
|
||||
| Content::RangedNumber(..) => return Err(TypeError),
|
||||
| Content::RangedNumber(..)
|
||||
| Content::Pure
|
||||
| Content::Effectful => return Err(TypeError),
|
||||
Content::Error => return Err(TypeError),
|
||||
Content::RecursionVar {
|
||||
structure,
|
||||
|
@ -150,7 +152,8 @@ fn index_var(
|
|||
var = *structure;
|
||||
}
|
||||
Content::Structure(structure) => match structure {
|
||||
FlatType::Func(_, _, _) => return Err(TypeError),
|
||||
FlatType::Func(_, _, _, _) => return Err(TypeError),
|
||||
FlatType::EffectfulFunc => return Err(TypeError),
|
||||
FlatType::Apply(Symbol::LIST_LIST, args) => {
|
||||
match (subs.get_subs_slice(*args), ctor) {
|
||||
([elem_var], IndexCtor::List) => {
|
||||
|
@ -237,9 +240,6 @@ fn index_var(
|
|||
};
|
||||
return Ok(std::iter::repeat(Variable::NULL).take(num_fields).collect());
|
||||
}
|
||||
FlatType::EmptyTuple => {
|
||||
return Ok(std::iter::repeat(Variable::NULL).take(0).collect());
|
||||
}
|
||||
FlatType::EmptyTagUnion => {
|
||||
internal_error!("empty tag unions are not indexable")
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::abilities::SpecializationId;
|
||||
use crate::annotation::{freshen_opaque_def, IntroducedVariables};
|
||||
use crate::builtins::builtin_defs_map;
|
||||
use crate::def::{can_defs_with_return, Annotation, Def};
|
||||
use crate::def::{can_defs_with_return, Annotation, Def, DefKind};
|
||||
use crate::env::Env;
|
||||
use crate::num::{
|
||||
finish_parsing_base, finish_parsing_float, finish_parsing_num, float_expr_from_result,
|
||||
|
@ -12,7 +12,7 @@ use crate::pattern::{canonicalize_pattern, BindingsFromPattern, Pattern, PermitS
|
|||
use crate::procedure::{QualifiedReference, References};
|
||||
use crate::scope::{Scope, SymbolLookup};
|
||||
use crate::traverse::{walk_expr, Visitor};
|
||||
use roc_collections::soa::Index;
|
||||
use roc_collections::soa::index_push_new;
|
||||
use roc_collections::{SendMap, VecMap, VecSet};
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::called_via::CalledVia;
|
||||
|
@ -27,6 +27,7 @@ use roc_region::all::{Loc, Region};
|
|||
use roc_types::num::SingleQuoteBound;
|
||||
use roc_types::subs::{ExhaustiveMark, IllegalCycleMark, RedundantMark, VarStore, Variable};
|
||||
use roc_types::types::{Alias, Category, IndexOrField, LambdaSet, OptAbleVar, Type};
|
||||
use soa::Index;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
@ -38,7 +39,7 @@ pub type PendingDerives = VecMap<Symbol, (Type, Vec<Loc<Symbol>>)>;
|
|||
#[derive(Clone, Default, Debug)]
|
||||
pub struct Output {
|
||||
pub references: References,
|
||||
pub tail_call: Option<Symbol>,
|
||||
pub tail_calls: Vec<Symbol>,
|
||||
pub introduced_variables: IntroducedVariables,
|
||||
pub aliases: VecMap<Symbol, Alias>,
|
||||
pub non_closures: VecSet<Symbol>,
|
||||
|
@ -49,8 +50,8 @@ impl Output {
|
|||
pub fn union(&mut self, other: Self) {
|
||||
self.references.union_mut(&other.references);
|
||||
|
||||
if let (None, Some(later)) = (self.tail_call, other.tail_call) {
|
||||
self.tail_call = Some(later);
|
||||
if self.tail_calls.is_empty() && !other.tail_calls.is_empty() {
|
||||
self.tail_calls = other.tail_calls;
|
||||
}
|
||||
|
||||
self.introduced_variables
|
||||
|
@ -202,7 +203,7 @@ pub enum Expr {
|
|||
/// This is *only* for calling functions, not for tag application.
|
||||
/// The Tag variant contains any applied values inside it.
|
||||
Call(
|
||||
Box<(Variable, Loc<Expr>, Variable, Variable)>,
|
||||
Box<(Variable, Loc<Expr>, Variable, Variable, Variable)>,
|
||||
Vec<(Variable, Loc<Expr>)>,
|
||||
CalledVia,
|
||||
),
|
||||
|
@ -318,13 +319,6 @@ pub enum Expr {
|
|||
lookups_in_cond: Vec<ExpectLookup>,
|
||||
},
|
||||
|
||||
// not parsed, but is generated when lowering toplevel effectful expects
|
||||
ExpectFx {
|
||||
loc_condition: Box<Loc<Expr>>,
|
||||
loc_continuation: Box<Loc<Expr>>,
|
||||
lookups_in_cond: Vec<ExpectLookup>,
|
||||
},
|
||||
|
||||
Dbg {
|
||||
source_location: Box<str>,
|
||||
source: Box<str>,
|
||||
|
@ -334,6 +328,11 @@ pub enum Expr {
|
|||
symbol: Symbol,
|
||||
},
|
||||
|
||||
Return {
|
||||
return_value: Box<Loc<Expr>>,
|
||||
return_var: Variable,
|
||||
},
|
||||
|
||||
/// Rendered as empty box in editor
|
||||
TypedHole(Variable),
|
||||
|
||||
|
@ -406,8 +405,8 @@ impl Expr {
|
|||
Category::OpaqueWrap(opaque_name)
|
||||
}
|
||||
Self::Expect { .. } => Category::Expect,
|
||||
Self::ExpectFx { .. } => Category::Expect,
|
||||
Self::Crash { .. } => Category::Crash,
|
||||
Self::Return { .. } => Category::Return,
|
||||
|
||||
Self::Dbg { .. } => Category::Expect,
|
||||
|
||||
|
@ -448,6 +447,8 @@ pub struct ClosureData {
|
|||
pub function_type: Variable,
|
||||
pub closure_type: Variable,
|
||||
pub return_type: Variable,
|
||||
pub fx_type: Variable,
|
||||
pub early_returns: Vec<(Variable, Region)>,
|
||||
pub name: Symbol,
|
||||
pub captured_symbols: Vec<(Symbol, Variable)>,
|
||||
pub recursive: Recursive,
|
||||
|
@ -524,6 +525,8 @@ impl StructAccessorData {
|
|||
function_type: function_var,
|
||||
closure_type: closure_var,
|
||||
return_type: field_var,
|
||||
fx_type: Variable::PURE,
|
||||
early_returns: vec![],
|
||||
name,
|
||||
captured_symbols: vec![],
|
||||
recursive: Recursive::NotRecursive,
|
||||
|
@ -597,6 +600,8 @@ impl OpaqueWrapFunctionData {
|
|||
function_type: function_var,
|
||||
closure_type: closure_var,
|
||||
return_type: opaque_var,
|
||||
fx_type: Variable::PURE,
|
||||
early_returns: vec![],
|
||||
name: function_name,
|
||||
captured_symbols: vec![],
|
||||
recursive: Recursive::NotRecursive,
|
||||
|
@ -762,7 +767,6 @@ pub fn canonicalize_expr<'a>(
|
|||
|
||||
let output = Output {
|
||||
references,
|
||||
tail_call: None,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -830,7 +834,6 @@ pub fn canonicalize_expr<'a>(
|
|||
|
||||
let output = Output {
|
||||
references,
|
||||
tail_call: None,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -947,17 +950,19 @@ pub fn canonicalize_expr<'a>(
|
|||
output.union(fn_expr_output);
|
||||
|
||||
// Default: We're not tail-calling a symbol (by name), we're tail-calling a function value.
|
||||
output.tail_call = None;
|
||||
output.tail_calls = vec![];
|
||||
|
||||
let expr = match fn_expr.value {
|
||||
Var(symbol, _) => {
|
||||
output.references.insert_call(symbol);
|
||||
|
||||
// we're tail-calling a symbol by name, check if it's the tail-callable symbol
|
||||
output.tail_call = match &env.tailcallable_symbol {
|
||||
Some(tc_sym) if *tc_sym == symbol => Some(symbol),
|
||||
Some(_) | None => None,
|
||||
};
|
||||
if env
|
||||
.tailcallable_symbol
|
||||
.is_some_and(|tc_sym| tc_sym == symbol)
|
||||
{
|
||||
output.tail_calls.push(symbol);
|
||||
}
|
||||
|
||||
Call(
|
||||
Box::new((
|
||||
|
@ -965,6 +970,7 @@ pub fn canonicalize_expr<'a>(
|
|||
fn_expr,
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
)),
|
||||
args,
|
||||
*application_style,
|
||||
|
@ -1004,6 +1010,7 @@ pub fn canonicalize_expr<'a>(
|
|||
fn_expr,
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
)),
|
||||
args,
|
||||
*application_style,
|
||||
|
@ -1056,7 +1063,7 @@ pub fn canonicalize_expr<'a>(
|
|||
}
|
||||
ast::Expr::Defs(loc_defs, loc_ret) => {
|
||||
// The body expression gets a new scope for canonicalization,
|
||||
scope.inner_scope(|inner_scope| {
|
||||
scope.inner_def_scope(|inner_scope| {
|
||||
let defs: Defs = (*loc_defs).clone();
|
||||
can_defs_with_return(env, var_store, inner_scope, env.arena.alloc(defs), loc_ret)
|
||||
})
|
||||
|
@ -1083,12 +1090,12 @@ pub fn canonicalize_expr<'a>(
|
|||
canonicalize_expr(env, var_store, scope, loc_cond.region, &loc_cond.value);
|
||||
|
||||
// the condition can never be a tail-call
|
||||
output.tail_call = None;
|
||||
output.tail_calls = vec![];
|
||||
|
||||
let mut can_branches = Vec::with_capacity(branches.len());
|
||||
|
||||
for branch in branches.iter() {
|
||||
let (can_when_branch, branch_references) = scope.inner_scope(|inner_scope| {
|
||||
let (can_when_branch, branch_references) = scope.inner_def_scope(|inner_scope| {
|
||||
canonicalize_when_branch(
|
||||
env,
|
||||
var_store,
|
||||
|
@ -1108,7 +1115,7 @@ pub fn canonicalize_expr<'a>(
|
|||
// if code gen mistakenly thinks this is a tail call just because its condition
|
||||
// happened to be one. (The condition gave us our initial output value.)
|
||||
if branches.is_empty() {
|
||||
output.tail_call = None;
|
||||
output.tail_calls = vec![];
|
||||
}
|
||||
|
||||
// Incorporate all three expressions into a combined Output value.
|
||||
|
@ -1170,6 +1177,11 @@ pub fn canonicalize_expr<'a>(
|
|||
ast::Expr::TrySuffix { .. } => internal_error!(
|
||||
"a Expr::TrySuffix expression was not completely removed in desugar_value_def_suffixed"
|
||||
),
|
||||
ast::Expr::Try => {
|
||||
// Treat remaining `try` keywords as normal variables so that we can continue to support `Result.try`
|
||||
canonicalize_var_lookup(env, var_store, scope, "", "try", region)
|
||||
}
|
||||
|
||||
ast::Expr::Tag(tag) => {
|
||||
let variant_var = var_store.fresh();
|
||||
let ext_var = var_store.fresh();
|
||||
|
@ -1224,36 +1236,6 @@ pub fn canonicalize_expr<'a>(
|
|||
}
|
||||
}
|
||||
}
|
||||
ast::Expr::Expect(condition, continuation) => {
|
||||
let mut output = Output::default();
|
||||
|
||||
let (loc_condition, output1) =
|
||||
canonicalize_expr(env, var_store, scope, condition.region, &condition.value);
|
||||
|
||||
// Get all the lookups that were referenced in the condition,
|
||||
// so we can print their values later.
|
||||
let lookups_in_cond = get_lookup_symbols(&loc_condition.value);
|
||||
|
||||
let (loc_continuation, output2) = canonicalize_expr(
|
||||
env,
|
||||
var_store,
|
||||
scope,
|
||||
continuation.region,
|
||||
&continuation.value,
|
||||
);
|
||||
|
||||
output.union(output1);
|
||||
output.union(output2);
|
||||
|
||||
(
|
||||
Expect {
|
||||
loc_condition: Box::new(loc_condition),
|
||||
loc_continuation: Box::new(loc_continuation),
|
||||
lookups_in_cond,
|
||||
},
|
||||
output,
|
||||
)
|
||||
}
|
||||
ast::Expr::Dbg => {
|
||||
// Dbg was not desugared as either part of an `Apply` or a `Pizza` binop, so it's
|
||||
// invalid.
|
||||
|
@ -1306,6 +1288,40 @@ pub fn canonicalize_expr<'a>(
|
|||
output,
|
||||
)
|
||||
}
|
||||
ast::Expr::Return(return_expr, after_return) => {
|
||||
let mut output = Output::default();
|
||||
|
||||
if let Some(after_return) = after_return {
|
||||
let region_with_return =
|
||||
Region::span_across(&return_expr.region, &after_return.region);
|
||||
|
||||
env.problem(Problem::StatementsAfterReturn {
|
||||
region: region_with_return,
|
||||
});
|
||||
}
|
||||
|
||||
let (loc_return_expr, output1) = canonicalize_expr(
|
||||
env,
|
||||
var_store,
|
||||
scope,
|
||||
return_expr.region,
|
||||
&return_expr.value,
|
||||
);
|
||||
|
||||
output.union(output1);
|
||||
|
||||
let return_var = var_store.fresh();
|
||||
|
||||
scope.early_returns.push((return_var, return_expr.region));
|
||||
|
||||
(
|
||||
Return {
|
||||
return_value: Box::new(loc_return_expr),
|
||||
return_var,
|
||||
},
|
||||
output,
|
||||
)
|
||||
}
|
||||
ast::Expr::If {
|
||||
if_thens,
|
||||
final_else: final_else_branch,
|
||||
|
@ -1385,10 +1401,6 @@ pub fn canonicalize_expr<'a>(
|
|||
Output::default(),
|
||||
)
|
||||
}
|
||||
ast::Expr::MalformedClosure => {
|
||||
use roc_problem::can::RuntimeError::*;
|
||||
(RuntimeError(MalformedClosure(region)), Output::default())
|
||||
}
|
||||
ast::Expr::MalformedIdent(name, bad_ident) => {
|
||||
use roc_problem::can::RuntimeError::*;
|
||||
|
||||
|
@ -1541,7 +1553,7 @@ pub fn canonicalize_closure<'a>(
|
|||
loc_body_expr: &'a Loc<ast::Expr<'a>>,
|
||||
opt_def_name: Option<Symbol>,
|
||||
) -> (ClosureData, Output) {
|
||||
scope.inner_scope(|inner_scope| {
|
||||
scope.inner_function_scope(|inner_scope| {
|
||||
canonicalize_closure_body(
|
||||
env,
|
||||
var_store,
|
||||
|
@ -1656,6 +1668,17 @@ fn canonicalize_closure_body<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
let mut final_expr = &loc_body_expr;
|
||||
while let Expr::LetRec(_, inner, _) | Expr::LetNonRec(_, inner) = &final_expr.value {
|
||||
final_expr = inner;
|
||||
}
|
||||
|
||||
if let Expr::Return { return_value, .. } = &final_expr.value {
|
||||
env.problem(Problem::ReturnAtEndOfFunction {
|
||||
region: return_value.region,
|
||||
});
|
||||
}
|
||||
|
||||
// store the references of this function in the Env. This information is used
|
||||
// when we canonicalize a surrounding def (if it exists)
|
||||
env.closures.insert(symbol, output.references.clone());
|
||||
|
@ -1669,10 +1692,14 @@ fn canonicalize_closure_body<'a>(
|
|||
output.non_closures.insert(symbol);
|
||||
}
|
||||
|
||||
let return_type_var = var_store.fresh();
|
||||
|
||||
let closure_data = ClosureData {
|
||||
function_type: var_store.fresh(),
|
||||
closure_type: var_store.fresh(),
|
||||
return_type: var_store.fresh(),
|
||||
return_type: return_type_var,
|
||||
fx_type: var_store.fresh(),
|
||||
early_returns: scope.early_returns.clone(),
|
||||
name: symbol,
|
||||
captured_symbols,
|
||||
recursive: Recursive::NotRecursive,
|
||||
|
@ -1955,10 +1982,6 @@ fn canonicalize_field<'a>(
|
|||
SpaceBefore(sub_field, _) | SpaceAfter(sub_field, _) => {
|
||||
canonicalize_field(env, var_store, scope, sub_field)
|
||||
}
|
||||
|
||||
Malformed(_string) => {
|
||||
internal_error!("TODO canonicalize malformed record field");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2075,7 +2098,8 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
|
|||
| other @ TypedHole { .. }
|
||||
| other @ ForeignCall { .. }
|
||||
| other @ OpaqueWrapFunction(_)
|
||||
| other @ Crash { .. } => other,
|
||||
| other @ Crash { .. }
|
||||
| other @ Return { .. } => other,
|
||||
|
||||
List {
|
||||
elem_var,
|
||||
|
@ -2203,28 +2227,6 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
|
|||
}
|
||||
}
|
||||
|
||||
ExpectFx {
|
||||
loc_condition,
|
||||
loc_continuation,
|
||||
lookups_in_cond,
|
||||
} => {
|
||||
let loc_condition = Loc {
|
||||
region: loc_condition.region,
|
||||
value: inline_calls(var_store, loc_condition.value),
|
||||
};
|
||||
|
||||
let loc_continuation = Loc {
|
||||
region: loc_continuation.region,
|
||||
value: inline_calls(var_store, loc_continuation.value),
|
||||
};
|
||||
|
||||
ExpectFx {
|
||||
loc_condition: Box::new(loc_condition),
|
||||
loc_continuation: Box::new(loc_continuation),
|
||||
lookups_in_cond,
|
||||
}
|
||||
}
|
||||
|
||||
Dbg {
|
||||
source_location,
|
||||
source,
|
||||
|
@ -2266,6 +2268,7 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
|
|||
expr_var: def.expr_var,
|
||||
pattern_vars: def.pattern_vars,
|
||||
annotation: def.annotation,
|
||||
kind: def.kind,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -2287,6 +2290,7 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
|
|||
expr_var: def.expr_var,
|
||||
pattern_vars: def.pattern_vars,
|
||||
annotation: def.annotation,
|
||||
kind: def.kind,
|
||||
};
|
||||
|
||||
let loc_expr = Loc {
|
||||
|
@ -2301,6 +2305,8 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
|
|||
function_type,
|
||||
closure_type,
|
||||
return_type,
|
||||
fx_type,
|
||||
early_returns,
|
||||
recursive,
|
||||
name,
|
||||
captured_symbols,
|
||||
|
@ -2317,6 +2323,8 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
|
|||
function_type,
|
||||
closure_type,
|
||||
return_type,
|
||||
fx_type,
|
||||
early_returns,
|
||||
recursive,
|
||||
name,
|
||||
captured_symbols,
|
||||
|
@ -2424,10 +2432,11 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
|
|||
}
|
||||
|
||||
Call(boxed_tuple, args, called_via) => {
|
||||
let (fn_var, loc_expr, closure_var, expr_var) = *boxed_tuple;
|
||||
let (fn_var, loc_expr, closure_var, expr_var, fx_var) = *boxed_tuple;
|
||||
|
||||
match loc_expr.value {
|
||||
Var(symbol, _) if symbol.is_builtin() => {
|
||||
// NOTE: This assumes builtins are not effectful!
|
||||
match builtin_defs_map(symbol, var_store) {
|
||||
Some(Def {
|
||||
loc_expr:
|
||||
|
@ -2471,6 +2480,7 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
|
|||
expr_var,
|
||||
pattern_vars,
|
||||
annotation: None,
|
||||
kind: DefKind::Let,
|
||||
};
|
||||
|
||||
loc_answer = Loc {
|
||||
|
@ -2495,7 +2505,7 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
|
|||
_ => {
|
||||
// For now, we only inline calls to builtins. Leave this alone!
|
||||
Call(
|
||||
Box::new((fn_var, loc_expr, closure_var, expr_var)),
|
||||
Box::new((fn_var, loc_expr, closure_var, expr_var, fx_var)),
|
||||
args,
|
||||
called_via,
|
||||
)
|
||||
|
@ -2534,15 +2544,15 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
|||
| ast::Expr::RecordUpdater(_)
|
||||
| ast::Expr::Crash
|
||||
| ast::Expr::Dbg
|
||||
| ast::Expr::Try
|
||||
| ast::Expr::Underscore(_)
|
||||
| ast::Expr::MalformedIdent(_, _)
|
||||
| ast::Expr::Tag(_)
|
||||
| ast::Expr::OpaqueRef(_)
|
||||
| ast::Expr::MalformedClosure => true,
|
||||
| ast::Expr::OpaqueRef(_) => true,
|
||||
// Newlines are disallowed inside interpolation, and these all require newlines
|
||||
ast::Expr::DbgStmt(_, _)
|
||||
| ast::Expr::LowLevelDbg(_, _, _)
|
||||
| ast::Expr::Expect(_, _)
|
||||
| ast::Expr::Return(_, _)
|
||||
| ast::Expr::When(_, _)
|
||||
| ast::Expr::Backpassing(_, _, _)
|
||||
| ast::Expr::SpaceBefore(_, _)
|
||||
|
@ -2563,9 +2573,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
|||
| ast::StrSegment::Plaintext(_) => true,
|
||||
// Disallow nested interpolation. Alternatively, we could allow it but require
|
||||
// a comment above it apologizing to the next person who has to read the code.
|
||||
ast::StrSegment::Interpolated(_) | ast::StrSegment::DeprecatedInterpolated(_) => {
|
||||
false
|
||||
}
|
||||
ast::StrSegment::Interpolated(_) => false,
|
||||
})
|
||||
}
|
||||
ast::Expr::Record(fields) => fields.iter().all(|loc_field| match loc_field.value {
|
||||
|
@ -2574,7 +2582,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
|||
| ast::AssignedField::IgnoredValue(_label, loc_comments, loc_val) => {
|
||||
loc_comments.is_empty() && is_valid_interpolation(&loc_val.value)
|
||||
}
|
||||
ast::AssignedField::Malformed(_) | ast::AssignedField::LabelOnly(_) => true,
|
||||
ast::AssignedField::LabelOnly(_) => true,
|
||||
ast::AssignedField::SpaceBefore(_, _) | ast::AssignedField::SpaceAfter(_, _) => false,
|
||||
}),
|
||||
ast::Expr::Tuple(fields) => fields
|
||||
|
@ -2625,7 +2633,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
|||
| ast::AssignedField::IgnoredValue(_label, loc_comments, loc_val) => {
|
||||
loc_comments.is_empty() && is_valid_interpolation(&loc_val.value)
|
||||
}
|
||||
ast::AssignedField::Malformed(_) | ast::AssignedField::LabelOnly(_) => true,
|
||||
ast::AssignedField::LabelOnly(_) => true,
|
||||
ast::AssignedField::SpaceBefore(_, _)
|
||||
| ast::AssignedField::SpaceAfter(_, _) => false,
|
||||
})
|
||||
|
@ -2638,7 +2646,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
|||
| ast::AssignedField::IgnoredValue(_label, loc_comments, loc_val) => {
|
||||
loc_comments.is_empty() && is_valid_interpolation(&loc_val.value)
|
||||
}
|
||||
ast::AssignedField::Malformed(_) | ast::AssignedField::LabelOnly(_) => true,
|
||||
ast::AssignedField::LabelOnly(_) => true,
|
||||
ast::AssignedField::SpaceBefore(_, _)
|
||||
| ast::AssignedField::SpaceAfter(_, _) => false,
|
||||
})
|
||||
|
@ -2696,7 +2704,7 @@ fn flatten_str_lines<'a>(
|
|||
);
|
||||
}
|
||||
},
|
||||
Interpolated(loc_expr) | DeprecatedInterpolated(loc_expr) => {
|
||||
Interpolated(loc_expr) => {
|
||||
if is_valid_interpolation(loc_expr.value) {
|
||||
// Interpolations desugar to Str.concat calls
|
||||
output.references.insert_call(Symbol::STR_CONCAT);
|
||||
|
@ -2763,6 +2771,7 @@ fn desugar_str_segments(var_store: &mut VarStore, segments: Vec<StrSegment>) ->
|
|||
fn_expr,
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
)),
|
||||
vec![
|
||||
(var_store.fresh(), empty_string),
|
||||
|
@ -2799,6 +2808,7 @@ fn desugar_str_segments(var_store: &mut VarStore, segments: Vec<StrSegment>) ->
|
|||
fn_expr,
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
)),
|
||||
vec![
|
||||
(var_store.fresh(), loc_new_expr),
|
||||
|
@ -2845,6 +2855,7 @@ impl Declarations {
|
|||
pub fn new() -> Self {
|
||||
Self::with_capacity(0)
|
||||
}
|
||||
|
||||
pub fn with_capacity(capacity: usize) -> Self {
|
||||
Self {
|
||||
declarations: Vec::with_capacity(capacity),
|
||||
|
@ -2891,6 +2902,8 @@ impl Declarations {
|
|||
let function_def = FunctionDef {
|
||||
closure_type: loc_closure_data.value.closure_type,
|
||||
return_type: loc_closure_data.value.return_type,
|
||||
fx_type: loc_closure_data.value.fx_type,
|
||||
early_returns: loc_closure_data.value.early_returns,
|
||||
captured_symbols: loc_closure_data.value.captured_symbols,
|
||||
arguments: loc_closure_data.value.arguments,
|
||||
};
|
||||
|
@ -2900,7 +2913,7 @@ impl Declarations {
|
|||
|
||||
let loc_function_def = Loc::at(loc_closure_data.region, function_def);
|
||||
|
||||
let function_def_index = Index::push_new(&mut self.function_bodies, loc_function_def);
|
||||
let function_def_index = index_push_new(&mut self.function_bodies, loc_function_def);
|
||||
|
||||
let tag = match loc_closure_data.value.recursive {
|
||||
Recursive::NotRecursive | Recursive::Recursive => {
|
||||
|
@ -2942,6 +2955,8 @@ impl Declarations {
|
|||
let function_def = FunctionDef {
|
||||
closure_type: loc_closure_data.value.closure_type,
|
||||
return_type: loc_closure_data.value.return_type,
|
||||
fx_type: loc_closure_data.value.fx_type,
|
||||
early_returns: loc_closure_data.value.early_returns,
|
||||
captured_symbols: loc_closure_data.value.captured_symbols,
|
||||
arguments: loc_closure_data.value.arguments,
|
||||
};
|
||||
|
@ -2951,7 +2966,7 @@ impl Declarations {
|
|||
|
||||
let loc_function_def = Loc::at(loc_closure_data.region, function_def);
|
||||
|
||||
let function_def_index = Index::push_new(&mut self.function_bodies, loc_function_def);
|
||||
let function_def_index = index_push_new(&mut self.function_bodies, loc_function_def);
|
||||
|
||||
if let Some(annotation) = host_annotation {
|
||||
self.host_exposed_annotations
|
||||
|
@ -2991,24 +3006,6 @@ impl Declarations {
|
|||
index
|
||||
}
|
||||
|
||||
pub fn push_expect_fx(
|
||||
&mut self,
|
||||
preceding_comment: Region,
|
||||
name: Symbol,
|
||||
loc_expr: Loc<Expr>,
|
||||
) -> usize {
|
||||
let index = self.declarations.len();
|
||||
|
||||
self.declarations.push(DeclarationTag::ExpectationFx);
|
||||
self.variables.push(Variable::BOOL);
|
||||
self.symbols.push(Loc::at(preceding_comment, name));
|
||||
self.annotations.push(None);
|
||||
|
||||
self.expressions.push(loc_expr);
|
||||
|
||||
index
|
||||
}
|
||||
|
||||
pub fn push_value_def(
|
||||
&mut self,
|
||||
symbol: Loc<Symbol>,
|
||||
|
@ -3057,7 +3054,7 @@ impl Declarations {
|
|||
pattern_vars,
|
||||
};
|
||||
|
||||
let destructure_def_index = Index::push_new(&mut self.destructs, destruct_def);
|
||||
let destructure_def_index = index_push_new(&mut self.destructs, destruct_def);
|
||||
|
||||
self.declarations
|
||||
.push(DeclarationTag::Destructure(destructure_def_index));
|
||||
|
@ -3122,6 +3119,8 @@ impl Declarations {
|
|||
let function_def = FunctionDef {
|
||||
closure_type: closure_data.closure_type,
|
||||
return_type: closure_data.return_type,
|
||||
fx_type: closure_data.fx_type,
|
||||
early_returns: closure_data.early_returns,
|
||||
captured_symbols: closure_data.captured_symbols,
|
||||
arguments: closure_data.arguments,
|
||||
};
|
||||
|
@ -3129,7 +3128,7 @@ impl Declarations {
|
|||
let loc_function_def = Loc::at(def.loc_expr.region, function_def);
|
||||
|
||||
let function_def_index =
|
||||
Index::push_new(&mut self.function_bodies, loc_function_def);
|
||||
index_push_new(&mut self.function_bodies, loc_function_def);
|
||||
|
||||
self.declarations[index] = DeclarationTag::Function(function_def_index);
|
||||
self.expressions[index] = *closure_data.loc_body;
|
||||
|
@ -3162,6 +3161,8 @@ impl Declarations {
|
|||
function_type: var_store.fresh(),
|
||||
closure_type: var_store.fresh(),
|
||||
return_type: var_store.fresh(),
|
||||
fx_type: var_store.fresh(),
|
||||
early_returns: vec![],
|
||||
name: self.symbols[index].value,
|
||||
captured_symbols: vec![],
|
||||
recursive: Recursive::NotRecursive,
|
||||
|
@ -3174,6 +3175,8 @@ impl Declarations {
|
|||
let function_def = FunctionDef {
|
||||
closure_type: loc_closure_data.value.closure_type,
|
||||
return_type: loc_closure_data.value.return_type,
|
||||
fx_type: loc_closure_data.value.fx_type,
|
||||
early_returns: loc_closure_data.value.early_returns,
|
||||
captured_symbols: loc_closure_data.value.captured_symbols,
|
||||
arguments: loc_closure_data.value.arguments,
|
||||
};
|
||||
|
@ -3181,7 +3184,7 @@ impl Declarations {
|
|||
let loc_function_def = Loc::at(region, function_def);
|
||||
|
||||
let function_def_index =
|
||||
Index::push_new(&mut self.function_bodies, loc_function_def);
|
||||
index_push_new(&mut self.function_bodies, loc_function_def);
|
||||
|
||||
if let Some(annotation) = &mut self.annotations[index] {
|
||||
annotation.convert_to_fn(new_args_len, var_store);
|
||||
|
@ -3255,12 +3258,6 @@ impl Declarations {
|
|||
|
||||
collector.visit_expr(&loc_expr.value, loc_expr.region, var);
|
||||
}
|
||||
ExpectationFx => {
|
||||
let loc_expr =
|
||||
toplevel_expect_to_inline_expect_fx(self.expressions[index].clone());
|
||||
|
||||
collector.visit_expr(&loc_expr.value, loc_expr.region, var);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3279,7 +3276,6 @@ roc_error_macros::assert_sizeof_default!(DeclarationTag, 8);
|
|||
pub enum DeclarationTag {
|
||||
Value,
|
||||
Expectation,
|
||||
ExpectationFx,
|
||||
Function(Index<Loc<FunctionDef>>),
|
||||
Recursive(Index<Loc<FunctionDef>>),
|
||||
TailRecursive(Index<Loc<FunctionDef>>),
|
||||
|
@ -3297,7 +3293,7 @@ impl DeclarationTag {
|
|||
match self {
|
||||
Function(_) | Recursive(_) | TailRecursive(_) => 1,
|
||||
Value => 1,
|
||||
Expectation | ExpectationFx => 1,
|
||||
Expectation => 1,
|
||||
Destructure(_) => 1,
|
||||
MutualRecursion { length, .. } => length as usize + 1,
|
||||
}
|
||||
|
@ -3308,6 +3304,8 @@ impl DeclarationTag {
|
|||
pub struct FunctionDef {
|
||||
pub closure_type: Variable,
|
||||
pub return_type: Variable,
|
||||
pub fx_type: Variable,
|
||||
pub early_returns: Vec<(Variable, Region)>,
|
||||
pub captured_symbols: Vec<(Symbol, Variable)>,
|
||||
pub arguments: Vec<(Variable, AnnotatedMark, Loc<Pattern>)>,
|
||||
}
|
||||
|
@ -3441,9 +3439,6 @@ pub(crate) fn get_lookup_symbols(expr: &Expr) -> Vec<ExpectLookup> {
|
|||
Expr::Expect {
|
||||
loc_continuation, ..
|
||||
}
|
||||
| Expr::ExpectFx {
|
||||
loc_continuation, ..
|
||||
}
|
||||
| Expr::Dbg {
|
||||
loc_continuation, ..
|
||||
} => {
|
||||
|
@ -3452,6 +3447,9 @@ pub(crate) fn get_lookup_symbols(expr: &Expr) -> Vec<ExpectLookup> {
|
|||
// Intentionally ignore the lookups in the nested `expect` condition itself,
|
||||
// because they couldn't possibly influence the outcome of this `expect`!
|
||||
}
|
||||
Expr::Return { return_value, .. } => {
|
||||
stack.push(&return_value.value);
|
||||
}
|
||||
Expr::Crash { msg, .. } => stack.push(&msg.value),
|
||||
Expr::Num(_, _, _, _)
|
||||
| Expr::Float(_, _, _, _, _)
|
||||
|
@ -3496,15 +3494,7 @@ pub(crate) fn get_lookup_symbols(expr: &Expr) -> Vec<ExpectLookup> {
|
|||
/// This is supposed to happen just before monomorphization:
|
||||
/// all type errors and such are generated from the user source,
|
||||
/// but this transformation means that we don't need special codegen for toplevel expects
|
||||
pub fn toplevel_expect_to_inline_expect_pure(loc_expr: Loc<Expr>) -> Loc<Expr> {
|
||||
toplevel_expect_to_inline_expect_help(loc_expr, false)
|
||||
}
|
||||
|
||||
pub fn toplevel_expect_to_inline_expect_fx(loc_expr: Loc<Expr>) -> Loc<Expr> {
|
||||
toplevel_expect_to_inline_expect_help(loc_expr, true)
|
||||
}
|
||||
|
||||
fn toplevel_expect_to_inline_expect_help(mut loc_expr: Loc<Expr>, has_effects: bool) -> Loc<Expr> {
|
||||
pub fn toplevel_expect_to_inline_expect_pure(mut loc_expr: Loc<Expr>) -> Loc<Expr> {
|
||||
enum StoredDef {
|
||||
NonRecursive(Region, Box<Def>),
|
||||
Recursive(Region, Vec<Def>, IllegalCycleMark),
|
||||
|
@ -3542,18 +3532,10 @@ fn toplevel_expect_to_inline_expect_help(mut loc_expr: Loc<Expr>, has_effects: b
|
|||
}
|
||||
|
||||
let expect_region = loc_expr.region;
|
||||
let expect = if has_effects {
|
||||
Expr::ExpectFx {
|
||||
loc_condition: Box::new(loc_expr),
|
||||
loc_continuation: Box::new(Loc::at_zero(Expr::EmptyRecord)),
|
||||
lookups_in_cond,
|
||||
}
|
||||
} else {
|
||||
Expr::Expect {
|
||||
loc_condition: Box::new(loc_expr),
|
||||
loc_continuation: Box::new(Loc::at_zero(Expr::EmptyRecord)),
|
||||
lookups_in_cond,
|
||||
}
|
||||
let expect = Expr::Expect {
|
||||
loc_condition: Box::new(loc_expr),
|
||||
loc_continuation: Box::new(Loc::at_zero(Expr::EmptyRecord)),
|
||||
lookups_in_cond,
|
||||
};
|
||||
|
||||
let mut loc_expr = Loc::at(expect_region, expect);
|
||||
|
@ -3585,11 +3567,6 @@ impl crate::traverse::Visitor for ExpectCollector {
|
|||
lookups_in_cond,
|
||||
loc_condition,
|
||||
..
|
||||
}
|
||||
| Expr::ExpectFx {
|
||||
lookups_in_cond,
|
||||
loc_condition,
|
||||
..
|
||||
} => {
|
||||
self.expects
|
||||
.insert(loc_condition.region, lookups_in_cond.to_vec());
|
||||
|
|
|
@ -14,6 +14,7 @@ pub mod copy;
|
|||
pub mod def;
|
||||
mod derive;
|
||||
pub mod desugar;
|
||||
pub mod effect_module;
|
||||
pub mod env;
|
||||
pub mod exhaustive;
|
||||
pub mod expected;
|
||||
|
@ -25,7 +26,6 @@ pub mod procedure;
|
|||
pub mod scope;
|
||||
pub mod string;
|
||||
pub mod suffixed;
|
||||
pub mod task_module;
|
||||
pub mod traverse;
|
||||
|
||||
pub use derive::DERIVED_REGION;
|
||||
|
|
|
@ -2,9 +2,9 @@ use std::path::Path;
|
|||
|
||||
use crate::abilities::{AbilitiesStore, ImplKey, PendingAbilitiesStore, ResolvedImpl};
|
||||
use crate::annotation::{canonicalize_annotation, AnnotationFor};
|
||||
use crate::def::{canonicalize_defs, report_unused_imports, Def};
|
||||
use crate::def::{canonicalize_defs, report_unused_imports, Def, DefKind};
|
||||
use crate::desugar::desugar_record_destructures;
|
||||
use crate::env::Env;
|
||||
use crate::env::{Env, FxMode};
|
||||
use crate::expr::{
|
||||
ClosureData, DbgLookup, Declarations, ExpectLookup, Expr, Output, PendingDerives,
|
||||
};
|
||||
|
@ -226,6 +226,7 @@ pub fn canonicalize_module_defs<'a>(
|
|||
symbols_from_requires: &[(Loc<Symbol>, Loc<TypeAnnotation<'a>>)],
|
||||
var_store: &mut VarStore,
|
||||
opt_shorthand: Option<&'a str>,
|
||||
fx_mode: FxMode,
|
||||
) -> ModuleOutput {
|
||||
let mut can_exposed_imports = MutMap::default();
|
||||
|
||||
|
@ -247,6 +248,7 @@ pub fn canonicalize_module_defs<'a>(
|
|||
dep_idents,
|
||||
qualified_module_ids,
|
||||
opt_shorthand,
|
||||
fx_mode,
|
||||
);
|
||||
|
||||
for (name, alias) in aliases.into_iter() {
|
||||
|
@ -369,6 +371,12 @@ pub fn canonicalize_module_defs<'a>(
|
|||
PatternType::TopLevelDef,
|
||||
);
|
||||
|
||||
for (_early_return_var, early_return_region) in &scope.early_returns {
|
||||
env.problem(Problem::ReturnOutsideOfFunction {
|
||||
region: *early_return_region,
|
||||
});
|
||||
}
|
||||
|
||||
let pending_derives = output.pending_derives;
|
||||
|
||||
// See if any of the new idents we defined went unused.
|
||||
|
@ -425,7 +433,7 @@ pub fn canonicalize_module_defs<'a>(
|
|||
..Default::default()
|
||||
};
|
||||
|
||||
let (mut declarations, mut output) = crate::def::sort_can_defs_new(
|
||||
let (mut declarations, mut output) = crate::def::sort_top_level_can_defs(
|
||||
&mut env,
|
||||
&mut scope,
|
||||
var_store,
|
||||
|
@ -527,7 +535,7 @@ pub fn canonicalize_module_defs<'a>(
|
|||
aliases: Default::default(),
|
||||
};
|
||||
|
||||
let hosted_def = crate::task_module::build_host_exposed_def(
|
||||
let hosted_def = crate::effect_module::build_host_exposed_def(
|
||||
&mut scope, *symbol, &ident, var_store, annotation,
|
||||
);
|
||||
|
||||
|
@ -580,7 +588,7 @@ pub fn canonicalize_module_defs<'a>(
|
|||
aliases: Default::default(),
|
||||
};
|
||||
|
||||
let hosted_def = crate::task_module::build_host_exposed_def(
|
||||
let hosted_def = crate::effect_module::build_host_exposed_def(
|
||||
&mut scope, *symbol, &ident, var_store, annotation,
|
||||
);
|
||||
|
||||
|
@ -601,7 +609,6 @@ pub fn canonicalize_module_defs<'a>(
|
|||
// the declarations of this group will be treaded individually by later iterations
|
||||
}
|
||||
Expectation => { /* ignore */ }
|
||||
ExpectationFx => { /* ignore */ }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -649,6 +656,7 @@ pub fn canonicalize_module_defs<'a>(
|
|||
expr_var: var_store.fresh(),
|
||||
pattern_vars,
|
||||
annotation: None,
|
||||
kind: DefKind::Let,
|
||||
};
|
||||
|
||||
declarations.push_def(def);
|
||||
|
@ -738,14 +746,6 @@ pub fn canonicalize_module_defs<'a>(
|
|||
&mut fix_closures_closure_captures,
|
||||
);
|
||||
}
|
||||
ExpectationFx => {
|
||||
let loc_expr = &mut declarations.expressions[index];
|
||||
fix_values_captured_in_closure_expr(
|
||||
&mut loc_expr.value,
|
||||
&mut fix_closures_no_capture_symbols,
|
||||
&mut fix_closures_closure_captures,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -947,11 +947,6 @@ fn fix_values_captured_in_closure_expr(
|
|||
loc_continuation,
|
||||
..
|
||||
}
|
||||
| ExpectFx {
|
||||
loc_condition,
|
||||
loc_continuation,
|
||||
..
|
||||
}
|
||||
| Dbg {
|
||||
loc_message: loc_condition,
|
||||
loc_continuation,
|
||||
|
@ -969,6 +964,14 @@ fn fix_values_captured_in_closure_expr(
|
|||
);
|
||||
}
|
||||
|
||||
Return { return_value, .. } => {
|
||||
fix_values_captured_in_closure_expr(
|
||||
&mut return_value.value,
|
||||
no_capture_symbols,
|
||||
closure_captures,
|
||||
);
|
||||
}
|
||||
|
||||
Crash { msg, ret_var: _ } => {
|
||||
fix_values_captured_in_closure_expr(
|
||||
&mut msg.value,
|
||||
|
|
|
@ -1110,7 +1110,7 @@ fn flatten_str_lines(lines: &[&[StrSegment<'_>]]) -> Pattern {
|
|||
Unicode(loc_digits) => {
|
||||
todo!("parse unicode digits {:?}", loc_digits);
|
||||
}
|
||||
Interpolated(loc_expr) | DeprecatedInterpolated(loc_expr) => {
|
||||
Interpolated(loc_expr) => {
|
||||
return Pattern::UnsupportedPattern(loc_expr.region);
|
||||
}
|
||||
EscapedChar(escaped) => buf.push(escaped.unescape()),
|
||||
|
|
|
@ -48,6 +48,8 @@ pub struct Scope {
|
|||
/// Ignored variables (variables that start with an underscore).
|
||||
/// We won't intern them because they're only used during canonicalization for error reporting.
|
||||
ignored_locals: VecMap<String, Region>,
|
||||
|
||||
pub early_returns: Vec<(Variable, Region)>,
|
||||
}
|
||||
|
||||
impl Scope {
|
||||
|
@ -73,6 +75,7 @@ impl Scope {
|
|||
modules: ScopeModules::new(home, module_name),
|
||||
imported_symbols: default_imports,
|
||||
ignored_locals: VecMap::default(),
|
||||
early_returns: Vec::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -429,7 +432,8 @@ impl Scope {
|
|||
self.aliases.contains_key(&name)
|
||||
}
|
||||
|
||||
pub fn inner_scope<F, T>(&mut self, f: F) -> T
|
||||
/// Enter an inner scope within a definition, e.g. a def or when block.
|
||||
pub fn inner_def_scope<F, T>(&mut self, f: F) -> T
|
||||
where
|
||||
F: FnOnce(&mut Scope) -> T,
|
||||
{
|
||||
|
@ -462,6 +466,20 @@ impl Scope {
|
|||
result
|
||||
}
|
||||
|
||||
/// Enter an inner scope within a child function, e.g. a closure body.
|
||||
pub fn inner_function_scope<F, T>(&mut self, f: F) -> T
|
||||
where
|
||||
F: FnOnce(&mut Scope) -> T,
|
||||
{
|
||||
let early_returns_snapshot = std::mem::take(&mut self.early_returns);
|
||||
|
||||
let result = self.inner_def_scope(f);
|
||||
|
||||
self.early_returns = early_returns_snapshot;
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn register_debug_idents(&self) {
|
||||
self.home.register_debug_idents(&self.locals.ident_ids)
|
||||
}
|
||||
|
@ -868,7 +886,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn inner_scope_does_not_influence_outer() {
|
||||
fn inner_def_scope_does_not_influence_outer() {
|
||||
let _register_module_debug_names = ModuleIds::default();
|
||||
let mut scope = Scope::new(
|
||||
ModuleId::ATTR,
|
||||
|
@ -882,7 +900,7 @@ mod test {
|
|||
|
||||
assert!(scope.lookup(&ident, region).is_err());
|
||||
|
||||
scope.inner_scope(|inner| {
|
||||
scope.inner_def_scope(|inner| {
|
||||
assert!(inner.introduce(ident.clone(), region).is_ok());
|
||||
});
|
||||
|
||||
|
@ -908,7 +926,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn idents_with_inner_scope() {
|
||||
fn idents_with_inner_def_scope() {
|
||||
let _register_module_debug_names = ModuleIds::default();
|
||||
let mut scope = Scope::new(
|
||||
ModuleId::ATTR,
|
||||
|
@ -943,7 +961,7 @@ mod test {
|
|||
&[ident1.clone(), ident2.clone(), ident3.clone(),]
|
||||
);
|
||||
|
||||
scope.inner_scope(|inner| {
|
||||
scope.inner_def_scope(|inner| {
|
||||
let ident4 = Ident::from("Ångström");
|
||||
let ident5 = Ident::from("Sirály");
|
||||
|
||||
|
|
|
@ -155,49 +155,6 @@ pub fn unwrap_suffixed_expression<'a>(
|
|||
|
||||
Expr::LowLevelDbg(..) => unwrap_low_level_dbg(arena, loc_expr, maybe_def_pat),
|
||||
|
||||
Expr::Expect(condition, continuation) => {
|
||||
if is_expr_suffixed(&condition.value) {
|
||||
// we cannot unwrap a suffixed expression within expect
|
||||
// e.g. expect (foo! "bar")
|
||||
return Err(EUnwrapped::Malformed);
|
||||
}
|
||||
|
||||
match unwrap_suffixed_expression(arena, continuation, maybe_def_pat) {
|
||||
Ok(unwrapped_expr) => {
|
||||
let new_expect = arena
|
||||
.alloc(Loc::at(loc_expr.region, Expect(condition, unwrapped_expr)));
|
||||
return Ok(new_expect);
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr {
|
||||
loc_expr: unwrapped_expr,
|
||||
target,
|
||||
}) => {
|
||||
let new_expect = arena
|
||||
.alloc(Loc::at(loc_expr.region, Expect(condition, unwrapped_expr)));
|
||||
Err(EUnwrapped::UnwrappedDefExpr {
|
||||
loc_expr: new_expect,
|
||||
target,
|
||||
})
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedSubExpr {
|
||||
sub_arg: unwrapped_expr,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
target,
|
||||
}) => {
|
||||
let new_expect = arena
|
||||
.alloc(Loc::at(loc_expr.region, Expect(condition, unwrapped_expr)));
|
||||
Err(EUnwrapped::UnwrappedSubExpr {
|
||||
sub_arg: new_expect,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
target,
|
||||
})
|
||||
}
|
||||
Err(EUnwrapped::Malformed) => Err(EUnwrapped::Malformed),
|
||||
}
|
||||
}
|
||||
|
||||
// we only need to unwrap some expressions, leave the rest as is
|
||||
_ => Ok(loc_expr),
|
||||
}
|
||||
|
@ -325,7 +282,14 @@ pub fn unwrap_suffixed_expression_apply_help<'a>(
|
|||
|
||||
let new_apply = arena.alloc(Loc::at(loc_expr.region, Expr::Apply(unwrapped_function, local_args, called_via)));
|
||||
|
||||
return init_unwrapped_err(arena, new_apply, maybe_def_pat, target);
|
||||
match maybe_def_pat {
|
||||
Some(..) => {
|
||||
return Err(EUnwrapped::UnwrappedDefExpr { loc_expr: new_apply, target });
|
||||
}
|
||||
None => {
|
||||
return init_unwrapped_err(arena, new_apply, maybe_def_pat, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// function is another expression
|
||||
|
@ -673,9 +637,10 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
|
|||
};
|
||||
|
||||
let maybe_suffixed_value_def = match current_value_def {
|
||||
Annotation(..) | Dbg{..} | Expect{..} | ExpectFx{..} | Stmt(..) | ModuleImport{..} | IngestedFileImport(_) => None,
|
||||
Annotation(..) | Dbg{..} | Expect{..} | Stmt(..) | ModuleImport{..} | IngestedFileImport(_) => None,
|
||||
AnnotatedBody { body_pattern, body_expr, ann_type, ann_pattern, .. } => Some((body_pattern, body_expr, Some((ann_pattern, ann_type)))),
|
||||
Body (def_pattern, def_expr) => Some((def_pattern, def_expr, None)),
|
||||
StmtAfterExpr => None,
|
||||
};
|
||||
|
||||
match maybe_suffixed_value_def {
|
||||
|
|
|
@ -22,6 +22,10 @@ pub enum DeclarationInfo<'a> {
|
|||
pattern: Pattern,
|
||||
annotation: Option<&'a Annotation>,
|
||||
},
|
||||
Return {
|
||||
loc_expr: &'a Loc<Expr>,
|
||||
expr_var: Variable,
|
||||
},
|
||||
Expectation {
|
||||
loc_condition: &'a Loc<Expr>,
|
||||
},
|
||||
|
@ -50,6 +54,7 @@ impl<'a> DeclarationInfo<'a> {
|
|||
loc_expr,
|
||||
..
|
||||
} => Region::span_across(&loc_symbol.region, &loc_expr.region),
|
||||
Return { loc_expr, .. } => loc_expr.region,
|
||||
Expectation { loc_condition } => loc_condition.region,
|
||||
Function {
|
||||
loc_symbol,
|
||||
|
@ -67,6 +72,7 @@ impl<'a> DeclarationInfo<'a> {
|
|||
fn var(&self) -> Variable {
|
||||
match self {
|
||||
DeclarationInfo::Value { expr_var, .. } => *expr_var,
|
||||
DeclarationInfo::Return { expr_var, .. } => *expr_var,
|
||||
DeclarationInfo::Expectation { .. } => Variable::BOOL,
|
||||
DeclarationInfo::Function { expr_var, .. } => *expr_var,
|
||||
DeclarationInfo::Destructure { expr_var, .. } => *expr_var,
|
||||
|
@ -101,7 +107,7 @@ pub fn walk_decls<V: Visitor>(visitor: &mut V, decls: &Declarations) {
|
|||
annotation: decls.annotations[index].as_ref(),
|
||||
}
|
||||
}
|
||||
Expectation | ExpectationFx => {
|
||||
Expectation => {
|
||||
let loc_condition = &decls.expressions[index];
|
||||
|
||||
DeclarationInfo::Expectation { loc_condition }
|
||||
|
@ -185,6 +191,9 @@ pub fn walk_decl<V: Visitor>(visitor: &mut V, decl: DeclarationInfo<'_>) {
|
|||
Expectation { loc_condition } => {
|
||||
visitor.visit_expr(&loc_condition.value, loc_condition.region, Variable::BOOL);
|
||||
}
|
||||
Return { loc_expr, expr_var } => {
|
||||
visitor.visit_expr(&loc_expr.value, loc_expr.region, expr_var);
|
||||
}
|
||||
Function {
|
||||
loc_symbol,
|
||||
loc_body,
|
||||
|
@ -283,7 +292,7 @@ pub fn walk_expr<V: Visitor>(visitor: &mut V, expr: &Expr, var: Variable) {
|
|||
visitor.visit_expr(&body.value, body.region, var);
|
||||
}
|
||||
Expr::Call(f, args, _called_via) => {
|
||||
let (fn_var, loc_fn, _closure_var, _ret_var) = &**f;
|
||||
let (fn_var, loc_fn, _closure_var, _ret_var, _fx_var) = &**f;
|
||||
walk_call(visitor, *fn_var, loc_fn, args);
|
||||
}
|
||||
Expr::Crash { msg, .. } => {
|
||||
|
@ -376,18 +385,6 @@ pub fn walk_expr<V: Visitor>(visitor: &mut V, expr: &Expr, var: Variable) {
|
|||
Variable::NULL,
|
||||
);
|
||||
}
|
||||
Expr::ExpectFx {
|
||||
loc_condition,
|
||||
loc_continuation,
|
||||
lookups_in_cond: _,
|
||||
} => {
|
||||
visitor.visit_expr(&loc_condition.value, loc_condition.region, Variable::BOOL);
|
||||
visitor.visit_expr(
|
||||
&loc_continuation.value,
|
||||
loc_continuation.region,
|
||||
Variable::NULL,
|
||||
);
|
||||
}
|
||||
Expr::Dbg {
|
||||
variable,
|
||||
source: _,
|
||||
|
@ -403,6 +400,12 @@ pub fn walk_expr<V: Visitor>(visitor: &mut V, expr: &Expr, var: Variable) {
|
|||
Variable::NULL,
|
||||
);
|
||||
}
|
||||
Expr::Return {
|
||||
return_value,
|
||||
return_var,
|
||||
} => {
|
||||
visitor.visit_expr(&return_value.value, return_value.region, *return_var);
|
||||
}
|
||||
Expr::TypedHole(_) => { /* terminal */ }
|
||||
Expr::RuntimeError(..) => { /* terminal */ }
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut
|
|||
&dep_idents,
|
||||
&qualified_module_ids,
|
||||
None,
|
||||
roc_can::env::FxMode::PurityInference,
|
||||
);
|
||||
|
||||
// Desugar operators (convert them to Apply calls, taking into account
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-28,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -59,16 +60,16 @@ Defs {
|
|||
@15-22 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@15-22,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-25,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -43,16 +44,16 @@ Defs {
|
|||
@15-19 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@15-19,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-43,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -53,16 +54,16 @@ Defs {
|
|||
@15-33 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@15-33,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-45,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -53,16 +54,16 @@ Defs {
|
|||
@15-35 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@15-35,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-28,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -43,16 +44,16 @@ Defs {
|
|||
@15-22 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@15-22,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-26,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -24,25 +25,25 @@ Defs {
|
|||
@0-4 Identifier {
|
||||
ident: "main",
|
||||
},
|
||||
@11-15 Apply(
|
||||
@11-15 Var {
|
||||
@11-14 Apply(
|
||||
@11-14 Var {
|
||||
module_name: "Task",
|
||||
ident: "await",
|
||||
},
|
||||
[
|
||||
@11-15 Defs(
|
||||
@11-14 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@11-15,
|
||||
@11-14,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -66,19 +67,19 @@ Defs {
|
|||
body_pattern: @11-15 Identifier {
|
||||
ident: "#!0_stmt",
|
||||
},
|
||||
body_expr: @11-15 Var {
|
||||
body_expr: @11-14 Var {
|
||||
module_name: "",
|
||||
ident: "foo",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@11-15 Var {
|
||||
@11-14 Var {
|
||||
module_name: "",
|
||||
ident: "#!0_stmt",
|
||||
},
|
||||
),
|
||||
@11-15 Closure(
|
||||
@11-14 Closure(
|
||||
[
|
||||
@11-15 Underscore(
|
||||
"#!stmt",
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-42,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -43,16 +44,16 @@ Defs {
|
|||
@16-35 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@16-35,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-69,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -27,16 +28,16 @@ Defs {
|
|||
@11-69 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@15-57,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -51,25 +52,25 @@ Defs {
|
|||
ident: "msg",
|
||||
},
|
||||
],
|
||||
@31-42 Apply(
|
||||
@31-42 Var {
|
||||
@31-43 Apply(
|
||||
@31-43 Var {
|
||||
module_name: "Task",
|
||||
ident: "await",
|
||||
},
|
||||
[
|
||||
@31-42 Defs(
|
||||
@31-43 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@31-42,
|
||||
@31-43,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -93,8 +94,8 @@ Defs {
|
|||
body_pattern: @31-43 Identifier {
|
||||
ident: "#!0_stmt",
|
||||
},
|
||||
body_expr: @31-42 Apply(
|
||||
@31-42 Var {
|
||||
body_expr: @31-43 Apply(
|
||||
@31-43 Var {
|
||||
module_name: "",
|
||||
ident: "line",
|
||||
},
|
||||
|
@ -111,12 +112,12 @@ Defs {
|
|||
},
|
||||
],
|
||||
},
|
||||
@31-42 Var {
|
||||
@31-43 Var {
|
||||
module_name: "",
|
||||
ident: "#!0_stmt",
|
||||
},
|
||||
),
|
||||
@31-42 Closure(
|
||||
@31-43 Closure(
|
||||
[
|
||||
@31-43 Underscore(
|
||||
"#!stmt",
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-114,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -27,16 +28,16 @@ Defs {
|
|||
@11-114 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@39-101,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -53,6 +54,7 @@ Defs {
|
|||
[],
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@22-30 Apply(
|
||||
"",
|
||||
"Task",
|
||||
|
@ -77,16 +79,16 @@ Defs {
|
|||
@56-91 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@82-91,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-143,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -27,16 +28,16 @@ Defs {
|
|||
@12-143 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@56-119,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -62,6 +63,7 @@ Defs {
|
|||
[],
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@34-45 Apply(
|
||||
"",
|
||||
"Task",
|
||||
|
@ -105,16 +107,16 @@ Defs {
|
|||
@76-83 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@76-83,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -174,16 +176,16 @@ Defs {
|
|||
@92-99 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@92-99,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
assertion_line: 463
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-26,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -28,16 +28,16 @@ Defs {
|
|||
@11-26 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@15-26,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -50,16 +50,16 @@ Defs {
|
|||
Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@20-25,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-49,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -24,17 +25,17 @@ Defs {
|
|||
@0-4 Identifier {
|
||||
ident: "main",
|
||||
},
|
||||
@17-24 Apply(
|
||||
@17-24 Var {
|
||||
@17-23 Apply(
|
||||
@17-23 Var {
|
||||
module_name: "Task",
|
||||
ident: "await",
|
||||
},
|
||||
[
|
||||
@17-24 Var {
|
||||
@17-23 Var {
|
||||
module_name: "",
|
||||
ident: "getFoo",
|
||||
},
|
||||
@17-24 Closure(
|
||||
@17-23 Closure(
|
||||
[
|
||||
@11-14 Identifier {
|
||||
ident: "foo",
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-24,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -30,28 +31,28 @@ Defs {
|
|||
ident: "await",
|
||||
},
|
||||
[
|
||||
@15-17 Var {
|
||||
@15-16 Var {
|
||||
module_name: "",
|
||||
ident: "a",
|
||||
},
|
||||
@11-17 Closure(
|
||||
[
|
||||
@15-17 Identifier {
|
||||
@15-16 Identifier {
|
||||
ident: "#!0_arg",
|
||||
},
|
||||
],
|
||||
@11-17 LowLevelDbg(
|
||||
(
|
||||
"test.roc:2",
|
||||
"in",
|
||||
"i",
|
||||
),
|
||||
@15-17 Apply(
|
||||
@15-17 Var {
|
||||
@15-16 Apply(
|
||||
@15-16 Var {
|
||||
module_name: "Inspect",
|
||||
ident: "toStr",
|
||||
},
|
||||
[
|
||||
@15-17 Var {
|
||||
@15-16 Var {
|
||||
module_name: "",
|
||||
ident: "#!0_arg",
|
||||
},
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-99,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -48,7 +49,7 @@ Defs {
|
|||
"1",
|
||||
),
|
||||
],
|
||||
value: @97-99 Var {
|
||||
value: @97-98 Var {
|
||||
module_name: "",
|
||||
ident: "c",
|
||||
},
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
Index(2147483649),
|
||||
EitherIndex(2147483648),
|
||||
EitherIndex(2147483649),
|
||||
],
|
||||
regions: [
|
||||
@0-54,
|
||||
@56-98,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice(start = 0, length = 2),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 2 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice(start = 2, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 2, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -33,16 +34,16 @@ Defs {
|
|||
@11-54 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@15-20,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -68,16 +69,16 @@ Defs {
|
|||
@25-39 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@25-39,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -128,7 +129,7 @@ Defs {
|
|||
"#!stmt",
|
||||
),
|
||||
],
|
||||
@45-54 Var {
|
||||
@45-53 Var {
|
||||
module_name: "",
|
||||
ident: "printBar",
|
||||
},
|
||||
|
@ -145,16 +146,16 @@ Defs {
|
|||
@71-98 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@75-80,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-158,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -39,16 +40,16 @@ Defs {
|
|||
value: @46-130 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@50-52,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -70,13 +71,13 @@ Defs {
|
|||
module_name: "",
|
||||
ident: "a",
|
||||
},
|
||||
@92-94 Var {
|
||||
@92-93 Var {
|
||||
module_name: "",
|
||||
ident: "b",
|
||||
},
|
||||
),
|
||||
],
|
||||
final_else: @128-130 Var {
|
||||
final_else: @128-129 Var {
|
||||
module_name: "",
|
||||
ident: "c",
|
||||
},
|
||||
|
@ -91,7 +92,7 @@ Defs {
|
|||
"B",
|
||||
),
|
||||
],
|
||||
value: @156-158 Var {
|
||||
value: @156-157 Var {
|
||||
module_name: "",
|
||||
ident: "d",
|
||||
},
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-31,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -27,16 +28,16 @@ Defs {
|
|||
@11-31 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@11-24,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -63,7 +64,7 @@ Defs {
|
|||
},
|
||||
],
|
||||
},
|
||||
@29-31 Var {
|
||||
@29-30 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
},
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-307,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -27,9 +28,9 @@ Defs {
|
|||
@11-307 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
Index(2147483649),
|
||||
Index(2147483650),
|
||||
EitherIndex(2147483648),
|
||||
EitherIndex(2147483649),
|
||||
EitherIndex(2147483650),
|
||||
],
|
||||
regions: [
|
||||
@20-37,
|
||||
|
@ -37,14 +38,14 @@ Defs {
|
|||
@109-298,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice(start = 0, length = 1),
|
||||
Slice(start = 1, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 1, length: 1 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice(start = 1, length = 0),
|
||||
Slice(start = 2, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 1, length: 0 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 2, length: 0 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -165,16 +166,16 @@ Defs {
|
|||
@140-152 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@140-152,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -287,16 +288,16 @@ Defs {
|
|||
@227-239 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@227-239,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-189,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -27,20 +28,20 @@ Defs {
|
|||
@11-189 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
Index(2147483649),
|
||||
EitherIndex(2147483648),
|
||||
EitherIndex(2147483649),
|
||||
],
|
||||
regions: [
|
||||
@20-37,
|
||||
@52-70,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice(start = 1, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 1, length: 0 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -85,26 +86,26 @@ Defs {
|
|||
),
|
||||
],
|
||||
},
|
||||
@79-87 Apply(
|
||||
@79-87 Var {
|
||||
@79-86 Apply(
|
||||
@79-86 Var {
|
||||
module_name: "Task",
|
||||
ident: "await",
|
||||
},
|
||||
[
|
||||
@79-87 Var {
|
||||
@79-86 Var {
|
||||
module_name: "",
|
||||
ident: "isFalse",
|
||||
},
|
||||
@79-87 Closure(
|
||||
@79-86 Closure(
|
||||
[
|
||||
@79-87 Identifier {
|
||||
@79-86 Identifier {
|
||||
ident: "#!0_arg",
|
||||
},
|
||||
],
|
||||
@76-189 If {
|
||||
if_thens: [
|
||||
(
|
||||
@79-87 Var {
|
||||
@79-86 Var {
|
||||
module_name: "",
|
||||
ident: "#!0_arg",
|
||||
},
|
||||
|
@ -124,26 +125,26 @@ Defs {
|
|||
),
|
||||
),
|
||||
],
|
||||
final_else: @125-132 Apply(
|
||||
@125-132 Var {
|
||||
final_else: @125-131 Apply(
|
||||
@125-131 Var {
|
||||
module_name: "Task",
|
||||
ident: "await",
|
||||
},
|
||||
[
|
||||
@125-132 Var {
|
||||
@125-131 Var {
|
||||
module_name: "",
|
||||
ident: "isTrue",
|
||||
},
|
||||
@125-132 Closure(
|
||||
@125-131 Closure(
|
||||
[
|
||||
@125-132 Identifier {
|
||||
@125-131 Identifier {
|
||||
ident: "#!1_arg",
|
||||
},
|
||||
],
|
||||
@76-189 If {
|
||||
if_thens: [
|
||||
(
|
||||
@125-132 Var {
|
||||
@125-131 Var {
|
||||
module_name: "",
|
||||
ident: "#!1_arg",
|
||||
},
|
||||
|
|
|
@ -0,0 +1,290 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
EitherIndex(2147483648),
|
||||
EitherIndex(2147483649),
|
||||
EitherIndex(2147483650),
|
||||
],
|
||||
regions: [
|
||||
@0-80,
|
||||
@82-227,
|
||||
@229-266,
|
||||
],
|
||||
space_before: [
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 2 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 2, length: 2 },
|
||||
],
|
||||
space_after: [
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 2, length: 0 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 4, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
Body(
|
||||
@0-3 Identifier {
|
||||
ident: "inc",
|
||||
},
|
||||
@6-80 Closure(
|
||||
[
|
||||
@7-8 Identifier {
|
||||
ident: "i",
|
||||
},
|
||||
],
|
||||
@16-80 If {
|
||||
if_thens: [
|
||||
(
|
||||
@19-24 Apply(
|
||||
@21-22 Var {
|
||||
module_name: "Num",
|
||||
ident: "isGt",
|
||||
},
|
||||
[
|
||||
@19-20 Var {
|
||||
module_name: "",
|
||||
ident: "i",
|
||||
},
|
||||
@23-24 Num(
|
||||
"2",
|
||||
),
|
||||
],
|
||||
BinOp(
|
||||
GreaterThan,
|
||||
),
|
||||
),
|
||||
@38-52 Apply(
|
||||
@38-41 Tag(
|
||||
"Err",
|
||||
),
|
||||
[
|
||||
@42-52 Tag(
|
||||
"MaxReached",
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
),
|
||||
],
|
||||
final_else: @70-80 Apply(
|
||||
@70-72 Tag(
|
||||
"Ok",
|
||||
),
|
||||
[
|
||||
@74-79 ParensAround(
|
||||
Apply(
|
||||
@76-77 Var {
|
||||
module_name: "Num",
|
||||
ident: "add",
|
||||
},
|
||||
[
|
||||
@74-75 Var {
|
||||
module_name: "",
|
||||
ident: "i",
|
||||
},
|
||||
@78-79 Num(
|
||||
"1",
|
||||
),
|
||||
],
|
||||
BinOp(
|
||||
Plus,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
indented_else: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
Expect {
|
||||
condition: @93-227 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
EitherIndex(2147483648),
|
||||
EitherIndex(2147483649),
|
||||
],
|
||||
regions: [
|
||||
@99-189,
|
||||
@203-208,
|
||||
],
|
||||
space_before: [
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
space_after: [
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 1, length: 0 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
Body(
|
||||
@93-96 Identifier {
|
||||
ident: "run",
|
||||
},
|
||||
@99-189 Closure(
|
||||
[
|
||||
@100-101 Identifier {
|
||||
ident: "i",
|
||||
},
|
||||
],
|
||||
@132-172 Apply(
|
||||
@132-172 Var {
|
||||
module_name: "Result",
|
||||
ident: "try",
|
||||
},
|
||||
[
|
||||
@132-152 Apply(
|
||||
@132-152 Var {
|
||||
module_name: "",
|
||||
ident: "inc",
|
||||
},
|
||||
[
|
||||
@132-133 Var {
|
||||
module_name: "",
|
||||
ident: "i",
|
||||
},
|
||||
],
|
||||
BinOp(
|
||||
Pizza,
|
||||
),
|
||||
),
|
||||
@132-172 Closure(
|
||||
[
|
||||
@132-152 Identifier {
|
||||
ident: "#!0_arg",
|
||||
},
|
||||
],
|
||||
@132-172 Apply(
|
||||
@132-172 Var {
|
||||
module_name: "Result",
|
||||
ident: "try",
|
||||
},
|
||||
[
|
||||
@132-172 Apply(
|
||||
@132-172 Var {
|
||||
module_name: "",
|
||||
ident: "inc",
|
||||
},
|
||||
[
|
||||
@132-152 Var {
|
||||
module_name: "",
|
||||
ident: "#!0_arg",
|
||||
},
|
||||
],
|
||||
BinOp(
|
||||
Pizza,
|
||||
),
|
||||
),
|
||||
@132-172 Closure(
|
||||
[
|
||||
@113-117 Identifier {
|
||||
ident: "newi",
|
||||
},
|
||||
],
|
||||
@182-189 Apply(
|
||||
@182-184 Tag(
|
||||
"Ok",
|
||||
),
|
||||
[
|
||||
@185-189 Var {
|
||||
module_name: "",
|
||||
ident: "newi",
|
||||
},
|
||||
],
|
||||
Space,
|
||||
),
|
||||
),
|
||||
],
|
||||
QuestionSuffix,
|
||||
),
|
||||
),
|
||||
],
|
||||
QuestionSuffix,
|
||||
),
|
||||
),
|
||||
),
|
||||
Body(
|
||||
@194-200 Identifier {
|
||||
ident: "result",
|
||||
},
|
||||
@203-208 Apply(
|
||||
@203-206 Var {
|
||||
module_name: "",
|
||||
ident: "run",
|
||||
},
|
||||
[
|
||||
@207-208 Num(
|
||||
"0",
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
),
|
||||
],
|
||||
},
|
||||
@213-227 Apply(
|
||||
@220-222 Var {
|
||||
module_name: "Bool",
|
||||
ident: "isEq",
|
||||
},
|
||||
[
|
||||
@213-219 Var {
|
||||
module_name: "",
|
||||
ident: "result",
|
||||
},
|
||||
@223-227 Apply(
|
||||
@223-225 Tag(
|
||||
"Ok",
|
||||
),
|
||||
[
|
||||
@226-227 Num(
|
||||
"2",
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
],
|
||||
BinOp(
|
||||
Equals,
|
||||
),
|
||||
),
|
||||
),
|
||||
preceding_comment: @82-82,
|
||||
},
|
||||
Body(
|
||||
@229-233 Identifier {
|
||||
ident: "main",
|
||||
},
|
||||
@240-266 Apply(
|
||||
@240-266 Var {
|
||||
module_name: "Stdout",
|
||||
ident: "line",
|
||||
},
|
||||
[
|
||||
@253-266 Str(
|
||||
PlainLine(
|
||||
"Hello world",
|
||||
),
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
),
|
||||
],
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
EitherIndex(2147483648),
|
||||
EitherIndex(2147483649),
|
||||
],
|
||||
regions: [
|
||||
@0-33,
|
||||
@35-45,
|
||||
],
|
||||
space_before: [
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 2 },
|
||||
],
|
||||
space_after: [
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 2, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
AnnotatedBody {
|
||||
ann_pattern: @0-3 Identifier {
|
||||
ident: "run",
|
||||
},
|
||||
ann_type: @6-15 Apply(
|
||||
"",
|
||||
"Task",
|
||||
[
|
||||
@11-13 Record {
|
||||
fields: [],
|
||||
ext: None,
|
||||
},
|
||||
@14-15 Inferred,
|
||||
],
|
||||
),
|
||||
lines_between: [
|
||||
Newline,
|
||||
],
|
||||
body_pattern: @16-19 Identifier {
|
||||
ident: "run",
|
||||
},
|
||||
body_expr: @22-33 Apply(
|
||||
@22-33 Var {
|
||||
module_name: "",
|
||||
ident: "line",
|
||||
},
|
||||
[
|
||||
@28-33 Str(
|
||||
PlainLine(
|
||||
"foo",
|
||||
),
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
},
|
||||
Body(
|
||||
@35-39 Identifier {
|
||||
ident: "main",
|
||||
},
|
||||
@42-45 Var {
|
||||
module_name: "",
|
||||
ident: "run",
|
||||
},
|
||||
),
|
||||
],
|
||||
}
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-26,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -27,16 +28,16 @@ Defs {
|
|||
@11-26 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@15-17,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-33,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -24,25 +25,25 @@ Defs {
|
|||
@0-4 Identifier {
|
||||
ident: "main",
|
||||
},
|
||||
@11-15 Apply(
|
||||
@11-15 Var {
|
||||
@11-14 Apply(
|
||||
@11-14 Var {
|
||||
module_name: "Task",
|
||||
ident: "await",
|
||||
},
|
||||
[
|
||||
@11-15 Defs(
|
||||
@11-14 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@11-15,
|
||||
@11-14,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -66,43 +67,43 @@ Defs {
|
|||
body_pattern: @11-15 Identifier {
|
||||
ident: "#!2_stmt",
|
||||
},
|
||||
body_expr: @11-15 Var {
|
||||
body_expr: @11-14 Var {
|
||||
module_name: "",
|
||||
ident: "foo",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@11-15 Var {
|
||||
@11-14 Var {
|
||||
module_name: "",
|
||||
ident: "#!2_stmt",
|
||||
},
|
||||
),
|
||||
@11-15 Closure(
|
||||
@11-14 Closure(
|
||||
[
|
||||
@11-15 Underscore(
|
||||
"#!stmt",
|
||||
),
|
||||
],
|
||||
@20-24 Apply(
|
||||
@20-24 Var {
|
||||
@20-23 Apply(
|
||||
@20-23 Var {
|
||||
module_name: "Task",
|
||||
ident: "await",
|
||||
},
|
||||
[
|
||||
@20-24 Defs(
|
||||
@20-23 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@20-24,
|
||||
@20-23,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -126,25 +127,25 @@ Defs {
|
|||
body_pattern: @20-24 Identifier {
|
||||
ident: "#!1_stmt",
|
||||
},
|
||||
body_expr: @20-24 Var {
|
||||
body_expr: @20-23 Var {
|
||||
module_name: "",
|
||||
ident: "bar",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@20-24 Var {
|
||||
@20-23 Var {
|
||||
module_name: "",
|
||||
ident: "#!1_stmt",
|
||||
},
|
||||
),
|
||||
@20-24 Closure(
|
||||
@20-23 Closure(
|
||||
[
|
||||
@20-24 Underscore(
|
||||
"#!stmt",
|
||||
),
|
||||
],
|
||||
@29-33 Var {
|
||||
@29-32 Var {
|
||||
module_name: "",
|
||||
ident: "baz",
|
||||
},
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-26,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-72,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -33,16 +34,16 @@ Defs {
|
|||
@11-23 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@11-23,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -94,14 +95,14 @@ Defs {
|
|||
"#!stmt",
|
||||
),
|
||||
],
|
||||
@33-55 Apply(
|
||||
@33-55 Var {
|
||||
@33-56 Apply(
|
||||
@33-56 Var {
|
||||
module_name: "Task",
|
||||
ident: "await",
|
||||
},
|
||||
[
|
||||
@33-55 Apply(
|
||||
@33-55 Var {
|
||||
@33-56 Apply(
|
||||
@33-56 Var {
|
||||
module_name: "Stdout",
|
||||
ident: "line",
|
||||
},
|
||||
|
@ -116,7 +117,7 @@ Defs {
|
|||
Pizza,
|
||||
),
|
||||
),
|
||||
@33-55 Closure(
|
||||
@33-56 Closure(
|
||||
[
|
||||
@28-30 RecordDestructure(
|
||||
[],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-51,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -27,16 +28,16 @@ Defs {
|
|||
@11-51 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@17-24,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-24,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -33,16 +34,16 @@ Defs {
|
|||
@11-16 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@11-16,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-61,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-49,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -27,16 +28,16 @@ Defs {
|
|||
@11-49 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@23-42,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -45,17 +46,17 @@ Defs {
|
|||
@11-12 Identifier {
|
||||
ident: "x",
|
||||
},
|
||||
@27-29 Apply(
|
||||
@27-29 Var {
|
||||
@27-28 Apply(
|
||||
@27-28 Var {
|
||||
module_name: "Task",
|
||||
ident: "await",
|
||||
},
|
||||
[
|
||||
@27-29 Var {
|
||||
@27-28 Var {
|
||||
module_name: "",
|
||||
ident: "b",
|
||||
},
|
||||
@27-29 Closure(
|
||||
@27-28 Closure(
|
||||
[
|
||||
@23-24 Identifier {
|
||||
ident: "a",
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-22,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
assertion_line: 473
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-51,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -28,16 +28,16 @@ Defs {
|
|||
@11-51 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@11-40,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -55,16 +55,16 @@ Defs {
|
|||
@11-23 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@11-12,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-73,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -24,25 +25,25 @@ Defs {
|
|||
@0-4 Identifier {
|
||||
ident: "main",
|
||||
},
|
||||
@11-56 Apply(
|
||||
@11-56 Var {
|
||||
@11-57 Apply(
|
||||
@11-57 Var {
|
||||
module_name: "Task",
|
||||
ident: "await",
|
||||
},
|
||||
[
|
||||
@11-56 Defs(
|
||||
@11-57 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@11-56,
|
||||
@11-57,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -66,8 +67,8 @@ Defs {
|
|||
body_pattern: @11-57 Identifier {
|
||||
ident: "#!0_stmt",
|
||||
},
|
||||
body_expr: @11-56 Apply(
|
||||
@11-56 Var {
|
||||
body_expr: @11-57 Apply(
|
||||
@11-57 Var {
|
||||
module_name: "",
|
||||
ident: "line",
|
||||
},
|
||||
|
@ -101,12 +102,12 @@ Defs {
|
|||
},
|
||||
],
|
||||
},
|
||||
@11-56 Var {
|
||||
@11-57 Var {
|
||||
module_name: "",
|
||||
ident: "#!0_stmt",
|
||||
},
|
||||
),
|
||||
@11-56 Closure(
|
||||
@11-57 Closure(
|
||||
[
|
||||
@11-57 Underscore(
|
||||
"#!stmt",
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-67,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -42,16 +43,16 @@ Defs {
|
|||
@19-30 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@19-30,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-154,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -24,17 +25,17 @@ Defs {
|
|||
@0-4 Identifier {
|
||||
ident: "main",
|
||||
},
|
||||
@20-31 Apply(
|
||||
@20-31 Var {
|
||||
@20-30 Apply(
|
||||
@20-30 Var {
|
||||
module_name: "Task",
|
||||
ident: "await",
|
||||
},
|
||||
[
|
||||
@20-31 Var {
|
||||
@20-30 Var {
|
||||
module_name: "Stdin",
|
||||
ident: "line",
|
||||
},
|
||||
@20-31 Closure(
|
||||
@20-30 Closure(
|
||||
[
|
||||
@11-17 Identifier {
|
||||
ident: "result",
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-44,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -30,25 +31,25 @@ Defs {
|
|||
ident: "x",
|
||||
},
|
||||
],
|
||||
@28-30 Apply(
|
||||
@28-30 Var {
|
||||
@28-29 Apply(
|
||||
@28-29 Var {
|
||||
module_name: "Task",
|
||||
ident: "await",
|
||||
},
|
||||
[
|
||||
@14-30 Defs(
|
||||
@14-29 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@28-30,
|
||||
@28-29,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
@ -73,19 +74,19 @@ Defs {
|
|||
body_pattern: @24-25 Identifier {
|
||||
ident: "#!0_expr",
|
||||
},
|
||||
body_expr: @28-30 Var {
|
||||
body_expr: @28-29 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@28-30 Var {
|
||||
@28-29 Var {
|
||||
module_name: "",
|
||||
ident: "#!0_expr",
|
||||
},
|
||||
),
|
||||
@28-30 Closure(
|
||||
@28-29 Closure(
|
||||
[
|
||||
@24-25 Identifier {
|
||||
ident: "r",
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-45,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -24,24 +25,24 @@ Defs {
|
|||
@0-4 Identifier {
|
||||
ident: "main",
|
||||
},
|
||||
@15-19 Apply(
|
||||
@15-19 Var {
|
||||
@15-18 Apply(
|
||||
@15-18 Var {
|
||||
module_name: "Task",
|
||||
ident: "await",
|
||||
},
|
||||
[
|
||||
@15-19 Var {
|
||||
@15-18 Var {
|
||||
module_name: "",
|
||||
ident: "foo",
|
||||
},
|
||||
@15-19 Closure(
|
||||
@15-18 Closure(
|
||||
[
|
||||
@11-12 Identifier {
|
||||
ident: "a",
|
||||
},
|
||||
],
|
||||
@15-19 Apply(
|
||||
@15-19 Var {
|
||||
@15-18 Apply(
|
||||
@15-18 Var {
|
||||
module_name: "Task",
|
||||
ident: "await",
|
||||
},
|
||||
|
@ -50,7 +51,7 @@ Defs {
|
|||
module_name: "",
|
||||
ident: "bar",
|
||||
},
|
||||
@15-19 Closure(
|
||||
@15-18 Closure(
|
||||
[
|
||||
@28-33 Identifier {
|
||||
ident: "#!0_arg",
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-120,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -30,18 +31,18 @@ Defs {
|
|||
ident: "await",
|
||||
},
|
||||
[
|
||||
@16-24 Var {
|
||||
@16-23 Var {
|
||||
module_name: "",
|
||||
ident: "getList",
|
||||
},
|
||||
@11-120 Closure(
|
||||
[
|
||||
@16-24 Identifier {
|
||||
@16-23 Identifier {
|
||||
ident: "#!2_arg",
|
||||
},
|
||||
],
|
||||
@11-120 When(
|
||||
@16-24 Var {
|
||||
@16-23 Var {
|
||||
module_name: "",
|
||||
ident: "#!2_arg",
|
||||
},
|
||||
|
@ -61,16 +62,16 @@ Defs {
|
|||
@54-65 Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@54-65,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
source: crates/compiler/can/tests/test_suffixed.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
EitherIndex(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-74,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 1 },
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
|
@ -30,18 +31,18 @@ Defs {
|
|||
ident: "await",
|
||||
},
|
||||
[
|
||||
@16-24 Var {
|
||||
@16-23 Var {
|
||||
module_name: "",
|
||||
ident: "getList",
|
||||
},
|
||||
@11-74 Closure(
|
||||
[
|
||||
@16-24 Identifier {
|
||||
@16-23 Identifier {
|
||||
ident: "#!0_arg",
|
||||
},
|
||||
],
|
||||
@11-74 When(
|
||||
@16-24 Var {
|
||||
@16-23 Var {
|
||||
module_name: "",
|
||||
ident: "#!0_arg",
|
||||
},
|
||||
|
|
|
@ -16,7 +16,7 @@ mod test_can {
|
|||
use bumpalo::Bump;
|
||||
use core::panic;
|
||||
use roc_can::expr::Expr::{self, *};
|
||||
use roc_can::expr::{ClosureData, IntValue, Recursive};
|
||||
use roc_can::expr::{ClosureData, IntValue, Recursive, WhenBranch};
|
||||
use roc_can::pattern::Pattern;
|
||||
use roc_module::called_via::CalledVia;
|
||||
use roc_problem::can::{CycleEntry, FloatErrorKind, IntErrorKind, Problem, RuntimeError};
|
||||
|
@ -415,7 +415,7 @@ mod test_can {
|
|||
let arena = Bump::new();
|
||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||
|
||||
assert_eq!(problems.len(), 2);
|
||||
assert_eq!(problems.len(), 1);
|
||||
println!("{problems:#?}");
|
||||
assert!(problems.iter().any(|problem| matches!(
|
||||
problem,
|
||||
|
@ -504,6 +504,7 @@ mod test_can {
|
|||
|
||||
assert_eq!(problems, Vec::new());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn correct_double_nested_body() {
|
||||
let src = indoc!(
|
||||
|
@ -801,6 +802,280 @@ mod test_can {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_desugar_plain_prefix() {
|
||||
let src = indoc!(
|
||||
r#"
|
||||
try Str.toU64 "123"
|
||||
"#
|
||||
);
|
||||
let arena = Bump::new();
|
||||
let out = can_expr_with(&arena, test_home(), src);
|
||||
|
||||
assert_eq!(out.problems, Vec::new());
|
||||
|
||||
// Assert that we desugar to:
|
||||
//
|
||||
// when Str.toU64 "123" is
|
||||
// Ok `0` -> `0`
|
||||
// Err `1` -> return Err `1`
|
||||
|
||||
let (cond_expr, branches) = assert_when(&out.loc_expr.value);
|
||||
let cond_args = assert_func_call(cond_expr, "toU64", CalledVia::Try, &out.interns);
|
||||
|
||||
assert_eq!(cond_args.len(), 1);
|
||||
assert_str_value(&cond_args[0].1.value, "123");
|
||||
|
||||
assert_eq!(branches.len(), 2);
|
||||
|
||||
assert_eq!(branches[0].patterns.len(), 1);
|
||||
assert!(!branches[0].patterns[0].degenerate);
|
||||
match &branches[0].patterns[0].pattern.value {
|
||||
Pattern::AppliedTag {
|
||||
tag_name,
|
||||
arguments,
|
||||
..
|
||||
} => {
|
||||
assert_eq!(tag_name.0.to_string(), "Ok");
|
||||
assert_eq!(arguments.len(), 1);
|
||||
assert_pattern_name(&arguments[0].1.value, "0", &out.interns);
|
||||
}
|
||||
other => panic!("First argument was not an applied tag: {:?}", other),
|
||||
}
|
||||
|
||||
assert!(&branches[0].guard.is_none());
|
||||
assert_var_usage(&branches[0].value.value, "0", &out.interns);
|
||||
|
||||
assert_eq!(branches[1].patterns.len(), 1);
|
||||
assert!(!branches[1].patterns[0].degenerate);
|
||||
match &branches[1].patterns[0].pattern.value {
|
||||
Pattern::AppliedTag {
|
||||
tag_name,
|
||||
arguments,
|
||||
..
|
||||
} => {
|
||||
assert_eq!(tag_name.0.to_string(), "Err");
|
||||
assert_eq!(arguments.len(), 1);
|
||||
assert_pattern_name(&arguments[0].1.value, "1", &out.interns);
|
||||
}
|
||||
other => panic!("First argument was not an applied tag: {:?}", other),
|
||||
}
|
||||
|
||||
match &branches[1].value.value {
|
||||
Expr::Return { return_value, .. } => match &return_value.value {
|
||||
Expr::Tag {
|
||||
name, arguments, ..
|
||||
} => {
|
||||
assert_eq!(name.0.to_string(), "Err");
|
||||
assert_eq!(arguments.len(), 1);
|
||||
assert_var_usage(&arguments[0].1.value, "1", &out.interns);
|
||||
}
|
||||
other_inner => panic!("Expr was not a Tag: {:?}", other_inner),
|
||||
},
|
||||
other_outer => panic!("Expr was not a Return: {:?}", other_outer),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_desugar_pipe_prefix() {
|
||||
let src = indoc!(
|
||||
r#"
|
||||
"123" |> try Str.toU64
|
||||
"#
|
||||
);
|
||||
let arena = Bump::new();
|
||||
let out = can_expr_with(&arena, test_home(), src);
|
||||
|
||||
assert_eq!(out.problems, Vec::new());
|
||||
|
||||
// Assert that we desugar to:
|
||||
//
|
||||
// when Str.toU64 "123" is
|
||||
// Ok `0` -> `0`
|
||||
// Err `1` -> return Err `1`
|
||||
|
||||
let (cond_expr, branches) = assert_when(&out.loc_expr.value);
|
||||
let cond_args = assert_func_call(cond_expr, "toU64", CalledVia::Try, &out.interns);
|
||||
|
||||
assert_eq!(cond_args.len(), 1);
|
||||
assert_str_value(&cond_args[0].1.value, "123");
|
||||
|
||||
assert_eq!(branches.len(), 2);
|
||||
|
||||
assert_eq!(branches[0].patterns.len(), 1);
|
||||
assert!(!branches[0].patterns[0].degenerate);
|
||||
match &branches[0].patterns[0].pattern.value {
|
||||
Pattern::AppliedTag {
|
||||
tag_name,
|
||||
arguments,
|
||||
..
|
||||
} => {
|
||||
assert_eq!(tag_name.0.to_string(), "Ok");
|
||||
assert_eq!(arguments.len(), 1);
|
||||
assert_pattern_name(&arguments[0].1.value, "0", &out.interns);
|
||||
}
|
||||
other => panic!("First argument was not an applied tag: {:?}", other),
|
||||
}
|
||||
|
||||
assert!(&branches[0].guard.is_none());
|
||||
assert_var_usage(&branches[0].value.value, "0", &out.interns);
|
||||
|
||||
assert_eq!(branches[1].patterns.len(), 1);
|
||||
assert!(!branches[1].patterns[0].degenerate);
|
||||
match &branches[1].patterns[0].pattern.value {
|
||||
Pattern::AppliedTag {
|
||||
tag_name,
|
||||
arguments,
|
||||
..
|
||||
} => {
|
||||
assert_eq!(tag_name.0.to_string(), "Err");
|
||||
assert_eq!(arguments.len(), 1);
|
||||
assert_pattern_name(&arguments[0].1.value, "1", &out.interns);
|
||||
}
|
||||
other => panic!("First argument was not an applied tag: {:?}", other),
|
||||
}
|
||||
|
||||
match &branches[1].value.value {
|
||||
Expr::Return { return_value, .. } => match &return_value.value {
|
||||
Expr::Tag {
|
||||
name, arguments, ..
|
||||
} => {
|
||||
assert_eq!(name.0.to_string(), "Err");
|
||||
assert_eq!(arguments.len(), 1);
|
||||
assert_var_usage(&arguments[0].1.value, "1", &out.interns);
|
||||
}
|
||||
other_inner => panic!("Expr was not a Tag: {:?}", other_inner),
|
||||
},
|
||||
other_outer => panic!("Expr was not a Return: {:?}", other_outer),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_desugar_pipe_suffix() {
|
||||
let src = indoc!(
|
||||
r#"
|
||||
Str.toU64 "123" |> try
|
||||
"#
|
||||
);
|
||||
let arena = Bump::new();
|
||||
let out = can_expr_with(&arena, test_home(), src);
|
||||
|
||||
assert_eq!(out.problems, Vec::new());
|
||||
|
||||
// Assert that we desugar to:
|
||||
//
|
||||
// when Str.toU64 "123" is
|
||||
// Ok `0` -> `0`
|
||||
// Err `1` -> return Err `1`
|
||||
|
||||
let (cond_expr, branches) = assert_when(&out.loc_expr.value);
|
||||
let cond_args = assert_func_call(cond_expr, "toU64", CalledVia::Space, &out.interns);
|
||||
|
||||
assert_eq!(cond_args.len(), 1);
|
||||
assert_str_value(&cond_args[0].1.value, "123");
|
||||
|
||||
assert_eq!(branches.len(), 2);
|
||||
|
||||
assert_eq!(branches[0].patterns.len(), 1);
|
||||
assert!(!branches[0].patterns[0].degenerate);
|
||||
match &branches[0].patterns[0].pattern.value {
|
||||
Pattern::AppliedTag {
|
||||
tag_name,
|
||||
arguments,
|
||||
..
|
||||
} => {
|
||||
assert_eq!(tag_name.0.to_string(), "Ok");
|
||||
assert_eq!(arguments.len(), 1);
|
||||
assert_pattern_name(&arguments[0].1.value, "0", &out.interns);
|
||||
}
|
||||
other => panic!("First argument was not an applied tag: {:?}", other),
|
||||
}
|
||||
|
||||
assert!(&branches[0].guard.is_none());
|
||||
assert_var_usage(&branches[0].value.value, "0", &out.interns);
|
||||
|
||||
assert_eq!(branches[1].patterns.len(), 1);
|
||||
assert!(!branches[1].patterns[0].degenerate);
|
||||
match &branches[1].patterns[0].pattern.value {
|
||||
Pattern::AppliedTag {
|
||||
tag_name,
|
||||
arguments,
|
||||
..
|
||||
} => {
|
||||
assert_eq!(tag_name.0.to_string(), "Err");
|
||||
assert_eq!(arguments.len(), 1);
|
||||
assert_pattern_name(&arguments[0].1.value, "1", &out.interns);
|
||||
}
|
||||
other => panic!("First argument was not an applied tag: {:?}", other),
|
||||
}
|
||||
|
||||
match &branches[1].value.value {
|
||||
Expr::Return { return_value, .. } => match &return_value.value {
|
||||
Expr::Tag {
|
||||
name, arguments, ..
|
||||
} => {
|
||||
assert_eq!(name.0.to_string(), "Err");
|
||||
assert_eq!(arguments.len(), 1);
|
||||
assert_var_usage(&arguments[0].1.value, "1", &out.interns);
|
||||
}
|
||||
other_inner => panic!("Expr was not a Tag: {:?}", other_inner),
|
||||
},
|
||||
other_outer => panic!("Expr was not a Return: {:?}", other_outer),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_desugar_works_elsewhere() {
|
||||
let src = indoc!(
|
||||
r#"
|
||||
when Foo 123 is
|
||||
Foo try -> try
|
||||
"#
|
||||
);
|
||||
let arena = Bump::new();
|
||||
let out = can_expr_with(&arena, test_home(), src);
|
||||
|
||||
assert_eq!(out.problems, Vec::new());
|
||||
|
||||
// Assert that we don't treat `try` as a keyword here
|
||||
// by desugaring to:
|
||||
//
|
||||
// when Foo 123 is
|
||||
// Foo try -> try
|
||||
|
||||
let (cond_expr, branches) = assert_when(&out.loc_expr.value);
|
||||
match cond_expr {
|
||||
Expr::Tag {
|
||||
name, arguments, ..
|
||||
} => {
|
||||
assert_eq!(name.0.to_string(), "Foo");
|
||||
assert_eq!(arguments.len(), 1);
|
||||
assert_num_value(&arguments[0].1.value, 123);
|
||||
}
|
||||
_ => panic!("cond_expr was not a Tag: {:?}", cond_expr),
|
||||
}
|
||||
|
||||
assert_eq!(branches.len(), 1);
|
||||
assert_eq!(branches[0].patterns.len(), 1);
|
||||
assert!(!branches[0].patterns[0].degenerate);
|
||||
|
||||
match &branches[0].patterns[0].pattern.value {
|
||||
Pattern::AppliedTag {
|
||||
tag_name,
|
||||
arguments,
|
||||
..
|
||||
} => {
|
||||
assert_eq!(tag_name.0.to_string(), "Foo");
|
||||
assert_eq!(arguments.len(), 1);
|
||||
assert_pattern_name(&arguments[0].1.value, "try", &out.interns);
|
||||
}
|
||||
other => panic!("First argument was not an applied tag: {:?}", other),
|
||||
}
|
||||
|
||||
assert_var_usage(&branches[0].value.value, "try", &out.interns);
|
||||
assert!(&branches[0].guard.is_none());
|
||||
}
|
||||
|
||||
fn assert_num_value(expr: &Expr, num: usize) {
|
||||
match expr {
|
||||
Expr::Num(_, num_str, _, _) => {
|
||||
|
@ -810,6 +1085,15 @@ mod test_can {
|
|||
}
|
||||
}
|
||||
|
||||
fn assert_str_value(expr: &Expr, str_val: &str) {
|
||||
match expr {
|
||||
Expr::Str(str_expr) => {
|
||||
assert_eq!(&**str_expr, str_val)
|
||||
}
|
||||
_ => panic!("Expr wasn't a Str with value {str_val}: {:?}", expr),
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_var_usage(expr: &Expr, name: &str, interns: &roc_module::symbol::Interns) {
|
||||
match expr {
|
||||
Expr::Var(sym, _) => assert_eq!(sym.as_str(interns), name),
|
||||
|
@ -835,7 +1119,10 @@ mod test_can {
|
|||
|
||||
args.clone()
|
||||
}
|
||||
_ => panic!("Expr was not a RecordBuilder Call: {:?}", expr),
|
||||
_ => panic!(
|
||||
"Expr was not a Call with CalledVia={:?}: {:?}",
|
||||
called_via, expr
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -846,6 +1133,15 @@ mod test_can {
|
|||
}
|
||||
}
|
||||
|
||||
fn assert_when(expr: &Expr) -> (&Expr, &Vec<WhenBranch>) {
|
||||
match expr {
|
||||
Expr::When {
|
||||
loc_cond, branches, ..
|
||||
} => (&loc_cond.value, branches),
|
||||
_ => panic!("Expr was not a When: {:?}", expr),
|
||||
}
|
||||
}
|
||||
|
||||
// TAIL CALLS
|
||||
fn get_closure(expr: &Expr, i: usize) -> roc_can::expr::Recursive {
|
||||
match expr {
|
||||
|
|
|
@ -6,7 +6,7 @@ mod suffixed_tests {
|
|||
use bumpalo::Bump;
|
||||
use insta::assert_snapshot;
|
||||
use roc_can::desugar::desugar_defs_node_values;
|
||||
use roc_can::env::Env;
|
||||
use roc_can::env::{Env, FxMode};
|
||||
use roc_can::scope::Scope;
|
||||
use roc_module::symbol::{IdentIds, ModuleIds, PackageModuleIds};
|
||||
use roc_parse::test_helpers::parse_defs_with;
|
||||
|
@ -34,6 +34,7 @@ mod suffixed_tests {
|
|||
&dep_idents,
|
||||
&qualified_module_ids,
|
||||
None,
|
||||
FxMode::Task,
|
||||
);
|
||||
|
||||
let mut defs = parse_defs_with(arena, indoc!($src)).unwrap();
|
||||
|
@ -606,6 +607,44 @@ mod suffixed_tests {
|
|||
"##
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_7081() {
|
||||
run_test!(
|
||||
r##"
|
||||
inc = \i ->
|
||||
if i > 2 then
|
||||
Err MaxReached
|
||||
else
|
||||
Ok (i + 1)
|
||||
|
||||
expect
|
||||
run = \i ->
|
||||
newi =
|
||||
i
|
||||
|> inc?
|
||||
|> inc?
|
||||
Ok newi
|
||||
result = run 0
|
||||
result == Ok 2
|
||||
|
||||
main =
|
||||
Stdout.line! "Hello world"
|
||||
"##
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_7103() {
|
||||
run_test!(
|
||||
r##"
|
||||
run : Task {} _
|
||||
run = line! "foo"
|
||||
|
||||
main = run
|
||||
"##
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue