mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Merge branch 'main' into auto-snake-case
This commit is contained in:
commit
7a2f8bfa71
44 changed files with 650 additions and 464 deletions
8
.github/workflows/nix_linux_x86_64.yml
vendored
8
.github/workflows/nix_linux_x86_64.yml
vendored
|
@ -18,22 +18,22 @@ jobs:
|
||||||
run: nix-build
|
run: nix-build
|
||||||
|
|
||||||
- name: execute tests with --release
|
- name: execute tests with --release
|
||||||
# skipping glue tests due to difficult multithreading bug, we run them single threaded in the next step
|
# skipping glue tests due to difficult multithreading bug, we run them single threaded in the next step, see #7476
|
||||||
run: nix develop -c cargo test --locked --release -- --skip glue_cli_tests
|
run: nix develop -c cargo test --locked --release -- --skip glue_cli_tests
|
||||||
|
|
||||||
- name: glue_cli_tests
|
- name: glue_cli_tests
|
||||||
# single threaded due to difficult bug when multithreading
|
# single threaded due to difficult bug when multithreading, see #7476
|
||||||
run: nix develop -c cargo test --locked --release glue_cli_tests -- --test-threads=1
|
run: nix develop -c cargo test --locked --release glue_cli_tests -- --test-threads=1
|
||||||
|
|
||||||
- name: roc test all builtins
|
- name: roc test all builtins
|
||||||
run: nix develop -c ./ci/roc_test_builtins.sh
|
run: nix develop -c ./ci/roc_test_builtins.sh
|
||||||
|
|
||||||
- name: test wasm32 cli_tests
|
- name: test wasm32 cli_tests
|
||||||
# skipping glue tests due to difficult multithreading bug, we run them single threaded in the next step
|
# skipping glue tests due to difficult multithreading bug, we run them single threaded in the next step, see #7476
|
||||||
run: nix develop -c cargo test --locked --release --features="wasm32-cli-run" -- --skip glue_cli_tests
|
run: nix develop -c cargo test --locked --release --features="wasm32-cli-run" -- --skip glue_cli_tests
|
||||||
|
|
||||||
- name: wasm32 glue_cli_tests
|
- name: wasm32 glue_cli_tests
|
||||||
# single threaded due to difficult bug when multithreading
|
# single threaded due to difficult bug when multithreading, see #7476
|
||||||
run: nix develop -c cargo test --locked --release --features="wasm32-cli-run" glue_cli_tests -- --test-threads=1
|
run: nix develop -c cargo test --locked --release --features="wasm32-cli-run" glue_cli_tests -- --test-threads=1
|
||||||
|
|
||||||
- name: test the dev backend # these tests require an explicit feature flag
|
- name: test the dev backend # these tests require an explicit feature flag
|
||||||
|
|
8
.github/workflows/ubuntu_x86_64.yml
vendored
8
.github/workflows/ubuntu_x86_64.yml
vendored
|
@ -63,7 +63,7 @@ jobs:
|
||||||
- name: test website build script
|
- name: test website build script
|
||||||
run: bash www/build.sh
|
run: bash www/build.sh
|
||||||
|
|
||||||
- name: run fuzz tests - ok to merge if this one fails # for now!
|
#- name: run fuzz tests - ok to merge if this one fails # for now!
|
||||||
run: |
|
# run: |
|
||||||
cargo +nightly-2024-02-03 install --locked cargo-fuzz
|
# cargo +nightly-2024-02-03 install --locked cargo-fuzz
|
||||||
cd crates/compiler/test_syntax/fuzz && cargo +nightly-2024-02-03 fuzz run -j4 fuzz_expr --sanitizer=none -- -dict=dict.txt -max_total_time=60
|
# cd crates/compiler/test_syntax/fuzz && cargo +nightly-2024-02-03 fuzz run -j4 fuzz_expr --sanitizer=none -- -dict=dict.txt -max_total_time=60
|
||||||
|
|
|
@ -22,6 +22,10 @@ jobs:
|
||||||
- name: Check if debug flag files are in sync
|
- name: Check if debug flag files are in sync
|
||||||
run: ./ci/check_debug_vars.sh
|
run: ./ci/check_debug_vars.sh
|
||||||
|
|
||||||
# for skipped tests; see #6946, #6947
|
|
||||||
- name: cargo test without --release
|
- name: cargo test without --release
|
||||||
run: nix develop -c sh -c 'export ROC_CHECK_MONO_IR=1 && cargo test'
|
# skipping glue tests due to difficult multithreading bug, we run them single threaded in the next step, see #7476
|
||||||
|
run: nix develop -c sh -c 'export ROC_CHECK_MONO_IR=1 && cargo test --locked -- --skip glue_cli_tests'
|
||||||
|
|
||||||
|
- name: glue_cli_tests
|
||||||
|
# single threaded due to difficult bug when multithreading, see #7476
|
||||||
|
run: nix develop -c sh -c 'export ROC_CHECK_MONO_IR=1 && cargo test --locked glue_cli_tests -- --test-threads=1'
|
||||||
|
|
1
AUTHORS
1
AUTHORS
|
@ -170,3 +170,4 @@ Isak Jones <isak.jones.980@gmail.com>
|
||||||
Ch1n3du <danielonyesoh@gmail.com>
|
Ch1n3du <danielonyesoh@gmail.com>
|
||||||
Elias Mulhall <eli.mulhall@gmail.com>
|
Elias Mulhall <eli.mulhall@gmail.com>
|
||||||
ABuffSeagull <reecevanatta@hey.com>
|
ABuffSeagull <reecevanatta@hey.com>
|
||||||
|
Timon Krebs <timonkrebs@hotmail.com>
|
|
@ -895,7 +895,7 @@ mod cli_tests {
|
||||||
build_platform_host();
|
build_platform_host();
|
||||||
|
|
||||||
let cli_build = ExecCli::new(
|
let cli_build = ExecCli::new(
|
||||||
roc_cli::CMD_DEV,
|
roc_cli::CMD_BUILD,
|
||||||
file_from_root("crates/cli/tests/test-projects/effectful", "form.roc"),
|
file_from_root("crates/cli/tests/test-projects/effectful", "form.roc"),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -915,14 +915,14 @@ mod cli_tests {
|
||||||
fn effectful_hello() {
|
fn effectful_hello() {
|
||||||
build_platform_host();
|
build_platform_host();
|
||||||
|
|
||||||
let cli_build = ExecCli::new(
|
let cli_dev = ExecCli::new(
|
||||||
roc_cli::CMD_DEV,
|
roc_cli::CMD_DEV,
|
||||||
file_from_root("crates/cli/tests/test-projects/effectful/", "hello.roc"),
|
file_from_root("crates/cli/tests/test-projects/effectful/", "hello.roc"),
|
||||||
);
|
);
|
||||||
|
|
||||||
let expected_out = "I'm an effect 👻\n";
|
let expected_out = "I'm an effect 👻\n";
|
||||||
|
|
||||||
cli_build.run().assert_clean_stdout(expected_out);
|
cli_dev.run().assert_clean_stdout(expected_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -930,14 +930,14 @@ mod cli_tests {
|
||||||
fn effectful_loops() {
|
fn effectful_loops() {
|
||||||
build_platform_host();
|
build_platform_host();
|
||||||
|
|
||||||
let cli_build = ExecCli::new(
|
let cli_dev = ExecCli::new(
|
||||||
roc_cli::CMD_DEV,
|
roc_cli::CMD_DEV,
|
||||||
file_from_root("crates/cli/tests/test-projects/effectful/", "loops.roc"),
|
file_from_root("crates/cli/tests/test-projects/effectful/", "loops.roc"),
|
||||||
);
|
);
|
||||||
|
|
||||||
let expected_out = "Lu\nMarce\nJoaquin\nChloé\nMati\nPedro\n";
|
let expected_out = "Lu\nMarce\nJoaquin\nChloé\nMati\nPedro\n";
|
||||||
|
|
||||||
cli_build.run().assert_clean_stdout(expected_out);
|
cli_dev.run().assert_clean_stdout(expected_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -945,7 +945,7 @@ mod cli_tests {
|
||||||
fn effectful_untyped_passed_fx() {
|
fn effectful_untyped_passed_fx() {
|
||||||
build_platform_host();
|
build_platform_host();
|
||||||
|
|
||||||
let cli_build = ExecCli::new(
|
let cli_dev = ExecCli::new(
|
||||||
roc_cli::CMD_DEV,
|
roc_cli::CMD_DEV,
|
||||||
file_from_root(
|
file_from_root(
|
||||||
"crates/cli/tests/test-projects/effectful/",
|
"crates/cli/tests/test-projects/effectful/",
|
||||||
|
@ -955,7 +955,7 @@ mod cli_tests {
|
||||||
|
|
||||||
let expected_out = "Before hello\nHello, World!\nAfter hello\n";
|
let expected_out = "Before hello\nHello, World!\nAfter hello\n";
|
||||||
|
|
||||||
cli_build.run().assert_clean_stdout(expected_out);
|
cli_dev.run().assert_clean_stdout(expected_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -963,7 +963,7 @@ mod cli_tests {
|
||||||
fn effectful_ignore_result() {
|
fn effectful_ignore_result() {
|
||||||
build_platform_host();
|
build_platform_host();
|
||||||
|
|
||||||
let cli_build = ExecCli::new(
|
let cli_dev = ExecCli::new(
|
||||||
roc_cli::CMD_DEV,
|
roc_cli::CMD_DEV,
|
||||||
file_from_root(
|
file_from_root(
|
||||||
"crates/cli/tests/test-projects/effectful/",
|
"crates/cli/tests/test-projects/effectful/",
|
||||||
|
@ -973,7 +973,7 @@ mod cli_tests {
|
||||||
|
|
||||||
let expected_out = "I asked for input and I ignored it. Deal with it! 😎\n";
|
let expected_out = "I asked for input and I ignored it. Deal with it! 😎\n";
|
||||||
|
|
||||||
cli_build.run().assert_clean_stdout(expected_out);
|
cli_dev.run().assert_clean_stdout(expected_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -982,7 +982,7 @@ mod cli_tests {
|
||||||
build_platform_host();
|
build_platform_host();
|
||||||
|
|
||||||
let cli_build = ExecCli::new(
|
let cli_build = ExecCli::new(
|
||||||
roc_cli::CMD_DEV,
|
roc_cli::CMD_BUILD,
|
||||||
file_from_root(
|
file_from_root(
|
||||||
"crates/cli/tests/test-projects/effectful",
|
"crates/cli/tests/test-projects/effectful",
|
||||||
"suffixed_record_field.roc",
|
"suffixed_record_field.roc",
|
||||||
|
@ -1005,7 +1005,7 @@ mod cli_tests {
|
||||||
build_platform_host();
|
build_platform_host();
|
||||||
|
|
||||||
let cli_build = ExecCli::new(
|
let cli_build = ExecCli::new(
|
||||||
roc_cli::CMD_DEV,
|
roc_cli::CMD_BUILD,
|
||||||
file_from_root("crates/cli/tests/test-projects/effectful", "on_err.roc"),
|
file_from_root("crates/cli/tests/test-projects/effectful", "on_err.roc"),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1020,7 +1020,7 @@ mod cli_tests {
|
||||||
build_platform_host();
|
build_platform_host();
|
||||||
|
|
||||||
let cli_build = ExecCli::new(
|
let cli_build = ExecCli::new(
|
||||||
roc_cli::CMD_DEV,
|
roc_cli::CMD_BUILD,
|
||||||
file_from_root(
|
file_from_root(
|
||||||
"crates/cli/tests/test-projects/effectful",
|
"crates/cli/tests/test-projects/effectful",
|
||||||
"for_each_try.roc",
|
"for_each_try.roc",
|
||||||
|
|
|
@ -80,6 +80,8 @@ impl ExecCli {
|
||||||
app_stdin_opt: Option<&str>,
|
app_stdin_opt: Option<&str>,
|
||||||
app_args_opt: Option<&[&str]>,
|
app_args_opt: Option<&[&str]>,
|
||||||
) {
|
) {
|
||||||
|
assert!(self.sub_command == roc_cli::CMD_BUILD, "check_build_and_run should be run with the build command, instead it was run with '{}'.", self.sub_command);
|
||||||
|
|
||||||
let build_cmd_out = self.run();
|
let build_cmd_out = self.run();
|
||||||
build_cmd_out.assert_clean_success();
|
build_cmd_out.assert_clean_success();
|
||||||
|
|
||||||
|
|
|
@ -456,7 +456,7 @@ fn gen_from_mono_module_dev<'a>(
|
||||||
|
|
||||||
#[cfg(feature = "target-wasm32")]
|
#[cfg(feature = "target-wasm32")]
|
||||||
{
|
{
|
||||||
internal_error!("Compiler was not built with feature 'target-wasm32'.")
|
internal_error!("Compiler was built with feature 'target-wasm32'.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(_, Architecture::Aarch32) => {
|
(_, Architecture::Aarch32) => {
|
||||||
|
|
|
@ -283,10 +283,16 @@ dbg_bool = \b ->
|
||||||
|
|
||||||
dbg_str : Str -> Inspector DbgFormatter
|
dbg_str : Str -> Inspector DbgFormatter
|
||||||
dbg_str = \s ->
|
dbg_str = \s ->
|
||||||
|
# escape invisible unicode characters as in fmt_str_body crates/compiler/fmt/src/expr.rs
|
||||||
|
escape_s =
|
||||||
|
Str.replace_each(s, "\u(feff)", "\\u(feff)")
|
||||||
|
|> Str.replace_each("\u(200b)", "\\u(200b)")
|
||||||
|
|> Str.replace_each("\u(200c)", "\\u(200c)")
|
||||||
|
|> Str.replace_each("\u(200d)", "\\u(200d)")
|
||||||
|
|
||||||
custom_dbg_str = \f0 ->
|
custom_dbg_str = \f0 ->
|
||||||
f0
|
dbg_write(f0, "\"")
|
||||||
|> dbg_write("\"")
|
|> dbg_write(escape_s)
|
||||||
|> dbg_write(s) # TODO: Should we be escaping strings for dbg/logging?
|
|
||||||
|> dbg_write("\"")
|
|> dbg_write("\"")
|
||||||
|
|
||||||
custom(custom_dbg_str)
|
custom(custom_dbg_str)
|
||||||
|
|
|
@ -538,14 +538,14 @@ to_utf8 : Str -> List U8
|
||||||
## expect Str.from_utf8([]) == Ok("")
|
## expect Str.from_utf8([]) == Ok("")
|
||||||
## expect Str.from_utf8([255]) |> Result.is_err
|
## expect Str.from_utf8([255]) |> Result.is_err
|
||||||
## ```
|
## ```
|
||||||
from_utf8 : List U8 -> Result Str [BadUtf8 Utf8ByteProblem U64]
|
from_utf8 : List U8 -> Result Str [BadUtf8 { problem : Utf8ByteProblem, index : U64 }]
|
||||||
from_utf8 = \bytes ->
|
from_utf8 = \bytes ->
|
||||||
result = from_utf8_lowlevel(bytes)
|
result = from_utf8_lowlevel bytes
|
||||||
|
|
||||||
if result.c_is_ok then
|
if result.c_is_ok then
|
||||||
Ok(result.b_string)
|
Ok(result.b_string)
|
||||||
else
|
else
|
||||||
Err(BadUtf8(result.d_problem_code, result.a_byte_index))
|
Err (BadUtf8 { problem: result.d_problem_code, index: result.a_byte_index })
|
||||||
|
|
||||||
expect (Str.from_utf8([82, 111, 99])) == Ok("Roc")
|
expect (Str.from_utf8([82, 111, 99])) == Ok("Roc")
|
||||||
expect (Str.from_utf8([224, 174, 154, 224, 174, 191])) == Ok("சி")
|
expect (Str.from_utf8([224, 174, 154, 224, 174, 191])) == Ok("சி")
|
||||||
|
|
|
@ -272,7 +272,7 @@ enum PendingTypeDef<'a> {
|
||||||
name: Loc<Symbol>,
|
name: Loc<Symbol>,
|
||||||
vars: Vec<Loc<Lowercase>>,
|
vars: Vec<Loc<Lowercase>>,
|
||||||
ann: &'a Loc<ast::TypeAnnotation<'a>>,
|
ann: &'a Loc<ast::TypeAnnotation<'a>>,
|
||||||
derived: Option<&'a Loc<ast::ImplementsAbilities<'a>>>,
|
derived: Option<&'a ast::ImplementsAbilities<'a>>,
|
||||||
},
|
},
|
||||||
|
|
||||||
Ability {
|
Ability {
|
||||||
|
@ -319,7 +319,7 @@ impl PendingTypeDef<'_> {
|
||||||
ann,
|
ann,
|
||||||
derived,
|
derived,
|
||||||
} => {
|
} => {
|
||||||
let end = derived.map(|d| d.region).unwrap_or(ann.region);
|
let end = derived.map(|d| d.item.region).unwrap_or(ann.region);
|
||||||
let region = Region::span_across(&name.region, &end);
|
let region = Region::span_across(&name.region, &end);
|
||||||
|
|
||||||
Some((name.value, region))
|
Some((name.value, region))
|
||||||
|
@ -761,12 +761,11 @@ fn canonicalize_opaque<'a>(
|
||||||
var_store: &mut VarStore,
|
var_store: &mut VarStore,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
pending_abilities_in_scope: &PendingAbilitiesInScope,
|
pending_abilities_in_scope: &PendingAbilitiesInScope,
|
||||||
|
|
||||||
name: Loc<Symbol>,
|
name: Loc<Symbol>,
|
||||||
name_str: &'a str,
|
name_str: &'a str,
|
||||||
ann: &'a Loc<ast::TypeAnnotation<'a>>,
|
ann: &'a Loc<ast::TypeAnnotation<'a>>,
|
||||||
vars: &[Loc<Lowercase>],
|
vars: &[Loc<Lowercase>],
|
||||||
has_abilities: Option<&'a Loc<ast::ImplementsAbilities<'a>>>,
|
has_abilities: Option<&'a ast::ImplementsAbilities<'a>>,
|
||||||
) -> Result<CanonicalizedOpaque<'a>, ()> {
|
) -> Result<CanonicalizedOpaque<'a>, ()> {
|
||||||
let alias = canonicalize_alias(
|
let alias = canonicalize_alias(
|
||||||
env,
|
env,
|
||||||
|
@ -784,11 +783,11 @@ fn canonicalize_opaque<'a>(
|
||||||
|
|
||||||
let mut derived_defs = Vec::new();
|
let mut derived_defs = Vec::new();
|
||||||
if let Some(has_abilities) = has_abilities {
|
if let Some(has_abilities) = has_abilities {
|
||||||
let has_abilities = has_abilities.value.collection();
|
let has_abilities = has_abilities.item;
|
||||||
|
|
||||||
let mut derived_abilities = vec![];
|
let mut derived_abilities = vec![];
|
||||||
|
|
||||||
for has_ability in has_abilities.items {
|
for has_ability in has_abilities.value.items {
|
||||||
let region = has_ability.region;
|
let region = has_ability.region;
|
||||||
let (ability, opt_impls) = match has_ability.value.extract_spaces().item {
|
let (ability, opt_impls) = match has_ability.value.extract_spaces().item {
|
||||||
ast::ImplementsAbility::ImplementsAbility { ability, impls } => (ability, impls),
|
ast::ImplementsAbility::ImplementsAbility { ability, impls } => (ability, impls),
|
||||||
|
@ -1303,7 +1302,7 @@ fn canonicalize_type_defs<'a>(
|
||||||
Loc<Symbol>,
|
Loc<Symbol>,
|
||||||
Vec<Loc<Lowercase>>,
|
Vec<Loc<Lowercase>>,
|
||||||
&'a Loc<ast::TypeAnnotation<'a>>,
|
&'a Loc<ast::TypeAnnotation<'a>>,
|
||||||
Option<&'a Loc<ast::ImplementsAbilities<'a>>>,
|
Option<&'a ast::ImplementsAbilities<'a>>,
|
||||||
),
|
),
|
||||||
Ability(Loc<Symbol>, Vec<PendingAbilityMember<'a>>),
|
Ability(Loc<Symbol>, Vec<PendingAbilityMember<'a>>),
|
||||||
}
|
}
|
||||||
|
@ -2805,7 +2804,7 @@ fn to_pending_alias_or_opaque<'a>(
|
||||||
name: &'a Loc<&'a str>,
|
name: &'a Loc<&'a str>,
|
||||||
vars: &'a [Loc<ast::Pattern<'a>>],
|
vars: &'a [Loc<ast::Pattern<'a>>],
|
||||||
ann: &'a Loc<ast::TypeAnnotation<'a>>,
|
ann: &'a Loc<ast::TypeAnnotation<'a>>,
|
||||||
opt_derived: Option<&'a Loc<ast::ImplementsAbilities<'a>>>,
|
opt_derived: Option<&'a ast::ImplementsAbilities<'a>>,
|
||||||
kind: AliasKind,
|
kind: AliasKind,
|
||||||
) -> PendingTypeDef<'a> {
|
) -> PendingTypeDef<'a> {
|
||||||
let region = Region::span_across(&name.region, &ann.region);
|
let region = Region::span_across(&name.region, &ann.region);
|
||||||
|
@ -2898,15 +2897,7 @@ fn to_pending_type_def<'a>(
|
||||||
header: TypeHeader { name, vars },
|
header: TypeHeader { name, vars },
|
||||||
typ: ann,
|
typ: ann,
|
||||||
derived,
|
derived,
|
||||||
} => to_pending_alias_or_opaque(
|
} => to_pending_alias_or_opaque(env, scope, name, vars, ann, *derived, AliasKind::Opaque),
|
||||||
env,
|
|
||||||
scope,
|
|
||||||
name,
|
|
||||||
vars,
|
|
||||||
ann,
|
|
||||||
derived.as_ref(),
|
|
||||||
AliasKind::Opaque,
|
|
||||||
),
|
|
||||||
|
|
||||||
Ability {
|
Ability {
|
||||||
header, members, ..
|
header, members, ..
|
||||||
|
|
|
@ -703,36 +703,37 @@ impl<'a> Formattable for ImplementsAbility<'a> {
|
||||||
|
|
||||||
impl<'a> Formattable for ImplementsAbilities<'a> {
|
impl<'a> Formattable for ImplementsAbilities<'a> {
|
||||||
fn is_multiline(&self) -> bool {
|
fn is_multiline(&self) -> bool {
|
||||||
match self {
|
self.before_implements_kw.iter().any(|s| s.is_comment())
|
||||||
ImplementsAbilities::SpaceAfter(..) | ImplementsAbilities::SpaceBefore(..) => true,
|
|| self.after_implements_kw.iter().any(|s| s.is_comment())
|
||||||
ImplementsAbilities::Implements(has_abilities) => {
|
|| is_collection_multiline(&self.item.value)
|
||||||
is_collection_multiline(has_abilities)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
|
fn format_with_options(&self, buf: &mut Buf, _parens: Parens, newlines: Newlines, indent: u16) {
|
||||||
match self {
|
if !self.before_implements_kw.is_empty() {
|
||||||
ImplementsAbilities::Implements(has_abilities) => {
|
buf.newline();
|
||||||
if newlines == Newlines::Yes {
|
buf.indent(indent);
|
||||||
buf.newline();
|
fmt_comments_only(
|
||||||
}
|
buf,
|
||||||
buf.indent(indent);
|
self.before_implements_kw.iter(),
|
||||||
buf.push_str(roc_parse::keyword::IMPLEMENTS);
|
NewlineAt::Bottom,
|
||||||
buf.spaces(1);
|
indent,
|
||||||
fmt_collection(buf, indent, Braces::Square, *has_abilities, Newlines::No);
|
);
|
||||||
}
|
|
||||||
ImplementsAbilities::SpaceBefore(has_abilities, spaces) => {
|
|
||||||
buf.newline();
|
|
||||||
buf.indent(indent);
|
|
||||||
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
|
|
||||||
has_abilities.format_with_options(buf, parens, Newlines::No, indent)
|
|
||||||
}
|
|
||||||
ImplementsAbilities::SpaceAfter(has_abilities, spaces) => {
|
|
||||||
has_abilities.format_with_options(buf, parens, newlines, indent);
|
|
||||||
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if newlines == Newlines::Yes {
|
||||||
|
buf.ensure_ends_with_newline();
|
||||||
|
}
|
||||||
|
buf.indent(indent);
|
||||||
|
buf.push_str(roc_parse::keyword::IMPLEMENTS);
|
||||||
|
if !self.after_implements_kw.is_empty() {
|
||||||
|
fmt_comments_only(
|
||||||
|
buf,
|
||||||
|
self.after_implements_kw.iter(),
|
||||||
|
NewlineAt::Bottom,
|
||||||
|
indent,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
buf.ensure_ends_with_whitespace();
|
||||||
|
fmt_collection(buf, indent, Braces::Square, self.item.value, Newlines::No);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1217,7 +1218,7 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
|
||||||
},
|
},
|
||||||
after: last_after,
|
after: last_after,
|
||||||
needs_indent,
|
needs_indent,
|
||||||
prec: Prec::AsType,
|
prec: Prec::FunctionType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@ use roc_error_macros::internal_error;
|
||||||
use roc_parse::ast::{
|
use roc_parse::ast::{
|
||||||
AbilityMember, Defs, Expr, ExtractSpaces, ImportAlias, ImportAsKeyword, ImportExposingKeyword,
|
AbilityMember, Defs, Expr, ExtractSpaces, ImportAlias, ImportAsKeyword, ImportExposingKeyword,
|
||||||
ImportedModuleName, IngestedFileAnnotation, IngestedFileImport, ModuleImport,
|
ImportedModuleName, IngestedFileAnnotation, IngestedFileImport, ModuleImport,
|
||||||
ModuleImportParams, Pattern, PatternApplyStyle, Spaceable, Spaces, SpacesAfter, SpacesBefore,
|
ModuleImportParams, Pattern, PatternApplyStyle, Spaces, SpacesBefore, StrLiteral,
|
||||||
StrLiteral, TypeAnnotation, TypeDef, TypeHeader, ValueDef,
|
TypeAnnotation, TypeDef, TypeHeader, ValueDef,
|
||||||
};
|
};
|
||||||
use roc_parse::expr::merge_spaces;
|
use roc_parse::expr::merge_spaces;
|
||||||
use roc_parse::header::Keyword;
|
use roc_parse::header::Keyword;
|
||||||
|
@ -94,21 +94,6 @@ pub fn def_lift_spaces<'a, 'b: 'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lift_spaces_after<'a, 'b: 'a, T: 'b + ExtractSpaces<'a> + Spaceable<'a>>(
|
|
||||||
arena: &'a Bump,
|
|
||||||
item: T,
|
|
||||||
) -> SpacesAfter<'a, <T as ExtractSpaces<'a>>::Item>
|
|
||||||
where
|
|
||||||
<T as ExtractSpaces<'a>>::Item: Spaceable<'a>,
|
|
||||||
{
|
|
||||||
let spaces = item.extract_spaces();
|
|
||||||
|
|
||||||
SpacesAfter {
|
|
||||||
item: spaces.item.maybe_before(arena, spaces.before),
|
|
||||||
after: spaces.after,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tydef_lift_spaces<'a, 'b: 'a>(arena: &'a Bump, def: TypeDef<'b>) -> Spaces<'a, TypeDef<'a>> {
|
pub fn tydef_lift_spaces<'a, 'b: 'a>(arena: &'a Bump, def: TypeDef<'b>) -> Spaces<'a, TypeDef<'a>> {
|
||||||
match def {
|
match def {
|
||||||
TypeDef::Alias { header, ann } => {
|
TypeDef::Alias { header, ann } => {
|
||||||
|
@ -128,17 +113,12 @@ pub fn tydef_lift_spaces<'a, 'b: 'a>(arena: &'a Bump, def: TypeDef<'b>) -> Space
|
||||||
typ,
|
typ,
|
||||||
derived,
|
derived,
|
||||||
} => {
|
} => {
|
||||||
if let Some(derived) = derived {
|
if derived.is_some() {
|
||||||
let derived_lifted = lift_spaces_after(arena, derived.value);
|
// It's structurally impossible for a derived clause to have spaces after
|
||||||
|
|
||||||
Spaces {
|
Spaces {
|
||||||
before: &[],
|
before: &[],
|
||||||
item: TypeDef::Opaque {
|
item: def,
|
||||||
header,
|
after: &[],
|
||||||
typ,
|
|
||||||
derived: Some(Loc::at(derived.region, derived_lifted.item)),
|
|
||||||
},
|
|
||||||
after: derived_lifted.after,
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let typ_lifted = ann_lift_spaces_after(arena, &typ.value);
|
let typ_lifted = ann_lift_spaces_after(arena, &typ.value);
|
||||||
|
@ -461,7 +441,7 @@ impl<'a> Formattable for TypeDef<'a> {
|
||||||
// Always put the has-abilities clause on a newline if the opaque annotation
|
// Always put the has-abilities clause on a newline if the opaque annotation
|
||||||
// contains a where-has clause.
|
// contains a where-has clause.
|
||||||
let has_abilities_multiline = if let Some(has_abilities) = has_abilities {
|
let has_abilities_multiline = if let Some(has_abilities) = has_abilities {
|
||||||
!has_abilities.value.is_empty() && ann_is_where_clause
|
!has_abilities.item.value.is_empty() && ann_is_where_clause
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
@ -481,7 +461,7 @@ impl<'a> Formattable for TypeDef<'a> {
|
||||||
if let Some(has_abilities) = has_abilities {
|
if let Some(has_abilities) = has_abilities {
|
||||||
buf.spaces(1);
|
buf.spaces(1);
|
||||||
|
|
||||||
has_abilities.format_with_options(
|
(*has_abilities).format_with_options(
|
||||||
buf,
|
buf,
|
||||||
Parens::NotNeeded,
|
Parens::NotNeeded,
|
||||||
Newlines::from_bool(make_multiline),
|
Newlines::from_bool(make_multiline),
|
||||||
|
|
|
@ -1814,14 +1814,17 @@ fn fmt_return<'a>(
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
buf.push_str(keyword::RETURN);
|
buf.push_str(keyword::RETURN);
|
||||||
|
|
||||||
let return_indent = if return_value.is_multiline() {
|
let value = expr_lift_spaces(parens, buf.text.bump(), &return_value.value);
|
||||||
|
|
||||||
|
let return_indent = if value.item.is_multiline()
|
||||||
|
|| (newlines == Newlines::Yes && !value.before.is_empty())
|
||||||
|
|| value.before.iter().any(|s| s.is_comment())
|
||||||
|
{
|
||||||
indent + INDENT
|
indent + INDENT
|
||||||
} else {
|
} else {
|
||||||
indent
|
indent
|
||||||
};
|
};
|
||||||
|
|
||||||
let value = expr_lift_spaces(parens, buf.text.bump(), &return_value.value);
|
|
||||||
|
|
||||||
if !value.before.is_empty() {
|
if !value.before.is_empty() {
|
||||||
format_spaces(buf, value.before, newlines, return_indent);
|
format_spaces(buf, value.before, newlines, return_indent);
|
||||||
}
|
}
|
||||||
|
@ -2057,15 +2060,17 @@ fn fmt_record_like<'a, 'b: 'a, Field, ToSpacesAround>(
|
||||||
// doesnt make sense.
|
// doesnt make sense.
|
||||||
Some(RecordPrefix::Update(record_var)) => {
|
Some(RecordPrefix::Update(record_var)) => {
|
||||||
buf.spaces(1);
|
buf.spaces(1);
|
||||||
record_var.format(buf, indent);
|
record_var.format(buf, indent + INDENT);
|
||||||
buf.indent(indent);
|
buf.indent(indent + INDENT);
|
||||||
buf.push_str(" &");
|
buf.ensure_ends_with_whitespace();
|
||||||
|
buf.push_str("&");
|
||||||
}
|
}
|
||||||
Some(RecordPrefix::Mapper(mapper_var)) => {
|
Some(RecordPrefix::Mapper(mapper_var)) => {
|
||||||
buf.spaces(1);
|
buf.spaces(1);
|
||||||
mapper_var.format(buf, indent);
|
mapper_var.format(buf, indent + INDENT);
|
||||||
buf.indent(indent);
|
buf.indent(indent + INDENT);
|
||||||
buf.push_str(" <-");
|
buf.ensure_ends_with_whitespace();
|
||||||
|
buf.push_str("<-");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -841,7 +841,7 @@ pub enum TypeDef<'a> {
|
||||||
Opaque {
|
Opaque {
|
||||||
header: TypeHeader<'a>,
|
header: TypeHeader<'a>,
|
||||||
typ: Loc<TypeAnnotation<'a>>,
|
typ: Loc<TypeAnnotation<'a>>,
|
||||||
derived: Option<Loc<ImplementsAbilities<'a>>>,
|
derived: Option<&'a ImplementsAbilities<'a>>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// An ability definition. E.g.
|
/// An ability definition. E.g.
|
||||||
|
@ -1552,31 +1552,11 @@ pub enum ImplementsAbility<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub enum ImplementsAbilities<'a> {
|
pub struct ImplementsAbilities<'a> {
|
||||||
/// `implements [Eq { eq: myEq }, Hash]`
|
pub before_implements_kw: &'a [CommentOrNewline<'a>],
|
||||||
Implements(Collection<'a, Loc<ImplementsAbility<'a>>>),
|
pub implements: Region,
|
||||||
|
pub after_implements_kw: &'a [CommentOrNewline<'a>],
|
||||||
// We preserve this for the formatter; canonicalization ignores it.
|
pub item: Loc<Collection<'a, Loc<ImplementsAbility<'a>>>>,
|
||||||
SpaceBefore(&'a ImplementsAbilities<'a>, &'a [CommentOrNewline<'a>]),
|
|
||||||
SpaceAfter(&'a ImplementsAbilities<'a>, &'a [CommentOrNewline<'a>]),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImplementsAbilities<'_> {
|
|
||||||
pub fn collection(&self) -> &Collection<Loc<ImplementsAbility>> {
|
|
||||||
let mut it = self;
|
|
||||||
loop {
|
|
||||||
match it {
|
|
||||||
Self::SpaceBefore(inner, _) | Self::SpaceAfter(inner, _) => {
|
|
||||||
it = inner;
|
|
||||||
}
|
|
||||||
Self::Implements(collection) => return collection,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
|
||||||
self.collection().is_empty()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
|
@ -2278,15 +2258,6 @@ impl<'a> Spaceable<'a> for ImplementsAbility<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Spaceable<'a> for ImplementsAbilities<'a> {
|
|
||||||
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
|
|
||||||
ImplementsAbilities::SpaceBefore(self, spaces)
|
|
||||||
}
|
|
||||||
fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
|
|
||||||
ImplementsAbilities::SpaceAfter(self, spaces)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Expr<'a> {
|
impl<'a> Expr<'a> {
|
||||||
pub const REPL_OPAQUE_FUNCTION: Self = Expr::Var {
|
pub const REPL_OPAQUE_FUNCTION: Self = Expr::Var {
|
||||||
module_name: "",
|
module_name: "",
|
||||||
|
@ -2396,7 +2367,6 @@ impl_extract_spaces!(Tag);
|
||||||
impl_extract_spaces!(AssignedField<T>);
|
impl_extract_spaces!(AssignedField<T>);
|
||||||
impl_extract_spaces!(TypeAnnotation);
|
impl_extract_spaces!(TypeAnnotation);
|
||||||
impl_extract_spaces!(ImplementsAbility);
|
impl_extract_spaces!(ImplementsAbility);
|
||||||
impl_extract_spaces!(ImplementsAbilities);
|
|
||||||
impl_extract_spaces!(Implements);
|
impl_extract_spaces!(Implements);
|
||||||
|
|
||||||
impl<'a, T: Copy> ExtractSpaces<'a> for Spaced<'a, T> {
|
impl<'a, T: Copy> ExtractSpaces<'a> for Spaced<'a, T> {
|
||||||
|
@ -2720,7 +2690,11 @@ impl<'a> Malformed for TypeDef<'a> {
|
||||||
header,
|
header,
|
||||||
typ,
|
typ,
|
||||||
derived,
|
derived,
|
||||||
} => header.is_malformed() || typ.is_malformed() || derived.is_malformed(),
|
} => {
|
||||||
|
header.is_malformed()
|
||||||
|
|| typ.is_malformed()
|
||||||
|
|| derived.map(|d| d.item.is_malformed()).unwrap_or_default()
|
||||||
|
}
|
||||||
TypeDef::Ability {
|
TypeDef::Ability {
|
||||||
header,
|
header,
|
||||||
loc_implements,
|
loc_implements,
|
||||||
|
@ -2762,19 +2736,6 @@ impl<'a> Malformed for ImplementsAbility<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Malformed for ImplementsAbilities<'a> {
|
|
||||||
fn is_malformed(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
ImplementsAbilities::Implements(abilities) => {
|
|
||||||
abilities.iter().any(|ability| ability.is_malformed())
|
|
||||||
}
|
|
||||||
ImplementsAbilities::SpaceBefore(has, _) | ImplementsAbilities::SpaceAfter(has, _) => {
|
|
||||||
has.is_malformed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Malformed for AbilityImpls<'a> {
|
impl<'a> Malformed for AbilityImpls<'a> {
|
||||||
fn is_malformed(&self) -> bool {
|
fn is_malformed(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::ast::CommentOrNewline;
|
use crate::ast::CommentOrNewline;
|
||||||
use crate::ast::Spaceable;
|
use crate::ast::Spaceable;
|
||||||
|
use crate::ast::SpacesBefore;
|
||||||
use crate::parser::succeed;
|
use crate::parser::succeed;
|
||||||
use crate::parser::Progress;
|
use crate::parser::Progress;
|
||||||
use crate::parser::SpaceProblem;
|
use crate::parser::SpaceProblem;
|
||||||
|
@ -175,6 +176,24 @@ where
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn plain_spaces_before<'a, P, S, E>(
|
||||||
|
parser: P,
|
||||||
|
indent_problem: fn(Position) -> E,
|
||||||
|
) -> impl Parser<'a, SpacesBefore<'a, S>, E>
|
||||||
|
where
|
||||||
|
S: 'a,
|
||||||
|
P: 'a + Parser<'a, S, E>,
|
||||||
|
E: 'a + SpaceProblem,
|
||||||
|
{
|
||||||
|
parser::map(
|
||||||
|
and(backtrackable(space0_e(indent_problem)), parser),
|
||||||
|
|(space_list, item): (&'a [CommentOrNewline<'a>], S)| SpacesBefore {
|
||||||
|
before: space_list,
|
||||||
|
item,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn space0_after_e<'a, P, S, E>(
|
pub fn space0_after_e<'a, P, S, E>(
|
||||||
parser: P,
|
parser: P,
|
||||||
indent_problem: fn(Position) -> E,
|
indent_problem: fn(Position) -> E,
|
||||||
|
|
|
@ -1170,20 +1170,14 @@ fn alias_signature<'a>() -> impl Parser<'a, Loc<TypeAnnotation<'a>>, EExpr<'a>>
|
||||||
increment_min_indent(specialize_err(EExpr::Type, type_annotation::located(false)))
|
increment_min_indent(specialize_err(EExpr::Type, type_annotation::located(false)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opaque_signature<'a>() -> impl Parser<
|
fn opaque_signature<'a>(
|
||||||
'a,
|
) -> impl Parser<'a, (Loc<TypeAnnotation<'a>>, Option<&'a ImplementsAbilities<'a>>), EExpr<'a>> {
|
||||||
(
|
|
||||||
Loc<TypeAnnotation<'a>>,
|
|
||||||
Option<Loc<ImplementsAbilities<'a>>>,
|
|
||||||
),
|
|
||||||
EExpr<'a>,
|
|
||||||
> {
|
|
||||||
and(
|
and(
|
||||||
specialize_err(EExpr::Type, type_annotation::located_opaque_signature(true)),
|
specialize_err(EExpr::Type, type_annotation::located_opaque_signature(true)),
|
||||||
optional(backtrackable(specialize_err(
|
optional(map_with_arena(
|
||||||
EExpr::Type,
|
specialize_err(EExpr::Type, type_annotation::implements_abilities()),
|
||||||
space0_before_e(type_annotation::implements_abilities(), EType::TIndentStart),
|
|arena, item| &*arena.alloc(item),
|
||||||
))),
|
)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,14 +3,14 @@ use bumpalo::Bump;
|
||||||
use roc_module::called_via::{BinOp, UnaryOp};
|
use roc_module::called_via::{BinOp, UnaryOp};
|
||||||
use roc_region::all::{Loc, Position, Region};
|
use roc_region::all::{Loc, Position, Region};
|
||||||
|
|
||||||
|
use crate::ast::ImplementsAbilities;
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
AbilityImpls, AbilityMember, AssignedField, Collection, Defs, Expr, FullAst, Header,
|
AbilityImpls, AbilityMember, AssignedField, Collection, Defs, Expr, FullAst, Header,
|
||||||
Implements, ImplementsAbilities, ImplementsAbility, ImplementsClause, ImportAlias,
|
Implements, ImplementsAbility, ImplementsClause, ImportAlias, ImportAsKeyword,
|
||||||
ImportAsKeyword, ImportExposingKeyword, ImportedModuleName, IngestedFileAnnotation,
|
ImportExposingKeyword, ImportedModuleName, IngestedFileAnnotation, IngestedFileImport,
|
||||||
IngestedFileImport, ModuleImport, ModuleImportParams, Pattern, PatternAs, Spaced, Spaces,
|
ModuleImport, ModuleImportParams, Pattern, PatternAs, Spaced, Spaces, SpacesBefore,
|
||||||
SpacesBefore, StrLiteral, StrSegment, Tag, TypeAnnotation, TypeDef, TypeHeader, ValueDef,
|
StrLiteral, StrSegment, Tag, TypeAnnotation, TypeDef, TypeHeader, ValueDef, WhenBranch,
|
||||||
WhenBranch,
|
|
||||||
},
|
},
|
||||||
header::{
|
header::{
|
||||||
AppHeader, ExposedName, ExposesKeyword, HostedHeader, ImportsEntry, ImportsKeyword,
|
AppHeader, ExposedName, ExposesKeyword, HostedHeader, ImportsEntry, ImportsKeyword,
|
||||||
|
@ -372,7 +372,7 @@ impl<'a> Normalize<'a> for TypeDef<'a> {
|
||||||
vars: vars.normalize(arena),
|
vars: vars.normalize(arena),
|
||||||
},
|
},
|
||||||
typ: typ.normalize(arena),
|
typ: typ.normalize(arena),
|
||||||
derived: derived.normalize(arena),
|
derived: derived.map(|item| &*arena.alloc(item.normalize(arena))),
|
||||||
},
|
},
|
||||||
Ability {
|
Ability {
|
||||||
header: TypeHeader { name, vars },
|
header: TypeHeader { name, vars },
|
||||||
|
@ -1001,6 +1001,17 @@ impl<'a> Normalize<'a> for AbilityImpls<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Normalize<'a> for ImplementsAbilities<'a> {
|
||||||
|
fn normalize(&self, arena: &'a Bump) -> Self {
|
||||||
|
ImplementsAbilities {
|
||||||
|
before_implements_kw: &[],
|
||||||
|
implements: Region::zero(),
|
||||||
|
after_implements_kw: &[],
|
||||||
|
item: self.item.normalize(arena),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Normalize<'a> for ImplementsAbility<'a> {
|
impl<'a> Normalize<'a> for ImplementsAbility<'a> {
|
||||||
fn normalize(&self, arena: &'a Bump) -> Self {
|
fn normalize(&self, arena: &'a Bump) -> Self {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -1017,18 +1028,6 @@ impl<'a> Normalize<'a> for ImplementsAbility<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Normalize<'a> for ImplementsAbilities<'a> {
|
|
||||||
fn normalize(&self, arena: &'a Bump) -> Self {
|
|
||||||
match *self {
|
|
||||||
ImplementsAbilities::Implements(derived) => {
|
|
||||||
ImplementsAbilities::Implements(derived.normalize(arena))
|
|
||||||
}
|
|
||||||
ImplementsAbilities::SpaceBefore(derived, _)
|
|
||||||
| ImplementsAbilities::SpaceAfter(derived, _) => derived.normalize(arena),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Normalize<'a> for PatternAs<'a> {
|
impl<'a> Normalize<'a> for PatternAs<'a> {
|
||||||
fn normalize(&self, arena: &'a Bump) -> Self {
|
fn normalize(&self, arena: &'a Bump) -> Self {
|
||||||
PatternAs {
|
PatternAs {
|
||||||
|
|
|
@ -4,8 +4,8 @@ use crate::ast::{
|
||||||
TypeAnnotation, TypeHeader,
|
TypeAnnotation, TypeHeader,
|
||||||
};
|
};
|
||||||
use crate::blankspace::{
|
use crate::blankspace::{
|
||||||
self, space0_around_ee, space0_before_e, space0_before_optional_after, space0_e,
|
self, plain_spaces_before, space0_around_ee, space0_before_e, space0_before_optional_after,
|
||||||
spaces_before_optional_after,
|
space0_e, spaces_before_optional_after,
|
||||||
};
|
};
|
||||||
use crate::expr::record_field;
|
use crate::expr::record_field;
|
||||||
use crate::ident::{lowercase_ident, lowercase_ident_keyword_e};
|
use crate::ident::{lowercase_ident, lowercase_ident_keyword_e};
|
||||||
|
@ -787,25 +787,39 @@ fn parse_implements_clause_chain_after_where<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a implements-abilities clause, e.g. `implements [Eq, Hash]`.
|
/// Parse a implements-abilities clause, e.g. `implements [Eq, Hash]`.
|
||||||
pub fn implements_abilities<'a>() -> impl Parser<'a, Loc<ImplementsAbilities<'a>>, EType<'a>> {
|
pub fn implements_abilities<'a>() -> impl Parser<'a, ImplementsAbilities<'a>, EType<'a>> {
|
||||||
increment_min_indent(skip_first(
|
map(
|
||||||
// Parse "implements"; we don't care about this keyword
|
plain_spaces_before(
|
||||||
crate::parser::keyword(crate::keyword::IMPLEMENTS, EType::TImplementsClause),
|
increment_min_indent(and(
|
||||||
// Parse "Hash"; this may be qualified from another module like "Hash.Hash"
|
// Parse "implements"; we don't care about this keyword
|
||||||
space0_before_e(
|
map(
|
||||||
loc(map(
|
loc(crate::parser::keyword(
|
||||||
collection_trailing_sep_e(
|
crate::keyword::IMPLEMENTS,
|
||||||
byte(b'[', EType::TStart),
|
EType::TImplementsClause,
|
||||||
loc(parse_implements_ability()),
|
)),
|
||||||
byte(b',', EType::TEnd),
|
|item| item.region,
|
||||||
byte(b']', EType::TEnd),
|
),
|
||||||
ImplementsAbility::SpaceBefore,
|
// Parse "Hash"; this may be qualified from another module like "Hash.Hash"
|
||||||
|
plain_spaces_before(
|
||||||
|
loc(collection_trailing_sep_e(
|
||||||
|
byte(b'[', EType::TStart),
|
||||||
|
loc(parse_implements_ability()),
|
||||||
|
byte(b',', EType::TEnd),
|
||||||
|
byte(b']', EType::TEnd),
|
||||||
|
ImplementsAbility::SpaceBefore,
|
||||||
|
)),
|
||||||
|
EType::TIndentEnd,
|
||||||
),
|
),
|
||||||
ImplementsAbilities::Implements,
|
|
||||||
)),
|
)),
|
||||||
EType::TIndentEnd,
|
EType::TIndentStart,
|
||||||
),
|
),
|
||||||
))
|
|item| ImplementsAbilities {
|
||||||
|
before_implements_kw: item.before,
|
||||||
|
implements: item.item.0,
|
||||||
|
after_implements_kw: item.item.1.before,
|
||||||
|
item: item.item.1.item,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_implements_ability<'a>() -> impl Parser<'a, ImplementsAbility<'a>, EType<'a>> {
|
fn parse_implements_ability<'a>() -> impl Parser<'a, ImplementsAbility<'a>, EType<'a>> {
|
||||||
|
|
|
@ -165,7 +165,7 @@ mod solve_expr {
|
||||||
Str.from_utf8
|
Str.from_utf8
|
||||||
"
|
"
|
||||||
),
|
),
|
||||||
"List U8 -> Result Str [BadUtf8 Utf8ByteProblem U64]",
|
"List U8 -> Result Str [BadUtf8 { index : U64, problem : Utf8ByteProblem }]",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -692,7 +692,7 @@ fn str_from_utf8_fail_invalid_start_byte() {
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.from_utf8 [97, 98, 0x80, 99] is
|
when Str.from_utf8 [97, 98, 0x80, 99] is
|
||||||
Err (BadUtf8 InvalidStartByte byte_index) ->
|
Err (BadUtf8 {problem: InvalidStartByte, index: byte_index}) ->
|
||||||
if byte_index == 2 then
|
if byte_index == 2 then
|
||||||
"a"
|
"a"
|
||||||
else
|
else
|
||||||
|
@ -712,7 +712,7 @@ fn str_from_utf8_fail_unexpected_end_of_sequence() {
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.from_utf8 [97, 98, 99, 0xC2] is
|
when Str.from_utf8 [97, 98, 99, 0xC2] is
|
||||||
Err (BadUtf8 UnexpectedEndOfSequence byte_index) ->
|
Err (BadUtf8 {problem: UnexpectedEndOfSequence, index: byte_index}) ->
|
||||||
if byte_index == 3 then
|
if byte_index == 3 then
|
||||||
"a"
|
"a"
|
||||||
else
|
else
|
||||||
|
@ -732,7 +732,7 @@ fn str_from_utf8_fail_expected_continuation() {
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.from_utf8 [97, 98, 99, 0xC2, 0x00] is
|
when Str.from_utf8 [97, 98, 99, 0xC2, 0x00] is
|
||||||
Err (BadUtf8 ExpectedContinuation byte_index) ->
|
Err (BadUtf8 {problem: ExpectedContinuation, index: byte_index}) ->
|
||||||
if byte_index == 3 then
|
if byte_index == 3 then
|
||||||
"a"
|
"a"
|
||||||
else
|
else
|
||||||
|
@ -752,7 +752,7 @@ fn str_from_utf8_fail_overlong_encoding() {
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.from_utf8 [97, 0xF0, 0x80, 0x80, 0x80] is
|
when Str.from_utf8 [97, 0xF0, 0x80, 0x80, 0x80] is
|
||||||
Err (BadUtf8 OverlongEncoding byte_index) ->
|
Err (BadUtf8 {problem: OverlongEncoding, index: byte_index}) ->
|
||||||
if byte_index == 1 then
|
if byte_index == 1 then
|
||||||
"a"
|
"a"
|
||||||
else
|
else
|
||||||
|
@ -772,7 +772,7 @@ fn str_from_utf8_fail_codepoint_too_large() {
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.from_utf8 [97, 0xF4, 0x90, 0x80, 0x80] is
|
when Str.from_utf8 [97, 0xF4, 0x90, 0x80, 0x80] is
|
||||||
Err (BadUtf8 CodepointTooLarge byte_index) ->
|
Err (BadUtf8 {problem: CodepointTooLarge, index: byte_index}) ->
|
||||||
if byte_index == 1 then
|
if byte_index == 1 then
|
||||||
"a"
|
"a"
|
||||||
else
|
else
|
||||||
|
@ -792,7 +792,7 @@ fn str_from_utf8_fail_surrogate_half() {
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.from_utf8 [97, 98, 0xED, 0xA0, 0x80] is
|
when Str.from_utf8 [97, 98, 0xED, 0xA0, 0x80] is
|
||||||
Err (BadUtf8 EncodesSurrogateHalf byte_index) ->
|
Err (BadUtf8 {problem: EncodesSurrogateHalf, index: byte_index}) ->
|
||||||
if byte_index == 2 then
|
if byte_index == 2 then
|
||||||
"a"
|
"a"
|
||||||
else
|
else
|
||||||
|
|
|
@ -522,7 +522,7 @@ fn str_from_utf8_fail_invalid_start_byte() {
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.from_utf8 [97, 98, 0x80, 99] is
|
when Str.from_utf8 [97, 98, 0x80, 99] is
|
||||||
Err (BadUtf8 InvalidStartByte byte_index) ->
|
Err (BadUtf8 {problem: InvalidStartByte, index: byte_index}) ->
|
||||||
if byte_index == 2 then
|
if byte_index == 2 then
|
||||||
"a"
|
"a"
|
||||||
else
|
else
|
||||||
|
@ -541,7 +541,7 @@ fn str_from_utf8_fail_unexpected_end_of_sequence() {
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.from_utf8 [97, 98, 99, 0xC2] is
|
when Str.from_utf8 [97, 98, 99, 0xC2] is
|
||||||
Err (BadUtf8 UnexpectedEndOfSequence byte_index) ->
|
Err (BadUtf8 {problem: UnexpectedEndOfSequence, index: byte_index}) ->
|
||||||
if byte_index == 3 then
|
if byte_index == 3 then
|
||||||
"a"
|
"a"
|
||||||
else
|
else
|
||||||
|
@ -560,7 +560,7 @@ fn str_from_utf8_fail_expected_continuation() {
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.from_utf8 [97, 98, 99, 0xC2, 0x00] is
|
when Str.from_utf8 [97, 98, 99, 0xC2, 0x00] is
|
||||||
Err (BadUtf8 ExpectedContinuation byte_index) ->
|
Err (BadUtf8 {problem: ExpectedContinuation, index: byte_index}) ->
|
||||||
if byte_index == 3 then
|
if byte_index == 3 then
|
||||||
"a"
|
"a"
|
||||||
else
|
else
|
||||||
|
@ -579,7 +579,7 @@ fn str_from_utf8_fail_overlong_encoding() {
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.from_utf8 [97, 0xF0, 0x80, 0x80, 0x80] is
|
when Str.from_utf8 [97, 0xF0, 0x80, 0x80, 0x80] is
|
||||||
Err (BadUtf8 OverlongEncoding byte_index) ->
|
Err (BadUtf8 {problem: OverlongEncoding, index: byte_index}) ->
|
||||||
if byte_index == 1 then
|
if byte_index == 1 then
|
||||||
"a"
|
"a"
|
||||||
else
|
else
|
||||||
|
@ -598,7 +598,7 @@ fn str_from_utf8_fail_codepoint_too_large() {
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.from_utf8 [97, 0xF4, 0x90, 0x80, 0x80] is
|
when Str.from_utf8 [97, 0xF4, 0x90, 0x80, 0x80] is
|
||||||
Err (BadUtf8 CodepointTooLarge byte_index) ->
|
Err (BadUtf8 {problem: CodepointTooLarge, index: byte_index}) ->
|
||||||
if byte_index == 1 then
|
if byte_index == 1 then
|
||||||
"a"
|
"a"
|
||||||
else
|
else
|
||||||
|
@ -617,7 +617,7 @@ fn str_from_utf8_fail_surrogate_half() {
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.from_utf8 [97, 98, 0xED, 0xA0, 0x80] is
|
when Str.from_utf8 [97, 98, 0xED, 0xA0, 0x80] is
|
||||||
Err (BadUtf8 EncodesSurrogateHalf byte_index) ->
|
Err (BadUtf8 {problem: EncodesSurrogateHalf, index: byte_index}) ->
|
||||||
if byte_index == 2 then
|
if byte_index == 2 then
|
||||||
"a"
|
"a"
|
||||||
else
|
else
|
||||||
|
|
|
@ -164,31 +164,31 @@ procedure Num.96 (#Attr.2):
|
||||||
ret Num.287;
|
ret Num.287;
|
||||||
|
|
||||||
procedure Str.12 (#Attr.2):
|
procedure Str.12 (#Attr.2):
|
||||||
let Str.258 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
let Str.259 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||||
ret Str.258;
|
|
||||||
|
|
||||||
procedure Str.36 (#Attr.2):
|
|
||||||
let Str.259 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
|
||||||
ret Str.259;
|
ret Str.259;
|
||||||
|
|
||||||
|
procedure Str.36 (#Attr.2):
|
||||||
|
let Str.260 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||||
|
ret Str.260;
|
||||||
|
|
||||||
procedure Str.43 (#Attr.2):
|
procedure Str.43 (#Attr.2):
|
||||||
let Str.253 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
let Str.254 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||||
ret Str.253;
|
ret Str.254;
|
||||||
|
|
||||||
procedure Str.9 (Str.73):
|
procedure Str.9 (Str.73):
|
||||||
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
||||||
let Str.250 : Int1 = StructAtIndex 2 Str.74;
|
let Str.251 : Int1 = StructAtIndex 2 Str.74;
|
||||||
if Str.250 then
|
if Str.251 then
|
||||||
let Str.252 : Str = StructAtIndex 1 Str.74;
|
let Str.253 : Str = StructAtIndex 1 Str.74;
|
||||||
let Str.251 : [C {U64, U8}, C Str] = TagId(1) Str.252;
|
let Str.252 : [C {U64, U8}, C Str] = TagId(1) Str.253;
|
||||||
ret Str.251;
|
ret Str.252;
|
||||||
else
|
else
|
||||||
let Str.248 : U8 = StructAtIndex 3 Str.74;
|
|
||||||
let Str.249 : U64 = StructAtIndex 0 Str.74;
|
let Str.249 : U64 = StructAtIndex 0 Str.74;
|
||||||
|
let Str.250 : U8 = StructAtIndex 3 Str.74;
|
||||||
let #Derived_gen.45 : Str = StructAtIndex 1 Str.74;
|
let #Derived_gen.45 : Str = StructAtIndex 1 Str.74;
|
||||||
dec #Derived_gen.45;
|
dec #Derived_gen.45;
|
||||||
let Str.247 : {U64, U8} = Struct {Str.249, Str.248};
|
let Str.248 : {U64, U8} = Struct {Str.249, Str.250};
|
||||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.247;
|
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.248;
|
||||||
ret Str.246;
|
ret Str.246;
|
||||||
|
|
||||||
procedure Test.20 (Test.56):
|
procedure Test.20 (Test.56):
|
||||||
|
|
|
@ -105,31 +105,31 @@ procedure Num.96 (#Attr.2):
|
||||||
ret Num.283;
|
ret Num.283;
|
||||||
|
|
||||||
procedure Str.12 (#Attr.2):
|
procedure Str.12 (#Attr.2):
|
||||||
let Str.255 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
let Str.256 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||||
ret Str.255;
|
|
||||||
|
|
||||||
procedure Str.36 (#Attr.2):
|
|
||||||
let Str.256 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
|
||||||
ret Str.256;
|
ret Str.256;
|
||||||
|
|
||||||
|
procedure Str.36 (#Attr.2):
|
||||||
|
let Str.257 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||||
|
ret Str.257;
|
||||||
|
|
||||||
procedure Str.43 (#Attr.2):
|
procedure Str.43 (#Attr.2):
|
||||||
let Str.253 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
let Str.254 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||||
ret Str.253;
|
ret Str.254;
|
||||||
|
|
||||||
procedure Str.9 (Str.73):
|
procedure Str.9 (Str.73):
|
||||||
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
||||||
let Str.250 : Int1 = StructAtIndex 2 Str.74;
|
let Str.251 : Int1 = StructAtIndex 2 Str.74;
|
||||||
if Str.250 then
|
if Str.251 then
|
||||||
let Str.252 : Str = StructAtIndex 1 Str.74;
|
let Str.253 : Str = StructAtIndex 1 Str.74;
|
||||||
let Str.251 : [C {U64, U8}, C Str] = TagId(1) Str.252;
|
let Str.252 : [C {U64, U8}, C Str] = TagId(1) Str.253;
|
||||||
ret Str.251;
|
ret Str.252;
|
||||||
else
|
else
|
||||||
let Str.248 : U8 = StructAtIndex 3 Str.74;
|
|
||||||
let Str.249 : U64 = StructAtIndex 0 Str.74;
|
let Str.249 : U64 = StructAtIndex 0 Str.74;
|
||||||
|
let Str.250 : U8 = StructAtIndex 3 Str.74;
|
||||||
let #Derived_gen.24 : Str = StructAtIndex 1 Str.74;
|
let #Derived_gen.24 : Str = StructAtIndex 1 Str.74;
|
||||||
dec #Derived_gen.24;
|
dec #Derived_gen.24;
|
||||||
let Str.247 : {U64, U8} = Struct {Str.249, Str.248};
|
let Str.248 : {U64, U8} = Struct {Str.249, Str.250};
|
||||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.247;
|
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.248;
|
||||||
ret Str.246;
|
ret Str.246;
|
||||||
|
|
||||||
procedure Test.20 (Test.56):
|
procedure Test.20 (Test.56):
|
||||||
|
|
|
@ -112,31 +112,31 @@ procedure Num.96 (#Attr.2):
|
||||||
ret Num.283;
|
ret Num.283;
|
||||||
|
|
||||||
procedure Str.12 (#Attr.2):
|
procedure Str.12 (#Attr.2):
|
||||||
let Str.255 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
let Str.256 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||||
ret Str.255;
|
|
||||||
|
|
||||||
procedure Str.36 (#Attr.2):
|
|
||||||
let Str.256 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
|
||||||
ret Str.256;
|
ret Str.256;
|
||||||
|
|
||||||
|
procedure Str.36 (#Attr.2):
|
||||||
|
let Str.257 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||||
|
ret Str.257;
|
||||||
|
|
||||||
procedure Str.43 (#Attr.2):
|
procedure Str.43 (#Attr.2):
|
||||||
let Str.253 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
let Str.254 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||||
ret Str.253;
|
ret Str.254;
|
||||||
|
|
||||||
procedure Str.9 (Str.73):
|
procedure Str.9 (Str.73):
|
||||||
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
||||||
let Str.250 : Int1 = StructAtIndex 2 Str.74;
|
let Str.251 : Int1 = StructAtIndex 2 Str.74;
|
||||||
if Str.250 then
|
if Str.251 then
|
||||||
let Str.252 : Str = StructAtIndex 1 Str.74;
|
let Str.253 : Str = StructAtIndex 1 Str.74;
|
||||||
let Str.251 : [C {U64, U8}, C Str] = TagId(1) Str.252;
|
let Str.252 : [C {U64, U8}, C Str] = TagId(1) Str.253;
|
||||||
ret Str.251;
|
ret Str.252;
|
||||||
else
|
else
|
||||||
let Str.248 : U8 = StructAtIndex 3 Str.74;
|
|
||||||
let Str.249 : U64 = StructAtIndex 0 Str.74;
|
let Str.249 : U64 = StructAtIndex 0 Str.74;
|
||||||
|
let Str.250 : U8 = StructAtIndex 3 Str.74;
|
||||||
let #Derived_gen.28 : Str = StructAtIndex 1 Str.74;
|
let #Derived_gen.28 : Str = StructAtIndex 1 Str.74;
|
||||||
dec #Derived_gen.28;
|
dec #Derived_gen.28;
|
||||||
let Str.247 : {U64, U8} = Struct {Str.249, Str.248};
|
let Str.248 : {U64, U8} = Struct {Str.249, Str.250};
|
||||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.247;
|
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.248;
|
||||||
ret Str.246;
|
ret Str.246;
|
||||||
|
|
||||||
procedure Test.20 (Test.56):
|
procedure Test.20 (Test.56):
|
||||||
|
|
|
@ -38,31 +38,31 @@ procedure Num.96 (#Attr.2):
|
||||||
ret Num.283;
|
ret Num.283;
|
||||||
|
|
||||||
procedure Str.12 (#Attr.2):
|
procedure Str.12 (#Attr.2):
|
||||||
let Str.255 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
let Str.256 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||||
ret Str.255;
|
|
||||||
|
|
||||||
procedure Str.36 (#Attr.2):
|
|
||||||
let Str.256 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
|
||||||
ret Str.256;
|
ret Str.256;
|
||||||
|
|
||||||
|
procedure Str.36 (#Attr.2):
|
||||||
|
let Str.257 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||||
|
ret Str.257;
|
||||||
|
|
||||||
procedure Str.43 (#Attr.2):
|
procedure Str.43 (#Attr.2):
|
||||||
let Str.253 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
let Str.254 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||||
ret Str.253;
|
ret Str.254;
|
||||||
|
|
||||||
procedure Str.9 (Str.73):
|
procedure Str.9 (Str.73):
|
||||||
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
||||||
let Str.250 : Int1 = StructAtIndex 2 Str.74;
|
let Str.251 : Int1 = StructAtIndex 2 Str.74;
|
||||||
if Str.250 then
|
if Str.251 then
|
||||||
let Str.252 : Str = StructAtIndex 1 Str.74;
|
let Str.253 : Str = StructAtIndex 1 Str.74;
|
||||||
let Str.251 : [C {U64, U8}, C Str] = TagId(1) Str.252;
|
let Str.252 : [C {U64, U8}, C Str] = TagId(1) Str.253;
|
||||||
ret Str.251;
|
ret Str.252;
|
||||||
else
|
else
|
||||||
let Str.248 : U8 = StructAtIndex 3 Str.74;
|
|
||||||
let Str.249 : U64 = StructAtIndex 0 Str.74;
|
let Str.249 : U64 = StructAtIndex 0 Str.74;
|
||||||
|
let Str.250 : U8 = StructAtIndex 3 Str.74;
|
||||||
let #Derived_gen.3 : Str = StructAtIndex 1 Str.74;
|
let #Derived_gen.3 : Str = StructAtIndex 1 Str.74;
|
||||||
dec #Derived_gen.3;
|
dec #Derived_gen.3;
|
||||||
let Str.247 : {U64, U8} = Struct {Str.249, Str.248};
|
let Str.248 : {U64, U8} = Struct {Str.249, Str.250};
|
||||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.247;
|
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.248;
|
||||||
ret Str.246;
|
ret Str.246;
|
||||||
|
|
||||||
procedure Test.20 (Test.56):
|
procedure Test.20 (Test.56):
|
||||||
|
|
|
@ -110,31 +110,31 @@ procedure Num.96 (#Attr.2):
|
||||||
ret Num.283;
|
ret Num.283;
|
||||||
|
|
||||||
procedure Str.12 (#Attr.2):
|
procedure Str.12 (#Attr.2):
|
||||||
let Str.255 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
let Str.256 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||||
ret Str.255;
|
|
||||||
|
|
||||||
procedure Str.36 (#Attr.2):
|
|
||||||
let Str.256 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
|
||||||
ret Str.256;
|
ret Str.256;
|
||||||
|
|
||||||
|
procedure Str.36 (#Attr.2):
|
||||||
|
let Str.257 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||||
|
ret Str.257;
|
||||||
|
|
||||||
procedure Str.43 (#Attr.2):
|
procedure Str.43 (#Attr.2):
|
||||||
let Str.253 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
let Str.254 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||||
ret Str.253;
|
ret Str.254;
|
||||||
|
|
||||||
procedure Str.9 (Str.73):
|
procedure Str.9 (Str.73):
|
||||||
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
||||||
let Str.250 : Int1 = StructAtIndex 2 Str.74;
|
let Str.251 : Int1 = StructAtIndex 2 Str.74;
|
||||||
if Str.250 then
|
if Str.251 then
|
||||||
let Str.252 : Str = StructAtIndex 1 Str.74;
|
let Str.253 : Str = StructAtIndex 1 Str.74;
|
||||||
let Str.251 : [C {U64, U8}, C Str] = TagId(1) Str.252;
|
let Str.252 : [C {U64, U8}, C Str] = TagId(1) Str.253;
|
||||||
ret Str.251;
|
ret Str.252;
|
||||||
else
|
else
|
||||||
let Str.248 : U8 = StructAtIndex 3 Str.74;
|
|
||||||
let Str.249 : U64 = StructAtIndex 0 Str.74;
|
let Str.249 : U64 = StructAtIndex 0 Str.74;
|
||||||
|
let Str.250 : U8 = StructAtIndex 3 Str.74;
|
||||||
let #Derived_gen.27 : Str = StructAtIndex 1 Str.74;
|
let #Derived_gen.27 : Str = StructAtIndex 1 Str.74;
|
||||||
dec #Derived_gen.27;
|
dec #Derived_gen.27;
|
||||||
let Str.247 : {U64, U8} = Struct {Str.249, Str.248};
|
let Str.248 : {U64, U8} = Struct {Str.249, Str.250};
|
||||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.247;
|
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.248;
|
||||||
ret Str.246;
|
ret Str.246;
|
||||||
|
|
||||||
procedure Test.20 (Test.56):
|
procedure Test.20 (Test.56):
|
||||||
|
|
|
@ -113,31 +113,31 @@ procedure Num.96 (#Attr.2):
|
||||||
ret Num.283;
|
ret Num.283;
|
||||||
|
|
||||||
procedure Str.12 (#Attr.2):
|
procedure Str.12 (#Attr.2):
|
||||||
let Str.255 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
let Str.256 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||||
ret Str.255;
|
|
||||||
|
|
||||||
procedure Str.36 (#Attr.2):
|
|
||||||
let Str.256 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
|
||||||
ret Str.256;
|
ret Str.256;
|
||||||
|
|
||||||
|
procedure Str.36 (#Attr.2):
|
||||||
|
let Str.257 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||||
|
ret Str.257;
|
||||||
|
|
||||||
procedure Str.43 (#Attr.2):
|
procedure Str.43 (#Attr.2):
|
||||||
let Str.253 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
let Str.254 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||||
ret Str.253;
|
ret Str.254;
|
||||||
|
|
||||||
procedure Str.9 (Str.73):
|
procedure Str.9 (Str.73):
|
||||||
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
||||||
let Str.250 : Int1 = StructAtIndex 2 Str.74;
|
let Str.251 : Int1 = StructAtIndex 2 Str.74;
|
||||||
if Str.250 then
|
if Str.251 then
|
||||||
let Str.252 : Str = StructAtIndex 1 Str.74;
|
let Str.253 : Str = StructAtIndex 1 Str.74;
|
||||||
let Str.251 : [C {U64, U8}, C Str] = TagId(1) Str.252;
|
let Str.252 : [C {U64, U8}, C Str] = TagId(1) Str.253;
|
||||||
ret Str.251;
|
ret Str.252;
|
||||||
else
|
else
|
||||||
let Str.248 : U8 = StructAtIndex 3 Str.74;
|
|
||||||
let Str.249 : U64 = StructAtIndex 0 Str.74;
|
let Str.249 : U64 = StructAtIndex 0 Str.74;
|
||||||
|
let Str.250 : U8 = StructAtIndex 3 Str.74;
|
||||||
let #Derived_gen.28 : Str = StructAtIndex 1 Str.74;
|
let #Derived_gen.28 : Str = StructAtIndex 1 Str.74;
|
||||||
dec #Derived_gen.28;
|
dec #Derived_gen.28;
|
||||||
let Str.247 : {U64, U8} = Struct {Str.249, Str.248};
|
let Str.248 : {U64, U8} = Struct {Str.249, Str.250};
|
||||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.247;
|
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.248;
|
||||||
ret Str.246;
|
ret Str.246;
|
||||||
|
|
||||||
procedure Test.20 (Test.56):
|
procedure Test.20 (Test.56):
|
||||||
|
|
38
crates/compiler/test_syntax/src/bin/dump_syntax.rs
Normal file
38
crates/compiler/test_syntax/src/bin/dump_syntax.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
//! Dump a syntax tree for a given input file.
|
||||||
|
//!
|
||||||
|
//! Typical usage:
|
||||||
|
//! `cargo run --bin dump_syntax -- full file.roc`
|
||||||
|
|
||||||
|
use std::process::exit;
|
||||||
|
|
||||||
|
use bumpalo::Bump;
|
||||||
|
use test_syntax::test_helpers::InputKind;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args = std::env::args().collect::<Vec<String>>();
|
||||||
|
if args.len() != 3 {
|
||||||
|
eprintln!("Usage: {} [expr|full|moduledefs|header] <input>", args[0]);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let kind = match args[1].as_str() {
|
||||||
|
"expr" => InputKind::Expr,
|
||||||
|
"full" => InputKind::Full,
|
||||||
|
"moduledefs" => InputKind::ModuleDefs,
|
||||||
|
"header" => InputKind::Header,
|
||||||
|
_ => {
|
||||||
|
eprintln!("Invalid input kind: {}", args[1]);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let text = std::fs::read_to_string(&args[2]).unwrap_or_else(|e| {
|
||||||
|
eprintln!("Error reading file: {}", e);
|
||||||
|
exit(1);
|
||||||
|
});
|
||||||
|
let input = kind.with_text(&text);
|
||||||
|
let arena = Bump::new();
|
||||||
|
let output = input.parse_in(&arena);
|
||||||
|
eprintln!("memory used: {}", arena.allocated_bytes());
|
||||||
|
println!("{:#?}", output);
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
x :
|
||||||
|
(a where e
|
||||||
|
implements K)
|
||||||
|
-> Z
|
||||||
|
s
|
|
@ -0,0 +1,81 @@
|
||||||
|
@0-31 SpaceAfter(
|
||||||
|
Defs(
|
||||||
|
Defs {
|
||||||
|
tags: [
|
||||||
|
EitherIndex(2147483648),
|
||||||
|
],
|
||||||
|
regions: [
|
||||||
|
@0-29,
|
||||||
|
],
|
||||||
|
space_before: [
|
||||||
|
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||||
|
],
|
||||||
|
space_after: [
|
||||||
|
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||||
|
],
|
||||||
|
spaces: [],
|
||||||
|
type_defs: [],
|
||||||
|
value_defs: [
|
||||||
|
Annotation(
|
||||||
|
@0-1 Identifier {
|
||||||
|
ident: "x",
|
||||||
|
},
|
||||||
|
@3-28 Function(
|
||||||
|
[
|
||||||
|
@3-25 Where(
|
||||||
|
@3-4 SpaceAfter(
|
||||||
|
BoundVariable(
|
||||||
|
"a",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[
|
||||||
|
@11-25 ImplementsClause {
|
||||||
|
var: @11-12 SpaceBefore(
|
||||||
|
SpaceAfter(
|
||||||
|
"e",
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
abilities: [
|
||||||
|
@24-25 Apply(
|
||||||
|
"",
|
||||||
|
"K",
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Pure,
|
||||||
|
@27-28 Apply(
|
||||||
|
"",
|
||||||
|
"Z",
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
@30-31 SpaceBefore(
|
||||||
|
Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "s",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,5 @@
|
||||||
|
x:(a
|
||||||
|
where
|
||||||
|
e
|
||||||
|
implements K->Z)
|
||||||
|
s
|
|
@ -24,16 +24,16 @@
|
||||||
"p",
|
"p",
|
||||||
),
|
),
|
||||||
derived: Some(
|
derived: Some(
|
||||||
@18-20 SpaceBefore(
|
ImplementsAbilities {
|
||||||
Implements(
|
before_implements_kw: [
|
||||||
[],
|
|
||||||
),
|
|
||||||
[
|
|
||||||
LineComment(
|
LineComment(
|
||||||
"",
|
"",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
implements: @8-18,
|
||||||
|
after_implements_kw: [],
|
||||||
|
item: @18-20 [],
|
||||||
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
P := W
|
||||||
|
implements []
|
||||||
|
t
|
|
@ -0,0 +1,57 @@
|
||||||
|
@0-25 SpaceAfter(
|
||||||
|
Defs(
|
||||||
|
Defs {
|
||||||
|
tags: [
|
||||||
|
EitherIndex(0),
|
||||||
|
],
|
||||||
|
regions: [
|
||||||
|
@0-23,
|
||||||
|
],
|
||||||
|
space_before: [
|
||||||
|
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||||
|
],
|
||||||
|
space_after: [
|
||||||
|
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||||
|
],
|
||||||
|
spaces: [],
|
||||||
|
type_defs: [
|
||||||
|
Opaque {
|
||||||
|
header: TypeHeader {
|
||||||
|
name: @0-1 "P",
|
||||||
|
vars: [],
|
||||||
|
},
|
||||||
|
typ: @3-4 Apply(
|
||||||
|
"",
|
||||||
|
"W",
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
derived: Some(
|
||||||
|
ImplementsAbilities {
|
||||||
|
before_implements_kw: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
implements: @7-17,
|
||||||
|
after_implements_kw: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: @21-23 [],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
value_defs: [],
|
||||||
|
},
|
||||||
|
@24-25 SpaceBefore(
|
||||||
|
Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "t",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,4 @@
|
||||||
|
P:=W
|
||||||
|
implements
|
||||||
|
[]
|
||||||
|
t
|
|
@ -81,8 +81,11 @@
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
derived: Some(
|
derived: Some(
|
||||||
@19-29 Implements(
|
ImplementsAbilities {
|
||||||
[
|
before_implements_kw: [],
|
||||||
|
implements: @8-18,
|
||||||
|
after_implements_kw: [],
|
||||||
|
item: @19-29 [
|
||||||
@20-22 ImplementsAbility {
|
@20-22 ImplementsAbility {
|
||||||
ability: @20-22 Apply(
|
ability: @20-22 Apply(
|
||||||
"",
|
"",
|
||||||
|
@ -100,7 +103,7 @@
|
||||||
impls: None,
|
impls: None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
Opaque {
|
Opaque {
|
||||||
|
@ -126,8 +129,11 @@
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
derived: Some(
|
derived: Some(
|
||||||
@74-84 Implements(
|
ImplementsAbilities {
|
||||||
[
|
before_implements_kw: [],
|
||||||
|
implements: @63-73,
|
||||||
|
after_implements_kw: [],
|
||||||
|
item: @74-84 [
|
||||||
@75-77 ImplementsAbility {
|
@75-77 ImplementsAbility {
|
||||||
ability: @75-77 Apply(
|
ability: @75-77 Apply(
|
||||||
"",
|
"",
|
||||||
|
@ -145,7 +151,7 @@
|
||||||
impls: None,
|
impls: None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
Opaque {
|
Opaque {
|
||||||
|
@ -171,31 +177,31 @@
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
derived: Some(
|
derived: Some(
|
||||||
@134-144 SpaceBefore(
|
ImplementsAbilities {
|
||||||
Implements(
|
before_implements_kw: [
|
||||||
[
|
|
||||||
@135-137 ImplementsAbility {
|
|
||||||
ability: @135-137 Apply(
|
|
||||||
"",
|
|
||||||
"Eq",
|
|
||||||
[],
|
|
||||||
),
|
|
||||||
impls: None,
|
|
||||||
},
|
|
||||||
@139-143 ImplementsAbility {
|
|
||||||
ability: @139-143 Apply(
|
|
||||||
"",
|
|
||||||
"Hash",
|
|
||||||
[],
|
|
||||||
),
|
|
||||||
impls: None,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
),
|
|
||||||
[
|
|
||||||
Newline,
|
Newline,
|
||||||
],
|
],
|
||||||
),
|
implements: @123-133,
|
||||||
|
after_implements_kw: [],
|
||||||
|
item: @134-144 [
|
||||||
|
@135-137 ImplementsAbility {
|
||||||
|
ability: @135-137 Apply(
|
||||||
|
"",
|
||||||
|
"Eq",
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
impls: None,
|
||||||
|
},
|
||||||
|
@139-143 ImplementsAbility {
|
||||||
|
ability: @139-143 Apply(
|
||||||
|
"",
|
||||||
|
"Hash",
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
impls: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
Opaque {
|
Opaque {
|
||||||
|
@ -209,8 +215,11 @@
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
derived: Some(
|
derived: Some(
|
||||||
@165-187 Implements(
|
ImplementsAbilities {
|
||||||
[
|
before_implements_kw: [],
|
||||||
|
implements: @154-164,
|
||||||
|
after_implements_kw: [],
|
||||||
|
item: @165-187 [
|
||||||
@166-173 ImplementsAbility {
|
@166-173 ImplementsAbility {
|
||||||
ability: @166-168 Apply(
|
ability: @166-168 Apply(
|
||||||
"",
|
"",
|
||||||
|
@ -244,7 +253,7 @@
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
Opaque {
|
Opaque {
|
||||||
|
@ -258,8 +267,11 @@
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
derived: Some(
|
derived: Some(
|
||||||
@208-222 Implements(
|
ImplementsAbilities {
|
||||||
[
|
before_implements_kw: [],
|
||||||
|
implements: @197-207,
|
||||||
|
after_implements_kw: [],
|
||||||
|
item: @208-222 [
|
||||||
@209-221 ImplementsAbility {
|
@209-221 ImplementsAbility {
|
||||||
ability: @209-211 Apply(
|
ability: @209-211 Apply(
|
||||||
"",
|
"",
|
||||||
|
@ -280,7 +292,7 @@
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
Opaque {
|
Opaque {
|
||||||
|
@ -294,8 +306,11 @@
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
derived: Some(
|
derived: Some(
|
||||||
@243-263 Implements(
|
ImplementsAbilities {
|
||||||
[
|
before_implements_kw: [],
|
||||||
|
implements: @232-242,
|
||||||
|
after_implements_kw: [],
|
||||||
|
item: @243-263 [
|
||||||
@244-256 ImplementsAbility {
|
@244-256 ImplementsAbility {
|
||||||
ability: @244-246 Apply(
|
ability: @244-246 Apply(
|
||||||
"",
|
"",
|
||||||
|
@ -324,7 +339,7 @@
|
||||||
impls: None,
|
impls: None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
Opaque {
|
Opaque {
|
||||||
|
@ -338,8 +353,11 @@
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
derived: Some(
|
derived: Some(
|
||||||
@284-304 Implements(
|
ImplementsAbilities {
|
||||||
[
|
before_implements_kw: [],
|
||||||
|
implements: @273-283,
|
||||||
|
after_implements_kw: [],
|
||||||
|
item: @284-304 [
|
||||||
@285-289 ImplementsAbility {
|
@285-289 ImplementsAbility {
|
||||||
ability: @285-289 Apply(
|
ability: @285-289 Apply(
|
||||||
"",
|
"",
|
||||||
|
@ -368,7 +386,7 @@
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
Opaque {
|
Opaque {
|
||||||
|
@ -382,9 +400,12 @@
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
derived: Some(
|
derived: Some(
|
||||||
@325-327 Implements(
|
ImplementsAbilities {
|
||||||
[],
|
before_implements_kw: [],
|
||||||
),
|
implements: @314-324,
|
||||||
|
after_implements_kw: [],
|
||||||
|
item: @325-327 [],
|
||||||
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
Opaque {
|
Opaque {
|
||||||
|
@ -410,47 +431,47 @@
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
derived: Some(
|
derived: Some(
|
||||||
@377-399 SpaceBefore(
|
ImplementsAbilities {
|
||||||
Implements(
|
before_implements_kw: [
|
||||||
[
|
|
||||||
@378-385 ImplementsAbility {
|
|
||||||
ability: @378-380 Apply(
|
|
||||||
"",
|
|
||||||
"Eq",
|
|
||||||
[],
|
|
||||||
),
|
|
||||||
impls: Some(
|
|
||||||
@381-385 AbilityImpls(
|
|
||||||
[
|
|
||||||
@382-384 LabelOnly(
|
|
||||||
@382-384 "eq",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
@387-398 ImplementsAbility {
|
|
||||||
ability: @387-391 Apply(
|
|
||||||
"",
|
|
||||||
"Hash",
|
|
||||||
[],
|
|
||||||
),
|
|
||||||
impls: Some(
|
|
||||||
@392-398 AbilityImpls(
|
|
||||||
[
|
|
||||||
@393-397 LabelOnly(
|
|
||||||
@393-397 "hash",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
),
|
|
||||||
[
|
|
||||||
Newline,
|
Newline,
|
||||||
],
|
],
|
||||||
),
|
implements: @366-376,
|
||||||
|
after_implements_kw: [],
|
||||||
|
item: @377-399 [
|
||||||
|
@378-385 ImplementsAbility {
|
||||||
|
ability: @378-380 Apply(
|
||||||
|
"",
|
||||||
|
"Eq",
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
impls: Some(
|
||||||
|
@381-385 AbilityImpls(
|
||||||
|
[
|
||||||
|
@382-384 LabelOnly(
|
||||||
|
@382-384 "eq",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
@387-398 ImplementsAbility {
|
||||||
|
ability: @387-391 Apply(
|
||||||
|
"",
|
||||||
|
"Hash",
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
impls: Some(
|
||||||
|
@392-398 AbilityImpls(
|
||||||
|
[
|
||||||
|
@393-397 LabelOnly(
|
||||||
|
@393-397 "hash",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
Opaque {
|
Opaque {
|
||||||
|
@ -464,8 +485,11 @@
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
derived: Some(
|
derived: Some(
|
||||||
@420-427 Implements(
|
ImplementsAbilities {
|
||||||
[
|
before_implements_kw: [],
|
||||||
|
implements: @409-419,
|
||||||
|
after_implements_kw: [],
|
||||||
|
item: @420-427 [
|
||||||
@421-426 ImplementsAbility {
|
@421-426 ImplementsAbility {
|
||||||
ability: @421-423 Apply(
|
ability: @421-423 Apply(
|
||||||
"",
|
"",
|
||||||
|
@ -479,7 +503,7 @@
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
{ i #
|
{ i #
|
||||||
& }
|
& }
|
|
@ -0,0 +1,2 @@
|
||||||
|
return { #
|
||||||
|
g & } e
|
|
@ -0,0 +1,36 @@
|
||||||
|
@0-15 SpaceAfter(
|
||||||
|
Return(
|
||||||
|
@0-15 SpaceBefore(
|
||||||
|
Apply(
|
||||||
|
@8-14 RecordUpdate {
|
||||||
|
update: @11-12 SpaceBefore(
|
||||||
|
Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "g",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
LineComment(
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
fields: [],
|
||||||
|
},
|
||||||
|
[
|
||||||
|
@14-15 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "e",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Space,
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
return
|
||||||
|
{#
|
||||||
|
g&}e
|
|
@ -301,6 +301,7 @@ mod test_snapshots {
|
||||||
pass/ann_effectful_fn.expr,
|
pass/ann_effectful_fn.expr,
|
||||||
pass/ann_open_union.expr,
|
pass/ann_open_union.expr,
|
||||||
pass/ann_parens_comments.expr,
|
pass/ann_parens_comments.expr,
|
||||||
|
pass/ann_parens_where_implements_func.expr,
|
||||||
pass/ann_pattern_comment_before_body.expr,
|
pass/ann_pattern_comment_before_body.expr,
|
||||||
pass/ann_record_pat_with_comment.expr,
|
pass/ann_record_pat_with_comment.expr,
|
||||||
pass/ann_tag_union_newline_comment.expr,
|
pass/ann_tag_union_newline_comment.expr,
|
||||||
|
@ -552,6 +553,7 @@ mod test_snapshots {
|
||||||
pass/newline_after_sub.expr,
|
pass/newline_after_sub.expr,
|
||||||
pass/newline_and_spaces_before_less_than.expr,
|
pass/newline_and_spaces_before_less_than.expr,
|
||||||
pass/newline_before_add.expr,
|
pass/newline_before_add.expr,
|
||||||
|
pass/newline_before_and_after_implements_opaque.expr,
|
||||||
pass/newline_before_import_curlies.expr,
|
pass/newline_before_import_curlies.expr,
|
||||||
pass/newline_before_sub.expr,
|
pass/newline_before_sub.expr,
|
||||||
pass/newline_in_packages.full,
|
pass/newline_in_packages.full,
|
||||||
|
@ -666,6 +668,7 @@ mod test_snapshots {
|
||||||
pass/return_multiline.expr,
|
pass/return_multiline.expr,
|
||||||
pass/return_only_statement.expr,
|
pass/return_only_statement.expr,
|
||||||
pass/return_parens_comments.expr,
|
pass/return_parens_comments.expr,
|
||||||
|
pass/return_record_update_comment_empty_fields.expr,
|
||||||
pass/return_then_nested_parens.expr,
|
pass/return_then_nested_parens.expr,
|
||||||
pass/return_with_after.expr,
|
pass/return_with_after.expr,
|
||||||
pass/separate_defs.moduledefs,
|
pass/separate_defs.moduledefs,
|
||||||
|
|
|
@ -535,12 +535,7 @@ impl IterTokens for Loc<ImplementsAbilities<'_>> {
|
||||||
|
|
||||||
impl IterTokens for ImplementsAbilities<'_> {
|
impl IterTokens for ImplementsAbilities<'_> {
|
||||||
fn iter_tokens<'a>(&self, arena: &'a Bump) -> BumpVec<'a, Loc<Token>> {
|
fn iter_tokens<'a>(&self, arena: &'a Bump) -> BumpVec<'a, Loc<Token>> {
|
||||||
match self {
|
self.item.value.iter_tokens(arena)
|
||||||
ImplementsAbilities::Implements(impls) => impls.iter_tokens(arena),
|
|
||||||
ImplementsAbilities::SpaceBefore(i, _) | ImplementsAbilities::SpaceAfter(i, _) => {
|
|
||||||
i.iter_tokens(arena)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1321,59 +1321,9 @@ fn surgery_macho_help(
|
||||||
continue;
|
continue;
|
||||||
} else if matches!(app_obj.symbol_by_index(index), Ok(sym) if ["_longjmp", "_setjmp"].contains(&sym.name().unwrap_or_default()))
|
} else if matches!(app_obj.symbol_by_index(index), Ok(sym) if ["_longjmp", "_setjmp"].contains(&sym.name().unwrap_or_default()))
|
||||||
{
|
{
|
||||||
// These symbols have to stay undefined as we dynamically link them from libSystem.dylib at runtime.
|
// Explicitly ignore `longjmp` and `setjmp` which are used only in `roc test` mode and thus are unreferenced
|
||||||
// TODO have a table of all known symbols; perhaps parse and use an Apple provided libSystem.tbd stub file?
|
// by the app and can be safely skipped.
|
||||||
let name = app_obj
|
// In the future, `longjmp` and `setjmp` will be obsoleted and thus this prong can be safely deleted.
|
||||||
.symbol_by_index(index)
|
|
||||||
.and_then(|sym| sym.name())
|
|
||||||
.ok()
|
|
||||||
.unwrap();
|
|
||||||
match rel.1.kind() {
|
|
||||||
RelocationKind::PltRelative => {
|
|
||||||
if verbose {
|
|
||||||
println!("\t\tTODO synthesise __stub entry for {name}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RelocationKind::Got => {
|
|
||||||
if verbose {
|
|
||||||
println!("\t\tTODO synthesise __got entry for {name}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RelocationKind::Unknown => {
|
|
||||||
if let RelocationFlags::MachO { r_type, .. } = rel.1.flags() {
|
|
||||||
match r_type {
|
|
||||||
macho::ARM64_RELOC_GOT_LOAD_PAGE21
|
|
||||||
| macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12 => {
|
|
||||||
if verbose {
|
|
||||||
println!(
|
|
||||||
"\t\tTODO synthesise __got entry for {name}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
macho::ARM64_RELOC_BRANCH26 => {
|
|
||||||
if verbose {
|
|
||||||
println!(
|
|
||||||
"\t\tTODO synthesise __stub entry for {name}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => internal_error!(
|
|
||||||
"Invalid relocation for libc symbol, {:+x?}: {name}",
|
|
||||||
rel
|
|
||||||
),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
internal_error!(
|
|
||||||
"Invalid relocation found for Mach-O: {:?}",
|
|
||||||
rel
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => internal_error!(
|
|
||||||
"Invalid relocation for libc symbol, {:+x?}: {name}",
|
|
||||||
rel
|
|
||||||
),
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
internal_error!(
|
internal_error!(
|
||||||
|
|
|
@ -59,6 +59,7 @@
|
||||||
xorg.libXi
|
xorg.libXi
|
||||||
xorg.libxcb
|
xorg.libxcb
|
||||||
cargo-llvm-cov # to visualize code coverage
|
cargo-llvm-cov # to visualize code coverage
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
# DevInputs are not necessary to build roc as a user
|
# DevInputs are not necessary to build roc as a user
|
||||||
|
@ -75,6 +76,8 @@
|
||||||
cmake
|
cmake
|
||||||
# provides llvm
|
# provides llvm
|
||||||
llvmPkgs.dev
|
llvmPkgs.dev
|
||||||
|
# for debugging:
|
||||||
|
# lldb
|
||||||
# faster builds - see https://github.com/roc-lang/roc/blob/main/BUILDING_FROM_SOURCE.md#use-lld-for-the-linker
|
# faster builds - see https://github.com/roc-lang/roc/blob/main/BUILDING_FROM_SOURCE.md#use-lld-for-the-linker
|
||||||
# provides lld
|
# provides lld
|
||||||
pkgs.lld_18
|
pkgs.lld_18
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue