mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-11 18:58:24 +03:00
New module
header
Implements the new `module` header syntax as described in "module and package changes" [1]: ``` module [Request, Response, req] ``` The old syntax should still work fine, and is automatically upgraded to the new one when running `roc format`. [1] https://docs.google.com/document/d/1E_77fO-44BtoBtXoVeWyGh1xN2KRTWTu8q6i25RNNx0/edit
This commit is contained in:
parent
7754dd7ef7
commit
057a18573a
@ -8,7 +8,6 @@ use roc_fmt::def::fmt_defs;
|
|||||||
use roc_fmt::module::fmt_module;
|
use roc_fmt::module::fmt_module;
|
||||||
use roc_fmt::spaces::RemoveSpaces;
|
use roc_fmt::spaces::RemoveSpaces;
|
||||||
use roc_fmt::{Ast, Buf};
|
use roc_fmt::{Ast, Buf};
|
||||||
use roc_parse::ast::Defs;
|
|
||||||
use roc_parse::module::parse_module_defs;
|
use roc_parse::module::parse_module_defs;
|
||||||
use roc_parse::{module, parser::SyntaxError, state::State};
|
use roc_parse::{module, parser::SyntaxError, state::State};
|
||||||
|
|
||||||
@ -226,7 +225,9 @@ fn parse_all<'a>(arena: &'a Bump, src: &'a str) -> Result<Ast<'a>, SyntaxError<'
|
|||||||
let (module, state) = module::parse_header(arena, State::new(src.as_bytes()))
|
let (module, state) = module::parse_header(arena, State::new(src.as_bytes()))
|
||||||
.map_err(|e| SyntaxError::Header(e.problem))?;
|
.map_err(|e| SyntaxError::Header(e.problem))?;
|
||||||
|
|
||||||
let defs = parse_module_defs(arena, state, Defs::default())?;
|
let (module, defs) = module.upgrade_header_imports(arena);
|
||||||
|
|
||||||
|
let defs = parse_module_defs(arena, state, defs)?;
|
||||||
|
|
||||||
Ok(Ast { module, defs })
|
Ok(Ast { module, defs })
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
interface Bool
|
module [Bool, Eq, true, false, and, or, not, isEq, isNotEq]
|
||||||
exposes [Bool, Eq, true, false, and, or, not, isEq, isNotEq]
|
|
||||||
imports []
|
|
||||||
|
|
||||||
## Defines a type that can be compared for total equality.
|
## Defines a type that can be compared for total equality.
|
||||||
##
|
##
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
## - Holding unknown Roc types when developing [platforms](https://github.com/roc-lang/roc/wiki/Roc-concepts-explained#platform).
|
## - Holding unknown Roc types when developing [platforms](https://github.com/roc-lang/roc/wiki/Roc-concepts-explained#platform).
|
||||||
## - To improve performance in rare cases.
|
## - To improve performance in rare cases.
|
||||||
##
|
##
|
||||||
interface Box
|
module [box, unbox]
|
||||||
exposes [box, unbox]
|
|
||||||
imports []
|
|
||||||
|
|
||||||
## Allocates a value on the heap. Boxing is an expensive process as it copies
|
## Allocates a value on the heap. Boxing is an expensive process as it copies
|
||||||
## the value from the stack to the heap. This may provide a performance
|
## the value from the stack to the heap. This may provide a performance
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
interface Decode
|
module [
|
||||||
exposes [
|
|
||||||
DecodeError,
|
DecodeError,
|
||||||
DecodeResult,
|
DecodeResult,
|
||||||
Decoder,
|
Decoder,
|
||||||
@ -29,8 +28,7 @@ interface Decode
|
|||||||
fromBytesPartial,
|
fromBytesPartial,
|
||||||
fromBytes,
|
fromBytes,
|
||||||
mapResult,
|
mapResult,
|
||||||
]
|
]
|
||||||
imports []
|
|
||||||
|
|
||||||
import List
|
import List
|
||||||
import Result exposing [Result]
|
import Result exposing [Result]
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
interface Dict
|
module [
|
||||||
exposes [
|
|
||||||
Dict,
|
Dict,
|
||||||
empty,
|
empty,
|
||||||
withCapacity,
|
withCapacity,
|
||||||
@ -28,8 +27,7 @@ interface Dict
|
|||||||
removeAll,
|
removeAll,
|
||||||
map,
|
map,
|
||||||
joinMap,
|
joinMap,
|
||||||
]
|
]
|
||||||
imports []
|
|
||||||
|
|
||||||
import Bool exposing [Bool, Eq]
|
import Bool exposing [Bool, Eq]
|
||||||
import Result exposing [Result]
|
import Result exposing [Result]
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
interface Encode
|
module [
|
||||||
exposes [
|
|
||||||
Encoder,
|
Encoder,
|
||||||
Encoding,
|
Encoding,
|
||||||
toEncoder,
|
toEncoder,
|
||||||
@ -27,8 +26,7 @@ interface Encode
|
|||||||
appendWith,
|
appendWith,
|
||||||
append,
|
append,
|
||||||
toBytes,
|
toBytes,
|
||||||
]
|
]
|
||||||
imports []
|
|
||||||
|
|
||||||
import Num exposing [
|
import Num exposing [
|
||||||
U8,
|
U8,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
interface Hash
|
module [
|
||||||
exposes [
|
|
||||||
Hash,
|
Hash,
|
||||||
Hasher,
|
Hasher,
|
||||||
hash,
|
hash,
|
||||||
@ -20,7 +19,7 @@ interface Hash
|
|||||||
hashStrBytes,
|
hashStrBytes,
|
||||||
hashList,
|
hashList,
|
||||||
hashUnordered,
|
hashUnordered,
|
||||||
] imports []
|
]
|
||||||
|
|
||||||
import Bool exposing [Bool]
|
import Bool exposing [Bool]
|
||||||
import List
|
import List
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
interface Inspect
|
module [
|
||||||
exposes [
|
|
||||||
Inspect,
|
Inspect,
|
||||||
Inspector,
|
Inspector,
|
||||||
InspectFormatter,
|
InspectFormatter,
|
||||||
@ -34,8 +33,7 @@ interface Inspect
|
|||||||
apply,
|
apply,
|
||||||
toInspector,
|
toInspector,
|
||||||
toStr,
|
toStr,
|
||||||
]
|
]
|
||||||
imports []
|
|
||||||
|
|
||||||
import Bool exposing [Bool]
|
import Bool exposing [Bool]
|
||||||
import Num exposing [U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, F32, F64, Dec]
|
import Num exposing [U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, F32, F64, Dec]
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
interface List
|
module [
|
||||||
exposes [
|
|
||||||
isEmpty,
|
isEmpty,
|
||||||
get,
|
get,
|
||||||
set,
|
set,
|
||||||
@ -70,8 +69,7 @@ interface List
|
|||||||
walkBackwardsUntil,
|
walkBackwardsUntil,
|
||||||
countIf,
|
countIf,
|
||||||
chunksOf,
|
chunksOf,
|
||||||
]
|
]
|
||||||
imports []
|
|
||||||
|
|
||||||
import Bool exposing [Bool, Eq]
|
import Bool exposing [Bool, Eq]
|
||||||
import Result exposing [Result]
|
import Result exposing [Result]
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
interface Num
|
module [
|
||||||
exposes [
|
|
||||||
Num,
|
Num,
|
||||||
Int,
|
Int,
|
||||||
Frac,
|
Frac,
|
||||||
@ -156,8 +155,7 @@ interface Num
|
|||||||
f64ToParts,
|
f64ToParts,
|
||||||
f32FromParts,
|
f32FromParts,
|
||||||
f64FromParts,
|
f64FromParts,
|
||||||
]
|
]
|
||||||
imports []
|
|
||||||
|
|
||||||
import Bool exposing [Bool]
|
import Bool exposing [Bool]
|
||||||
import Result exposing [Result]
|
import Result exposing [Result]
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
interface Result
|
module [Result, isOk, isErr, map, mapErr, try, onErr, withDefault]
|
||||||
exposes [Result, isOk, isErr, map, mapErr, try, onErr, withDefault]
|
|
||||||
imports []
|
|
||||||
|
|
||||||
import Bool exposing [Bool]
|
import Bool exposing [Bool]
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
interface Set
|
module [
|
||||||
exposes [
|
|
||||||
Set,
|
Set,
|
||||||
empty,
|
empty,
|
||||||
withCapacity,
|
withCapacity,
|
||||||
@ -23,8 +22,7 @@ interface Set
|
|||||||
difference,
|
difference,
|
||||||
map,
|
map,
|
||||||
joinMap,
|
joinMap,
|
||||||
]
|
]
|
||||||
imports []
|
|
||||||
|
|
||||||
import List
|
import List
|
||||||
import Bool exposing [Bool, Eq]
|
import Bool exposing [Bool, Eq]
|
||||||
|
@ -326,8 +326,7 @@
|
|||||||
## If a situation like this comes up, a slice can be turned into a separate string by using [`Str.concat`](https://www.roc-lang.org/builtins/Str#concat) to concatenate the slice onto an empty string (or one created with [`Str.withCapacity`](https://www.roc-lang.org/builtins/Str#withCapacity)).
|
## If a situation like this comes up, a slice can be turned into a separate string by using [`Str.concat`](https://www.roc-lang.org/builtins/Str#concat) to concatenate the slice onto an empty string (or one created with [`Str.withCapacity`](https://www.roc-lang.org/builtins/Str#withCapacity)).
|
||||||
##
|
##
|
||||||
## Currently, the only way to get seamless slices of strings is by calling certain `Str` functions which return them. In general, `Str` functions which accept a string and return a subset of that string tend to do this. [`Str.trim`](https://www.roc-lang.org/builtins/Str#trim) is another example of a function which returns a seamless slice.
|
## Currently, the only way to get seamless slices of strings is by calling certain `Str` functions which return them. In general, `Str` functions which accept a string and return a subset of that string tend to do this. [`Str.trim`](https://www.roc-lang.org/builtins/Str#trim) is another example of a function which returns a seamless slice.
|
||||||
interface Str
|
module [
|
||||||
exposes [
|
|
||||||
Utf8Problem,
|
Utf8Problem,
|
||||||
Utf8ByteProblem,
|
Utf8ByteProblem,
|
||||||
concat,
|
concat,
|
||||||
@ -368,8 +367,7 @@ interface Str
|
|||||||
withCapacity,
|
withCapacity,
|
||||||
withPrefix,
|
withPrefix,
|
||||||
contains,
|
contains,
|
||||||
]
|
]
|
||||||
imports []
|
|
||||||
|
|
||||||
import Bool exposing [Bool]
|
import Bool exposing [Bool]
|
||||||
import Result exposing [Result]
|
import Result exposing [Result]
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
## THIS MODULE IS DEPRECATED AND CURRENTLY IN THE PROCESS OF BEING REMOVED
|
## THIS MODULE IS DEPRECATED AND CURRENTLY IN THE PROCESS OF BEING REMOVED
|
||||||
## FROM STD LIBRARY
|
## FROM STD LIBRARY
|
||||||
interface TotallyNotJson
|
module [
|
||||||
exposes [
|
|
||||||
Json,
|
Json,
|
||||||
json,
|
json,
|
||||||
jsonWithOptions,
|
jsonWithOptions,
|
||||||
]
|
]
|
||||||
imports []
|
|
||||||
|
|
||||||
import List
|
import List
|
||||||
import Str
|
import Str
|
||||||
|
@ -506,7 +506,7 @@ fn canonicalize_claimed_ability_impl<'a>(
|
|||||||
// OPTION-1: The implementation identifier is the only identifier of that name in the
|
// OPTION-1: The implementation identifier is the only identifier of that name in the
|
||||||
// scope. For example,
|
// scope. For example,
|
||||||
//
|
//
|
||||||
// interface F imports [] exposes []
|
// module []
|
||||||
//
|
//
|
||||||
// Hello := {} implements [Encoding.{ toEncoder }]
|
// Hello := {} implements [Encoding.{ toEncoder }]
|
||||||
//
|
//
|
||||||
@ -518,7 +518,9 @@ fn canonicalize_claimed_ability_impl<'a>(
|
|||||||
// OPTION-2: The implementation identifier is a unique shadow of the ability member,
|
// OPTION-2: The implementation identifier is a unique shadow of the ability member,
|
||||||
// which has also been explicitly imported. For example,
|
// which has also been explicitly imported. For example,
|
||||||
//
|
//
|
||||||
// interface F imports [Encoding.{ toEncoder }] exposes []
|
// module []
|
||||||
|
//
|
||||||
|
// import Encoding exposing [toEncoder]
|
||||||
//
|
//
|
||||||
// Hello := {} implements [Encoding.{ toEncoder }]
|
// Hello := {} implements [Encoding.{ toEncoder }]
|
||||||
//
|
//
|
||||||
|
@ -8,7 +8,7 @@ use bumpalo::Bump;
|
|||||||
use roc_parse::ast::{Collection, Header, Module, Spaced, Spaces};
|
use roc_parse::ast::{Collection, Header, Module, Spaced, Spaces};
|
||||||
use roc_parse::header::{
|
use roc_parse::header::{
|
||||||
AppHeader, ExposedName, ExposesKeyword, GeneratesKeyword, HostedHeader, ImportsEntry,
|
AppHeader, ExposedName, ExposesKeyword, GeneratesKeyword, HostedHeader, ImportsEntry,
|
||||||
ImportsKeyword, InterfaceHeader, Keyword, KeywordItem, ModuleName, PackageEntry, PackageHeader,
|
ImportsKeyword, Keyword, KeywordItem, ModuleHeader, ModuleName, PackageEntry, PackageHeader,
|
||||||
PackageKeyword, PackageName, PackagesKeyword, PlatformHeader, PlatformRequires,
|
PackageKeyword, PackageName, PackagesKeyword, PlatformHeader, PlatformRequires,
|
||||||
ProvidesKeyword, ProvidesTo, RequiresKeyword, To, ToKeyword, TypedIdent, WithKeyword,
|
ProvidesKeyword, ProvidesTo, RequiresKeyword, To, ToKeyword, TypedIdent, WithKeyword,
|
||||||
};
|
};
|
||||||
@ -18,8 +18,8 @@ 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>) {
|
||||||
fmt_comments_only(buf, module.comments.iter(), NewlineAt::Bottom, 0);
|
fmt_comments_only(buf, module.comments.iter(), NewlineAt::Bottom, 0);
|
||||||
match &module.header {
|
match &module.header {
|
||||||
Header::Interface(header) => {
|
Header::Module(header) => {
|
||||||
fmt_interface_header(buf, header);
|
fmt_module_header(buf, header);
|
||||||
}
|
}
|
||||||
Header::App(header) => {
|
Header::App(header) => {
|
||||||
fmt_app_header(buf, header);
|
fmt_app_header(buf, header);
|
||||||
@ -171,20 +171,19 @@ impl<'a, K: Formattable, V: Formattable> Formattable for KeywordItem<'a, K, V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt_interface_header<'a>(buf: &mut Buf, header: &'a InterfaceHeader<'a>) {
|
pub fn fmt_module_header<'a>(buf: &mut Buf, header: &'a ModuleHeader<'a>) {
|
||||||
buf.indent(0);
|
buf.indent(0);
|
||||||
buf.push_str("interface");
|
buf.push_str("module");
|
||||||
|
|
||||||
|
if header.before_exposes.iter().all(|c| c.is_newline()) {
|
||||||
|
buf.spaces(1);
|
||||||
|
fmt_exposes(buf, header.exposes, 0);
|
||||||
|
} else {
|
||||||
let indent = INDENT;
|
let indent = INDENT;
|
||||||
fmt_default_spaces(buf, header.before_name, indent);
|
|
||||||
|
|
||||||
// module name
|
fmt_default_spaces(buf, header.before_exposes, indent);
|
||||||
buf.indent(indent);
|
fmt_exposes(buf, header.exposes, indent);
|
||||||
buf.push_str(header.name.value.as_str());
|
};
|
||||||
|
|
||||||
header.exposes.keyword.format(buf, indent);
|
|
||||||
fmt_exposes(buf, header.exposes.item, indent);
|
|
||||||
header.imports.keyword.format(buf, indent);
|
|
||||||
fmt_imports(buf, header.imports.item, indent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt_hosted_header<'a>(buf: &mut Buf, header: &'a HostedHeader<'a>) {
|
pub fn fmt_hosted_header<'a>(buf: &mut Buf, header: &'a HostedHeader<'a>) {
|
||||||
|
@ -10,9 +10,9 @@ use roc_parse::{
|
|||||||
StrSegment, Tag, TypeAnnotation, TypeDef, TypeHeader, ValueDef, WhenBranch,
|
StrSegment, Tag, TypeAnnotation, TypeDef, TypeHeader, ValueDef, WhenBranch,
|
||||||
},
|
},
|
||||||
header::{
|
header::{
|
||||||
AppHeader, ExposedName, HostedHeader, ImportsEntry, InterfaceHeader, KeywordItem,
|
AppHeader, ExposedName, HostedHeader, ImportsEntry, KeywordItem, ModuleHeader, ModuleName,
|
||||||
ModuleName, PackageEntry, PackageHeader, PackageName, PlatformHeader, PlatformRequires,
|
PackageEntry, PackageHeader, PackageName, PlatformHeader, PlatformRequires, ProvidesTo, To,
|
||||||
ProvidesTo, To, TypedIdent,
|
TypedIdent,
|
||||||
},
|
},
|
||||||
ident::{BadIdent, UppercaseIdent},
|
ident::{BadIdent, UppercaseIdent},
|
||||||
};
|
};
|
||||||
@ -283,11 +283,10 @@ impl<'a> RemoveSpaces<'a> for ProvidesTo<'a> {
|
|||||||
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 {
|
||||||
let header = match &self.header {
|
let header = match &self.header {
|
||||||
Header::Interface(header) => Header::Interface(InterfaceHeader {
|
Header::Module(header) => Header::Module(ModuleHeader {
|
||||||
before_name: &[],
|
before_exposes: &[],
|
||||||
name: header.name.remove_spaces(arena),
|
|
||||||
exposes: header.exposes.remove_spaces(arena),
|
exposes: header.exposes.remove_spaces(arena),
|
||||||
imports: header.imports.remove_spaces(arena),
|
interface_imports: header.interface_imports.remove_spaces(arena),
|
||||||
}),
|
}),
|
||||||
Header::App(header) => Header::App(AppHeader {
|
Header::App(header) => Header::App(AppHeader {
|
||||||
before_name: &[],
|
before_name: &[],
|
||||||
|
@ -6109,9 +6109,7 @@ In roc, functions are always written as a lambda, like{}
|
|||||||
report_header_problem_as(
|
report_header_problem_as(
|
||||||
indoc!(
|
indoc!(
|
||||||
r"
|
r"
|
||||||
interface Foobar
|
module [main, @Foo]
|
||||||
exposes [main, @Foo]
|
|
||||||
imports [pf.Task, Base64]
|
|
||||||
"
|
"
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
@ -6120,39 +6118,12 @@ In roc, functions are always written as a lambda, like{}
|
|||||||
|
|
||||||
I am partway through parsing an `exposes` list, but I got stuck here:
|
I am partway through parsing an `exposes` list, but I got stuck here:
|
||||||
|
|
||||||
1│ interface Foobar
|
1│ module [main, @Foo]
|
||||||
2│ exposes [main, @Foo]
|
|
||||||
^
|
^
|
||||||
|
|
||||||
I was expecting a type name, value name or function name next, like
|
I was expecting a type name, value name or function name next, like
|
||||||
|
|
||||||
exposes [Animal, default, tame]
|
[Animal, default, tame]
|
||||||
"
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn invalid_module_name() {
|
|
||||||
report_header_problem_as(
|
|
||||||
indoc!(
|
|
||||||
r"
|
|
||||||
interface foobar
|
|
||||||
exposes [main, @Foo]
|
|
||||||
imports [pf.Task, Base64]
|
|
||||||
"
|
|
||||||
),
|
|
||||||
indoc!(
|
|
||||||
r"
|
|
||||||
── WEIRD MODULE NAME in /code/proj/Main.roc ────────────────────────────────────
|
|
||||||
|
|
||||||
I am partway through parsing a header, but got stuck here:
|
|
||||||
|
|
||||||
1│ interface foobar
|
|
||||||
^
|
|
||||||
|
|
||||||
I am expecting a module name next, like BigNum or Main. Module names
|
|
||||||
must start with an uppercase letter.
|
|
||||||
"
|
"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -49,8 +49,8 @@ use roc_mono::{drop_specialization, inc_dec};
|
|||||||
use roc_packaging::cache::RocCacheDir;
|
use roc_packaging::cache::RocCacheDir;
|
||||||
use roc_parse::ast::{self, CommentOrNewline, ExtractSpaces, Spaced, ValueDef};
|
use roc_parse::ast::{self, CommentOrNewline, ExtractSpaces, Spaced, ValueDef};
|
||||||
use roc_parse::header::{
|
use roc_parse::header::{
|
||||||
ExposedName, HeaderType, ImportsKeywordItem, PackageEntry, PackageHeader, PlatformHeader, To,
|
self, ExposedName, HeaderType, ImportsKeywordItem, PackageEntry, PackageHeader, PlatformHeader,
|
||||||
TypedIdent,
|
To, TypedIdent,
|
||||||
};
|
};
|
||||||
use roc_parse::module::parse_module_defs;
|
use roc_parse::module::parse_module_defs;
|
||||||
use roc_parse::parser::{FileError, SourceError, SyntaxError};
|
use roc_parse::parser::{FileError, SourceError, SyntaxError};
|
||||||
@ -644,7 +644,7 @@ struct CanAndCon {
|
|||||||
enum PlatformPath<'a> {
|
enum PlatformPath<'a> {
|
||||||
NotSpecified,
|
NotSpecified,
|
||||||
Valid(To<'a>),
|
Valid(To<'a>),
|
||||||
RootIsInterface,
|
RootIsModule,
|
||||||
RootIsHosted,
|
RootIsHosted,
|
||||||
RootIsPlatformModule,
|
RootIsPlatformModule,
|
||||||
}
|
}
|
||||||
@ -1204,8 +1204,9 @@ fn adjust_header_paths<'a>(
|
|||||||
{
|
{
|
||||||
debug_assert_eq!(*header_id, header_output.module_id);
|
debug_assert_eq!(*header_id, header_output.module_id);
|
||||||
|
|
||||||
if let HeaderType::Interface { name, .. } = header_type {
|
if let HeaderType::Module { name, .. } = header_type {
|
||||||
// Interface modules can have names like Foo.Bar.Baz,
|
// [modules-revamp] TODO: Privacy changes
|
||||||
|
// Modules can have names like Foo.Bar.Baz,
|
||||||
// in which case we need to adjust the src_dir to
|
// in which case we need to adjust the src_dir to
|
||||||
// remove the "Bar/Baz" directories in order to correctly
|
// remove the "Bar/Baz" directories in order to correctly
|
||||||
// resolve this interface module's imports!
|
// resolve this interface module's imports!
|
||||||
@ -2313,13 +2314,13 @@ fn update<'a>(
|
|||||||
state.exposed_modules = exposes_ids;
|
state.exposed_modules = exposes_ids;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Builtin { .. } | Interface { .. } => {
|
Builtin { .. } | Module { .. } => {
|
||||||
if header.is_root_module {
|
if header.is_root_module {
|
||||||
debug_assert!(matches!(
|
debug_assert!(matches!(
|
||||||
state.platform_path,
|
state.platform_path,
|
||||||
PlatformPath::NotSpecified
|
PlatformPath::NotSpecified
|
||||||
));
|
));
|
||||||
state.platform_path = PlatformPath::RootIsInterface;
|
state.platform_path = PlatformPath::RootIsModule;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Hosted { .. } => {
|
Hosted { .. } => {
|
||||||
@ -2956,7 +2957,7 @@ fn update<'a>(
|
|||||||
// This happens due to abilities. In detail, consider
|
// This happens due to abilities. In detail, consider
|
||||||
//
|
//
|
||||||
// # Default module
|
// # Default module
|
||||||
// interface Default exposes [default, getDefault]
|
// module [default, getDefault]
|
||||||
//
|
//
|
||||||
// Default implements default : {} -> a where a implements Default
|
// Default implements default : {} -> a where a implements Default
|
||||||
//
|
//
|
||||||
@ -3198,7 +3199,7 @@ fn finish_specialization<'a>(
|
|||||||
let module_id = state.root_id;
|
let module_id = state.root_id;
|
||||||
let uses_prebuilt_platform = match platform_data {
|
let uses_prebuilt_platform = match platform_data {
|
||||||
Some(data) => data.is_prebuilt,
|
Some(data) => data.is_prebuilt,
|
||||||
// If there's no platform data (e.g. because we're building an interface module)
|
// If there's no platform data (e.g. because we're building a module)
|
||||||
// then there's no prebuilt platform either!
|
// then there's no prebuilt platform either!
|
||||||
None => false,
|
None => false,
|
||||||
};
|
};
|
||||||
@ -3346,12 +3347,12 @@ fn load_package_from_disk<'a>(
|
|||||||
match parsed {
|
match parsed {
|
||||||
Ok((
|
Ok((
|
||||||
ast::Module {
|
ast::Module {
|
||||||
header: ast::Header::Interface(header),
|
header: ast::Header::Module(header),
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
_parse_state,
|
_parse_state,
|
||||||
)) => Err(LoadingProblem::UnexpectedHeader(format!(
|
)) => Err(LoadingProblem::UnexpectedHeader(format!(
|
||||||
"expected platform/package module, got Interface with header\n{header:?}"
|
"expected platform/package module, got Module with header\n{header:?}"
|
||||||
))),
|
))),
|
||||||
Ok((
|
Ok((
|
||||||
ast::Module {
|
ast::Module {
|
||||||
@ -3477,23 +3478,25 @@ fn load_builtin_module_help<'a>(
|
|||||||
match parsed {
|
match parsed {
|
||||||
Ok((
|
Ok((
|
||||||
ast::Module {
|
ast::Module {
|
||||||
header: ast::Header::Interface(header),
|
header: ast::Header::Module(header),
|
||||||
comments,
|
comments,
|
||||||
},
|
},
|
||||||
parse_state,
|
parse_state,
|
||||||
)) => {
|
)) => {
|
||||||
|
let name_stem = arena.alloc_str(filename.file_stem().unwrap().to_str().unwrap());
|
||||||
|
|
||||||
let info = HeaderInfo {
|
let info = HeaderInfo {
|
||||||
filename,
|
filename,
|
||||||
is_root_module,
|
is_root_module,
|
||||||
opt_shorthand,
|
opt_shorthand,
|
||||||
packages: &[],
|
packages: &[],
|
||||||
header_type: HeaderType::Builtin {
|
header_type: HeaderType::Builtin {
|
||||||
name: header.name.value,
|
name: header::ModuleName::new(name_stem),
|
||||||
exposes: unspace(arena, header.exposes.item.items),
|
exposes: unspace(arena, header.exposes.items),
|
||||||
generates_with: &[],
|
generates_with: &[],
|
||||||
},
|
},
|
||||||
module_comments: comments,
|
module_comments: comments,
|
||||||
header_imports: Some(header.imports),
|
header_imports: header.interface_imports,
|
||||||
};
|
};
|
||||||
|
|
||||||
(info, parse_state)
|
(info, parse_state)
|
||||||
@ -3693,45 +3696,6 @@ fn find_task<T>(local: &Worker<T>, global: &Injector<T>, stealers: &[Stealer<T>]
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_interface_matches_file_path<'a>(
|
|
||||||
interface_name: Loc<roc_parse::header::ModuleName<'a>>,
|
|
||||||
path: &Path,
|
|
||||||
state: &roc_parse::state::State<'a>,
|
|
||||||
) -> Result<(), LoadingProblem<'a>> {
|
|
||||||
let module_parts = interface_name.value.as_str().split(MODULE_SEPARATOR).rev();
|
|
||||||
|
|
||||||
let mut is_mismatched = false;
|
|
||||||
let mut opt_path = Some(path);
|
|
||||||
for part in module_parts {
|
|
||||||
match opt_path.and_then(|path| path.file_stem().map(|fi| (path, fi))) {
|
|
||||||
None => {
|
|
||||||
is_mismatched = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Some((path, fi)) => {
|
|
||||||
if fi != part {
|
|
||||||
is_mismatched = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
opt_path = path.parent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !is_mismatched {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
use roc_parse::parser::EHeader;
|
|
||||||
let syntax_problem =
|
|
||||||
SyntaxError::Header(EHeader::InconsistentModuleName(interface_name.region));
|
|
||||||
let problem = LoadingProblem::ParsingFailed(FileError {
|
|
||||||
problem: SourceError::new(syntax_problem, state),
|
|
||||||
filename: path.to_path_buf(),
|
|
||||||
});
|
|
||||||
Err(problem)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct HeaderOutput<'a> {
|
struct HeaderOutput<'a> {
|
||||||
module_id: ModuleId,
|
module_id: ModuleId,
|
||||||
@ -3798,48 +3762,35 @@ fn parse_header<'a>(
|
|||||||
match parsed {
|
match parsed {
|
||||||
Ok((
|
Ok((
|
||||||
ast::Module {
|
ast::Module {
|
||||||
header: ast::Header::Interface(header),
|
header: ast::Header::Module(header),
|
||||||
comments,
|
comments,
|
||||||
},
|
},
|
||||||
parse_state,
|
parse_state,
|
||||||
)) => {
|
)) => {
|
||||||
verify_interface_matches_file_path(header.name, &filename, &parse_state)?;
|
let module_name = match opt_expected_module_name {
|
||||||
|
Some(pq_name) => arena.alloc_str(pq_name.as_inner().as_str()),
|
||||||
|
None => {
|
||||||
|
// [modules-revamp] [privacy-changes] TODO: Support test/check on nested modules
|
||||||
|
arena.alloc_str(filename.file_stem().unwrap().to_str().unwrap())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let header_name_region = header.name.region;
|
|
||||||
let info = HeaderInfo {
|
let info = HeaderInfo {
|
||||||
filename,
|
filename,
|
||||||
is_root_module,
|
is_root_module,
|
||||||
opt_shorthand,
|
opt_shorthand,
|
||||||
packages: &[],
|
packages: &[],
|
||||||
header_type: HeaderType::Interface {
|
header_type: HeaderType::Module {
|
||||||
name: header.name.value,
|
name: roc_parse::header::ModuleName::new(module_name),
|
||||||
exposes: unspace(arena, header.exposes.item.items),
|
exposes: unspace(arena, header.exposes.items),
|
||||||
},
|
},
|
||||||
module_comments: comments,
|
module_comments: comments,
|
||||||
header_imports: Some(header.imports),
|
header_imports: header.interface_imports,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (module_id, module_name, header) =
|
let (module_id, _, header) =
|
||||||
build_header(info, parse_state.clone(), module_ids, module_timing)?;
|
build_header(info, parse_state.clone(), module_ids, module_timing)?;
|
||||||
|
|
||||||
if let Some(expected_module_name) = opt_expected_module_name {
|
|
||||||
if expected_module_name != module_name {
|
|
||||||
let problem = SourceError::new(
|
|
||||||
IncorrectModuleName {
|
|
||||||
module_id,
|
|
||||||
found: Loc::at(header_name_region, module_name),
|
|
||||||
expected: expected_module_name,
|
|
||||||
},
|
|
||||||
&parse_state,
|
|
||||||
);
|
|
||||||
let problem = LoadingProblem::IncorrectModuleName(FileError {
|
|
||||||
problem,
|
|
||||||
filename: header.module_path,
|
|
||||||
});
|
|
||||||
return Err(problem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(HeaderOutput {
|
Ok(HeaderOutput {
|
||||||
module_id,
|
module_id,
|
||||||
msg: Msg::Header(header),
|
msg: Msg::Header(header),
|
||||||
@ -4217,14 +4168,9 @@ fn build_header<'a>(
|
|||||||
// Package modules do not have names.
|
// Package modules do not have names.
|
||||||
String::new().into()
|
String::new().into()
|
||||||
}
|
}
|
||||||
HeaderType::Interface { name, .. }
|
HeaderType::Module { name, .. }
|
||||||
| HeaderType::Builtin { name, .. }
|
| HeaderType::Builtin { name, .. }
|
||||||
| HeaderType::Hosted { name, .. } => {
|
| HeaderType::Hosted { name, .. } => name.as_str().into(),
|
||||||
// TODO check to see if name is consistent with filename.
|
|
||||||
// If it isn't, report a problem!
|
|
||||||
|
|
||||||
name.as_str().into()
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let (name, home) = {
|
let (name, home) = {
|
||||||
@ -5172,7 +5118,7 @@ fn parse<'a>(
|
|||||||
}
|
}
|
||||||
HeaderType::App { .. }
|
HeaderType::App { .. }
|
||||||
| HeaderType::Package { .. }
|
| HeaderType::Package { .. }
|
||||||
| HeaderType::Interface { .. }
|
| HeaderType::Module { .. }
|
||||||
| HeaderType::Builtin { .. }
|
| HeaderType::Builtin { .. }
|
||||||
| HeaderType::Hosted { .. } => {}
|
| HeaderType::Hosted { .. } => {}
|
||||||
};
|
};
|
||||||
@ -6408,12 +6354,12 @@ fn report_cannot_run(
|
|||||||
severity: Severity::RuntimeError,
|
severity: Severity::RuntimeError,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RootIsInterface => {
|
RootIsModule => {
|
||||||
let doc = alloc.stack([
|
let doc = alloc.stack([
|
||||||
alloc.reflow(
|
alloc.reflow(
|
||||||
r"The input file is an `interface` module, but only `app` modules can be run.",
|
r"The input file is a module, but only `app` modules can be run.",
|
||||||
),
|
),
|
||||||
alloc.reflow(r"Tip: You can use `roc check` or `roc test` to verify an interface module like this one."),
|
alloc.reflow(r"Tip: You can use `roc check` or `roc test` to verify a module like this one."),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
|
@ -339,7 +339,7 @@ fn import_transitive_alias() {
|
|||||||
"RBTree.roc",
|
"RBTree.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r"
|
r"
|
||||||
interface RBTree exposes [RedBlackTree, empty] imports []
|
module [RedBlackTree, empty]
|
||||||
|
|
||||||
# The color of a node. Leaves are considered Black.
|
# The color of a node. Leaves are considered Black.
|
||||||
NodeColor : [Red, Black]
|
NodeColor : [Red, Black]
|
||||||
@ -357,7 +357,7 @@ fn import_transitive_alias() {
|
|||||||
"Other.roc",
|
"Other.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r"
|
r"
|
||||||
interface Other exposes [empty] imports []
|
module [empty]
|
||||||
|
|
||||||
import RBTree
|
import RBTree
|
||||||
|
|
||||||
@ -372,9 +372,9 @@ fn import_transitive_alias() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn interface_with_deps() {
|
fn module_with_deps() {
|
||||||
let subs_by_module = Default::default();
|
let subs_by_module = Default::default();
|
||||||
let src_dir = fixtures_dir().join("interface_with_deps");
|
let src_dir = fixtures_dir().join("module_with_deps");
|
||||||
let filename = src_dir.join("Primary.roc");
|
let filename = src_dir.join("Primary.roc");
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let loaded = load_and_typecheck(
|
let loaded = load_and_typecheck(
|
||||||
@ -488,7 +488,7 @@ fn load_docs() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn import_alias() {
|
fn import_alias() {
|
||||||
let subs_by_module = Default::default();
|
let subs_by_module = Default::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "ImportAlias", subs_by_module);
|
let loaded_module = load_fixture("module_with_deps", "ImportAlias", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
@ -501,7 +501,7 @@ fn import_alias() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn import_inside_def() {
|
fn import_inside_def() {
|
||||||
let subs_by_module = Default::default();
|
let subs_by_module = Default::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "ImportInsideDef", subs_by_module);
|
let loaded_module = load_fixture("module_with_deps", "ImportInsideDef", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
@ -517,7 +517,7 @@ fn import_inside_def() {
|
|||||||
fn exposed_used_outside_scope() {
|
fn exposed_used_outside_scope() {
|
||||||
let subs_by_module = Default::default();
|
let subs_by_module = Default::default();
|
||||||
load_fixture(
|
load_fixture(
|
||||||
"interface_with_deps",
|
"module_with_deps",
|
||||||
"ExposedUsedOutsideScope",
|
"ExposedUsedOutsideScope",
|
||||||
subs_by_module,
|
subs_by_module,
|
||||||
);
|
);
|
||||||
@ -527,17 +527,13 @@ fn exposed_used_outside_scope() {
|
|||||||
#[should_panic(expected = "MODULE NOT IMPORTED")]
|
#[should_panic(expected = "MODULE NOT IMPORTED")]
|
||||||
fn import_used_outside_scope() {
|
fn import_used_outside_scope() {
|
||||||
let subs_by_module = Default::default();
|
let subs_by_module = Default::default();
|
||||||
load_fixture(
|
load_fixture("module_with_deps", "ImportUsedOutsideScope", subs_by_module);
|
||||||
"interface_with_deps",
|
|
||||||
"ImportUsedOutsideScope",
|
|
||||||
subs_by_module,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_load_and_typecheck() {
|
fn test_load_and_typecheck() {
|
||||||
let subs_by_module = Default::default();
|
let subs_by_module = Default::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "WithBuiltins", subs_by_module);
|
let loaded_module = load_fixture("module_with_deps", "WithBuiltins", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
@ -558,7 +554,7 @@ fn test_load_and_typecheck() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn iface_quicksort() {
|
fn iface_quicksort() {
|
||||||
let subs_by_module = Default::default();
|
let subs_by_module = Default::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "Quicksort", subs_by_module);
|
let loaded_module = load_fixture("module_with_deps", "Quicksort", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
@ -574,7 +570,7 @@ fn iface_quicksort() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn load_astar() {
|
fn load_astar() {
|
||||||
let subs_by_module = Default::default();
|
let subs_by_module = Default::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "AStar", subs_by_module);
|
let loaded_module = load_fixture("module_with_deps", "AStar", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
@ -606,7 +602,7 @@ fn load_principal_types() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn iface_dep_types() {
|
fn iface_dep_types() {
|
||||||
let subs_by_module = Default::default();
|
let subs_by_module = Default::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "Primary", subs_by_module);
|
let loaded_module = load_fixture("module_with_deps", "Primary", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
@ -650,7 +646,7 @@ fn app_dep_types() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn imported_dep_regression() {
|
fn imported_dep_regression() {
|
||||||
let subs_by_module = Default::default();
|
let subs_by_module = Default::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "OneDep", subs_by_module);
|
let loaded_module = load_fixture("module_with_deps", "OneDep", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
@ -663,7 +659,7 @@ fn imported_dep_regression() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn ingested_file() {
|
fn ingested_file() {
|
||||||
let subs_by_module = Default::default();
|
let subs_by_module = Default::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "IngestedFile", subs_by_module);
|
let loaded_module = load_fixture("module_with_deps", "IngestedFile", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
@ -678,7 +674,7 @@ fn ingested_file() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn ingested_file_bytes() {
|
fn ingested_file_bytes() {
|
||||||
let subs_by_module = Default::default();
|
let subs_by_module = Default::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "IngestedFileBytes", subs_by_module);
|
let loaded_module = load_fixture("module_with_deps", "IngestedFileBytes", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
@ -695,7 +691,7 @@ fn parse_problem() {
|
|||||||
"Main.roc",
|
"Main.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r"
|
r"
|
||||||
interface Main exposes [main] imports []
|
module [main]
|
||||||
|
|
||||||
main = [
|
main = [
|
||||||
"
|
"
|
||||||
@ -732,7 +728,7 @@ fn parse_problem() {
|
|||||||
#[should_panic(expected = "FILE NOT FOUND")]
|
#[should_panic(expected = "FILE NOT FOUND")]
|
||||||
fn file_not_found() {
|
fn file_not_found() {
|
||||||
let subs_by_module = Default::default();
|
let subs_by_module = Default::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "invalid$name", subs_by_module);
|
let loaded_module = load_fixture("module_with_deps", "invalid$name", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
@ -887,7 +883,7 @@ fn opaque_wrapped_unwrapped_outside_defining_module() {
|
|||||||
"Age.roc",
|
"Age.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r"
|
r"
|
||||||
interface Age exposes [Age] imports []
|
module [Age]
|
||||||
|
|
||||||
Age := U32
|
Age := U32
|
||||||
"
|
"
|
||||||
@ -897,7 +893,7 @@ fn opaque_wrapped_unwrapped_outside_defining_module() {
|
|||||||
"Main.roc",
|
"Main.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r"
|
r"
|
||||||
interface Main exposes [twenty, readAge] imports []
|
module [twenty, readAge]
|
||||||
|
|
||||||
import Age exposing [Age]
|
import Age exposing [Age]
|
||||||
|
|
||||||
@ -965,7 +961,8 @@ fn unused_imports() {
|
|||||||
"Dep1.roc",
|
"Dep1.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
interface Dep1 exposes [one] imports []
|
module [one]
|
||||||
|
|
||||||
one = 1
|
one = 1
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
@ -974,7 +971,8 @@ fn unused_imports() {
|
|||||||
"Dep2.roc",
|
"Dep2.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
interface Dep2 exposes [two] imports []
|
module [two]
|
||||||
|
|
||||||
two = 2
|
two = 2
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
@ -983,7 +981,7 @@ fn unused_imports() {
|
|||||||
"Dep3.roc",
|
"Dep3.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
interface Dep3 exposes [Three, three] imports []
|
module [Three, three]
|
||||||
|
|
||||||
Three : [Three]
|
Three : [Three]
|
||||||
|
|
||||||
@ -995,7 +993,7 @@ fn unused_imports() {
|
|||||||
"Main.roc",
|
"Main.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
interface Main exposes [usedModule, unusedModule, unusedExposed, unusedWithAlias, usingThreeValue] imports []
|
module [usedModule, unusedModule, unusedExposed, usingThreeValue, unusedWithAlias]
|
||||||
|
|
||||||
import Dep1
|
import Dep1
|
||||||
import Dep3 exposing [Three]
|
import Dep3 exposing [Three]
|
||||||
@ -1663,48 +1661,13 @@ fn import_builtin_in_platform_and_check_app() {
|
|||||||
assert!(result.is_ok(), "should check");
|
assert!(result.is_ok(), "should check");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn module_doesnt_match_file_path() {
|
|
||||||
let modules = vec![(
|
|
||||||
"Age.roc",
|
|
||||||
indoc!(
|
|
||||||
r"
|
|
||||||
interface NotAge exposes [Age] imports []
|
|
||||||
|
|
||||||
Age := U32
|
|
||||||
"
|
|
||||||
),
|
|
||||||
)];
|
|
||||||
|
|
||||||
let err = multiple_modules("module_doesnt_match_file_path", modules).unwrap_err();
|
|
||||||
assert_eq!(
|
|
||||||
err,
|
|
||||||
indoc!(
|
|
||||||
r"
|
|
||||||
── WEIRD MODULE NAME in tmp/module_doesnt_match_file_path/Age.roc ──────────────
|
|
||||||
|
|
||||||
This module name does not correspond with the file path it is defined
|
|
||||||
in:
|
|
||||||
|
|
||||||
1│ interface NotAge exposes [Age] imports []
|
|
||||||
^^^^^^
|
|
||||||
|
|
||||||
Module names must correspond with the file paths they are defined in.
|
|
||||||
For example, I expect to see BigNum defined in BigNum.roc, or Math.Sin
|
|
||||||
defined in Math/Sin.roc."
|
|
||||||
),
|
|
||||||
"\n{}",
|
|
||||||
err
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn module_cyclic_import_itself() {
|
fn module_cyclic_import_itself() {
|
||||||
let modules = vec![(
|
let modules = vec![(
|
||||||
"Age.roc",
|
"Age.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r"
|
r"
|
||||||
interface Age exposes [] imports []
|
module []
|
||||||
|
|
||||||
import Age
|
import Age
|
||||||
"
|
"
|
||||||
@ -1742,7 +1705,8 @@ fn module_cyclic_import_transitive() {
|
|||||||
"Age.roc",
|
"Age.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r"
|
r"
|
||||||
interface Age exposes [] imports []
|
module []
|
||||||
|
|
||||||
import Person
|
import Person
|
||||||
"
|
"
|
||||||
),
|
),
|
||||||
@ -1751,7 +1715,8 @@ fn module_cyclic_import_transitive() {
|
|||||||
"Person.roc",
|
"Person.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r"
|
r"
|
||||||
interface Person exposes [] imports []
|
module []
|
||||||
|
|
||||||
import Age
|
import Age
|
||||||
"
|
"
|
||||||
),
|
),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use crate::header::{
|
use crate::header::{
|
||||||
self, AppHeader, HostedHeader, InterfaceHeader, ModuleName, PackageHeader, PlatformHeader,
|
self, AppHeader, HostedHeader, ModuleHeader, ModuleName, PackageHeader, PlatformHeader,
|
||||||
};
|
};
|
||||||
use crate::ident::Accessor;
|
use crate::ident::Accessor;
|
||||||
use crate::parser::ESingleQuote;
|
use crate::parser::ESingleQuote;
|
||||||
@ -99,6 +99,21 @@ pub struct Module<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Module<'a> {
|
impl<'a> Module<'a> {
|
||||||
|
pub fn upgrade_header_imports(self, arena: &'a Bump) -> (Self, Defs<'a>) {
|
||||||
|
let (header, defs) = match self.header {
|
||||||
|
Header::Module(header) => (
|
||||||
|
Header::Module(ModuleHeader {
|
||||||
|
interface_imports: None,
|
||||||
|
..header
|
||||||
|
}),
|
||||||
|
Self::header_imports_to_defs(arena, header.interface_imports),
|
||||||
|
),
|
||||||
|
header => (header, Defs::default()),
|
||||||
|
};
|
||||||
|
|
||||||
|
(Module { header, ..self }, defs)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn header_imports_to_defs(
|
pub fn header_imports_to_defs(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
imports: Option<
|
imports: Option<
|
||||||
@ -209,7 +224,7 @@ impl<'a> Module<'a> {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Header<'a> {
|
pub enum Header<'a> {
|
||||||
Interface(InterfaceHeader<'a>),
|
Module(ModuleHeader<'a>),
|
||||||
App(AppHeader<'a>),
|
App(AppHeader<'a>),
|
||||||
Package(PackageHeader<'a>),
|
Package(PackageHeader<'a>),
|
||||||
Platform(PlatformHeader<'a>),
|
Platform(PlatformHeader<'a>),
|
||||||
@ -2272,7 +2287,7 @@ impl<'a> Malformed for Module<'a> {
|
|||||||
impl<'a> Malformed for Header<'a> {
|
impl<'a> Malformed for Header<'a> {
|
||||||
fn is_malformed(&self) -> bool {
|
fn is_malformed(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Header::Interface(header) => header.is_malformed(),
|
Header::Module(header) => header.is_malformed(),
|
||||||
Header::App(header) => header.is_malformed(),
|
Header::App(header) => header.is_malformed(),
|
||||||
Header::Package(header) => header.is_malformed(),
|
Header::Package(header) => header.is_malformed(),
|
||||||
Header::Platform(header) => header.is_malformed(),
|
Header::Platform(header) => header.is_malformed(),
|
||||||
|
@ -19,7 +19,7 @@ impl<'a> HeaderType<'a> {
|
|||||||
}
|
}
|
||||||
| HeaderType::Hosted { exposes, .. }
|
| HeaderType::Hosted { exposes, .. }
|
||||||
| HeaderType::Builtin { exposes, .. }
|
| HeaderType::Builtin { exposes, .. }
|
||||||
| HeaderType::Interface { exposes, .. } => exposes,
|
| HeaderType::Module { exposes, .. } => exposes,
|
||||||
HeaderType::Platform { .. } | HeaderType::Package { .. } => &[],
|
HeaderType::Platform { .. } | HeaderType::Package { .. } => &[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ impl<'a> HeaderType<'a> {
|
|||||||
HeaderType::Builtin { .. } => "builtin",
|
HeaderType::Builtin { .. } => "builtin",
|
||||||
HeaderType::Package { .. } => "package",
|
HeaderType::Package { .. } => "package",
|
||||||
HeaderType::Platform { .. } => "platform",
|
HeaderType::Platform { .. } => "platform",
|
||||||
HeaderType::Interface { .. } => "interface",
|
HeaderType::Module { .. } => "module",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ pub enum HeaderType<'a> {
|
|||||||
/// usually `pf`
|
/// usually `pf`
|
||||||
config_shorthand: &'a str,
|
config_shorthand: &'a str,
|
||||||
},
|
},
|
||||||
Interface {
|
Module {
|
||||||
name: ModuleName<'a>,
|
name: ModuleName<'a>,
|
||||||
exposes: &'a [Loc<ExposedName<'a>>],
|
exposes: &'a [Loc<ExposedName<'a>>],
|
||||||
},
|
},
|
||||||
@ -82,9 +82,9 @@ pub enum HeaderType<'a> {
|
|||||||
impl<'a> HeaderType<'a> {
|
impl<'a> HeaderType<'a> {
|
||||||
pub fn get_name(self) -> Option<&'a str> {
|
pub fn get_name(self) -> Option<&'a str> {
|
||||||
match self {
|
match self {
|
||||||
Self::Interface { name, .. }
|
Self::Module { name, .. } | Self::Builtin { name, .. } | Self::Hosted { name, .. } => {
|
||||||
| Self::Builtin { name, .. }
|
Some(name.into())
|
||||||
| Self::Hosted { name, .. } => Some(name.into()),
|
}
|
||||||
Self::App {
|
Self::App {
|
||||||
output_name: StrLiteral::PlainLine(name),
|
output_name: StrLiteral::PlainLine(name),
|
||||||
..
|
..
|
||||||
@ -106,13 +106,11 @@ impl<'a> HeaderType<'a> {
|
|||||||
|
|
||||||
pub fn to_maybe_builtin(self, module_id: ModuleId) -> Self {
|
pub fn to_maybe_builtin(self, module_id: ModuleId) -> Self {
|
||||||
match self {
|
match self {
|
||||||
HeaderType::Interface { name, exposes } if module_id.is_builtin() => {
|
HeaderType::Module { name, exposes } if module_id.is_builtin() => HeaderType::Builtin {
|
||||||
HeaderType::Builtin {
|
|
||||||
name,
|
name,
|
||||||
exposes,
|
exposes,
|
||||||
generates_with: &[],
|
generates_with: &[],
|
||||||
}
|
},
|
||||||
}
|
|
||||||
_ => self,
|
_ => self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -246,12 +244,12 @@ pub struct KeywordItem<'a, K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct InterfaceHeader<'a> {
|
pub struct ModuleHeader<'a> {
|
||||||
pub before_name: &'a [CommentOrNewline<'a>],
|
pub before_exposes: &'a [CommentOrNewline<'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>>>>>,
|
// Keeping this so we can format old interface header into module headers
|
||||||
pub imports: KeywordItem<'a, ImportsKeyword, Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>>,
|
pub interface_imports: Option<KeywordItem<'a, ImportsKeyword, ImportsCollection<'a>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ImportsKeywordItem<'a> = KeywordItem<'a, ImportsKeyword, ImportsCollection<'a>>;
|
pub type ImportsKeywordItem<'a> = KeywordItem<'a, ImportsKeyword, ImportsCollection<'a>>;
|
||||||
@ -430,7 +428,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Malformed for InterfaceHeader<'a> {
|
impl<'a> Malformed for ModuleHeader<'a> {
|
||||||
fn is_malformed(&self) -> bool {
|
fn is_malformed(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use crate::ast::{Collection, Defs, Header, Module, Spaced, Spaces};
|
use crate::ast::{Collection, CommentOrNewline, 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, ExposesKeyword, GeneratesKeyword,
|
package_entry, package_name, AppHeader, ExposedName, ExposesKeyword, GeneratesKeyword,
|
||||||
HostedHeader, ImportsEntry, ImportsKeyword, InterfaceHeader, Keyword, KeywordItem, ModuleName,
|
HostedHeader, ImportsEntry, ImportsKeyword, ImportsKeywordItem, Keyword, KeywordItem,
|
||||||
PackageEntry, PackageHeader, PackagesKeyword, PlatformHeader, PlatformRequires,
|
ModuleHeader, ModuleName, PackageEntry, PackageHeader, PackagesKeyword, PlatformHeader,
|
||||||
ProvidesKeyword, ProvidesTo, RequiresKeyword, To, ToKeyword, TypedIdent, WithKeyword,
|
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, *};
|
||||||
@ -60,12 +61,20 @@ pub fn header<'a>() -> impl Parser<'a, Module<'a>, EHeader<'a>> {
|
|||||||
record!(Module {
|
record!(Module {
|
||||||
comments: space0_e(EHeader::IndentStart),
|
comments: space0_e(EHeader::IndentStart),
|
||||||
header: one_of![
|
header: one_of![
|
||||||
|
map!(
|
||||||
|
skip_first!(
|
||||||
|
keyword("module", EHeader::Start),
|
||||||
|
increment_min_indent(module_header())
|
||||||
|
),
|
||||||
|
Header::Module
|
||||||
|
),
|
||||||
|
// Old headers
|
||||||
map!(
|
map!(
|
||||||
skip_first!(
|
skip_first!(
|
||||||
keyword("interface", EHeader::Start),
|
keyword("interface", EHeader::Start),
|
||||||
increment_min_indent(interface_header())
|
increment_min_indent(interface_header())
|
||||||
),
|
),
|
||||||
Header::Interface
|
Header::Module
|
||||||
),
|
),
|
||||||
map!(
|
map!(
|
||||||
skip_first!(
|
skip_first!(
|
||||||
@ -100,22 +109,65 @@ pub fn header<'a>() -> impl Parser<'a, Module<'a>, EHeader<'a>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn interface_header<'a>() -> impl Parser<'a, InterfaceHeader<'a>, EHeader<'a>> {
|
fn module_header<'a>() -> impl Parser<'a, ModuleHeader<'a>, EHeader<'a>> {
|
||||||
record!(InterfaceHeader {
|
record!(ModuleHeader {
|
||||||
before_name: space0_e(EHeader::IndentStart),
|
before_exposes: space0_e(EHeader::IndentStart),
|
||||||
name: loc!(module_name_help(EHeader::ModuleName)),
|
exposes: specialize_err(EHeader::Exposes, exposes_list()),
|
||||||
exposes: specialize_err(EHeader::Exposes, exposes_values()),
|
interface_imports: succeed!(None)
|
||||||
imports: specialize_err(EHeader::Imports, imports()),
|
})
|
||||||
|
.trace("module_header")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse old interface headers so we can format them into module headers
|
||||||
|
#[inline(always)]
|
||||||
|
fn interface_header<'a>() -> impl Parser<'a, ModuleHeader<'a>, EHeader<'a>> {
|
||||||
|
use bumpalo::collections::Vec;
|
||||||
|
|
||||||
|
let before_exposes = map_with_arena!(
|
||||||
|
and!(
|
||||||
|
skip_second!(
|
||||||
|
space0_e(EHeader::IndentStart),
|
||||||
|
loc!(module_name_help(EHeader::ModuleName))
|
||||||
|
),
|
||||||
|
specialize_err(EHeader::Exposes, exposes_kw())
|
||||||
|
),
|
||||||
|
|arena: &'a bumpalo::Bump,
|
||||||
|
(before_name, kw): (&'a [CommentOrNewline<'a>], Spaces<'a, ExposesKeyword>)| {
|
||||||
|
let mut combined: Vec<CommentOrNewline> =
|
||||||
|
Vec::with_capacity_in(before_name.len() + kw.before.len() + kw.after.len(), arena);
|
||||||
|
combined.extend(before_name);
|
||||||
|
combined.extend(kw.before);
|
||||||
|
combined.extend(kw.after);
|
||||||
|
arena.alloc(combined)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
record!(ModuleHeader {
|
||||||
|
before_exposes: before_exposes,
|
||||||
|
exposes: specialize_err(EHeader::Exposes, exposes_list()).trace("exposes_list"),
|
||||||
|
interface_imports: map!(
|
||||||
|
specialize_err(EHeader::Imports, imports()),
|
||||||
|
imports_none_if_empty
|
||||||
|
)
|
||||||
|
.trace("imports"),
|
||||||
})
|
})
|
||||||
.trace("interface_header")
|
.trace("interface_header")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn imports_none_if_empty(value: ImportsKeywordItem<'_>) -> Option<ImportsKeywordItem<'_>> {
|
||||||
|
if value.item.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[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>> {
|
||||||
record!(HostedHeader {
|
record!(HostedHeader {
|
||||||
before_name: space0_e(EHeader::IndentStart),
|
before_name: space0_e(EHeader::IndentStart),
|
||||||
name: loc!(module_name_help(EHeader::ModuleName)),
|
name: loc!(module_name_help(EHeader::ModuleName)),
|
||||||
exposes: specialize_err(EHeader::Exposes, exposes_values()),
|
exposes: specialize_err(EHeader::Exposes, exposes_values_kw()),
|
||||||
imports: specialize_err(EHeader::Imports, imports()),
|
imports: specialize_err(EHeader::Imports, imports()),
|
||||||
generates: specialize_err(EHeader::Generates, generates()),
|
generates: specialize_err(EHeader::Generates, generates()),
|
||||||
generates_with: specialize_err(EHeader::GeneratesWith, generates_with()),
|
generates_with: specialize_err(EHeader::GeneratesWith, generates_with()),
|
||||||
@ -388,26 +440,37 @@ 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_kw<'a>() -> impl Parser<
|
||||||
'a,
|
'a,
|
||||||
KeywordItem<'a, ExposesKeyword, Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>>,
|
KeywordItem<'a, ExposesKeyword, Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>>,
|
||||||
EExposes,
|
EExposes,
|
||||||
> {
|
> {
|
||||||
record!(KeywordItem {
|
record!(KeywordItem {
|
||||||
keyword: spaces_around_keyword(
|
keyword: exposes_kw(),
|
||||||
|
item: exposes_list()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn exposes_kw<'a>() -> impl Parser<'a, Spaces<'a, ExposesKeyword>, EExposes> {
|
||||||
|
spaces_around_keyword(
|
||||||
ExposesKeyword,
|
ExposesKeyword,
|
||||||
EExposes::Exposes,
|
EExposes::Exposes,
|
||||||
EExposes::IndentExposes,
|
EExposes::IndentExposes,
|
||||||
EExposes::IndentListStart
|
EExposes::IndentListStart,
|
||||||
),
|
)
|
||||||
item: collection_trailing_sep_e!(
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn exposes_list<'a>() -> impl Parser<'a, Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>, EExposes>
|
||||||
|
{
|
||||||
|
collection_trailing_sep_e!(
|
||||||
byte(b'[', EExposes::ListStart),
|
byte(b'[', EExposes::ListStart),
|
||||||
exposes_entry(EExposes::Identifier),
|
exposes_entry(EExposes::Identifier),
|
||||||
byte(b',', EExposes::ListEnd),
|
byte(b',', EExposes::ListEnd),
|
||||||
byte(b']', EExposes::ListEnd),
|
byte(b']', EExposes::ListEnd),
|
||||||
Spaced::SpaceBefore
|
Spaced::SpaceBefore
|
||||||
)
|
)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spaces_around_keyword<'a, K: Keyword, E>(
|
pub fn spaces_around_keyword<'a, K: Keyword, E>(
|
||||||
|
@ -1 +0,0 @@
|
|||||||
interface Foo exposes [] imports []
|
|
@ -1,27 +0,0 @@
|
|||||||
Module {
|
|
||||||
comments: [],
|
|
||||||
header: Interface(
|
|
||||||
InterfaceHeader {
|
|
||||||
before_name: [],
|
|
||||||
name: @10-13 ModuleName(
|
|
||||||
"Foo",
|
|
||||||
),
|
|
||||||
exposes: KeywordItem {
|
|
||||||
keyword: Spaces {
|
|
||||||
before: [],
|
|
||||||
item: ExposesKeyword,
|
|
||||||
after: [],
|
|
||||||
},
|
|
||||||
item: [],
|
|
||||||
},
|
|
||||||
imports: KeywordItem {
|
|
||||||
keyword: Spaces {
|
|
||||||
before: [],
|
|
||||||
item: ImportsKeyword,
|
|
||||||
after: [],
|
|
||||||
},
|
|
||||||
item: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
),
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
interface Foo exposes [] imports []
|
|
@ -0,0 +1 @@
|
|||||||
|
module []
|
@ -0,0 +1,10 @@
|
|||||||
|
Module {
|
||||||
|
comments: [],
|
||||||
|
header: Module(
|
||||||
|
ModuleHeader {
|
||||||
|
before_exposes: [],
|
||||||
|
exposes: [],
|
||||||
|
interface_imports: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
module []
|
@ -1 +0,0 @@
|
|||||||
interface T exposes [] imports []
|
|
@ -1,27 +0,0 @@
|
|||||||
Module {
|
|
||||||
comments: [],
|
|
||||||
header: Interface(
|
|
||||||
InterfaceHeader {
|
|
||||||
before_name: [],
|
|
||||||
name: @10-11 ModuleName(
|
|
||||||
"T",
|
|
||||||
),
|
|
||||||
exposes: KeywordItem {
|
|
||||||
keyword: Spaces {
|
|
||||||
before: [],
|
|
||||||
item: ExposesKeyword,
|
|
||||||
after: [],
|
|
||||||
},
|
|
||||||
item: [],
|
|
||||||
},
|
|
||||||
imports: KeywordItem {
|
|
||||||
keyword: Spaces {
|
|
||||||
before: [],
|
|
||||||
item: ImportsKeyword,
|
|
||||||
after: [],
|
|
||||||
},
|
|
||||||
item: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
),
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
interface T exposes [] imports []
|
|
@ -0,0 +1,5 @@
|
|||||||
|
module [
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
c,
|
||||||
|
]
|
@ -0,0 +1,25 @@
|
|||||||
|
Module {
|
||||||
|
comments: [],
|
||||||
|
header: Module(
|
||||||
|
ModuleHeader {
|
||||||
|
before_exposes: [],
|
||||||
|
exposes: [
|
||||||
|
@8-9 ExposedName(
|
||||||
|
"a",
|
||||||
|
),
|
||||||
|
@11-12 ExposedName(
|
||||||
|
"b",
|
||||||
|
),
|
||||||
|
@18-19 SpaceBefore(
|
||||||
|
ExposedName(
|
||||||
|
"c",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
interface_imports: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
module [a, b,
|
||||||
|
c]
|
@ -0,0 +1 @@
|
|||||||
|
module []
|
@ -0,0 +1,10 @@
|
|||||||
|
Module {
|
||||||
|
comments: [],
|
||||||
|
header: Module(
|
||||||
|
ModuleHeader {
|
||||||
|
before_exposes: [],
|
||||||
|
exposes: [],
|
||||||
|
interface_imports: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
module []
|
@ -1 +0,0 @@
|
|||||||
interface Foo.Bar.Baz exposes [] imports []
|
|
@ -1,27 +0,0 @@
|
|||||||
Module {
|
|
||||||
comments: [],
|
|
||||||
header: Interface(
|
|
||||||
InterfaceHeader {
|
|
||||||
before_name: [],
|
|
||||||
name: @10-21 ModuleName(
|
|
||||||
"Foo.Bar.Baz",
|
|
||||||
),
|
|
||||||
exposes: KeywordItem {
|
|
||||||
keyword: Spaces {
|
|
||||||
before: [],
|
|
||||||
item: ExposesKeyword,
|
|
||||||
after: [],
|
|
||||||
},
|
|
||||||
item: [],
|
|
||||||
},
|
|
||||||
imports: KeywordItem {
|
|
||||||
keyword: Spaces {
|
|
||||||
before: [],
|
|
||||||
item: ImportsKeyword,
|
|
||||||
after: [],
|
|
||||||
},
|
|
||||||
item: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
),
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
interface Foo.Bar.Baz exposes [] imports []
|
|
@ -0,0 +1 @@
|
|||||||
|
module [Foo, foo, bar]
|
@ -0,0 +1,20 @@
|
|||||||
|
Module {
|
||||||
|
comments: [],
|
||||||
|
header: Module(
|
||||||
|
ModuleHeader {
|
||||||
|
before_exposes: [],
|
||||||
|
exposes: [
|
||||||
|
@23-26 ExposedName(
|
||||||
|
"Foo",
|
||||||
|
),
|
||||||
|
@28-31 ExposedName(
|
||||||
|
"foo",
|
||||||
|
),
|
||||||
|
@33-36 ExposedName(
|
||||||
|
"bar",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
interface_imports: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
interface Foo exposes [Foo, foo, bar] imports []
|
@ -4768,10 +4768,10 @@ mod test_fmt {
|
|||||||
// MODULES
|
// MODULES
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn single_line_interface() {
|
fn single_line_module() {
|
||||||
module_formats_same(indoc!(
|
module_formats_same(indoc!(
|
||||||
r"
|
r"
|
||||||
interface Foo exposes [] imports []"
|
module []"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4781,12 +4781,14 @@ mod test_fmt {
|
|||||||
module_formats_to(
|
module_formats_to(
|
||||||
indoc!(
|
indoc!(
|
||||||
r"
|
r"
|
||||||
interface Foo exposes [] imports []
|
module []
|
||||||
|
|
||||||
a = 42 # Yay greetings"
|
a = 42 # Yay greetings"
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r"
|
r"
|
||||||
interface Foo exposes [] imports []
|
module []
|
||||||
|
|
||||||
a = 42 # Yay greetings
|
a = 42 # Yay greetings
|
||||||
"
|
"
|
||||||
),
|
),
|
||||||
@ -4794,49 +4796,25 @@ mod test_fmt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn multiline_interface() {
|
fn module_exposing() {
|
||||||
module_formats_same(indoc!(
|
module_formats_same(indoc!(
|
||||||
r"
|
r"
|
||||||
interface Foo
|
module [Bar, Baz, a, b]"
|
||||||
exposes []
|
|
||||||
imports []"
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn interface_exposing() {
|
fn module_exposing_multiline() {
|
||||||
module_formats_same(indoc!(
|
module_formats_same(indoc!(
|
||||||
r"
|
r"
|
||||||
interface Foo
|
module [
|
||||||
exposes [Bar, Baz, a, b]
|
|
||||||
imports []"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn interface_importing() {
|
|
||||||
module_formats_same(indoc!(
|
|
||||||
r"
|
|
||||||
interface Foo
|
|
||||||
exposes [Bar, Baz, a, b]
|
|
||||||
imports [Blah, Thing.{ foo, bar }, Stuff]"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn multi_line_interface() {
|
|
||||||
module_formats_same(indoc!(
|
|
||||||
r"
|
|
||||||
interface Foo
|
|
||||||
exposes [
|
|
||||||
Stuff,
|
Stuff,
|
||||||
Things,
|
Things,
|
||||||
somethingElse,
|
somethingElse,
|
||||||
]
|
]
|
||||||
imports [
|
|
||||||
Blah,
|
import Blah
|
||||||
Baz.{ stuff, things },
|
import Baz exposing [stuff, things]"
|
||||||
]"
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4866,9 +4844,7 @@ mod test_fmt {
|
|||||||
&format!(
|
&format!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
interface Foo
|
module []
|
||||||
exposes []
|
|
||||||
imports []
|
|
||||||
|
|
||||||
# comment 1{space}
|
# comment 1{space}
|
||||||
def = "" # comment 2{space}
|
def = "" # comment 2{space}
|
||||||
@ -4879,9 +4855,7 @@ mod test_fmt {
|
|||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
interface Foo
|
module []
|
||||||
exposes []
|
|
||||||
imports []
|
|
||||||
|
|
||||||
# comment 1
|
# comment 1
|
||||||
def = "" # comment 2
|
def = "" # comment 2
|
||||||
@ -5700,7 +5674,7 @@ mod test_fmt {
|
|||||||
|
|
||||||
module_formats_same(indoc!(
|
module_formats_same(indoc!(
|
||||||
r"
|
r"
|
||||||
interface Foo exposes [] imports []
|
module []
|
||||||
|
|
||||||
expect x == y
|
expect x == y
|
||||||
|
|
||||||
@ -5727,7 +5701,7 @@ mod test_fmt {
|
|||||||
|
|
||||||
module_formats_same(indoc!(
|
module_formats_same(indoc!(
|
||||||
r"
|
r"
|
||||||
interface Foo exposes [] imports []
|
module []
|
||||||
|
|
||||||
expect
|
expect
|
||||||
foo bar
|
foo bar
|
||||||
@ -5831,7 +5805,7 @@ mod test_fmt {
|
|||||||
fn ability_member_doc_comments() {
|
fn ability_member_doc_comments() {
|
||||||
module_formats_same(indoc!(
|
module_formats_same(indoc!(
|
||||||
r"
|
r"
|
||||||
interface Foo exposes [] imports []
|
module []
|
||||||
|
|
||||||
A implements
|
A implements
|
||||||
## This is member ab
|
## This is member ab
|
||||||
@ -5850,9 +5824,7 @@ mod test_fmt {
|
|||||||
module_formats_same(indoc!(
|
module_formats_same(indoc!(
|
||||||
r"
|
r"
|
||||||
# hello world
|
# hello world
|
||||||
interface Foo
|
module []
|
||||||
exposes []
|
|
||||||
imports []
|
|
||||||
"
|
"
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -5876,6 +5848,17 @@ mod test_fmt {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn comments_before_exposes_preserved() {
|
||||||
|
module_formats_same(indoc!(
|
||||||
|
r"
|
||||||
|
module
|
||||||
|
# comment
|
||||||
|
[a, b]
|
||||||
|
"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn clauses_with_multiple_abilities() {
|
fn clauses_with_multiple_abilities() {
|
||||||
expr_formats_same(indoc!(
|
expr_formats_same(indoc!(
|
||||||
|
@ -301,8 +301,8 @@ mod test_snapshots {
|
|||||||
pass/def_without_newline.expr,
|
pass/def_without_newline.expr,
|
||||||
pass/destructure_tag_assignment.expr,
|
pass/destructure_tag_assignment.expr,
|
||||||
pass/empty_app_header.header,
|
pass/empty_app_header.header,
|
||||||
|
pass/empty_module_header.header,
|
||||||
pass/empty_hosted_header.header,
|
pass/empty_hosted_header.header,
|
||||||
pass/empty_interface_header.header,
|
|
||||||
pass/empty_list.expr,
|
pass/empty_list.expr,
|
||||||
pass/empty_package_header.header,
|
pass/empty_package_header.header,
|
||||||
pass/empty_platform_header.header,
|
pass/empty_platform_header.header,
|
||||||
@ -333,7 +333,7 @@ mod test_snapshots {
|
|||||||
pass/inline_import.expr,
|
pass/inline_import.expr,
|
||||||
pass/inline_ingested_file.expr,
|
pass/inline_ingested_file.expr,
|
||||||
pass/int_with_underscore.expr,
|
pass/int_with_underscore.expr,
|
||||||
pass/interface_with_newline.header,
|
pass/module_with_newline.header,
|
||||||
pass/lambda_in_chain.expr,
|
pass/lambda_in_chain.expr,
|
||||||
pass/lambda_indent.expr,
|
pass/lambda_indent.expr,
|
||||||
pass/list_closing_indent_not_enough.expr,
|
pass/list_closing_indent_not_enough.expr,
|
||||||
@ -348,6 +348,7 @@ mod test_snapshots {
|
|||||||
pass/minus_twelve_minus_five.expr,
|
pass/minus_twelve_minus_five.expr,
|
||||||
pass/mixed_docs.expr,
|
pass/mixed_docs.expr,
|
||||||
pass/module_def_newline.moduledefs,
|
pass/module_def_newline.moduledefs,
|
||||||
|
pass/module_multiline_exposes.header,
|
||||||
pass/multi_backpassing.expr,
|
pass/multi_backpassing.expr,
|
||||||
pass/multi_backpassing_in_def.moduledefs,
|
pass/multi_backpassing_in_def.moduledefs,
|
||||||
pass/multi_backpassing_with_apply.expr,
|
pass/multi_backpassing_with_apply.expr,
|
||||||
@ -369,7 +370,6 @@ mod test_snapshots {
|
|||||||
pass/nested_def_annotation.moduledefs,
|
pass/nested_def_annotation.moduledefs,
|
||||||
pass/nested_def_without_newline.expr,
|
pass/nested_def_without_newline.expr,
|
||||||
pass/nested_if.expr,
|
pass/nested_if.expr,
|
||||||
pass/nested_module.header,
|
|
||||||
pass/newline_after_equals.expr, // Regression test for https://github.com/roc-lang/roc/issues/51
|
pass/newline_after_equals.expr, // Regression test for https://github.com/roc-lang/roc/issues/51
|
||||||
pass/newline_after_mul.expr,
|
pass/newline_after_mul.expr,
|
||||||
pass/newline_after_paren.expr,
|
pass/newline_after_paren.expr,
|
||||||
@ -409,6 +409,7 @@ mod test_snapshots {
|
|||||||
pass/outdented_colon_in_record.expr,
|
pass/outdented_colon_in_record.expr,
|
||||||
pass/outdented_list.expr,
|
pass/outdented_list.expr,
|
||||||
pass/outdented_record.expr,
|
pass/outdented_record.expr,
|
||||||
|
pass/old_interface_header.header,
|
||||||
pass/packed_singleton_list.expr,
|
pass/packed_singleton_list.expr,
|
||||||
pass/parens_in_type_def_apply.expr,
|
pass/parens_in_type_def_apply.expr,
|
||||||
pass/parens_in_value_def_annotation.expr,
|
pass/parens_in_value_def_annotation.expr,
|
||||||
|
@ -11,9 +11,8 @@ use roc_parse::{
|
|||||||
WhenBranch,
|
WhenBranch,
|
||||||
},
|
},
|
||||||
header::{
|
header::{
|
||||||
AppHeader, ExposedName, HostedHeader, ImportsEntry, InterfaceHeader, ModuleName,
|
AppHeader, ExposedName, HostedHeader, ImportsEntry, ModuleHeader, ModuleName, PackageEntry,
|
||||||
PackageEntry, PackageHeader, PackageName, PlatformHeader, PlatformRequires, ProvidesTo, To,
|
PackageHeader, PackageName, PlatformHeader, PlatformRequires, ProvidesTo, To, TypedIdent,
|
||||||
TypedIdent,
|
|
||||||
},
|
},
|
||||||
ident::{Accessor, UppercaseIdent},
|
ident::{Accessor, UppercaseIdent},
|
||||||
};
|
};
|
||||||
@ -202,7 +201,7 @@ impl IterTokens for Module<'_> {
|
|||||||
impl IterTokens for Header<'_> {
|
impl IterTokens for Header<'_> {
|
||||||
fn iter_tokens<'a>(&self, arena: &'a Bump) -> BumpVec<'a, Loc<Token>> {
|
fn iter_tokens<'a>(&self, arena: &'a Bump) -> BumpVec<'a, Loc<Token>> {
|
||||||
match self {
|
match self {
|
||||||
Header::Interface(ih) => ih.iter_tokens(arena),
|
Header::Module(mh) => mh.iter_tokens(arena),
|
||||||
Header::App(app) => app.iter_tokens(arena),
|
Header::App(app) => app.iter_tokens(arena),
|
||||||
Header::Package(pkg) => pkg.iter_tokens(arena),
|
Header::Package(pkg) => pkg.iter_tokens(arena),
|
||||||
Header::Platform(pf) => pf.iter_tokens(arena),
|
Header::Platform(pf) => pf.iter_tokens(arena),
|
||||||
@ -211,19 +210,15 @@ impl IterTokens for Header<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IterTokens for InterfaceHeader<'_> {
|
impl IterTokens for ModuleHeader<'_> {
|
||||||
fn iter_tokens<'a>(&self, arena: &'a Bump) -> BumpVec<'a, Loc<Token>> {
|
fn iter_tokens<'a>(&self, arena: &'a Bump) -> BumpVec<'a, Loc<Token>> {
|
||||||
let Self {
|
let Self {
|
||||||
before_name: _,
|
before_exposes: _,
|
||||||
name,
|
|
||||||
exposes,
|
exposes,
|
||||||
imports,
|
interface_imports: _,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
(name.iter_tokens(arena).into_iter())
|
exposes.iter_tokens(arena)
|
||||||
.chain(exposes.item.iter_tokens(arena))
|
|
||||||
.chain(imports.item.iter_tokens(arena))
|
|
||||||
.collect_in(arena)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ fn write_archive<W: Write>(path: &Path, writer: W) -> io::Result<()> {
|
|||||||
// TODO use this when finding .roc files by discovering them from the root module.
|
// TODO use this when finding .roc files by discovering them from the root module.
|
||||||
// let other_modules: &[Module<'_>] =
|
// let other_modules: &[Module<'_>] =
|
||||||
match read_header(&arena, &mut buf, path)?.header {
|
match read_header(&arena, &mut buf, path)?.header {
|
||||||
Header::Interface(_) => {
|
Header::Module(_) => {
|
||||||
todo!();
|
todo!();
|
||||||
// TODO report error
|
// TODO report error
|
||||||
}
|
}
|
||||||
|
@ -3621,7 +3621,7 @@ fn to_exposes_report<'a>(
|
|||||||
"I was expecting a type name, value name or function name next, like",
|
"I was expecting a type name, value name or function name next, like",
|
||||||
)]),
|
)]),
|
||||||
alloc
|
alloc
|
||||||
.parser_suggestion("exposes [Animal, default, tame]")
|
.parser_suggestion("[Animal, default, tame]")
|
||||||
.indent(4),
|
.indent(4),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -3646,7 +3646,7 @@ fn to_exposes_report<'a>(
|
|||||||
alloc.reflow(" keyword next, like"),
|
alloc.reflow(" keyword next, like"),
|
||||||
]),
|
]),
|
||||||
alloc
|
alloc
|
||||||
.parser_suggestion("exposes [Animal, default, tame]")
|
.parser_suggestion("[Animal, default, tame]")
|
||||||
.indent(4),
|
.indent(4),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
interface Community
|
module [
|
||||||
exposes [
|
|
||||||
Community,
|
Community,
|
||||||
empty,
|
empty,
|
||||||
addPerson,
|
addPerson,
|
||||||
addFriend,
|
addFriend,
|
||||||
Person,
|
Person,
|
||||||
walkFriendNames,
|
walkFriendNames,
|
||||||
]
|
]
|
||||||
imports []
|
|
||||||
|
|
||||||
## Datatype representing a community for demonstration purposes in inspect-gui.roc and inspect-logging.roc
|
## Datatype representing a community for demonstration purposes in inspect-gui.roc and inspect-logging.roc
|
||||||
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
interface GuiFormatter
|
module [
|
||||||
exposes [
|
|
||||||
GuiFormatter,
|
GuiFormatter,
|
||||||
toGui,
|
toGui,
|
||||||
]
|
]
|
||||||
imports []
|
|
||||||
|
|
||||||
## Creates GUI representations of Roc values, for use in inspect-gui.roc
|
## Creates GUI representations of Roc values, for use in inspect-gui.roc
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
interface Context
|
module [Context, Data, with, getChar, Option, pushStack, popStack, toStr, inWhileScope]
|
||||||
exposes [Context, Data, with, getChar, Option, pushStack, popStack, toStr, inWhileScope]
|
|
||||||
imports [pf.File, pf.Task.{ Task }, Variable.{ Variable }]
|
import pf.File
|
||||||
|
import pf.Task exposing [Task]
|
||||||
|
import Variable exposing [Variable]
|
||||||
|
|
||||||
Option a : [Some a, None]
|
Option a : [Some a, None]
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
interface Variable
|
module [Variable, fromUtf8, toIndex, totalCount, toStr]
|
||||||
exposes [Variable, fromUtf8, toIndex, totalCount, toStr]
|
|
||||||
imports []
|
|
||||||
|
|
||||||
# Variables in False can only be single letters. Thus, the valid variables are "a" to "z".
|
# Variables in False can only be single letters. Thus, the valid variables are "a" to "z".
|
||||||
# This opaque type deals with ensure we always have valid variables.
|
# This opaque type deals with ensure we always have valid variables.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
interface File
|
module [line, Handle, withOpen, chunk]
|
||||||
exposes [line, Handle, withOpen, chunk]
|
|
||||||
imports [pf.Effect, Task.{ Task }]
|
import pf.Effect
|
||||||
|
import Task exposing [Task]
|
||||||
|
|
||||||
Handle := U64
|
Handle := U64
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
interface Stdin
|
module [char]
|
||||||
exposes [char]
|
|
||||||
imports [pf.Effect, Task]
|
import pf.Effect
|
||||||
|
import Task
|
||||||
|
|
||||||
# line : Task.Task Str *
|
# line : Task.Task Str *
|
||||||
# line = Effect.after Effect.getLine Task.succeed # TODO FIXME Effect.getLine should suffice
|
# line = Effect.after Effect.getLine Task.succeed # TODO FIXME Effect.getLine should suffice
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
interface Stdout
|
module [line, raw]
|
||||||
exposes [line, raw]
|
|
||||||
imports [pf.Effect, Task.{ Task }]
|
import pf.Effect
|
||||||
|
import Task exposing [Task]
|
||||||
|
|
||||||
line : Str -> Task {} *
|
line : Str -> Task {} *
|
||||||
line = \str -> Effect.map (Effect.putLine str) (\_ -> Ok {})
|
line = \str -> Effect.map (Effect.putLine str) (\_ -> Ok {})
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
interface Task
|
module [Task, succeed, fail, await, map, onFail, attempt, fromResult, loop]
|
||||||
exposes [Task, succeed, fail, await, map, onFail, attempt, fromResult, loop]
|
|
||||||
imports [pf.Effect]
|
import pf.Effect
|
||||||
|
|
||||||
Task ok err : Effect.Effect (Result ok err)
|
Task ok err : Effect.Effect (Result ok err)
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
interface Program
|
module [Program]
|
||||||
exposes [Program]
|
|
||||||
imports []
|
|
||||||
|
|
||||||
Program model : {
|
Program model : {
|
||||||
init : {} -> model,
|
init : {} -> model,
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
interface Action
|
module [Action, none, update, map]
|
||||||
exposes [Action, none, update, map]
|
|
||||||
imports []
|
|
||||||
|
|
||||||
Action state : [None, Update state]
|
Action state : [None, Update state]
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
interface Elem
|
module [Elem, PressEvent, row, col, text, button, none, translate, list]
|
||||||
exposes [Elem, PressEvent, row, col, text, button, none, translate, list]
|
|
||||||
imports [Action.{ Action }]
|
import Action exposing [Action]
|
||||||
|
|
||||||
Elem state : [
|
Elem state : [
|
||||||
# PERFORMANCE NOTE:
|
# PERFORMANCE NOTE:
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
interface Game
|
module [Bounds, Elem, Event]
|
||||||
exposes [Bounds, Elem, Event]
|
|
||||||
imports []
|
|
||||||
|
|
||||||
Rgba : { r : F32, g : F32, b : F32, a : F32 }
|
Rgba : { r : F32, g : F32, b : F32, a : F32 }
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
interface Action
|
module [Action, none, update, map]
|
||||||
exposes [Action, none, update, map]
|
|
||||||
imports []
|
|
||||||
|
|
||||||
Action state : [None, Update state]
|
Action state : [None, Update state]
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
interface Elem
|
module [Elem, PressEvent, row, col, text, button, none, translate, list]
|
||||||
exposes [Elem, PressEvent, row, col, text, button, none, translate, list]
|
|
||||||
imports [Action.{ Action }]
|
import Action exposing [Action]
|
||||||
|
|
||||||
Elem state : [
|
Elem state : [
|
||||||
# PERFORMANCE NOTE:
|
# PERFORMANCE NOTE:
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
interface Html
|
module [
|
||||||
exposes [
|
|
||||||
Node,
|
Node,
|
||||||
Attribute,
|
Attribute,
|
||||||
render,
|
render,
|
||||||
@ -121,8 +120,9 @@ interface Html
|
|||||||
summary,
|
summary,
|
||||||
slot,
|
slot,
|
||||||
template,
|
template,
|
||||||
]
|
]
|
||||||
imports [Html.Attributes]
|
|
||||||
|
import Html.Attributes
|
||||||
|
|
||||||
Node : [
|
Node : [
|
||||||
Text Str,
|
Text Str,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
interface Html.Attributes
|
module [
|
||||||
exposes [
|
|
||||||
Attribute,
|
Attribute,
|
||||||
attribute,
|
attribute,
|
||||||
accept,
|
accept,
|
||||||
@ -137,8 +136,7 @@ interface Html.Attributes
|
|||||||
value,
|
value,
|
||||||
width,
|
width,
|
||||||
wrap,
|
wrap,
|
||||||
]
|
]
|
||||||
imports []
|
|
||||||
|
|
||||||
Attribute : [Attribute Str Str]
|
Attribute : [Attribute Str Str]
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
interface ExampleApp
|
module [exampleApp, State]
|
||||||
exposes [exampleApp, State]
|
|
||||||
imports [
|
import pf.Html exposing [App, Html, html, head, body, div, text, h1]
|
||||||
pf.Html.{ App, Html, html, head, body, div, text, h1 },
|
|
||||||
]
|
|
||||||
|
|
||||||
State : {
|
State : {
|
||||||
answer : U32,
|
answer : U32,
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
interface Action
|
module [Action, none, update, map]
|
||||||
exposes [Action, none, update, map]
|
|
||||||
imports []
|
|
||||||
|
|
||||||
Action state : [None, Update state]
|
Action state : [None, Update state]
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
interface Html
|
module [
|
||||||
exposes [
|
|
||||||
App,
|
App,
|
||||||
Html,
|
Html,
|
||||||
Attribute,
|
Attribute,
|
||||||
@ -122,8 +121,10 @@ interface Html
|
|||||||
summary,
|
summary,
|
||||||
slot,
|
slot,
|
||||||
template,
|
template,
|
||||||
]
|
]
|
||||||
imports [Html.Internal.Shared, Html.Internal.Server]
|
|
||||||
|
import Html.Internal.Shared
|
||||||
|
import Html.Internal.Server
|
||||||
|
|
||||||
App state initData : Html.Internal.Shared.App state initData
|
App state initData : Html.Internal.Shared.App state initData
|
||||||
Html state : Html.Internal.Shared.Html state
|
Html state : Html.Internal.Shared.Html state
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
interface Html.Attributes
|
module [
|
||||||
exposes [
|
|
||||||
attribute,
|
attribute,
|
||||||
accept,
|
accept,
|
||||||
acceptCharset,
|
acceptCharset,
|
||||||
@ -133,8 +132,9 @@ interface Html.Attributes
|
|||||||
value,
|
value,
|
||||||
width,
|
width,
|
||||||
wrap,
|
wrap,
|
||||||
]
|
]
|
||||||
imports [Html.Internal.Shared.{ Attribute }]
|
|
||||||
|
import Html.Internal.Shared exposing [Attribute]
|
||||||
|
|
||||||
attribute : Str -> (Str -> Attribute state)
|
attribute : Str -> (Str -> Attribute state)
|
||||||
attribute = \attrType ->
|
attribute = \attrType ->
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
interface Html.Event
|
module [
|
||||||
exposes [
|
|
||||||
Handler,
|
Handler,
|
||||||
CyclicStructureAccessor,
|
CyclicStructureAccessor,
|
||||||
on,
|
on,
|
||||||
@ -17,11 +16,10 @@ interface Html.Event
|
|||||||
onFocus,
|
onFocus,
|
||||||
onInput,
|
onInput,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
]
|
]
|
||||||
imports [
|
|
||||||
Action.{ Action },
|
import Action exposing [Action]
|
||||||
Html.Internal.Shared.{ Attribute },
|
import Html.Internal.Shared exposing [Attribute]
|
||||||
]
|
|
||||||
|
|
||||||
Handler state : Html.Internal.Shared.Handler state
|
Handler state : Html.Internal.Shared.Handler state
|
||||||
CyclicStructureAccessor : Html.Internal.Shared.CyclicStructureAccessor
|
CyclicStructureAccessor : Html.Internal.Shared.CyclicStructureAccessor
|
||||||
|
@ -1,29 +1,27 @@
|
|||||||
interface Html.Internal.Client
|
module [
|
||||||
exposes [
|
|
||||||
PlatformState,
|
PlatformState,
|
||||||
initClientApp,
|
initClientApp,
|
||||||
dispatchEvent,
|
dispatchEvent,
|
||||||
]
|
]
|
||||||
imports [
|
|
||||||
Effect.{
|
import Effect exposing [
|
||||||
Effect,
|
Effect,
|
||||||
NodeId,
|
NodeId,
|
||||||
HandlerId,
|
HandlerId,
|
||||||
TagName,
|
TagName,
|
||||||
AttrType,
|
AttrType,
|
||||||
EventType,
|
EventType,
|
||||||
},
|
]
|
||||||
Html.Internal.Shared.{
|
import Html.Internal.Shared exposing [
|
||||||
App,
|
App,
|
||||||
Html,
|
Html,
|
||||||
Attribute,
|
Attribute,
|
||||||
CyclicStructureAccessor,
|
CyclicStructureAccessor,
|
||||||
Handler,
|
Handler,
|
||||||
translateStatic,
|
translateStatic,
|
||||||
},
|
]
|
||||||
TotallyNotJson,
|
import TotallyNotJson
|
||||||
Action,
|
import Action
|
||||||
]
|
|
||||||
|
|
||||||
PlatformState state initData : {
|
PlatformState state initData : {
|
||||||
app : App state initData,
|
app : App state initData,
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
interface Html.Internal.Server
|
module [
|
||||||
exposes [
|
|
||||||
appendRenderedStatic,
|
appendRenderedStatic,
|
||||||
initServerApp,
|
initServerApp,
|
||||||
]
|
]
|
||||||
imports [
|
|
||||||
Html.Internal.Shared.{ Html, Attribute, App, translateStatic, text, element },
|
import Html.Internal.Shared exposing [Html, Attribute, App, translateStatic, text, element]
|
||||||
TotallyNotJson,
|
import TotallyNotJson
|
||||||
]
|
|
||||||
|
|
||||||
# -------------------------------
|
# -------------------------------
|
||||||
# STATIC HTML
|
# STATIC HTML
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
interface Html.Internal.Shared
|
module [
|
||||||
exposes [
|
|
||||||
App,
|
App,
|
||||||
Html,
|
Html,
|
||||||
Attribute,
|
Attribute,
|
||||||
@ -12,10 +11,9 @@ interface Html.Internal.Shared
|
|||||||
translate,
|
translate,
|
||||||
translateStatic,
|
translateStatic,
|
||||||
nodeSize,
|
nodeSize,
|
||||||
]
|
]
|
||||||
imports [
|
|
||||||
Action.{ Action },
|
import Action exposing [Action]
|
||||||
]
|
|
||||||
|
|
||||||
App state initData : {
|
App state initData : {
|
||||||
init : DecodingResult initData -> state,
|
init : DecodingResult initData -> state,
|
||||||
|
Loading…
Reference in New Issue
Block a user