mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
Use UppercaseIdent over PlatformRigids
This commit is contained in:
parent
620e3f2913
commit
c1c0ffb25f
10 changed files with 157 additions and 51 deletions
|
@ -12,10 +12,11 @@ use roc_parse::ast::{
|
||||||
};
|
};
|
||||||
use roc_parse::header::{
|
use roc_parse::header::{
|
||||||
AppHeader, Effects, ExposedName, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry,
|
AppHeader, Effects, ExposedName, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry,
|
||||||
PackageName, PlatformHeader, PlatformRequires, PlatformRigid, To, TypedIdent,
|
PackageName, PlatformHeader, PlatformRequires, To, TypedIdent,
|
||||||
};
|
};
|
||||||
use roc_parse::{
|
use roc_parse::{
|
||||||
ast::{Def, Module},
|
ast::{Def, Module},
|
||||||
|
ident::UppercaseIdent,
|
||||||
module::{self, module_defs},
|
module::{self, module_defs},
|
||||||
parser::{Parser, SyntaxError},
|
parser::{Parser, SyntaxError},
|
||||||
state::State,
|
state::State,
|
||||||
|
@ -285,7 +286,7 @@ impl<'a> RemoveSpaces<'a> for PlatformRequires<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> RemoveSpaces<'a> for PlatformRigid<'a> {
|
impl<'a> RemoveSpaces<'a> for UppercaseIdent<'a> {
|
||||||
fn remove_spaces(&self, _arena: &'a Bump) -> Self {
|
fn remove_spaces(&self, _arena: &'a Bump) -> Self {
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::{
|
||||||
Buf,
|
Buf,
|
||||||
};
|
};
|
||||||
use roc_parse::ast::{AliasHeader, AssignedField, Expr, Tag, TypeAnnotation};
|
use roc_parse::ast::{AliasHeader, AssignedField, Expr, Tag, TypeAnnotation};
|
||||||
|
use roc_parse::ident::UppercaseIdent;
|
||||||
use roc_region::all::Loc;
|
use roc_region::all::Loc;
|
||||||
|
|
||||||
/// Does an AST node need parens around it?
|
/// Does an AST node need parens around it?
|
||||||
|
@ -107,6 +108,22 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Formattable for UppercaseIdent<'a> {
|
||||||
|
fn is_multiline(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_with_options<'buf>(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buf<'buf>,
|
||||||
|
_parens: Parens,
|
||||||
|
_newlines: Newlines,
|
||||||
|
_indent: u16,
|
||||||
|
) {
|
||||||
|
buf.push_str((*self).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Formattable for TypeAnnotation<'a> {
|
impl<'a> Formattable for TypeAnnotation<'a> {
|
||||||
fn is_multiline(&self) -> bool {
|
fn is_multiline(&self) -> bool {
|
||||||
use roc_parse::ast::TypeAnnotation::*;
|
use roc_parse::ast::TypeAnnotation::*;
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::Buf;
|
||||||
use roc_parse::ast::{Collection, Module, Spaced};
|
use roc_parse::ast::{Collection, Module, Spaced};
|
||||||
use roc_parse::header::{
|
use roc_parse::header::{
|
||||||
AppHeader, Effects, ExposedName, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry,
|
AppHeader, Effects, ExposedName, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry,
|
||||||
PackageName, PlatformHeader, PlatformRequires, PlatformRigid, To, TypedIdent,
|
PackageName, PlatformHeader, PlatformRequires, To, TypedIdent,
|
||||||
};
|
};
|
||||||
use roc_region::all::Loc;
|
use roc_region::all::Loc;
|
||||||
|
|
||||||
|
@ -206,18 +206,6 @@ impl<'a, T: Formattable> Formattable for Spaced<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Formattable for PlatformRigid<'a> {
|
|
||||||
fn is_multiline(&self) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn format<'buf>(&self, buf: &mut Buf<'buf>, _indent: u16) {
|
|
||||||
buf.push_str(self.rigid);
|
|
||||||
buf.push_str("=>");
|
|
||||||
buf.push_str(self.alias);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fmt_imports<'a, 'buf>(
|
fn fmt_imports<'a, 'buf>(
|
||||||
buf: &mut Buf<'buf>,
|
buf: &mut Buf<'buf>,
|
||||||
loc_entries: Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>,
|
loc_entries: Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::ast::{Collection, CommentOrNewline, Spaced, StrLiteral, TypeAnnotation};
|
use crate::ast::{Collection, CommentOrNewline, Spaced, StrLiteral, TypeAnnotation};
|
||||||
use crate::blankspace::space0_e;
|
use crate::blankspace::space0_e;
|
||||||
use crate::ident::lowercase_ident;
|
use crate::ident::{lowercase_ident, UppercaseIdent};
|
||||||
use crate::parser::Progress::*;
|
use crate::parser::Progress::*;
|
||||||
use crate::parser::{specialize, word1, EPackageEntry, EPackageName, Parser};
|
use crate::parser::{specialize, word1, EPackageEntry, EPackageName, Parser};
|
||||||
use crate::state::State;
|
use crate::state::State;
|
||||||
|
@ -126,15 +126,9 @@ pub struct PackageHeader<'a> {
|
||||||
pub after_imports: &'a [CommentOrNewline<'a>],
|
pub after_imports: &'a [CommentOrNewline<'a>],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
|
||||||
pub struct PlatformRigid<'a> {
|
|
||||||
pub rigid: &'a str,
|
|
||||||
pub alias: &'a str,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct PlatformRequires<'a> {
|
pub struct PlatformRequires<'a> {
|
||||||
pub rigids: Collection<'a, Loc<Spaced<'a, PlatformRigid<'a>>>>,
|
pub rigids: Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>,
|
||||||
pub signature: Loc<Spaced<'a, TypedIdent<'a>>>,
|
pub signature: Loc<Spaced<'a, TypedIdent<'a>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,23 @@ use bumpalo::collections::vec::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use roc_region::all::Position;
|
use roc_region::all::Position;
|
||||||
|
|
||||||
|
/// A global tag, for example. Must start with an uppercase letter
|
||||||
|
/// and then contain only letters and numbers afterwards - no dots allowed!
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub struct UppercaseIdent<'a>(&'a str);
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for UppercaseIdent<'a> {
|
||||||
|
fn from(string: &'a str) -> Self {
|
||||||
|
UppercaseIdent(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<UppercaseIdent<'a>> for &'a str {
|
||||||
|
fn from(ident: UppercaseIdent<'a>) -> Self {
|
||||||
|
ident.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The parser accepts all of these in any position where any one of them could
|
/// The parser accepts all of these in any position where any one of them could
|
||||||
/// appear. This way, canonicalization can give more helpful error messages like
|
/// appear. This way, canonicalization can give more helpful error messages like
|
||||||
/// "you can't redefine this tag!" if you wrote `Foo = ...` or
|
/// "you can't redefine this tag!" if you wrote `Foo = ...` or
|
||||||
|
@ -91,6 +108,21 @@ pub fn tag_name<'a>() -> impl Parser<'a, &'a str, ()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This could be:
|
||||||
|
///
|
||||||
|
/// * A module name
|
||||||
|
/// * A type name
|
||||||
|
/// * A global tag
|
||||||
|
pub fn uppercase<'a>() -> impl Parser<'a, UppercaseIdent<'a>, ()> {
|
||||||
|
move |_, state: State<'a>| match chomp_uppercase_part(state.bytes()) {
|
||||||
|
Err(progress) => Err((progress, (), state)),
|
||||||
|
Ok(ident) => {
|
||||||
|
let width = ident.len();
|
||||||
|
Ok((MadeProgress, ident.into(), state.advance(width)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This could be:
|
/// This could be:
|
||||||
///
|
///
|
||||||
/// * A module name
|
/// * A module name
|
||||||
|
|
|
@ -2,13 +2,13 @@ use crate::ast::{Collection, CommentOrNewline, Def, Module, Spaced};
|
||||||
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, Effects, ExposedName, ImportsEntry, InterfaceHeader,
|
package_entry, package_name, AppHeader, Effects, ExposedName, ImportsEntry, InterfaceHeader,
|
||||||
ModuleName, PackageEntry, PlatformHeader, PlatformRequires, PlatformRigid, To, TypedIdent,
|
ModuleName, PackageEntry, PlatformHeader, PlatformRequires, To, TypedIdent,
|
||||||
};
|
};
|
||||||
use crate::ident::{lowercase_ident, unqualified_ident, uppercase_ident};
|
use crate::ident::{self, lowercase_ident, unqualified_ident, uppercase_ident, UppercaseIdent};
|
||||||
use crate::parser::Progress::{self, *};
|
use crate::parser::Progress::{self, *};
|
||||||
use crate::parser::{
|
use crate::parser::{
|
||||||
backtrackable, specialize, specialize_region, word1, word2, EEffects, EExposes, EHeader,
|
backtrackable, specialize, specialize_region, word1, EEffects, EExposes, EHeader, EImports,
|
||||||
EImports, EPackages, EProvides, ERequires, ETypedIdent, Parser, SourceError, SyntaxError,
|
EPackages, EProvides, ERequires, ETypedIdent, Parser, SourceError, SyntaxError,
|
||||||
};
|
};
|
||||||
use crate::state::State;
|
use crate::state::State;
|
||||||
use crate::string_literal;
|
use crate::string_literal;
|
||||||
|
@ -439,10 +439,13 @@ fn platform_requires<'a>() -> impl Parser<'a, PlatformRequires<'a>, ERequires<'a
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn requires_rigids<'a>(
|
fn requires_rigids<'a>(
|
||||||
min_indent: u32,
|
min_indent: u32,
|
||||||
) -> impl Parser<'a, Collection<'a, Loc<Spaced<'a, PlatformRigid<'a>>>>, ERequires<'a>> {
|
) -> impl Parser<'a, Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>, ERequires<'a>> {
|
||||||
collection_trailing_sep_e!(
|
collection_trailing_sep_e!(
|
||||||
word1(b'{', ERequires::ListStart),
|
word1(b'{', ERequires::ListStart),
|
||||||
specialize(|_, pos| ERequires::Rigid(pos), loc!(requires_rigid())),
|
specialize(
|
||||||
|
|_, pos| ERequires::Rigid(pos),
|
||||||
|
loc!(map!(ident::uppercase(), Spaced::Item))
|
||||||
|
),
|
||||||
word1(b',', ERequires::ListEnd),
|
word1(b',', ERequires::ListEnd),
|
||||||
word1(b'}', ERequires::ListEnd),
|
word1(b'}', ERequires::ListEnd),
|
||||||
min_indent,
|
min_indent,
|
||||||
|
@ -453,17 +456,6 @@ fn requires_rigids<'a>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn requires_rigid<'a>() -> impl Parser<'a, Spaced<'a, PlatformRigid<'a>>, ()> {
|
|
||||||
map!(
|
|
||||||
and!(
|
|
||||||
lowercase_ident(),
|
|
||||||
skip_first!(word2(b'=', b'>', |_| ()), uppercase_ident())
|
|
||||||
),
|
|
||||||
|(rigid, alias)| Spaced::Item(PlatformRigid { rigid, alias })
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn requires_typed_ident<'a>() -> impl Parser<'a, Loc<Spaced<'a, TypedIdent<'a>>>, ERequires<'a>> {
|
fn requires_typed_ident<'a>() -> impl Parser<'a, Loc<Spaced<'a, TypedIdent<'a>>>, ERequires<'a>> {
|
||||||
skip_first!(
|
skip_first!(
|
||||||
|
|
|
@ -5,15 +5,14 @@ Platform {
|
||||||
),
|
),
|
||||||
requires: PlatformRequires {
|
requires: PlatformRequires {
|
||||||
rigids: [
|
rigids: [
|
||||||
@36-48 PlatformRigid {
|
@36-41 UppercaseIdent(
|
||||||
rigid: "model",
|
"Model",
|
||||||
alias: "Model",
|
),
|
||||||
},
|
|
||||||
],
|
],
|
||||||
signature: @52-61 TypedIdent {
|
signature: @45-54 TypedIdent {
|
||||||
ident: @52-56 "main",
|
ident: @45-49 "main",
|
||||||
spaces_before_colon: [],
|
spaces_before_colon: [],
|
||||||
ann: @59-61 Record {
|
ann: @52-54 Record {
|
||||||
fields: [],
|
fields: [],
|
||||||
ext: None,
|
ext: None,
|
||||||
},
|
},
|
||||||
|
@ -21,17 +20,17 @@ Platform {
|
||||||
},
|
},
|
||||||
exposes: [],
|
exposes: [],
|
||||||
packages: [
|
packages: [
|
||||||
@94-106 PackageEntry {
|
@87-99 PackageEntry {
|
||||||
shorthand: "foo",
|
shorthand: "foo",
|
||||||
spaces_after_shorthand: [],
|
spaces_after_shorthand: [],
|
||||||
package_name: @99-106 PackageName(
|
package_name: @92-99 PackageName(
|
||||||
"./foo",
|
"./foo",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
imports: [],
|
imports: [],
|
||||||
provides: [
|
provides: [
|
||||||
@139-150 ExposedName(
|
@132-143 ExposedName(
|
||||||
"mainForHost",
|
"mainForHost",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
platform "foo/barbaz"
|
platform "foo/barbaz"
|
||||||
requires {model=>Model} { main : {} }
|
requires {Model} { main : {} }
|
||||||
exposes []
|
exposes []
|
||||||
packages { foo: "./foo" }
|
packages { foo: "./foo" }
|
||||||
imports []
|
imports []
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
Platform {
|
||||||
|
header: PlatformHeader {
|
||||||
|
name: @9-21 PackageName(
|
||||||
|
"test/types",
|
||||||
|
),
|
||||||
|
requires: PlatformRequires {
|
||||||
|
rigids: [
|
||||||
|
@37-42 UppercaseIdent(
|
||||||
|
"Flags",
|
||||||
|
),
|
||||||
|
@44-49 UppercaseIdent(
|
||||||
|
"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: [],
|
||||||
|
packages: [],
|
||||||
|
imports: [],
|
||||||
|
provides: [
|
||||||
|
@141-152 ExposedName(
|
||||||
|
"mainForHost",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
effects: Effects {
|
||||||
|
spaces_before_effects_keyword: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
spaces_after_effects_keyword: [],
|
||||||
|
spaces_after_type_name: [],
|
||||||
|
effect_shortname: "fx",
|
||||||
|
effect_type_name: "Effect",
|
||||||
|
entries: [],
|
||||||
|
},
|
||||||
|
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: [],
|
||||||
|
},
|
||||||
|
}
|
|
@ -266,8 +266,14 @@ mod test_parse {
|
||||||
let result = func(&input);
|
let result = func(&input);
|
||||||
|
|
||||||
let actual_result = if should_pass {
|
let actual_result = if should_pass {
|
||||||
|
eprintln!("The source code for this test did not successfully parse!\n");
|
||||||
|
|
||||||
result.unwrap()
|
result.unwrap()
|
||||||
} else {
|
} else {
|
||||||
|
eprintln!(
|
||||||
|
"The source code for this test successfully parsed, but it was not expected to!\n"
|
||||||
|
);
|
||||||
|
|
||||||
result.unwrap_err()
|
result.unwrap_err()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue