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
|
||||
|
||||
- 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
|
||||
|
||||
- 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
|
||||
|
||||
- name: roc test all builtins
|
||||
run: nix develop -c ./ci/roc_test_builtins.sh
|
||||
|
||||
- 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
|
||||
|
||||
- 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
|
||||
|
||||
- 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
|
||||
run: bash www/build.sh
|
||||
|
||||
- name: run fuzz tests - ok to merge if this one fails # for now!
|
||||
run: |
|
||||
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
|
||||
#- name: run fuzz tests - ok to merge if this one fails # for now!
|
||||
# run: |
|
||||
# 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
|
||||
|
|
|
@ -22,6 +22,10 @@ jobs:
|
|||
- name: Check if debug flag files are in sync
|
||||
run: ./ci/check_debug_vars.sh
|
||||
|
||||
# for skipped tests; see #6946, #6947
|
||||
- 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>
|
||||
Elias Mulhall <eli.mulhall@gmail.com>
|
||||
ABuffSeagull <reecevanatta@hey.com>
|
||||
Timon Krebs <timonkrebs@hotmail.com>
|
|
@ -895,7 +895,7 @@ mod cli_tests {
|
|||
build_platform_host();
|
||||
|
||||
let cli_build = ExecCli::new(
|
||||
roc_cli::CMD_DEV,
|
||||
roc_cli::CMD_BUILD,
|
||||
file_from_root("crates/cli/tests/test-projects/effectful", "form.roc"),
|
||||
);
|
||||
|
||||
|
@ -915,14 +915,14 @@ mod cli_tests {
|
|||
fn effectful_hello() {
|
||||
build_platform_host();
|
||||
|
||||
let cli_build = ExecCli::new(
|
||||
let cli_dev = ExecCli::new(
|
||||
roc_cli::CMD_DEV,
|
||||
file_from_root("crates/cli/tests/test-projects/effectful/", "hello.roc"),
|
||||
);
|
||||
|
||||
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]
|
||||
|
@ -930,14 +930,14 @@ mod cli_tests {
|
|||
fn effectful_loops() {
|
||||
build_platform_host();
|
||||
|
||||
let cli_build = ExecCli::new(
|
||||
let cli_dev = ExecCli::new(
|
||||
roc_cli::CMD_DEV,
|
||||
file_from_root("crates/cli/tests/test-projects/effectful/", "loops.roc"),
|
||||
);
|
||||
|
||||
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]
|
||||
|
@ -945,7 +945,7 @@ mod cli_tests {
|
|||
fn effectful_untyped_passed_fx() {
|
||||
build_platform_host();
|
||||
|
||||
let cli_build = ExecCli::new(
|
||||
let cli_dev = ExecCli::new(
|
||||
roc_cli::CMD_DEV,
|
||||
file_from_root(
|
||||
"crates/cli/tests/test-projects/effectful/",
|
||||
|
@ -955,7 +955,7 @@ mod cli_tests {
|
|||
|
||||
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]
|
||||
|
@ -963,7 +963,7 @@ mod cli_tests {
|
|||
fn effectful_ignore_result() {
|
||||
build_platform_host();
|
||||
|
||||
let cli_build = ExecCli::new(
|
||||
let cli_dev = ExecCli::new(
|
||||
roc_cli::CMD_DEV,
|
||||
file_from_root(
|
||||
"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";
|
||||
|
||||
cli_build.run().assert_clean_stdout(expected_out);
|
||||
cli_dev.run().assert_clean_stdout(expected_out);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -982,7 +982,7 @@ mod cli_tests {
|
|||
build_platform_host();
|
||||
|
||||
let cli_build = ExecCli::new(
|
||||
roc_cli::CMD_DEV,
|
||||
roc_cli::CMD_BUILD,
|
||||
file_from_root(
|
||||
"crates/cli/tests/test-projects/effectful",
|
||||
"suffixed_record_field.roc",
|
||||
|
@ -1005,7 +1005,7 @@ mod cli_tests {
|
|||
build_platform_host();
|
||||
|
||||
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"),
|
||||
);
|
||||
|
||||
|
@ -1020,7 +1020,7 @@ mod cli_tests {
|
|||
build_platform_host();
|
||||
|
||||
let cli_build = ExecCli::new(
|
||||
roc_cli::CMD_DEV,
|
||||
roc_cli::CMD_BUILD,
|
||||
file_from_root(
|
||||
"crates/cli/tests/test-projects/effectful",
|
||||
"for_each_try.roc",
|
||||
|
|
|
@ -80,6 +80,8 @@ impl ExecCli {
|
|||
app_stdin_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();
|
||||
build_cmd_out.assert_clean_success();
|
||||
|
||||
|
|
|
@ -456,7 +456,7 @@ fn gen_from_mono_module_dev<'a>(
|
|||
|
||||
#[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) => {
|
||||
|
|
|
@ -283,10 +283,16 @@ dbg_bool = \b ->
|
|||
|
||||
dbg_str : Str -> Inspector DbgFormatter
|
||||
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 ->
|
||||
f0
|
||||
|> dbg_write("\"")
|
||||
|> dbg_write(s) # TODO: Should we be escaping strings for dbg/logging?
|
||||
dbg_write(f0, "\"")
|
||||
|> dbg_write(escape_s)
|
||||
|> dbg_write("\"")
|
||||
|
||||
custom(custom_dbg_str)
|
||||
|
|
|
@ -538,14 +538,14 @@ to_utf8 : Str -> List U8
|
|||
## expect Str.from_utf8([]) == Ok("")
|
||||
## 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 ->
|
||||
result = from_utf8_lowlevel(bytes)
|
||||
result = from_utf8_lowlevel bytes
|
||||
|
||||
if result.c_is_ok then
|
||||
Ok(result.b_string)
|
||||
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([224, 174, 154, 224, 174, 191])) == Ok("சி")
|
||||
|
|
|
@ -272,7 +272,7 @@ enum PendingTypeDef<'a> {
|
|||
name: Loc<Symbol>,
|
||||
vars: Vec<Loc<Lowercase>>,
|
||||
ann: &'a Loc<ast::TypeAnnotation<'a>>,
|
||||
derived: Option<&'a Loc<ast::ImplementsAbilities<'a>>>,
|
||||
derived: Option<&'a ast::ImplementsAbilities<'a>>,
|
||||
},
|
||||
|
||||
Ability {
|
||||
|
@ -319,7 +319,7 @@ impl PendingTypeDef<'_> {
|
|||
ann,
|
||||
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);
|
||||
|
||||
Some((name.value, region))
|
||||
|
@ -761,12 +761,11 @@ fn canonicalize_opaque<'a>(
|
|||
var_store: &mut VarStore,
|
||||
scope: &mut Scope,
|
||||
pending_abilities_in_scope: &PendingAbilitiesInScope,
|
||||
|
||||
name: Loc<Symbol>,
|
||||
name_str: &'a str,
|
||||
ann: &'a Loc<ast::TypeAnnotation<'a>>,
|
||||
vars: &[Loc<Lowercase>],
|
||||
has_abilities: Option<&'a Loc<ast::ImplementsAbilities<'a>>>,
|
||||
has_abilities: Option<&'a ast::ImplementsAbilities<'a>>,
|
||||
) -> Result<CanonicalizedOpaque<'a>, ()> {
|
||||
let alias = canonicalize_alias(
|
||||
env,
|
||||
|
@ -784,11 +783,11 @@ fn canonicalize_opaque<'a>(
|
|||
|
||||
let mut derived_defs = Vec::new();
|
||||
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![];
|
||||
|
||||
for has_ability in has_abilities.items {
|
||||
for has_ability in has_abilities.value.items {
|
||||
let region = has_ability.region;
|
||||
let (ability, opt_impls) = match has_ability.value.extract_spaces().item {
|
||||
ast::ImplementsAbility::ImplementsAbility { ability, impls } => (ability, impls),
|
||||
|
@ -1303,7 +1302,7 @@ fn canonicalize_type_defs<'a>(
|
|||
Loc<Symbol>,
|
||||
Vec<Loc<Lowercase>>,
|
||||
&'a Loc<ast::TypeAnnotation<'a>>,
|
||||
Option<&'a Loc<ast::ImplementsAbilities<'a>>>,
|
||||
Option<&'a ast::ImplementsAbilities<'a>>,
|
||||
),
|
||||
Ability(Loc<Symbol>, Vec<PendingAbilityMember<'a>>),
|
||||
}
|
||||
|
@ -2805,7 +2804,7 @@ fn to_pending_alias_or_opaque<'a>(
|
|||
name: &'a Loc<&'a str>,
|
||||
vars: &'a [Loc<ast::Pattern<'a>>],
|
||||
ann: &'a Loc<ast::TypeAnnotation<'a>>,
|
||||
opt_derived: Option<&'a Loc<ast::ImplementsAbilities<'a>>>,
|
||||
opt_derived: Option<&'a ast::ImplementsAbilities<'a>>,
|
||||
kind: AliasKind,
|
||||
) -> PendingTypeDef<'a> {
|
||||
let region = Region::span_across(&name.region, &ann.region);
|
||||
|
@ -2898,15 +2897,7 @@ fn to_pending_type_def<'a>(
|
|||
header: TypeHeader { name, vars },
|
||||
typ: ann,
|
||||
derived,
|
||||
} => to_pending_alias_or_opaque(
|
||||
env,
|
||||
scope,
|
||||
name,
|
||||
vars,
|
||||
ann,
|
||||
derived.as_ref(),
|
||||
AliasKind::Opaque,
|
||||
),
|
||||
} => to_pending_alias_or_opaque(env, scope, name, vars, ann, *derived, AliasKind::Opaque),
|
||||
|
||||
Ability {
|
||||
header, members, ..
|
||||
|
|
|
@ -703,36 +703,37 @@ impl<'a> Formattable for ImplementsAbility<'a> {
|
|||
|
||||
impl<'a> Formattable for ImplementsAbilities<'a> {
|
||||
fn is_multiline(&self) -> bool {
|
||||
match self {
|
||||
ImplementsAbilities::SpaceAfter(..) | ImplementsAbilities::SpaceBefore(..) => true,
|
||||
ImplementsAbilities::Implements(has_abilities) => {
|
||||
is_collection_multiline(has_abilities)
|
||||
}
|
||||
}
|
||||
self.before_implements_kw.iter().any(|s| s.is_comment())
|
||||
|| self.after_implements_kw.iter().any(|s| s.is_comment())
|
||||
|| is_collection_multiline(&self.item.value)
|
||||
}
|
||||
|
||||
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
|
||||
match self {
|
||||
ImplementsAbilities::Implements(has_abilities) => {
|
||||
if newlines == Newlines::Yes {
|
||||
fn format_with_options(&self, buf: &mut Buf, _parens: Parens, newlines: Newlines, indent: u16) {
|
||||
if !self.before_implements_kw.is_empty() {
|
||||
buf.newline();
|
||||
buf.indent(indent);
|
||||
fmt_comments_only(
|
||||
buf,
|
||||
self.before_implements_kw.iter(),
|
||||
NewlineAt::Bottom,
|
||||
indent,
|
||||
);
|
||||
}
|
||||
if newlines == Newlines::Yes {
|
||||
buf.ensure_ends_with_newline();
|
||||
}
|
||||
buf.indent(indent);
|
||||
buf.push_str(roc_parse::keyword::IMPLEMENTS);
|
||||
buf.spaces(1);
|
||||
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 !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,
|
||||
needs_indent,
|
||||
prec: Prec::AsType,
|
||||
prec: Prec::FunctionType,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@ use roc_error_macros::internal_error;
|
|||
use roc_parse::ast::{
|
||||
AbilityMember, Defs, Expr, ExtractSpaces, ImportAlias, ImportAsKeyword, ImportExposingKeyword,
|
||||
ImportedModuleName, IngestedFileAnnotation, IngestedFileImport, ModuleImport,
|
||||
ModuleImportParams, Pattern, PatternApplyStyle, Spaceable, Spaces, SpacesAfter, SpacesBefore,
|
||||
StrLiteral, TypeAnnotation, TypeDef, TypeHeader, ValueDef,
|
||||
ModuleImportParams, Pattern, PatternApplyStyle, Spaces, SpacesBefore, StrLiteral,
|
||||
TypeAnnotation, TypeDef, TypeHeader, ValueDef,
|
||||
};
|
||||
use roc_parse::expr::merge_spaces;
|
||||
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>> {
|
||||
match def {
|
||||
TypeDef::Alias { header, ann } => {
|
||||
|
@ -128,17 +113,12 @@ pub fn tydef_lift_spaces<'a, 'b: 'a>(arena: &'a Bump, def: TypeDef<'b>) -> Space
|
|||
typ,
|
||||
derived,
|
||||
} => {
|
||||
if let Some(derived) = derived {
|
||||
let derived_lifted = lift_spaces_after(arena, derived.value);
|
||||
|
||||
if derived.is_some() {
|
||||
// It's structurally impossible for a derived clause to have spaces after
|
||||
Spaces {
|
||||
before: &[],
|
||||
item: TypeDef::Opaque {
|
||||
header,
|
||||
typ,
|
||||
derived: Some(Loc::at(derived.region, derived_lifted.item)),
|
||||
},
|
||||
after: derived_lifted.after,
|
||||
item: def,
|
||||
after: &[],
|
||||
}
|
||||
} else {
|
||||
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
|
||||
// contains a where-has clause.
|
||||
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 {
|
||||
false
|
||||
};
|
||||
|
@ -481,7 +461,7 @@ impl<'a> Formattable for TypeDef<'a> {
|
|||
if let Some(has_abilities) = has_abilities {
|
||||
buf.spaces(1);
|
||||
|
||||
has_abilities.format_with_options(
|
||||
(*has_abilities).format_with_options(
|
||||
buf,
|
||||
Parens::NotNeeded,
|
||||
Newlines::from_bool(make_multiline),
|
||||
|
|
|
@ -1814,14 +1814,17 @@ fn fmt_return<'a>(
|
|||
buf.indent(indent);
|
||||
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
|
||||
} else {
|
||||
indent
|
||||
};
|
||||
|
||||
let value = expr_lift_spaces(parens, buf.text.bump(), &return_value.value);
|
||||
|
||||
if !value.before.is_empty() {
|
||||
format_spaces(buf, value.before, newlines, return_indent);
|
||||
}
|
||||
|
@ -2057,15 +2060,17 @@ fn fmt_record_like<'a, 'b: 'a, Field, ToSpacesAround>(
|
|||
// doesnt make sense.
|
||||
Some(RecordPrefix::Update(record_var)) => {
|
||||
buf.spaces(1);
|
||||
record_var.format(buf, indent);
|
||||
buf.indent(indent);
|
||||
buf.push_str(" &");
|
||||
record_var.format(buf, indent + INDENT);
|
||||
buf.indent(indent + INDENT);
|
||||
buf.ensure_ends_with_whitespace();
|
||||
buf.push_str("&");
|
||||
}
|
||||
Some(RecordPrefix::Mapper(mapper_var)) => {
|
||||
buf.spaces(1);
|
||||
mapper_var.format(buf, indent);
|
||||
buf.indent(indent);
|
||||
buf.push_str(" <-");
|
||||
mapper_var.format(buf, indent + INDENT);
|
||||
buf.indent(indent + INDENT);
|
||||
buf.ensure_ends_with_whitespace();
|
||||
buf.push_str("<-");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -841,7 +841,7 @@ pub enum TypeDef<'a> {
|
|||
Opaque {
|
||||
header: TypeHeader<'a>,
|
||||
typ: Loc<TypeAnnotation<'a>>,
|
||||
derived: Option<Loc<ImplementsAbilities<'a>>>,
|
||||
derived: Option<&'a ImplementsAbilities<'a>>,
|
||||
},
|
||||
|
||||
/// An ability definition. E.g.
|
||||
|
@ -1552,31 +1552,11 @@ pub enum ImplementsAbility<'a> {
|
|||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum ImplementsAbilities<'a> {
|
||||
/// `implements [Eq { eq: myEq }, Hash]`
|
||||
Implements(Collection<'a, Loc<ImplementsAbility<'a>>>),
|
||||
|
||||
// We preserve this for the formatter; canonicalization ignores it.
|
||||
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()
|
||||
}
|
||||
pub struct ImplementsAbilities<'a> {
|
||||
pub before_implements_kw: &'a [CommentOrNewline<'a>],
|
||||
pub implements: Region,
|
||||
pub after_implements_kw: &'a [CommentOrNewline<'a>],
|
||||
pub item: Loc<Collection<'a, Loc<ImplementsAbility<'a>>>>,
|
||||
}
|
||||
|
||||
#[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> {
|
||||
pub const REPL_OPAQUE_FUNCTION: Self = Expr::Var {
|
||||
module_name: "",
|
||||
|
@ -2396,7 +2367,6 @@ impl_extract_spaces!(Tag);
|
|||
impl_extract_spaces!(AssignedField<T>);
|
||||
impl_extract_spaces!(TypeAnnotation);
|
||||
impl_extract_spaces!(ImplementsAbility);
|
||||
impl_extract_spaces!(ImplementsAbilities);
|
||||
impl_extract_spaces!(Implements);
|
||||
|
||||
impl<'a, T: Copy> ExtractSpaces<'a> for Spaced<'a, T> {
|
||||
|
@ -2720,7 +2690,11 @@ impl<'a> Malformed for TypeDef<'a> {
|
|||
header,
|
||||
typ,
|
||||
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 {
|
||||
header,
|
||||
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> {
|
||||
fn is_malformed(&self) -> bool {
|
||||
match self {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::ast::CommentOrNewline;
|
||||
use crate::ast::Spaceable;
|
||||
use crate::ast::SpacesBefore;
|
||||
use crate::parser::succeed;
|
||||
use crate::parser::Progress;
|
||||
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>(
|
||||
parser: P,
|
||||
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)))
|
||||
}
|
||||
|
||||
fn opaque_signature<'a>() -> impl Parser<
|
||||
'a,
|
||||
(
|
||||
Loc<TypeAnnotation<'a>>,
|
||||
Option<Loc<ImplementsAbilities<'a>>>,
|
||||
),
|
||||
EExpr<'a>,
|
||||
> {
|
||||
fn opaque_signature<'a>(
|
||||
) -> impl Parser<'a, (Loc<TypeAnnotation<'a>>, Option<&'a ImplementsAbilities<'a>>), EExpr<'a>> {
|
||||
and(
|
||||
specialize_err(EExpr::Type, type_annotation::located_opaque_signature(true)),
|
||||
optional(backtrackable(specialize_err(
|
||||
EExpr::Type,
|
||||
space0_before_e(type_annotation::implements_abilities(), EType::TIndentStart),
|
||||
))),
|
||||
optional(map_with_arena(
|
||||
specialize_err(EExpr::Type, type_annotation::implements_abilities()),
|
||||
|arena, item| &*arena.alloc(item),
|
||||
)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@ use bumpalo::Bump;
|
|||
use roc_module::called_via::{BinOp, UnaryOp};
|
||||
use roc_region::all::{Loc, Position, Region};
|
||||
|
||||
use crate::ast::ImplementsAbilities;
|
||||
use crate::{
|
||||
ast::{
|
||||
AbilityImpls, AbilityMember, AssignedField, Collection, Defs, Expr, FullAst, Header,
|
||||
Implements, ImplementsAbilities, ImplementsAbility, ImplementsClause, ImportAlias,
|
||||
ImportAsKeyword, ImportExposingKeyword, ImportedModuleName, IngestedFileAnnotation,
|
||||
IngestedFileImport, ModuleImport, ModuleImportParams, Pattern, PatternAs, Spaced, Spaces,
|
||||
SpacesBefore, StrLiteral, StrSegment, Tag, TypeAnnotation, TypeDef, TypeHeader, ValueDef,
|
||||
WhenBranch,
|
||||
Implements, ImplementsAbility, ImplementsClause, ImportAlias, ImportAsKeyword,
|
||||
ImportExposingKeyword, ImportedModuleName, IngestedFileAnnotation, IngestedFileImport,
|
||||
ModuleImport, ModuleImportParams, Pattern, PatternAs, Spaced, Spaces, SpacesBefore,
|
||||
StrLiteral, StrSegment, Tag, TypeAnnotation, TypeDef, TypeHeader, ValueDef, WhenBranch,
|
||||
},
|
||||
header::{
|
||||
AppHeader, ExposedName, ExposesKeyword, HostedHeader, ImportsEntry, ImportsKeyword,
|
||||
|
@ -372,7 +372,7 @@ impl<'a> Normalize<'a> for TypeDef<'a> {
|
|||
vars: vars.normalize(arena),
|
||||
},
|
||||
typ: typ.normalize(arena),
|
||||
derived: derived.normalize(arena),
|
||||
derived: derived.map(|item| &*arena.alloc(item.normalize(arena))),
|
||||
},
|
||||
Ability {
|
||||
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> {
|
||||
fn normalize(&self, arena: &'a Bump) -> 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> {
|
||||
fn normalize(&self, arena: &'a Bump) -> Self {
|
||||
PatternAs {
|
||||
|
|
|
@ -4,8 +4,8 @@ use crate::ast::{
|
|||
TypeAnnotation, TypeHeader,
|
||||
};
|
||||
use crate::blankspace::{
|
||||
self, space0_around_ee, space0_before_e, space0_before_optional_after, space0_e,
|
||||
spaces_before_optional_after,
|
||||
self, plain_spaces_before, space0_around_ee, space0_before_e, space0_before_optional_after,
|
||||
space0_e, spaces_before_optional_after,
|
||||
};
|
||||
use crate::expr::record_field;
|
||||
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]`.
|
||||
pub fn implements_abilities<'a>() -> impl Parser<'a, Loc<ImplementsAbilities<'a>>, EType<'a>> {
|
||||
increment_min_indent(skip_first(
|
||||
pub fn implements_abilities<'a>() -> impl Parser<'a, ImplementsAbilities<'a>, EType<'a>> {
|
||||
map(
|
||||
plain_spaces_before(
|
||||
increment_min_indent(and(
|
||||
// Parse "implements"; we don't care about this keyword
|
||||
crate::parser::keyword(crate::keyword::IMPLEMENTS, EType::TImplementsClause),
|
||||
map(
|
||||
loc(crate::parser::keyword(
|
||||
crate::keyword::IMPLEMENTS,
|
||||
EType::TImplementsClause,
|
||||
)),
|
||||
|item| item.region,
|
||||
),
|
||||
// Parse "Hash"; this may be qualified from another module like "Hash.Hash"
|
||||
space0_before_e(
|
||||
loc(map(
|
||||
collection_trailing_sep_e(
|
||||
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,
|
||||
),
|
||||
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>> {
|
||||
|
|
|
@ -165,7 +165,7 @@ mod solve_expr {
|
|||
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!(
|
||||
r#"
|
||||
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
|
||||
"a"
|
||||
else
|
||||
|
@ -712,7 +712,7 @@ fn str_from_utf8_fail_unexpected_end_of_sequence() {
|
|||
indoc!(
|
||||
r#"
|
||||
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
|
||||
"a"
|
||||
else
|
||||
|
@ -732,7 +732,7 @@ fn str_from_utf8_fail_expected_continuation() {
|
|||
indoc!(
|
||||
r#"
|
||||
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
|
||||
"a"
|
||||
else
|
||||
|
@ -752,7 +752,7 @@ fn str_from_utf8_fail_overlong_encoding() {
|
|||
indoc!(
|
||||
r#"
|
||||
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
|
||||
"a"
|
||||
else
|
||||
|
@ -772,7 +772,7 @@ fn str_from_utf8_fail_codepoint_too_large() {
|
|||
indoc!(
|
||||
r#"
|
||||
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
|
||||
"a"
|
||||
else
|
||||
|
@ -792,7 +792,7 @@ fn str_from_utf8_fail_surrogate_half() {
|
|||
indoc!(
|
||||
r#"
|
||||
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
|
||||
"a"
|
||||
else
|
||||
|
|
|
@ -522,7 +522,7 @@ fn str_from_utf8_fail_invalid_start_byte() {
|
|||
indoc!(
|
||||
r#"
|
||||
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
|
||||
"a"
|
||||
else
|
||||
|
@ -541,7 +541,7 @@ fn str_from_utf8_fail_unexpected_end_of_sequence() {
|
|||
indoc!(
|
||||
r#"
|
||||
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
|
||||
"a"
|
||||
else
|
||||
|
@ -560,7 +560,7 @@ fn str_from_utf8_fail_expected_continuation() {
|
|||
indoc!(
|
||||
r#"
|
||||
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
|
||||
"a"
|
||||
else
|
||||
|
@ -579,7 +579,7 @@ fn str_from_utf8_fail_overlong_encoding() {
|
|||
indoc!(
|
||||
r#"
|
||||
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
|
||||
"a"
|
||||
else
|
||||
|
@ -598,7 +598,7 @@ fn str_from_utf8_fail_codepoint_too_large() {
|
|||
indoc!(
|
||||
r#"
|
||||
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
|
||||
"a"
|
||||
else
|
||||
|
@ -617,7 +617,7 @@ fn str_from_utf8_fail_surrogate_half() {
|
|||
indoc!(
|
||||
r#"
|
||||
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
|
||||
"a"
|
||||
else
|
||||
|
|
|
@ -164,31 +164,31 @@ procedure Num.96 (#Attr.2):
|
|||
ret Num.287;
|
||||
|
||||
procedure Str.12 (#Attr.2):
|
||||
let Str.258 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
ret Str.258;
|
||||
|
||||
procedure Str.36 (#Attr.2):
|
||||
let Str.259 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||
let Str.259 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
ret Str.259;
|
||||
|
||||
procedure Str.36 (#Attr.2):
|
||||
let Str.260 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||
ret Str.260;
|
||||
|
||||
procedure Str.43 (#Attr.2):
|
||||
let Str.253 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||
ret Str.253;
|
||||
let Str.254 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||
ret Str.254;
|
||||
|
||||
procedure Str.9 (Str.73):
|
||||
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
||||
let Str.250 : Int1 = StructAtIndex 2 Str.74;
|
||||
if Str.250 then
|
||||
let Str.252 : Str = StructAtIndex 1 Str.74;
|
||||
let Str.251 : [C {U64, U8}, C Str] = TagId(1) Str.252;
|
||||
ret Str.251;
|
||||
let Str.251 : Int1 = StructAtIndex 2 Str.74;
|
||||
if Str.251 then
|
||||
let Str.253 : Str = StructAtIndex 1 Str.74;
|
||||
let Str.252 : [C {U64, U8}, C Str] = TagId(1) Str.253;
|
||||
ret Str.252;
|
||||
else
|
||||
let Str.248 : U8 = StructAtIndex 3 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;
|
||||
dec #Derived_gen.45;
|
||||
let Str.247 : {U64, U8} = Struct {Str.249, Str.248};
|
||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.247;
|
||||
let Str.248 : {U64, U8} = Struct {Str.249, Str.250};
|
||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.248;
|
||||
ret Str.246;
|
||||
|
||||
procedure Test.20 (Test.56):
|
||||
|
|
|
@ -105,31 +105,31 @@ procedure Num.96 (#Attr.2):
|
|||
ret Num.283;
|
||||
|
||||
procedure Str.12 (#Attr.2):
|
||||
let Str.255 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
ret Str.255;
|
||||
|
||||
procedure Str.36 (#Attr.2):
|
||||
let Str.256 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||
let Str.256 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
ret Str.256;
|
||||
|
||||
procedure Str.36 (#Attr.2):
|
||||
let Str.257 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||
ret Str.257;
|
||||
|
||||
procedure Str.43 (#Attr.2):
|
||||
let Str.253 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||
ret Str.253;
|
||||
let Str.254 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||
ret Str.254;
|
||||
|
||||
procedure Str.9 (Str.73):
|
||||
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
||||
let Str.250 : Int1 = StructAtIndex 2 Str.74;
|
||||
if Str.250 then
|
||||
let Str.252 : Str = StructAtIndex 1 Str.74;
|
||||
let Str.251 : [C {U64, U8}, C Str] = TagId(1) Str.252;
|
||||
ret Str.251;
|
||||
let Str.251 : Int1 = StructAtIndex 2 Str.74;
|
||||
if Str.251 then
|
||||
let Str.253 : Str = StructAtIndex 1 Str.74;
|
||||
let Str.252 : [C {U64, U8}, C Str] = TagId(1) Str.253;
|
||||
ret Str.252;
|
||||
else
|
||||
let Str.248 : U8 = StructAtIndex 3 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;
|
||||
dec #Derived_gen.24;
|
||||
let Str.247 : {U64, U8} = Struct {Str.249, Str.248};
|
||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.247;
|
||||
let Str.248 : {U64, U8} = Struct {Str.249, Str.250};
|
||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.248;
|
||||
ret Str.246;
|
||||
|
||||
procedure Test.20 (Test.56):
|
||||
|
|
|
@ -112,31 +112,31 @@ procedure Num.96 (#Attr.2):
|
|||
ret Num.283;
|
||||
|
||||
procedure Str.12 (#Attr.2):
|
||||
let Str.255 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
ret Str.255;
|
||||
|
||||
procedure Str.36 (#Attr.2):
|
||||
let Str.256 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||
let Str.256 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
ret Str.256;
|
||||
|
||||
procedure Str.36 (#Attr.2):
|
||||
let Str.257 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||
ret Str.257;
|
||||
|
||||
procedure Str.43 (#Attr.2):
|
||||
let Str.253 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||
ret Str.253;
|
||||
let Str.254 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||
ret Str.254;
|
||||
|
||||
procedure Str.9 (Str.73):
|
||||
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
||||
let Str.250 : Int1 = StructAtIndex 2 Str.74;
|
||||
if Str.250 then
|
||||
let Str.252 : Str = StructAtIndex 1 Str.74;
|
||||
let Str.251 : [C {U64, U8}, C Str] = TagId(1) Str.252;
|
||||
ret Str.251;
|
||||
let Str.251 : Int1 = StructAtIndex 2 Str.74;
|
||||
if Str.251 then
|
||||
let Str.253 : Str = StructAtIndex 1 Str.74;
|
||||
let Str.252 : [C {U64, U8}, C Str] = TagId(1) Str.253;
|
||||
ret Str.252;
|
||||
else
|
||||
let Str.248 : U8 = StructAtIndex 3 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;
|
||||
dec #Derived_gen.28;
|
||||
let Str.247 : {U64, U8} = Struct {Str.249, Str.248};
|
||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.247;
|
||||
let Str.248 : {U64, U8} = Struct {Str.249, Str.250};
|
||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.248;
|
||||
ret Str.246;
|
||||
|
||||
procedure Test.20 (Test.56):
|
||||
|
|
|
@ -38,31 +38,31 @@ procedure Num.96 (#Attr.2):
|
|||
ret Num.283;
|
||||
|
||||
procedure Str.12 (#Attr.2):
|
||||
let Str.255 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
ret Str.255;
|
||||
|
||||
procedure Str.36 (#Attr.2):
|
||||
let Str.256 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||
let Str.256 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
ret Str.256;
|
||||
|
||||
procedure Str.36 (#Attr.2):
|
||||
let Str.257 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||
ret Str.257;
|
||||
|
||||
procedure Str.43 (#Attr.2):
|
||||
let Str.253 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||
ret Str.253;
|
||||
let Str.254 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||
ret Str.254;
|
||||
|
||||
procedure Str.9 (Str.73):
|
||||
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
||||
let Str.250 : Int1 = StructAtIndex 2 Str.74;
|
||||
if Str.250 then
|
||||
let Str.252 : Str = StructAtIndex 1 Str.74;
|
||||
let Str.251 : [C {U64, U8}, C Str] = TagId(1) Str.252;
|
||||
ret Str.251;
|
||||
let Str.251 : Int1 = StructAtIndex 2 Str.74;
|
||||
if Str.251 then
|
||||
let Str.253 : Str = StructAtIndex 1 Str.74;
|
||||
let Str.252 : [C {U64, U8}, C Str] = TagId(1) Str.253;
|
||||
ret Str.252;
|
||||
else
|
||||
let Str.248 : U8 = StructAtIndex 3 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;
|
||||
dec #Derived_gen.3;
|
||||
let Str.247 : {U64, U8} = Struct {Str.249, Str.248};
|
||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.247;
|
||||
let Str.248 : {U64, U8} = Struct {Str.249, Str.250};
|
||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.248;
|
||||
ret Str.246;
|
||||
|
||||
procedure Test.20 (Test.56):
|
||||
|
|
|
@ -110,31 +110,31 @@ procedure Num.96 (#Attr.2):
|
|||
ret Num.283;
|
||||
|
||||
procedure Str.12 (#Attr.2):
|
||||
let Str.255 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
ret Str.255;
|
||||
|
||||
procedure Str.36 (#Attr.2):
|
||||
let Str.256 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||
let Str.256 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
ret Str.256;
|
||||
|
||||
procedure Str.36 (#Attr.2):
|
||||
let Str.257 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||
ret Str.257;
|
||||
|
||||
procedure Str.43 (#Attr.2):
|
||||
let Str.253 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||
ret Str.253;
|
||||
let Str.254 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||
ret Str.254;
|
||||
|
||||
procedure Str.9 (Str.73):
|
||||
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
||||
let Str.250 : Int1 = StructAtIndex 2 Str.74;
|
||||
if Str.250 then
|
||||
let Str.252 : Str = StructAtIndex 1 Str.74;
|
||||
let Str.251 : [C {U64, U8}, C Str] = TagId(1) Str.252;
|
||||
ret Str.251;
|
||||
let Str.251 : Int1 = StructAtIndex 2 Str.74;
|
||||
if Str.251 then
|
||||
let Str.253 : Str = StructAtIndex 1 Str.74;
|
||||
let Str.252 : [C {U64, U8}, C Str] = TagId(1) Str.253;
|
||||
ret Str.252;
|
||||
else
|
||||
let Str.248 : U8 = StructAtIndex 3 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;
|
||||
dec #Derived_gen.27;
|
||||
let Str.247 : {U64, U8} = Struct {Str.249, Str.248};
|
||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.247;
|
||||
let Str.248 : {U64, U8} = Struct {Str.249, Str.250};
|
||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.248;
|
||||
ret Str.246;
|
||||
|
||||
procedure Test.20 (Test.56):
|
||||
|
|
|
@ -113,31 +113,31 @@ procedure Num.96 (#Attr.2):
|
|||
ret Num.283;
|
||||
|
||||
procedure Str.12 (#Attr.2):
|
||||
let Str.255 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
ret Str.255;
|
||||
|
||||
procedure Str.36 (#Attr.2):
|
||||
let Str.256 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||
let Str.256 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
ret Str.256;
|
||||
|
||||
procedure Str.36 (#Attr.2):
|
||||
let Str.257 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
|
||||
ret Str.257;
|
||||
|
||||
procedure Str.43 (#Attr.2):
|
||||
let Str.253 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||
ret Str.253;
|
||||
let Str.254 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||
ret Str.254;
|
||||
|
||||
procedure Str.9 (Str.73):
|
||||
let Str.74 : {U64, Str, Int1, U8} = CallByName Str.43 Str.73;
|
||||
let Str.250 : Int1 = StructAtIndex 2 Str.74;
|
||||
if Str.250 then
|
||||
let Str.252 : Str = StructAtIndex 1 Str.74;
|
||||
let Str.251 : [C {U64, U8}, C Str] = TagId(1) Str.252;
|
||||
ret Str.251;
|
||||
let Str.251 : Int1 = StructAtIndex 2 Str.74;
|
||||
if Str.251 then
|
||||
let Str.253 : Str = StructAtIndex 1 Str.74;
|
||||
let Str.252 : [C {U64, U8}, C Str] = TagId(1) Str.253;
|
||||
ret Str.252;
|
||||
else
|
||||
let Str.248 : U8 = StructAtIndex 3 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;
|
||||
dec #Derived_gen.28;
|
||||
let Str.247 : {U64, U8} = Struct {Str.249, Str.248};
|
||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.247;
|
||||
let Str.248 : {U64, U8} = Struct {Str.249, Str.250};
|
||||
let Str.246 : [C {U64, U8}, C Str] = TagId(0) Str.248;
|
||||
ret Str.246;
|
||||
|
||||
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",
|
||||
),
|
||||
derived: Some(
|
||||
@18-20 SpaceBefore(
|
||||
Implements(
|
||||
[],
|
||||
),
|
||||
[
|
||||
ImplementsAbilities {
|
||||
before_implements_kw: [
|
||||
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(
|
||||
@19-29 Implements(
|
||||
[
|
||||
ImplementsAbilities {
|
||||
before_implements_kw: [],
|
||||
implements: @8-18,
|
||||
after_implements_kw: [],
|
||||
item: @19-29 [
|
||||
@20-22 ImplementsAbility {
|
||||
ability: @20-22 Apply(
|
||||
"",
|
||||
|
@ -100,7 +103,7 @@
|
|||
impls: None,
|
||||
},
|
||||
],
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
Opaque {
|
||||
|
@ -126,8 +129,11 @@
|
|||
],
|
||||
),
|
||||
derived: Some(
|
||||
@74-84 Implements(
|
||||
[
|
||||
ImplementsAbilities {
|
||||
before_implements_kw: [],
|
||||
implements: @63-73,
|
||||
after_implements_kw: [],
|
||||
item: @74-84 [
|
||||
@75-77 ImplementsAbility {
|
||||
ability: @75-77 Apply(
|
||||
"",
|
||||
|
@ -145,7 +151,7 @@
|
|||
impls: None,
|
||||
},
|
||||
],
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
Opaque {
|
||||
|
@ -171,9 +177,13 @@
|
|||
],
|
||||
),
|
||||
derived: Some(
|
||||
@134-144 SpaceBefore(
|
||||
Implements(
|
||||
[
|
||||
ImplementsAbilities {
|
||||
before_implements_kw: [
|
||||
Newline,
|
||||
],
|
||||
implements: @123-133,
|
||||
after_implements_kw: [],
|
||||
item: @134-144 [
|
||||
@135-137 ImplementsAbility {
|
||||
ability: @135-137 Apply(
|
||||
"",
|
||||
|
@ -191,11 +201,7 @@
|
|||
impls: None,
|
||||
},
|
||||
],
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
Opaque {
|
||||
|
@ -209,8 +215,11 @@
|
|||
[],
|
||||
),
|
||||
derived: Some(
|
||||
@165-187 Implements(
|
||||
[
|
||||
ImplementsAbilities {
|
||||
before_implements_kw: [],
|
||||
implements: @154-164,
|
||||
after_implements_kw: [],
|
||||
item: @165-187 [
|
||||
@166-173 ImplementsAbility {
|
||||
ability: @166-168 Apply(
|
||||
"",
|
||||
|
@ -244,7 +253,7 @@
|
|||
),
|
||||
},
|
||||
],
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
Opaque {
|
||||
|
@ -258,8 +267,11 @@
|
|||
[],
|
||||
),
|
||||
derived: Some(
|
||||
@208-222 Implements(
|
||||
[
|
||||
ImplementsAbilities {
|
||||
before_implements_kw: [],
|
||||
implements: @197-207,
|
||||
after_implements_kw: [],
|
||||
item: @208-222 [
|
||||
@209-221 ImplementsAbility {
|
||||
ability: @209-211 Apply(
|
||||
"",
|
||||
|
@ -280,7 +292,7 @@
|
|||
),
|
||||
},
|
||||
],
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
Opaque {
|
||||
|
@ -294,8 +306,11 @@
|
|||
[],
|
||||
),
|
||||
derived: Some(
|
||||
@243-263 Implements(
|
||||
[
|
||||
ImplementsAbilities {
|
||||
before_implements_kw: [],
|
||||
implements: @232-242,
|
||||
after_implements_kw: [],
|
||||
item: @243-263 [
|
||||
@244-256 ImplementsAbility {
|
||||
ability: @244-246 Apply(
|
||||
"",
|
||||
|
@ -324,7 +339,7 @@
|
|||
impls: None,
|
||||
},
|
||||
],
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
Opaque {
|
||||
|
@ -338,8 +353,11 @@
|
|||
[],
|
||||
),
|
||||
derived: Some(
|
||||
@284-304 Implements(
|
||||
[
|
||||
ImplementsAbilities {
|
||||
before_implements_kw: [],
|
||||
implements: @273-283,
|
||||
after_implements_kw: [],
|
||||
item: @284-304 [
|
||||
@285-289 ImplementsAbility {
|
||||
ability: @285-289 Apply(
|
||||
"",
|
||||
|
@ -368,7 +386,7 @@
|
|||
),
|
||||
},
|
||||
],
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
Opaque {
|
||||
|
@ -382,9 +400,12 @@
|
|||
[],
|
||||
),
|
||||
derived: Some(
|
||||
@325-327 Implements(
|
||||
[],
|
||||
),
|
||||
ImplementsAbilities {
|
||||
before_implements_kw: [],
|
||||
implements: @314-324,
|
||||
after_implements_kw: [],
|
||||
item: @325-327 [],
|
||||
},
|
||||
),
|
||||
},
|
||||
Opaque {
|
||||
|
@ -410,9 +431,13 @@
|
|||
],
|
||||
),
|
||||
derived: Some(
|
||||
@377-399 SpaceBefore(
|
||||
Implements(
|
||||
[
|
||||
ImplementsAbilities {
|
||||
before_implements_kw: [
|
||||
Newline,
|
||||
],
|
||||
implements: @366-376,
|
||||
after_implements_kw: [],
|
||||
item: @377-399 [
|
||||
@378-385 ImplementsAbility {
|
||||
ability: @378-380 Apply(
|
||||
"",
|
||||
|
@ -446,11 +471,7 @@
|
|||
),
|
||||
},
|
||||
],
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
Opaque {
|
||||
|
@ -464,8 +485,11 @@
|
|||
[],
|
||||
),
|
||||
derived: Some(
|
||||
@420-427 Implements(
|
||||
[
|
||||
ImplementsAbilities {
|
||||
before_implements_kw: [],
|
||||
implements: @409-419,
|
||||
after_implements_kw: [],
|
||||
item: @420-427 [
|
||||
@421-426 ImplementsAbility {
|
||||
ability: @421-423 Apply(
|
||||
"",
|
||||
|
@ -479,7 +503,7 @@
|
|||
),
|
||||
},
|
||||
],
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
|
|
|
@ -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_open_union.expr,
|
||||
pass/ann_parens_comments.expr,
|
||||
pass/ann_parens_where_implements_func.expr,
|
||||
pass/ann_pattern_comment_before_body.expr,
|
||||
pass/ann_record_pat_with_comment.expr,
|
||||
pass/ann_tag_union_newline_comment.expr,
|
||||
|
@ -552,6 +553,7 @@ mod test_snapshots {
|
|||
pass/newline_after_sub.expr,
|
||||
pass/newline_and_spaces_before_less_than.expr,
|
||||
pass/newline_before_add.expr,
|
||||
pass/newline_before_and_after_implements_opaque.expr,
|
||||
pass/newline_before_import_curlies.expr,
|
||||
pass/newline_before_sub.expr,
|
||||
pass/newline_in_packages.full,
|
||||
|
@ -666,6 +668,7 @@ mod test_snapshots {
|
|||
pass/return_multiline.expr,
|
||||
pass/return_only_statement.expr,
|
||||
pass/return_parens_comments.expr,
|
||||
pass/return_record_update_comment_empty_fields.expr,
|
||||
pass/return_then_nested_parens.expr,
|
||||
pass/return_with_after.expr,
|
||||
pass/separate_defs.moduledefs,
|
||||
|
|
|
@ -535,12 +535,7 @@ impl IterTokens for Loc<ImplementsAbilities<'_>> {
|
|||
|
||||
impl IterTokens for ImplementsAbilities<'_> {
|
||||
fn iter_tokens<'a>(&self, arena: &'a Bump) -> BumpVec<'a, Loc<Token>> {
|
||||
match self {
|
||||
ImplementsAbilities::Implements(impls) => impls.iter_tokens(arena),
|
||||
ImplementsAbilities::SpaceBefore(i, _) | ImplementsAbilities::SpaceAfter(i, _) => {
|
||||
i.iter_tokens(arena)
|
||||
}
|
||||
}
|
||||
self.item.value.iter_tokens(arena)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1321,59 +1321,9 @@ fn surgery_macho_help(
|
|||
continue;
|
||||
} 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.
|
||||
// TODO have a table of all known symbols; perhaps parse and use an Apple provided libSystem.tbd stub file?
|
||||
let name = app_obj
|
||||
.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
|
||||
),
|
||||
}
|
||||
// Explicitly ignore `longjmp` and `setjmp` which are used only in `roc test` mode and thus are unreferenced
|
||||
// by the app and can be safely skipped.
|
||||
// In the future, `longjmp` and `setjmp` will be obsoleted and thus this prong can be safely deleted.
|
||||
continue;
|
||||
} else {
|
||||
internal_error!(
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
xorg.libXi
|
||||
xorg.libxcb
|
||||
cargo-llvm-cov # to visualize code coverage
|
||||
|
||||
];
|
||||
|
||||
# DevInputs are not necessary to build roc as a user
|
||||
|
@ -75,6 +76,8 @@
|
|||
cmake
|
||||
# provides llvm
|
||||
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
|
||||
# provides lld
|
||||
pkgs.lld_18
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue