mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
Merge branch 'main' of github.com:rtfeldman/roc into wasm_interp_imports
This commit is contained in:
commit
04d493c49e
32 changed files with 1890 additions and 1579 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -5860,7 +5860,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm3"
|
name = "wasm3"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
source = "git+https://github.com/roc-lang/wasm3-rs?rev=f0f807d1fc0a50d1d68e5799e54ee62c05af00f5#f0f807d1fc0a50d1d68e5799e54ee62c05af00f5"
|
source = "git+https://github.com/roc-lang/wasm3-rs?rev=ba0cdab7404f7f2995a8c18e614ce020dabd6da0#ba0cdab7404f7f2995a8c18e614ce020dabd6da0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cty",
|
"cty",
|
||||||
"wasm3-sys",
|
"wasm3-sys",
|
||||||
|
@ -5869,7 +5869,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm3-sys"
|
name = "wasm3-sys"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
source = "git+https://github.com/roc-lang/wasm3-rs?rev=f0f807d1fc0a50d1d68e5799e54ee62c05af00f5#f0f807d1fc0a50d1d68e5799e54ee62c05af00f5"
|
source = "git+https://github.com/roc-lang/wasm3-rs?rev=ba0cdab7404f7f2995a8c18e614ce020dabd6da0#ba0cdab7404f7f2995a8c18e614ce020dabd6da0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"cty",
|
"cty",
|
||||||
|
|
|
@ -112,7 +112,7 @@ target-lexicon = "0.12.3"
|
||||||
tempfile = "3.2.0"
|
tempfile = "3.2.0"
|
||||||
unicode-segmentation = "1.10.0"
|
unicode-segmentation = "1.10.0"
|
||||||
walkdir = "2.3.2"
|
walkdir = "2.3.2"
|
||||||
wasm3 = { git = "https://github.com/roc-lang/wasm3-rs", rev = "f0f807d1fc0a50d1d68e5799e54ee62c05af00f5" }
|
wasm3 = { git = "https://github.com/roc-lang/wasm3-rs", rev = "ba0cdab7404f7f2995a8c18e614ce020dabd6da0" }
|
||||||
wyhash = "0.5.0"
|
wyhash = "0.5.0"
|
||||||
|
|
||||||
# TODO: Deal with the update of object to 0.27.
|
# TODO: Deal with the update of object to 0.27.
|
||||||
|
|
|
@ -235,14 +235,7 @@ mod cli_run {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CliMode::Roc => {
|
CliMode::Roc => run_roc_on(file, flags.clone(), stdin, roc_app_args, extra_env),
|
||||||
if !extra_env.is_empty() {
|
|
||||||
// TODO: `roc` and `roc dev` are currently buggy for `env.roc`
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
run_roc_on(file, flags.clone(), stdin, roc_app_args, extra_env)
|
|
||||||
}
|
|
||||||
CliMode::RocRun => run_roc_on(
|
CliMode::RocRun => run_roc_on(
|
||||||
file,
|
file,
|
||||||
iter::once(CMD_RUN).chain(flags.clone()),
|
iter::once(CMD_RUN).chain(flags.clone()),
|
||||||
|
|
|
@ -1491,7 +1491,14 @@ pub fn llvm_module_to_dylib(
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
child.wait().unwrap();
|
let exit_status = child.wait().unwrap();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
exit_status.success(),
|
||||||
|
"\n___________\nLinking command failed with status {:?}:\n\n {:?}\n___________\n",
|
||||||
|
exit_status,
|
||||||
|
child
|
||||||
|
);
|
||||||
|
|
||||||
// Load the dylib
|
// Load the dylib
|
||||||
let path = dylib_path.as_path().to_str().unwrap();
|
let path = dylib_path.as_path().to_str().unwrap();
|
||||||
|
|
|
@ -63,9 +63,7 @@ pub trait Formattable {
|
||||||
_parens: Parens,
|
_parens: Parens,
|
||||||
_newlines: Newlines,
|
_newlines: Newlines,
|
||||||
indent: u16,
|
indent: u16,
|
||||||
) {
|
);
|
||||||
self.format(buf, indent);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn format<'buf>(&self, buf: &mut Buf<'buf>, indent: u16) {
|
fn format<'buf>(&self, buf: &mut Buf<'buf>, indent: u16) {
|
||||||
self.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent);
|
self.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent);
|
||||||
|
@ -96,18 +94,13 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> Formattable for Collection<'a, T>
|
pub fn is_collection_multiline<T: Formattable>(collection: &Collection<'_, T>) -> bool {
|
||||||
where
|
// if there are any comments, they must go on their own line
|
||||||
T: Formattable,
|
// because otherwise they'd comment out the closing delimiter
|
||||||
{
|
!collection.final_comments().is_empty() ||
|
||||||
fn is_multiline(&self) -> bool {
|
// if any of the items in the collection are multiline,
|
||||||
// if there are any comments, they must go on their own line
|
// then the whole collection must be multiline
|
||||||
// because otherwise they'd comment out the closing delimiter
|
collection.items.iter().any(Formattable::is_multiline)
|
||||||
!self.final_comments().is_empty() ||
|
|
||||||
// if any of the items in the collection are multiline,
|
|
||||||
// then the whole collection must be multiline
|
|
||||||
self.items.iter().any(Formattable::is_multiline)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Located formattable value is also formattable
|
/// A Located formattable value is also formattable
|
||||||
|
@ -577,7 +570,7 @@ impl<'a> Formattable for HasImpls<'a> {
|
||||||
fn is_multiline(&self) -> bool {
|
fn is_multiline(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
HasImpls::SpaceBefore(_, _) | HasImpls::SpaceAfter(_, _) => true,
|
HasImpls::SpaceBefore(_, _) | HasImpls::SpaceAfter(_, _) => true,
|
||||||
HasImpls::HasImpls(impls) => impls.is_multiline(),
|
HasImpls::HasImpls(impls) => is_collection_multiline(impls),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -657,7 +650,7 @@ impl<'a> Formattable for HasAbilities<'a> {
|
||||||
fn is_multiline(&self) -> bool {
|
fn is_multiline(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
HasAbilities::SpaceAfter(..) | HasAbilities::SpaceBefore(..) => true,
|
HasAbilities::SpaceAfter(..) | HasAbilities::SpaceBefore(..) => true,
|
||||||
HasAbilities::Has(has_abilities) => has_abilities.is_multiline(),
|
HasAbilities::Has(has_abilities) => is_collection_multiline(has_abilities),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use roc_parse::ast::{Collection, CommentOrNewline, ExtractSpaces};
|
use roc_parse::ast::{Collection, CommentOrNewline, ExtractSpaces};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
annotation::{Formattable, Newlines},
|
annotation::{is_collection_multiline, Formattable, Newlines},
|
||||||
spaces::{fmt_comments_only, NewlineAt, INDENT},
|
spaces::{fmt_comments_only, NewlineAt, INDENT},
|
||||||
Buf,
|
Buf,
|
||||||
};
|
};
|
||||||
|
@ -34,7 +34,7 @@ pub fn fmt_collection<'a, 'buf, T: ExtractSpaces<'a> + Formattable>(
|
||||||
Braces::Square => ']',
|
Braces::Square => ']',
|
||||||
};
|
};
|
||||||
|
|
||||||
if items.is_multiline() {
|
if is_collection_multiline(&items) {
|
||||||
let braces_indent = indent;
|
let braces_indent = indent;
|
||||||
let item_indent = braces_indent + INDENT;
|
let item_indent = braces_indent + INDENT;
|
||||||
if newline == Newlines::Yes {
|
if newline == Newlines::Yes {
|
||||||
|
|
|
@ -1,184 +1,248 @@
|
||||||
use crate::annotation::{Formattable, Newlines};
|
use crate::annotation::{is_collection_multiline, Formattable, Newlines, Parens};
|
||||||
use crate::collection::{fmt_collection, Braces};
|
use crate::collection::{fmt_collection, Braces};
|
||||||
use crate::expr::fmt_str_literal;
|
use crate::expr::fmt_str_literal;
|
||||||
|
use crate::spaces::RemoveSpaces;
|
||||||
use crate::spaces::{fmt_comments_only, fmt_default_spaces, fmt_spaces, NewlineAt, INDENT};
|
use crate::spaces::{fmt_comments_only, fmt_default_spaces, fmt_spaces, NewlineAt, INDENT};
|
||||||
use crate::Buf;
|
use crate::Buf;
|
||||||
use roc_parse::ast::{Collection, Module, Spaced};
|
use bumpalo::Bump;
|
||||||
|
use roc_parse::ast::{Collection, Header, Module, Spaced, Spaces};
|
||||||
use roc_parse::header::{
|
use roc_parse::header::{
|
||||||
AppHeader, ExposedName, HostedHeader, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry,
|
AppHeader, ExposedName, ExposesKeyword, GeneratesKeyword, HostedHeader, ImportsEntry,
|
||||||
PackageName, PlatformHeader, PlatformRequires, To, TypedIdent,
|
ImportsKeyword, InterfaceHeader, Keyword, KeywordItem, ModuleName, PackageEntry,
|
||||||
|
PackageKeyword, PackageName, PackagesKeyword, PlatformHeader, PlatformRequires,
|
||||||
|
ProvidesKeyword, ProvidesTo, RequiresKeyword, To, ToKeyword, TypedIdent, WithKeyword,
|
||||||
};
|
};
|
||||||
use roc_parse::ident::UppercaseIdent;
|
use roc_parse::ident::UppercaseIdent;
|
||||||
use roc_region::all::Loc;
|
use roc_region::all::Loc;
|
||||||
|
|
||||||
pub fn fmt_module<'a>(buf: &mut Buf<'_>, module: &'a Module<'a>) {
|
pub fn fmt_module<'a>(buf: &mut Buf<'_>, module: &'a Module<'a>) {
|
||||||
match module {
|
fmt_comments_only(buf, module.comments.iter(), NewlineAt::Bottom, 0);
|
||||||
Module::Interface { header } => {
|
match &module.header {
|
||||||
|
Header::Interface(header) => {
|
||||||
fmt_interface_header(buf, header);
|
fmt_interface_header(buf, header);
|
||||||
}
|
}
|
||||||
Module::App { header } => {
|
Header::App(header) => {
|
||||||
fmt_app_header(buf, header);
|
fmt_app_header(buf, header);
|
||||||
}
|
}
|
||||||
Module::Platform { header } => {
|
Header::Platform(header) => {
|
||||||
fmt_platform_header(buf, header);
|
fmt_platform_header(buf, header);
|
||||||
}
|
}
|
||||||
Module::Hosted { header } => {
|
Header::Hosted(header) => {
|
||||||
fmt_hosted_header(buf, header);
|
fmt_hosted_header(buf, header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! keywords {
|
||||||
|
($($name:ident),* $(,)?) => {
|
||||||
|
$(
|
||||||
|
impl Formattable for $name {
|
||||||
|
fn is_multiline(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_with_options<'buf>(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buf<'buf>,
|
||||||
|
_parens: crate::annotation::Parens,
|
||||||
|
_newlines: Newlines,
|
||||||
|
indent: u16,
|
||||||
|
) {
|
||||||
|
buf.indent(indent);
|
||||||
|
buf.push_str($name::KEYWORD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> RemoveSpaces<'a> for $name {
|
||||||
|
fn remove_spaces(&self, _arena: &'a Bump) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keywords! {
|
||||||
|
ExposesKeyword,
|
||||||
|
ImportsKeyword,
|
||||||
|
WithKeyword,
|
||||||
|
GeneratesKeyword,
|
||||||
|
PackageKeyword,
|
||||||
|
PackagesKeyword,
|
||||||
|
RequiresKeyword,
|
||||||
|
ProvidesKeyword,
|
||||||
|
ToKeyword,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Formattable> Formattable for Option<V> {
|
||||||
|
fn is_multiline(&self) -> bool {
|
||||||
|
if let Some(v) = self {
|
||||||
|
v.is_multiline()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_with_options<'buf>(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buf<'buf>,
|
||||||
|
parens: crate::annotation::Parens,
|
||||||
|
newlines: Newlines,
|
||||||
|
indent: u16,
|
||||||
|
) {
|
||||||
|
if let Some(v) = self {
|
||||||
|
v.format_with_options(buf, parens, newlines, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Formattable for ProvidesTo<'a> {
|
||||||
|
fn is_multiline(&self) -> bool {
|
||||||
|
if let Some(types) = &self.types {
|
||||||
|
if is_collection_multiline(types) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.provides_keyword.is_multiline()
|
||||||
|
|| is_collection_multiline(&self.entries)
|
||||||
|
|| self.to_keyword.is_multiline()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_with_options<'buf>(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buf<'buf>,
|
||||||
|
_parens: crate::annotation::Parens,
|
||||||
|
_newlines: Newlines,
|
||||||
|
indent: u16,
|
||||||
|
) {
|
||||||
|
self.provides_keyword.format(buf, indent);
|
||||||
|
fmt_provides(buf, self.entries, self.types, indent);
|
||||||
|
self.to_keyword.format(buf, indent);
|
||||||
|
fmt_to(buf, self.to.value, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Formattable for PlatformRequires<'a> {
|
||||||
|
fn is_multiline(&self) -> bool {
|
||||||
|
is_collection_multiline(&self.rigids) || self.signature.is_multiline()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_with_options<'buf>(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buf<'buf>,
|
||||||
|
_parens: crate::annotation::Parens,
|
||||||
|
_newlines: Newlines,
|
||||||
|
indent: u16,
|
||||||
|
) {
|
||||||
|
fmt_requires(buf, self, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, V: Formattable> Formattable for Spaces<'a, V> {
|
||||||
|
fn is_multiline(&self) -> bool {
|
||||||
|
!self.before.is_empty() || !self.after.is_empty() || self.item.is_multiline()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_with_options<'buf>(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buf<'buf>,
|
||||||
|
parens: crate::annotation::Parens,
|
||||||
|
newlines: Newlines,
|
||||||
|
indent: u16,
|
||||||
|
) {
|
||||||
|
fmt_default_spaces(buf, self.before, indent);
|
||||||
|
self.item.format_with_options(buf, parens, newlines, indent);
|
||||||
|
fmt_default_spaces(buf, self.after, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K: Formattable, V: Formattable> Formattable for KeywordItem<'a, K, V> {
|
||||||
|
fn is_multiline(&self) -> bool {
|
||||||
|
self.keyword.is_multiline() || self.item.is_multiline()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_with_options<'buf>(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buf<'buf>,
|
||||||
|
parens: Parens,
|
||||||
|
newlines: Newlines,
|
||||||
|
indent: u16,
|
||||||
|
) {
|
||||||
|
self.keyword
|
||||||
|
.format_with_options(buf, parens, newlines, indent);
|
||||||
|
self.item.format_with_options(buf, parens, newlines, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fmt_interface_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a InterfaceHeader<'a>) {
|
pub fn fmt_interface_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a InterfaceHeader<'a>) {
|
||||||
let indent = INDENT;
|
|
||||||
|
|
||||||
fmt_comments_only(buf, header.before_header.iter(), NewlineAt::Bottom, indent);
|
|
||||||
|
|
||||||
buf.indent(0);
|
buf.indent(0);
|
||||||
buf.push_str("interface");
|
buf.push_str("interface");
|
||||||
|
let indent = INDENT;
|
||||||
|
fmt_default_spaces(buf, header.before_name, indent);
|
||||||
|
|
||||||
// module name
|
// module name
|
||||||
fmt_default_spaces(buf, header.after_interface_keyword, indent);
|
buf.indent(indent);
|
||||||
buf.push_str(header.name.value.as_str());
|
buf.push_str(header.name.value.as_str());
|
||||||
|
|
||||||
// exposes
|
header.exposes.keyword.format(buf, indent);
|
||||||
fmt_default_spaces(buf, header.before_exposes, indent);
|
fmt_exposes(buf, header.exposes.item, indent);
|
||||||
buf.indent(indent);
|
header.imports.keyword.format(buf, indent);
|
||||||
buf.push_str("exposes");
|
fmt_imports(buf, header.imports.item, indent);
|
||||||
fmt_default_spaces(buf, header.after_exposes, indent);
|
|
||||||
fmt_exposes(buf, header.exposes, indent);
|
|
||||||
|
|
||||||
// imports
|
|
||||||
fmt_default_spaces(buf, header.before_imports, indent);
|
|
||||||
buf.indent(indent);
|
|
||||||
buf.push_str("imports");
|
|
||||||
fmt_default_spaces(buf, header.after_imports, indent);
|
|
||||||
fmt_imports(buf, header.imports, indent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt_hosted_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a HostedHeader<'a>) {
|
pub fn fmt_hosted_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a HostedHeader<'a>) {
|
||||||
let indent = INDENT;
|
|
||||||
|
|
||||||
fmt_comments_only(buf, header.before_header.iter(), NewlineAt::Bottom, indent);
|
|
||||||
|
|
||||||
buf.indent(0);
|
buf.indent(0);
|
||||||
buf.push_str("hosted");
|
buf.push_str("hosted");
|
||||||
|
let indent = INDENT;
|
||||||
|
fmt_default_spaces(buf, header.before_name, indent);
|
||||||
|
|
||||||
// module name
|
|
||||||
fmt_default_spaces(buf, header.after_hosted_keyword, indent);
|
|
||||||
buf.push_str(header.name.value.as_str());
|
buf.push_str(header.name.value.as_str());
|
||||||
|
|
||||||
// exposes
|
header.exposes.keyword.format(buf, indent);
|
||||||
fmt_default_spaces(buf, header.before_exposes, indent);
|
fmt_exposes(buf, header.exposes.item, indent);
|
||||||
buf.indent(indent);
|
header.imports.keyword.format(buf, indent);
|
||||||
buf.push_str("exposes");
|
fmt_imports(buf, header.imports.item, indent);
|
||||||
fmt_default_spaces(buf, header.after_exposes, indent);
|
header.generates.format(buf, indent);
|
||||||
fmt_exposes(buf, header.exposes, indent);
|
header.generates_with.keyword.format(buf, indent);
|
||||||
|
fmt_exposes(buf, header.generates_with.item, indent);
|
||||||
// imports
|
|
||||||
fmt_default_spaces(buf, header.before_imports, indent);
|
|
||||||
buf.indent(indent);
|
|
||||||
buf.push_str("imports");
|
|
||||||
fmt_default_spaces(buf, header.after_imports, indent);
|
|
||||||
fmt_imports(buf, header.imports, indent);
|
|
||||||
|
|
||||||
// generates
|
|
||||||
fmt_default_spaces(buf, header.before_generates, indent);
|
|
||||||
buf.indent(indent);
|
|
||||||
buf.push_str("generates");
|
|
||||||
fmt_default_spaces(buf, header.after_generates, indent);
|
|
||||||
buf.push_str(header.generates.into());
|
|
||||||
|
|
||||||
// with
|
|
||||||
fmt_default_spaces(buf, header.before_with, indent);
|
|
||||||
buf.indent(indent);
|
|
||||||
buf.push_str("with");
|
|
||||||
fmt_default_spaces(buf, header.after_with, indent);
|
|
||||||
fmt_exposes(buf, header.generates_with, indent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt_app_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a AppHeader<'a>) {
|
pub fn fmt_app_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a AppHeader<'a>) {
|
||||||
let indent = INDENT;
|
|
||||||
|
|
||||||
fmt_comments_only(buf, header.before_header.iter(), NewlineAt::Bottom, indent);
|
|
||||||
|
|
||||||
buf.indent(0);
|
buf.indent(0);
|
||||||
buf.push_str("app");
|
buf.push_str("app");
|
||||||
|
let indent = INDENT;
|
||||||
|
fmt_default_spaces(buf, header.before_name, indent);
|
||||||
|
|
||||||
fmt_default_spaces(buf, header.after_app_keyword, indent);
|
|
||||||
fmt_str_literal(buf, header.name.value, indent);
|
fmt_str_literal(buf, header.name.value, indent);
|
||||||
|
|
||||||
// packages
|
if let Some(packages) = &header.packages {
|
||||||
fmt_default_spaces(buf, header.before_packages, indent);
|
packages.keyword.format(buf, indent);
|
||||||
buf.indent(indent);
|
fmt_packages(buf, packages.item, indent);
|
||||||
buf.push_str("packages");
|
}
|
||||||
fmt_default_spaces(buf, header.after_packages, indent);
|
if let Some(imports) = &header.imports {
|
||||||
fmt_packages(buf, header.packages, indent);
|
imports.keyword.format(buf, indent);
|
||||||
|
fmt_imports(buf, imports.item, indent);
|
||||||
// imports
|
}
|
||||||
fmt_default_spaces(buf, header.before_imports, indent);
|
header.provides.format(buf, indent);
|
||||||
buf.indent(indent);
|
|
||||||
buf.push_str("imports");
|
|
||||||
fmt_default_spaces(buf, header.after_imports, indent);
|
|
||||||
fmt_imports(buf, header.imports, indent);
|
|
||||||
|
|
||||||
// provides
|
|
||||||
fmt_default_spaces(buf, header.before_provides, indent);
|
|
||||||
buf.indent(indent);
|
|
||||||
buf.push_str("provides");
|
|
||||||
fmt_default_spaces(buf, header.after_provides, indent);
|
|
||||||
fmt_provides(buf, header.provides, header.provides_types, indent);
|
|
||||||
fmt_default_spaces(buf, header.before_to, indent);
|
|
||||||
buf.indent(indent);
|
|
||||||
buf.push_str("to");
|
|
||||||
fmt_default_spaces(buf, header.after_to, indent);
|
|
||||||
fmt_to(buf, header.to.value, indent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt_platform_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a PlatformHeader<'a>) {
|
pub fn fmt_platform_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a PlatformHeader<'a>) {
|
||||||
let indent = INDENT;
|
|
||||||
|
|
||||||
fmt_comments_only(buf, header.before_header.iter(), NewlineAt::Bottom, indent);
|
|
||||||
|
|
||||||
buf.indent(0);
|
buf.indent(0);
|
||||||
buf.push_str("platform");
|
buf.push_str("platform");
|
||||||
|
let indent = INDENT;
|
||||||
|
fmt_default_spaces(buf, header.before_name, indent);
|
||||||
|
|
||||||
fmt_default_spaces(buf, header.after_platform_keyword, indent);
|
|
||||||
fmt_package_name(buf, header.name.value, indent);
|
fmt_package_name(buf, header.name.value, indent);
|
||||||
|
|
||||||
// requires
|
header.requires.format(buf, indent);
|
||||||
fmt_default_spaces(buf, header.before_requires, indent);
|
header.exposes.keyword.format(buf, indent);
|
||||||
buf.indent(indent);
|
fmt_exposes(buf, header.exposes.item, indent);
|
||||||
buf.push_str("requires");
|
header.packages.keyword.format(buf, indent);
|
||||||
fmt_default_spaces(buf, header.after_requires, indent);
|
fmt_packages(buf, header.packages.item, indent);
|
||||||
fmt_requires(buf, &header.requires, indent);
|
header.imports.keyword.format(buf, indent);
|
||||||
|
fmt_imports(buf, header.imports.item, indent);
|
||||||
// exposes
|
header.provides.keyword.format(buf, indent);
|
||||||
fmt_default_spaces(buf, header.before_exposes, indent);
|
fmt_provides(buf, header.provides.item, None, indent);
|
||||||
buf.indent(indent);
|
|
||||||
buf.push_str("exposes");
|
|
||||||
fmt_default_spaces(buf, header.after_exposes, indent);
|
|
||||||
fmt_exposes(buf, header.exposes, indent);
|
|
||||||
|
|
||||||
// packages
|
|
||||||
fmt_default_spaces(buf, header.before_packages, indent);
|
|
||||||
buf.indent(indent);
|
|
||||||
buf.push_str("packages");
|
|
||||||
fmt_default_spaces(buf, header.after_packages, indent);
|
|
||||||
fmt_packages(buf, header.packages, indent);
|
|
||||||
|
|
||||||
// imports
|
|
||||||
fmt_default_spaces(buf, header.before_imports, indent);
|
|
||||||
buf.indent(indent);
|
|
||||||
buf.push_str("imports");
|
|
||||||
fmt_default_spaces(buf, header.after_imports, indent);
|
|
||||||
fmt_imports(buf, header.imports, indent);
|
|
||||||
|
|
||||||
// provides
|
|
||||||
fmt_default_spaces(buf, header.before_provides, indent);
|
|
||||||
buf.indent(indent);
|
|
||||||
buf.push_str("provides");
|
|
||||||
fmt_default_spaces(buf, header.after_provides, indent);
|
|
||||||
fmt_provides(buf, header.provides, None, indent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fmt_requires<'a, 'buf>(buf: &mut Buf<'buf>, requires: &PlatformRequires<'a>, indent: u16) {
|
fn fmt_requires<'a, 'buf>(buf: &mut Buf<'buf>, requires: &PlatformRequires<'a>, indent: u16) {
|
||||||
|
@ -195,7 +259,13 @@ impl<'a> Formattable for TypedIdent<'a> {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format<'buf>(&self, buf: &mut Buf<'buf>, indent: u16) {
|
fn format_with_options<'buf>(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buf<'buf>,
|
||||||
|
_parens: Parens,
|
||||||
|
_newlines: Newlines,
|
||||||
|
indent: u16,
|
||||||
|
) {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
buf.push_str(self.ident.value);
|
buf.push_str(self.ident.value);
|
||||||
fmt_default_spaces(buf, self.spaces_before_colon, indent);
|
fmt_default_spaces(buf, self.spaces_before_colon, indent);
|
||||||
|
@ -306,7 +376,13 @@ impl<'a> Formattable for ModuleName<'a> {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format<'buf>(&self, buf: &mut Buf<'buf>, _indent: u16) {
|
fn format_with_options<'buf>(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buf<'buf>,
|
||||||
|
_parens: Parens,
|
||||||
|
_newlines: Newlines,
|
||||||
|
_indent: u16,
|
||||||
|
) {
|
||||||
buf.push_str(self.as_str());
|
buf.push_str(self.as_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -316,7 +392,13 @@ impl<'a> Formattable for ExposedName<'a> {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format<'buf>(&self, buf: &mut Buf<'buf>, indent: u16) {
|
fn format_with_options<'buf>(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buf<'buf>,
|
||||||
|
_parens: Parens,
|
||||||
|
_newlines: Newlines,
|
||||||
|
indent: u16,
|
||||||
|
) {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
buf.push_str(self.as_str());
|
buf.push_str(self.as_str());
|
||||||
}
|
}
|
||||||
|
@ -341,7 +423,13 @@ impl<'a> Formattable for PackageEntry<'a> {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format<'buf>(&self, buf: &mut Buf<'buf>, indent: u16) {
|
fn format_with_options<'buf>(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buf<'buf>,
|
||||||
|
_parens: Parens,
|
||||||
|
_newlines: Newlines,
|
||||||
|
indent: u16,
|
||||||
|
) {
|
||||||
fmt_packages_entry(buf, self, indent);
|
fmt_packages_entry(buf, self, indent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -351,7 +439,13 @@ impl<'a> Formattable for ImportsEntry<'a> {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format<'buf>(&self, buf: &mut Buf<'buf>, indent: u16) {
|
fn format_with_options<'buf>(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buf<'buf>,
|
||||||
|
_parens: Parens,
|
||||||
|
_newlines: Newlines,
|
||||||
|
indent: u16,
|
||||||
|
) {
|
||||||
fmt_imports_entry(buf, self, indent);
|
fmt_imports_entry(buf, self, indent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,13 @@ use roc_module::called_via::{BinOp, UnaryOp};
|
||||||
use roc_parse::{
|
use roc_parse::{
|
||||||
ast::{
|
ast::{
|
||||||
AbilityMember, AssignedField, Collection, CommentOrNewline, Defs, Expr, Has, HasAbilities,
|
AbilityMember, AssignedField, Collection, CommentOrNewline, Defs, Expr, Has, HasAbilities,
|
||||||
HasAbility, HasClause, HasImpls, Module, Pattern, Spaced, StrLiteral, StrSegment, Tag,
|
HasAbility, HasClause, HasImpls, Header, Module, Pattern, Spaced, Spaces, StrLiteral,
|
||||||
TypeAnnotation, TypeDef, TypeHeader, ValueDef, WhenBranch,
|
StrSegment, Tag, TypeAnnotation, TypeDef, TypeHeader, ValueDef, WhenBranch,
|
||||||
},
|
},
|
||||||
header::{
|
header::{
|
||||||
AppHeader, ExposedName, HostedHeader, ImportsEntry, InterfaceHeader, ModuleName,
|
AppHeader, ExposedName, HostedHeader, ImportsEntry, InterfaceHeader, KeywordItem,
|
||||||
PackageEntry, PackageName, PlatformHeader, PlatformRequires, To, TypedIdent,
|
ModuleName, PackageEntry, PackageName, PlatformHeader, PlatformRequires, ProvidesTo, To,
|
||||||
|
TypedIdent,
|
||||||
},
|
},
|
||||||
ident::UppercaseIdent,
|
ident::UppercaseIdent,
|
||||||
};
|
};
|
||||||
|
@ -242,83 +243,74 @@ impl<'a> RemoveSpaces<'a> for Defs<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, V: RemoveSpaces<'a>> RemoveSpaces<'a> for Spaces<'a, V> {
|
||||||
|
fn remove_spaces(&self, arena: &'a Bump) -> Self {
|
||||||
|
Spaces {
|
||||||
|
before: &[],
|
||||||
|
item: self.item.remove_spaces(arena),
|
||||||
|
after: &[],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K: RemoveSpaces<'a>, V: RemoveSpaces<'a>> RemoveSpaces<'a> for KeywordItem<'a, K, V> {
|
||||||
|
fn remove_spaces(&self, arena: &'a Bump) -> Self {
|
||||||
|
KeywordItem {
|
||||||
|
keyword: self.keyword.remove_spaces(arena),
|
||||||
|
item: self.item.remove_spaces(arena),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> RemoveSpaces<'a> for ProvidesTo<'a> {
|
||||||
|
fn remove_spaces(&self, arena: &'a Bump) -> Self {
|
||||||
|
ProvidesTo {
|
||||||
|
provides_keyword: self.provides_keyword.remove_spaces(arena),
|
||||||
|
entries: self.entries.remove_spaces(arena),
|
||||||
|
types: self.types.remove_spaces(arena),
|
||||||
|
to_keyword: self.to_keyword.remove_spaces(arena),
|
||||||
|
to: self.to.remove_spaces(arena),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> RemoveSpaces<'a> for Module<'a> {
|
impl<'a> RemoveSpaces<'a> for Module<'a> {
|
||||||
fn remove_spaces(&self, arena: &'a Bump) -> Self {
|
fn remove_spaces(&self, arena: &'a Bump) -> Self {
|
||||||
match self {
|
let header = match &self.header {
|
||||||
Module::Interface { header } => Module::Interface {
|
Header::Interface(header) => Header::Interface(InterfaceHeader {
|
||||||
header: InterfaceHeader {
|
before_name: &[],
|
||||||
name: header.name.remove_spaces(arena),
|
name: header.name.remove_spaces(arena),
|
||||||
exposes: header.exposes.remove_spaces(arena),
|
exposes: header.exposes.remove_spaces(arena),
|
||||||
imports: header.imports.remove_spaces(arena),
|
imports: header.imports.remove_spaces(arena),
|
||||||
before_header: &[],
|
}),
|
||||||
after_interface_keyword: &[],
|
Header::App(header) => Header::App(AppHeader {
|
||||||
before_exposes: &[],
|
before_name: &[],
|
||||||
after_exposes: &[],
|
name: header.name.remove_spaces(arena),
|
||||||
before_imports: &[],
|
packages: header.packages.remove_spaces(arena),
|
||||||
after_imports: &[],
|
imports: header.imports.remove_spaces(arena),
|
||||||
},
|
provides: header.provides.remove_spaces(arena),
|
||||||
},
|
}),
|
||||||
Module::App { header } => Module::App {
|
Header::Platform(header) => Header::Platform(PlatformHeader {
|
||||||
header: AppHeader {
|
before_name: &[],
|
||||||
name: header.name.remove_spaces(arena),
|
name: header.name.remove_spaces(arena),
|
||||||
packages: header.packages.remove_spaces(arena),
|
requires: header.requires.remove_spaces(arena),
|
||||||
imports: header.imports.remove_spaces(arena),
|
exposes: header.exposes.remove_spaces(arena),
|
||||||
provides: header.provides.remove_spaces(arena),
|
packages: header.packages.remove_spaces(arena),
|
||||||
provides_types: header.provides_types.map(|ts| ts.remove_spaces(arena)),
|
imports: header.imports.remove_spaces(arena),
|
||||||
to: header.to.remove_spaces(arena),
|
provides: header.provides.remove_spaces(arena),
|
||||||
before_header: &[],
|
}),
|
||||||
after_app_keyword: &[],
|
Header::Hosted(header) => Header::Hosted(HostedHeader {
|
||||||
before_packages: &[],
|
before_name: &[],
|
||||||
after_packages: &[],
|
name: header.name.remove_spaces(arena),
|
||||||
before_imports: &[],
|
exposes: header.exposes.remove_spaces(arena),
|
||||||
after_imports: &[],
|
imports: header.imports.remove_spaces(arena),
|
||||||
before_provides: &[],
|
generates: header.generates.remove_spaces(arena),
|
||||||
after_provides: &[],
|
generates_with: header.generates_with.remove_spaces(arena),
|
||||||
before_to: &[],
|
}),
|
||||||
after_to: &[],
|
};
|
||||||
},
|
Module {
|
||||||
},
|
comments: &[],
|
||||||
Module::Platform { header } => Module::Platform {
|
header,
|
||||||
header: PlatformHeader {
|
|
||||||
name: header.name.remove_spaces(arena),
|
|
||||||
requires: header.requires.remove_spaces(arena),
|
|
||||||
exposes: header.exposes.remove_spaces(arena),
|
|
||||||
packages: header.packages.remove_spaces(arena),
|
|
||||||
imports: header.imports.remove_spaces(arena),
|
|
||||||
provides: header.provides.remove_spaces(arena),
|
|
||||||
before_header: &[],
|
|
||||||
after_platform_keyword: &[],
|
|
||||||
before_requires: &[],
|
|
||||||
after_requires: &[],
|
|
||||||
before_exposes: &[],
|
|
||||||
after_exposes: &[],
|
|
||||||
before_packages: &[],
|
|
||||||
after_packages: &[],
|
|
||||||
before_imports: &[],
|
|
||||||
after_imports: &[],
|
|
||||||
before_provides: &[],
|
|
||||||
after_provides: &[],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Module::Hosted { header } => Module::Hosted {
|
|
||||||
header: HostedHeader {
|
|
||||||
name: header.name.remove_spaces(arena),
|
|
||||||
exposes: header.exposes.remove_spaces(arena),
|
|
||||||
imports: header.imports.remove_spaces(arena),
|
|
||||||
generates: header.generates.remove_spaces(arena),
|
|
||||||
generates_with: header.generates_with.remove_spaces(arena),
|
|
||||||
before_header: &[],
|
|
||||||
after_hosted_keyword: &[],
|
|
||||||
before_exposes: &[],
|
|
||||||
after_exposes: &[],
|
|
||||||
before_imports: &[],
|
|
||||||
after_imports: &[],
|
|
||||||
before_generates: &[],
|
|
||||||
after_generates: &[],
|
|
||||||
before_with: &[],
|
|
||||||
after_with: &[],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3003,7 +3003,10 @@ fn update<'a>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
log!("re-launching specializations pass");
|
log!(
|
||||||
|
"re-launching make-specializations: pass {}",
|
||||||
|
state.make_specializations_pass.current_pass() + 1
|
||||||
|
);
|
||||||
|
|
||||||
state.make_specializations_pass.inc();
|
state.make_specializations_pass.inc();
|
||||||
|
|
||||||
|
@ -3293,25 +3296,43 @@ fn load_platform_module<'a>(
|
||||||
pkg_module_timing.parse_header = parse_header_duration;
|
pkg_module_timing.parse_header = parse_header_duration;
|
||||||
|
|
||||||
match parsed {
|
match parsed {
|
||||||
Ok((ast::Module::Interface { header }, _parse_state)) => {
|
Ok((
|
||||||
Err(LoadingProblem::UnexpectedHeader(format!(
|
ast::Module {
|
||||||
"expected platform/package module, got Interface with header\n{:?}",
|
header: ast::Header::Interface(header),
|
||||||
header
|
..
|
||||||
)))
|
},
|
||||||
}
|
_parse_state,
|
||||||
Ok((ast::Module::Hosted { header }, _parse_state)) => {
|
)) => Err(LoadingProblem::UnexpectedHeader(format!(
|
||||||
Err(LoadingProblem::UnexpectedHeader(format!(
|
"expected platform/package module, got Interface with header\n{:?}",
|
||||||
"expected platform/package module, got Hosted module with header\n{:?}",
|
header
|
||||||
header
|
))),
|
||||||
)))
|
Ok((
|
||||||
}
|
ast::Module {
|
||||||
Ok((ast::Module::App { header }, _parse_state)) => {
|
header: ast::Header::Hosted(header),
|
||||||
Err(LoadingProblem::UnexpectedHeader(format!(
|
..
|
||||||
"expected platform/package module, got App with header\n{:?}",
|
},
|
||||||
header
|
_parse_state,
|
||||||
)))
|
)) => Err(LoadingProblem::UnexpectedHeader(format!(
|
||||||
}
|
"expected platform/package module, got Hosted module with header\n{:?}",
|
||||||
Ok((ast::Module::Platform { header }, parser_state)) => {
|
header
|
||||||
|
))),
|
||||||
|
Ok((
|
||||||
|
ast::Module {
|
||||||
|
header: ast::Header::App(header),
|
||||||
|
..
|
||||||
|
},
|
||||||
|
_parse_state,
|
||||||
|
)) => Err(LoadingProblem::UnexpectedHeader(format!(
|
||||||
|
"expected platform/package module, got App with header\n{:?}",
|
||||||
|
header
|
||||||
|
))),
|
||||||
|
Ok((
|
||||||
|
ast::Module {
|
||||||
|
header: ast::Header::Platform(header),
|
||||||
|
..
|
||||||
|
},
|
||||||
|
parser_state,
|
||||||
|
)) => {
|
||||||
// make a `platform` module that ultimately exposes `main` to the host
|
// make a `platform` module that ultimately exposes `main` to the host
|
||||||
let platform_module_msg = fabricate_platform_module(
|
let platform_module_msg = fabricate_platform_module(
|
||||||
arena,
|
arena,
|
||||||
|
@ -3356,7 +3377,13 @@ fn load_builtin_module_help<'a>(
|
||||||
let parsed = roc_parse::module::parse_header(arena, parse_state.clone());
|
let parsed = roc_parse::module::parse_header(arena, parse_state.clone());
|
||||||
|
|
||||||
match parsed {
|
match parsed {
|
||||||
Ok((ast::Module::Interface { header }, parse_state)) => {
|
Ok((
|
||||||
|
ast::Module {
|
||||||
|
header: ast::Header::Interface(header),
|
||||||
|
..
|
||||||
|
},
|
||||||
|
parse_state,
|
||||||
|
)) => {
|
||||||
let info = HeaderInfo {
|
let info = HeaderInfo {
|
||||||
loc_name: Loc {
|
loc_name: Loc {
|
||||||
region: header.name.region,
|
region: header.name.region,
|
||||||
|
@ -3366,8 +3393,8 @@ fn load_builtin_module_help<'a>(
|
||||||
is_root_module,
|
is_root_module,
|
||||||
opt_shorthand,
|
opt_shorthand,
|
||||||
packages: &[],
|
packages: &[],
|
||||||
exposes: unspace(arena, header.exposes.items),
|
exposes: unspace(arena, header.exposes.item.items),
|
||||||
imports: unspace(arena, header.imports.items),
|
imports: unspace(arena, header.imports.item.items),
|
||||||
extra: HeaderFor::Builtin {
|
extra: HeaderFor::Builtin {
|
||||||
generates_with: &[],
|
generates_with: &[],
|
||||||
},
|
},
|
||||||
|
@ -3643,7 +3670,13 @@ fn parse_header<'a>(
|
||||||
module_timing.parse_header = parse_header_duration;
|
module_timing.parse_header = parse_header_duration;
|
||||||
|
|
||||||
match parsed {
|
match parsed {
|
||||||
Ok((ast::Module::Interface { header }, parse_state)) => {
|
Ok((
|
||||||
|
ast::Module {
|
||||||
|
header: ast::Header::Interface(header),
|
||||||
|
..
|
||||||
|
},
|
||||||
|
parse_state,
|
||||||
|
)) => {
|
||||||
verify_interface_matches_file_path(header.name, &filename, &parse_state)?;
|
verify_interface_matches_file_path(header.name, &filename, &parse_state)?;
|
||||||
|
|
||||||
let header_name_region = header.name.region;
|
let header_name_region = header.name.region;
|
||||||
|
@ -3657,8 +3690,8 @@ fn parse_header<'a>(
|
||||||
is_root_module,
|
is_root_module,
|
||||||
opt_shorthand,
|
opt_shorthand,
|
||||||
packages: &[],
|
packages: &[],
|
||||||
exposes: unspace(arena, header.exposes.items),
|
exposes: unspace(arena, header.exposes.item.items),
|
||||||
imports: unspace(arena, header.imports.items),
|
imports: unspace(arena, header.imports.item.items),
|
||||||
extra: HeaderFor::Interface,
|
extra: HeaderFor::Interface,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3690,7 +3723,13 @@ fn parse_header<'a>(
|
||||||
|
|
||||||
Ok((module_id, Msg::Header(header)))
|
Ok((module_id, Msg::Header(header)))
|
||||||
}
|
}
|
||||||
Ok((ast::Module::Hosted { header }, parse_state)) => {
|
Ok((
|
||||||
|
ast::Module {
|
||||||
|
header: ast::Header::Hosted(header),
|
||||||
|
..
|
||||||
|
},
|
||||||
|
parse_state,
|
||||||
|
)) => {
|
||||||
let info = HeaderInfo {
|
let info = HeaderInfo {
|
||||||
loc_name: Loc {
|
loc_name: Loc {
|
||||||
region: header.name.region,
|
region: header.name.region,
|
||||||
|
@ -3700,11 +3739,11 @@ fn parse_header<'a>(
|
||||||
is_root_module,
|
is_root_module,
|
||||||
opt_shorthand,
|
opt_shorthand,
|
||||||
packages: &[],
|
packages: &[],
|
||||||
exposes: unspace(arena, header.exposes.items),
|
exposes: unspace(arena, header.exposes.item.items),
|
||||||
imports: unspace(arena, header.imports.items),
|
imports: unspace(arena, header.imports.item.items),
|
||||||
extra: HeaderFor::Hosted {
|
extra: HeaderFor::Hosted {
|
||||||
generates: header.generates,
|
generates: header.generates.item,
|
||||||
generates_with: unspace(arena, header.generates_with.items),
|
generates_with: unspace(arena, header.generates_with.item.items),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3718,16 +3757,27 @@ fn parse_header<'a>(
|
||||||
|
|
||||||
Ok((module_id, Msg::Header(header)))
|
Ok((module_id, Msg::Header(header)))
|
||||||
}
|
}
|
||||||
Ok((ast::Module::App { header }, parse_state)) => {
|
Ok((
|
||||||
|
ast::Module {
|
||||||
|
header: ast::Header::App(header),
|
||||||
|
..
|
||||||
|
},
|
||||||
|
parse_state,
|
||||||
|
)) => {
|
||||||
let mut app_file_dir = filename.clone();
|
let mut app_file_dir = filename.clone();
|
||||||
app_file_dir.pop();
|
app_file_dir.pop();
|
||||||
|
|
||||||
let packages = unspace(arena, header.packages.items);
|
let packages = if let Some(packages) = header.packages {
|
||||||
|
unspace(arena, packages.item.items)
|
||||||
|
} else {
|
||||||
|
&[]
|
||||||
|
};
|
||||||
|
|
||||||
let mut exposes = bumpalo::collections::Vec::new_in(arena);
|
let mut exposes = bumpalo::collections::Vec::new_in(arena);
|
||||||
exposes.extend(unspace(arena, header.provides.items));
|
|
||||||
|
|
||||||
if let Some(provided_types) = header.provides_types {
|
exposes.extend(unspace(arena, header.provides.entries.items));
|
||||||
|
|
||||||
|
if let Some(provided_types) = header.provides.types {
|
||||||
for provided_type in unspace(arena, provided_types.items) {
|
for provided_type in unspace(arena, provided_types.items) {
|
||||||
let string: &str = provided_type.value.into();
|
let string: &str = provided_type.value.into();
|
||||||
let exposed_name = ExposedName::new(string);
|
let exposed_name = ExposedName::new(string);
|
||||||
|
@ -3748,9 +3798,13 @@ fn parse_header<'a>(
|
||||||
opt_shorthand,
|
opt_shorthand,
|
||||||
packages,
|
packages,
|
||||||
exposes,
|
exposes,
|
||||||
imports: unspace(arena, header.imports.items),
|
imports: if let Some(imports) = header.imports {
|
||||||
|
unspace(arena, imports.item.items)
|
||||||
|
} else {
|
||||||
|
&[]
|
||||||
|
},
|
||||||
extra: HeaderFor::App {
|
extra: HeaderFor::App {
|
||||||
to_platform: header.to.value,
|
to_platform: header.provides.to.value,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3763,7 +3817,7 @@ fn parse_header<'a>(
|
||||||
);
|
);
|
||||||
let app_module_header_msg = Msg::Header(resolved_header);
|
let app_module_header_msg = Msg::Header(resolved_header);
|
||||||
|
|
||||||
match header.to.value {
|
match header.provides.to.value {
|
||||||
To::ExistingPackage(existing_package) => {
|
To::ExistingPackage(existing_package) => {
|
||||||
let opt_base_package = packages.iter().find_map(|loc_package_entry| {
|
let opt_base_package = packages.iter().find_map(|loc_package_entry| {
|
||||||
let Loc { value, .. } = loc_package_entry;
|
let Loc { value, .. } = loc_package_entry;
|
||||||
|
@ -3851,7 +3905,13 @@ fn parse_header<'a>(
|
||||||
To::NewPackage(_package_name) => Ok((module_id, app_module_header_msg)),
|
To::NewPackage(_package_name) => Ok((module_id, app_module_header_msg)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok((ast::Module::Platform { header }, parse_state)) => Ok(fabricate_platform_module(
|
Ok((
|
||||||
|
ast::Module {
|
||||||
|
header: ast::Header::Platform(header),
|
||||||
|
..
|
||||||
|
},
|
||||||
|
parse_state,
|
||||||
|
)) => Ok(fabricate_platform_module(
|
||||||
arena,
|
arena,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
@ -4881,13 +4941,13 @@ fn fabricate_platform_module<'a>(
|
||||||
opt_shorthand,
|
opt_shorthand,
|
||||||
opt_app_module_id,
|
opt_app_module_id,
|
||||||
packages: &[],
|
packages: &[],
|
||||||
provides: unspace(arena, header.provides.items),
|
provides: unspace(arena, header.provides.item.items),
|
||||||
requires: &*arena.alloc([Loc::at(
|
requires: &*arena.alloc([Loc::at(
|
||||||
header.requires.signature.region,
|
header.requires.item.signature.region,
|
||||||
header.requires.signature.extract_spaces().item,
|
header.requires.item.signature.extract_spaces().item,
|
||||||
)]),
|
)]),
|
||||||
requires_types: unspace(arena, header.requires.rigids.items),
|
requires_types: unspace(arena, header.requires.item.rigids.items),
|
||||||
imports: unspace(arena, header.imports.items),
|
imports: unspace(arena, header.imports.item.items),
|
||||||
};
|
};
|
||||||
|
|
||||||
send_header_two(
|
send_header_two(
|
||||||
|
|
|
@ -454,6 +454,8 @@ impl<'a> Dependencies<'a> {
|
||||||
pub fn load_find_and_make_specializations_after_check(&mut self) -> MutSet<(ModuleId, Phase)> {
|
pub fn load_find_and_make_specializations_after_check(&mut self) -> MutSet<(ModuleId, Phase)> {
|
||||||
let mut output = MutSet::default();
|
let mut output = MutSet::default();
|
||||||
|
|
||||||
|
// Take out the specialization dependency graph, as this should not be modified as we
|
||||||
|
// reload the build graph. We'll make sure the state is unaffected at the end of this call.
|
||||||
let mut make_specializations_dependents = MakeSpecializationsDependents::default();
|
let mut make_specializations_dependents = MakeSpecializationsDependents::default();
|
||||||
let default_make_specializations_dependents_len = make_specializations_dependents.0.len();
|
let default_make_specializations_dependents_len = make_specializations_dependents.0.len();
|
||||||
std::mem::swap(
|
std::mem::swap(
|
||||||
|
@ -484,8 +486,9 @@ impl<'a> Dependencies<'a> {
|
||||||
self.add_dependency(module_dep, module, Phase::MakeSpecializations);
|
self.add_dependency(module_dep, module, Phase::MakeSpecializations);
|
||||||
self.add_dependency(ModuleId::DERIVED_GEN, module, Phase::MakeSpecializations);
|
self.add_dependency(ModuleId::DERIVED_GEN, module, Phase::MakeSpecializations);
|
||||||
|
|
||||||
// `module_dep` can't make its specializations until the current module does.
|
// That `module_dep` can't make its specializations until the current module does
|
||||||
info.has_pred = true;
|
// should already be accounted for in `make_specializations_dependents`, which we
|
||||||
|
// populated when initially building the graph.
|
||||||
}
|
}
|
||||||
|
|
||||||
if module != ModuleId::DERIVED_GEN {
|
if module != ModuleId::DERIVED_GEN {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use roc_collections::soa::{EitherIndex, Index, Slice};
|
||||||
use roc_module::called_via::{BinOp, CalledVia, UnaryOp};
|
use roc_module::called_via::{BinOp, CalledVia, UnaryOp};
|
||||||
use roc_region::all::{Loc, Position, Region};
|
use roc_region::all::{Loc, Position, Region};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Spaces<'a, T> {
|
pub struct Spaces<'a, T> {
|
||||||
pub before: &'a [CommentOrNewline<'a>],
|
pub before: &'a [CommentOrNewline<'a>],
|
||||||
pub item: T,
|
pub item: T,
|
||||||
|
@ -81,11 +81,17 @@ impl<'a, T: ExtractSpaces<'a>> ExtractSpaces<'a> for Loc<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Module<'a> {
|
pub struct Module<'a> {
|
||||||
Interface { header: InterfaceHeader<'a> },
|
pub comments: &'a [CommentOrNewline<'a>],
|
||||||
App { header: AppHeader<'a> },
|
pub header: Header<'a>,
|
||||||
Platform { header: PlatformHeader<'a> },
|
}
|
||||||
Hosted { header: HostedHeader<'a> },
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum Header<'a> {
|
||||||
|
Interface(InterfaceHeader<'a>),
|
||||||
|
App(AppHeader<'a>),
|
||||||
|
Platform(PlatformHeader<'a>),
|
||||||
|
Hosted(HostedHeader<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
@ -767,69 +773,173 @@ impl<'a> Pattern<'a> {
|
||||||
pub fn equivalent(&self, other: &Self) -> bool {
|
pub fn equivalent(&self, other: &Self) -> bool {
|
||||||
use Pattern::*;
|
use Pattern::*;
|
||||||
|
|
||||||
match (self, other) {
|
match other {
|
||||||
(Identifier(x), Identifier(y)) => x == y,
|
SpaceBefore(y, _) | SpaceAfter(y, _) => {
|
||||||
(Tag(x), Tag(y)) => x == y,
|
return self.equivalent(y);
|
||||||
(Apply(constructor_x, args_x), Apply(constructor_y, args_y)) => {
|
}
|
||||||
let equivalent_args = args_x
|
_ => {}
|
||||||
.iter()
|
}
|
||||||
.zip(args_y.iter())
|
|
||||||
.all(|(p, q)| p.value.equivalent(&q.value));
|
|
||||||
|
|
||||||
constructor_x.value.equivalent(&constructor_y.value) && equivalent_args
|
match self {
|
||||||
|
Tag(x) => {
|
||||||
|
if let Tag(y) = other {
|
||||||
|
x == y
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(RecordDestructure(fields_x), RecordDestructure(fields_y)) => fields_x
|
Apply(constructor_x, args_x) => {
|
||||||
.iter()
|
if let Apply(constructor_y, args_y) = other {
|
||||||
.zip(fields_y.iter())
|
let equivalent_args = args_x
|
||||||
.all(|(p, q)| p.value.equivalent(&q.value)),
|
.iter()
|
||||||
(RequiredField(x, inner_x), RequiredField(y, inner_y)) => {
|
.zip(args_y.iter())
|
||||||
x == y && inner_x.value.equivalent(&inner_y.value)
|
.all(|(p, q)| p.value.equivalent(&q.value));
|
||||||
|
|
||||||
|
constructor_x.value.equivalent(&constructor_y.value) && equivalent_args
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(OptionalField(x, _), OptionalField(y, _))
|
RecordDestructure(fields_x) => {
|
||||||
| (OptionalField(x, _), Identifier(y))
|
if let RecordDestructure(fields_y) = other {
|
||||||
| (Identifier(x), OptionalField(y, _)) => {
|
fields_x
|
||||||
// optional record fields can be annotated as:
|
.iter()
|
||||||
// { x, y } : { x : Int, y ? Bool }
|
.zip(fields_y.iter())
|
||||||
// { x, y ? False } = rec
|
.all(|(p, q)| p.value.equivalent(&q.value))
|
||||||
x == y
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Literal
|
RequiredField(x, inner_x) => {
|
||||||
(NumLiteral(x), NumLiteral(y)) => x == y,
|
if let RequiredField(y, inner_y) = other {
|
||||||
(
|
x == y && inner_x.value.equivalent(&inner_y.value)
|
||||||
NonBase10Literal {
|
} else {
|
||||||
string: string_x,
|
false
|
||||||
base: base_x,
|
}
|
||||||
is_negative: is_negative_x,
|
}
|
||||||
},
|
|
||||||
NonBase10Literal {
|
// optional record fields can be annotated as:
|
||||||
|
// { x, y } : { x : Int, y ? Bool }
|
||||||
|
// { x, y ? False } = rec
|
||||||
|
OptionalField(x, _) => match other {
|
||||||
|
Identifier(y) | OptionalField(y, _) => x == y,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Identifier(x) => match other {
|
||||||
|
Identifier(y) | OptionalField(y, _) => x == y,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
NumLiteral(x) => {
|
||||||
|
if let NumLiteral(y) = other {
|
||||||
|
x == y
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NonBase10Literal {
|
||||||
|
string: string_x,
|
||||||
|
base: base_x,
|
||||||
|
is_negative: is_negative_x,
|
||||||
|
} => {
|
||||||
|
if let NonBase10Literal {
|
||||||
string: string_y,
|
string: string_y,
|
||||||
base: base_y,
|
base: base_y,
|
||||||
is_negative: is_negative_y,
|
is_negative: is_negative_y,
|
||||||
},
|
} = other
|
||||||
) => string_x == string_y && base_x == base_y && is_negative_x == is_negative_y,
|
{
|
||||||
(FloatLiteral(x), FloatLiteral(y)) => x == y,
|
string_x == string_y && base_x == base_y && is_negative_x == is_negative_y
|
||||||
(StrLiteral(x), StrLiteral(y)) => x == y,
|
} else {
|
||||||
(Underscore(x), Underscore(y)) => x == y,
|
false
|
||||||
|
}
|
||||||
// Space
|
}
|
||||||
(SpaceBefore(x, _), SpaceBefore(y, _)) => x.equivalent(y),
|
FloatLiteral(x) => {
|
||||||
(SpaceAfter(x, _), SpaceAfter(y, _)) => x.equivalent(y),
|
if let FloatLiteral(y) = other {
|
||||||
|
x == y
|
||||||
// Malformed
|
} else {
|
||||||
(Malformed(x), Malformed(y)) => x == y,
|
false
|
||||||
(
|
}
|
||||||
QualifiedIdentifier {
|
}
|
||||||
module_name: a,
|
StrLiteral(x) => {
|
||||||
ident: x,
|
if let StrLiteral(y) = other {
|
||||||
},
|
x == y
|
||||||
QualifiedIdentifier {
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Underscore(x) => {
|
||||||
|
if let Underscore(y) = other {
|
||||||
|
x == y
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SpaceBefore(x, _) | SpaceAfter(x, _) => match other {
|
||||||
|
SpaceBefore(y, _) | SpaceAfter(y, _) => x.equivalent(y),
|
||||||
|
y => x.equivalent(y),
|
||||||
|
},
|
||||||
|
Malformed(x) => {
|
||||||
|
if let Malformed(y) = other {
|
||||||
|
x == y
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QualifiedIdentifier {
|
||||||
|
module_name: a,
|
||||||
|
ident: x,
|
||||||
|
} => {
|
||||||
|
if let QualifiedIdentifier {
|
||||||
module_name: b,
|
module_name: b,
|
||||||
ident: y,
|
ident: y,
|
||||||
},
|
} = other
|
||||||
) => (a == b) && (x == y),
|
{
|
||||||
|
a == b && x == y
|
||||||
// Different constructors
|
} else {
|
||||||
_ => false,
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OpaqueRef(a) => {
|
||||||
|
if let OpaqueRef(b) = other {
|
||||||
|
a == b
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SingleQuote(a) => {
|
||||||
|
if let SingleQuote(b) = other {
|
||||||
|
a == b
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tuple(items_x) => {
|
||||||
|
if let Tuple(items_y) = other {
|
||||||
|
items_x
|
||||||
|
.iter()
|
||||||
|
.zip(items_y.iter())
|
||||||
|
.all(|(p, q)| p.value.equivalent(&q.value))
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List(items_x) => {
|
||||||
|
if let List(items_y) = other {
|
||||||
|
items_x
|
||||||
|
.iter()
|
||||||
|
.zip(items_y.iter())
|
||||||
|
.all(|(p, q)| p.value.equivalent(&q.value))
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ListRest => matches!(other, ListRest),
|
||||||
|
MalformedIdent(str_x, _) => {
|
||||||
|
if let MalformedIdent(str_y, _) = other {
|
||||||
|
str_x == str_y
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -565,7 +565,6 @@ pub fn parse_single_def<'a>(
|
||||||
|
|
||||||
let start = state.pos();
|
let start = state.pos();
|
||||||
|
|
||||||
let parse_dbg = crate::parser::keyword_e(crate::keyword::DBG, EExpect::Dbg);
|
|
||||||
let parse_expect_vanilla = crate::parser::keyword_e(crate::keyword::EXPECT, EExpect::Expect);
|
let parse_expect_vanilla = crate::parser::keyword_e(crate::keyword::EXPECT, EExpect::Expect);
|
||||||
let parse_expect_fx = crate::parser::keyword_e(crate::keyword::EXPECT_FX, EExpect::Expect);
|
let parse_expect_fx = crate::parser::keyword_e(crate::keyword::EXPECT_FX, EExpect::Expect);
|
||||||
let parse_expect = either!(parse_expect_fx, parse_expect_vanilla);
|
let parse_expect = either!(parse_expect_fx, parse_expect_vanilla);
|
||||||
|
@ -578,24 +577,8 @@ pub fn parse_single_def<'a>(
|
||||||
Err((NoProgress, _)) => {
|
Err((NoProgress, _)) => {
|
||||||
match parse_expect.parse(arena, state.clone(), min_indent) {
|
match parse_expect.parse(arena, state.clone(), min_indent) {
|
||||||
Err((_, _)) => {
|
Err((_, _)) => {
|
||||||
match parse_dbg.parse(arena, state, min_indent) {
|
// a hacky way to get expression-based error messages. TODO fix this
|
||||||
Ok((_, _, state)) => parse_statement_inside_def(
|
Ok((NoProgress, None, initial))
|
||||||
arena,
|
|
||||||
state,
|
|
||||||
min_indent,
|
|
||||||
start,
|
|
||||||
spaces_before_current_start,
|
|
||||||
spaces_before_current,
|
|
||||||
|preceding_comment, loc_def_expr| ValueDef::Dbg {
|
|
||||||
condition: arena.alloc(loc_def_expr),
|
|
||||||
preceding_comment,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Err((_, _)) => {
|
|
||||||
// a hacky way to get expression-based error messages. TODO fix this
|
|
||||||
Ok((NoProgress, None, initial))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok((_, expect_flavor, state)) => parse_statement_inside_def(
|
Ok((_, expect_flavor, state)) => parse_statement_inside_def(
|
||||||
arena,
|
arena,
|
||||||
|
@ -1089,10 +1072,10 @@ fn opaque_signature_with_space_before<'a>(
|
||||||
EType::TIndentStart,
|
EType::TIndentStart,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
optional(specialize(
|
optional(backtrackable(specialize(
|
||||||
EExpr::Type,
|
EExpr::Type,
|
||||||
space0_before_e(type_annotation::has_abilities(), EType::TIndentStart,),
|
space0_before_e(type_annotation::has_abilities(), EType::TIndentStart,),
|
||||||
))
|
)))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2557,7 +2540,7 @@ fn record_help<'a>() -> impl Parser<
|
||||||
and!(
|
and!(
|
||||||
// You can optionally have an identifier followed by an '&' to
|
// You can optionally have an identifier followed by an '&' to
|
||||||
// make this a record update, e.g. { Foo.user & username: "blah" }.
|
// make this a record update, e.g. { Foo.user & username: "blah" }.
|
||||||
optional(skip_second!(
|
optional(backtrackable(skip_second!(
|
||||||
space0_around_ee(
|
space0_around_ee(
|
||||||
// We wrap the ident in an Expr here,
|
// We wrap the ident in an Expr here,
|
||||||
// so that we have a Spaceable value to work with,
|
// so that we have a Spaceable value to work with,
|
||||||
|
@ -2568,7 +2551,7 @@ fn record_help<'a>() -> impl Parser<
|
||||||
ERecord::IndentAmpersand,
|
ERecord::IndentAmpersand,
|
||||||
),
|
),
|
||||||
word1(b'&', ERecord::Ampersand)
|
word1(b'&', ERecord::Ampersand)
|
||||||
)),
|
))),
|
||||||
loc!(skip_first!(
|
loc!(skip_first!(
|
||||||
// We specifically allow space characters inside here, so that
|
// We specifically allow space characters inside here, so that
|
||||||
// `{ }` can be successfully parsed as an empty record, and then
|
// `{ }` can be successfully parsed as an empty record, and then
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use crate::ast::{Collection, CommentOrNewline, Spaced, StrLiteral, TypeAnnotation};
|
use crate::ast::{Collection, CommentOrNewline, Spaced, Spaces, StrLiteral, TypeAnnotation};
|
||||||
use crate::blankspace::space0_e;
|
use crate::blankspace::space0_e;
|
||||||
use crate::ident::{lowercase_ident, UppercaseIdent};
|
use crate::ident::{lowercase_ident, UppercaseIdent};
|
||||||
use crate::parser::Progress::*;
|
use crate::parser::{optional, then};
|
||||||
use crate::parser::{specialize, word1, EPackageEntry, EPackageName, Parser};
|
use crate::parser::{specialize, word1, EPackageEntry, EPackageName, Parser};
|
||||||
use crate::state::State;
|
|
||||||
use crate::string_literal;
|
use crate::string_literal;
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_region::all::Loc;
|
use roc_region::all::Loc;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum HeaderFor<'a> {
|
pub enum HeaderFor<'a> {
|
||||||
|
@ -124,40 +124,61 @@ impl<'a> ExposedName<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Keyword: Copy + Clone + Debug {
|
||||||
|
const KEYWORD: &'static str;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! keywords {
|
||||||
|
($($name:ident => $string:expr),* $(,)?) => {
|
||||||
|
$(
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub struct $name;
|
||||||
|
|
||||||
|
impl Keyword for $name {
|
||||||
|
const KEYWORD: &'static str = $string;
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keywords! {
|
||||||
|
ExposesKeyword => "exposes",
|
||||||
|
ImportsKeyword => "imports",
|
||||||
|
WithKeyword => "with",
|
||||||
|
GeneratesKeyword => "generates",
|
||||||
|
PackageKeyword => "package",
|
||||||
|
PackagesKeyword => "packages",
|
||||||
|
RequiresKeyword => "requires",
|
||||||
|
ProvidesKeyword => "provides",
|
||||||
|
ToKeyword => "to",
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct KeywordItem<'a, K, V> {
|
||||||
|
pub keyword: Spaces<'a, K>,
|
||||||
|
pub item: V,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct InterfaceHeader<'a> {
|
pub struct InterfaceHeader<'a> {
|
||||||
|
pub before_name: &'a [CommentOrNewline<'a>],
|
||||||
pub name: Loc<ModuleName<'a>>,
|
pub name: Loc<ModuleName<'a>>,
|
||||||
pub exposes: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
|
||||||
pub imports: Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>,
|
|
||||||
|
|
||||||
// Potential comments and newlines - these will typically all be empty.
|
pub exposes: KeywordItem<'a, ExposesKeyword, Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>>,
|
||||||
pub before_header: &'a [CommentOrNewline<'a>],
|
pub imports: KeywordItem<'a, ImportsKeyword, Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>>,
|
||||||
pub after_interface_keyword: &'a [CommentOrNewline<'a>],
|
|
||||||
pub before_exposes: &'a [CommentOrNewline<'a>],
|
|
||||||
pub after_exposes: &'a [CommentOrNewline<'a>],
|
|
||||||
pub before_imports: &'a [CommentOrNewline<'a>],
|
|
||||||
pub after_imports: &'a [CommentOrNewline<'a>],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct HostedHeader<'a> {
|
pub struct HostedHeader<'a> {
|
||||||
|
pub before_name: &'a [CommentOrNewline<'a>],
|
||||||
pub name: Loc<ModuleName<'a>>,
|
pub name: Loc<ModuleName<'a>>,
|
||||||
pub exposes: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
pub exposes: KeywordItem<'a, ExposesKeyword, Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>>,
|
||||||
pub imports: Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>,
|
|
||||||
pub generates: UppercaseIdent<'a>,
|
|
||||||
pub generates_with: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
|
||||||
|
|
||||||
// Potential comments and newlines - these will typically all be empty.
|
pub imports: KeywordItem<'a, ImportsKeyword, Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>>,
|
||||||
pub before_header: &'a [CommentOrNewline<'a>],
|
|
||||||
pub after_hosted_keyword: &'a [CommentOrNewline<'a>],
|
pub generates: KeywordItem<'a, GeneratesKeyword, UppercaseIdent<'a>>,
|
||||||
pub before_exposes: &'a [CommentOrNewline<'a>],
|
pub generates_with:
|
||||||
pub after_exposes: &'a [CommentOrNewline<'a>],
|
KeywordItem<'a, WithKeyword, Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>>,
|
||||||
pub before_imports: &'a [CommentOrNewline<'a>],
|
|
||||||
pub after_imports: &'a [CommentOrNewline<'a>],
|
|
||||||
pub before_generates: &'a [CommentOrNewline<'a>],
|
|
||||||
pub after_generates: &'a [CommentOrNewline<'a>],
|
|
||||||
pub before_with: &'a [CommentOrNewline<'a>],
|
|
||||||
pub after_with: &'a [CommentOrNewline<'a>],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
@ -168,42 +189,39 @@ pub enum To<'a> {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct AppHeader<'a> {
|
pub struct AppHeader<'a> {
|
||||||
|
pub before_name: &'a [CommentOrNewline<'a>],
|
||||||
pub name: Loc<StrLiteral<'a>>,
|
pub name: Loc<StrLiteral<'a>>,
|
||||||
pub packages: Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>,
|
|
||||||
pub imports: Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>,
|
|
||||||
pub provides: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
|
||||||
pub provides_types: Option<Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>>,
|
|
||||||
pub to: Loc<To<'a>>,
|
|
||||||
|
|
||||||
// Potential comments and newlines - these will typically all be empty.
|
pub packages:
|
||||||
pub before_header: &'a [CommentOrNewline<'a>],
|
Option<KeywordItem<'a, PackagesKeyword, Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>>>,
|
||||||
pub after_app_keyword: &'a [CommentOrNewline<'a>],
|
pub imports:
|
||||||
pub before_packages: &'a [CommentOrNewline<'a>],
|
Option<KeywordItem<'a, ImportsKeyword, Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>>>,
|
||||||
pub after_packages: &'a [CommentOrNewline<'a>],
|
pub provides: ProvidesTo<'a>,
|
||||||
pub before_imports: &'a [CommentOrNewline<'a>],
|
}
|
||||||
pub after_imports: &'a [CommentOrNewline<'a>],
|
|
||||||
pub before_provides: &'a [CommentOrNewline<'a>],
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub after_provides: &'a [CommentOrNewline<'a>],
|
pub struct ProvidesTo<'a> {
|
||||||
pub before_to: &'a [CommentOrNewline<'a>],
|
pub provides_keyword: Spaces<'a, ProvidesKeyword>,
|
||||||
pub after_to: &'a [CommentOrNewline<'a>],
|
pub entries: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
||||||
|
pub types: Option<Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>>,
|
||||||
|
|
||||||
|
pub to_keyword: Spaces<'a, ToKeyword>,
|
||||||
|
pub to: Loc<To<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct PackageHeader<'a> {
|
pub struct PackageHeader<'a> {
|
||||||
|
pub before_name: &'a [CommentOrNewline<'a>],
|
||||||
pub name: Loc<PackageName<'a>>,
|
pub name: Loc<PackageName<'a>>,
|
||||||
pub exposes: Vec<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
|
||||||
pub packages: Vec<'a, (Loc<&'a str>, Loc<PackageName<'a>>)>,
|
|
||||||
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
|
|
||||||
|
|
||||||
// Potential comments and newlines - these will typically all be empty.
|
pub exposes_keyword: Spaces<'a, ExposesKeyword>,
|
||||||
pub before_header: &'a [CommentOrNewline<'a>],
|
pub exposes: Vec<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
||||||
pub after_package_keyword: &'a [CommentOrNewline<'a>],
|
|
||||||
pub before_exposes: &'a [CommentOrNewline<'a>],
|
pub packages_keyword: Spaces<'a, PackagesKeyword>,
|
||||||
pub after_exposes: &'a [CommentOrNewline<'a>],
|
pub packages: Vec<'a, (Loc<&'a str>, Loc<PackageName<'a>>)>,
|
||||||
pub before_packages: &'a [CommentOrNewline<'a>],
|
|
||||||
pub after_packages: &'a [CommentOrNewline<'a>],
|
pub imports_keyword: Spaces<'a, ImportsKeyword>,
|
||||||
pub before_imports: &'a [CommentOrNewline<'a>],
|
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
|
||||||
pub after_imports: &'a [CommentOrNewline<'a>],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
@ -214,26 +232,16 @@ pub struct PlatformRequires<'a> {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct PlatformHeader<'a> {
|
pub struct PlatformHeader<'a> {
|
||||||
|
pub before_name: &'a [CommentOrNewline<'a>],
|
||||||
pub name: Loc<PackageName<'a>>,
|
pub name: Loc<PackageName<'a>>,
|
||||||
pub requires: PlatformRequires<'a>,
|
|
||||||
pub exposes: Collection<'a, Loc<Spaced<'a, ModuleName<'a>>>>,
|
|
||||||
pub packages: Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>,
|
|
||||||
pub imports: Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>,
|
|
||||||
pub provides: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
|
||||||
|
|
||||||
// Potential comments and newlines - these will typically all be empty.
|
pub requires: KeywordItem<'a, RequiresKeyword, PlatformRequires<'a>>,
|
||||||
pub before_header: &'a [CommentOrNewline<'a>],
|
pub exposes: KeywordItem<'a, ExposesKeyword, Collection<'a, Loc<Spaced<'a, ModuleName<'a>>>>>,
|
||||||
pub after_platform_keyword: &'a [CommentOrNewline<'a>],
|
pub packages:
|
||||||
pub before_requires: &'a [CommentOrNewline<'a>],
|
KeywordItem<'a, PackagesKeyword, Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>>,
|
||||||
pub after_requires: &'a [CommentOrNewline<'a>],
|
pub imports: KeywordItem<'a, ImportsKeyword, Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>>,
|
||||||
pub before_exposes: &'a [CommentOrNewline<'a>],
|
pub provides:
|
||||||
pub after_exposes: &'a [CommentOrNewline<'a>],
|
KeywordItem<'a, ProvidesKeyword, Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>>,
|
||||||
pub before_packages: &'a [CommentOrNewline<'a>],
|
|
||||||
pub after_packages: &'a [CommentOrNewline<'a>],
|
|
||||||
pub before_imports: &'a [CommentOrNewline<'a>],
|
|
||||||
pub after_imports: &'a [CommentOrNewline<'a>],
|
|
||||||
pub before_provides: &'a [CommentOrNewline<'a>],
|
|
||||||
pub after_provides: &'a [CommentOrNewline<'a>],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
|
@ -270,50 +278,47 @@ pub struct PackageEntry<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPackageEntry<'a>> {
|
pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPackageEntry<'a>> {
|
||||||
move |arena, state, min_indent| {
|
map!(
|
||||||
// You may optionally have a package shorthand,
|
// You may optionally have a package shorthand,
|
||||||
// e.g. "uc" in `uc: roc/unicode 1.0.0`
|
// e.g. "uc" in `uc: roc/unicode 1.0.0`
|
||||||
//
|
//
|
||||||
// (Indirect dependencies don't have a shorthand.)
|
// (Indirect dependencies don't have a shorthand.)
|
||||||
let (_, opt_shorthand, state) = maybe!(and!(
|
and!(
|
||||||
skip_second!(
|
optional(and!(
|
||||||
specialize(|_, pos| EPackageEntry::Shorthand(pos), lowercase_ident()),
|
skip_second!(
|
||||||
word1(b':', EPackageEntry::Colon)
|
specialize(|_, pos| EPackageEntry::Shorthand(pos), lowercase_ident()),
|
||||||
),
|
word1(b':', EPackageEntry::Colon)
|
||||||
space0_e(EPackageEntry::IndentPackage)
|
),
|
||||||
))
|
space0_e(EPackageEntry::IndentPackage)
|
||||||
.parse(arena, state, min_indent)?;
|
)),
|
||||||
|
|
||||||
let (_, package_or_path, state) =
|
|
||||||
loc!(specialize(EPackageEntry::BadPackage, package_name()))
|
loc!(specialize(EPackageEntry::BadPackage, package_name()))
|
||||||
.parse(arena, state, min_indent)?;
|
),
|
||||||
|
move |(opt_shorthand, package_or_path)| {
|
||||||
|
let entry = match opt_shorthand {
|
||||||
|
Some((shorthand, spaces_after_shorthand)) => PackageEntry {
|
||||||
|
shorthand,
|
||||||
|
spaces_after_shorthand,
|
||||||
|
package_name: package_or_path,
|
||||||
|
},
|
||||||
|
None => PackageEntry {
|
||||||
|
shorthand: "",
|
||||||
|
spaces_after_shorthand: &[],
|
||||||
|
package_name: package_or_path,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
let entry = match opt_shorthand {
|
Spaced::Item(entry)
|
||||||
Some((shorthand, spaces_after_shorthand)) => PackageEntry {
|
}
|
||||||
shorthand,
|
)
|
||||||
spaces_after_shorthand,
|
|
||||||
package_name: package_or_path,
|
|
||||||
},
|
|
||||||
None => PackageEntry {
|
|
||||||
shorthand: "",
|
|
||||||
spaces_after_shorthand: &[],
|
|
||||||
package_name: package_or_path,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok((MadeProgress, Spaced::Item(entry), state))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn package_name<'a>() -> impl Parser<'a, PackageName<'a>, EPackageName<'a>> {
|
pub fn package_name<'a>() -> impl Parser<'a, PackageName<'a>, EPackageName<'a>> {
|
||||||
move |arena, state: State<'a>, min_indent: u32| {
|
then(
|
||||||
let pos = state.pos();
|
loc!(specialize(EPackageName::BadPath, string_literal::parse())),
|
||||||
specialize(EPackageName::BadPath, string_literal::parse())
|
move |_arena, state, progress, text| match text.value {
|
||||||
.parse(arena, state, min_indent)
|
StrLiteral::PlainLine(text) => Ok((progress, PackageName(text), state)),
|
||||||
.and_then(|(progress, text, next_state)| match text {
|
StrLiteral::Line(_) => Err((progress, EPackageName::Escapes(text.region.start()))),
|
||||||
StrLiteral::PlainLine(text) => Ok((progress, PackageName(text), next_state)),
|
StrLiteral::Block(_) => Err((progress, EPackageName::Multiline(text.region.start()))),
|
||||||
StrLiteral::Line(_) => Err((progress, EPackageName::Escapes(pos))),
|
},
|
||||||
StrLiteral::Block(_) => Err((progress, EPackageName::Multiline(pos))),
|
)
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
use crate::ast::{Collection, CommentOrNewline, Defs, Module, Spaced};
|
use crate::ast::{Collection, Defs, Header, Module, Spaced, Spaces};
|
||||||
use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
|
use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
|
||||||
use crate::header::{
|
use crate::header::{
|
||||||
package_entry, package_name, AppHeader, ExposedName, HostedHeader, ImportsEntry,
|
package_entry, package_name, AppHeader, ExposedName, ExposesKeyword, GeneratesKeyword,
|
||||||
InterfaceHeader, ModuleName, PackageEntry, PlatformHeader, PlatformRequires, To, TypedIdent,
|
HostedHeader, ImportsEntry, ImportsKeyword, InterfaceHeader, Keyword, KeywordItem, ModuleName,
|
||||||
|
PackageEntry, PackagesKeyword, PlatformHeader, PlatformRequires, ProvidesKeyword, ProvidesTo,
|
||||||
|
RequiresKeyword, To, ToKeyword, TypedIdent, WithKeyword,
|
||||||
};
|
};
|
||||||
use crate::ident::{self, lowercase_ident, unqualified_ident, uppercase, UppercaseIdent};
|
use crate::ident::{self, lowercase_ident, unqualified_ident, uppercase, UppercaseIdent};
|
||||||
use crate::parser::Progress::{self, *};
|
use crate::parser::Progress::{self, *};
|
||||||
|
@ -48,132 +50,63 @@ pub fn parse_header<'a>(
|
||||||
fn header<'a>() -> impl Parser<'a, Module<'a>, EHeader<'a>> {
|
fn header<'a>() -> impl Parser<'a, Module<'a>, EHeader<'a>> {
|
||||||
use crate::parser::keyword_e;
|
use crate::parser::keyword_e;
|
||||||
|
|
||||||
type Clos<'b> = Box<(dyn FnOnce(&'b [CommentOrNewline]) -> Module<'b> + 'b)>;
|
record!(Module {
|
||||||
|
comments: space0_e(EHeader::IndentStart),
|
||||||
map!(
|
header: one_of![
|
||||||
and!(
|
map!(
|
||||||
space0_e(EHeader::IndentStart),
|
skip_first!(
|
||||||
one_of![
|
keyword_e("interface", EHeader::Start),
|
||||||
map!(
|
increment_min_indent(interface_header())
|
||||||
skip_first!(
|
|
||||||
keyword_e("interface", EHeader::Start),
|
|
||||||
increment_min_indent(interface_header())
|
|
||||||
),
|
|
||||||
|mut header: InterfaceHeader<'a>| -> Clos<'a> {
|
|
||||||
Box::new(|spaces| {
|
|
||||||
header.before_header = spaces;
|
|
||||||
Module::Interface { header }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
),
|
),
|
||||||
map!(
|
Header::Interface
|
||||||
skip_first!(
|
),
|
||||||
keyword_e("app", EHeader::Start),
|
map!(
|
||||||
increment_min_indent(app_header())
|
skip_first!(
|
||||||
),
|
keyword_e("app", EHeader::Start),
|
||||||
|mut header: AppHeader<'a>| -> Clos<'a> {
|
increment_min_indent(app_header())
|
||||||
Box::new(|spaces| {
|
|
||||||
header.before_header = spaces;
|
|
||||||
Module::App { header }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
),
|
),
|
||||||
map!(
|
Header::App
|
||||||
skip_first!(
|
),
|
||||||
keyword_e("platform", EHeader::Start),
|
map!(
|
||||||
increment_min_indent(platform_header())
|
skip_first!(
|
||||||
),
|
keyword_e("platform", EHeader::Start),
|
||||||
|mut header: PlatformHeader<'a>| -> Clos<'a> {
|
increment_min_indent(platform_header())
|
||||||
Box::new(|spaces| {
|
|
||||||
header.before_header = spaces;
|
|
||||||
Module::Platform { header }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
),
|
),
|
||||||
map!(
|
Header::Platform
|
||||||
skip_first!(
|
),
|
||||||
keyword_e("hosted", EHeader::Start),
|
map!(
|
||||||
increment_min_indent(hosted_header())
|
skip_first!(
|
||||||
),
|
keyword_e("hosted", EHeader::Start),
|
||||||
|mut header: HostedHeader<'a>| -> Clos<'a> {
|
increment_min_indent(hosted_header())
|
||||||
Box::new(|spaces| {
|
),
|
||||||
header.before_header = spaces;
|
Header::Hosted
|
||||||
Module::Hosted { header }
|
),
|
||||||
})
|
]
|
||||||
}
|
})
|
||||||
)
|
|
||||||
]
|
|
||||||
),
|
|
||||||
|(spaces, make_header): (&'a [CommentOrNewline], Clos<'a>)| { make_header(spaces) }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn interface_header<'a>() -> impl Parser<'a, InterfaceHeader<'a>, EHeader<'a>> {
|
fn interface_header<'a>() -> impl Parser<'a, InterfaceHeader<'a>, EHeader<'a>> {
|
||||||
|arena, state, min_indent: u32| {
|
record!(InterfaceHeader {
|
||||||
let (_, after_interface_keyword, state) =
|
before_name: space0_e(EHeader::IndentStart),
|
||||||
space0_e(EHeader::IndentStart).parse(arena, state, min_indent)?;
|
name: loc!(module_name_help(EHeader::ModuleName)),
|
||||||
let (_, name, state) =
|
exposes: specialize(EHeader::Exposes, exposes_values()),
|
||||||
loc!(module_name_help(EHeader::ModuleName)).parse(arena, state, min_indent)?;
|
imports: specialize(EHeader::Imports, imports()),
|
||||||
|
})
|
||||||
let (_, ((before_exposes, after_exposes), exposes), state) =
|
.trace("interface_header")
|
||||||
specialize(EHeader::Exposes, exposes_values()).parse(arena, state, min_indent)?;
|
|
||||||
let (_, ((before_imports, after_imports), imports), state) =
|
|
||||||
specialize(EHeader::Imports, imports()).parse(arena, state, min_indent)?;
|
|
||||||
|
|
||||||
let header = InterfaceHeader {
|
|
||||||
name,
|
|
||||||
exposes,
|
|
||||||
imports,
|
|
||||||
before_header: &[] as &[_],
|
|
||||||
after_interface_keyword,
|
|
||||||
before_exposes,
|
|
||||||
after_exposes,
|
|
||||||
before_imports,
|
|
||||||
after_imports,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok((MadeProgress, header, state))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn hosted_header<'a>() -> impl Parser<'a, HostedHeader<'a>, EHeader<'a>> {
|
fn hosted_header<'a>() -> impl Parser<'a, HostedHeader<'a>, EHeader<'a>> {
|
||||||
|arena, state, min_indent: u32| {
|
record!(HostedHeader {
|
||||||
let (_, after_hosted_keyword, state) =
|
before_name: space0_e(EHeader::IndentStart),
|
||||||
space0_e(EHeader::IndentStart).parse(arena, state, min_indent)?;
|
name: loc!(module_name_help(EHeader::ModuleName)),
|
||||||
let (_, name, state) =
|
exposes: specialize(EHeader::Exposes, exposes_values()),
|
||||||
loc!(module_name_help(EHeader::ModuleName)).parse(arena, state, min_indent)?;
|
imports: specialize(EHeader::Imports, imports()),
|
||||||
|
generates: specialize(EHeader::Generates, generates()),
|
||||||
let (_, ((before_exposes, after_exposes), exposes), state) =
|
generates_with: specialize(EHeader::GeneratesWith, generates_with()),
|
||||||
specialize(EHeader::Exposes, exposes_values()).parse(arena, state, min_indent)?;
|
})
|
||||||
let (_, ((before_imports, after_imports), imports), state) =
|
.trace("hosted_header")
|
||||||
specialize(EHeader::Imports, imports()).parse(arena, state, min_indent)?;
|
|
||||||
let (_, ((before_generates, after_generates), generates), state) =
|
|
||||||
specialize(EHeader::Generates, generates()).parse(arena, state, min_indent)?;
|
|
||||||
let (_, ((before_with, after_with), generates_with), state) =
|
|
||||||
specialize(EHeader::GeneratesWith, generates_with()).parse(arena, state, min_indent)?;
|
|
||||||
|
|
||||||
let header = HostedHeader {
|
|
||||||
name,
|
|
||||||
exposes,
|
|
||||||
imports,
|
|
||||||
generates,
|
|
||||||
generates_with,
|
|
||||||
before_header: &[] as &[_],
|
|
||||||
after_hosted_keyword,
|
|
||||||
before_exposes,
|
|
||||||
after_exposes,
|
|
||||||
before_imports,
|
|
||||||
after_imports,
|
|
||||||
before_generates,
|
|
||||||
after_generates,
|
|
||||||
before_with,
|
|
||||||
after_with,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok((MadeProgress, header, state))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chomp_module_name(buffer: &[u8]) -> Result<&str, Progress> {
|
fn chomp_module_name(buffer: &[u8]) -> Result<&str, Progress> {
|
||||||
|
@ -237,127 +170,31 @@ fn module_name<'a>() -> impl Parser<'a, ModuleName<'a>, ()> {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
|
fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
|
||||||
|arena, state, min_indent: u32| {
|
record!(AppHeader {
|
||||||
let (_, after_app_keyword, state) =
|
before_name: space0_e(EHeader::IndentStart),
|
||||||
space0_e(EHeader::IndentStart).parse(arena, state, min_indent)?;
|
name: loc!(crate::parser::specialize(
|
||||||
let (_, name, state) = loc!(crate::parser::specialize(
|
|
||||||
EHeader::AppName,
|
EHeader::AppName,
|
||||||
string_literal::parse()
|
string_literal::parse()
|
||||||
))
|
)),
|
||||||
.parse(arena, state, min_indent)?;
|
packages: optional(specialize(EHeader::Packages, packages())),
|
||||||
|
imports: optional(specialize(EHeader::Imports, imports())),
|
||||||
let (_, opt_pkgs, state) =
|
provides: specialize(EHeader::Provides, provides_to()),
|
||||||
maybe!(specialize(EHeader::Packages, packages())).parse(arena, state, min_indent)?;
|
})
|
||||||
let (_, opt_imports, state) =
|
.trace("app_header")
|
||||||
maybe!(specialize(EHeader::Imports, imports())).parse(arena, state, min_indent)?;
|
|
||||||
let (_, provides, state) =
|
|
||||||
specialize(EHeader::Provides, provides_to()).parse(arena, state, min_indent)?;
|
|
||||||
|
|
||||||
let (before_packages, after_packages, packages) = match opt_pkgs {
|
|
||||||
Some(pkgs) => {
|
|
||||||
let pkgs: Packages<'a> = pkgs; // rustc must be told the type here
|
|
||||||
|
|
||||||
(
|
|
||||||
pkgs.before_packages_keyword,
|
|
||||||
pkgs.after_packages_keyword,
|
|
||||||
pkgs.entries,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => (&[] as _, &[] as _, Collection::empty()),
|
|
||||||
};
|
|
||||||
|
|
||||||
// rustc must be told the type here
|
|
||||||
#[allow(clippy::type_complexity)]
|
|
||||||
let opt_imports: Option<(
|
|
||||||
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
|
||||||
Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>,
|
|
||||||
)> = opt_imports;
|
|
||||||
|
|
||||||
let ((before_imports, after_imports), imports) =
|
|
||||||
opt_imports.unwrap_or_else(|| ((&[] as _, &[] as _), Collection::empty()));
|
|
||||||
let provides: ProvidesTo<'a> = provides; // rustc must be told the type here
|
|
||||||
|
|
||||||
let header = AppHeader {
|
|
||||||
name,
|
|
||||||
packages,
|
|
||||||
imports,
|
|
||||||
provides: provides.entries,
|
|
||||||
provides_types: provides.types,
|
|
||||||
to: provides.to,
|
|
||||||
before_header: &[] as &[_],
|
|
||||||
after_app_keyword,
|
|
||||||
before_packages,
|
|
||||||
after_packages,
|
|
||||||
before_imports,
|
|
||||||
after_imports,
|
|
||||||
before_provides: provides.before_provides_keyword,
|
|
||||||
after_provides: provides.after_provides_keyword,
|
|
||||||
before_to: provides.before_to_keyword,
|
|
||||||
after_to: provides.after_to_keyword,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok((MadeProgress, header, state))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn platform_header<'a>() -> impl Parser<'a, PlatformHeader<'a>, EHeader<'a>> {
|
fn platform_header<'a>() -> impl Parser<'a, PlatformHeader<'a>, EHeader<'a>> {
|
||||||
|arena, state, min_indent: u32| {
|
record!(PlatformHeader {
|
||||||
let (_, after_platform_keyword, state) =
|
before_name: space0_e(EHeader::IndentStart),
|
||||||
space0_e(EHeader::IndentStart).parse(arena, state, min_indent)?;
|
name: loc!(specialize(EHeader::PlatformName, package_name())),
|
||||||
let (_, name, state) = loc!(specialize(EHeader::PlatformName, package_name()))
|
requires: specialize(EHeader::Requires, requires()),
|
||||||
.parse(arena, state, min_indent)?;
|
exposes: specialize(EHeader::Exposes, exposes_modules()),
|
||||||
|
packages: specialize(EHeader::Packages, packages()),
|
||||||
let (_, ((before_requires, after_requires), requires), state) =
|
imports: specialize(EHeader::Imports, imports()),
|
||||||
specialize(EHeader::Requires, requires()).parse(arena, state, min_indent)?;
|
provides: specialize(EHeader::Provides, provides_exposed()),
|
||||||
|
})
|
||||||
let (_, ((before_exposes, after_exposes), exposes), state) =
|
.trace("platform_header")
|
||||||
specialize(EHeader::Exposes, exposes_modules()).parse(arena, state, min_indent)?;
|
|
||||||
|
|
||||||
let (_, packages, state) =
|
|
||||||
specialize(EHeader::Packages, packages()).parse(arena, state, min_indent)?;
|
|
||||||
|
|
||||||
let (_, ((before_imports, after_imports), imports), state) =
|
|
||||||
specialize(EHeader::Imports, imports()).parse(arena, state, min_indent)?;
|
|
||||||
|
|
||||||
let (_, ((before_provides, after_provides), (provides, _provides_type)), state) =
|
|
||||||
specialize(EHeader::Provides, provides_without_to()).parse(arena, state, min_indent)?;
|
|
||||||
|
|
||||||
let header = PlatformHeader {
|
|
||||||
name,
|
|
||||||
requires,
|
|
||||||
exposes,
|
|
||||||
packages: packages.entries,
|
|
||||||
imports,
|
|
||||||
provides,
|
|
||||||
before_header: &[] as &[_],
|
|
||||||
after_platform_keyword,
|
|
||||||
before_requires,
|
|
||||||
after_requires,
|
|
||||||
before_exposes,
|
|
||||||
after_exposes,
|
|
||||||
before_packages: packages.before_packages_keyword,
|
|
||||||
after_packages: packages.after_packages_keyword,
|
|
||||||
before_imports,
|
|
||||||
after_imports,
|
|
||||||
before_provides,
|
|
||||||
after_provides,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok((MadeProgress, header, state))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct ProvidesTo<'a> {
|
|
||||||
entries: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
|
||||||
types: Option<Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>>,
|
|
||||||
to: Loc<To<'a>>,
|
|
||||||
|
|
||||||
before_provides_keyword: &'a [CommentOrNewline<'a>],
|
|
||||||
after_provides_keyword: &'a [CommentOrNewline<'a>],
|
|
||||||
before_to_keyword: &'a [CommentOrNewline<'a>],
|
|
||||||
after_to_keyword: &'a [CommentOrNewline<'a>],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn provides_to_package<'a>() -> impl Parser<'a, To<'a>, EProvides<'a>> {
|
fn provides_to_package<'a>() -> impl Parser<'a, To<'a>, EProvides<'a>> {
|
||||||
|
@ -372,68 +209,54 @@ fn provides_to_package<'a>() -> impl Parser<'a, To<'a>, EProvides<'a>> {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn provides_to<'a>() -> impl Parser<'a, ProvidesTo<'a>, EProvides<'a>> {
|
fn provides_to<'a>() -> impl Parser<'a, ProvidesTo<'a>, EProvides<'a>> {
|
||||||
map!(
|
record!(ProvidesTo {
|
||||||
and!(
|
provides_keyword: spaces_around_keyword(
|
||||||
provides_without_to(),
|
ProvidesKeyword,
|
||||||
and!(
|
|
||||||
spaces_around_keyword(
|
|
||||||
"to",
|
|
||||||
EProvides::To,
|
|
||||||
EProvides::IndentTo,
|
|
||||||
EProvides::IndentListStart
|
|
||||||
),
|
|
||||||
loc!(provides_to_package())
|
|
||||||
)
|
|
||||||
),
|
|
||||||
|(
|
|
||||||
((before_provides_keyword, after_provides_keyword), (entries, provides_types)),
|
|
||||||
((before_to_keyword, after_to_keyword), to),
|
|
||||||
)| {
|
|
||||||
ProvidesTo {
|
|
||||||
entries,
|
|
||||||
types: provides_types,
|
|
||||||
to,
|
|
||||||
before_provides_keyword,
|
|
||||||
after_provides_keyword,
|
|
||||||
before_to_keyword,
|
|
||||||
after_to_keyword,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn provides_without_to<'a>() -> impl Parser<
|
|
||||||
'a,
|
|
||||||
(
|
|
||||||
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
|
||||||
(
|
|
||||||
Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
|
||||||
Option<Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>>,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
EProvides<'a>,
|
|
||||||
> {
|
|
||||||
and!(
|
|
||||||
spaces_around_keyword(
|
|
||||||
"provides",
|
|
||||||
EProvides::Provides,
|
EProvides::Provides,
|
||||||
EProvides::IndentProvides,
|
EProvides::IndentProvides,
|
||||||
EProvides::IndentListStart
|
EProvides::IndentListStart
|
||||||
),
|
),
|
||||||
and!(
|
entries: collection_trailing_sep_e!(
|
||||||
collection_trailing_sep_e!(
|
word1(b'[', EProvides::ListStart),
|
||||||
word1(b'[', EProvides::ListStart),
|
exposes_entry(EProvides::Identifier),
|
||||||
exposes_entry(EProvides::Identifier),
|
word1(b',', EProvides::ListEnd),
|
||||||
word1(b',', EProvides::ListEnd),
|
word1(b']', EProvides::ListEnd),
|
||||||
word1(b']', EProvides::ListEnd),
|
EProvides::IndentListEnd,
|
||||||
EProvides::IndentListEnd,
|
Spaced::SpaceBefore
|
||||||
Spaced::SpaceBefore
|
),
|
||||||
),
|
types: optional(backtrackable(provides_types())),
|
||||||
// Optionally
|
to_keyword: spaces_around_keyword(
|
||||||
optional(provides_types())
|
ToKeyword,
|
||||||
)
|
EProvides::To,
|
||||||
)
|
EProvides::IndentTo,
|
||||||
|
EProvides::IndentListStart
|
||||||
|
),
|
||||||
|
to: loc!(provides_to_package()),
|
||||||
|
})
|
||||||
|
.trace("provides_to")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn provides_exposed<'a>() -> impl Parser<
|
||||||
|
'a,
|
||||||
|
KeywordItem<'a, ProvidesKeyword, Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>>,
|
||||||
|
EProvides<'a>,
|
||||||
|
> {
|
||||||
|
record!(KeywordItem {
|
||||||
|
keyword: spaces_around_keyword(
|
||||||
|
ProvidesKeyword,
|
||||||
|
EProvides::Provides,
|
||||||
|
EProvides::IndentProvides,
|
||||||
|
EProvides::IndentListStart
|
||||||
|
),
|
||||||
|
item: collection_trailing_sep_e!(
|
||||||
|
word1(b'[', EProvides::ListStart),
|
||||||
|
exposes_entry(EProvides::Identifier),
|
||||||
|
word1(b',', EProvides::ListEnd),
|
||||||
|
word1(b']', EProvides::ListEnd),
|
||||||
|
EProvides::IndentListEnd,
|
||||||
|
Spaced::SpaceBefore
|
||||||
|
),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -491,34 +314,25 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn requires<'a>() -> impl Parser<
|
fn requires<'a>(
|
||||||
'a,
|
) -> impl Parser<'a, KeywordItem<'a, RequiresKeyword, PlatformRequires<'a>>, ERequires<'a>> {
|
||||||
(
|
record!(KeywordItem {
|
||||||
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
keyword: spaces_around_keyword(
|
||||||
PlatformRequires<'a>,
|
RequiresKeyword,
|
||||||
),
|
|
||||||
ERequires<'a>,
|
|
||||||
> {
|
|
||||||
and!(
|
|
||||||
spaces_around_keyword(
|
|
||||||
"requires",
|
|
||||||
ERequires::Requires,
|
ERequires::Requires,
|
||||||
ERequires::IndentRequires,
|
ERequires::IndentRequires,
|
||||||
ERequires::IndentListStart
|
ERequires::IndentListStart
|
||||||
),
|
),
|
||||||
platform_requires()
|
item: platform_requires(),
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn platform_requires<'a>() -> impl Parser<'a, PlatformRequires<'a>, ERequires<'a>> {
|
fn platform_requires<'a>() -> impl Parser<'a, PlatformRequires<'a>, ERequires<'a>> {
|
||||||
map!(
|
record!(PlatformRequires {
|
||||||
and!(
|
rigids: skip_second!(requires_rigids(), space0_e(ERequires::ListStart)),
|
||||||
skip_second!(requires_rigids(), space0_e(ERequires::ListStart)),
|
signature: requires_typed_ident()
|
||||||
requires_typed_ident()
|
})
|
||||||
),
|
|
||||||
|(rigids, signature)| { PlatformRequires { rigids, signature } }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -555,20 +369,17 @@ fn requires_typed_ident<'a>() -> impl Parser<'a, Loc<Spaced<'a, TypedIdent<'a>>>
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn exposes_values<'a>() -> impl Parser<
|
fn exposes_values<'a>() -> impl Parser<
|
||||||
'a,
|
'a,
|
||||||
(
|
KeywordItem<'a, ExposesKeyword, Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>>,
|
||||||
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
|
||||||
Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
|
||||||
),
|
|
||||||
EExposes,
|
EExposes,
|
||||||
> {
|
> {
|
||||||
and!(
|
record!(KeywordItem {
|
||||||
spaces_around_keyword(
|
keyword: spaces_around_keyword(
|
||||||
"exposes",
|
ExposesKeyword,
|
||||||
EExposes::Exposes,
|
EExposes::Exposes,
|
||||||
EExposes::IndentExposes,
|
EExposes::IndentExposes,
|
||||||
EExposes::IndentListStart
|
EExposes::IndentListStart
|
||||||
),
|
),
|
||||||
collection_trailing_sep_e!(
|
item: collection_trailing_sep_e!(
|
||||||
word1(b'[', EExposes::ListStart),
|
word1(b'[', EExposes::ListStart),
|
||||||
exposes_entry(EExposes::Identifier),
|
exposes_entry(EExposes::Identifier),
|
||||||
word1(b',', EExposes::ListEnd),
|
word1(b',', EExposes::ListEnd),
|
||||||
|
@ -576,52 +387,58 @@ fn exposes_values<'a>() -> impl Parser<
|
||||||
EExposes::IndentListEnd,
|
EExposes::IndentListEnd,
|
||||||
Spaced::SpaceBefore
|
Spaced::SpaceBefore
|
||||||
)
|
)
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spaces_around_keyword<'a, E>(
|
fn spaces_around_keyword<'a, K: Keyword, E>(
|
||||||
keyword: &'static str,
|
keyword_item: K,
|
||||||
expectation: fn(Position) -> E,
|
expectation: fn(Position) -> E,
|
||||||
indent_problem1: fn(Position) -> E,
|
indent_problem1: fn(Position) -> E,
|
||||||
indent_problem2: fn(Position) -> E,
|
indent_problem2: fn(Position) -> E,
|
||||||
) -> impl Parser<'a, (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), E>
|
) -> impl Parser<'a, Spaces<'a, K>, E>
|
||||||
where
|
where
|
||||||
E: 'a + SpaceProblem,
|
E: 'a + SpaceProblem,
|
||||||
{
|
{
|
||||||
and!(
|
map!(
|
||||||
skip_second!(
|
and!(
|
||||||
backtrackable(space0_e(indent_problem1)),
|
skip_second!(
|
||||||
crate::parser::keyword_e(keyword, expectation)
|
backtrackable(space0_e(indent_problem1)),
|
||||||
|
crate::parser::keyword_e(K::KEYWORD, expectation)
|
||||||
|
),
|
||||||
|
space0_e(indent_problem2)
|
||||||
),
|
),
|
||||||
space0_e(indent_problem2)
|
|(before, after)| {
|
||||||
|
Spaces {
|
||||||
|
before,
|
||||||
|
item: keyword_item,
|
||||||
|
after,
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn exposes_modules<'a>() -> impl Parser<
|
fn exposes_modules<'a>() -> impl Parser<
|
||||||
'a,
|
'a,
|
||||||
(
|
KeywordItem<'a, ExposesKeyword, Collection<'a, Loc<Spaced<'a, ModuleName<'a>>>>>,
|
||||||
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
|
||||||
Collection<'a, Loc<Spaced<'a, ModuleName<'a>>>>,
|
|
||||||
),
|
|
||||||
EExposes,
|
EExposes,
|
||||||
> {
|
> {
|
||||||
and!(
|
record!(KeywordItem {
|
||||||
spaces_around_keyword(
|
keyword: spaces_around_keyword(
|
||||||
"exposes",
|
ExposesKeyword,
|
||||||
EExposes::Exposes,
|
EExposes::Exposes,
|
||||||
EExposes::IndentExposes,
|
EExposes::IndentExposes,
|
||||||
EExposes::IndentListStart
|
EExposes::IndentListStart
|
||||||
),
|
),
|
||||||
collection_trailing_sep_e!(
|
item: collection_trailing_sep_e!(
|
||||||
word1(b'[', EExposes::ListStart),
|
word1(b'[', EExposes::ListStart),
|
||||||
exposes_module(EExposes::Identifier),
|
exposes_module(EExposes::Identifier),
|
||||||
word1(b',', EExposes::ListEnd),
|
word1(b',', EExposes::ListEnd),
|
||||||
word1(b']', EExposes::ListEnd),
|
word1(b']', EExposes::ListEnd),
|
||||||
EExposes::IndentListEnd,
|
EExposes::IndentListEnd,
|
||||||
Spaced::SpaceBefore
|
Spaced::SpaceBefore
|
||||||
)
|
),
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exposes_module<'a, F, E>(
|
fn exposes_module<'a, F, E>(
|
||||||
|
@ -638,82 +455,58 @@ where
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Packages<'a> {
|
|
||||||
entries: Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>,
|
|
||||||
before_packages_keyword: &'a [CommentOrNewline<'a>],
|
|
||||||
after_packages_keyword: &'a [CommentOrNewline<'a>],
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn packages<'a>() -> impl Parser<'a, Packages<'a>, EPackages<'a>> {
|
fn packages<'a>() -> impl Parser<
|
||||||
map!(
|
|
||||||
and!(
|
|
||||||
spaces_around_keyword(
|
|
||||||
"packages",
|
|
||||||
EPackages::Packages,
|
|
||||||
EPackages::IndentPackages,
|
|
||||||
EPackages::IndentListStart
|
|
||||||
),
|
|
||||||
collection_trailing_sep_e!(
|
|
||||||
word1(b'{', EPackages::ListStart),
|
|
||||||
specialize(EPackages::PackageEntry, loc!(package_entry())),
|
|
||||||
word1(b',', EPackages::ListEnd),
|
|
||||||
word1(b'}', EPackages::ListEnd),
|
|
||||||
EPackages::IndentListEnd,
|
|
||||||
Spaced::SpaceBefore
|
|
||||||
)
|
|
||||||
),
|
|
||||||
|((before_packages_keyword, after_packages_keyword), entries): (
|
|
||||||
(_, _),
|
|
||||||
Collection<'a, _>
|
|
||||||
)| {
|
|
||||||
Packages {
|
|
||||||
entries,
|
|
||||||
before_packages_keyword,
|
|
||||||
after_packages_keyword,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn generates<'a>() -> impl Parser<
|
|
||||||
'a,
|
'a,
|
||||||
(
|
KeywordItem<'a, PackagesKeyword, Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>>,
|
||||||
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
EPackages<'a>,
|
||||||
UppercaseIdent<'a>,
|
|
||||||
),
|
|
||||||
EGenerates,
|
|
||||||
> {
|
> {
|
||||||
and!(
|
record!(KeywordItem {
|
||||||
spaces_around_keyword(
|
keyword: spaces_around_keyword(
|
||||||
"generates",
|
PackagesKeyword,
|
||||||
|
EPackages::Packages,
|
||||||
|
EPackages::IndentPackages,
|
||||||
|
EPackages::IndentListStart
|
||||||
|
),
|
||||||
|
item: collection_trailing_sep_e!(
|
||||||
|
word1(b'{', EPackages::ListStart),
|
||||||
|
specialize(EPackages::PackageEntry, loc!(package_entry())),
|
||||||
|
word1(b',', EPackages::ListEnd),
|
||||||
|
word1(b'}', EPackages::ListEnd),
|
||||||
|
EPackages::IndentListEnd,
|
||||||
|
Spaced::SpaceBefore
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn generates<'a>(
|
||||||
|
) -> impl Parser<'a, KeywordItem<'a, GeneratesKeyword, UppercaseIdent<'a>>, EGenerates> {
|
||||||
|
record!(KeywordItem {
|
||||||
|
keyword: spaces_around_keyword(
|
||||||
|
GeneratesKeyword,
|
||||||
EGenerates::Generates,
|
EGenerates::Generates,
|
||||||
EGenerates::IndentGenerates,
|
EGenerates::IndentGenerates,
|
||||||
EGenerates::IndentTypeStart
|
EGenerates::IndentTypeStart
|
||||||
),
|
),
|
||||||
specialize(|(), pos| EGenerates::Identifier(pos), uppercase())
|
item: specialize(|(), pos| EGenerates::Identifier(pos), uppercase())
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn generates_with<'a>() -> impl Parser<
|
fn generates_with<'a>() -> impl Parser<
|
||||||
'a,
|
'a,
|
||||||
(
|
KeywordItem<'a, WithKeyword, Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>>,
|
||||||
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
|
||||||
Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
|
||||||
),
|
|
||||||
EGeneratesWith,
|
EGeneratesWith,
|
||||||
> {
|
> {
|
||||||
and!(
|
record!(KeywordItem {
|
||||||
spaces_around_keyword(
|
keyword: spaces_around_keyword(
|
||||||
"with",
|
WithKeyword,
|
||||||
EGeneratesWith::With,
|
EGeneratesWith::With,
|
||||||
EGeneratesWith::IndentWith,
|
EGeneratesWith::IndentWith,
|
||||||
EGeneratesWith::IndentListStart
|
EGeneratesWith::IndentListStart
|
||||||
),
|
),
|
||||||
collection_trailing_sep_e!(
|
item: collection_trailing_sep_e!(
|
||||||
word1(b'[', EGeneratesWith::ListStart),
|
word1(b'[', EGeneratesWith::ListStart),
|
||||||
exposes_entry(EGeneratesWith::Identifier),
|
exposes_entry(EGeneratesWith::Identifier),
|
||||||
word1(b',', EGeneratesWith::ListEnd),
|
word1(b',', EGeneratesWith::ListEnd),
|
||||||
|
@ -721,26 +514,23 @@ fn generates_with<'a>() -> impl Parser<
|
||||||
EGeneratesWith::IndentListEnd,
|
EGeneratesWith::IndentListEnd,
|
||||||
Spaced::SpaceBefore
|
Spaced::SpaceBefore
|
||||||
)
|
)
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn imports<'a>() -> impl Parser<
|
fn imports<'a>() -> impl Parser<
|
||||||
'a,
|
'a,
|
||||||
(
|
KeywordItem<'a, ImportsKeyword, Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>>,
|
||||||
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
|
|
||||||
Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>,
|
|
||||||
),
|
|
||||||
EImports,
|
EImports,
|
||||||
> {
|
> {
|
||||||
and!(
|
record!(KeywordItem {
|
||||||
spaces_around_keyword(
|
keyword: spaces_around_keyword(
|
||||||
"imports",
|
ImportsKeyword,
|
||||||
EImports::Imports,
|
EImports::Imports,
|
||||||
EImports::IndentImports,
|
EImports::IndentImports,
|
||||||
EImports::IndentListStart
|
EImports::IndentListStart
|
||||||
),
|
),
|
||||||
collection_trailing_sep_e!(
|
item: collection_trailing_sep_e!(
|
||||||
word1(b'[', EImports::ListStart),
|
word1(b'[', EImports::ListStart),
|
||||||
loc!(imports_entry()),
|
loc!(imports_entry()),
|
||||||
word1(b',', EImports::ListEnd),
|
word1(b',', EImports::ListEnd),
|
||||||
|
@ -748,7 +538,8 @@ fn imports<'a>() -> impl Parser<
|
||||||
EImports::IndentListEnd,
|
EImports::IndentListEnd,
|
||||||
Spaced::SpaceBefore
|
Spaced::SpaceBefore
|
||||||
)
|
)
|
||||||
)
|
})
|
||||||
|
.trace("imports")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -810,15 +601,15 @@ fn imports_entry<'a>() -> impl Parser<'a, Spaced<'a, ImportsEntry<'a>>, EImports
|
||||||
and!(
|
and!(
|
||||||
and!(
|
and!(
|
||||||
// e.g. `pf.`
|
// e.g. `pf.`
|
||||||
maybe!(skip_second!(
|
optional(backtrackable(skip_second!(
|
||||||
shortname(),
|
shortname(),
|
||||||
word1(b'.', EImports::ShorthandDot)
|
word1(b'.', EImports::ShorthandDot)
|
||||||
)),
|
))),
|
||||||
// e.g. `Task`
|
// e.g. `Task`
|
||||||
module_name_help(EImports::ModuleName)
|
module_name_help(EImports::ModuleName)
|
||||||
),
|
),
|
||||||
// e.g. `.{ Task, after}`
|
// e.g. `.{ Task, after}`
|
||||||
maybe!(skip_first!(
|
optional(skip_first!(
|
||||||
word1(b'.', EImports::ExposingDot),
|
word1(b'.', EImports::ExposingDot),
|
||||||
collection_trailing_sep_e!(
|
collection_trailing_sep_e!(
|
||||||
word1(b'{', EImports::SetStart),
|
word1(b'{', EImports::SetStart),
|
||||||
|
@ -842,4 +633,5 @@ fn imports_entry<'a>() -> impl Parser<'a, Spaced<'a, ImportsEntry<'a>>, EImports
|
||||||
Spaced::Item(entry)
|
Spaced::Item(entry)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
.trace("imports_entry")
|
||||||
}
|
}
|
||||||
|
|
|
@ -852,13 +852,14 @@ where
|
||||||
self.message
|
self.message
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let previous_state = state.clone();
|
||||||
INDENT.with(|i| *i.borrow_mut() += 1);
|
INDENT.with(|i| *i.borrow_mut() += 1);
|
||||||
let res = self.parser.parse(arena, state, min_indent);
|
let res = self.parser.parse(arena, state, min_indent);
|
||||||
INDENT.with(|i| *i.borrow_mut() = cur_indent);
|
INDENT.with(|i| *i.borrow_mut() = cur_indent);
|
||||||
|
|
||||||
let (progress, value, state) = match &res {
|
let (progress, value, state) = match &res {
|
||||||
Ok((progress, result, state)) => (progress, Ok(result), state),
|
Ok((progress, result, state)) => (progress, Ok(result), state),
|
||||||
Err((progress, error)) => (progress, Err(error), state),
|
Err((progress, error)) => (progress, Err(error), &previous_state),
|
||||||
};
|
};
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
|
@ -1229,11 +1230,8 @@ where
|
||||||
|
|
||||||
match parser.parse(arena, state, min_indent) {
|
match parser.parse(arena, state, min_indent) {
|
||||||
Ok((progress, out1, state)) => Ok((progress, Some(out1), state)),
|
Ok((progress, out1, state)) => Ok((progress, Some(out1), state)),
|
||||||
Err((_, _)) => {
|
Err((MadeProgress, e)) => Err((MadeProgress, e)),
|
||||||
// NOTE this will backtrack
|
Err((NoProgress, _)) => Ok((NoProgress, None, original_state)),
|
||||||
// TODO can we get rid of some of the potential backtracking?
|
|
||||||
Ok((NoProgress, None, original_state))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1435,6 +1433,25 @@ macro_rules! and {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Take as input something that looks like a struct literal where values are parsers
|
||||||
|
/// and return a parser that runs each parser and returns a struct literal with the
|
||||||
|
/// results.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! record {
|
||||||
|
($name:ident $(:: $name_ext:ident)* { $($field:ident: $parser:expr),* $(,)? }) => {
|
||||||
|
move |arena: &'a bumpalo::Bump, state: $crate::state::State<'a>, min_indent: u32| {
|
||||||
|
let mut state = state;
|
||||||
|
let mut progress = NoProgress;
|
||||||
|
$(
|
||||||
|
let (new_progress, $field, new_state) = $parser.parse(arena, state, min_indent)?;
|
||||||
|
state = new_state;
|
||||||
|
progress = progress.or(new_progress);
|
||||||
|
)*
|
||||||
|
Ok((progress, $name $(:: $name_ext)* { $($field),* }, state))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Similar to `and`, but we modify the min_indent of the second parser to be
|
/// Similar to `and`, but we modify the min_indent of the second parser to be
|
||||||
/// 1 greater than the line_indent() at the start of the first parser.
|
/// 1 greater than the line_indent() at the start of the first parser.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
@ -1507,21 +1524,6 @@ macro_rules! one_of {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! maybe {
|
|
||||||
($p1:expr) => {
|
|
||||||
move |arena: &'a bumpalo::Bump, state: $crate::state::State<'a>, min_indent: u32| {
|
|
||||||
let original_state = state.clone();
|
|
||||||
|
|
||||||
match $p1.parse(arena, state, min_indent) {
|
|
||||||
Ok((progress, value, state)) => Ok((progress, Some(value), state)),
|
|
||||||
Err((MadeProgress, fail)) => Err((MadeProgress, fail)),
|
|
||||||
Err((NoProgress, _)) => Ok((NoProgress, None, original_state)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! one_of_with_error {
|
macro_rules! one_of_with_error {
|
||||||
($toerror:expr; $p1:expr) => {
|
($toerror:expr; $p1:expr) => {
|
||||||
|
|
|
@ -349,23 +349,20 @@ fn record_type_field<'a>() -> impl Parser<'a, AssignedField<'a, TypeAnnotation<'
|
||||||
fn record_type<'a>(
|
fn record_type<'a>(
|
||||||
stop_at_surface_has: bool,
|
stop_at_surface_has: bool,
|
||||||
) -> impl Parser<'a, TypeAnnotation<'a>, ETypeRecord<'a>> {
|
) -> impl Parser<'a, TypeAnnotation<'a>, ETypeRecord<'a>> {
|
||||||
map!(
|
record!(TypeAnnotation::Record {
|
||||||
and!(
|
fields: collection_trailing_sep_e!(
|
||||||
collection_trailing_sep_e!(
|
word1(b'{', ETypeRecord::Open),
|
||||||
word1(b'{', ETypeRecord::Open),
|
loc!(record_type_field()),
|
||||||
loc!(record_type_field()),
|
word1(b',', ETypeRecord::End),
|
||||||
word1(b',', ETypeRecord::End),
|
word1(b'}', ETypeRecord::End),
|
||||||
word1(b'}', ETypeRecord::End),
|
ETypeRecord::IndentEnd,
|
||||||
ETypeRecord::IndentEnd,
|
AssignedField::SpaceBefore
|
||||||
AssignedField::SpaceBefore
|
|
||||||
),
|
|
||||||
optional(allocated(specialize_ref(
|
|
||||||
ETypeRecord::Type,
|
|
||||||
term(stop_at_surface_has)
|
|
||||||
)))
|
|
||||||
),
|
),
|
||||||
|(fields, ext)| { TypeAnnotation::Record { fields, ext } }
|
ext: optional(allocated(specialize_ref(
|
||||||
)
|
ETypeRecord::Type,
|
||||||
|
term(stop_at_surface_has)
|
||||||
|
)))
|
||||||
|
})
|
||||||
.trace("type_annotation:record_type")
|
.trace("type_annotation:record_type")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,29 +512,26 @@ pub fn has_abilities<'a>() -> impl Parser<'a, Loc<HasAbilities<'a>>, EType<'a>>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_has_ability<'a>() -> impl Parser<'a, HasAbility<'a>, EType<'a>> {
|
fn parse_has_ability<'a>() -> impl Parser<'a, HasAbility<'a>, EType<'a>> {
|
||||||
increment_min_indent(map!(
|
increment_min_indent(record!(HasAbility::HasAbility {
|
||||||
and!(
|
ability: loc!(specialize(EType::TApply, concrete_type())),
|
||||||
loc!(specialize(EType::TApply, concrete_type())),
|
impls: optional(backtrackable(space0_before_e(
|
||||||
optional(space0_before_e(
|
loc!(map!(
|
||||||
loc!(map!(
|
specialize(
|
||||||
specialize(
|
EType::TAbilityImpl,
|
||||||
EType::TAbilityImpl,
|
collection_trailing_sep_e!(
|
||||||
collection_trailing_sep_e!(
|
word1(b'{', ETypeAbilityImpl::Open),
|
||||||
word1(b'{', ETypeAbilityImpl::Open),
|
specialize(|e: ERecord<'_>, _| e.into(), loc!(record_value_field())),
|
||||||
specialize(|e: ERecord<'_>, _| e.into(), loc!(record_value_field())),
|
word1(b',', ETypeAbilityImpl::End),
|
||||||
word1(b',', ETypeAbilityImpl::End),
|
word1(b'}', ETypeAbilityImpl::End),
|
||||||
word1(b'}', ETypeAbilityImpl::End),
|
ETypeAbilityImpl::IndentEnd,
|
||||||
ETypeAbilityImpl::IndentEnd,
|
AssignedField::SpaceBefore
|
||||||
AssignedField::SpaceBefore
|
)
|
||||||
)
|
),
|
||||||
),
|
HasImpls::HasImpls
|
||||||
HasImpls::HasImpls
|
)),
|
||||||
)),
|
EType::TIndentEnd
|
||||||
EType::TIndentEnd
|
)))
|
||||||
))
|
}))
|
||||||
),
|
|
||||||
|(ability, impls): (_, Option<_>)| { HasAbility::HasAbility { ability, impls } }
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expression<'a>(
|
fn expression<'a>(
|
||||||
|
@ -594,10 +588,10 @@ fn expression<'a>(
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if !is_trailing_comma_valid {
|
if !is_trailing_comma_valid {
|
||||||
let (_, comma, _) = optional(skip_first!(
|
let (_, comma, _) = optional(backtrackable(skip_first!(
|
||||||
space0_e(EType::TIndentStart),
|
space0_e(EType::TIndentStart),
|
||||||
word1(b',', EType::TStart)
|
word1(b',', EType::TStart)
|
||||||
))
|
)))
|
||||||
.trace("check trailing comma")
|
.trace("check trailing comma")
|
||||||
.parse(arena, state.clone(), min_indent)?;
|
.parse(arena, state.clone(), min_indent)?;
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,48 @@
|
||||||
App {
|
Module {
|
||||||
header: AppHeader {
|
comments: [],
|
||||||
name: @4-14 PlainLine(
|
header: App(
|
||||||
"test-app",
|
AppHeader {
|
||||||
),
|
before_name: [],
|
||||||
packages: [],
|
name: @4-14 PlainLine(
|
||||||
imports: [],
|
"test-app",
|
||||||
provides: [],
|
),
|
||||||
provides_types: None,
|
packages: Some(
|
||||||
to: @53-57 ExistingPackage(
|
KeywordItem {
|
||||||
"blah",
|
keyword: Spaces {
|
||||||
),
|
before: [],
|
||||||
before_header: [],
|
item: PackagesKeyword,
|
||||||
after_app_keyword: [],
|
after: [],
|
||||||
before_packages: [],
|
},
|
||||||
after_packages: [],
|
item: [],
|
||||||
before_imports: [],
|
},
|
||||||
after_imports: [],
|
),
|
||||||
before_provides: [],
|
imports: Some(
|
||||||
after_provides: [],
|
KeywordItem {
|
||||||
before_to: [],
|
keyword: Spaces {
|
||||||
after_to: [],
|
before: [],
|
||||||
},
|
item: ImportsKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
provides: ProvidesTo {
|
||||||
|
provides_keyword: Spaces {
|
||||||
|
before: [],
|
||||||
|
item: ProvidesKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
entries: [],
|
||||||
|
types: None,
|
||||||
|
to_keyword: Spaces {
|
||||||
|
before: [],
|
||||||
|
item: ToKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
to: @53-57 ExistingPackage(
|
||||||
|
"blah",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,45 @@
|
||||||
Hosted {
|
Module {
|
||||||
header: HostedHeader {
|
comments: [],
|
||||||
name: @7-10 ModuleName(
|
header: Hosted(
|
||||||
"Foo",
|
HostedHeader {
|
||||||
),
|
before_name: [],
|
||||||
exposes: [],
|
name: @7-10 ModuleName(
|
||||||
imports: [],
|
"Foo",
|
||||||
generates: UppercaseIdent(
|
),
|
||||||
"Bar",
|
exposes: KeywordItem {
|
||||||
),
|
keyword: Spaces {
|
||||||
generates_with: [],
|
before: [],
|
||||||
before_header: [],
|
item: ExposesKeyword,
|
||||||
after_hosted_keyword: [],
|
after: [],
|
||||||
before_exposes: [],
|
},
|
||||||
after_exposes: [],
|
item: [],
|
||||||
before_imports: [],
|
},
|
||||||
after_imports: [],
|
imports: KeywordItem {
|
||||||
before_generates: [],
|
keyword: Spaces {
|
||||||
after_generates: [],
|
before: [],
|
||||||
before_with: [],
|
item: ImportsKeyword,
|
||||||
after_with: [],
|
after: [],
|
||||||
},
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
generates: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [],
|
||||||
|
item: GeneratesKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: UppercaseIdent(
|
||||||
|
"Bar",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
generates_with: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [],
|
||||||
|
item: WithKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,27 @@
|
||||||
Interface {
|
Module {
|
||||||
header: InterfaceHeader {
|
comments: [],
|
||||||
name: @10-13 ModuleName(
|
header: Interface(
|
||||||
"Foo",
|
InterfaceHeader {
|
||||||
),
|
before_name: [],
|
||||||
exposes: [],
|
name: @10-13 ModuleName(
|
||||||
imports: [],
|
"Foo",
|
||||||
before_header: [],
|
),
|
||||||
after_interface_keyword: [],
|
exposes: KeywordItem {
|
||||||
before_exposes: [],
|
keyword: Spaces {
|
||||||
after_exposes: [],
|
before: [],
|
||||||
before_imports: [],
|
item: ExposesKeyword,
|
||||||
after_imports: [],
|
after: [],
|
||||||
},
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
imports: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [],
|
||||||
|
item: ImportsKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,61 @@
|
||||||
Platform {
|
Module {
|
||||||
header: PlatformHeader {
|
comments: [],
|
||||||
name: @9-25 PackageName(
|
header: Platform(
|
||||||
"rtfeldman/blah",
|
PlatformHeader {
|
||||||
),
|
before_name: [],
|
||||||
requires: PlatformRequires {
|
name: @9-25 PackageName(
|
||||||
rigids: [],
|
"rtfeldman/blah",
|
||||||
signature: @40-49 TypedIdent {
|
),
|
||||||
ident: @40-44 "main",
|
requires: KeywordItem {
|
||||||
spaces_before_colon: [],
|
keyword: Spaces {
|
||||||
ann: @47-49 Record {
|
before: [],
|
||||||
fields: [],
|
item: RequiresKeyword,
|
||||||
ext: None,
|
after: [],
|
||||||
|
},
|
||||||
|
item: PlatformRequires {
|
||||||
|
rigids: [],
|
||||||
|
signature: @40-49 TypedIdent {
|
||||||
|
ident: @40-44 "main",
|
||||||
|
spaces_before_colon: [],
|
||||||
|
ann: @47-49 Record {
|
||||||
|
fields: [],
|
||||||
|
ext: None,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
exposes: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [],
|
||||||
|
item: ExposesKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
packages: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [],
|
||||||
|
item: PackagesKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
imports: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [],
|
||||||
|
item: ImportsKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
provides: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [],
|
||||||
|
item: ProvidesKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
exposes: [],
|
),
|
||||||
packages: [],
|
|
||||||
imports: [],
|
|
||||||
provides: [],
|
|
||||||
before_header: [],
|
|
||||||
after_platform_keyword: [],
|
|
||||||
before_requires: [],
|
|
||||||
after_requires: [],
|
|
||||||
before_exposes: [],
|
|
||||||
after_exposes: [],
|
|
||||||
before_packages: [],
|
|
||||||
after_packages: [],
|
|
||||||
before_imports: [],
|
|
||||||
after_imports: [],
|
|
||||||
before_provides: [],
|
|
||||||
after_provides: [],
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +1,74 @@
|
||||||
App {
|
Module {
|
||||||
header: AppHeader {
|
comments: [],
|
||||||
name: @4-15 PlainLine(
|
header: App(
|
||||||
"quicksort",
|
AppHeader {
|
||||||
),
|
before_name: [],
|
||||||
packages: [
|
name: @4-15 PlainLine(
|
||||||
@31-47 PackageEntry {
|
|
||||||
shorthand: "pf",
|
|
||||||
spaces_after_shorthand: [],
|
|
||||||
package_name: @35-47 PackageName(
|
|
||||||
"./platform",
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
imports: [
|
|
||||||
@64-75 Package(
|
|
||||||
"foo",
|
|
||||||
ModuleName(
|
|
||||||
"Bar.Baz",
|
|
||||||
),
|
|
||||||
[],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
provides: [
|
|
||||||
@93-102 ExposedName(
|
|
||||||
"quicksort",
|
"quicksort",
|
||||||
),
|
),
|
||||||
],
|
packages: Some(
|
||||||
provides_types: None,
|
KeywordItem {
|
||||||
to: @108-110 ExistingPackage(
|
keyword: Spaces {
|
||||||
"pf",
|
before: [
|
||||||
),
|
Newline,
|
||||||
before_header: [],
|
],
|
||||||
after_app_keyword: [],
|
item: PackagesKeyword,
|
||||||
before_packages: [
|
after: [],
|
||||||
Newline,
|
},
|
||||||
],
|
item: [
|
||||||
after_packages: [],
|
@31-47 PackageEntry {
|
||||||
before_imports: [
|
shorthand: "pf",
|
||||||
Newline,
|
spaces_after_shorthand: [],
|
||||||
],
|
package_name: @35-47 PackageName(
|
||||||
after_imports: [],
|
"./platform",
|
||||||
before_provides: [
|
),
|
||||||
Newline,
|
},
|
||||||
],
|
],
|
||||||
after_provides: [],
|
},
|
||||||
before_to: [],
|
),
|
||||||
after_to: [],
|
imports: Some(
|
||||||
},
|
KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: ImportsKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [
|
||||||
|
@64-75 Package(
|
||||||
|
"foo",
|
||||||
|
ModuleName(
|
||||||
|
"Bar.Baz",
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
provides: ProvidesTo {
|
||||||
|
provides_keyword: Spaces {
|
||||||
|
before: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: ProvidesKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
entries: [
|
||||||
|
@93-102 ExposedName(
|
||||||
|
"quicksort",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
types: None,
|
||||||
|
to_keyword: Spaces {
|
||||||
|
before: [],
|
||||||
|
item: ToKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
to: @108-110 ExistingPackage(
|
||||||
|
"pf",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,75 +1,99 @@
|
||||||
App {
|
Module {
|
||||||
header: AppHeader {
|
comments: [],
|
||||||
name: @4-15 PlainLine(
|
header: App(
|
||||||
"quicksort",
|
AppHeader {
|
||||||
),
|
before_name: [],
|
||||||
packages: [
|
name: @4-15 PlainLine(
|
||||||
@31-47 PackageEntry {
|
"quicksort",
|
||||||
shorthand: "pf",
|
),
|
||||||
spaces_after_shorthand: [],
|
packages: Some(
|
||||||
package_name: @35-47 PackageName(
|
KeywordItem {
|
||||||
"./platform",
|
keyword: Spaces {
|
||||||
),
|
before: [
|
||||||
},
|
Newline,
|
||||||
],
|
],
|
||||||
imports: [
|
item: PackagesKeyword,
|
||||||
@65-141 Package(
|
after: [],
|
||||||
"foo",
|
},
|
||||||
ModuleName(
|
item: [
|
||||||
"Bar",
|
@31-47 PackageEntry {
|
||||||
),
|
shorthand: "pf",
|
||||||
Collection {
|
spaces_after_shorthand: [],
|
||||||
items: [
|
package_name: @35-47 PackageName(
|
||||||
@83-86 SpaceBefore(
|
"./platform",
|
||||||
ExposedName(
|
|
||||||
"Baz",
|
|
||||||
),
|
),
|
||||||
[
|
},
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
@96-104 SpaceBefore(
|
|
||||||
ExposedName(
|
|
||||||
"FortyTwo",
|
|
||||||
),
|
|
||||||
[
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
final_comments: [
|
},
|
||||||
Newline,
|
),
|
||||||
LineComment(
|
imports: Some(
|
||||||
" I'm a happy comment",
|
KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: ImportsKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [
|
||||||
|
@65-141 Package(
|
||||||
|
"foo",
|
||||||
|
ModuleName(
|
||||||
|
"Bar",
|
||||||
|
),
|
||||||
|
Collection {
|
||||||
|
items: [
|
||||||
|
@83-86 SpaceBefore(
|
||||||
|
ExposedName(
|
||||||
|
"Baz",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
@96-104 SpaceBefore(
|
||||||
|
ExposedName(
|
||||||
|
"FortyTwo",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
final_comments: [
|
||||||
|
Newline,
|
||||||
|
LineComment(
|
||||||
|
" I'm a happy comment",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
provides: ProvidesTo {
|
||||||
provides: [
|
provides_keyword: Spaces {
|
||||||
@159-168 ExposedName(
|
before: [
|
||||||
"quicksort",
|
Newline,
|
||||||
),
|
],
|
||||||
],
|
item: ProvidesKeyword,
|
||||||
provides_types: None,
|
after: [],
|
||||||
to: @175-177 ExistingPackage(
|
},
|
||||||
"pf",
|
entries: [
|
||||||
),
|
@159-168 ExposedName(
|
||||||
before_header: [],
|
"quicksort",
|
||||||
after_app_keyword: [],
|
),
|
||||||
before_packages: [
|
],
|
||||||
Newline,
|
types: None,
|
||||||
],
|
to_keyword: Spaces {
|
||||||
after_packages: [],
|
before: [],
|
||||||
before_imports: [
|
item: ToKeyword,
|
||||||
Newline,
|
after: [],
|
||||||
],
|
},
|
||||||
after_imports: [],
|
to: @175-177 ExistingPackage(
|
||||||
before_provides: [
|
"pf",
|
||||||
Newline,
|
),
|
||||||
],
|
},
|
||||||
after_provides: [],
|
},
|
||||||
before_to: [],
|
),
|
||||||
after_to: [],
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,71 +1,98 @@
|
||||||
Platform {
|
Module {
|
||||||
header: PlatformHeader {
|
comments: [],
|
||||||
name: @9-14 PackageName(
|
header: Platform(
|
||||||
"cli",
|
PlatformHeader {
|
||||||
),
|
before_name: [],
|
||||||
requires: PlatformRequires {
|
name: @9-14 PackageName(
|
||||||
rigids: [],
|
"cli",
|
||||||
signature: @32-49 TypedIdent {
|
),
|
||||||
ident: @32-36 "main",
|
requires: KeywordItem {
|
||||||
spaces_before_colon: [],
|
keyword: Spaces {
|
||||||
ann: @39-49 Apply(
|
before: [
|
||||||
"",
|
Newline,
|
||||||
"Task",
|
|
||||||
[
|
|
||||||
@44-46 Record {
|
|
||||||
fields: [],
|
|
||||||
ext: None,
|
|
||||||
},
|
|
||||||
@47-49 TagUnion {
|
|
||||||
ext: None,
|
|
||||||
tags: [],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
),
|
item: RequiresKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: PlatformRequires {
|
||||||
|
rigids: [],
|
||||||
|
signature: @32-49 TypedIdent {
|
||||||
|
ident: @32-36 "main",
|
||||||
|
spaces_before_colon: [],
|
||||||
|
ann: @39-49 Apply(
|
||||||
|
"",
|
||||||
|
"Task",
|
||||||
|
[
|
||||||
|
@44-46 Record {
|
||||||
|
fields: [],
|
||||||
|
ext: None,
|
||||||
|
},
|
||||||
|
@47-49 TagUnion {
|
||||||
|
ext: None,
|
||||||
|
tags: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
exposes: KeywordItem {
|
||||||
exposes: [],
|
keyword: Spaces {
|
||||||
packages: [],
|
before: [
|
||||||
imports: [
|
LineComment(
|
||||||
@110-123 Module(
|
" TODO FIXME",
|
||||||
ModuleName(
|
),
|
||||||
"Task",
|
],
|
||||||
),
|
item: ExposesKeyword,
|
||||||
[
|
after: [],
|
||||||
@117-121 ExposedName(
|
},
|
||||||
"Task",
|
item: [],
|
||||||
|
},
|
||||||
|
packages: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: PackagesKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
imports: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: ImportsKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [
|
||||||
|
@110-123 Module(
|
||||||
|
ModuleName(
|
||||||
|
"Task",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
@117-121 ExposedName(
|
||||||
|
"Task",
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
},
|
||||||
],
|
provides: KeywordItem {
|
||||||
provides: [
|
keyword: Spaces {
|
||||||
@141-152 ExposedName(
|
before: [
|
||||||
"mainForHost",
|
Newline,
|
||||||
),
|
],
|
||||||
],
|
item: ProvidesKeyword,
|
||||||
before_header: [],
|
after: [],
|
||||||
after_platform_keyword: [],
|
},
|
||||||
before_requires: [
|
item: [
|
||||||
Newline,
|
@141-152 ExposedName(
|
||||||
],
|
"mainForHost",
|
||||||
after_requires: [],
|
),
|
||||||
before_exposes: [
|
],
|
||||||
LineComment(
|
},
|
||||||
" TODO FIXME",
|
},
|
||||||
),
|
),
|
||||||
],
|
|
||||||
after_exposes: [],
|
|
||||||
before_packages: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
after_packages: [],
|
|
||||||
before_imports: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
after_imports: [],
|
|
||||||
before_provides: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
after_provides: [],
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,27 @@
|
||||||
Interface {
|
Module {
|
||||||
header: InterfaceHeader {
|
comments: [],
|
||||||
name: @10-11 ModuleName(
|
header: Interface(
|
||||||
"T",
|
InterfaceHeader {
|
||||||
),
|
before_name: [],
|
||||||
exposes: [],
|
name: @10-11 ModuleName(
|
||||||
imports: [],
|
"T",
|
||||||
before_header: [],
|
),
|
||||||
after_interface_keyword: [],
|
exposes: KeywordItem {
|
||||||
before_exposes: [],
|
keyword: Spaces {
|
||||||
after_exposes: [],
|
before: [],
|
||||||
before_imports: [],
|
item: ExposesKeyword,
|
||||||
after_imports: [],
|
after: [],
|
||||||
},
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
imports: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [],
|
||||||
|
item: ImportsKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,32 @@
|
||||||
App {
|
Module {
|
||||||
header: AppHeader {
|
comments: [],
|
||||||
name: @4-14 PlainLine(
|
header: App(
|
||||||
"test-app",
|
AppHeader {
|
||||||
),
|
before_name: [],
|
||||||
packages: [],
|
name: @4-14 PlainLine(
|
||||||
imports: [],
|
"test-app",
|
||||||
provides: [],
|
|
||||||
provides_types: None,
|
|
||||||
to: @30-38 NewPackage(
|
|
||||||
PackageName(
|
|
||||||
"./blah",
|
|
||||||
),
|
),
|
||||||
),
|
packages: None,
|
||||||
before_header: [],
|
imports: None,
|
||||||
after_app_keyword: [],
|
provides: ProvidesTo {
|
||||||
before_packages: [],
|
provides_keyword: Spaces {
|
||||||
after_packages: [],
|
before: [],
|
||||||
before_imports: [],
|
item: ProvidesKeyword,
|
||||||
after_imports: [],
|
after: [],
|
||||||
before_provides: [],
|
},
|
||||||
after_provides: [],
|
entries: [],
|
||||||
before_to: [],
|
types: None,
|
||||||
after_to: [],
|
to_keyword: Spaces {
|
||||||
},
|
before: [],
|
||||||
|
item: ToKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
to: @30-38 NewPackage(
|
||||||
|
PackageName(
|
||||||
|
"./blah",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,27 @@
|
||||||
Interface {
|
Module {
|
||||||
header: InterfaceHeader {
|
comments: [],
|
||||||
name: @10-21 ModuleName(
|
header: Interface(
|
||||||
"Foo.Bar.Baz",
|
InterfaceHeader {
|
||||||
),
|
before_name: [],
|
||||||
exposes: [],
|
name: @10-21 ModuleName(
|
||||||
imports: [],
|
"Foo.Bar.Baz",
|
||||||
before_header: [],
|
),
|
||||||
after_interface_keyword: [],
|
exposes: KeywordItem {
|
||||||
before_exposes: [],
|
keyword: Spaces {
|
||||||
after_exposes: [],
|
before: [],
|
||||||
before_imports: [],
|
item: ExposesKeyword,
|
||||||
after_imports: [],
|
after: [],
|
||||||
},
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
imports: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [],
|
||||||
|
item: ImportsKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,130 +1,152 @@
|
||||||
Hosted {
|
Module {
|
||||||
header: HostedHeader {
|
comments: [],
|
||||||
name: @7-10 ModuleName(
|
header: Hosted(
|
||||||
"Foo",
|
HostedHeader {
|
||||||
),
|
before_name: [],
|
||||||
exposes: Collection {
|
name: @7-10 ModuleName(
|
||||||
items: [
|
"Foo",
|
||||||
@45-50 SpaceBefore(
|
),
|
||||||
ExposedName(
|
exposes: KeywordItem {
|
||||||
"Stuff",
|
keyword: Spaces {
|
||||||
),
|
before: [
|
||||||
[
|
|
||||||
Newline,
|
Newline,
|
||||||
],
|
],
|
||||||
),
|
item: ExposesKeyword,
|
||||||
@64-70 SpaceBefore(
|
after: [
|
||||||
ExposedName(
|
|
||||||
"Things",
|
|
||||||
),
|
|
||||||
[
|
|
||||||
Newline,
|
Newline,
|
||||||
],
|
],
|
||||||
),
|
},
|
||||||
@84-97 SpaceBefore(
|
item: Collection {
|
||||||
ExposedName(
|
items: [
|
||||||
"somethingElse",
|
@45-50 SpaceBefore(
|
||||||
),
|
ExposedName(
|
||||||
[
|
"Stuff",
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
final_comments: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
imports: Collection {
|
|
||||||
items: [
|
|
||||||
@143-147 SpaceBefore(
|
|
||||||
Module(
|
|
||||||
ModuleName(
|
|
||||||
"Blah",
|
|
||||||
),
|
|
||||||
[],
|
|
||||||
),
|
|
||||||
[
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
@161-182 SpaceBefore(
|
|
||||||
Module(
|
|
||||||
ModuleName(
|
|
||||||
"Baz",
|
|
||||||
),
|
|
||||||
[
|
|
||||||
@167-172 ExposedName(
|
|
||||||
"stuff",
|
|
||||||
),
|
),
|
||||||
@174-180 ExposedName(
|
[
|
||||||
"things",
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
@64-70 SpaceBefore(
|
||||||
|
ExposedName(
|
||||||
|
"Things",
|
||||||
),
|
),
|
||||||
],
|
[
|
||||||
),
|
Newline,
|
||||||
[
|
],
|
||||||
|
),
|
||||||
|
@84-97 SpaceBefore(
|
||||||
|
ExposedName(
|
||||||
|
"somethingElse",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
final_comments: [
|
||||||
Newline,
|
Newline,
|
||||||
],
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
imports: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: ImportsKeyword,
|
||||||
|
after: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
item: Collection {
|
||||||
|
items: [
|
||||||
|
@143-147 SpaceBefore(
|
||||||
|
Module(
|
||||||
|
ModuleName(
|
||||||
|
"Blah",
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
@161-182 SpaceBefore(
|
||||||
|
Module(
|
||||||
|
ModuleName(
|
||||||
|
"Baz",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
@167-172 ExposedName(
|
||||||
|
"stuff",
|
||||||
|
),
|
||||||
|
@174-180 ExposedName(
|
||||||
|
"things",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
final_comments: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
generates: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: GeneratesKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: UppercaseIdent(
|
||||||
|
"Bar",
|
||||||
),
|
),
|
||||||
],
|
},
|
||||||
final_comments: [
|
generates_with: KeywordItem {
|
||||||
Newline,
|
keyword: Spaces {
|
||||||
],
|
before: [],
|
||||||
|
item: WithKeyword,
|
||||||
|
after: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
item: Collection {
|
||||||
|
items: [
|
||||||
|
@239-242 SpaceBefore(
|
||||||
|
ExposedName(
|
||||||
|
"map",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
@256-261 SpaceBefore(
|
||||||
|
ExposedName(
|
||||||
|
"after",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
@275-279 SpaceBefore(
|
||||||
|
ExposedName(
|
||||||
|
"loop",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
final_comments: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
generates: UppercaseIdent(
|
),
|
||||||
"Bar",
|
|
||||||
),
|
|
||||||
generates_with: Collection {
|
|
||||||
items: [
|
|
||||||
@239-242 SpaceBefore(
|
|
||||||
ExposedName(
|
|
||||||
"map",
|
|
||||||
),
|
|
||||||
[
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
@256-261 SpaceBefore(
|
|
||||||
ExposedName(
|
|
||||||
"after",
|
|
||||||
),
|
|
||||||
[
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
@275-279 SpaceBefore(
|
|
||||||
ExposedName(
|
|
||||||
"loop",
|
|
||||||
),
|
|
||||||
[
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
final_comments: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
before_header: [],
|
|
||||||
after_hosted_keyword: [],
|
|
||||||
before_exposes: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
after_exposes: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
before_imports: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
after_imports: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
before_generates: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
after_generates: [],
|
|
||||||
before_with: [],
|
|
||||||
after_with: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,60 +1,87 @@
|
||||||
Platform {
|
Module {
|
||||||
header: PlatformHeader {
|
comments: [],
|
||||||
name: @9-21 PackageName(
|
header: Platform(
|
||||||
"foo/barbaz",
|
PlatformHeader {
|
||||||
),
|
before_name: [],
|
||||||
requires: PlatformRequires {
|
name: @9-21 PackageName(
|
||||||
rigids: [
|
"foo/barbaz",
|
||||||
@36-41 UppercaseIdent(
|
),
|
||||||
"Model",
|
requires: KeywordItem {
|
||||||
),
|
keyword: Spaces {
|
||||||
],
|
before: [
|
||||||
signature: @45-54 TypedIdent {
|
Newline,
|
||||||
ident: @45-49 "main",
|
],
|
||||||
spaces_before_colon: [],
|
item: RequiresKeyword,
|
||||||
ann: @52-54 Record {
|
after: [],
|
||||||
fields: [],
|
},
|
||||||
ext: None,
|
item: PlatformRequires {
|
||||||
|
rigids: [
|
||||||
|
@36-41 UppercaseIdent(
|
||||||
|
"Model",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
signature: @45-54 TypedIdent {
|
||||||
|
ident: @45-49 "main",
|
||||||
|
spaces_before_colon: [],
|
||||||
|
ann: @52-54 Record {
|
||||||
|
fields: [],
|
||||||
|
ext: None,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
exposes: KeywordItem {
|
||||||
exposes: [],
|
keyword: Spaces {
|
||||||
packages: [
|
before: [
|
||||||
@87-99 PackageEntry {
|
Newline,
|
||||||
shorthand: "foo",
|
],
|
||||||
spaces_after_shorthand: [],
|
item: ExposesKeyword,
|
||||||
package_name: @92-99 PackageName(
|
after: [],
|
||||||
"./foo",
|
},
|
||||||
),
|
item: [],
|
||||||
},
|
},
|
||||||
],
|
packages: KeywordItem {
|
||||||
imports: [],
|
keyword: Spaces {
|
||||||
provides: [
|
before: [
|
||||||
@132-143 ExposedName(
|
Newline,
|
||||||
"mainForHost",
|
],
|
||||||
),
|
item: PackagesKeyword,
|
||||||
],
|
after: [],
|
||||||
before_header: [],
|
},
|
||||||
after_platform_keyword: [],
|
item: [
|
||||||
before_requires: [
|
@87-99 PackageEntry {
|
||||||
Newline,
|
shorthand: "foo",
|
||||||
],
|
spaces_after_shorthand: [],
|
||||||
after_requires: [],
|
package_name: @92-99 PackageName(
|
||||||
before_exposes: [
|
"./foo",
|
||||||
Newline,
|
),
|
||||||
],
|
},
|
||||||
after_exposes: [],
|
],
|
||||||
before_packages: [
|
},
|
||||||
Newline,
|
imports: KeywordItem {
|
||||||
],
|
keyword: Spaces {
|
||||||
after_packages: [],
|
before: [
|
||||||
before_imports: [
|
Newline,
|
||||||
Newline,
|
],
|
||||||
],
|
item: ImportsKeyword,
|
||||||
after_imports: [],
|
after: [],
|
||||||
before_provides: [
|
},
|
||||||
Newline,
|
item: [],
|
||||||
],
|
},
|
||||||
after_provides: [],
|
provides: KeywordItem {
|
||||||
},
|
keyword: Spaces {
|
||||||
|
before: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: ProvidesKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [
|
||||||
|
@132-143 ExposedName(
|
||||||
|
"mainForHost",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,59 +1,83 @@
|
||||||
App {
|
Module {
|
||||||
header: AppHeader {
|
comments: [],
|
||||||
name: @4-10 PlainLine(
|
header: App(
|
||||||
"test",
|
AppHeader {
|
||||||
),
|
before_name: [],
|
||||||
packages: [
|
name: @4-10 PlainLine(
|
||||||
@26-42 PackageEntry {
|
"test",
|
||||||
shorthand: "pf",
|
),
|
||||||
spaces_after_shorthand: [],
|
packages: Some(
|
||||||
package_name: @30-42 PackageName(
|
KeywordItem {
|
||||||
"./platform",
|
keyword: Spaces {
|
||||||
|
before: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: PackagesKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [
|
||||||
|
@26-42 PackageEntry {
|
||||||
|
shorthand: "pf",
|
||||||
|
spaces_after_shorthand: [],
|
||||||
|
package_name: @30-42 PackageName(
|
||||||
|
"./platform",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
imports: Some(
|
||||||
|
KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: ImportsKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [
|
||||||
|
@59-70 Package(
|
||||||
|
"foo",
|
||||||
|
ModuleName(
|
||||||
|
"Bar.Baz",
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
provides: ProvidesTo {
|
||||||
|
provides_keyword: Spaces {
|
||||||
|
before: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: ProvidesKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
entries: [
|
||||||
|
@88-97 ExposedName(
|
||||||
|
"quicksort",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
types: Some(
|
||||||
|
[
|
||||||
|
@102-107 UppercaseIdent(
|
||||||
|
"Flags",
|
||||||
|
),
|
||||||
|
@109-114 UppercaseIdent(
|
||||||
|
"Model",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
to_keyword: Spaces {
|
||||||
|
before: [],
|
||||||
|
item: ToKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
to: @121-123 ExistingPackage(
|
||||||
|
"pf",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
imports: [
|
),
|
||||||
@59-70 Package(
|
|
||||||
"foo",
|
|
||||||
ModuleName(
|
|
||||||
"Bar.Baz",
|
|
||||||
),
|
|
||||||
[],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
provides: [
|
|
||||||
@88-97 ExposedName(
|
|
||||||
"quicksort",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
provides_types: Some(
|
|
||||||
[
|
|
||||||
@102-107 UppercaseIdent(
|
|
||||||
"Flags",
|
|
||||||
),
|
|
||||||
@109-114 UppercaseIdent(
|
|
||||||
"Model",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
to: @121-123 ExistingPackage(
|
|
||||||
"pf",
|
|
||||||
),
|
|
||||||
before_header: [],
|
|
||||||
after_app_keyword: [],
|
|
||||||
before_packages: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
after_packages: [],
|
|
||||||
before_imports: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
after_imports: [],
|
|
||||||
before_provides: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
after_provides: [],
|
|
||||||
before_to: [],
|
|
||||||
after_to: [],
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,67 +1,94 @@
|
||||||
Platform {
|
Module {
|
||||||
header: PlatformHeader {
|
comments: [],
|
||||||
name: @9-21 PackageName(
|
header: Platform(
|
||||||
"test/types",
|
PlatformHeader {
|
||||||
),
|
before_name: [],
|
||||||
requires: PlatformRequires {
|
name: @9-21 PackageName(
|
||||||
rigids: [
|
"test/types",
|
||||||
@37-42 UppercaseIdent(
|
),
|
||||||
"Flags",
|
requires: KeywordItem {
|
||||||
),
|
keyword: Spaces {
|
||||||
@44-49 UppercaseIdent(
|
before: [
|
||||||
"Model",
|
Newline,
|
||||||
),
|
],
|
||||||
],
|
item: RequiresKeyword,
|
||||||
signature: @55-77 TypedIdent {
|
after: [],
|
||||||
ident: @55-59 "main",
|
},
|
||||||
spaces_before_colon: [],
|
item: PlatformRequires {
|
||||||
ann: @62-77 Apply(
|
rigids: [
|
||||||
"",
|
@37-42 UppercaseIdent(
|
||||||
"App",
|
|
||||||
[
|
|
||||||
@66-71 Apply(
|
|
||||||
"",
|
|
||||||
"Flags",
|
"Flags",
|
||||||
[],
|
|
||||||
),
|
),
|
||||||
@72-77 Apply(
|
@44-49 UppercaseIdent(
|
||||||
"",
|
|
||||||
"Model",
|
"Model",
|
||||||
[],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
signature: @55-77 TypedIdent {
|
||||||
|
ident: @55-59 "main",
|
||||||
|
spaces_before_colon: [],
|
||||||
|
ann: @62-77 Apply(
|
||||||
|
"",
|
||||||
|
"App",
|
||||||
|
[
|
||||||
|
@66-71 Apply(
|
||||||
|
"",
|
||||||
|
"Flags",
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
@72-77 Apply(
|
||||||
|
"",
|
||||||
|
"Model",
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
exposes: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: ExposesKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
packages: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: PackagesKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
imports: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: ImportsKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [],
|
||||||
|
},
|
||||||
|
provides: KeywordItem {
|
||||||
|
keyword: Spaces {
|
||||||
|
before: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
item: ProvidesKeyword,
|
||||||
|
after: [],
|
||||||
|
},
|
||||||
|
item: [
|
||||||
|
@141-152 ExposedName(
|
||||||
|
"mainForHost",
|
||||||
|
),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
exposes: [],
|
),
|
||||||
packages: [],
|
|
||||||
imports: [],
|
|
||||||
provides: [
|
|
||||||
@141-152 ExposedName(
|
|
||||||
"mainForHost",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
before_header: [],
|
|
||||||
after_platform_keyword: [],
|
|
||||||
before_requires: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
after_requires: [],
|
|
||||||
before_exposes: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
after_exposes: [],
|
|
||||||
before_packages: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
after_packages: [],
|
|
||||||
before_imports: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
after_imports: [],
|
|
||||||
before_provides: [
|
|
||||||
Newline,
|
|
||||||
],
|
|
||||||
after_provides: [],
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,11 +158,6 @@ pub fn generate_stub_lib(
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if let EntryPoint::Executable { platform_path, .. } = &loaded.entry_point {
|
if let EntryPoint::Executable { platform_path, .. } = &loaded.entry_point {
|
||||||
let platform_path = input_path
|
|
||||||
.to_path_buf()
|
|
||||||
.parent()
|
|
||||||
.unwrap()
|
|
||||||
.join(platform_path);
|
|
||||||
let stub_lib = if let target_lexicon::OperatingSystem::Windows = triple.operating_system {
|
let stub_lib = if let target_lexicon::OperatingSystem::Windows = triple.operating_system {
|
||||||
platform_path.with_file_name("libapp.obj")
|
platform_path.with_file_name("libapp.obj")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use brotli::enc::BrotliEncoderParams;
|
use brotli::enc::BrotliEncoderParams;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use flate2::write::GzEncoder;
|
use flate2::write::GzEncoder;
|
||||||
use roc_parse::ast::Module;
|
use roc_parse::ast::{Header, Module};
|
||||||
use roc_parse::header::PlatformHeader;
|
use roc_parse::header::PlatformHeader;
|
||||||
use roc_parse::module::parse_header;
|
use roc_parse::module::parse_header;
|
||||||
use roc_parse::state::State;
|
use roc_parse::state::State;
|
||||||
|
@ -124,22 +124,20 @@ fn write_archive<W: Write>(path: &Path, writer: W) -> io::Result<()> {
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
|
|
||||||
let _other_modules: &[Module<'_>] = match read_header(&arena, &mut buf, path)? {
|
let _other_modules: &[Module<'_>] = match read_header(&arena, &mut buf, path)?.header {
|
||||||
Module::Interface { .. } => {
|
Header::Interface(_) => {
|
||||||
todo!();
|
todo!();
|
||||||
// TODO report error
|
// TODO report error
|
||||||
}
|
}
|
||||||
Module::App { .. } => {
|
Header::App(_) => {
|
||||||
todo!();
|
todo!();
|
||||||
// TODO report error
|
// TODO report error
|
||||||
}
|
}
|
||||||
Module::Hosted { .. } => {
|
Header::Hosted(_) => {
|
||||||
todo!();
|
todo!();
|
||||||
// TODO report error
|
// TODO report error
|
||||||
}
|
}
|
||||||
Module::Platform {
|
Header::Platform(PlatformHeader { imports: _, .. }) => {
|
||||||
header: PlatformHeader { imports: _, .. },
|
|
||||||
} => {
|
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
// Add all the prebuilt host files to the archive.
|
// Add all the prebuilt host files to the archive.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue