mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 15:03:46 +00:00
Merge branch 'main' into rust-1-76-0-upgrade
This commit is contained in:
commit
c303be7553
244 changed files with 1776 additions and 1841 deletions
|
@ -1001,7 +1001,7 @@ bitwiseNot = \n ->
|
|||
## ```roc
|
||||
## shiftLeftBy 0b0000_0011 2 == 0b0000_1100
|
||||
##
|
||||
## 0b0000_0101 |> shiftLeftBy 2 == 0b0000_1100
|
||||
## 0b0000_0101 |> shiftLeftBy 2 == 0b0001_0100
|
||||
## ```
|
||||
## In some languages `shiftLeftBy` is implemented as a binary operator `<<`.
|
||||
shiftLeftBy : Int a, U8 -> Int a
|
||||
|
|
|
@ -748,10 +748,11 @@ fn can_annotation_help(
|
|||
|
||||
for loc_var in *loc_vars {
|
||||
let var = match loc_var.value {
|
||||
Pattern::Identifier {
|
||||
ident: name,
|
||||
suffixed: _,
|
||||
} if name.chars().next().unwrap().is_lowercase() => name,
|
||||
Pattern::Identifier { ident: name, .. }
|
||||
if name.chars().next().unwrap().is_lowercase() =>
|
||||
{
|
||||
name
|
||||
}
|
||||
_ => unreachable!("I thought this was validated during parsing"),
|
||||
};
|
||||
let var_name = Lowercase::from(var);
|
||||
|
|
|
@ -547,11 +547,7 @@ fn canonicalize_claimed_ability_impl<'a>(
|
|||
}
|
||||
AssignedField::RequiredValue(label, _spaces, value) => {
|
||||
let impl_ident = match value.value {
|
||||
ast::Expr::Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed: _,
|
||||
} => {
|
||||
ast::Expr::Var { module_name, ident } => {
|
||||
if module_name.is_empty() {
|
||||
ident
|
||||
} else {
|
||||
|
@ -2574,10 +2570,9 @@ fn to_pending_alias_or_opaque<'a>(
|
|||
|
||||
for loc_var in vars.iter() {
|
||||
match loc_var.value {
|
||||
ast::Pattern::Identifier {
|
||||
ident: name,
|
||||
suffixed: _,
|
||||
} if name.chars().next().unwrap().is_lowercase() => {
|
||||
ast::Pattern::Identifier { ident: name, .. }
|
||||
if name.chars().next().unwrap().is_lowercase() =>
|
||||
{
|
||||
let lowercase = Lowercase::from(name);
|
||||
can_rigids.push(Loc {
|
||||
value: lowercase,
|
||||
|
|
|
@ -25,10 +25,7 @@ fn to_encoder<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
opaque_ref,
|
||||
&*env.arena.alloc([Loc::at(
|
||||
DERIVED_REGION,
|
||||
ast::Pattern::Identifier {
|
||||
ident: payload,
|
||||
suffixed: 0,
|
||||
},
|
||||
ast::Pattern::Identifier { ident: payload },
|
||||
)]),
|
||||
);
|
||||
|
||||
|
@ -37,12 +34,10 @@ fn to_encoder<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
alloc_expr(ast::Expr::Var {
|
||||
module_name: "Encode",
|
||||
ident: "toEncoder",
|
||||
suffixed: 0,
|
||||
}),
|
||||
&*env.arena.alloc([&*alloc_expr(ast::Expr::Var {
|
||||
module_name: "",
|
||||
ident: payload,
|
||||
suffixed: 0,
|
||||
})]),
|
||||
roc_module::called_via::CalledVia::Space,
|
||||
));
|
||||
|
@ -67,23 +62,19 @@ fn decoder<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
alloc_expr(ast::Expr::Var {
|
||||
module_name: "Decode",
|
||||
ident: "decodeWith",
|
||||
suffixed: 0,
|
||||
}),
|
||||
env.arena.alloc([
|
||||
&*alloc_expr(ast::Expr::Var {
|
||||
module_name: "",
|
||||
ident: bytes,
|
||||
suffixed: 0,
|
||||
}),
|
||||
alloc_expr(ast::Expr::Var {
|
||||
module_name: "Decode",
|
||||
ident: "decoder",
|
||||
suffixed: 0,
|
||||
}),
|
||||
alloc_expr(ast::Expr::Var {
|
||||
module_name: "",
|
||||
ident: fmt,
|
||||
suffixed: 0,
|
||||
}),
|
||||
]),
|
||||
CalledVia::Space,
|
||||
|
@ -94,7 +85,6 @@ fn decoder<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
alloc_expr(ast::Expr::Var {
|
||||
module_name: "Decode",
|
||||
ident: "mapResult",
|
||||
suffixed: 0,
|
||||
}),
|
||||
env.arena.alloc([
|
||||
&*alloc_expr(call_decode_with),
|
||||
|
@ -107,20 +97,8 @@ fn decoder<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
// Decode.mapResult (Decode.decodeWith bytes Decode.decoder fmt) @Opaq
|
||||
let custom_closure = ast::Expr::Closure(
|
||||
env.arena.alloc([
|
||||
Loc::at(
|
||||
DERIVED_REGION,
|
||||
ast::Pattern::Identifier {
|
||||
ident: bytes,
|
||||
suffixed: 0,
|
||||
},
|
||||
),
|
||||
Loc::at(
|
||||
DERIVED_REGION,
|
||||
ast::Pattern::Identifier {
|
||||
ident: fmt,
|
||||
suffixed: 0,
|
||||
},
|
||||
),
|
||||
Loc::at(DERIVED_REGION, ast::Pattern::Identifier { ident: bytes }),
|
||||
Loc::at(DERIVED_REGION, ast::Pattern::Identifier { ident: fmt }),
|
||||
]),
|
||||
alloc_expr(call_map_result),
|
||||
);
|
||||
|
@ -130,7 +108,6 @@ fn decoder<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
alloc_expr(ast::Expr::Var {
|
||||
module_name: "Decode",
|
||||
ident: "custom",
|
||||
suffixed: 0,
|
||||
}),
|
||||
env.arena.alloc([&*alloc_expr(custom_closure)]),
|
||||
CalledVia::Space,
|
||||
|
@ -153,10 +130,7 @@ fn hash<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
opaque_ref,
|
||||
&*env.arena.alloc([Loc::at(
|
||||
DERIVED_REGION,
|
||||
ast::Pattern::Identifier {
|
||||
ident: payload,
|
||||
suffixed: 0,
|
||||
},
|
||||
ast::Pattern::Identifier { ident: payload },
|
||||
)]),
|
||||
);
|
||||
|
||||
|
@ -165,18 +139,15 @@ fn hash<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
alloc_expr(ast::Expr::Var {
|
||||
module_name: "Hash",
|
||||
ident: "hash",
|
||||
suffixed: 0,
|
||||
}),
|
||||
&*env.arena.alloc([
|
||||
&*alloc_expr(ast::Expr::Var {
|
||||
module_name: "",
|
||||
ident: hasher,
|
||||
suffixed: 0,
|
||||
}),
|
||||
&*alloc_expr(ast::Expr::Var {
|
||||
module_name: "",
|
||||
ident: payload,
|
||||
suffixed: 0,
|
||||
}),
|
||||
]),
|
||||
roc_module::called_via::CalledVia::Space,
|
||||
|
@ -185,13 +156,7 @@ fn hash<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
// \hasher, @Opaq payload -> Hash.hash hasher payload
|
||||
ast::Expr::Closure(
|
||||
env.arena.alloc([
|
||||
Loc::at(
|
||||
DERIVED_REGION,
|
||||
ast::Pattern::Identifier {
|
||||
ident: hasher,
|
||||
suffixed: 0,
|
||||
},
|
||||
),
|
||||
Loc::at(DERIVED_REGION, ast::Pattern::Identifier { ident: hasher }),
|
||||
Loc::at(DERIVED_REGION, opaque_apply_pattern),
|
||||
]),
|
||||
call_member,
|
||||
|
@ -211,10 +176,7 @@ fn is_eq<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
opaque_ref,
|
||||
&*env.arena.alloc([Loc::at(
|
||||
DERIVED_REGION,
|
||||
ast::Pattern::Identifier {
|
||||
ident: payload1,
|
||||
suffixed: 0,
|
||||
},
|
||||
ast::Pattern::Identifier { ident: payload1 },
|
||||
)]),
|
||||
);
|
||||
// \@Opaq payload2
|
||||
|
@ -222,10 +184,7 @@ fn is_eq<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
opaque_ref,
|
||||
&*env.arena.alloc([Loc::at(
|
||||
DERIVED_REGION,
|
||||
ast::Pattern::Identifier {
|
||||
ident: payload2,
|
||||
suffixed: 0,
|
||||
},
|
||||
ast::Pattern::Identifier { ident: payload2 },
|
||||
)]),
|
||||
);
|
||||
|
||||
|
@ -234,18 +193,15 @@ fn is_eq<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
alloc_expr(ast::Expr::Var {
|
||||
module_name: "Bool",
|
||||
ident: "isEq",
|
||||
suffixed: 0,
|
||||
}),
|
||||
&*env.arena.alloc([
|
||||
&*alloc_expr(ast::Expr::Var {
|
||||
module_name: "",
|
||||
ident: payload1,
|
||||
suffixed: 0,
|
||||
}),
|
||||
&*alloc_expr(ast::Expr::Var {
|
||||
module_name: "",
|
||||
ident: payload2,
|
||||
suffixed: 0,
|
||||
}),
|
||||
]),
|
||||
roc_module::called_via::CalledVia::Space,
|
||||
|
@ -274,10 +230,7 @@ fn to_inspector<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
opaque_ref,
|
||||
&*env.arena.alloc([Loc::at(
|
||||
DERIVED_REGION,
|
||||
ast::Pattern::Identifier {
|
||||
ident: payload,
|
||||
suffixed: 0,
|
||||
},
|
||||
ast::Pattern::Identifier { ident: payload },
|
||||
)]),
|
||||
);
|
||||
|
||||
|
@ -286,12 +239,10 @@ fn to_inspector<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
alloc_expr(ast::Expr::Var {
|
||||
module_name: "Inspect",
|
||||
ident: "toInspector",
|
||||
suffixed: 0,
|
||||
}),
|
||||
&*env.arena.alloc([&*alloc_expr(ast::Expr::Var {
|
||||
module_name: "",
|
||||
ident: payload,
|
||||
suffixed: 0,
|
||||
})]),
|
||||
roc_module::called_via::CalledVia::Space,
|
||||
));
|
||||
|
@ -306,7 +257,6 @@ fn to_inspector<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
alloc_expr(ast::Expr::Var {
|
||||
module_name: "Inspect",
|
||||
ident: "tag",
|
||||
suffixed: 0,
|
||||
}),
|
||||
&*env.arena.alloc([&*opaque_name, &*to_inspector_list]),
|
||||
roc_module::called_via::CalledVia::Space,
|
||||
|
@ -319,14 +269,12 @@ fn to_inspector<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
alloc_expr(ast::Expr::Var {
|
||||
module_name: "Inspect",
|
||||
ident: "apply",
|
||||
suffixed: 0,
|
||||
}),
|
||||
&*env.arena.alloc([
|
||||
&*opaque_inspector,
|
||||
&*alloc_expr(ast::Expr::Var {
|
||||
module_name: "",
|
||||
ident: fmt,
|
||||
suffixed: 0,
|
||||
}),
|
||||
]),
|
||||
roc_module::called_via::CalledVia::Space,
|
||||
|
@ -335,10 +283,7 @@ fn to_inspector<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
let custom_closure = alloc_expr(ast::Expr::Closure(
|
||||
env.arena.alloc([Loc::at(
|
||||
DERIVED_REGION,
|
||||
ast::Pattern::Identifier {
|
||||
ident: fmt,
|
||||
suffixed: 0,
|
||||
},
|
||||
ast::Pattern::Identifier { ident: fmt },
|
||||
)]),
|
||||
apply_opaque_inspector,
|
||||
));
|
||||
|
@ -348,7 +293,6 @@ fn to_inspector<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
|
|||
alloc_expr(ast::Expr::Var {
|
||||
module_name: "Inspect",
|
||||
ident: "custom",
|
||||
suffixed: 0,
|
||||
}),
|
||||
env.arena.alloc([&*custom_closure]),
|
||||
CalledVia::Space,
|
||||
|
|
|
@ -57,11 +57,7 @@ fn new_op_call_expr<'a>(
|
|||
let args = arena.alloc([left, right]);
|
||||
|
||||
let loc_expr = arena.alloc(Loc {
|
||||
value: Expr::Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed: 0,
|
||||
},
|
||||
value: Expr::Var { module_name, ident },
|
||||
region: loc_op.region,
|
||||
});
|
||||
|
||||
|
@ -189,33 +185,13 @@ pub fn desugar_value_def_suffixed<'a>(arena: &'a Bump, value_def: ValueDef<'a>)
|
|||
sub_arg,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
}) => {
|
||||
let ok_wrapped_return = arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
Expr::Apply(
|
||||
arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
Expr::Var {
|
||||
module_name: ModuleName::TASK,
|
||||
ident: "ok",
|
||||
suffixed: 0,
|
||||
},
|
||||
)),
|
||||
arena.alloc([sub_new]),
|
||||
CalledVia::BangSuffix,
|
||||
),
|
||||
));
|
||||
}) => desugar_value_def_suffixed(
|
||||
arena,
|
||||
Body(
|
||||
loc_pattern,
|
||||
apply_task_await(
|
||||
arena,
|
||||
loc_expr.region,
|
||||
sub_arg,
|
||||
sub_pat,
|
||||
ok_wrapped_return,
|
||||
),
|
||||
)
|
||||
}
|
||||
apply_task_await(arena, loc_expr.region, sub_arg, sub_pat, sub_new),
|
||||
),
|
||||
),
|
||||
Err(..) => Body(
|
||||
loc_pattern,
|
||||
arena.alloc(Loc::at(loc_expr.region, MalformedSuffixed(loc_expr))),
|
||||
|
@ -243,13 +219,22 @@ pub fn desugar_value_def_suffixed<'a>(arena: &'a Bump, value_def: ValueDef<'a>)
|
|||
sub_arg,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
}) => AnnotatedBody {
|
||||
ann_pattern,
|
||||
ann_type,
|
||||
comment,
|
||||
body_pattern,
|
||||
body_expr: apply_task_await(arena, body_expr.region, sub_arg, sub_pat, sub_new),
|
||||
},
|
||||
}) => desugar_value_def_suffixed(
|
||||
arena,
|
||||
AnnotatedBody {
|
||||
ann_pattern,
|
||||
ann_type,
|
||||
comment,
|
||||
body_pattern,
|
||||
body_expr: apply_task_await(
|
||||
arena,
|
||||
body_expr.region,
|
||||
sub_arg,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
),
|
||||
},
|
||||
),
|
||||
Err(..) => AnnotatedBody {
|
||||
ann_pattern,
|
||||
ann_type,
|
||||
|
@ -347,6 +332,15 @@ pub fn desugar_expr<'a>(
|
|||
|
||||
arena.alloc(Loc { region, value })
|
||||
}
|
||||
// desugar the sub_expression, but leave the TaskAwaitBang as this will
|
||||
// be unwrapped later in desugar_value_def_suffixed
|
||||
TaskAwaitBang(sub_expr) => {
|
||||
let intermediate = arena.alloc(Loc::at(loc_expr.region, **sub_expr));
|
||||
let new_sub_loc_expr = desugar_expr(arena, intermediate, src, line_info, module_path);
|
||||
let new_sub_expr = arena.alloc(new_sub_loc_expr.value);
|
||||
|
||||
arena.alloc(Loc::at(loc_expr.region, TaskAwaitBang(new_sub_expr)))
|
||||
}
|
||||
RecordAccess(sub_expr, paths) => {
|
||||
let region = loc_expr.region;
|
||||
let loc_sub_expr = Loc {
|
||||
|
@ -606,12 +600,10 @@ pub fn desugar_expr<'a>(
|
|||
Negate => Var {
|
||||
module_name: ModuleName::NUM,
|
||||
ident: "neg",
|
||||
suffixed: 0,
|
||||
},
|
||||
Not => Var {
|
||||
module_name: ModuleName::BOOL,
|
||||
ident: "not",
|
||||
suffixed: 0,
|
||||
},
|
||||
};
|
||||
let loc_fn_var = arena.alloc(Loc { region, value });
|
||||
|
@ -709,7 +701,6 @@ pub fn desugar_expr<'a>(
|
|||
let inspect_fn = Var {
|
||||
module_name: ModuleName::INSPECT,
|
||||
ident: "toStr",
|
||||
suffixed: 0,
|
||||
};
|
||||
let loc_inspect_fn_var = arena.alloc(Loc {
|
||||
value: inspect_fn,
|
||||
|
@ -764,7 +755,6 @@ pub fn desugar_expr<'a>(
|
|||
Expr::Var {
|
||||
module_name: ModuleName::TASK,
|
||||
ident: "ok",
|
||||
suffixed: 0,
|
||||
},
|
||||
)),
|
||||
arena.alloc(apply_args),
|
||||
|
@ -860,7 +850,6 @@ fn desugar_field<'a>(
|
|||
value: Var {
|
||||
module_name: "",
|
||||
ident: loc_str.value,
|
||||
suffixed: 0,
|
||||
},
|
||||
region: loc_str.region,
|
||||
};
|
||||
|
@ -1041,7 +1030,6 @@ fn record_builder_arg<'a>(
|
|||
value: Expr::Var {
|
||||
module_name: "",
|
||||
ident: arena.alloc("#".to_owned() + label.value),
|
||||
suffixed: 0,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1081,10 +1069,7 @@ fn record_builder_arg<'a>(
|
|||
|
||||
for label in apply_field_names.iter().rev() {
|
||||
let name = arena.alloc("#".to_owned() + label.value);
|
||||
let ident = roc_parse::ast::Pattern::Identifier {
|
||||
ident: name,
|
||||
suffixed: 0,
|
||||
};
|
||||
let ident = roc_parse::ast::Pattern::Identifier { ident: name };
|
||||
|
||||
let arg_pattern = arena.alloc(Loc {
|
||||
value: ident,
|
||||
|
|
|
@ -1019,11 +1019,9 @@ pub fn canonicalize_expr<'a>(
|
|||
(expr, output)
|
||||
}
|
||||
}
|
||||
ast::Expr::Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed: _, // TODO should we use suffixed here?
|
||||
} => canonicalize_var_lookup(env, var_store, scope, module_name, ident, region),
|
||||
ast::Expr::Var { module_name, ident } => {
|
||||
canonicalize_var_lookup(env, var_store, scope, module_name, ident, region)
|
||||
}
|
||||
ast::Expr::Underscore(name) => {
|
||||
// we parse underscores, but they are not valid expression syntax
|
||||
|
||||
|
@ -1171,6 +1169,7 @@ pub fn canonicalize_expr<'a>(
|
|||
output,
|
||||
)
|
||||
}
|
||||
ast::Expr::TaskAwaitBang(..) => internal_error!("a Expr::TaskAwaitBang expression was not completed removed in desugar_value_def_suffixed"),
|
||||
ast::Expr::Tag(tag) => {
|
||||
let variant_var = var_store.fresh();
|
||||
let ext_var = var_store.fresh();
|
||||
|
@ -2464,7 +2463,8 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
|||
| ast::Expr::Closure(_, loc_expr) => is_valid_interpolation(&loc_expr.value),
|
||||
ast::Expr::TupleAccess(sub_expr, _)
|
||||
| ast::Expr::ParensAround(sub_expr)
|
||||
| ast::Expr::RecordAccess(sub_expr, _) => is_valid_interpolation(sub_expr),
|
||||
| ast::Expr::RecordAccess(sub_expr, _)
|
||||
| ast::Expr::TaskAwaitBang(sub_expr) => is_valid_interpolation(sub_expr),
|
||||
ast::Expr::Apply(loc_expr, args, _called_via) => {
|
||||
is_valid_interpolation(&loc_expr.value)
|
||||
&& args
|
||||
|
|
|
@ -265,10 +265,7 @@ pub fn canonicalize_def_header_pattern<'a>(
|
|||
|
||||
match pattern {
|
||||
// Identifiers that shadow ability members may appear (and may only appear) at the header of a def.
|
||||
Identifier {
|
||||
ident: name,
|
||||
suffixed: _,
|
||||
} => {
|
||||
Identifier { ident: name } => {
|
||||
match scope.introduce_or_shadow_ability_member(
|
||||
pending_abilities_in_scope,
|
||||
(*name).into(),
|
||||
|
@ -376,13 +373,12 @@ pub fn canonicalize_pattern<'a>(
|
|||
use PatternType::*;
|
||||
|
||||
let can_pattern = match pattern {
|
||||
Identifier {
|
||||
ident: name,
|
||||
suffixed: _,
|
||||
} => match canonicalize_pattern_symbol(env, scope, output, region, permit_shadows, name) {
|
||||
Ok(symbol) => Pattern::Identifier(symbol),
|
||||
Err(pattern) => pattern,
|
||||
},
|
||||
Identifier { ident: name } => {
|
||||
match canonicalize_pattern_symbol(env, scope, output, region, permit_shadows, name) {
|
||||
Ok(symbol) => Pattern::Identifier(symbol),
|
||||
Err(pattern) => pattern,
|
||||
}
|
||||
}
|
||||
Underscore(name) => {
|
||||
// An underscored identifier can't be used, but we'll still add it to the scope
|
||||
// for better error messages if someone tries to use it.
|
||||
|
@ -632,10 +628,7 @@ pub fn canonicalize_pattern<'a>(
|
|||
|
||||
for loc_pattern in patterns.iter() {
|
||||
match loc_pattern.value {
|
||||
Identifier {
|
||||
ident: label,
|
||||
suffixed: _,
|
||||
} => {
|
||||
Identifier { ident: label } => {
|
||||
match scope.introduce(label.into(), region) {
|
||||
Ok(symbol) => {
|
||||
output.references.insert_bound(symbol);
|
||||
|
|
|
@ -53,13 +53,11 @@ impl Scope {
|
|||
initial_ident_ids: IdentIds,
|
||||
starting_abilities_store: PendingAbilitiesStore,
|
||||
) -> Scope {
|
||||
let default_imports =
|
||||
// Add all `Apply` types.
|
||||
(Symbol::apply_types_in_scope().into_iter())
|
||||
// Add all tag names we might want to suggest as hints in error messages.
|
||||
.chain(Symbol::symbols_in_scope_for_hints());
|
||||
|
||||
let default_imports = default_imports.map(|(a, (b, c))| (a, b, c)).collect();
|
||||
// Add all `Apply` types.
|
||||
let default_imports = Symbol::apply_types_in_scope()
|
||||
.into_iter()
|
||||
.map(|(a, (b, c))| (a, b, c))
|
||||
.collect();
|
||||
|
||||
Scope {
|
||||
home,
|
||||
|
@ -728,13 +726,7 @@ mod test {
|
|||
|
||||
assert_eq!(
|
||||
&idents,
|
||||
&[
|
||||
Ident::from("Str"),
|
||||
Ident::from("List"),
|
||||
Ident::from("Box"),
|
||||
Ident::from("Ok"),
|
||||
Ident::from("Err"),
|
||||
]
|
||||
&[Ident::from("Str"), Ident::from("List"), Ident::from("Box"),]
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -751,13 +743,7 @@ mod test {
|
|||
|
||||
assert_eq!(
|
||||
&idents,
|
||||
&[
|
||||
Ident::from("Str"),
|
||||
Ident::from("List"),
|
||||
Ident::from("Box"),
|
||||
Ident::from("Ok"),
|
||||
Ident::from("Err"),
|
||||
]
|
||||
&[Ident::from("Str"), Ident::from("List"), Ident::from("Box"),]
|
||||
);
|
||||
|
||||
let builtin_count = idents.len();
|
||||
|
|
|
@ -6,7 +6,7 @@ use roc_error_macros::internal_error;
|
|||
use roc_module::called_via::CalledVia;
|
||||
use roc_module::ident::ModuleName;
|
||||
use roc_parse::ast::Expr::{self, *};
|
||||
use roc_parse::ast::{is_loc_expr_suffixed, Pattern, ValueDef};
|
||||
use roc_parse::ast::{is_expr_suffixed, Pattern, ValueDef, WhenBranch};
|
||||
use roc_region::all::{Loc, Region};
|
||||
use std::cell::Cell;
|
||||
|
||||
|
@ -31,11 +31,9 @@ fn next_suffixed_answer_pattern(arena: &Bump) -> (Expr, Pattern) {
|
|||
Expr::Var {
|
||||
module_name: "",
|
||||
ident: answer_ident,
|
||||
suffixed: 0,
|
||||
},
|
||||
Pattern::Identifier {
|
||||
ident: answer_ident.as_str(),
|
||||
suffixed: 0,
|
||||
},
|
||||
)
|
||||
})
|
||||
|
@ -95,63 +93,10 @@ pub fn unwrap_suffixed_expression<'a>(
|
|||
) -> Result<&'a Loc<Expr<'a>>, EUnwrapped<'a>> {
|
||||
let unwrapped_expression = {
|
||||
match loc_expr.value {
|
||||
Expr::Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed,
|
||||
} => {
|
||||
match suffixed {
|
||||
0 => Ok(loc_expr),
|
||||
1 => {
|
||||
let unwrapped_var = arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
Expr::Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed: suffixed.saturating_sub(1),
|
||||
},
|
||||
));
|
||||
Expr::TaskAwaitBang(sub_expr) => {
|
||||
let unwrapped_sub_expr = arena.alloc(Loc::at(loc_expr.region, *sub_expr));
|
||||
|
||||
init_unwrapped_err(arena, unwrapped_var, maybe_def_pat)
|
||||
}
|
||||
_ => {
|
||||
let unwrapped_var = arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
Expr::Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed: 0,
|
||||
},
|
||||
));
|
||||
|
||||
// we generate an intermediate pattern `#!a0` etc
|
||||
// so we dont unwrap the definition pattern
|
||||
let (mut answer_var, answer_pat) = next_suffixed_answer_pattern(arena);
|
||||
|
||||
// we transfer the suffix from the Var to the intermediate answer Var
|
||||
// as that will need to be unwrapped in a future call
|
||||
if let Expr::Var {
|
||||
module_name: "",
|
||||
ident: answer_ident,
|
||||
suffixed: 0,
|
||||
} = answer_var
|
||||
{
|
||||
answer_var = Expr::Var {
|
||||
module_name: "",
|
||||
ident: answer_ident,
|
||||
suffixed: suffixed.saturating_sub(1),
|
||||
}
|
||||
} else {
|
||||
internal_error!("expected a suffixed Var to be generated");
|
||||
}
|
||||
|
||||
Err(EUnwrapped::UnwrappedSubExpr {
|
||||
sub_arg: unwrapped_var,
|
||||
sub_pat: arena.alloc(Loc::at(unwrapped_var.region, answer_pat)),
|
||||
sub_new: arena.alloc(Loc::at(unwrapped_var.region, answer_var)),
|
||||
})
|
||||
}
|
||||
}
|
||||
init_unwrapped_err(arena, unwrapped_sub_expr, maybe_def_pat)
|
||||
}
|
||||
|
||||
Expr::Defs(..) => unwrap_suffixed_expression_defs_help(arena, loc_expr, maybe_def_pat),
|
||||
|
@ -192,7 +137,9 @@ pub fn unwrap_suffixed_expression<'a>(
|
|||
// KEEP THIS HERE FOR DEBUGGING
|
||||
// USEFUL TO SEE THE UNWRAPPING
|
||||
// OF AST NODES AS THEY DESCEND
|
||||
// dbg!(&loc_expr, &unwrapped_expression);
|
||||
// if is_expr_suffixed(&loc_expr.value) {
|
||||
// dbg!(&maybe_def_pat, &loc_expr, &unwrapped_expression);
|
||||
// }
|
||||
|
||||
unwrapped_expression
|
||||
}
|
||||
|
@ -246,19 +193,7 @@ pub fn unwrap_suffixed_expression_closure_help<'a>(
|
|||
) -> Result<&'a Loc<Expr<'a>>, EUnwrapped<'a>> {
|
||||
match loc_expr.value {
|
||||
Expr::Closure(closure_args, closure_loc_ret) => {
|
||||
|
||||
// Check to make sure that arguments are not suffixed
|
||||
let suffixed_arg_count = closure_args
|
||||
.iter()
|
||||
.filter(|loc_pat| loc_pat.value.is_suffixed())
|
||||
.count();
|
||||
|
||||
if suffixed_arg_count > 0 {
|
||||
debug_assert!(false,"closure arguments should not be suffixed");
|
||||
return Err(EUnwrapped::Malformed);
|
||||
}
|
||||
|
||||
// note we use `None` here as we don't want to pass a DefExpr up and
|
||||
// note we use `None` here as we don't want to pass a DefExpr up and
|
||||
// unwrap the definition pattern for the closure
|
||||
match unwrap_suffixed_expression(arena, closure_loc_ret, None) {
|
||||
Ok(unwrapped_expr) => {
|
||||
|
@ -314,21 +249,15 @@ pub fn unwrap_suffixed_expression_apply_help<'a>(
|
|||
}
|
||||
|
||||
// special case for when our Apply function is a suffixed Var (but not multiple suffixed)
|
||||
if let Expr::Var { module_name, ident, suffixed } = function.value {
|
||||
if suffixed == 1 {
|
||||
let unwrapped_function = arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
Expr::Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed: suffixed - 1,
|
||||
},
|
||||
));
|
||||
if let Expr::TaskAwaitBang(sub_expr) = function.value {
|
||||
let unwrapped_function = arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
*sub_expr,
|
||||
));
|
||||
|
||||
let new_apply = arena.alloc(Loc::at(loc_expr.region, Expr::Apply(unwrapped_function, local_args, called_via)));
|
||||
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);
|
||||
}
|
||||
return init_unwrapped_err(arena, new_apply, maybe_def_pat);
|
||||
}
|
||||
|
||||
// function is another expression
|
||||
|
@ -366,7 +295,7 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
|||
let (current_if_then_statement, current_if_then_expression) = if_then;
|
||||
|
||||
// unwrap suffixed (innermost) expressions e.g. `if true then doThing! then ...`
|
||||
if is_loc_expr_suffixed(current_if_then_expression) {
|
||||
if is_expr_suffixed(¤t_if_then_expression.value) {
|
||||
// split if_thens around the current index
|
||||
let (before, after) = roc_parse::ast::split_around(if_thens, index);
|
||||
|
||||
|
@ -396,29 +325,8 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
|||
sub_pat,
|
||||
sub_new,
|
||||
}) => {
|
||||
let ok_wrapped_return = arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
Expr::Apply(
|
||||
arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
Expr::Var {
|
||||
module_name: ModuleName::TASK,
|
||||
ident: "ok",
|
||||
suffixed: 0,
|
||||
},
|
||||
)),
|
||||
arena.alloc([sub_new]),
|
||||
CalledVia::BangSuffix,
|
||||
),
|
||||
));
|
||||
|
||||
let unwrapped_expression = apply_task_await(
|
||||
arena,
|
||||
sub_arg.region,
|
||||
sub_arg,
|
||||
sub_pat,
|
||||
ok_wrapped_return,
|
||||
);
|
||||
let unwrapped_expression =
|
||||
apply_task_await(arena, sub_arg.region, sub_arg, sub_pat, sub_new);
|
||||
|
||||
let mut new_if_thens = Vec::new_in(arena);
|
||||
|
||||
|
@ -443,7 +351,7 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
|||
// unwrap suffixed statements e.g. `if isThing! then ...`
|
||||
// note we want to split and nest if-then's so we only run Task's
|
||||
// that are required
|
||||
if is_loc_expr_suffixed(current_if_then_statement) {
|
||||
if is_expr_suffixed(¤t_if_then_statement.value) {
|
||||
// split if_thens around the current index
|
||||
let (before, after) = roc_parse::ast::split_around(if_thens, index);
|
||||
|
||||
|
@ -555,29 +463,8 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
|||
sub_pat,
|
||||
sub_new,
|
||||
}) => {
|
||||
let ok_wrapped_return = arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
Expr::Apply(
|
||||
arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
Expr::Var {
|
||||
module_name: ModuleName::TASK,
|
||||
ident: "ok",
|
||||
suffixed: 0,
|
||||
},
|
||||
)),
|
||||
arena.alloc([sub_new]),
|
||||
CalledVia::BangSuffix,
|
||||
),
|
||||
));
|
||||
|
||||
let unwrapped_final_else = apply_task_await(
|
||||
arena,
|
||||
sub_arg.region,
|
||||
sub_arg,
|
||||
sub_pat,
|
||||
ok_wrapped_return,
|
||||
);
|
||||
let unwrapped_final_else =
|
||||
apply_task_await(arena, sub_arg.region, sub_arg, sub_pat, sub_new);
|
||||
|
||||
let new_if = arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
|
@ -594,11 +481,61 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
|||
}
|
||||
|
||||
pub fn unwrap_suffixed_expression_when_help<'a>(
|
||||
_arena: &'a Bump,
|
||||
arena: &'a Bump,
|
||||
loc_expr: &'a Loc<Expr<'a>>,
|
||||
_maybe_def_pat: Option<&'a Loc<Pattern<'a>>>,
|
||||
maybe_def_pat: Option<&'a Loc<Pattern<'a>>>,
|
||||
) -> Result<&'a Loc<Expr<'a>>, EUnwrapped<'a>> {
|
||||
Ok(loc_expr)
|
||||
match loc_expr.value {
|
||||
Expr::When(condition, branches) => {
|
||||
|
||||
// first unwrap any when branches values
|
||||
// e.g.
|
||||
// when foo is
|
||||
// [] -> line! "bar"
|
||||
// _ -> line! "baz"
|
||||
for (branch_index, WhenBranch{value: branch_loc_expr,patterns, guard}) in branches.iter().enumerate() {
|
||||
|
||||
// if the branch isn't suffixed we can leave it alone
|
||||
if is_expr_suffixed(&branch_loc_expr.value) {
|
||||
let unwrapped_branch_value = match unwrap_suffixed_expression(arena, branch_loc_expr, None) {
|
||||
Ok(unwrapped_branch_value) => unwrapped_branch_value,
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => apply_task_await(arena, branch_loc_expr.region, sub_arg, sub_pat, sub_new),
|
||||
Err(..) => return Err(EUnwrapped::Malformed),
|
||||
};
|
||||
|
||||
let new_branch = WhenBranch{value: *unwrapped_branch_value, patterns, guard: *guard};
|
||||
let mut new_branches = Vec::new_in(arena);
|
||||
let (before, rest) = branches.split_at(branch_index);
|
||||
let after = &rest[1..];
|
||||
|
||||
new_branches.extend_from_slice(before);
|
||||
new_branches.push(arena.alloc(new_branch));
|
||||
new_branches.extend_from_slice(after);
|
||||
|
||||
let new_when = arena.alloc(Loc::at(loc_expr.region, Expr::When(condition, arena.alloc_slice_copy(new_branches.as_slice()))));
|
||||
|
||||
return unwrap_suffixed_expression(arena, new_when, maybe_def_pat);
|
||||
}
|
||||
}
|
||||
|
||||
// then unwrap the when condition
|
||||
match unwrap_suffixed_expression(arena, condition, None) {
|
||||
Ok(unwrapped_condition) => {
|
||||
let new_when = arena.alloc(Loc::at(loc_expr.region, Expr::When(unwrapped_condition, branches)));
|
||||
Ok(new_when)
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
||||
let new_when = arena.alloc(Loc::at(loc_expr.region, Expr::When(sub_new, branches)));
|
||||
let applied_task_await = apply_task_await(arena,loc_expr.region,sub_arg,sub_pat,new_when);
|
||||
Ok(applied_task_await)
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(..))
|
||||
| Err(EUnwrapped::Malformed) => Err(EUnwrapped::Malformed)
|
||||
}
|
||||
|
||||
}
|
||||
_ => internal_error!("unreachable, expected a When node to be passed into unwrap_suffixed_expression_defs_help"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unwrap_suffixed_expression_defs_help<'a>(
|
||||
|
@ -649,6 +586,7 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
|
|||
let next_expr = match unwrap_suffixed_expression(arena,loc_ret,maybe_def_pat) {
|
||||
Ok(next_expr) => next_expr,
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
||||
// We need to apply Task.ok here as the defs final expression was unwrapped
|
||||
apply_task_await(arena,def_expr.region,sub_arg,sub_pat,sub_new)
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(..)) | Err(EUnwrapped::Malformed) => {
|
||||
|
@ -764,7 +702,13 @@ pub fn apply_task_await<'a>(
|
|||
) -> &'a Loc<Expr<'a>> {
|
||||
// If the pattern and the new are the same then we don't need to unwrap anything
|
||||
// e.g. `Task.await foo \{} -> Task.ok {}` is the same as `foo`
|
||||
if is_pattern_empty_record(loc_pat) && is_expr_task_ok(loc_new) {
|
||||
if is_matching_empty_record(loc_pat, loc_new) {
|
||||
return loc_arg;
|
||||
}
|
||||
|
||||
// If the pattern and the new are matching answers then we don't need to unwrap anything
|
||||
// e.g. `Task.await foo \#!a1 -> Task.ok #!a1` is the same as `foo`
|
||||
if is_matching_intermediate_answer(loc_pat, loc_new) {
|
||||
return loc_arg;
|
||||
}
|
||||
|
||||
|
@ -789,7 +733,6 @@ pub fn apply_task_await<'a>(
|
|||
value: Var {
|
||||
module_name: ModuleName::TASK,
|
||||
ident: "await",
|
||||
suffixed: 0,
|
||||
},
|
||||
}),
|
||||
arena.alloc(task_await_apply_args),
|
||||
|
@ -798,33 +741,64 @@ pub fn apply_task_await<'a>(
|
|||
))
|
||||
}
|
||||
|
||||
fn is_pattern_empty_record<'a>(loc_pat: &'a Loc<Pattern<'a>>) -> bool {
|
||||
match loc_pat.value {
|
||||
fn extract_wrapped_task_ok_value<'a>(loc_expr: &'a Loc<Expr<'a>>) -> Option<&'a Loc<Expr<'a>>> {
|
||||
match loc_expr.value {
|
||||
Expr::Apply(function, arguments, _) => match function.value {
|
||||
Var {
|
||||
module_name, ident, ..
|
||||
} if module_name == ModuleName::TASK && ident == "ok" => arguments.first().copied(),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_matching_empty_record<'a>(
|
||||
loc_pat: &'a Loc<Pattern<'a>>,
|
||||
loc_expr: &'a Loc<Expr<'a>>,
|
||||
) -> bool {
|
||||
let is_empty_record = match extract_wrapped_task_ok_value(loc_expr) {
|
||||
Some(task_expr) => match task_expr.value {
|
||||
Expr::Record(collection) => collection.is_empty(),
|
||||
_ => false,
|
||||
},
|
||||
None => false,
|
||||
};
|
||||
|
||||
let is_pattern_empty_record = match loc_pat.value {
|
||||
Pattern::RecordDestructure(collection) => collection.is_empty(),
|
||||
_ => false,
|
||||
}
|
||||
};
|
||||
|
||||
is_empty_record && is_pattern_empty_record
|
||||
}
|
||||
|
||||
fn is_expr_task_ok<'a>(loc_expr: &'a Loc<Expr<'a>>) -> bool {
|
||||
match loc_expr.value {
|
||||
Expr::Apply(function, arguments, _) => {
|
||||
let is_task_ok = match function.value {
|
||||
Var {
|
||||
module_name, ident, ..
|
||||
} => module_name == ModuleName::TASK && ident == "ok",
|
||||
_ => false,
|
||||
};
|
||||
|
||||
let is_arg_empty_record = arguments
|
||||
.first()
|
||||
.map(|arg_loc_expr| match arg_loc_expr.value {
|
||||
Expr::Record(collection) => collection.is_empty(),
|
||||
_ => false,
|
||||
})
|
||||
.unwrap_or(false);
|
||||
|
||||
is_task_ok && is_arg_empty_record
|
||||
}
|
||||
pub fn is_matching_intermediate_answer<'a>(
|
||||
loc_pat: &'a Loc<Pattern<'a>>,
|
||||
loc_new: &'a Loc<Expr<'a>>,
|
||||
) -> bool {
|
||||
let pat_ident = match loc_pat.value {
|
||||
Pattern::Identifier { ident, .. } => Some(ident),
|
||||
_ => None,
|
||||
};
|
||||
let exp_ident = match loc_new.value {
|
||||
Expr::Var {
|
||||
module_name, ident, ..
|
||||
} if module_name.is_empty() && ident.starts_with('#') => Some(ident),
|
||||
_ => None,
|
||||
};
|
||||
let exp_ident_in_task = match extract_wrapped_task_ok_value(loc_new) {
|
||||
Some(task_expr) => match task_expr.value {
|
||||
Expr::Var {
|
||||
module_name, ident, ..
|
||||
} if module_name.is_empty() && ident.starts_with('#') => Some(ident),
|
||||
_ => None,
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
match (pat_ident, exp_ident, exp_ident_in_task) {
|
||||
(Some(a), Some(b), None) => a == b,
|
||||
(Some(a), None, Some(b)) => a == b,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -9,7 +9,7 @@ use crate::spaces::{
|
|||
use crate::Buf;
|
||||
use roc_module::called_via::{self, BinOp};
|
||||
use roc_parse::ast::{
|
||||
is_loc_expr_suffixed, AssignedField, Base, Collection, CommentOrNewline, Expr, ExtractSpaces,
|
||||
is_expr_suffixed, AssignedField, Base, Collection, CommentOrNewline, Expr, ExtractSpaces,
|
||||
Pattern, RecordBuilderField, WhenBranch,
|
||||
};
|
||||
use roc_parse::ast::{StrLiteral, StrSegment};
|
||||
|
@ -38,9 +38,7 @@ impl<'a> Formattable for Expr<'a> {
|
|||
| Num(..)
|
||||
| NonBase10Int { .. }
|
||||
| SingleQuote(_)
|
||||
| RecordAccess(_, _)
|
||||
| AccessorFunction(_)
|
||||
| TupleAccess(_, _)
|
||||
| Var { .. }
|
||||
| Underscore { .. }
|
||||
| MalformedIdent(_, _)
|
||||
|
@ -51,6 +49,10 @@ impl<'a> Formattable for Expr<'a> {
|
|||
| EmptyDefsFinal
|
||||
| Crash => false,
|
||||
|
||||
RecordAccess(inner, _) | TupleAccess(inner, _) | TaskAwaitBang(inner) => {
|
||||
inner.is_multiline()
|
||||
}
|
||||
|
||||
// These expressions always have newlines
|
||||
Defs(_, _) | When(_, _) => true,
|
||||
|
||||
|
@ -170,11 +172,7 @@ impl<'a> Formattable for Expr<'a> {
|
|||
Str(literal) => {
|
||||
fmt_str_literal(buf, *literal, indent);
|
||||
}
|
||||
Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed,
|
||||
} => {
|
||||
Var { module_name, ident } => {
|
||||
buf.indent(indent);
|
||||
if !module_name.is_empty() {
|
||||
buf.push_str(module_name);
|
||||
|
@ -182,11 +180,6 @@ impl<'a> Formattable for Expr<'a> {
|
|||
}
|
||||
|
||||
buf.push_str(ident);
|
||||
|
||||
let count: u8 = *suffixed;
|
||||
for _ in 0..count {
|
||||
buf.push('!');
|
||||
}
|
||||
}
|
||||
Underscore(name) => {
|
||||
buf.indent(indent);
|
||||
|
@ -512,60 +505,18 @@ impl<'a> Formattable for Expr<'a> {
|
|||
}
|
||||
}
|
||||
RecordAccess(expr, key) => {
|
||||
// Check for any `!` suffixes and format these at the end of expression
|
||||
let (expr_to_format, suffix_count) = if let Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed,
|
||||
} = expr
|
||||
{
|
||||
(
|
||||
Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed: 0,
|
||||
},
|
||||
suffixed,
|
||||
)
|
||||
} else {
|
||||
(**expr, &0u8)
|
||||
};
|
||||
|
||||
expr_to_format.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
||||
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
||||
buf.push('.');
|
||||
buf.push_str(key);
|
||||
|
||||
for _ in 0..*suffix_count {
|
||||
buf.push('!');
|
||||
}
|
||||
}
|
||||
TupleAccess(expr, key) => {
|
||||
// Check for any `!` suffixes and format these at the end of expression
|
||||
let (expr_to_format, suffix_count) = if let Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed,
|
||||
} = expr
|
||||
{
|
||||
(
|
||||
Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed: 0,
|
||||
},
|
||||
suffixed,
|
||||
)
|
||||
} else {
|
||||
(**expr, &0u8)
|
||||
};
|
||||
|
||||
expr_to_format.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
||||
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
||||
buf.push('.');
|
||||
buf.push_str(key);
|
||||
|
||||
for _ in 0..*suffix_count {
|
||||
buf.push('!');
|
||||
}
|
||||
}
|
||||
TaskAwaitBang(expr) => {
|
||||
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
||||
buf.push('!');
|
||||
}
|
||||
MalformedIdent(str, _) => {
|
||||
buf.indent(indent);
|
||||
|
@ -789,8 +740,8 @@ fn fmt_binops<'a>(
|
|||
|| loc_right_side.value.is_multiline()
|
||||
|| lefts.iter().any(|(expr, _)| expr.value.is_multiline());
|
||||
|
||||
let is_any_lefts_suffixed = lefts.iter().any(|(left, _)| is_loc_expr_suffixed(left));
|
||||
let is_right_suffixed = is_loc_expr_suffixed(loc_right_side);
|
||||
let is_any_lefts_suffixed = lefts.iter().any(|(left, _)| is_expr_suffixed(&left.value));
|
||||
let is_right_suffixed = is_expr_suffixed(&loc_right_side.value);
|
||||
let is_any_suffixed = is_any_lefts_suffixed || is_right_suffixed;
|
||||
|
||||
let mut is_first = false;
|
||||
|
|
|
@ -88,16 +88,9 @@ impl<'a> Formattable for Pattern<'a> {
|
|||
use self::Pattern::*;
|
||||
|
||||
match self {
|
||||
Identifier {
|
||||
ident: string,
|
||||
suffixed,
|
||||
} => {
|
||||
Identifier { ident: string } => {
|
||||
buf.indent(indent);
|
||||
buf.push_str(string);
|
||||
|
||||
for _ in 0..*suffixed {
|
||||
buf.push('!');
|
||||
}
|
||||
}
|
||||
Tag(name) | OpaqueRef(name) => {
|
||||
buf.indent(indent);
|
||||
|
@ -277,21 +270,13 @@ impl<'a> Formattable for Pattern<'a> {
|
|||
buf.indent(indent);
|
||||
buf.push_str(string);
|
||||
}
|
||||
QualifiedIdentifier {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed,
|
||||
} => {
|
||||
QualifiedIdentifier { module_name, ident } => {
|
||||
buf.indent(indent);
|
||||
if !module_name.is_empty() {
|
||||
buf.push_str(module_name);
|
||||
buf.push('.');
|
||||
}
|
||||
|
||||
for _ in 0..*suffixed {
|
||||
buf.push('!');
|
||||
}
|
||||
|
||||
buf.push_str(ident);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -686,6 +686,7 @@ impl<'a> RemoveSpaces<'a> for Expr<'a> {
|
|||
Expr::RecordAccess(a, b) => Expr::RecordAccess(arena.alloc(a.remove_spaces(arena)), b),
|
||||
Expr::AccessorFunction(a) => Expr::AccessorFunction(a),
|
||||
Expr::TupleAccess(a, b) => Expr::TupleAccess(arena.alloc(a.remove_spaces(arena)), b),
|
||||
Expr::TaskAwaitBang(a) => Expr::TaskAwaitBang(arena.alloc(a.remove_spaces(arena))),
|
||||
Expr::List(a) => Expr::List(a.remove_spaces(arena)),
|
||||
Expr::RecordUpdate { update, fields } => Expr::RecordUpdate {
|
||||
update: arena.alloc(update.remove_spaces(arena)),
|
||||
|
@ -694,15 +695,7 @@ impl<'a> RemoveSpaces<'a> for Expr<'a> {
|
|||
Expr::Record(a) => Expr::Record(a.remove_spaces(arena)),
|
||||
Expr::RecordBuilder(a) => Expr::RecordBuilder(a.remove_spaces(arena)),
|
||||
Expr::Tuple(a) => Expr::Tuple(a.remove_spaces(arena)),
|
||||
Expr::Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed,
|
||||
} => Expr::Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed,
|
||||
},
|
||||
Expr::Var { module_name, ident } => Expr::Var { module_name, ident },
|
||||
Expr::Underscore(a) => Expr::Underscore(a),
|
||||
Expr::Tag(a) => Expr::Tag(a),
|
||||
Expr::OpaqueRef(a) => Expr::OpaqueRef(a),
|
||||
|
@ -802,7 +795,7 @@ fn remove_spaces_bad_ident(ident: BadIdent) -> BadIdent {
|
|||
impl<'a> RemoveSpaces<'a> for Pattern<'a> {
|
||||
fn remove_spaces(&self, arena: &'a Bump) -> Self {
|
||||
match *self {
|
||||
Pattern::Identifier { ident, suffixed } => Pattern::Identifier { ident, suffixed },
|
||||
Pattern::Identifier { ident } => Pattern::Identifier { ident },
|
||||
Pattern::Tag(a) => Pattern::Tag(a),
|
||||
Pattern::OpaqueRef(a) => Pattern::OpaqueRef(a),
|
||||
Pattern::Apply(a, b) => Pattern::Apply(
|
||||
|
@ -835,15 +828,9 @@ impl<'a> RemoveSpaces<'a> for Pattern<'a> {
|
|||
Pattern::Underscore(a) => Pattern::Underscore(a),
|
||||
Pattern::Malformed(a) => Pattern::Malformed(a),
|
||||
Pattern::MalformedIdent(a, b) => Pattern::MalformedIdent(a, remove_spaces_bad_ident(b)),
|
||||
Pattern::QualifiedIdentifier {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed,
|
||||
} => Pattern::QualifiedIdentifier {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed,
|
||||
},
|
||||
Pattern::QualifiedIdentifier { module_name, ident } => {
|
||||
Pattern::QualifiedIdentifier { module_name, ident }
|
||||
}
|
||||
Pattern::SpaceBefore(a, _) => a.remove_spaces(arena),
|
||||
Pattern::SpaceAfter(a, _) => a.remove_spaces(arena),
|
||||
Pattern::SingleQuote(a) => Pattern::SingleQuote(a),
|
||||
|
|
|
@ -647,7 +647,7 @@ mod test_reporting {
|
|||
if true then 1 else 2
|
||||
"
|
||||
),
|
||||
@r"
|
||||
@r###"
|
||||
── UNRECOGNIZED NAME in /code/proj/Main.roc ────────────────────────────────────
|
||||
|
||||
Nothing is named `true` in this scope.
|
||||
|
@ -657,11 +657,11 @@ mod test_reporting {
|
|||
|
||||
Did you mean one of these?
|
||||
|
||||
Str
|
||||
Frac
|
||||
Num
|
||||
Str
|
||||
Err
|
||||
"
|
||||
U8
|
||||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
|
@ -812,10 +812,10 @@ mod test_reporting {
|
|||
|
||||
Did you mean one of these?
|
||||
|
||||
Ok
|
||||
List
|
||||
Err
|
||||
Box
|
||||
Str
|
||||
isDisabled
|
||||
"
|
||||
),
|
||||
);
|
||||
|
@ -2212,10 +2212,10 @@ mod test_reporting {
|
|||
|
||||
Did you mean one of these?
|
||||
|
||||
Ok
|
||||
U8
|
||||
Box
|
||||
Eq
|
||||
f
|
||||
"
|
||||
);
|
||||
|
||||
|
@ -5805,9 +5805,9 @@ All branches in an `if` must have the same type!
|
|||
Did you mean one of these?
|
||||
|
||||
Str
|
||||
Err
|
||||
U8
|
||||
F64
|
||||
Box
|
||||
"###
|
||||
);
|
||||
|
||||
|
|
|
@ -212,11 +212,7 @@ fn generate_entry_docs(
|
|||
match either_index.split() {
|
||||
Err(value_index) => match &defs.value_defs[value_index.index()] {
|
||||
ValueDef::Annotation(loc_pattern, loc_ann) => {
|
||||
if let Pattern::Identifier {
|
||||
ident: identifier,
|
||||
suffixed: _,
|
||||
} = loc_pattern.value
|
||||
{
|
||||
if let Pattern::Identifier { ident: identifier } = loc_pattern.value {
|
||||
// Check if this module exposes the def
|
||||
if let Some(ident_id) = ident_ids.get_id(identifier) {
|
||||
let name = identifier.to_string();
|
||||
|
@ -237,11 +233,7 @@ fn generate_entry_docs(
|
|||
ann_type,
|
||||
..
|
||||
} => {
|
||||
if let Pattern::Identifier {
|
||||
ident: identifier,
|
||||
suffixed: _,
|
||||
} = ann_pattern.value
|
||||
{
|
||||
if let Pattern::Identifier { ident: identifier } = ann_pattern.value {
|
||||
// Check if this module exposes the def
|
||||
if let Some(ident_id) = ident_ids.get_id(identifier) {
|
||||
let doc_def = DocDef {
|
||||
|
@ -257,11 +249,7 @@ fn generate_entry_docs(
|
|||
}
|
||||
|
||||
ValueDef::Body(pattern, _) => {
|
||||
if let Pattern::Identifier {
|
||||
ident: identifier,
|
||||
suffixed: _,
|
||||
} = pattern.value
|
||||
{
|
||||
if let Pattern::Identifier { ident: identifier } = pattern.value {
|
||||
// Check if this module exposes the def
|
||||
if let Some(ident_id) = ident_ids.get_id(identifier) {
|
||||
let doc_def = DocDef {
|
||||
|
@ -316,11 +304,7 @@ fn generate_entry_docs(
|
|||
let mut type_vars = Vec::new();
|
||||
|
||||
for var in vars.iter() {
|
||||
if let Pattern::Identifier {
|
||||
ident: ident_name,
|
||||
suffixed: _,
|
||||
} = var.value
|
||||
{
|
||||
if let Pattern::Identifier { ident: ident_name } = var.value {
|
||||
type_vars.push(ident_name.to_string());
|
||||
}
|
||||
}
|
||||
|
@ -354,11 +338,7 @@ fn generate_entry_docs(
|
|||
let mut type_vars = Vec::new();
|
||||
|
||||
for var in vars.iter() {
|
||||
if let Pattern::Identifier {
|
||||
ident: ident_name,
|
||||
suffixed: _,
|
||||
} = var.value
|
||||
{
|
||||
if let Pattern::Identifier { ident: ident_name } = var.value {
|
||||
type_vars.push(ident_name.to_string());
|
||||
}
|
||||
}
|
||||
|
@ -382,11 +362,7 @@ fn generate_entry_docs(
|
|||
let mut type_vars = Vec::new();
|
||||
|
||||
for var in vars.iter() {
|
||||
if let Pattern::Identifier {
|
||||
ident: ident_name,
|
||||
suffixed: _,
|
||||
} = var.value
|
||||
{
|
||||
if let Pattern::Identifier { ident: ident_name } = var.value {
|
||||
type_vars.push(ident_name.to_string());
|
||||
}
|
||||
}
|
||||
|
@ -648,7 +624,7 @@ fn type_to_docs(in_func_type_ann: bool, type_annotation: ast::TypeAnnotation) ->
|
|||
.vars
|
||||
.iter()
|
||||
.filter_map(|loc_pattern| match loc_pattern.value {
|
||||
ast::Pattern::Identifier { ident, suffixed: _ } => Some(ident.to_string()),
|
||||
ast::Pattern::Identifier { ident } => Some(ident.to_string()),
|
||||
_ => None,
|
||||
})
|
||||
.collect(),
|
||||
|
|
|
@ -2161,11 +2161,25 @@ fn report_unused_imported_modules(
|
|||
Occupied(entry) => entry.into_mut(),
|
||||
};
|
||||
|
||||
for (unused, region) in unused_imported_modules.drain() {
|
||||
if !unused.is_builtin() {
|
||||
existing.push(roc_problem::can::Problem::UnusedModuleImport(
|
||||
unused, region,
|
||||
));
|
||||
// TODO this outer conditional can be replaced by just the for loop
|
||||
// once we have Task as builtin. (Also the for loop doesn't need the "Task" check.)
|
||||
if !unused_imported_modules.is_empty() {
|
||||
let module_ids = Arc::clone(&state.arc_modules);
|
||||
let module_ids = module_ids.lock();
|
||||
|
||||
for (unused, region) in unused_imported_modules.drain() {
|
||||
if !unused.is_builtin() {
|
||||
let is_task_module = match module_ids.get_name(unused) {
|
||||
Some(name) => name.as_inner().as_str() == "Task",
|
||||
None => false,
|
||||
};
|
||||
|
||||
if !is_task_module {
|
||||
existing.push(roc_problem::can::Problem::UnusedModuleImport(
|
||||
unused, region,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3381,6 +3395,7 @@ fn finish(
|
|||
|
||||
LoadedModule {
|
||||
module_id: state.root_id,
|
||||
filename: state.root_path,
|
||||
interns,
|
||||
solved,
|
||||
can_problems: state.module_cache.can_problems,
|
||||
|
@ -5648,13 +5663,7 @@ fn value_def_from_imports<'a>(
|
|||
};
|
||||
let typed_ident = typed_ident.extract_spaces().item;
|
||||
let Loc { region, value } = typed_ident.ident;
|
||||
let ident = arena.alloc(Loc::at(
|
||||
region,
|
||||
Pattern::Identifier {
|
||||
ident: value,
|
||||
suffixed: 0,
|
||||
},
|
||||
));
|
||||
let ident = arena.alloc(Loc::at(region, Pattern::Identifier { ident: value }));
|
||||
|
||||
let ann_type = arena.alloc(typed_ident.ann);
|
||||
Some(ValueDef::AnnotatedBody {
|
||||
|
|
|
@ -30,6 +30,7 @@ use std::time::{Duration, Instant};
|
|||
#[derive(Debug)]
|
||||
pub struct LoadedModule {
|
||||
pub module_id: ModuleId,
|
||||
pub filename: PathBuf,
|
||||
pub interns: Interns,
|
||||
pub solved: Solved<Subs>,
|
||||
pub can_problems: MutMap<ModuleId, Vec<roc_problem::can::Problem>>,
|
||||
|
@ -54,6 +55,13 @@ pub struct LoadedModule {
|
|||
}
|
||||
|
||||
impl LoadedModule {
|
||||
/// Infer the filename for the given ModuleId, based on this root module's filename.
|
||||
pub fn filename(&self, module_id: ModuleId) -> PathBuf {
|
||||
let module_name = self.interns.module_name(module_id);
|
||||
|
||||
module_name.filename(&self.filename)
|
||||
}
|
||||
|
||||
pub fn total_problems(&self) -> usize {
|
||||
let mut total = 0;
|
||||
|
||||
|
|
|
@ -989,8 +989,8 @@ fn issue_2863_module_type_does_not_exist() {
|
|||
Did you mean one of these?
|
||||
|
||||
Decoding
|
||||
Dict
|
||||
Result
|
||||
Dict
|
||||
DecodeError
|
||||
"
|
||||
)
|
||||
|
@ -1280,7 +1280,7 @@ fn roc_file_no_extension() {
|
|||
indoc!(
|
||||
r#"
|
||||
app "helloWorld"
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.9.0/oKWkaruh2zXxin_xfsYsCJobH1tO8_JvNkFzDwwzNUQ.tar.br" }
|
||||
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" }
|
||||
imports [pf.Stdout]
|
||||
provides [main] to pf
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
pub use roc_ident::IdentStr;
|
||||
use std::fmt::{self, Debug};
|
||||
use std::{
|
||||
fmt::{self, Debug},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use crate::symbol::PQModuleName;
|
||||
|
||||
|
@ -45,6 +48,19 @@ impl<'a> QualifiedModuleName<'a> {
|
|||
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct ModuleName(IdentStr);
|
||||
|
||||
impl ModuleName {
|
||||
/// Given the root module's path, infer this module's path based on its name.
|
||||
pub fn filename(&self, root_filename: impl AsRef<Path>) -> PathBuf {
|
||||
let mut answer = root_filename.as_ref().with_file_name("");
|
||||
|
||||
for part in self.split('.') {
|
||||
answer = answer.join(part);
|
||||
}
|
||||
|
||||
answer.with_extension("roc")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for ModuleName {
|
||||
type Target = str;
|
||||
|
||||
|
|
|
@ -876,7 +876,6 @@ macro_rules! define_builtins {
|
|||
module_id.register_debug_idents(&ident_ids);
|
||||
}
|
||||
|
||||
|
||||
exposed_idents_by_module.insert(
|
||||
module_id,
|
||||
ident_ids
|
||||
|
@ -1016,27 +1015,6 @@ macro_rules! define_builtins {
|
|||
m => roc_error_macros::internal_error!("{:?} is not a builtin module!", m),
|
||||
}
|
||||
}
|
||||
|
||||
/// Symbols that should be added to the default scope, for hints as suggestions of
|
||||
/// names you might want to use.
|
||||
///
|
||||
/// TODO: this is a hack to get tag names to show up in error messages as suggestions,
|
||||
/// really we should be extracting tag names from candidate type aliases in scope.
|
||||
pub fn symbols_in_scope_for_hints() -> VecMap<Ident, (Symbol, Region)> {
|
||||
let mut scope = VecMap::default();
|
||||
|
||||
$(
|
||||
$(
|
||||
$(
|
||||
if $in_scope_for_hints {
|
||||
scope.insert($ident_name.into(), (Symbol::new(ModuleId::$module_const, IdentId($ident_id)), Region::zero()));
|
||||
}
|
||||
)?
|
||||
)*
|
||||
)+
|
||||
|
||||
scope
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1434,15 +1412,13 @@ define_builtins! {
|
|||
}
|
||||
7 RESULT: "Result" => {
|
||||
0 RESULT_RESULT: "Result" exposed_type=true // the Result.Result type alias
|
||||
1 RESULT_OK: "Ok" in_scope_for_hints=true // Result.Result a e = [Ok a, Err e]
|
||||
2 RESULT_ERR: "Err" in_scope_for_hints=true // Result.Result a e = [Ok a, Err e]
|
||||
1 RESULT_IS_ERR: "isErr"
|
||||
2 RESULT_ON_ERR: "onErr"
|
||||
3 RESULT_MAP: "map"
|
||||
4 RESULT_MAP_ERR: "mapErr"
|
||||
5 RESULT_WITH_DEFAULT: "withDefault"
|
||||
6 RESULT_TRY: "try"
|
||||
7 RESULT_IS_OK: "isOk"
|
||||
8 RESULT_IS_ERR: "isErr"
|
||||
9 RESULT_ON_ERR: "onErr"
|
||||
}
|
||||
8 DICT: "Dict" => {
|
||||
0 DICT_DICT: "Dict" exposed_type=true // the Dict.Dict type alias
|
||||
|
|
|
@ -251,7 +251,7 @@ pub enum Expr<'a> {
|
|||
is_negative: bool,
|
||||
},
|
||||
|
||||
// String Literals
|
||||
/// String Literals
|
||||
Str(StrLiteral<'a>), // string without escapes in it
|
||||
/// eg 'b'
|
||||
SingleQuote(&'a str),
|
||||
|
@ -265,6 +265,9 @@ pub enum Expr<'a> {
|
|||
/// Look up exactly one field on a tuple, e.g. `(x, y).1`.
|
||||
TupleAccess(&'a Expr<'a>, &'a str),
|
||||
|
||||
/// Task await bang - i.e. the ! in `File.readUtf8! path`
|
||||
TaskAwaitBang(&'a Expr<'a>),
|
||||
|
||||
// Collection Literals
|
||||
List(Collection<'a, &'a Loc<Expr<'a>>>),
|
||||
|
||||
|
@ -287,7 +290,6 @@ pub enum Expr<'a> {
|
|||
Var {
|
||||
module_name: &'a str, // module_name will only be filled if the original Roc code stated something like `5 + SomeModule.myVar`, module_name will be blank if it was `5 + myVar`
|
||||
ident: &'a str,
|
||||
suffixed: u8, // how many `!` suffixes, for example `doTheThing!!` executes a Task that returns a Task
|
||||
},
|
||||
|
||||
Underscore(&'a str),
|
||||
|
@ -354,17 +356,6 @@ pub enum Expr<'a> {
|
|||
}
|
||||
|
||||
impl Expr<'_> {
|
||||
pub fn increment_var_suffix(&mut self, count: u8) {
|
||||
match self {
|
||||
Expr::Var { suffixed, .. } => {
|
||||
*suffixed += count;
|
||||
}
|
||||
_ => {
|
||||
internal_error!("increment_var_suffix called on non-Var expression");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_region_spanning_binops(&self) -> Region {
|
||||
match self {
|
||||
Expr::BinOps(firsts, last) => {
|
||||
|
@ -391,45 +382,43 @@ pub fn split_loc_exprs_around<'a>(
|
|||
(before, after)
|
||||
}
|
||||
|
||||
pub fn is_loc_expr_suffixed(loc_expr: &Loc<Expr>) -> bool {
|
||||
match loc_expr.value.extract_spaces().item {
|
||||
pub fn is_expr_suffixed(expr: &Expr) -> bool {
|
||||
match expr {
|
||||
// expression without arguments, `read!`
|
||||
Expr::Var { suffixed, .. } => suffixed > 0,
|
||||
Expr::Var { .. } => false,
|
||||
|
||||
Expr::TaskAwaitBang(..) => true,
|
||||
|
||||
// expression with arguments, `line! "Foo"`
|
||||
Expr::Apply(sub_loc_expr, apply_args, _) => {
|
||||
let is_function_suffixed = is_loc_expr_suffixed(sub_loc_expr);
|
||||
let any_args_suffixed = apply_args.iter().any(|arg| is_loc_expr_suffixed(arg));
|
||||
let is_function_suffixed = is_expr_suffixed(&sub_loc_expr.value);
|
||||
let any_args_suffixed = apply_args.iter().any(|arg| is_expr_suffixed(&arg.value));
|
||||
|
||||
any_args_suffixed || is_function_suffixed
|
||||
}
|
||||
|
||||
// expression in a pipeline, `"hi" |> say!`
|
||||
Expr::BinOps(firsts, last) => {
|
||||
let is_expr_suffixed = is_loc_expr_suffixed(last);
|
||||
let any_chain_suffixed = firsts
|
||||
firsts
|
||||
.iter()
|
||||
.any(|(chain_loc_expr, _)| is_loc_expr_suffixed(chain_loc_expr));
|
||||
|
||||
is_expr_suffixed || any_chain_suffixed
|
||||
.any(|(chain_loc_expr, _)| is_expr_suffixed(&chain_loc_expr.value))
|
||||
|| is_expr_suffixed(&last.value)
|
||||
}
|
||||
|
||||
// expression in a if-then-else, `if isOk! then "ok" else doSomething!`
|
||||
Expr::If(if_thens, final_else) => {
|
||||
let any_if_thens_suffixed = if_thens.iter().any(|(if_then, else_expr)| {
|
||||
is_loc_expr_suffixed(if_then) || is_loc_expr_suffixed(else_expr)
|
||||
is_expr_suffixed(&if_then.value) || is_expr_suffixed(&else_expr.value)
|
||||
});
|
||||
|
||||
is_loc_expr_suffixed(final_else) || any_if_thens_suffixed
|
||||
is_expr_suffixed(&final_else.value) || any_if_thens_suffixed
|
||||
}
|
||||
|
||||
// expression in parens `(read!)`
|
||||
Expr::ParensAround(sub_loc_expr) => {
|
||||
is_loc_expr_suffixed(&Loc::at(loc_expr.region, *sub_loc_expr))
|
||||
}
|
||||
Expr::ParensAround(sub_loc_expr) => is_expr_suffixed(sub_loc_expr),
|
||||
|
||||
// expression in a closure
|
||||
Expr::Closure(_, sub_loc_expr) => is_loc_expr_suffixed(sub_loc_expr),
|
||||
Expr::Closure(_, sub_loc_expr) => is_expr_suffixed(&sub_loc_expr.value),
|
||||
|
||||
// expressions inside a Defs
|
||||
// note we ignore the final expression as it should not be suffixed
|
||||
|
@ -437,16 +426,81 @@ pub fn is_loc_expr_suffixed(loc_expr: &Loc<Expr>) -> bool {
|
|||
let any_defs_suffixed = defs.tags.iter().any(|tag| match tag.split() {
|
||||
Ok(_) => false,
|
||||
Err(value_index) => match defs.value_defs[value_index.index()] {
|
||||
ValueDef::Body(_, loc_expr) => is_loc_expr_suffixed(loc_expr),
|
||||
ValueDef::AnnotatedBody { body_expr, .. } => is_loc_expr_suffixed(body_expr),
|
||||
ValueDef::Body(_, loc_expr) => is_expr_suffixed(&loc_expr.value),
|
||||
ValueDef::AnnotatedBody { body_expr, .. } => is_expr_suffixed(&body_expr.value),
|
||||
_ => false,
|
||||
},
|
||||
});
|
||||
|
||||
any_defs_suffixed
|
||||
}
|
||||
Expr::Float(_) => false,
|
||||
Expr::Num(_) => false,
|
||||
Expr::NonBase10Int { .. } => false,
|
||||
Expr::Str(_) => false,
|
||||
Expr::SingleQuote(_) => false,
|
||||
Expr::RecordAccess(a, _) => is_expr_suffixed(a),
|
||||
Expr::AccessorFunction(_) => false,
|
||||
Expr::TupleAccess(a, _) => is_expr_suffixed(a),
|
||||
Expr::List(items) => items.iter().any(|x| is_expr_suffixed(&x.value)),
|
||||
Expr::RecordUpdate { update, fields } => {
|
||||
is_expr_suffixed(&update.value)
|
||||
|| fields
|
||||
.iter()
|
||||
.any(|field| is_assigned_value_suffixed(&field.value))
|
||||
}
|
||||
Expr::Record(items) => items
|
||||
.iter()
|
||||
.any(|field| is_assigned_value_suffixed(&field.value)),
|
||||
Expr::Tuple(items) => items.iter().any(|x| is_expr_suffixed(&x.value)),
|
||||
Expr::RecordBuilder(items) => items
|
||||
.iter()
|
||||
.any(|rbf| is_record_builder_field_suffixed(&rbf.value)),
|
||||
Expr::IngestedFile(_, _) => false,
|
||||
Expr::Underscore(_) => false,
|
||||
Expr::Crash => false,
|
||||
Expr::Tag(_) => false,
|
||||
Expr::OpaqueRef(_) => false,
|
||||
Expr::EmptyDefsFinal => false,
|
||||
Expr::Backpassing(_, _, _) => false, // TODO: we might want to check this?
|
||||
Expr::Expect(a, b) | Expr::Dbg(a, b) => {
|
||||
is_expr_suffixed(&a.value) || is_expr_suffixed(&b.value)
|
||||
}
|
||||
Expr::LowLevelDbg(_, _, _) => todo!(),
|
||||
Expr::UnaryOp(a, _) => is_expr_suffixed(&a.value),
|
||||
Expr::When(a, _) => is_expr_suffixed(&a.value),
|
||||
Expr::SpaceBefore(a, _) => is_expr_suffixed(a),
|
||||
Expr::SpaceAfter(a, _) => is_expr_suffixed(a),
|
||||
Expr::MalformedIdent(_, _) => false,
|
||||
Expr::MalformedClosure => false,
|
||||
Expr::MalformedSuffixed(_) => false,
|
||||
Expr::PrecedenceConflict(_) => false,
|
||||
Expr::MultipleRecordBuilders(_) => false,
|
||||
Expr::UnappliedRecordBuilder(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
_ => false,
|
||||
fn is_assigned_value_suffixed<'a>(value: &AssignedField<'a, Expr<'a>>) -> bool {
|
||||
match value {
|
||||
AssignedField::RequiredValue(_, _, a) | AssignedField::OptionalValue(_, _, a) => {
|
||||
is_expr_suffixed(&a.value)
|
||||
}
|
||||
AssignedField::LabelOnly(_) => false,
|
||||
AssignedField::SpaceBefore(a, _) | AssignedField::SpaceAfter(a, _) => {
|
||||
is_assigned_value_suffixed(a)
|
||||
}
|
||||
AssignedField::Malformed(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_record_builder_field_suffixed(field: &RecordBuilderField<'_>) -> bool {
|
||||
match field {
|
||||
RecordBuilderField::Value(_, _, a) => is_expr_suffixed(&a.value),
|
||||
RecordBuilderField::ApplyValue(_, _, _, a) => is_expr_suffixed(&a.value),
|
||||
RecordBuilderField::LabelOnly(_) => false,
|
||||
RecordBuilderField::SpaceBefore(a, _) => is_record_builder_field_suffixed(a),
|
||||
RecordBuilderField::SpaceAfter(a, _) => is_record_builder_field_suffixed(a),
|
||||
RecordBuilderField::Malformed(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -647,13 +701,13 @@ impl<'a> Defs<'a> {
|
|||
..
|
||||
},
|
||||
loc_expr,
|
||||
) if collection.is_empty() && is_loc_expr_suffixed(loc_expr) => {
|
||||
) if collection.is_empty() && is_expr_suffixed(&loc_expr.value) => {
|
||||
let mut new_defs = self.clone();
|
||||
new_defs.remove_value_def(tag_index);
|
||||
|
||||
return Some((new_defs, loc_expr));
|
||||
}
|
||||
ValueDef::Stmt(loc_expr) if is_loc_expr_suffixed(loc_expr) => {
|
||||
ValueDef::Stmt(loc_expr) if is_expr_suffixed(&loc_expr.value) => {
|
||||
let mut new_defs = self.clone();
|
||||
new_defs.remove_value_def(tag_index);
|
||||
|
||||
|
@ -1076,12 +1130,10 @@ pub enum Pattern<'a> {
|
|||
// Identifier
|
||||
Identifier {
|
||||
ident: &'a str,
|
||||
suffixed: u8,
|
||||
},
|
||||
QualifiedIdentifier {
|
||||
module_name: &'a str,
|
||||
ident: &'a str,
|
||||
suffixed: u8,
|
||||
},
|
||||
|
||||
Tag(&'a str),
|
||||
|
@ -1199,21 +1251,11 @@ impl<'a> Pattern<'a> {
|
|||
// { x, y } : { x : Int, y ? Bool }
|
||||
// { x, y ? False } = rec
|
||||
OptionalField(x, _) => match other {
|
||||
Identifier {
|
||||
ident: y,
|
||||
suffixed: 0,
|
||||
}
|
||||
| OptionalField(y, _) => x == y,
|
||||
Identifier { ident: y } | OptionalField(y, _) => x == y,
|
||||
_ => false,
|
||||
},
|
||||
Identifier {
|
||||
ident: x,
|
||||
suffixed: a,
|
||||
} => match other {
|
||||
Identifier {
|
||||
ident: y,
|
||||
suffixed: b,
|
||||
} => x == y && a == b,
|
||||
Identifier { ident: x } => match other {
|
||||
Identifier { ident: y } => x == y,
|
||||
OptionalField(y, _) => x == y,
|
||||
_ => false,
|
||||
},
|
||||
|
@ -1275,15 +1317,13 @@ impl<'a> Pattern<'a> {
|
|||
QualifiedIdentifier {
|
||||
module_name: a,
|
||||
ident: x,
|
||||
suffixed: i,
|
||||
} => {
|
||||
if let QualifiedIdentifier {
|
||||
module_name: b,
|
||||
ident: y,
|
||||
suffixed: j,
|
||||
} = other
|
||||
{
|
||||
a == b && x == y && i == j
|
||||
a == b && x == y
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -1348,15 +1388,6 @@ impl<'a> Pattern<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// used to check if a pattern is suffixed to report as an error
|
||||
pub fn is_suffixed(&self) -> bool {
|
||||
match self {
|
||||
Pattern::Identifier { suffixed, .. } => *suffixed > 0,
|
||||
Pattern::QualifiedIdentifier { suffixed, .. } => *suffixed > 0,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Collection<'a, T> {
|
||||
|
@ -1613,13 +1644,11 @@ impl<'a> Expr<'a> {
|
|||
pub const REPL_OPAQUE_FUNCTION: Self = Expr::Var {
|
||||
module_name: "",
|
||||
ident: "<function>",
|
||||
suffixed: 0,
|
||||
};
|
||||
|
||||
pub const REPL_RUNTIME_CRASH: Self = Expr::Var {
|
||||
module_name: "",
|
||||
ident: "*",
|
||||
suffixed: 0,
|
||||
};
|
||||
|
||||
pub fn loc_ref(&'a self, region: Region) -> Loc<&'a Self> {
|
||||
|
@ -1854,7 +1883,8 @@ impl<'a> Malformed for Expr<'a> {
|
|||
Str(inner) => inner.is_malformed(),
|
||||
|
||||
RecordAccess(inner, _) |
|
||||
TupleAccess(inner, _) => inner.is_malformed(),
|
||||
TupleAccess(inner, _) |
|
||||
TaskAwaitBang(inner) => inner.is_malformed(),
|
||||
|
||||
List(items) => items.is_malformed(),
|
||||
|
||||
|
|
|
@ -197,17 +197,12 @@ where
|
|||
)
|
||||
}
|
||||
|
||||
pub fn check_indent<'a, E>(
|
||||
indent_problem: fn(Position) -> E,
|
||||
inside_suffixed_statement: bool,
|
||||
) -> impl Parser<'a, (), E>
|
||||
pub fn check_indent<'a, E>(indent_problem: fn(Position) -> E) -> impl Parser<'a, (), E>
|
||||
where
|
||||
E: 'a,
|
||||
{
|
||||
let extra_spaces = if inside_suffixed_statement { 1 } else { 0 };
|
||||
|
||||
move |_, state: State<'a>, min_indent: u32| {
|
||||
if state.column() >= (min_indent + extra_spaces) {
|
||||
if state.column() >= min_indent {
|
||||
Ok((NoProgress, (), state))
|
||||
} else {
|
||||
Err((NoProgress, indent_problem(state.pos())))
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::ast::{
|
||||
is_loc_expr_suffixed, AssignedField, Collection, CommentOrNewline, Defs, Expr, ExtractSpaces,
|
||||
is_expr_suffixed, AssignedField, Collection, CommentOrNewline, Defs, Expr, ExtractSpaces,
|
||||
Implements, ImplementsAbilities, Pattern, RecordBuilderField, Spaceable, Spaces,
|
||||
TypeAnnotation, TypeDef, TypeHeader, ValueDef,
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ use crate::blankspace::{
|
|||
space0_after_e, space0_around_e_no_after_indent_check, space0_around_ee, space0_before_e,
|
||||
space0_before_optional_after, space0_e, spaces, spaces_around, spaces_before,
|
||||
};
|
||||
use crate::ident::{integer_ident, lowercase_ident, parse_ident, Accessor, Ident};
|
||||
use crate::ident::{integer_ident, lowercase_ident, parse_ident, Accessor, Ident, Suffix};
|
||||
use crate::keyword;
|
||||
use crate::parser::{
|
||||
self, backtrackable, byte, byte_indent, increment_min_indent, line_min_indent, optional,
|
||||
|
@ -135,7 +135,7 @@ fn loc_expr_in_parens_etc_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>
|
|||
specialize_err(EExpr::InParens, loc_expr_in_parens_help()),
|
||||
record_field_access_chain()
|
||||
)),
|
||||
move |arena: &'a Bump, value: Loc<(Loc<Expr<'a>>, Vec<'a, Accessor<'a>>)>| {
|
||||
move |arena: &'a Bump, value: Loc<(Loc<Expr<'a>>, Vec<'a, Suffix<'a>>)>| {
|
||||
let Loc {
|
||||
mut region,
|
||||
value: (loc_expr, field_accesses),
|
||||
|
@ -156,16 +156,23 @@ fn loc_expr_in_parens_etc_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>
|
|||
)
|
||||
}
|
||||
|
||||
fn record_field_access_chain<'a>() -> impl Parser<'a, Vec<'a, Accessor<'a>>, EExpr<'a>> {
|
||||
zero_or_more!(skip_first!(
|
||||
byte(b'.', EExpr::Access),
|
||||
specialize_err(
|
||||
|_, pos| EExpr::Access(pos),
|
||||
one_of!(
|
||||
map!(lowercase_ident(), Accessor::RecordField),
|
||||
map!(integer_ident(), Accessor::TupleIndex),
|
||||
fn record_field_access_chain<'a>() -> impl Parser<'a, Vec<'a, Suffix<'a>>, EExpr<'a>> {
|
||||
zero_or_more!(one_of!(
|
||||
skip_first!(
|
||||
byte(b'.', EExpr::Access),
|
||||
specialize_err(
|
||||
|_, pos| EExpr::Access(pos),
|
||||
one_of!(
|
||||
map!(lowercase_ident(), |x| Suffix::Accessor(
|
||||
Accessor::RecordField(x)
|
||||
)),
|
||||
map!(integer_ident(), |x| Suffix::Accessor(Accessor::TupleIndex(
|
||||
x
|
||||
))),
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
map!(byte(b'!', EExpr::Access), |_| Suffix::TaskAwaitBang),
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -188,10 +195,7 @@ fn loc_term_or_underscore_or_conditional<'a>(
|
|||
loc!(underscore_expression()),
|
||||
loc!(record_literal_help()),
|
||||
loc!(specialize_err(EExpr::List, list_literal_help())),
|
||||
loc!(map_with_arena!(
|
||||
assign_or_destructure_identifier(),
|
||||
ident_to_expr
|
||||
)),
|
||||
ident_seq(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -211,10 +215,7 @@ fn loc_term_or_underscore<'a>(
|
|||
loc!(underscore_expression()),
|
||||
loc!(record_literal_help()),
|
||||
loc!(specialize_err(EExpr::List, list_literal_help())),
|
||||
loc!(map_with_arena!(
|
||||
assign_or_destructure_identifier(),
|
||||
ident_to_expr
|
||||
)),
|
||||
ident_seq(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -229,13 +230,31 @@ fn loc_term<'a>(options: ExprParseOptions) -> impl Parser<'a, Loc<Expr<'a>>, EEx
|
|||
loc!(specialize_err(EExpr::Closure, closure_help(options))),
|
||||
loc!(record_literal_help()),
|
||||
loc!(specialize_err(EExpr::List, list_literal_help())),
|
||||
loc!(map_with_arena!(
|
||||
assign_or_destructure_identifier(),
|
||||
ident_to_expr
|
||||
)),
|
||||
ident_seq(),
|
||||
)
|
||||
}
|
||||
|
||||
fn ident_seq<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
||||
(|arena: &'a Bump, state: State<'a>, min_indent: u32| parse_ident_seq(arena, state, min_indent))
|
||||
.trace("ident_seq")
|
||||
}
|
||||
|
||||
fn parse_ident_seq<'a>(
|
||||
arena: &'a Bump,
|
||||
state: State<'a>,
|
||||
min_indent: u32,
|
||||
) -> ParseResult<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
||||
let (_, loc_ident, state) =
|
||||
loc!(assign_or_destructure_identifier()).parse(arena, state, min_indent)?;
|
||||
let expr = ident_to_expr(arena, loc_ident.value);
|
||||
let (_p, suffixes, state) = record_field_access_chain()
|
||||
.trace("record_field_access_chain")
|
||||
.parse(arena, state, min_indent)
|
||||
.map_err(|(_p, e)| (MadeProgress, e))?;
|
||||
let expr = apply_expr_access_chain(arena, expr, suffixes);
|
||||
Ok((MadeProgress, Loc::at(loc_ident.region, expr), state))
|
||||
}
|
||||
|
||||
fn underscore_expression<'a>() -> impl Parser<'a, Expr<'a>, EExpr<'a>> {
|
||||
move |arena: &'a Bump, state: State<'a>, min_indent: u32| {
|
||||
let start = state.pos();
|
||||
|
@ -343,7 +362,7 @@ fn expr_operator_chain<'a>(options: ExprParseOptions) -> impl Parser<'a, Expr<'a
|
|||
let initial_state = state.clone();
|
||||
let end = state.pos();
|
||||
|
||||
let new_options = if is_loc_expr_suffixed(&expr) {
|
||||
let new_options = if is_expr_suffixed(&expr.value) {
|
||||
options.set_suffixed_found()
|
||||
} else {
|
||||
options
|
||||
|
@ -372,7 +391,7 @@ fn expr_operator_chain<'a>(options: ExprParseOptions) -> impl Parser<'a, Expr<'a
|
|||
Ok((progress, expr, new_state)) => {
|
||||
// We need to check if we have just parsed a suffixed statement,
|
||||
// if so, this is a defs node.
|
||||
if is_loc_expr_suffixed(&Loc::at_zero(expr)) {
|
||||
if is_expr_suffixed(&expr) {
|
||||
let def_region = Region::new(end, new_state.pos());
|
||||
let value_def = ValueDef::Stmt(arena.alloc(Loc::at(def_region, expr)));
|
||||
|
||||
|
@ -444,7 +463,7 @@ impl<'a> ExprState<'a> {
|
|||
} else if !self.expr.value.is_tag()
|
||||
&& !self.expr.value.is_opaque()
|
||||
&& !self.arguments.is_empty()
|
||||
&& !is_loc_expr_suffixed(&self.expr)
|
||||
&& !is_expr_suffixed(&self.expr.value)
|
||||
{
|
||||
let region = Region::across_all(self.arguments.iter().map(|v| &v.region));
|
||||
|
||||
|
@ -671,7 +690,9 @@ pub fn parse_single_def<'a>(
|
|||
|_, loc_def_expr| -> ValueDef<'a> { ValueDef::Stmt(arena.alloc(loc_def_expr)) },
|
||||
) {
|
||||
Ok((_, Some(single_def), state)) => match single_def.type_or_value {
|
||||
Either::Second(ValueDef::Stmt(loc_expr)) if is_loc_expr_suffixed(loc_expr) => {
|
||||
Either::Second(ValueDef::Stmt(loc_expr))
|
||||
if is_expr_suffixed(&loc_expr.value) =>
|
||||
{
|
||||
Ok((MadeProgress, Some(single_def), state))
|
||||
}
|
||||
_ => Ok((NoProgress, None, initial)), // a hacky way to get expression-based error messages. TODO fix this
|
||||
|
@ -904,7 +925,9 @@ pub fn parse_single_def<'a>(
|
|||
|_, loc_def_expr| -> ValueDef<'a> { ValueDef::Stmt(arena.alloc(loc_def_expr)) },
|
||||
) {
|
||||
Ok((_, Some(single_def), state)) => match single_def.type_or_value {
|
||||
Either::Second(ValueDef::Stmt(loc_expr)) if is_loc_expr_suffixed(loc_expr) => {
|
||||
Either::Second(ValueDef::Stmt(loc_expr))
|
||||
if is_expr_suffixed(&loc_expr.value) =>
|
||||
{
|
||||
Ok((MadeProgress, Some(single_def), state))
|
||||
}
|
||||
_ => Ok((NoProgress, None, initial)),
|
||||
|
@ -933,7 +956,7 @@ pub fn parse_single_def_assignment<'a>(
|
|||
|
||||
// If the expression is actually a suffixed statement, then we need to continue
|
||||
// to parse the rest of the expression
|
||||
if crate::ast::is_loc_expr_suffixed(&first_loc_expr) {
|
||||
if crate::ast::is_expr_suffixed(&first_loc_expr.value) {
|
||||
let mut defs = Defs::default();
|
||||
// Take the suffixed value and make it a e.g. Body(`{}=`, Apply(Var(...)))
|
||||
// we will keep the pattern `def_loc_pattern` for the new Defs
|
||||
|
@ -1640,11 +1663,13 @@ fn finish_parsing_ability_def_help<'a>(
|
|||
Ok((MadeProgress, (type_def, def_region), state))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn parse_expr_operator<'a>(
|
||||
min_indent: u32,
|
||||
options: ExprParseOptions,
|
||||
mut expr_state: ExprState<'a>,
|
||||
loc_op: Loc<BinOp>,
|
||||
line_indent: u32,
|
||||
arena: &'a Bump,
|
||||
state: State<'a>,
|
||||
initial_state: State<'a>,
|
||||
|
@ -1689,7 +1714,8 @@ fn parse_expr_operator<'a>(
|
|||
}
|
||||
BinOp::Assignment => {
|
||||
let expr_region = expr_state.expr.region;
|
||||
let indented_more = min_indent + 1;
|
||||
|
||||
let indented_more = line_indent + 1;
|
||||
|
||||
let call = expr_state
|
||||
.validate_assignment_or_backpassing(arena, loc_op, EExpr::ElmStyleFunction)
|
||||
|
@ -1833,7 +1859,7 @@ fn parse_expr_operator<'a>(
|
|||
expr_state.end = new_end;
|
||||
expr_state.spaces_after = spaces;
|
||||
|
||||
let new_options = if is_loc_expr_suffixed(&new_expr) {
|
||||
let new_options = if is_expr_suffixed(&new_expr.value) {
|
||||
options.set_suffixed_found()
|
||||
} else {
|
||||
options
|
||||
|
@ -1852,7 +1878,7 @@ fn parse_expr_operator<'a>(
|
|||
let def_region = expr.get_region_spanning_binops();
|
||||
let mut new_expr = Loc::at(def_region, expr);
|
||||
|
||||
if is_loc_expr_suffixed(&new_expr) {
|
||||
if is_expr_suffixed(&new_expr.value) {
|
||||
// We have parsed a statement such as `"hello" |> line!`
|
||||
// put the spaces from after the operator in front of the call
|
||||
if !spaces_after_operator.is_empty() {
|
||||
|
@ -1896,12 +1922,18 @@ fn parse_expr_end<'a>(
|
|||
state: State<'a>,
|
||||
initial_state: State<'a>,
|
||||
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
|
||||
let inner_min_indent = if options.suffixed_found {
|
||||
min_indent + 1
|
||||
} else {
|
||||
min_indent
|
||||
};
|
||||
|
||||
let parser = skip_first!(
|
||||
crate::blankspace::check_indent(EExpr::IndentEnd, options.suffixed_found),
|
||||
crate::blankspace::check_indent(EExpr::IndentEnd),
|
||||
loc_term_or_underscore(options)
|
||||
);
|
||||
|
||||
match parser.parse(arena, state.clone(), min_indent) {
|
||||
match parser.parse(arena, state.clone(), inner_min_indent) {
|
||||
Err((MadeProgress, f)) => Err((MadeProgress, f)),
|
||||
Ok((
|
||||
_,
|
||||
|
@ -1959,7 +1991,7 @@ fn parse_expr_end<'a>(
|
|||
Ok((_, mut arg, state)) => {
|
||||
let new_end = state.pos();
|
||||
|
||||
let new_options = if is_loc_expr_suffixed(&arg) {
|
||||
let new_options = if is_expr_suffixed(&arg.value) {
|
||||
options.set_suffixed_found()
|
||||
} else {
|
||||
options
|
||||
|
@ -2003,6 +2035,7 @@ fn parse_expr_end<'a>(
|
|||
Err((NoProgress, _)) => {
|
||||
let before_op = state.clone();
|
||||
// try an operator
|
||||
let line_indent = state.line_indent();
|
||||
match loc!(operator()).parse(arena, state.clone(), min_indent) {
|
||||
Err((MadeProgress, f)) => Err((MadeProgress, f)),
|
||||
Ok((_, loc_op, state)) => {
|
||||
|
@ -2013,6 +2046,7 @@ fn parse_expr_end<'a>(
|
|||
options,
|
||||
expr_state,
|
||||
loc_op,
|
||||
line_indent,
|
||||
arena,
|
||||
state,
|
||||
initial_state,
|
||||
|
@ -2147,19 +2181,11 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
|
|||
}
|
||||
|
||||
let mut pat = match expr.item {
|
||||
Expr::Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed,
|
||||
} => {
|
||||
Expr::Var { module_name, ident } => {
|
||||
if module_name.is_empty() {
|
||||
Pattern::Identifier { ident, suffixed }
|
||||
Pattern::Identifier { ident }
|
||||
} else {
|
||||
Pattern::QualifiedIdentifier {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed,
|
||||
}
|
||||
Pattern::QualifiedIdentifier { module_name, ident }
|
||||
}
|
||||
}
|
||||
Expr::Underscore(opt_name) => Pattern::Underscore(opt_name),
|
||||
|
@ -2240,6 +2266,7 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
|
|||
| Expr::UnappliedRecordBuilder { .. }
|
||||
| Expr::RecordUpdate { .. }
|
||||
| Expr::UnaryOp(_, _)
|
||||
| Expr::TaskAwaitBang(..)
|
||||
| Expr::Crash => return Err(()),
|
||||
|
||||
Expr::Str(string) => Pattern::StrLiteral(string),
|
||||
|
@ -2294,10 +2321,7 @@ fn assigned_expr_field_to_pattern_help<'a>(
|
|||
)
|
||||
}
|
||||
}
|
||||
AssignedField::LabelOnly(name) => Pattern::Identifier {
|
||||
ident: name.value,
|
||||
suffixed: 0,
|
||||
},
|
||||
AssignedField::LabelOnly(name) => Pattern::Identifier { ident: name.value },
|
||||
AssignedField::SpaceBefore(nested, spaces) => Pattern::SpaceBefore(
|
||||
arena.alloc(assigned_expr_field_to_pattern_help(arena, nested)?),
|
||||
spaces,
|
||||
|
@ -2789,21 +2813,13 @@ fn ident_to_expr<'a>(arena: &'a Bump, src: Ident<'a>) -> Expr<'a> {
|
|||
match src {
|
||||
Ident::Tag(string) => Expr::Tag(string),
|
||||
Ident::OpaqueRef(string) => Expr::OpaqueRef(string),
|
||||
Ident::Access {
|
||||
module_name,
|
||||
parts,
|
||||
suffixed,
|
||||
} => {
|
||||
Ident::Access { module_name, parts } => {
|
||||
let mut iter = parts.iter();
|
||||
|
||||
// The first value in the iterator is the variable name,
|
||||
// e.g. `foo` in `foo.bar.baz`
|
||||
let mut answer = match iter.next() {
|
||||
Some(Accessor::RecordField(ident)) => Expr::Var {
|
||||
module_name,
|
||||
ident,
|
||||
suffixed,
|
||||
},
|
||||
Some(Accessor::RecordField(ident)) => Expr::Var { module_name, ident },
|
||||
Some(Accessor::TupleIndex(_)) => {
|
||||
// TODO: make this state impossible to represent in Ident::Access,
|
||||
// by splitting out parts[0] into a separate field with a type of `&'a str`,
|
||||
|
@ -3165,13 +3181,18 @@ fn record_builder_help<'a>(
|
|||
fn apply_expr_access_chain<'a>(
|
||||
arena: &'a Bump,
|
||||
value: Expr<'a>,
|
||||
accessors: Vec<'a, Accessor<'a>>,
|
||||
accessors: Vec<'a, Suffix<'a>>,
|
||||
) -> Expr<'a> {
|
||||
accessors
|
||||
.into_iter()
|
||||
.fold(value, |value, accessor| match accessor {
|
||||
Accessor::RecordField(field) => Expr::RecordAccess(arena.alloc(value), field),
|
||||
Accessor::TupleIndex(field) => Expr::TupleAccess(arena.alloc(value), field),
|
||||
Suffix::Accessor(Accessor::RecordField(field)) => {
|
||||
Expr::RecordAccess(arena.alloc(value), field)
|
||||
}
|
||||
Suffix::Accessor(Accessor::TupleIndex(field)) => {
|
||||
Expr::TupleAccess(arena.alloc(value), field)
|
||||
}
|
||||
Suffix::TaskAwaitBang => Expr::TaskAwaitBang(arena.alloc(value)),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@ pub enum Ident<'a> {
|
|||
Access {
|
||||
module_name: &'a str,
|
||||
parts: &'a [Accessor<'a>],
|
||||
suffixed: u8,
|
||||
},
|
||||
/// `.foo { foo: 42 }` or `.1 (1, 2, 3)`
|
||||
AccessorFunction(Accessor<'a>),
|
||||
|
@ -193,12 +192,7 @@ pub fn parse_ident<'a>(
|
|||
match chomp_identifier_chain(arena, state.bytes(), state.pos()) {
|
||||
Ok((width, ident)) => {
|
||||
let state = advance_state!(state, width as usize)?;
|
||||
if let Ident::Access {
|
||||
module_name,
|
||||
parts,
|
||||
suffixed,
|
||||
} = ident
|
||||
{
|
||||
if let Ident::Access { module_name, parts } = ident {
|
||||
if module_name.is_empty() {
|
||||
if let Some(first) = parts.first() {
|
||||
for keyword in crate::keyword::KEYWORDS.iter() {
|
||||
|
@ -209,15 +203,7 @@ pub fn parse_ident<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
return Ok((
|
||||
MadeProgress,
|
||||
Ident::Access {
|
||||
module_name,
|
||||
parts,
|
||||
suffixed,
|
||||
},
|
||||
state,
|
||||
));
|
||||
return Ok((MadeProgress, Ident::Access { module_name, parts }, state));
|
||||
}
|
||||
|
||||
Ok((MadeProgress, ident, state))
|
||||
|
@ -388,6 +374,12 @@ impl<'a> Accessor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Suffix<'a> {
|
||||
Accessor(Accessor<'a>),
|
||||
TaskAwaitBang,
|
||||
}
|
||||
|
||||
/// a `.foo` or `.1` accessor function
|
||||
fn chomp_accessor(buffer: &[u8], pos: Position) -> Result<Accessor, BadIdent> {
|
||||
// assumes the leading `.` has been chomped already
|
||||
|
@ -528,22 +520,9 @@ fn chomp_identifier_chain<'a>(
|
|||
|
||||
chomped += width as usize;
|
||||
|
||||
// Parse any `!` suffixes
|
||||
let mut suffixed = 0;
|
||||
while let Ok((ch, width)) = char::from_utf8_slice_start(&buffer[chomped..]) {
|
||||
if ch == '!' {
|
||||
suffixed += 1;
|
||||
chomped += width;
|
||||
} else {
|
||||
// we're done
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let ident = Ident::Access {
|
||||
module_name,
|
||||
parts: parts.into_bump_slice(),
|
||||
suffixed,
|
||||
};
|
||||
|
||||
Ok((chomped as u32, ident))
|
||||
|
@ -578,22 +557,9 @@ fn chomp_identifier_chain<'a>(
|
|||
// just one segment, starting with a lowercase letter; that's a normal identifier
|
||||
let value = unsafe { std::str::from_utf8_unchecked(&buffer[..chomped]) };
|
||||
|
||||
// Parse any `!` suffixes
|
||||
let mut suffixed = 0;
|
||||
while let Ok((ch, width)) = char::from_utf8_slice_start(&buffer[chomped..]) {
|
||||
if ch == '!' {
|
||||
suffixed += 1;
|
||||
chomped += width;
|
||||
} else {
|
||||
// we're done
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let ident = Ident::Access {
|
||||
module_name: "",
|
||||
parts: arena.alloc([Accessor::RecordField(value)]),
|
||||
suffixed,
|
||||
};
|
||||
|
||||
Ok((chomped as u32, ident))
|
||||
|
|
|
@ -12,7 +12,6 @@ use crate::string_literal::StrLikeLiteral;
|
|||
use bumpalo::collections::string::String;
|
||||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_region::all::{Loc, Region};
|
||||
|
||||
/// Different patterns are supported in different circumstances.
|
||||
|
@ -46,18 +45,10 @@ pub fn closure_param<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, EPattern<'a>> {
|
|||
|
||||
pub fn loc_pattern_help<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, EPattern<'a>> {
|
||||
move |arena, state: State<'a>, min_indent| {
|
||||
let (_, pattern, state) = loc_pattern_help_help().parse(arena, state, min_indent)?;
|
||||
let (_, pattern, state) = loc_pattern_help_help(true).parse(arena, state, min_indent)?;
|
||||
|
||||
let pattern_state = state.clone();
|
||||
|
||||
// Return early with the suffixed statement
|
||||
match pattern.value {
|
||||
Pattern::Identifier { suffixed, .. } if suffixed > 0 => {
|
||||
return Ok((MadeProgress, pattern, pattern_state))
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let (pattern_spaces, state) =
|
||||
match space0_e(EPattern::AsKeyword).parse(arena, state, min_indent) {
|
||||
Err(_) => return Ok((MadeProgress, pattern, pattern_state)),
|
||||
|
@ -82,11 +73,13 @@ pub fn loc_pattern_help<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, EPattern<'a>>
|
|||
}
|
||||
}
|
||||
|
||||
fn loc_pattern_help_help<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, EPattern<'a>> {
|
||||
fn loc_pattern_help_help<'a>(
|
||||
can_have_arguments: bool,
|
||||
) -> impl Parser<'a, Loc<Pattern<'a>>, EPattern<'a>> {
|
||||
one_of!(
|
||||
specialize_err(EPattern::PInParens, loc_pattern_in_parens_help()),
|
||||
loc!(underscore_pattern_help()),
|
||||
loc_ident_pattern_help(true),
|
||||
loc_ident_pattern_help(can_have_arguments),
|
||||
loc!(specialize_err(
|
||||
EPattern::Record,
|
||||
crate::pattern::record_pattern_help()
|
||||
|
@ -143,7 +136,8 @@ fn loc_tag_pattern_arg<'a>(
|
|||
min_indent,
|
||||
)?;
|
||||
|
||||
let (_, loc_pat, state) = loc_parse_tag_pattern_arg().parse(arena, state, min_indent)?;
|
||||
// Cannot have arguments here, pass `false` to make sure `Foo Bar 1` is parsed as `Foo (Bar) 1`, and not `Foo (Bar 1)`
|
||||
let (_, loc_pat, state) = loc_pattern_help_help(false).parse(arena, state, min_indent)?;
|
||||
|
||||
let Loc { region, value } = loc_pat;
|
||||
|
||||
|
@ -194,21 +188,6 @@ pub fn loc_implements_parser<'a>() -> impl Parser<'a, Loc<Implements<'a>>, EPatt
|
|||
)
|
||||
}
|
||||
|
||||
fn loc_parse_tag_pattern_arg<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, EPattern<'a>> {
|
||||
one_of!(
|
||||
specialize_err(EPattern::PInParens, loc_pattern_in_parens_help()),
|
||||
loc!(underscore_pattern_help()),
|
||||
// Make sure `Foo Bar 1` is parsed as `Foo (Bar) 1`, and not `Foo (Bar 1)`
|
||||
loc_ident_pattern_help(false),
|
||||
loc!(specialize_err(
|
||||
EPattern::Record,
|
||||
crate::pattern::record_pattern_help()
|
||||
)),
|
||||
loc!(string_like_pattern_help()),
|
||||
loc!(number_pattern_help())
|
||||
)
|
||||
}
|
||||
|
||||
fn loc_pattern_in_parens_help<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, PInParens<'a>> {
|
||||
then(
|
||||
loc!(collection_trailing_sep_e!(
|
||||
|
@ -405,46 +384,6 @@ fn loc_ident_pattern_help<'a>(
|
|||
Ok((MadeProgress, loc_pat, state))
|
||||
}
|
||||
}
|
||||
// Parse a statement that begins with a suffixed identifier, e.g. `Stdout.line! "Hello"`
|
||||
Ident::Access {
|
||||
module_name,
|
||||
parts,
|
||||
suffixed,
|
||||
..
|
||||
} if suffixed > 0 => {
|
||||
if module_name.is_empty() && parts.len() == 1 {
|
||||
if let Accessor::RecordField(var) = &parts[0] {
|
||||
Ok((
|
||||
MadeProgress,
|
||||
Loc {
|
||||
region: loc_ident.region,
|
||||
value: Pattern::Identifier {
|
||||
ident: var,
|
||||
suffixed,
|
||||
},
|
||||
},
|
||||
state,
|
||||
))
|
||||
} else {
|
||||
internal_error!("unexpected suffixed TupleIndex");
|
||||
}
|
||||
} else if let Accessor::RecordField(var) = &parts[0] {
|
||||
return Ok((
|
||||
MadeProgress,
|
||||
Loc {
|
||||
region: loc_ident.region,
|
||||
value: Pattern::QualifiedIdentifier {
|
||||
module_name,
|
||||
ident: var,
|
||||
suffixed,
|
||||
},
|
||||
},
|
||||
state,
|
||||
));
|
||||
} else {
|
||||
internal_error!("unexpected suffixed TupleIndex");
|
||||
}
|
||||
}
|
||||
Ident::Access {
|
||||
module_name, parts, ..
|
||||
} => {
|
||||
|
@ -463,10 +402,7 @@ fn loc_ident_pattern_help<'a>(
|
|||
MadeProgress,
|
||||
Loc {
|
||||
region: loc_ident.region,
|
||||
value: Pattern::Identifier {
|
||||
ident: var,
|
||||
suffixed: 0,
|
||||
},
|
||||
value: Pattern::Identifier { ident: var },
|
||||
},
|
||||
state,
|
||||
));
|
||||
|
@ -627,18 +563,9 @@ fn record_pattern_field<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, PRecord<'a>>
|
|||
None => {
|
||||
let Loc { value, region } = loc_label;
|
||||
let value = if !spaces.is_empty() {
|
||||
Pattern::SpaceAfter(
|
||||
arena.alloc(Pattern::Identifier {
|
||||
ident: value,
|
||||
suffixed: 0,
|
||||
}),
|
||||
spaces,
|
||||
)
|
||||
Pattern::SpaceAfter(arena.alloc(Pattern::Identifier { ident: value }), spaces)
|
||||
} else {
|
||||
Pattern::Identifier {
|
||||
ident: value,
|
||||
suffixed: 0,
|
||||
}
|
||||
Pattern::Identifier { ident: value }
|
||||
};
|
||||
|
||||
Ok((MadeProgress, Loc::at(region, value), state))
|
||||
|
|
|
@ -70,13 +70,7 @@ fn check_type_alias<'a>(
|
|||
var_names.reserve(vars.len());
|
||||
for var in vars {
|
||||
if let TypeAnnotation::BoundVariable(v) = var.value {
|
||||
var_names.push(Loc::at(
|
||||
var.region,
|
||||
Pattern::Identifier {
|
||||
ident: v,
|
||||
suffixed: 0,
|
||||
},
|
||||
));
|
||||
var_names.push(Loc::at(var.region, Pattern::Identifier { ident: v }));
|
||||
} else {
|
||||
return Err(ETypeInlineAlias::ArgumentNotLowercase(var.region.start()));
|
||||
}
|
||||
|
|
|
@ -175,7 +175,6 @@ mod test_parse {
|
|||
let expr = arena.alloc(Var {
|
||||
module_name: "",
|
||||
ident: "name",
|
||||
suffixed: 0,
|
||||
});
|
||||
|
||||
bumpalo::vec![in arena;
|
||||
|
@ -192,7 +191,6 @@ mod test_parse {
|
|||
let expr = arena.alloc(Var {
|
||||
module_name: "",
|
||||
ident: "name",
|
||||
suffixed: 0,
|
||||
});
|
||||
|
||||
bumpalo::vec![in arena;
|
||||
|
@ -238,7 +236,6 @@ mod test_parse {
|
|||
let expr = arena.alloc(Var {
|
||||
module_name: "",
|
||||
ident: "name",
|
||||
suffixed: 0,
|
||||
});
|
||||
|
||||
bumpalo::vec![in arena;
|
||||
|
@ -254,13 +251,11 @@ mod test_parse {
|
|||
let expr1 = arena.alloc(Var {
|
||||
module_name: "",
|
||||
ident: "name",
|
||||
suffixed: 0,
|
||||
});
|
||||
|
||||
let expr2 = arena.alloc(Var {
|
||||
module_name: "",
|
||||
ident: "project",
|
||||
suffixed: 0,
|
||||
});
|
||||
|
||||
bumpalo::vec![in arena;
|
||||
|
@ -281,13 +276,11 @@ mod test_parse {
|
|||
let expr1 = arena.alloc(Var {
|
||||
module_name: "",
|
||||
ident: "name",
|
||||
suffixed: 0,
|
||||
});
|
||||
|
||||
let expr2 = arena.alloc(Var {
|
||||
module_name: "",
|
||||
ident: "project",
|
||||
suffixed: 0,
|
||||
});
|
||||
|
||||
bumpalo::vec![in arena;
|
||||
|
|
|
@ -50,17 +50,17 @@ procedure Num.22 (#Attr.2, #Attr.3):
|
|||
let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
|
||||
procedure Result.5 (Result.12, Result.13):
|
||||
let Result.39 : U8 = 1i64;
|
||||
let Result.40 : U8 = GetTagId Result.12;
|
||||
let Result.41 : Int1 = lowlevel Eq Result.39 Result.40;
|
||||
if Result.41 then
|
||||
dec Result.13;
|
||||
let Result.14 : Str = UnionAtIndex (Id 1) (Index 0) Result.12;
|
||||
ret Result.14;
|
||||
procedure Result.5 (Result.10, Result.11):
|
||||
let Result.37 : U8 = 1i64;
|
||||
let Result.38 : U8 = GetTagId Result.10;
|
||||
let Result.39 : Int1 = lowlevel Eq Result.37 Result.38;
|
||||
if Result.39 then
|
||||
dec Result.11;
|
||||
let Result.12 : Str = UnionAtIndex (Id 1) (Index 0) Result.10;
|
||||
ret Result.12;
|
||||
else
|
||||
dec Result.12;
|
||||
ret Result.13;
|
||||
dec Result.10;
|
||||
ret Result.11;
|
||||
|
||||
procedure Test.10 (Test.11):
|
||||
let Test.12 : Str = CallByName Test.2 Test.11;
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
name = "test_syntax-fuzz"
|
||||
publish = false
|
||||
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
version.workspace = true
|
||||
version = "0.0.0"
|
||||
authors = ["Automatically generated"]
|
||||
edition = "2021"
|
||||
|
||||
[package.metadata]
|
||||
cargo-fuzz = true
|
||||
|
@ -12,8 +12,8 @@ cargo-fuzz = true
|
|||
[dependencies]
|
||||
test_syntax = { path = "../../test_syntax" }
|
||||
|
||||
bumpalo.workspace = true
|
||||
libfuzzer-sys.workspace = true
|
||||
bumpalo = { version = "3.12.0", features = ["collections"] }
|
||||
libfuzzer-sys = "0.4"
|
||||
|
||||
# Prevent this from interfering with workspaces
|
||||
[workspace]
|
||||
|
|
|
@ -2,7 +2,6 @@ When(
|
|||
@5-6 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
WhenBranch {
|
||||
|
|
|
@ -2,7 +2,6 @@ When(
|
|||
@5-6 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
WhenBranch {
|
||||
|
|
|
@ -4,7 +4,6 @@ BinOps(
|
|||
@0-1 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@2-3 Plus,
|
||||
),
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Annotation(
|
||||
@0-3 Identifier {
|
||||
ident: "foo",
|
||||
suffixed: 0,
|
||||
},
|
||||
@6-27 TagUnion {
|
||||
ext: None,
|
||||
|
@ -43,7 +42,6 @@ Defs(
|
|||
AnnotatedBody {
|
||||
ann_pattern: @0-3 Identifier {
|
||||
ident: "foo",
|
||||
suffixed: 0,
|
||||
},
|
||||
ann_type: @6-27 TagUnion {
|
||||
ext: None,
|
||||
|
@ -67,7 +65,6 @@ Defs(
|
|||
comment: None,
|
||||
body_pattern: @28-31 Identifier {
|
||||
ident: "foo",
|
||||
suffixed: 0,
|
||||
},
|
||||
body_expr: @34-38 Tag(
|
||||
"True",
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Annotation(
|
||||
@0-3 Identifier {
|
||||
ident: "foo",
|
||||
suffixed: 0,
|
||||
},
|
||||
@6-28 TagUnion {
|
||||
ext: Some(
|
||||
|
@ -45,7 +44,6 @@ Defs(
|
|||
AnnotatedBody {
|
||||
ann_pattern: @0-3 Identifier {
|
||||
ident: "foo",
|
||||
suffixed: 0,
|
||||
},
|
||||
ann_type: @6-28 TagUnion {
|
||||
ext: Some(
|
||||
|
@ -71,7 +69,6 @@ Defs(
|
|||
comment: None,
|
||||
body_pattern: @29-32 Identifier {
|
||||
ident: "foo",
|
||||
suffixed: 0,
|
||||
},
|
||||
body_expr: @35-39 Tag(
|
||||
"True",
|
||||
|
|
|
@ -20,11 +20,9 @@ Defs(
|
|||
[
|
||||
@2-3 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@5-7 Identifier {
|
||||
ident: "y",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -39,11 +37,9 @@ Defs(
|
|||
[
|
||||
@2-3 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@5-7 Identifier {
|
||||
ident: "y",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -57,11 +53,9 @@ Defs(
|
|||
[
|
||||
@17-18 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@20-21 Identifier {
|
||||
ident: "y",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -92,7 +86,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -20,7 +20,6 @@ Defs(
|
|||
vars: [
|
||||
@7-8 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -50,7 +49,6 @@ Defs(
|
|||
[
|
||||
@7-8 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -77,7 +75,6 @@ Defs(
|
|||
[
|
||||
@33-34 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -99,7 +96,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -20,11 +20,9 @@ Defs(
|
|||
[
|
||||
@2-3 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@5-6 Identifier {
|
||||
ident: "y",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -39,11 +37,9 @@ Defs(
|
|||
[
|
||||
@2-3 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@5-6 Identifier {
|
||||
ident: "y",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -57,11 +53,9 @@ Defs(
|
|||
[
|
||||
@17-18 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@20-21 Identifier {
|
||||
ident: "y",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -84,7 +78,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -2,23 +2,19 @@ Apply(
|
|||
@0-1 Var {
|
||||
module_name: "",
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
@2-3 Var {
|
||||
module_name: "",
|
||||
ident: "b",
|
||||
suffixed: 0,
|
||||
},
|
||||
@4-5 Var {
|
||||
module_name: "",
|
||||
ident: "c",
|
||||
suffixed: 0,
|
||||
},
|
||||
@6-7 Var {
|
||||
module_name: "",
|
||||
ident: "d",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
Space,
|
||||
|
|
|
@ -2,7 +2,6 @@ Apply(
|
|||
@0-4 Var {
|
||||
module_name: "",
|
||||
ident: "whee",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
@6-8 Num(
|
||||
|
|
|
@ -3,7 +3,6 @@ Apply(
|
|||
@1-5 Var {
|
||||
module_name: "",
|
||||
ident: "whee",
|
||||
suffixed: 0,
|
||||
},
|
||||
@0-1 Negate,
|
||||
),
|
||||
|
@ -14,7 +13,6 @@ Apply(
|
|||
@10-13 Var {
|
||||
module_name: "",
|
||||
ident: "foo",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
Space,
|
||||
|
|
|
@ -3,7 +3,6 @@ Apply(
|
|||
@1-5 Var {
|
||||
module_name: "",
|
||||
ident: "whee",
|
||||
suffixed: 0,
|
||||
},
|
||||
@0-1 Not,
|
||||
),
|
||||
|
@ -14,7 +13,6 @@ Apply(
|
|||
@10-13 Var {
|
||||
module_name: "",
|
||||
ident: "foo",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
Space,
|
||||
|
|
|
@ -2,7 +2,6 @@ Apply(
|
|||
@0-4 Var {
|
||||
module_name: "",
|
||||
ident: "whee",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
@5-6 Num(
|
||||
|
|
|
@ -19,7 +19,6 @@ SpaceBefore(
|
|||
Body(
|
||||
@107-108 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@111-112 Num(
|
||||
"5",
|
||||
|
|
|
@ -2,7 +2,6 @@ RecordAccess(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "rec",
|
||||
suffixed: 0,
|
||||
},
|
||||
"field",
|
||||
)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "whee",
|
||||
suffixed: 0,
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Annotation(
|
||||
@0-1 Identifier {
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
@3-4 SpaceBefore(
|
||||
BoundVariable(
|
||||
|
|
|
@ -3,7 +3,6 @@ Apply(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "f",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -4,7 +4,6 @@ BinOps(
|
|||
@0-1 Var {
|
||||
module_name: "",
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
@2-4 And,
|
||||
),
|
||||
|
@ -14,13 +13,11 @@ BinOps(
|
|||
[
|
||||
@6-7 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
@9-10 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
),
|
||||
[
|
||||
|
|
|
@ -4,7 +4,6 @@ BinOps(
|
|||
@0-1 Var {
|
||||
module_name: "",
|
||||
ident: "i",
|
||||
suffixed: 0,
|
||||
},
|
||||
@1-2 GreaterThan,
|
||||
),
|
||||
|
@ -15,13 +14,11 @@ BinOps(
|
|||
[
|
||||
@3-4 Identifier {
|
||||
ident: "s",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
@6-7 Var {
|
||||
module_name: "",
|
||||
ident: "s",
|
||||
suffixed: 0,
|
||||
},
|
||||
),
|
||||
[
|
||||
|
@ -33,7 +30,6 @@ BinOps(
|
|||
@9-10 Var {
|
||||
module_name: "",
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
@8-9 Negate,
|
||||
),
|
||||
|
|
|
@ -30,7 +30,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "q",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
LineComment(
|
||||
|
|
|
@ -21,7 +21,6 @@ Defs {
|
|||
Body(
|
||||
@0-3 Identifier {
|
||||
ident: "foo",
|
||||
suffixed: 0,
|
||||
},
|
||||
@6-7 Num(
|
||||
"1",
|
||||
|
|
|
@ -3,7 +3,6 @@ ParensAround(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "i",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
LineComment(
|
||||
|
|
|
@ -22,7 +22,6 @@ Defs(
|
|||
SpaceBefore(
|
||||
Identifier {
|
||||
ident: "h",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
LineComment(
|
||||
|
@ -47,7 +46,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "j",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -19,7 +19,6 @@ Defs(
|
|||
@0-1 SpaceAfter(
|
||||
Identifier {
|
||||
ident: "w",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
LineComment(
|
||||
|
|
|
@ -19,7 +19,6 @@ Defs(
|
|||
@0-1 SpaceAfter(
|
||||
Identifier {
|
||||
ident: "t",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
LineComment(
|
||||
|
@ -37,7 +36,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "e",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -98,13 +98,11 @@ Defs(
|
|||
@50-53 Var {
|
||||
module_name: "",
|
||||
ident: "try",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
@54-57 Var {
|
||||
module_name: "",
|
||||
ident: "foo",
|
||||
suffixed: 0,
|
||||
},
|
||||
@59-73 ParensAround(
|
||||
Closure(
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Annotation(
|
||||
@0-1 Identifier {
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
@2-3 BoundVariable(
|
||||
"b",
|
||||
|
@ -29,6 +28,5 @@ Defs(
|
|||
@4-5 Var {
|
||||
module_name: "",
|
||||
ident: "i",
|
||||
suffixed: 0,
|
||||
},
|
||||
)
|
||||
|
|
|
@ -23,7 +23,6 @@ Defs(
|
|||
[
|
||||
@6-9 Identifier {
|
||||
ident: "str",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -47,7 +46,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "str",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -19,7 +19,6 @@ SpaceBefore(
|
|||
Body(
|
||||
@48-49 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@52-53 Num(
|
||||
"5",
|
||||
|
|
|
@ -2,7 +2,6 @@ RecordUpdate {
|
|||
update: @1-2 Var {
|
||||
module_name: "",
|
||||
ident: "e",
|
||||
suffixed: 0,
|
||||
},
|
||||
fields: [],
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ BinOps(
|
|||
@0-1 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@1-3 Equals,
|
||||
),
|
||||
|
@ -12,6 +11,5 @@ BinOps(
|
|||
@3-4 Var {
|
||||
module_name: "",
|
||||
ident: "y",
|
||||
suffixed: 0,
|
||||
},
|
||||
)
|
||||
|
|
|
@ -4,7 +4,6 @@ BinOps(
|
|||
@0-1 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@2-4 Equals,
|
||||
),
|
||||
|
@ -12,6 +11,5 @@ BinOps(
|
|||
@5-6 Var {
|
||||
module_name: "",
|
||||
ident: "y",
|
||||
suffixed: 0,
|
||||
},
|
||||
)
|
||||
|
|
|
@ -33,7 +33,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Annotation(
|
||||
@0-5 Identifier {
|
||||
ident: "table",
|
||||
suffixed: 0,
|
||||
},
|
||||
@8-44 Function(
|
||||
[
|
||||
|
@ -57,7 +56,6 @@ Defs(
|
|||
AnnotatedBody {
|
||||
ann_pattern: @0-5 Identifier {
|
||||
ident: "table",
|
||||
suffixed: 0,
|
||||
},
|
||||
ann_type: @8-44 Function(
|
||||
[
|
||||
|
@ -95,7 +93,6 @@ Defs(
|
|||
comment: None,
|
||||
body_pattern: @45-50 Identifier {
|
||||
ident: "table",
|
||||
suffixed: 0,
|
||||
},
|
||||
body_expr: @53-89 Closure(
|
||||
[
|
||||
|
@ -103,7 +100,6 @@ Defs(
|
|||
[
|
||||
@55-61 Identifier {
|
||||
ident: "height",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -127,7 +123,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "table",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Annotation(
|
||||
@0-1 Identifier {
|
||||
ident: "f",
|
||||
suffixed: 0,
|
||||
},
|
||||
@4-20 Function(
|
||||
[
|
||||
|
@ -56,7 +55,6 @@ Defs(
|
|||
AnnotatedBody {
|
||||
ann_pattern: @0-1 Identifier {
|
||||
ident: "f",
|
||||
suffixed: 0,
|
||||
},
|
||||
ann_type: @4-20 Function(
|
||||
[
|
||||
|
@ -93,19 +91,16 @@ Defs(
|
|||
comment: None,
|
||||
body_pattern: @21-22 Identifier {
|
||||
ident: "f",
|
||||
suffixed: 0,
|
||||
},
|
||||
body_expr: @25-32 Closure(
|
||||
[
|
||||
@26-27 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
@31-32 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
),
|
||||
},
|
||||
|
@ -116,7 +111,6 @@ Defs(
|
|||
@34-35 Var {
|
||||
module_name: "",
|
||||
ident: "f",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
@36-47 Tuple(
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Annotation(
|
||||
@0-1 Identifier {
|
||||
ident: "f",
|
||||
suffixed: 0,
|
||||
},
|
||||
@4-21 Function(
|
||||
[
|
||||
|
@ -48,7 +47,6 @@ Defs(
|
|||
AnnotatedBody {
|
||||
ann_pattern: @0-1 Identifier {
|
||||
ident: "f",
|
||||
suffixed: 0,
|
||||
},
|
||||
ann_type: @4-21 Function(
|
||||
[
|
||||
|
@ -77,13 +75,11 @@ Defs(
|
|||
comment: None,
|
||||
body_pattern: @22-23 Identifier {
|
||||
ident: "f",
|
||||
suffixed: 0,
|
||||
},
|
||||
body_expr: @26-42 Closure(
|
||||
[
|
||||
@27-28 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
@32-42 Tuple(
|
||||
|
@ -91,7 +87,6 @@ Defs(
|
|||
@33-34 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@36-41 BinOps(
|
||||
[
|
||||
|
@ -99,7 +94,6 @@ Defs(
|
|||
@36-37 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@38-39 Plus,
|
||||
),
|
||||
|
@ -119,7 +113,6 @@ Defs(
|
|||
@44-45 Var {
|
||||
module_name: "",
|
||||
ident: "f",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
@46-48 Num(
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Body(
|
||||
@0-4 Identifier {
|
||||
ident: "iffy",
|
||||
suffixed: 0,
|
||||
},
|
||||
@5-6 Num(
|
||||
"5",
|
||||
|
|
|
@ -18,7 +18,6 @@ BinOps(
|
|||
Var {
|
||||
module_name: "Str",
|
||||
ident: "toUtf8",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
@ -32,14 +31,12 @@ BinOps(
|
|||
@28-36 Var {
|
||||
module_name: "List",
|
||||
ident: "map",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
@37-54 Closure(
|
||||
[
|
||||
@38-42 Identifier {
|
||||
ident: "byte",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
@46-54 BinOps(
|
||||
|
@ -48,7 +45,6 @@ BinOps(
|
|||
@46-50 Var {
|
||||
module_name: "",
|
||||
ident: "byte",
|
||||
suffixed: 0,
|
||||
},
|
||||
@51-52 Plus,
|
||||
),
|
||||
|
@ -71,6 +67,5 @@ BinOps(
|
|||
@58-70 Var {
|
||||
module_name: "List",
|
||||
ident: "reverse",
|
||||
suffixed: 0,
|
||||
},
|
||||
)
|
||||
|
|
|
@ -2,7 +2,6 @@ Closure(
|
|||
[
|
||||
@1-2 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
@8-9 SpaceBefore(
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Body(
|
||||
@0-6 Identifier {
|
||||
ident: "myList",
|
||||
suffixed: 0,
|
||||
},
|
||||
@9-57 List(
|
||||
Collection {
|
||||
|
@ -39,7 +38,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
@ -49,7 +47,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "b",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Body(
|
||||
@0-6 Identifier {
|
||||
ident: "myList",
|
||||
suffixed: 0,
|
||||
},
|
||||
@9-25 List(
|
||||
[
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Body(
|
||||
@0-6 Identifier {
|
||||
ident: "myList",
|
||||
suffixed: 0,
|
||||
},
|
||||
@9-26 List(
|
||||
Collection {
|
||||
|
|
|
@ -19,6 +19,5 @@ BinOps(
|
|||
@6-7 Var {
|
||||
module_name: "",
|
||||
ident: "i",
|
||||
suffixed: 0,
|
||||
},
|
||||
)
|
||||
|
|
|
@ -75,19 +75,15 @@ When(
|
|||
[
|
||||
@61-62 Identifier {
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
@64-65 Identifier {
|
||||
ident: "b",
|
||||
suffixed: 0,
|
||||
},
|
||||
@67-68 Identifier {
|
||||
ident: "c",
|
||||
suffixed: 0,
|
||||
},
|
||||
@70-71 Identifier {
|
||||
ident: "d",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -108,11 +104,9 @@ When(
|
|||
[
|
||||
@82-83 Identifier {
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
@85-86 Identifier {
|
||||
ident: "b",
|
||||
suffixed: 0,
|
||||
},
|
||||
@88-90 ListRest(
|
||||
None,
|
||||
|
@ -139,11 +133,9 @@ When(
|
|||
),
|
||||
@105-106 Identifier {
|
||||
ident: "c",
|
||||
suffixed: 0,
|
||||
},
|
||||
@108-109 Identifier {
|
||||
ident: "d",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -180,7 +172,6 @@ When(
|
|||
[
|
||||
@132-133 Identifier {
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -218,7 +209,6 @@ When(
|
|||
),
|
||||
@160-161 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
|
|
@ -19,7 +19,6 @@ SpaceBefore(
|
|||
Body(
|
||||
@113-114 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@117-118 Num(
|
||||
"5",
|
||||
|
|
|
@ -17,7 +17,6 @@ Defs {
|
|||
Body(
|
||||
@0-4 Identifier {
|
||||
ident: "main",
|
||||
suffixed: 0,
|
||||
},
|
||||
@11-24 SpaceBefore(
|
||||
Defs(
|
||||
|
@ -40,7 +39,6 @@ Defs {
|
|||
Body(
|
||||
@11-12 Identifier {
|
||||
ident: "i",
|
||||
suffixed: 0,
|
||||
},
|
||||
@15-17 Num(
|
||||
"64",
|
||||
|
@ -52,7 +50,6 @@ Defs {
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "i",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -2,18 +2,15 @@ Backpassing(
|
|||
[
|
||||
@0-1 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@3-4 Identifier {
|
||||
ident: "y",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
@8-23 Apply(
|
||||
@8-17 Var {
|
||||
module_name: "List",
|
||||
ident: "map2",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
@18-20 List(
|
||||
|
@ -32,7 +29,6 @@ Backpassing(
|
|||
@25-26 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@27-28 Plus,
|
||||
),
|
||||
|
@ -40,7 +36,6 @@ Backpassing(
|
|||
@29-30 Var {
|
||||
module_name: "",
|
||||
ident: "y",
|
||||
suffixed: 0,
|
||||
},
|
||||
),
|
||||
[
|
||||
|
|
|
@ -17,25 +17,21 @@ Defs {
|
|||
Body(
|
||||
@0-4 Identifier {
|
||||
ident: "main",
|
||||
suffixed: 0,
|
||||
},
|
||||
@12-50 SpaceBefore(
|
||||
Backpassing(
|
||||
[
|
||||
@12-16 Identifier {
|
||||
ident: "arg1",
|
||||
suffixed: 0,
|
||||
},
|
||||
@18-22 Identifier {
|
||||
ident: "arg2",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
@26-30 Apply(
|
||||
@26-27 Var {
|
||||
module_name: "",
|
||||
ident: "f",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
@28-30 Record(
|
||||
|
|
|
@ -12,13 +12,11 @@ Backpassing(
|
|||
),
|
||||
@5-6 Identifier {
|
||||
ident: "r",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
@10-11 Var {
|
||||
module_name: "",
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
@12-13 SpaceBefore(
|
||||
Tag(
|
||||
|
|
|
@ -29,7 +29,6 @@ Defs(
|
|||
Body(
|
||||
@0-1 Identifier {
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
@4-22 Str(
|
||||
Line(
|
||||
|
@ -53,7 +52,6 @@ Defs(
|
|||
Body(
|
||||
@23-24 Identifier {
|
||||
ident: "b",
|
||||
suffixed: 0,
|
||||
},
|
||||
@27-49 Str(
|
||||
Block(
|
||||
|
@ -79,7 +77,6 @@ Defs(
|
|||
Body(
|
||||
@50-51 Identifier {
|
||||
ident: "c",
|
||||
suffixed: 0,
|
||||
},
|
||||
@58-92 SpaceBefore(
|
||||
Str(
|
||||
|
|
|
@ -2,7 +2,6 @@ Apply(
|
|||
@0-1 Var {
|
||||
module_name: "",
|
||||
ident: "e",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
@1-10 Str(
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Annotation(
|
||||
@0-1 Identifier {
|
||||
ident: "f",
|
||||
suffixed: 0,
|
||||
},
|
||||
@8-10 SpaceBefore(
|
||||
Record {
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Annotation(
|
||||
@0-1 Identifier {
|
||||
ident: "f",
|
||||
suffixed: 0,
|
||||
},
|
||||
@17-19 SpaceBefore(
|
||||
Record {
|
||||
|
|
|
@ -4,7 +4,6 @@ RecordAccess(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "rec",
|
||||
suffixed: 0,
|
||||
},
|
||||
"abc",
|
||||
),
|
||||
|
|
|
@ -2,7 +2,6 @@ UnaryOp(
|
|||
@1-4 Var {
|
||||
module_name: "",
|
||||
ident: "inf",
|
||||
suffixed: 0,
|
||||
},
|
||||
@0-1 Negate,
|
||||
)
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Body(
|
||||
@0-1 Identifier {
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
@2-9 Apply(
|
||||
@2-3 SpaceAfter(
|
||||
|
@ -34,14 +33,12 @@ Defs(
|
|||
@6-7 Var {
|
||||
module_name: "",
|
||||
ident: "g",
|
||||
suffixed: 0,
|
||||
},
|
||||
@5-6 Negate,
|
||||
),
|
||||
@8-9 Var {
|
||||
module_name: "",
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
Space,
|
||||
|
@ -53,7 +50,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Body(
|
||||
@0-4 Identifier {
|
||||
ident: "main",
|
||||
suffixed: 0,
|
||||
},
|
||||
@11-71 SpaceBefore(
|
||||
Defs(
|
||||
|
@ -41,20 +40,17 @@ Defs(
|
|||
Body(
|
||||
@11-15 Identifier {
|
||||
ident: "task",
|
||||
suffixed: 0,
|
||||
},
|
||||
@18-62 Backpassing(
|
||||
[
|
||||
@18-22 Identifier {
|
||||
ident: "file",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
@43-46 SpaceBefore(
|
||||
Var {
|
||||
module_name: "",
|
||||
ident: "foo",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
@ -64,7 +60,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "bar",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
@ -78,7 +73,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "task",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -17,7 +17,6 @@ Defs {
|
|||
Body(
|
||||
@0-4 Identifier {
|
||||
ident: "main",
|
||||
suffixed: 0,
|
||||
},
|
||||
@11-115 SpaceBefore(
|
||||
Defs(
|
||||
|
@ -40,7 +39,6 @@ Defs {
|
|||
Annotation(
|
||||
@11-23 Identifier {
|
||||
ident: "wrappedNotEq",
|
||||
suffixed: 0,
|
||||
},
|
||||
@26-38 Function(
|
||||
[
|
||||
|
@ -61,7 +59,6 @@ Defs {
|
|||
AnnotatedBody {
|
||||
ann_pattern: @11-23 Identifier {
|
||||
ident: "wrappedNotEq",
|
||||
suffixed: 0,
|
||||
},
|
||||
ann_type: @26-38 Function(
|
||||
[
|
||||
|
@ -81,17 +78,14 @@ Defs {
|
|||
comment: None,
|
||||
body_pattern: @43-55 Identifier {
|
||||
ident: "wrappedNotEq",
|
||||
suffixed: 0,
|
||||
},
|
||||
body_expr: @58-93 Closure(
|
||||
[
|
||||
@59-63 Identifier {
|
||||
ident: "num1",
|
||||
suffixed: 0,
|
||||
},
|
||||
@65-69 Identifier {
|
||||
ident: "num2",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
@81-93 SpaceBefore(
|
||||
|
@ -101,7 +95,6 @@ Defs {
|
|||
@81-85 Var {
|
||||
module_name: "",
|
||||
ident: "num1",
|
||||
suffixed: 0,
|
||||
},
|
||||
@86-88 NotEquals,
|
||||
),
|
||||
|
@ -109,7 +102,6 @@ Defs {
|
|||
@89-93 Var {
|
||||
module_name: "",
|
||||
ident: "num2",
|
||||
suffixed: 0,
|
||||
},
|
||||
),
|
||||
[
|
||||
|
@ -125,7 +117,6 @@ Defs {
|
|||
@99-111 Var {
|
||||
module_name: "",
|
||||
ident: "wrappedNotEq",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
@112-113 Num(
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Body(
|
||||
@0-1 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@2-7 Defs(
|
||||
Defs {
|
||||
|
@ -40,7 +39,6 @@ Defs(
|
|||
Annotation(
|
||||
@2-3 Identifier {
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
@4-5 BoundVariable(
|
||||
"n",
|
||||
|
|
|
@ -4,7 +4,6 @@ If(
|
|||
@3-5 Var {
|
||||
module_name: "",
|
||||
ident: "t1",
|
||||
suffixed: 0,
|
||||
},
|
||||
@13-14 SpaceBefore(
|
||||
SpaceAfter(
|
||||
|
@ -24,7 +23,6 @@ If(
|
|||
@23-25 Var {
|
||||
module_name: "",
|
||||
ident: "t2",
|
||||
suffixed: 0,
|
||||
},
|
||||
@33-34 SpaceBefore(
|
||||
SpaceAfter(
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Body(
|
||||
@0-1 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@8-9 SpaceBefore(
|
||||
Num(
|
||||
|
|
|
@ -18,7 +18,6 @@ Defs(
|
|||
Body(
|
||||
@0-1 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@4-13 BinOps(
|
||||
[
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
app "hello"
|
||||
packages {
|
||||
pf:
|
||||
"https://github.com/roc-lang/basic-cli/releases/download/0.9.0/oKWkaruh2zXxin_xfsYsCJobH1tO8_JvNkFzDwwzNUQ.tar.br",
|
||||
"https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br",
|
||||
}
|
||||
imports [pf.Stdout]
|
||||
provides [main] to pf
|
||||
|
|
|
@ -17,14 +17,14 @@ Full {
|
|||
after: [],
|
||||
},
|
||||
item: [
|
||||
@27-145 SpaceAfter(
|
||||
@27-146 SpaceAfter(
|
||||
PackageEntry {
|
||||
shorthand: "pf",
|
||||
spaces_after_shorthand: [
|
||||
Newline,
|
||||
],
|
||||
package_name: @31-145 PackageName(
|
||||
"https://github.com/roc-lang/basic-cli/releases/download/0.9.0/oKWkaruh2zXxin_xfsYsCJobH1tO8_JvNkFzDwwzNUQ.tar.br",
|
||||
package_name: @31-146 PackageName(
|
||||
"https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br",
|
||||
),
|
||||
},
|
||||
[
|
||||
|
@ -44,7 +44,7 @@ Full {
|
|||
after: [],
|
||||
},
|
||||
item: [
|
||||
@161-170 Package(
|
||||
@162-171 Package(
|
||||
"pf",
|
||||
ModuleName(
|
||||
"Stdout",
|
||||
|
@ -63,7 +63,7 @@ Full {
|
|||
after: [],
|
||||
},
|
||||
entries: [
|
||||
@186-190 ExposedName(
|
||||
@187-191 ExposedName(
|
||||
"main",
|
||||
),
|
||||
],
|
||||
|
@ -73,7 +73,7 @@ Full {
|
|||
item: ToKeyword,
|
||||
after: [],
|
||||
},
|
||||
to: @195-197 ExistingPackage(
|
||||
to: @196-198 ExistingPackage(
|
||||
"pf",
|
||||
),
|
||||
},
|
||||
|
@ -85,7 +85,7 @@ Full {
|
|||
Index(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@199-246,
|
||||
@200-247,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 2),
|
||||
|
@ -100,19 +100,17 @@ Full {
|
|||
type_defs: [],
|
||||
value_defs: [
|
||||
Body(
|
||||
@199-203 Identifier {
|
||||
@200-204 Identifier {
|
||||
ident: "main",
|
||||
suffixed: 0,
|
||||
},
|
||||
@210-246 SpaceBefore(
|
||||
@211-247 SpaceBefore(
|
||||
Apply(
|
||||
@210-221 Var {
|
||||
@211-222 Var {
|
||||
module_name: "Stdout",
|
||||
ident: "line",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
@222-246 Str(
|
||||
@223-247 Str(
|
||||
PlainLine(
|
||||
"I'm a Roc application!",
|
||||
),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
app "hello"
|
||||
packages { pf:
|
||||
"https://github.com/roc-lang/basic-cli/releases/download/0.9.0/oKWkaruh2zXxin_xfsYsCJobH1tO8_JvNkFzDwwzNUQ.tar.br"
|
||||
"https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br"
|
||||
}
|
||||
imports [pf.Stdout]
|
||||
provides [main] to pf
|
||||
|
|
|
@ -43,7 +43,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "p",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -32,7 +32,6 @@ Defs(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "a",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -3,7 +3,6 @@ SpaceBefore(
|
|||
[
|
||||
@18-19 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
@23-32 ParensAround(
|
||||
|
@ -11,13 +10,11 @@ SpaceBefore(
|
|||
[
|
||||
@25-26 Identifier {
|
||||
ident: "y",
|
||||
suffixed: 0,
|
||||
},
|
||||
],
|
||||
@30-31 Var {
|
||||
module_name: "",
|
||||
ident: "y",
|
||||
suffixed: 0,
|
||||
},
|
||||
),
|
||||
),
|
||||
|
@ -25,7 +22,6 @@ SpaceBefore(
|
|||
Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -19,7 +19,6 @@ SpaceBefore(
|
|||
Body(
|
||||
@18-19 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@20-21 Num(
|
||||
"5",
|
||||
|
|
|
@ -19,7 +19,6 @@ SpaceBefore(
|
|||
Body(
|
||||
@18-19 Identifier {
|
||||
ident: "x",
|
||||
suffixed: 0,
|
||||
},
|
||||
@22-23 Num(
|
||||
"5",
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue