Merge branch 'main' into inline-imports

This commit is contained in:
Agus Zubiaga 2024-04-28 00:11:29 -03:00
commit a8a829aadd
No known key found for this signature in database
201 changed files with 1128 additions and 1523 deletions

View File

@ -14,14 +14,17 @@ jobs:
test-and-build:
name: Rust tests, build and package nightly release
runs-on: [self-hosted, macOS, ARM64]
env:
LIBRARY_PATH: /opt/homebrew/Cellar/zstd/1.5.6/lib
timeout-minutes: 90
steps:
- uses: actions/checkout@v4
- run: zig version
- name: Update PATH to use zig 11
run: |
echo "PATH=/Users/m1ci/Downloads/zig-macos-aarch64-0.11.0:$PATH" >> $GITHUB_ENV
- name: llvm version
run: llc --version | grep LLVM
- run: zig version
- name: run tests
run: cargo test --locked --release

2
Cargo.lock generated
View File

@ -2502,12 +2502,14 @@ dependencies = [
"roc_module",
"roc_packaging",
"roc_parse",
"roc_problem",
"roc_region",
"roc_reporting",
"roc_solve",
"roc_target",
"roc_types",
"snafu",
"ven_pretty",
]
[[package]]

View File

@ -54,6 +54,7 @@ mod cli_run {
const OPTIMIZE_FLAG: &str = concatcp!("--", roc_cli::FLAG_OPTIMIZE);
const LINKER_FLAG: &str = concatcp!("--", roc_cli::FLAG_LINKER);
const CHECK_FLAG: &str = concatcp!("--", roc_cli::FLAG_CHECK);
#[allow(dead_code)]
const PREBUILT_PLATFORM: &str = concatcp!("--", roc_cli::FLAG_PREBUILT);
#[allow(dead_code)]
const TARGET_FLAG: &str = concatcp!("--", roc_cli::FLAG_TARGET);
@ -1025,20 +1026,21 @@ mod cli_run {
// TODO not sure if this cfg should still be here: #[cfg(not(debug_assertions))]
// this is for testing the benchmarks, to perform proper benchmarks see crates/cli/benches/README.md
mod test_benchmarks {
#[allow(unused_imports)]
use super::{TestCliCommands, UseValgrind};
use cli_utils::helpers::cli_testing_dir;
#[allow(unused_imports)]
use super::{check_output_with_stdin, OPTIMIZE_FLAG, PREBUILT_PLATFORM};
#[allow(unused_imports)]
use std::{path::Path, sync::Once};
static BENCHMARKS_BUILD_PLATFORM: Once = Once::new();
fn test_benchmark(
roc_filename: &str,
stdin: &[&str],
expected_ending: &str,
use_valgrind: UseValgrind,
_use_valgrind: UseValgrind,
) {
let file_name = cli_testing_dir("benchmarks").join(roc_filename);
@ -1062,15 +1064,18 @@ mod cli_run {
}
#[cfg(all(not(feature = "wasm32-cli-run"), not(feature = "i386-cli-run")))]
check_output_regular(&file_name, stdin, expected_ending, use_valgrind);
check_output_regular(&file_name, stdin, expected_ending, _use_valgrind);
#[cfg(feature = "wasm32-cli-run")]
check_output_wasm(&file_name, stdin, expected_ending);
#[cfg(feature = "i386-cli-run")]
check_output_i386(&file_name, stdin, expected_ending, use_valgrind);
check_output_i386(&file_name, stdin, expected_ending, _use_valgrind);
}
#[cfg(all(not(feature = "wasm32-cli-run"), not(feature = "i386-cli-run")))]
static BENCHMARKS_BUILD_PLATFORM: Once = Once::new();
#[cfg(all(not(feature = "wasm32-cli-run"), not(feature = "i386-cli-run")))]
fn check_output_regular(
file_name: &Path,

View File

@ -752,10 +752,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);

View File

@ -558,11 +558,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 {
@ -2612,14 +2608,15 @@ pub fn report_unused_imports(
) {
for import in imports_introduced {
if references.has_module_lookup(import.module_id) {
for (symbol, region) in import.exposed_symbols {
if !references.has_unqualified_type_or_value_lookup(symbol)
&& !scope.abilities_store.is_specialization_name(symbol)
for (symbol, region) in &import.exposed_symbols {
if !references.has_unqualified_type_or_value_lookup(*symbol)
&& !scope.abilities_store.is_specialization_name(*symbol)
&& !import.is_task(env)
{
env.problem(Problem::UnusedImport(symbol, region));
env.problem(Problem::UnusedImport(*symbol, *region));
}
}
} else {
} else if !import.is_task(env) {
env.problem(Problem::UnusedModuleImport(import.module_id, import.region));
}
}
@ -2692,10 +2689,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,
@ -2890,6 +2886,16 @@ pub struct IntroducedImport {
exposed_symbols: Vec<(Symbol, Region)>,
}
impl IntroducedImport {
pub fn is_task(&self, env: &Env<'_>) -> bool {
// Temporarily needed for `!` convenience. Can be removed when Task becomes a builtin.
match env.qualified_module_ids.get_name(self.module_id) {
Some(name) => name.as_inner().as_str() == "Task",
None => false,
}
}
}
#[allow(clippy::too_many_arguments)]
fn to_pending_value_def<'a>(
env: &mut Env<'a>,

View File

@ -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,

View File

@ -9,8 +9,8 @@ use roc_module::called_via::{BinOp, CalledVia};
use roc_module::ident::ModuleName;
use roc_parse::ast::Expr::{self, *};
use roc_parse::ast::{
wrap_in_task_ok, AssignedField, Collection, Pattern, RecordBuilderField, StrLiteral,
StrSegment, ValueDef, WhenBranch,
AssignedField, Collection, Pattern, RecordBuilderField, StrLiteral, StrSegment, ValueDef,
WhenBranch,
};
use roc_region::all::{LineInfo, Loc, Region};
@ -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,
});
@ -200,13 +196,7 @@ pub fn desugar_value_def_suffixed<'a>(arena: &'a Bump, value_def: ValueDef<'a>)
arena,
Body(
loc_pattern,
apply_task_await(
arena,
loc_expr.region,
sub_arg,
sub_pat,
wrap_in_task_ok(arena, sub_new),
),
apply_task_await(arena, loc_expr.region, sub_arg, sub_pat, sub_new),
),
),
Err(..) => Body(
@ -248,7 +238,7 @@ pub fn desugar_value_def_suffixed<'a>(arena: &'a Bump, value_def: ValueDef<'a>)
body_expr.region,
sub_arg,
sub_pat,
wrap_in_task_ok(arena, sub_new),
sub_new,
),
},
),
@ -349,6 +339,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 {
@ -608,12 +607,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 });
@ -711,7 +708,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,
@ -766,7 +762,6 @@ pub fn desugar_expr<'a>(
Expr::Var {
module_name: ModuleName::TASK,
ident: "ok",
suffixed: 0,
},
)),
arena.alloc(apply_args),
@ -862,7 +857,6 @@ fn desugar_field<'a>(
value: Var {
module_name: "",
ident: loc_str.value,
suffixed: 0,
},
region: loc_str.region,
};
@ -1043,7 +1037,6 @@ fn record_builder_arg<'a>(
value: Expr::Var {
module_name: "",
ident: arena.alloc("#".to_owned() + label.value),
suffixed: 0,
},
});
@ -1083,10 +1076,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,

View File

@ -977,11 +977,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
@ -1129,6 +1127,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();
@ -2427,7 +2426,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

View File

@ -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.
@ -635,10 +631,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);

View File

@ -57,13 +57,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,
@ -742,13 +740,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"),]
);
}
@ -766,13 +758,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();

View File

@ -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, wrap_in_task_ok, Pattern, ValueDef, WhenBranch};
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,8 +137,8 @@ pub fn unwrap_suffixed_expression<'a>(
// KEEP THIS HERE FOR DEBUGGING
// USEFUL TO SEE THE UNWRAPPING
// OF AST NODES AS THEY DESCEND
// if is_loc_expr_suffixed(loc_expr) {
// dbg!(&loc_expr, &unwrapped_expression);
// if is_expr_suffixed(&loc_expr.value) {
// dbg!(&maybe_def_pat, &loc_expr, &unwrapped_expression);
// }
unwrapped_expression
@ -248,18 +193,6 @@ 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
// unwrap the definition pattern for the closure
match unwrap_suffixed_expression(arena, closure_loc_ret, None) {
@ -316,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
@ -368,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(&current_if_then_expression.value) {
// split if_thens around the current index
let (before, after) = roc_parse::ast::split_around(if_thens, index);
@ -398,13 +325,8 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
sub_pat,
sub_new,
}) => {
let unwrapped_expression = apply_task_await(
arena,
sub_arg.region,
sub_arg,
sub_pat,
wrap_in_task_ok(arena, sub_new),
);
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);
@ -429,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(&current_if_then_statement.value) {
// split if_thens around the current index
let (before, after) = roc_parse::ast::split_around(if_thens, index);
@ -541,13 +463,8 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
sub_pat,
sub_new,
}) => {
let unwrapped_final_else = apply_task_await(
arena,
sub_arg.region,
sub_arg,
sub_pat,
wrap_in_task_ok(arena, sub_new),
);
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,
@ -579,7 +496,7 @@ pub fn unwrap_suffixed_expression_when_help<'a>(
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_loc_expr_suffixed(branch_loc_expr) {
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),
@ -670,7 +587,7 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
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,wrap_in_task_ok(arena, sub_new))
apply_task_await(arena,def_expr.region,sub_arg,sub_pat,sub_new)
}
Err(EUnwrapped::UnwrappedDefExpr(..)) | Err(EUnwrapped::Malformed) => {
// TODO handle case when we have maybe_def_pat so can return an unwrapped up
@ -816,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),

File diff suppressed because one or more lines are too long

View File

@ -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(_, _)
@ -50,6 +48,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,
@ -169,11 +171,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);
@ -181,11 +179,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);
@ -511,60 +504,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);
@ -787,8 +738,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;

View File

@ -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);
}
}

View File

@ -738,6 +738,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)),
@ -746,15 +747,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),
@ -854,7 +847,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(
@ -887,15 +880,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),

View File

@ -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
"###
);

View File

@ -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 {
@ -322,11 +310,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());
}
}
@ -360,11 +344,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());
}
}
@ -388,11 +368,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());
}
}
@ -654,7 +630,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(),

View File

@ -3291,6 +3291,7 @@ fn finish(
LoadedModule {
module_id: state.root_id,
filename: state.root_path,
interns,
solved,
can_problems: state.module_cache.can_problems,

View File

@ -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;

View File

@ -1613,8 +1613,8 @@ fn issue_2863_module_type_does_not_exist() {
Did you mean one of these?
Decoding
Dict
Result
Dict
DecodeError
"
)

View File

@ -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;

View File

@ -968,7 +968,6 @@ macro_rules! define_builtins {
module_id.register_debug_idents(&ident_ids);
}
exposed_idents_by_module.insert(
module_id,
ident_ids
@ -1134,27 +1133,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
}
}
};
}
@ -1552,15 +1530,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

View File

@ -362,7 +362,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),
@ -376,6 +376,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>>>),
@ -395,7 +398,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),
@ -462,17 +464,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) => {
@ -499,45 +490,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
@ -545,35 +534,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
}
_ => false,
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::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,
}
}
pub fn wrap_in_task_ok<'a>(arena: &'a Bump, loc_expr: &'a Loc<Expr<'a>>) -> &'a Loc<Expr<'a>> {
arena.alloc(Loc::at(
loc_expr.region,
Expr::Apply(
arena.alloc(Loc::at(
loc_expr.region,
Expr::Var {
module_name: roc_module::ident::ModuleName::TASK,
ident: "ok",
suffixed: 0,
},
)),
arena.alloc([loc_expr]),
CalledVia::BangSuffix,
),
))
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,
}
}
pub fn split_around<T>(items: &[T], target: usize) -> (&[T], &[T]) {
@ -799,8 +834,6 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
// gets to their parent def.
expr_stack.push(&cont.value);
}
RecordAccess(expr, _) => expr_stack.push(expr),
TupleAccess(expr, _) => expr_stack.push(expr),
List(list) => {
expr_stack.reserve(list.len());
for loc_expr in list.items {
@ -899,11 +932,16 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
}
}
}
SpaceBefore(expr, _) => expr_stack.push(expr),
SpaceAfter(expr, _) => expr_stack.push(expr),
ParensAround(expr) => expr_stack.push(expr),
MultipleRecordBuilders(expr) => expr_stack.push(&expr.value),
UnappliedRecordBuilder(expr) => expr_stack.push(&expr.value),
RecordAccess(expr, _)
| TupleAccess(expr, _)
| TaskAwaitBang(expr)
| SpaceBefore(expr, _)
| SpaceAfter(expr, _)
| ParensAround(expr) => expr_stack.push(expr),
MultipleRecordBuilders(loc_expr) | UnappliedRecordBuilder(loc_expr) => {
expr_stack.push(&loc_expr.value)
}
Float(_)
| Num(_)
@ -1088,13 +1126,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);
@ -1517,12 +1555,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),
@ -1640,21 +1676,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,
},
@ -1716,15 +1742,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
}
@ -1789,15 +1813,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> {
@ -2054,13 +2069,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> {
@ -2294,7 +2307,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(),

View File

@ -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, ImportAlias, ImportAsKeyword, ImportExposingKeyword,
ImportedModuleName, IngestedFileImport, ModuleImport, Pattern, RecordBuilderField, Spaceable,
Spaced, Spaces, TypeAnnotation, TypeDef, TypeHeader, ValueDef,
@ -10,7 +10,7 @@ use crate::blankspace::{
};
use crate::ident::{
integer_ident, lowercase_ident, parse_ident, unqualified_ident, uppercase_ident, Accessor,
Ident,
Ident, Suffix,
};
use crate::module::module_name_help;
use crate::parser::{
@ -140,7 +140,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),
@ -161,16 +161,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),
))
}
@ -193,10 +200,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(),
)
}
@ -216,10 +220,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(),
)
}
@ -234,13 +235,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();
@ -347,7 +366,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
@ -376,7 +395,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)));
@ -448,7 +467,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));
@ -688,7 +707,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
@ -921,7 +942,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)),
@ -1065,7 +1088,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
@ -1968,7 +1991,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
@ -1987,7 +2010,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() {
@ -2100,7 +2123,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
@ -2290,19 +2313,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),
@ -2382,6 +2397,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),
@ -2436,10 +2452,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,
@ -2944,21 +2957,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`,
@ -3320,13 +3325,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)),
})
}

View File

@ -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))

View File

@ -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.
@ -50,14 +49,6 @@ pub fn loc_pattern_help<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, EPattern<'a>>
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)),
@ -393,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, ..
} => {
@ -451,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,
));
@ -615,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))

View File

@ -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()));
}

View File

@ -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;

View File

@ -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;

View File

@ -2,7 +2,6 @@ When(
@5-6 Var {
module_name: "",
ident: "x",
suffixed: 0,
},
[
WhenBranch {

View File

@ -2,7 +2,6 @@ When(
@5-6 Var {
module_name: "",
ident: "x",
suffixed: 0,
},
[
WhenBranch {

View File

@ -4,7 +4,6 @@ BinOps(
@0-1 Var {
module_name: "",
ident: "x",
suffixed: 0,
},
@2-3 Plus,
),

View File

@ -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",

View File

@ -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",

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -2,7 +2,6 @@ Apply(
@0-4 Var {
module_name: "",
ident: "whee",
suffixed: 0,
},
[
@6-8 Num(

View File

@ -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,

View File

@ -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,

View File

@ -2,7 +2,6 @@ Apply(
@0-4 Var {
module_name: "",
ident: "whee",
suffixed: 0,
},
[
@5-6 Num(

View File

@ -19,7 +19,6 @@ SpaceBefore(
Body(
@107-108 Identifier {
ident: "x",
suffixed: 0,
},
@111-112 Num(
"5",

View File

@ -2,7 +2,6 @@ RecordAccess(
Var {
module_name: "",
ident: "rec",
suffixed: 0,
},
"field",
)

View File

@ -1,5 +1,4 @@
Var {
module_name: "",
ident: "whee",
suffixed: 0,
}

View File

@ -18,7 +18,6 @@ Defs(
Annotation(
@0-1 Identifier {
ident: "a",
suffixed: 0,
},
@3-4 SpaceBefore(
BoundVariable(

View File

@ -3,7 +3,6 @@ Apply(
Var {
module_name: "",
ident: "f",
suffixed: 0,
},
[
Newline,

View File

@ -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,
},
),
[

View File

@ -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,
),

View File

@ -30,7 +30,6 @@ Defs(
Var {
module_name: "",
ident: "q",
suffixed: 0,
},
[
LineComment(

View File

@ -21,7 +21,6 @@ Defs {
Body(
@0-3 Identifier {
ident: "foo",
suffixed: 0,
},
@6-7 Num(
"1",

View File

@ -3,7 +3,6 @@ ParensAround(
Var {
module_name: "",
ident: "i",
suffixed: 0,
},
[
LineComment(

View File

@ -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,

View File

@ -19,7 +19,6 @@ Defs(
@0-1 SpaceAfter(
Identifier {
ident: "w",
suffixed: 0,
},
[
LineComment(

View File

@ -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,

View File

@ -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(

View File

@ -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,
},
)

View File

@ -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,

View File

@ -19,7 +19,6 @@ SpaceBefore(
Body(
@48-49 Identifier {
ident: "x",
suffixed: 0,
},
@52-53 Num(
"5",

View File

@ -2,7 +2,6 @@ RecordUpdate {
update: @1-2 Var {
module_name: "",
ident: "e",
suffixed: 0,
},
fields: [],
}

View File

@ -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,
},
)

View File

@ -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,
},
)

View File

@ -33,7 +33,6 @@ Defs(
Var {
module_name: "",
ident: "a",
suffixed: 0,
},
[
Newline,

View File

@ -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,

View File

@ -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(

View File

@ -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(

View File

@ -18,7 +18,6 @@ Defs(
Body(
@0-4 Identifier {
ident: "iffy",
suffixed: 0,
},
@5-6 Num(
"5",

View File

@ -78,7 +78,6 @@ Defs(
@53-62 Var {
module_name: "JE",
ident: "encode",
suffixed: 0,
},
[
@64-70 ParensAround(
@ -86,7 +85,6 @@ Defs(
@64-67 Var {
module_name: "",
ident: "int",
suffixed: 0,
},
[
@68-70 Num(

View File

@ -46,13 +46,11 @@ Defs(
@35-44 Var {
module_name: "",
ident: "parseJson",
suffixed: 0,
},
[
@45-49 Var {
module_name: "",
ident: "data",
suffixed: 0,
},
],
Space,

View File

@ -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,
},
)

View File

@ -2,7 +2,6 @@ Closure(
[
@1-2 Identifier {
ident: "x",
suffixed: 0,
},
],
@8-9 SpaceBefore(

View File

@ -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,

View File

@ -18,7 +18,6 @@ Defs(
Body(
@0-6 Identifier {
ident: "myList",
suffixed: 0,
},
@9-25 List(
[

View File

@ -18,7 +18,6 @@ Defs(
Body(
@0-6 Identifier {
ident: "myList",
suffixed: 0,
},
@9-26 List(
Collection {

View File

@ -19,6 +19,5 @@ BinOps(
@6-7 Var {
module_name: "",
ident: "i",
suffixed: 0,
},
)

View File

@ -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,
},
],
),

View File

@ -19,7 +19,6 @@ SpaceBefore(
Body(
@113-114 Identifier {
ident: "x",
suffixed: 0,
},
@117-118 Num(
"5",

View File

@ -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,

View File

@ -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,
},
),
[

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -2,7 +2,6 @@ Apply(
@0-1 Var {
module_name: "",
ident: "e",
suffixed: 0,
},
[
@1-10 Str(

View File

@ -18,7 +18,6 @@ Defs(
Annotation(
@0-1 Identifier {
ident: "f",
suffixed: 0,
},
@8-10 SpaceBefore(
Record {

View File

@ -18,7 +18,6 @@ Defs(
Annotation(
@0-1 Identifier {
ident: "f",
suffixed: 0,
},
@17-19 SpaceBefore(
Record {

View File

@ -4,7 +4,6 @@ RecordAccess(
Var {
module_name: "",
ident: "rec",
suffixed: 0,
},
"abc",
),

View File

@ -2,7 +2,6 @@ UnaryOp(
@1-4 Var {
module_name: "",
ident: "inf",
suffixed: 0,
},
@0-1 Negate,
)

View File

@ -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,

View File

@ -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,

View File

@ -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(

View File

@ -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",

View File

@ -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(

View File

@ -18,7 +18,6 @@ Defs(
Body(
@0-1 Identifier {
ident: "x",
suffixed: 0,
},
@8-9 SpaceBefore(
Num(

View File

@ -18,7 +18,6 @@ Defs(
Body(
@0-1 Identifier {
ident: "x",
suffixed: 0,
},
@4-13 BinOps(
[

View File

@ -102,14 +102,12 @@ Full {
Body(
@199-203 Identifier {
ident: "main",
suffixed: 0,
},
@210-246 SpaceBefore(
Apply(
@210-221 Var {
module_name: "Stdout",
ident: "line",
suffixed: 0,
},
[
@222-246 Str(

View File

@ -43,7 +43,6 @@ Defs(
Var {
module_name: "",
ident: "p",
suffixed: 0,
},
[
Newline,

View File

@ -32,7 +32,6 @@ Defs(
Var {
module_name: "",
ident: "a",
suffixed: 0,
},
[
Newline,

View File

@ -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,

View File

@ -19,7 +19,6 @@ SpaceBefore(
Body(
@18-19 Identifier {
ident: "x",
suffixed: 0,
},
@20-21 Num(
"5",

View File

@ -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