From 0786e554c622ed0a2a99b71b77ca1b9675adaa0e Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Mon, 13 Dec 2021 17:13:46 -0800 Subject: [PATCH] Extract spacing from parse::header::* items into explicit Spaced enum --- cli/src/format.rs | 60 ++--- compiler/fmt/src/annotation.rs | 2 +- compiler/fmt/src/module.rs | 188 ++++++-------- compiler/load/src/file.rs | 237 +++++++----------- compiler/parse/src/ast.rs | 116 +++++++-- compiler/parse/src/header.rs | 156 ++++-------- compiler/parse/src/module.rs | 67 ++--- .../empty_platform_header.header.result-ast | 2 +- .../pass/full_app_header.header.result-ast | 4 +- ...p_header_trailing_commas.header.result-ast | 8 +- ...nonempty_platform_header.header.result-ast | 8 +- 11 files changed, 378 insertions(+), 470 deletions(-) diff --git a/cli/src/format.rs b/cli/src/format.rs index 5f4424b066..c6440a241e 100644 --- a/cli/src/format.rs +++ b/cli/src/format.rs @@ -7,11 +7,11 @@ use roc_fmt::module::fmt_module; use roc_fmt::Buf; use roc_module::called_via::{BinOp, UnaryOp}; use roc_parse::ast::{ - AssignedField, Collection, Expr, Pattern, StrLiteral, StrSegment, Tag, TypeAnnotation, + AssignedField, Collection, Expr, Pattern, Spaced, StrLiteral, StrSegment, Tag, TypeAnnotation, WhenBranch, }; use roc_parse::header::{ - AppHeader, Effects, ExposesEntry, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry, + AppHeader, Effects, ExposedName, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry, PackageName, PackageOrPath, PlatformHeader, PlatformRequires, PlatformRigid, To, TypedIdent, }; use roc_parse::{ @@ -228,16 +228,22 @@ impl<'a> RemoveSpaces<'a> for &'a str { } } -impl<'a, T: RemoveSpaces<'a> + Copy> RemoveSpaces<'a> for ExposesEntry<'a, T> { +impl<'a, T: RemoveSpaces<'a> + Copy> RemoveSpaces<'a> for Spaced<'a, T> { fn remove_spaces(&self, arena: &'a Bump) -> Self { match *self { - ExposesEntry::Exposed(a) => ExposesEntry::Exposed(a.remove_spaces(arena)), - ExposesEntry::SpaceBefore(a, _) => a.remove_spaces(arena), - ExposesEntry::SpaceAfter(a, _) => a.remove_spaces(arena), + Spaced::Item(a) => Spaced::Item(a.remove_spaces(arena)), + Spaced::SpaceBefore(a, _) => a.remove_spaces(arena), + Spaced::SpaceAfter(a, _) => a.remove_spaces(arena), } } } +impl<'a> RemoveSpaces<'a> for ExposedName<'a> { + fn remove_spaces(&self, _arena: &'a Bump) -> Self { + *self + } +} + impl<'a> RemoveSpaces<'a> for ModuleName<'a> { fn remove_spaces(&self, _arena: &'a Bump) -> Self { *self @@ -261,18 +267,10 @@ impl<'a> RemoveSpaces<'a> for To<'a> { impl<'a> RemoveSpaces<'a> for TypedIdent<'a> { fn remove_spaces(&self, arena: &'a Bump) -> Self { - match *self { - TypedIdent::Entry { - ident, - spaces_before_colon: _, - ann, - } => TypedIdent::Entry { - ident: ident.remove_spaces(arena), - spaces_before_colon: &[], - ann: ann.remove_spaces(arena), - }, - TypedIdent::SpaceBefore(a, _) => a.remove_spaces(arena), - TypedIdent::SpaceAfter(a, _) => a.remove_spaces(arena), + TypedIdent { + ident: self.ident.remove_spaces(arena), + spaces_before_colon: &[], + ann: self.ann.remove_spaces(arena), } } } @@ -287,29 +285,17 @@ impl<'a> RemoveSpaces<'a> for PlatformRequires<'a> { } impl<'a> RemoveSpaces<'a> for PlatformRigid<'a> { - fn remove_spaces(&self, arena: &'a Bump) -> Self { - match *self { - PlatformRigid::Entry { rigid, alias } => PlatformRigid::Entry { rigid, alias }, - PlatformRigid::SpaceBefore(a, _) => a.remove_spaces(arena), - PlatformRigid::SpaceAfter(a, _) => a.remove_spaces(arena), - } + fn remove_spaces(&self, _arena: &'a Bump) -> Self { + *self } } impl<'a> RemoveSpaces<'a> for PackageEntry<'a> { fn remove_spaces(&self, arena: &'a Bump) -> Self { - match *self { - PackageEntry::Entry { - shorthand, - spaces_after_shorthand: _, - package_or_path, - } => PackageEntry::Entry { - shorthand, - spaces_after_shorthand: &[], - package_or_path: package_or_path.remove_spaces(arena), - }, - PackageEntry::SpaceBefore(a, _) => a.remove_spaces(arena), - PackageEntry::SpaceAfter(a, _) => a.remove_spaces(arena), + PackageEntry { + shorthand: self.shorthand, + spaces_after_shorthand: &[], + package_or_path: self.package_or_path.remove_spaces(arena), } } } @@ -328,8 +314,6 @@ impl<'a> RemoveSpaces<'a> for ImportsEntry<'a> { match *self { ImportsEntry::Module(a, b) => ImportsEntry::Module(a, b.remove_spaces(arena)), ImportsEntry::Package(a, b, c) => ImportsEntry::Package(a, b, c.remove_spaces(arena)), - ImportsEntry::SpaceBefore(a, _) => a.remove_spaces(arena), - ImportsEntry::SpaceAfter(a, _) => a.remove_spaces(arena), } } } diff --git a/compiler/fmt/src/annotation.rs b/compiler/fmt/src/annotation.rs index 314c97c222..6afe608110 100644 --- a/compiler/fmt/src/annotation.rs +++ b/compiler/fmt/src/annotation.rs @@ -83,7 +83,7 @@ where } /// A Located formattable value is also formattable -impl<'a, T> Formattable for Located +impl Formattable for Located where T: Formattable, { diff --git a/compiler/fmt/src/module.rs b/compiler/fmt/src/module.rs index b99b772249..a8595032a4 100644 --- a/compiler/fmt/src/module.rs +++ b/compiler/fmt/src/module.rs @@ -3,9 +3,9 @@ use crate::collection::fmt_collection; use crate::expr::fmt_str_literal; use crate::spaces::{fmt_default_spaces, fmt_spaces, INDENT}; use crate::Buf; -use roc_parse::ast::{Collection, Module}; +use roc_parse::ast::{Collection, Module, Spaced}; use roc_parse::header::{ - AppHeader, Effects, ExposesEntry, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry, + AppHeader, Effects, ExposedName, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry, PackageName, PackageOrPath, PlatformHeader, PlatformRequires, PlatformRigid, To, TypedIdent, }; use roc_region::all::Located; @@ -135,7 +135,7 @@ fn fmt_requires<'a, 'buf>(buf: &mut Buf<'buf>, requires: &PlatformRequires<'a>, fmt_collection(buf, indent, '{', '}', requires.rigids, Newlines::No); buf.push_str(" { "); - fmt_typed_ident(buf, &requires.signature.value, indent); + requires.signature.value.format(buf, indent); buf.push_str(" }"); } @@ -155,48 +155,17 @@ fn fmt_effects<'a, 'buf>(buf: &mut Buf<'buf>, effects: &Effects<'a>, indent: u16 fmt_collection(buf, indent, '{', '}', effects.entries, Newlines::No) } -fn fmt_typed_ident<'a, 'buf>(buf: &mut Buf<'buf>, entry: &TypedIdent<'a>, indent: u16) { - use TypedIdent::*; - match entry { - Entry { - ident, - spaces_before_colon, - ann, - } => { - buf.indent(indent); - buf.push_str(ident.value); - fmt_default_spaces(buf, spaces_before_colon, " ", indent); - buf.push_str(": "); - ann.value.format(buf, indent); - } - SpaceBefore(sub_entry, spaces) => { - fmt_spaces(buf, spaces.iter(), indent); - fmt_typed_ident(buf, sub_entry, indent); - } - SpaceAfter(sub_entry, spaces) => { - fmt_typed_ident(buf, sub_entry, indent); - fmt_spaces(buf, spaces.iter(), indent); - } - } -} - impl<'a> Formattable for TypedIdent<'a> { fn is_multiline(&self) -> bool { false } fn format<'buf>(&self, buf: &mut Buf<'buf>, indent: u16) { - fmt_typed_ident(buf, self, indent); - } -} - -impl<'a> Formattable for PlatformRigid<'a> { - fn is_multiline(&self) -> bool { - false - } - - fn format<'buf>(&self, buf: &mut Buf<'buf>, indent: u16) { - fmt_platform_rigid(buf, self, indent); + buf.indent(indent); + buf.push_str(self.ident.value); + fmt_default_spaces(buf, self.spaces_before_colon, " ", indent); + buf.push_str(": "); + self.ann.value.format(buf, indent); } } @@ -206,30 +175,50 @@ fn fmt_package_name<'buf>(buf: &mut Buf<'buf>, name: PackageName) { buf.push_str(name.pkg); } -fn fmt_platform_rigid<'a, 'buf>(buf: &mut Buf<'buf>, entry: &PlatformRigid<'a>, indent: u16) { - use roc_parse::header::PlatformRigid::*; +impl<'a, T: Formattable> Formattable for Spaced<'a, T> { + fn is_multiline(&self) -> bool { + // TODO + false + } - match entry { - Entry { rigid, alias } => { - buf.push_str(rigid); - buf.push_str("=>"); - buf.push_str(alias); + fn format_with_options<'buf>( + &self, + buf: &mut Buf<'buf>, + parens: crate::annotation::Parens, + newlines: Newlines, + indent: u16, + ) { + match self { + Spaced::Item(item) => { + item.format_with_options(buf, parens, newlines, indent); + } + Spaced::SpaceBefore(item, spaces) => { + fmt_spaces(buf, spaces.iter(), indent); + item.format_with_options(buf, parens, newlines, indent); + } + Spaced::SpaceAfter(item, spaces) => { + item.format_with_options(buf, parens, newlines, indent); + fmt_spaces(buf, spaces.iter(), indent); + } } + } +} - SpaceBefore(sub_entry, spaces) => { - fmt_spaces(buf, spaces.iter(), indent); - fmt_platform_rigid(buf, sub_entry, indent); - } - SpaceAfter(sub_entry, spaces) => { - fmt_platform_rigid(buf, sub_entry, indent); - fmt_spaces(buf, spaces.iter(), indent); - } +impl<'a> Formattable for PlatformRigid<'a> { + fn is_multiline(&self) -> bool { + false + } + + fn format<'buf>(&self, buf: &mut Buf<'buf>, _indent: u16) { + buf.push_str(self.rigid); + buf.push_str("=>"); + buf.push_str(self.alias); } } fn fmt_imports<'a, 'buf>( buf: &mut Buf<'buf>, - loc_entries: Collection<'a, Located>>, + loc_entries: Collection<'a, Located>>>, indent: u16, ) { fmt_collection(buf, indent, '[', ']', loc_entries, Newlines::No) @@ -237,7 +226,7 @@ fn fmt_imports<'a, 'buf>( fn fmt_provides<'a, 'buf>( buf: &mut Buf<'buf>, - loc_entries: Collection<'a, Located>>, + loc_entries: Collection<'a, Located>>>, indent: u16, ) { fmt_collection(buf, indent, '[', ']', loc_entries, Newlines::No) @@ -252,24 +241,14 @@ fn fmt_to<'buf>(buf: &mut Buf<'buf>, to: To, indent: u16) { } } -fn fmt_exposes<'a, 'buf, N: FormatName + Copy + 'a>( +fn fmt_exposes<'buf, N: Formattable + Copy>( buf: &mut Buf<'buf>, - loc_entries: Collection<'_, Located>>, + loc_entries: Collection<'_, Located>>, indent: u16, ) { fmt_collection(buf, indent, '[', ']', loc_entries, Newlines::No) } -impl<'a, N: FormatName> Formattable for ExposesEntry<'a, N> { - fn is_multiline(&self) -> bool { - false - } - - fn format<'buf>(&self, buf: &mut Buf<'buf>, indent: u16) { - fmt_exposes_entry(buf, self, indent); - } -} - pub trait FormatName { fn format<'buf>(&self, buf: &mut Buf<'buf>); } @@ -286,30 +265,35 @@ impl<'a> FormatName for ModuleName<'a> { } } -fn fmt_exposes_entry<'a, 'buf, N: FormatName>( - buf: &mut Buf<'buf>, - entry: &ExposesEntry<'a, N>, - indent: u16, -) { - use roc_parse::header::ExposesEntry::*; +impl<'a> Formattable for ModuleName<'a> { + fn is_multiline(&self) -> bool { + false + } - match entry { - Exposed(ident) => ident.format(buf), + fn format<'buf>(&self, buf: &mut Buf<'buf>, _indent: u16) { + buf.push_str(self.as_str()); + } +} - SpaceBefore(sub_entry, spaces) => { - fmt_spaces(buf, spaces.iter(), indent); - fmt_exposes_entry(buf, sub_entry, indent); - } - SpaceAfter(sub_entry, spaces) => { - fmt_exposes_entry(buf, sub_entry, indent); - fmt_spaces(buf, spaces.iter(), indent); - } +impl<'a> Formattable for ExposedName<'a> { + fn is_multiline(&self) -> bool { + false + } + + fn format<'buf>(&self, buf: &mut Buf<'buf>, _indent: u16) { + buf.push_str(self.as_str()); + } +} + +impl<'a> FormatName for ExposedName<'a> { + fn format<'buf>(&self, buf: &mut Buf<'buf>) { + buf.push_str(self.as_str()); } } fn fmt_packages<'a, 'buf>( buf: &mut Buf<'buf>, - loc_entries: Collection<'a, Located>>, + loc_entries: Collection<'a, Located>>>, indent: u16, ) { fmt_collection(buf, indent, '{', '}', loc_entries, Newlines::No) @@ -335,27 +319,10 @@ impl<'a> Formattable for ImportsEntry<'a> { } } fn fmt_packages_entry<'a, 'buf>(buf: &mut Buf<'buf>, entry: &PackageEntry<'a>, indent: u16) { - use PackageEntry::*; - match entry { - Entry { - shorthand, - spaces_after_shorthand, - package_or_path, - } => { - buf.push_str(shorthand); - buf.push(':'); - fmt_default_spaces(buf, spaces_after_shorthand, " ", indent); - fmt_package_or_path(buf, &package_or_path.value, indent); - } - SpaceBefore(sub_entry, spaces) => { - fmt_spaces(buf, spaces.iter(), indent); - fmt_packages_entry(buf, sub_entry, indent); - } - SpaceAfter(sub_entry, spaces) => { - fmt_packages_entry(buf, sub_entry, indent); - fmt_spaces(buf, spaces.iter(), indent); - } - } + buf.push_str(entry.shorthand); + buf.push(':'); + fmt_default_spaces(buf, entry.spaces_after_shorthand, " ", indent); + fmt_package_or_path(buf, &entry.package_or_path.value, indent); } fn fmt_package_or_path<'a, 'buf>( @@ -396,14 +363,5 @@ fn fmt_imports_entry<'a, 'buf>(buf: &mut Buf<'buf>, entry: &ImportsEntry<'a>, in fmt_collection(buf, indent, '{', '}', *entries, Newlines::No) } } - - SpaceBefore(sub_entry, spaces) => { - fmt_spaces(buf, spaces.iter(), indent); - fmt_imports_entry(buf, sub_entry, indent); - } - SpaceAfter(sub_entry, spaces) => { - fmt_imports_entry(buf, sub_entry, indent); - fmt_spaces(buf, spaces.iter(), indent); - } } } diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index a1279fdfab..e056790377 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -23,14 +23,13 @@ use roc_mono::ir::{ UpdateModeIds, }; use roc_mono::layout::{Layout, LayoutCache, LayoutProblem}; -use roc_parse::ast::{self, ExtractSpaces, StrLiteral, TypeAnnotation}; +use roc_parse::ast::{self, ExtractSpaces, Spaced, StrLiteral, TypeAnnotation}; use roc_parse::header::{ - ExposesEntry, ImportsEntry, PackageEntry, PackageOrPath, PlatformHeader, To, TypedIdent, + ExposedName, ImportsEntry, PackageEntry, PackageOrPath, PlatformHeader, To, TypedIdent, }; use roc_parse::module::module_defs; use roc_parse::parser::{self, ParseProblem, Parser, SyntaxError}; use roc_region::all::{Located, Region}; -use roc_reporting::internal_error; use roc_solve::module::SolvedModule; use roc_solve::solve; use roc_types::solved_types::Solved; @@ -2603,62 +2602,57 @@ fn parse_header<'a>( match header.to.value { To::ExistingPackage(existing_package) => { - let opt_base_package = packages.iter().find(|loc_package_entry| { + let opt_base_package = packages.iter().find_map(|loc_package_entry| { let Located { value, .. } = loc_package_entry; - match value.extract_spaces().item { - PackageEntry::Entry { shorthand, .. } => shorthand == existing_package, - _ => internal_error!(), + let item = value.extract_spaces().item; + if item.shorthand == existing_package { + Some(item) + } else { + None } }); - match opt_base_package { - Some(Located { - value: - PackageEntry::Entry { - shorthand, - package_or_path: - Located { - value: package_or_path, - .. - }, - .. - }, - .. - }) => { - match package_or_path { - PackageOrPath::Path(StrLiteral::PlainLine(package)) => { - // check whether we can find a Package-Config.roc file - let mut pkg_config_roc = pkg_config_dir; - pkg_config_roc.push(package); - pkg_config_roc.push(PKG_CONFIG_FILE_NAME); - pkg_config_roc.set_extension(ROC_FILE_EXTENSION); + if let Some(PackageEntry { + shorthand, + package_or_path: + Located { + value: package_or_path, + .. + }, + .. + }) = opt_base_package + { + match package_or_path { + PackageOrPath::Path(StrLiteral::PlainLine(package)) => { + // check whether we can find a Package-Config.roc file + let mut pkg_config_roc = pkg_config_dir; + pkg_config_roc.push(package); + pkg_config_roc.push(PKG_CONFIG_FILE_NAME); + pkg_config_roc.set_extension(ROC_FILE_EXTENSION); - if pkg_config_roc.as_path().exists() { - let load_pkg_config_msg = load_pkg_config( - arena, - &pkg_config_roc, - shorthand, - module_id, - module_ids, - ident_ids_by_module, - )?; + if pkg_config_roc.as_path().exists() { + let load_pkg_config_msg = load_pkg_config( + arena, + &pkg_config_roc, + shorthand, + module_id, + module_ids, + ident_ids_by_module, + )?; - Ok(( - module_id, - Msg::Many(vec![ - app_module_header_msg, - load_pkg_config_msg, - ]), - )) - } else { - Ok((module_id, app_module_header_msg)) - } + Ok(( + module_id, + Msg::Many(vec![app_module_header_msg, load_pkg_config_msg]), + )) + } else { + Ok((module_id, app_module_header_msg)) } - _ => unreachable!(), } + _ => unreachable!(), } - _ => panic!("could not find base"), + } else { + panic!("could not find base") } } To::NewPackage(package_or_path) => match package_or_path { @@ -2765,9 +2759,9 @@ struct HeaderInfo<'a> { is_root_module: bool, opt_shorthand: Option<&'a str>, header_src: &'a str, - packages: &'a [Located>], - exposes: &'a [Located>], - imports: &'a [Located>], + packages: &'a [Located>>], + exposes: &'a [Located>>], + imports: &'a [Located>>], to_platform: Option>, } @@ -2900,7 +2894,8 @@ fn send_header<'a>( // For example, if module A has [ B.{ foo } ], then // when we get here for B, `foo` will already have // an IdentId. We must reuse that! - let ident_id = ident_ids.get_or_insert(&loc_exposed.value.as_str().into()); + let ident_id = + ident_ids.get_or_insert(&loc_exposed.value.extract_spaces().item.as_str().into()); let symbol = Symbol::new(home, ident_id); exposed.push(symbol); @@ -2913,24 +2908,13 @@ fn send_header<'a>( ident_ids.clone() }; - let mut parse_entries: Vec<_> = packages.iter().map(|x| &x.value).collect(); - let mut package_entries = MutMap::default(); - - while let Some(parse_entry) = parse_entries.pop() { - use PackageEntry::*; - match parse_entry { - Entry { - shorthand, - package_or_path, - .. - } => { - package_entries.insert(*shorthand, package_or_path.value); - } - SpaceBefore(inner, _) | SpaceAfter(inner, _) => { - parse_entries.push(inner); - } - } - } + let package_entries = packages + .iter() + .map(|pkg| { + let pkg = pkg.value.extract_spaces().item; + (pkg.shorthand, pkg.package_or_path.value) + }) + .collect::>(); // Send the deps to the coordinator thread for processing, // then continue on to parsing and canonicalizing defs. @@ -2989,15 +2973,14 @@ struct PlatformHeaderInfo<'a> { header_src: &'a str, app_module_id: ModuleId, packages: &'a [Located>], - provides: &'a [Located>], + provides: &'a [Located>>], requires: &'a [Located>], - imports: &'a [Located>], + imports: &'a [Located>>], } // TODO refactor so more logic is shared with `send_header` #[allow(clippy::too_many_arguments)] fn send_header_two<'a>( - arena: &'a Bump, info: PlatformHeaderInfo<'a>, parse_state: parser::State<'a>, module_ids: Arc>>, @@ -3105,15 +3088,17 @@ fn send_header_two<'a>( .entry(app_module_id) .or_insert_with(IdentIds::default); - for (loc_ident, _) in unpack_exposes_entries(arena, requires) { - let ident: Ident = loc_ident.value.into(); + for entry in requires { + let entry = entry.value; + + let ident: Ident = entry.ident.value.into(); let ident_id = ident_ids.get_or_insert(&ident); let symbol = Symbol::new(app_module_id, ident_id); // Since this value is exposed, add it to our module's default scope. debug_assert!(!scope.contains_key(&ident.clone())); - scope.insert(ident, (symbol, loc_ident.region)); + scope.insert(ident, (symbol, entry.ident.region)); } } @@ -3133,7 +3118,8 @@ fn send_header_two<'a>( // For example, if module A has [ B.{ foo } ], then // when we get here for B, `foo` will already have // an IdentId. We must reuse that! - let ident_id = ident_ids.get_or_insert(&loc_exposed.value.as_str().into()); + let ident_id = + ident_ids.get_or_insert(&loc_exposed.value.extract_spaces().item.as_str().into()); let symbol = Symbol::new(home, ident_id); exposed.push(symbol); @@ -3146,24 +3132,10 @@ fn send_header_two<'a>( ident_ids.clone() }; - let mut parse_entries: Vec<_> = packages.iter().map(|x| &x.value).collect(); - let mut package_entries = MutMap::default(); - - while let Some(parse_entry) = parse_entries.pop() { - use PackageEntry::*; - match parse_entry { - Entry { - shorthand, - package_or_path, - .. - } => { - package_entries.insert(*shorthand, package_or_path.value); - } - SpaceBefore(inner, _) | SpaceAfter(inner, _) => { - parse_entries.push(inner); - } - } - } + let package_entries = packages + .iter() + .map(|pkg| (pkg.value.shorthand, pkg.value.package_or_path.value)) + .collect::>(); // Send the deps to the coordinator thread for processing, // then continue on to parsing and canonicalizing defs. @@ -3174,7 +3146,7 @@ fn send_header_two<'a>( let module_name = ModuleNameEnum::PkgConfig; let main_for_host = { - let ident_str: Ident = provides[0].value.as_str().into(); + let ident_str: Ident = provides[0].value.extract_spaces().item.as_str().into(); let ident_id = ident_ids.get_or_insert(&ident_str); Symbol::new(home, ident_id) @@ -3355,7 +3327,7 @@ fn fabricate_pkg_config_module<'a>( header_src: &'a str, module_timing: ModuleTiming, ) -> (ModuleId, Msg<'a>) { - let provides: &'a [Located>] = header.provides.items; + let provides: &'a [Located>>] = header.provides.items; let info = PlatformHeaderInfo { filename, @@ -3365,12 +3337,14 @@ fn fabricate_pkg_config_module<'a>( app_module_id, packages: &[], provides, - requires: arena.alloc([header.requires.signature]), + requires: &*arena.alloc([Located::at( + header.requires.signature.region, + header.requires.signature.extract_spaces().item, + )]), imports: header.imports.items, }; send_header_two( - arena, info, parse_state, module_ids, @@ -3413,12 +3387,12 @@ fn fabricate_effects_module<'a>( let mut module_ids = (*module_ids).lock(); for exposed in header.exposes.iter() { - if let ExposesEntry::Exposed(module_name) = exposed.value { - module_ids.get_or_insert(&PQModuleName::Qualified( - shorthand, - module_name.as_str().into(), - )); - } + let module_name = exposed.value.extract_spaces().item; + + module_ids.get_or_insert(&PQModuleName::Qualified( + shorthand, + module_name.as_str().into(), + )); } } @@ -3633,33 +3607,16 @@ fn fabricate_effects_module<'a>( fn unpack_exposes_entries<'a>( arena: &'a Bump, - entries: &'a [Located>], -) -> bumpalo::collections::Vec<'a, (&'a Located<&'a str>, &'a Located>)> { + entries: &'a [Located>>], +) -> bumpalo::collections::Vec<'a, (Located<&'a str>, Located>)> { use bumpalo::collections::Vec; - let mut stack: Vec<&TypedIdent> = Vec::with_capacity_in(entries.len(), arena); - let mut output = Vec::with_capacity_in(entries.len(), arena); + let iter = entries.iter().map(|entry| { + let entry: TypedIdent<'a> = entry.value.extract_spaces().item; + (entry.ident, entry.ann) + }); - for entry in entries.iter() { - stack.push(&entry.value); - } - - while let Some(effects_entry) = stack.pop() { - match effects_entry { - TypedIdent::Entry { - ident, - spaces_before_colon: _, - ann, - } => { - output.push((ident, ann)); - } - TypedIdent::SpaceAfter(nested, _) | TypedIdent::SpaceBefore(nested, _) => { - stack.push(nested); - } - } - } - - output + Vec::from_iter_in(iter, arena) } #[allow(clippy::too_many_arguments)] @@ -3816,10 +3773,12 @@ fn parse<'a>(arena: &'a Bump, header: ModuleHeader<'a>) -> Result, Loadi Ok(Msg::Parsed(parsed)) } -fn exposed_from_import<'a>(entry: &ImportsEntry<'a>) -> (QualifiedModuleName<'a>, Vec) { +fn exposed_from_import<'a>( + entry: &Spaced<'a, ImportsEntry<'a>>, +) -> (QualifiedModuleName<'a>, Vec) { use roc_parse::header::ImportsEntry::*; - match entry { + match entry.extract_spaces().item { Module(module_name, exposes) => { let mut exposed = Vec::with_capacity(exposes.len()); @@ -3849,21 +3808,11 @@ fn exposed_from_import<'a>(entry: &ImportsEntry<'a>) -> (QualifiedModuleName<'a> (qualified_module_name, exposed) } - - SpaceBefore(sub_entry, _) | SpaceAfter(sub_entry, _) => { - // Ignore spaces. - exposed_from_import(*sub_entry) - } } } -fn ident_from_exposed(entry: &ExposesEntry<'_, &str>) -> Ident { - use roc_parse::header::ExposesEntry::*; - - match entry { - Exposed(ident) => (*ident).into(), - SpaceBefore(sub_entry, _) | SpaceAfter(sub_entry, _) => ident_from_exposed(sub_entry), - } +fn ident_from_exposed(entry: &Spaced<'_, ExposedName<'_>>) -> Ident { + entry.extract_spaces().item.as_str().into() } #[allow(clippy::too_many_arguments)] diff --git a/compiler/parse/src/ast.rs b/compiler/parse/src/ast.rs index 2cbba78d92..bf2ec390a8 100644 --- a/compiler/parse/src/ast.rs +++ b/compiler/parse/src/ast.rs @@ -1,9 +1,6 @@ use std::fmt::Debug; -use crate::header::{ - AppHeader, ExposesEntry, ImportsEntry, InterfaceHeader, PackageEntry, PlatformHeader, - PlatformRigid, TypedIdent, -}; +use crate::header::{AppHeader, InterfaceHeader, PlatformHeader}; use crate::ident::Ident; use bumpalo::collections::{String, Vec}; use bumpalo::Bump; @@ -17,6 +14,33 @@ pub struct Spaces<'a, T> { pub after: &'a [CommentOrNewline<'a>], } +#[derive(Copy, Clone, PartialEq)] +pub enum Spaced<'a, T> { + Item(T), + + // Spaces + SpaceBefore(&'a Spaced<'a, T>, &'a [CommentOrNewline<'a>]), + SpaceAfter(&'a Spaced<'a, T>, &'a [CommentOrNewline<'a>]), +} + +impl<'a, T: Debug> Debug for Spaced<'a, T> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Item(item) => item.fmt(f), + Self::SpaceBefore(item, space) => f + .debug_tuple("SpaceBefore") + .field(item) + .field(space) + .finish(), + Self::SpaceAfter(item, space) => f + .debug_tuple("SpaceAfter") + .field(item) + .field(space) + .finish(), + } + } +} + pub trait ExtractSpaces<'a>: Sized + Copy { type Item; fn extract_spaces(&self) -> Spaces<'a, Self::Item>; @@ -674,6 +698,15 @@ pub trait Spaceable<'a> { } } +impl<'a, T> Spaceable<'a> for Spaced<'a, T> { + fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { + Spaced::SpaceBefore(self, spaces) + } + fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { + Spaced::SpaceAfter(self, spaces) + } +} + impl<'a> Spaceable<'a> for Expr<'a> { fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { Expr::SpaceBefore(self, spaces) @@ -701,24 +734,6 @@ impl<'a> Spaceable<'a> for TypeAnnotation<'a> { } } -impl<'a> Spaceable<'a> for ImportsEntry<'a> { - fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - ImportsEntry::SpaceBefore(self, spaces) - } - fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - ImportsEntry::SpaceAfter(self, spaces) - } -} - -impl<'a> Spaceable<'a> for TypedIdent<'a> { - fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - TypedIdent::SpaceBefore(self, spaces) - } - fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - TypedIdent::SpaceAfter(self, spaces) - } -} - impl<'a, Val> Spaceable<'a> for AssignedField<'a, Val> { fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { AssignedField::SpaceBefore(self, spaces) @@ -823,8 +838,55 @@ macro_rules! impl_extract_spaces { impl_extract_spaces!(Expr); impl_extract_spaces!(Tag); impl_extract_spaces!(AssignedField); -impl_extract_spaces!(PlatformRigid); -impl_extract_spaces!(TypedIdent); -impl_extract_spaces!(ImportsEntry); -impl_extract_spaces!(ExposesEntry); -impl_extract_spaces!(PackageEntry); + +impl<'a, T: Copy> ExtractSpaces<'a> for Spaced<'a, T> { + type Item = T; + + fn extract_spaces(&self) -> Spaces<'a, T> { + match self { + Spaced::SpaceBefore(item, before) => match item { + Spaced::SpaceBefore(_, _) => todo!(), + Spaced::SpaceAfter(item, after) => { + if let Spaced::Item(item) = item { + Spaces { + before, + item: *item, + after, + } + } else { + todo!(); + } + } + Spaced::Item(item) => Spaces { + before, + item: *item, + after: &[], + }, + }, + Spaced::SpaceAfter(item, after) => match item { + Spaced::SpaceBefore(item, before) => { + if let Spaced::Item(item) = item { + Spaces { + before, + item: *item, + after, + } + } else { + todo!(); + } + } + Spaced::SpaceAfter(_, _) => todo!(), + Spaced::Item(item) => Spaces { + before: &[], + item: *item, + after, + }, + }, + Spaced::Item(item) => Spaces { + before: &[], + item: *item, + after: &[], + }, + } + } +} diff --git a/compiler/parse/src/header.rs b/compiler/parse/src/header.rs index 0c01805f9f..06e1c8b1e6 100644 --- a/compiler/parse/src/header.rs +++ b/compiler/parse/src/header.rs @@ -1,4 +1,4 @@ -use crate::ast::{Collection, CommentOrNewline, Spaceable, StrLiteral, TypeAnnotation}; +use crate::ast::{Collection, CommentOrNewline, Spaced, StrLiteral, TypeAnnotation}; use crate::blankspace::space0_e; use crate::ident::lowercase_ident; use crate::parser::Progress::{self, *}; @@ -57,11 +57,30 @@ impl<'a> ModuleName<'a> { } } +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +pub struct ExposedName<'a>(&'a str); + +impl<'a> From> for &'a str { + fn from(name: ExposedName<'a>) -> Self { + name.0 + } +} + +impl<'a> ExposedName<'a> { + pub fn new(name: &'a str) -> Self { + ExposedName(name) + } + + pub fn as_str(&'a self) -> &'a str { + self.0 + } +} + #[derive(Clone, Debug, PartialEq)] pub struct InterfaceHeader<'a> { pub name: Loc>, - pub exposes: Collection<'a, Loc>>, - pub imports: Collection<'a, Loc>>, + pub exposes: Collection<'a, Loc>>>, + pub imports: Collection<'a, Loc>>>, // Potential comments and newlines - these will typically all be empty. pub before_header: &'a [CommentOrNewline<'a>], @@ -81,9 +100,9 @@ pub enum To<'a> { #[derive(Clone, Debug, PartialEq)] pub struct AppHeader<'a> { pub name: Loc>, - pub packages: Collection<'a, Loc>>, - pub imports: Collection<'a, Loc>>, - pub provides: Collection<'a, Loc>>, + pub packages: Collection<'a, Loc>>>, + pub imports: Collection<'a, Loc>>>, + pub provides: Collection<'a, Loc>>>, pub to: Loc>, // Potential comments and newlines - these will typically all be empty. @@ -102,7 +121,7 @@ pub struct AppHeader<'a> { #[derive(Clone, Debug, PartialEq)] pub struct PackageHeader<'a> { pub name: Loc>, - pub exposes: Vec<'a, Loc>>, + pub exposes: Vec<'a, Loc>>>, pub packages: Vec<'a, (Loc<&'a str>, Loc>)>, pub imports: Vec<'a, Loc>>, @@ -118,37 +137,25 @@ pub struct PackageHeader<'a> { } #[derive(Copy, Clone, Debug, PartialEq)] -pub enum PlatformRigid<'a> { - Entry { rigid: &'a str, alias: &'a str }, - - // Spaces - SpaceBefore(&'a PlatformRigid<'a>, &'a [CommentOrNewline<'a>]), - SpaceAfter(&'a PlatformRigid<'a>, &'a [CommentOrNewline<'a>]), -} - -impl<'a> Spaceable<'a> for PlatformRigid<'a> { - fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - PlatformRigid::SpaceBefore(self, spaces) - } - fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - PlatformRigid::SpaceAfter(self, spaces) - } +pub struct PlatformRigid<'a> { + pub rigid: &'a str, + pub alias: &'a str, } #[derive(Clone, Debug, PartialEq)] pub struct PlatformRequires<'a> { - pub rigids: Collection<'a, Loc>>, - pub signature: Loc>, + pub rigids: Collection<'a, Loc>>>, + pub signature: Loc>>, } #[derive(Clone, Debug, PartialEq)] pub struct PlatformHeader<'a> { pub name: Loc>, pub requires: PlatformRequires<'a>, - pub exposes: Collection<'a, Loc>>>, - pub packages: Collection<'a, Loc>>, - pub imports: Collection<'a, Loc>>, - pub provides: Collection<'a, Loc>>, + pub exposes: Collection<'a, Loc>>>, + pub packages: Collection<'a, Loc>>>, + pub imports: Collection<'a, Loc>>>, + pub provides: Collection<'a, Loc>>>, pub effects: Effects<'a>, // Potential comments and newlines - these will typically all be empty. @@ -174,26 +181,7 @@ pub struct Effects<'a> { pub spaces_after_type_name: &'a [CommentOrNewline<'a>], pub effect_shortname: &'a str, pub effect_type_name: &'a str, - pub entries: Collection<'a, Loc>>, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum ExposesEntry<'a, T> { - /// e.g. `Task` - Exposed(T), - - // Spaces - SpaceBefore(&'a ExposesEntry<'a, T>, &'a [CommentOrNewline<'a>]), - SpaceAfter(&'a ExposesEntry<'a, T>, &'a [CommentOrNewline<'a>]), -} - -impl<'a, T> Spaceable<'a> for ExposesEntry<'a, T> { - fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - ExposesEntry::SpaceBefore(self, spaces) - } - fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - ExposesEntry::SpaceAfter(self, spaces) - } + pub entries: Collection<'a, Loc>>>, } #[derive(Copy, Clone, Debug, PartialEq)] @@ -201,71 +189,35 @@ pub enum ImportsEntry<'a> { /// e.g. `Task` or `Task.{ Task, after }` Module( ModuleName<'a>, - Collection<'a, Loc>>, + Collection<'a, Loc>>>, ), /// e.g. `pf.Task` or `pf.Task.{ after }` or `pf.{ Task.{ Task, after } }` Package( &'a str, ModuleName<'a>, - Collection<'a, Loc>>, + Collection<'a, Loc>>>, ), - - // Spaces - SpaceBefore(&'a ImportsEntry<'a>, &'a [CommentOrNewline<'a>]), - SpaceAfter(&'a ImportsEntry<'a>, &'a [CommentOrNewline<'a>]), } -impl<'a> ExposesEntry<'a, &'a str> { - pub fn as_str(&'a self) -> &'a str { - use ExposesEntry::*; - - match self { - Exposed(string) => string, - SpaceBefore(sub_entry, _) | SpaceAfter(sub_entry, _) => sub_entry.as_str(), - } - } +/// e.g. +/// +/// printLine : Str -> Effect {} +#[derive(Copy, Clone, Debug, PartialEq)] +pub struct TypedIdent<'a> { + pub ident: Loc<&'a str>, + pub spaces_before_colon: &'a [CommentOrNewline<'a>], + pub ann: Loc>, } #[derive(Copy, Clone, Debug, PartialEq)] -pub enum TypedIdent<'a> { - /// e.g. - /// - /// printLine : Str -> Effect {} - Entry { - ident: Loc<&'a str>, - spaces_before_colon: &'a [CommentOrNewline<'a>], - ann: Loc>, - }, - - // Spaces - SpaceBefore(&'a TypedIdent<'a>, &'a [CommentOrNewline<'a>]), - SpaceAfter(&'a TypedIdent<'a>, &'a [CommentOrNewline<'a>]), +pub struct PackageEntry<'a> { + pub shorthand: &'a str, + pub spaces_after_shorthand: &'a [CommentOrNewline<'a>], + pub package_or_path: Loc>, } -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum PackageEntry<'a> { - Entry { - shorthand: &'a str, - spaces_after_shorthand: &'a [CommentOrNewline<'a>], - package_or_path: Loc>, - }, - - // Spaces - SpaceBefore(&'a PackageEntry<'a>, &'a [CommentOrNewline<'a>]), - SpaceAfter(&'a PackageEntry<'a>, &'a [CommentOrNewline<'a>]), -} - -impl<'a> Spaceable<'a> for PackageEntry<'a> { - fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - PackageEntry::SpaceBefore(self, spaces) - } - fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - PackageEntry::SpaceAfter(self, spaces) - } -} - -pub fn package_entry<'a>() -> impl Parser<'a, PackageEntry<'a>, EPackageEntry<'a>> { +pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPackageEntry<'a>> { move |arena, state| { // You may optionally have a package shorthand, // e.g. "uc" in `uc: roc/unicode 1.0.0` @@ -293,19 +245,19 @@ pub fn package_entry<'a>() -> impl Parser<'a, PackageEntry<'a>, EPackageEntry<'a .parse(arena, state)?; let entry = match opt_shorthand { - Some((shorthand, spaces_after_shorthand)) => PackageEntry::Entry { + Some((shorthand, spaces_after_shorthand)) => PackageEntry { shorthand, spaces_after_shorthand, package_or_path, }, - None => PackageEntry::Entry { + None => PackageEntry { shorthand: "", spaces_after_shorthand: &[], package_or_path, }, }; - Ok((MadeProgress, entry, state)) + Ok((MadeProgress, Spaced::Item(entry), state)) } } diff --git a/compiler/parse/src/module.rs b/compiler/parse/src/module.rs index ed5f2528f3..a429871b34 100644 --- a/compiler/parse/src/module.rs +++ b/compiler/parse/src/module.rs @@ -1,7 +1,7 @@ -use crate::ast::{Collection, CommentOrNewline, Def, Module}; +use crate::ast::{Collection, CommentOrNewline, Def, Module, Spaced}; use crate::blankspace::{space0_around_ee, space0_before_e, space0_e}; use crate::header::{ - package_entry, package_name, package_or_path, AppHeader, Effects, ExposesEntry, ImportsEntry, + package_entry, package_name, package_or_path, AppHeader, Effects, ExposedName, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry, PlatformHeader, PlatformRequires, PlatformRigid, To, TypedIdent, }; @@ -220,7 +220,7 @@ fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> { #[allow(clippy::type_complexity)] let opt_imports: Option<( (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), - Collection<'a, Located>>, + Collection<'a, Located>>>, )> = opt_imports; let ((before_imports, after_imports), imports) = @@ -303,7 +303,7 @@ fn platform_header<'a>() -> impl Parser<'a, PlatformHeader<'a>, EHeader<'a>> { #[derive(Debug)] struct ProvidesTo<'a> { - entries: Collection<'a, Located>>, + entries: Collection<'a, Located>>>, to: Located>, before_provides_keyword: &'a [CommentOrNewline<'a>], @@ -362,7 +362,7 @@ fn provides_without_to<'a>() -> impl Parser< 'a, ( (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), - Collection<'a, Located>>, + Collection<'a, Located>>>, ), EProvides<'a>, > { @@ -385,14 +385,14 @@ fn provides_without_to<'a>() -> impl Parser< EProvides::Open, EProvides::Space, EProvides::IndentListEnd, - ExposesEntry::SpaceBefore + Spaced::SpaceBefore ) ) } fn exposes_entry<'a, F, E>( to_expectation: F, -) -> impl Parser<'a, Located>, E> +) -> impl Parser<'a, Located>>, E> where F: Fn(crate::parser::Row, crate::parser::Col) -> E, F: Copy, @@ -400,7 +400,7 @@ where { loc!(map!( specialize(|_, r, c| to_expectation(r, c), unqualified_ident()), - ExposesEntry::Exposed + |n| Spaced::Item(ExposedName::new(n)) )) } @@ -444,7 +444,7 @@ fn platform_requires<'a>() -> impl Parser<'a, PlatformRequires<'a>, ERequires<'a #[inline(always)] fn requires_rigids<'a>( min_indent: u16, -) -> impl Parser<'a, Collection<'a, Located>>, ERequires<'a>> { +) -> impl Parser<'a, Collection<'a, Located>>>, ERequires<'a>> { collection_trailing_sep_e!( word1(b'{', ERequires::ListStart), specialize(|_, r, c| ERequires::Rigid(r, c), loc!(requires_rigid())), @@ -454,23 +454,24 @@ fn requires_rigids<'a>( ERequires::Open, ERequires::Space, ERequires::IndentListEnd, - PlatformRigid::SpaceBefore + Spaced::SpaceBefore ) } #[inline(always)] -fn requires_rigid<'a>() -> impl Parser<'a, PlatformRigid<'a>, ()> { +fn requires_rigid<'a>() -> impl Parser<'a, Spaced<'a, PlatformRigid<'a>>, ()> { map!( and!( lowercase_ident(), skip_first!(word2(b'=', b'>', |_, _| ()), uppercase_ident()) ), - |(rigid, alias)| PlatformRigid::Entry { rigid, alias } + |(rigid, alias)| Spaced::Item(PlatformRigid { rigid, alias }) ) } #[inline(always)] -fn requires_typed_ident<'a>() -> impl Parser<'a, Located>, ERequires<'a>> { +fn requires_typed_ident<'a>() -> impl Parser<'a, Located>>, ERequires<'a>> +{ skip_first!( word1(b'{', ERequires::ListStart), skip_second!( @@ -491,7 +492,7 @@ fn exposes_values<'a>() -> impl Parser< 'a, ( (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), - Collection<'a, Located>>, + Collection<'a, Located>>>, ), EExposes, > { @@ -515,7 +516,7 @@ fn exposes_values<'a>() -> impl Parser< EExposes::Open, EExposes::Space, EExposes::IndentListEnd, - ExposesEntry::SpaceBefore + Spaced::SpaceBefore ) ) } @@ -545,7 +546,7 @@ fn exposes_modules<'a>() -> impl Parser< 'a, ( (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), - Collection<'a, Located>>>, + Collection<'a, Located>>>, ), EExposes, > { @@ -569,14 +570,14 @@ fn exposes_modules<'a>() -> impl Parser< EExposes::Open, EExposes::Space, EExposes::IndentListEnd, - ExposesEntry::SpaceBefore + Spaced::SpaceBefore ) ) } fn exposes_module<'a, F, E>( to_expectation: F, -) -> impl Parser<'a, Located>>, E> +) -> impl Parser<'a, Located>>, E> where F: Fn(crate::parser::Row, crate::parser::Col) -> E, F: Copy, @@ -584,13 +585,13 @@ where { loc!(map!( specialize(|_, r, c| to_expectation(r, c), module_name()), - ExposesEntry::Exposed + Spaced::Item )) } #[derive(Debug)] struct Packages<'a> { - entries: Collection<'a, Located>>, + entries: Collection<'a, Located>>>, before_packages_keyword: &'a [CommentOrNewline<'a>], after_packages_keyword: &'a [CommentOrNewline<'a>], } @@ -618,7 +619,7 @@ fn packages<'a>() -> impl Parser<'a, Packages<'a>, EPackages<'a>> { EPackages::Open, EPackages::Space, EPackages::IndentListEnd, - PackageEntry::SpaceBefore + Spaced::SpaceBefore ) ), |((before_packages_keyword, after_packages_keyword), entries): ( @@ -639,7 +640,7 @@ fn imports<'a>() -> impl Parser< 'a, ( (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), - Collection<'a, Located>>, + Collection<'a, Located>>>, ), EImports, > { @@ -663,7 +664,7 @@ fn imports<'a>() -> impl Parser< EImports::Open, EImports::Space, EImports::IndentListEnd, - ImportsEntry::SpaceBefore + Spaced::SpaceBefore ) ) } @@ -706,7 +707,7 @@ fn effects<'a>() -> impl Parser<'a, Effects<'a>, EEffects<'a>> { EEffects::Open, EEffects::Space, EEffects::IndentListEnd, - TypedIdent::SpaceBefore + Spaced::SpaceBefore ) .parse(arena, state)?; @@ -726,7 +727,7 @@ fn effects<'a>() -> impl Parser<'a, Effects<'a>, EEffects<'a>> { } #[inline(always)] -fn typed_ident<'a>() -> impl Parser<'a, TypedIdent<'a>, ETypedIdent<'a>> { +fn typed_ident<'a>() -> impl Parser<'a, Spaced<'a, TypedIdent<'a>>, ETypedIdent<'a>> { // e.g. // // printLine : Str -> Effect {} @@ -752,11 +753,11 @@ fn typed_ident<'a>() -> impl Parser<'a, TypedIdent<'a>, ETypedIdent<'a>> { ) ), |((ident, spaces_before_colon), ann)| { - TypedIdent::Entry { + Spaced::Item(TypedIdent { ident, spaces_before_colon, ann, - } + }) } ) } @@ -775,12 +776,12 @@ where } #[inline(always)] -fn imports_entry<'a>() -> impl Parser<'a, ImportsEntry<'a>, EImports> { +fn imports_entry<'a>() -> impl Parser<'a, Spaced<'a, ImportsEntry<'a>>, EImports> { let min_indent = 1; type Temp<'a> = ( (Option<&'a str>, ModuleName<'a>), - Option>>>, + Option>>>>, ); map_with_arena!( @@ -806,18 +807,20 @@ fn imports_entry<'a>() -> impl Parser<'a, ImportsEntry<'a>, EImports> { EImports::Open, EImports::Space, EImports::IndentSetEnd, - ExposesEntry::SpaceBefore + Spaced::SpaceBefore ) )) ), |_arena, ((opt_shortname, module_name), opt_values): Temp<'a>| { let exposed_values = opt_values.unwrap_or_else(Collection::empty); - match opt_shortname { + let entry = match opt_shortname { Some(shortname) => ImportsEntry::Package(shortname, module_name, exposed_values), None => ImportsEntry::Module(module_name, exposed_values), - } + }; + + Spaced::Item(entry) } ) } diff --git a/compiler/parse/tests/snapshots/pass/empty_platform_header.header.result-ast b/compiler/parse/tests/snapshots/pass/empty_platform_header.header.result-ast index fa3993d530..47d116d78d 100644 --- a/compiler/parse/tests/snapshots/pass/empty_platform_header.header.result-ast +++ b/compiler/parse/tests/snapshots/pass/empty_platform_header.header.result-ast @@ -6,7 +6,7 @@ Platform { }, requires: PlatformRequires { rigids: [], - signature: |L 0-0, C 38-47| Entry { + signature: |L 0-0, C 38-47| TypedIdent { ident: |L 0-0, C 38-42| "main", spaces_before_colon: [], ann: |L 0-0, C 45-47| Record { diff --git a/compiler/parse/tests/snapshots/pass/full_app_header.header.result-ast b/compiler/parse/tests/snapshots/pass/full_app_header.header.result-ast index e33441e9ea..f04eff75bf 100644 --- a/compiler/parse/tests/snapshots/pass/full_app_header.header.result-ast +++ b/compiler/parse/tests/snapshots/pass/full_app_header.header.result-ast @@ -4,7 +4,7 @@ App { "quicksort", ), packages: [ - |L 1-1, C 15-31| Entry { + |L 1-1, C 15-31| PackageEntry { shorthand: "pf", spaces_after_shorthand: [], package_or_path: |L 1-1, C 19-31| Path( @@ -24,7 +24,7 @@ App { ), ], provides: [ - |L 3-3, C 15-24| Exposed( + |L 3-3, C 15-24| ExposedName( "quicksort", ), ], diff --git a/compiler/parse/tests/snapshots/pass/full_app_header_trailing_commas.header.result-ast b/compiler/parse/tests/snapshots/pass/full_app_header_trailing_commas.header.result-ast index 8864727f1b..988ff5ae7a 100644 --- a/compiler/parse/tests/snapshots/pass/full_app_header_trailing_commas.header.result-ast +++ b/compiler/parse/tests/snapshots/pass/full_app_header_trailing_commas.header.result-ast @@ -4,7 +4,7 @@ App { "quicksort", ), packages: [ - |L 1-1, C 15-31| Entry { + |L 1-1, C 15-31| PackageEntry { shorthand: "pf", spaces_after_shorthand: [], package_or_path: |L 1-1, C 19-31| Path( @@ -23,7 +23,7 @@ App { Collection { items: [ |L 3-3, C 8-11| SpaceBefore( - Exposed( + ExposedName( "Baz", ), [ @@ -31,7 +31,7 @@ App { ], ), |L 4-4, C 8-16| SpaceBefore( - Exposed( + ExposedName( "FortyTwo", ), [ @@ -49,7 +49,7 @@ App { ), ], provides: [ - |L 7-7, C 15-24| Exposed( + |L 7-7, C 15-24| ExposedName( "quicksort", ), ], diff --git a/compiler/parse/tests/snapshots/pass/nonempty_platform_header.header.result-ast b/compiler/parse/tests/snapshots/pass/nonempty_platform_header.header.result-ast index 8497dc8470..60259c1cd8 100644 --- a/compiler/parse/tests/snapshots/pass/nonempty_platform_header.header.result-ast +++ b/compiler/parse/tests/snapshots/pass/nonempty_platform_header.header.result-ast @@ -6,12 +6,12 @@ Platform { }, requires: PlatformRequires { rigids: [ - |L 1-1, C 14-26| Entry { + |L 1-1, C 14-26| PlatformRigid { rigid: "model", alias: "Model", }, ], - signature: |L 1-1, C 30-39| Entry { + signature: |L 1-1, C 30-39| TypedIdent { ident: |L 1-1, C 30-34| "main", spaces_before_colon: [], ann: |L 1-1, C 37-39| Record { @@ -22,7 +22,7 @@ Platform { }, exposes: [], packages: [ - |L 3-3, C 15-27| Entry { + |L 3-3, C 15-27| PackageEntry { shorthand: "foo", spaces_after_shorthand: [], package_or_path: |L 3-3, C 20-27| Path( @@ -34,7 +34,7 @@ Platform { ], imports: [], provides: [ - |L 5-5, C 15-26| Exposed( + |L 5-5, C 15-26| ExposedName( "mainForHost", ), ],