mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 11:52:19 +00:00
Merge pull request #6683 from roc-lang/new-module-headers
New `app`, `module`, and `package` headers
This commit is contained in:
commit
b53017a733
180 changed files with 2617 additions and 2710 deletions
|
@ -1,6 +1,4 @@
|
|||
interface Bool
|
||||
exposes [Bool, Eq, true, false, and, or, not, isEq, isNotEq]
|
||||
imports []
|
||||
module [Bool, Eq, true, false, and, or, not, isEq, isNotEq]
|
||||
|
||||
## 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).
|
||||
## - To improve performance in rare cases.
|
||||
##
|
||||
interface Box
|
||||
exposes [box, unbox]
|
||||
imports []
|
||||
module [box, unbox]
|
||||
|
||||
## 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
|
||||
|
|
|
@ -1,36 +1,34 @@
|
|||
interface Decode
|
||||
exposes [
|
||||
DecodeError,
|
||||
DecodeResult,
|
||||
Decoder,
|
||||
Decoding,
|
||||
DecoderFormatting,
|
||||
decoder,
|
||||
u8,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
u128,
|
||||
i8,
|
||||
i16,
|
||||
i32,
|
||||
i64,
|
||||
i128,
|
||||
f32,
|
||||
f64,
|
||||
dec,
|
||||
bool,
|
||||
string,
|
||||
list,
|
||||
record,
|
||||
tuple,
|
||||
custom,
|
||||
decodeWith,
|
||||
fromBytesPartial,
|
||||
fromBytes,
|
||||
mapResult,
|
||||
]
|
||||
imports []
|
||||
module [
|
||||
DecodeError,
|
||||
DecodeResult,
|
||||
Decoder,
|
||||
Decoding,
|
||||
DecoderFormatting,
|
||||
decoder,
|
||||
u8,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
u128,
|
||||
i8,
|
||||
i16,
|
||||
i32,
|
||||
i64,
|
||||
i128,
|
||||
f32,
|
||||
f64,
|
||||
dec,
|
||||
bool,
|
||||
string,
|
||||
list,
|
||||
record,
|
||||
tuple,
|
||||
custom,
|
||||
decodeWith,
|
||||
fromBytesPartial,
|
||||
fromBytes,
|
||||
mapResult,
|
||||
]
|
||||
|
||||
import List
|
||||
import Result exposing [Result]
|
||||
|
|
|
@ -1,35 +1,33 @@
|
|||
interface Dict
|
||||
exposes [
|
||||
Dict,
|
||||
empty,
|
||||
withCapacity,
|
||||
single,
|
||||
clear,
|
||||
capacity,
|
||||
reserve,
|
||||
releaseExcessCapacity,
|
||||
len,
|
||||
isEmpty,
|
||||
get,
|
||||
contains,
|
||||
insert,
|
||||
remove,
|
||||
update,
|
||||
walk,
|
||||
walkUntil,
|
||||
keepIf,
|
||||
dropIf,
|
||||
toList,
|
||||
fromList,
|
||||
keys,
|
||||
values,
|
||||
insertAll,
|
||||
keepShared,
|
||||
removeAll,
|
||||
map,
|
||||
joinMap,
|
||||
]
|
||||
imports []
|
||||
module [
|
||||
Dict,
|
||||
empty,
|
||||
withCapacity,
|
||||
single,
|
||||
clear,
|
||||
capacity,
|
||||
reserve,
|
||||
releaseExcessCapacity,
|
||||
len,
|
||||
isEmpty,
|
||||
get,
|
||||
contains,
|
||||
insert,
|
||||
remove,
|
||||
update,
|
||||
walk,
|
||||
walkUntil,
|
||||
keepIf,
|
||||
dropIf,
|
||||
toList,
|
||||
fromList,
|
||||
keys,
|
||||
values,
|
||||
insertAll,
|
||||
keepShared,
|
||||
removeAll,
|
||||
map,
|
||||
joinMap,
|
||||
]
|
||||
|
||||
import Bool exposing [Bool, Eq]
|
||||
import Result exposing [Result]
|
||||
|
|
|
@ -1,34 +1,32 @@
|
|||
interface Encode
|
||||
exposes [
|
||||
Encoder,
|
||||
Encoding,
|
||||
toEncoder,
|
||||
EncoderFormatting,
|
||||
u8,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
u128,
|
||||
i8,
|
||||
i16,
|
||||
i32,
|
||||
i64,
|
||||
i128,
|
||||
f32,
|
||||
f64,
|
||||
dec,
|
||||
bool,
|
||||
string,
|
||||
list,
|
||||
record,
|
||||
tag,
|
||||
tuple,
|
||||
custom,
|
||||
appendWith,
|
||||
append,
|
||||
toBytes,
|
||||
]
|
||||
imports []
|
||||
module [
|
||||
Encoder,
|
||||
Encoding,
|
||||
toEncoder,
|
||||
EncoderFormatting,
|
||||
u8,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
u128,
|
||||
i8,
|
||||
i16,
|
||||
i32,
|
||||
i64,
|
||||
i128,
|
||||
f32,
|
||||
f64,
|
||||
dec,
|
||||
bool,
|
||||
string,
|
||||
list,
|
||||
record,
|
||||
tag,
|
||||
tuple,
|
||||
custom,
|
||||
appendWith,
|
||||
append,
|
||||
toBytes,
|
||||
]
|
||||
|
||||
import Num exposing [
|
||||
U8,
|
||||
|
|
|
@ -1,26 +1,25 @@
|
|||
interface Hash
|
||||
exposes [
|
||||
Hash,
|
||||
Hasher,
|
||||
hash,
|
||||
addBytes,
|
||||
addU8,
|
||||
addU16,
|
||||
addU32,
|
||||
addU64,
|
||||
addU128,
|
||||
hashBool,
|
||||
hashI8,
|
||||
hashI16,
|
||||
hashI32,
|
||||
hashI64,
|
||||
hashI128,
|
||||
hashDec,
|
||||
complete,
|
||||
hashStrBytes,
|
||||
hashList,
|
||||
hashUnordered,
|
||||
] imports []
|
||||
module [
|
||||
Hash,
|
||||
Hasher,
|
||||
hash,
|
||||
addBytes,
|
||||
addU8,
|
||||
addU16,
|
||||
addU32,
|
||||
addU64,
|
||||
addU128,
|
||||
hashBool,
|
||||
hashI8,
|
||||
hashI16,
|
||||
hashI32,
|
||||
hashI64,
|
||||
hashI128,
|
||||
hashDec,
|
||||
complete,
|
||||
hashStrBytes,
|
||||
hashList,
|
||||
hashUnordered,
|
||||
]
|
||||
|
||||
import Bool exposing [Bool]
|
||||
import List
|
||||
|
|
|
@ -1,41 +1,39 @@
|
|||
interface Inspect
|
||||
exposes [
|
||||
Inspect,
|
||||
Inspector,
|
||||
InspectFormatter,
|
||||
ElemWalker,
|
||||
KeyValWalker,
|
||||
inspect,
|
||||
init,
|
||||
list,
|
||||
set,
|
||||
dict,
|
||||
tag,
|
||||
tuple,
|
||||
record,
|
||||
bool,
|
||||
str,
|
||||
function,
|
||||
opaque,
|
||||
u8,
|
||||
i8,
|
||||
u16,
|
||||
i16,
|
||||
u32,
|
||||
i32,
|
||||
u64,
|
||||
i64,
|
||||
u128,
|
||||
i128,
|
||||
f32,
|
||||
f64,
|
||||
dec,
|
||||
custom,
|
||||
apply,
|
||||
toInspector,
|
||||
toStr,
|
||||
]
|
||||
imports []
|
||||
module [
|
||||
Inspect,
|
||||
Inspector,
|
||||
InspectFormatter,
|
||||
ElemWalker,
|
||||
KeyValWalker,
|
||||
inspect,
|
||||
init,
|
||||
list,
|
||||
set,
|
||||
dict,
|
||||
tag,
|
||||
tuple,
|
||||
record,
|
||||
bool,
|
||||
str,
|
||||
function,
|
||||
opaque,
|
||||
u8,
|
||||
i8,
|
||||
u16,
|
||||
i16,
|
||||
u32,
|
||||
i32,
|
||||
u64,
|
||||
i64,
|
||||
u128,
|
||||
i128,
|
||||
f32,
|
||||
f64,
|
||||
dec,
|
||||
custom,
|
||||
apply,
|
||||
toInspector,
|
||||
toStr,
|
||||
]
|
||||
|
||||
import Bool exposing [Bool]
|
||||
import Num exposing [U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, F32, F64, Dec]
|
||||
|
|
|
@ -1,77 +1,75 @@
|
|||
interface List
|
||||
exposes [
|
||||
isEmpty,
|
||||
get,
|
||||
set,
|
||||
replace,
|
||||
update,
|
||||
append,
|
||||
appendIfOk,
|
||||
prepend,
|
||||
prependIfOk,
|
||||
map,
|
||||
len,
|
||||
withCapacity,
|
||||
walkBackwards,
|
||||
concat,
|
||||
first,
|
||||
single,
|
||||
repeat,
|
||||
reverse,
|
||||
join,
|
||||
keepIf,
|
||||
contains,
|
||||
sum,
|
||||
walk,
|
||||
last,
|
||||
keepOks,
|
||||
keepErrs,
|
||||
mapWithIndex,
|
||||
map2,
|
||||
map3,
|
||||
product,
|
||||
walkWithIndex,
|
||||
walkUntil,
|
||||
walkWithIndexUntil,
|
||||
walkFrom,
|
||||
walkFromUntil,
|
||||
range,
|
||||
sortWith,
|
||||
swap,
|
||||
dropAt,
|
||||
min,
|
||||
max,
|
||||
map4,
|
||||
mapTry,
|
||||
walkTry,
|
||||
joinMap,
|
||||
any,
|
||||
takeFirst,
|
||||
takeLast,
|
||||
dropFirst,
|
||||
dropLast,
|
||||
findFirst,
|
||||
findLast,
|
||||
findFirstIndex,
|
||||
findLastIndex,
|
||||
sublist,
|
||||
intersperse,
|
||||
split,
|
||||
splitFirst,
|
||||
splitLast,
|
||||
startsWith,
|
||||
endsWith,
|
||||
all,
|
||||
dropIf,
|
||||
sortAsc,
|
||||
sortDesc,
|
||||
reserve,
|
||||
releaseExcessCapacity,
|
||||
walkBackwardsUntil,
|
||||
countIf,
|
||||
chunksOf,
|
||||
]
|
||||
imports []
|
||||
module [
|
||||
isEmpty,
|
||||
get,
|
||||
set,
|
||||
replace,
|
||||
update,
|
||||
append,
|
||||
appendIfOk,
|
||||
prepend,
|
||||
prependIfOk,
|
||||
map,
|
||||
len,
|
||||
withCapacity,
|
||||
walkBackwards,
|
||||
concat,
|
||||
first,
|
||||
single,
|
||||
repeat,
|
||||
reverse,
|
||||
join,
|
||||
keepIf,
|
||||
contains,
|
||||
sum,
|
||||
walk,
|
||||
last,
|
||||
keepOks,
|
||||
keepErrs,
|
||||
mapWithIndex,
|
||||
map2,
|
||||
map3,
|
||||
product,
|
||||
walkWithIndex,
|
||||
walkUntil,
|
||||
walkWithIndexUntil,
|
||||
walkFrom,
|
||||
walkFromUntil,
|
||||
range,
|
||||
sortWith,
|
||||
swap,
|
||||
dropAt,
|
||||
min,
|
||||
max,
|
||||
map4,
|
||||
mapTry,
|
||||
walkTry,
|
||||
joinMap,
|
||||
any,
|
||||
takeFirst,
|
||||
takeLast,
|
||||
dropFirst,
|
||||
dropLast,
|
||||
findFirst,
|
||||
findLast,
|
||||
findFirstIndex,
|
||||
findLastIndex,
|
||||
sublist,
|
||||
intersperse,
|
||||
split,
|
||||
splitFirst,
|
||||
splitLast,
|
||||
startsWith,
|
||||
endsWith,
|
||||
all,
|
||||
dropIf,
|
||||
sortAsc,
|
||||
sortDesc,
|
||||
reserve,
|
||||
releaseExcessCapacity,
|
||||
walkBackwardsUntil,
|
||||
countIf,
|
||||
chunksOf,
|
||||
]
|
||||
|
||||
import Bool exposing [Bool, Eq]
|
||||
import Result exposing [Result]
|
||||
|
|
|
@ -1,163 +1,161 @@
|
|||
interface Num
|
||||
exposes [
|
||||
Num,
|
||||
Int,
|
||||
Frac,
|
||||
Integer,
|
||||
FloatingPoint,
|
||||
I128,
|
||||
I64,
|
||||
I32,
|
||||
I16,
|
||||
I8,
|
||||
U128,
|
||||
U64,
|
||||
U32,
|
||||
U16,
|
||||
U8,
|
||||
Signed128,
|
||||
Signed64,
|
||||
Signed32,
|
||||
Signed16,
|
||||
Signed8,
|
||||
Unsigned128,
|
||||
Unsigned64,
|
||||
Unsigned32,
|
||||
Unsigned16,
|
||||
Unsigned8,
|
||||
Dec,
|
||||
F64,
|
||||
F32,
|
||||
Decimal,
|
||||
Binary32,
|
||||
Binary64,
|
||||
e,
|
||||
pi,
|
||||
tau,
|
||||
abs,
|
||||
absDiff,
|
||||
neg,
|
||||
add,
|
||||
sub,
|
||||
mul,
|
||||
min,
|
||||
max,
|
||||
isLt,
|
||||
isLte,
|
||||
isGt,
|
||||
isGte,
|
||||
isApproxEq,
|
||||
sin,
|
||||
cos,
|
||||
tan,
|
||||
atan,
|
||||
acos,
|
||||
asin,
|
||||
isZero,
|
||||
isEven,
|
||||
isOdd,
|
||||
toFrac,
|
||||
isPositive,
|
||||
isNegative,
|
||||
isNaN,
|
||||
isInfinite,
|
||||
isFinite,
|
||||
rem,
|
||||
remChecked,
|
||||
div,
|
||||
divChecked,
|
||||
sqrt,
|
||||
sqrtChecked,
|
||||
log,
|
||||
logChecked,
|
||||
round,
|
||||
ceiling,
|
||||
floor,
|
||||
compare,
|
||||
pow,
|
||||
powInt,
|
||||
countLeadingZeroBits,
|
||||
countTrailingZeroBits,
|
||||
countOneBits,
|
||||
addWrap,
|
||||
addChecked,
|
||||
addSaturated,
|
||||
bitwiseAnd,
|
||||
bitwiseXor,
|
||||
bitwiseOr,
|
||||
bitwiseNot,
|
||||
shiftLeftBy,
|
||||
shiftRightBy,
|
||||
shiftRightZfBy,
|
||||
subWrap,
|
||||
subChecked,
|
||||
subSaturated,
|
||||
mulWrap,
|
||||
mulSaturated,
|
||||
mulChecked,
|
||||
intCast,
|
||||
divCeil,
|
||||
divCeilChecked,
|
||||
divTrunc,
|
||||
divTruncChecked,
|
||||
toStr,
|
||||
isMultipleOf,
|
||||
minI8,
|
||||
maxI8,
|
||||
minU8,
|
||||
maxU8,
|
||||
minI16,
|
||||
maxI16,
|
||||
minU16,
|
||||
maxU16,
|
||||
minI32,
|
||||
maxI32,
|
||||
minU32,
|
||||
maxU32,
|
||||
minI64,
|
||||
maxI64,
|
||||
minU64,
|
||||
maxU64,
|
||||
minI128,
|
||||
maxI128,
|
||||
minU128,
|
||||
maxU128,
|
||||
minF32,
|
||||
maxF32,
|
||||
minF64,
|
||||
maxF64,
|
||||
toI8,
|
||||
toI8Checked,
|
||||
toI16,
|
||||
toI16Checked,
|
||||
toI32,
|
||||
toI32Checked,
|
||||
toI64,
|
||||
toI64Checked,
|
||||
toI128,
|
||||
toI128Checked,
|
||||
toU8,
|
||||
toU8Checked,
|
||||
toU16,
|
||||
toU16Checked,
|
||||
toU32,
|
||||
toU32Checked,
|
||||
toU64,
|
||||
toU64Checked,
|
||||
toU128,
|
||||
toU128Checked,
|
||||
toF32,
|
||||
toF32Checked,
|
||||
toF64,
|
||||
toF64Checked,
|
||||
withoutDecimalPoint,
|
||||
withDecimalPoint,
|
||||
f32ToParts,
|
||||
f64ToParts,
|
||||
f32FromParts,
|
||||
f64FromParts,
|
||||
]
|
||||
imports []
|
||||
module [
|
||||
Num,
|
||||
Int,
|
||||
Frac,
|
||||
Integer,
|
||||
FloatingPoint,
|
||||
I128,
|
||||
I64,
|
||||
I32,
|
||||
I16,
|
||||
I8,
|
||||
U128,
|
||||
U64,
|
||||
U32,
|
||||
U16,
|
||||
U8,
|
||||
Signed128,
|
||||
Signed64,
|
||||
Signed32,
|
||||
Signed16,
|
||||
Signed8,
|
||||
Unsigned128,
|
||||
Unsigned64,
|
||||
Unsigned32,
|
||||
Unsigned16,
|
||||
Unsigned8,
|
||||
Dec,
|
||||
F64,
|
||||
F32,
|
||||
Decimal,
|
||||
Binary32,
|
||||
Binary64,
|
||||
e,
|
||||
pi,
|
||||
tau,
|
||||
abs,
|
||||
absDiff,
|
||||
neg,
|
||||
add,
|
||||
sub,
|
||||
mul,
|
||||
min,
|
||||
max,
|
||||
isLt,
|
||||
isLte,
|
||||
isGt,
|
||||
isGte,
|
||||
isApproxEq,
|
||||
sin,
|
||||
cos,
|
||||
tan,
|
||||
atan,
|
||||
acos,
|
||||
asin,
|
||||
isZero,
|
||||
isEven,
|
||||
isOdd,
|
||||
toFrac,
|
||||
isPositive,
|
||||
isNegative,
|
||||
isNaN,
|
||||
isInfinite,
|
||||
isFinite,
|
||||
rem,
|
||||
remChecked,
|
||||
div,
|
||||
divChecked,
|
||||
sqrt,
|
||||
sqrtChecked,
|
||||
log,
|
||||
logChecked,
|
||||
round,
|
||||
ceiling,
|
||||
floor,
|
||||
compare,
|
||||
pow,
|
||||
powInt,
|
||||
countLeadingZeroBits,
|
||||
countTrailingZeroBits,
|
||||
countOneBits,
|
||||
addWrap,
|
||||
addChecked,
|
||||
addSaturated,
|
||||
bitwiseAnd,
|
||||
bitwiseXor,
|
||||
bitwiseOr,
|
||||
bitwiseNot,
|
||||
shiftLeftBy,
|
||||
shiftRightBy,
|
||||
shiftRightZfBy,
|
||||
subWrap,
|
||||
subChecked,
|
||||
subSaturated,
|
||||
mulWrap,
|
||||
mulSaturated,
|
||||
mulChecked,
|
||||
intCast,
|
||||
divCeil,
|
||||
divCeilChecked,
|
||||
divTrunc,
|
||||
divTruncChecked,
|
||||
toStr,
|
||||
isMultipleOf,
|
||||
minI8,
|
||||
maxI8,
|
||||
minU8,
|
||||
maxU8,
|
||||
minI16,
|
||||
maxI16,
|
||||
minU16,
|
||||
maxU16,
|
||||
minI32,
|
||||
maxI32,
|
||||
minU32,
|
||||
maxU32,
|
||||
minI64,
|
||||
maxI64,
|
||||
minU64,
|
||||
maxU64,
|
||||
minI128,
|
||||
maxI128,
|
||||
minU128,
|
||||
maxU128,
|
||||
minF32,
|
||||
maxF32,
|
||||
minF64,
|
||||
maxF64,
|
||||
toI8,
|
||||
toI8Checked,
|
||||
toI16,
|
||||
toI16Checked,
|
||||
toI32,
|
||||
toI32Checked,
|
||||
toI64,
|
||||
toI64Checked,
|
||||
toI128,
|
||||
toI128Checked,
|
||||
toU8,
|
||||
toU8Checked,
|
||||
toU16,
|
||||
toU16Checked,
|
||||
toU32,
|
||||
toU32Checked,
|
||||
toU64,
|
||||
toU64Checked,
|
||||
toU128,
|
||||
toU128Checked,
|
||||
toF32,
|
||||
toF32Checked,
|
||||
toF64,
|
||||
toF64Checked,
|
||||
withoutDecimalPoint,
|
||||
withDecimalPoint,
|
||||
f32ToParts,
|
||||
f64ToParts,
|
||||
f32FromParts,
|
||||
f64FromParts,
|
||||
]
|
||||
|
||||
import Bool exposing [Bool]
|
||||
import Result exposing [Result]
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
interface Result
|
||||
exposes [Result, isOk, isErr, map, mapErr, try, onErr, withDefault]
|
||||
imports []
|
||||
module [Result, isOk, isErr, map, mapErr, try, onErr, withDefault]
|
||||
|
||||
import Bool exposing [Bool]
|
||||
|
||||
|
|
|
@ -1,30 +1,28 @@
|
|||
interface Set
|
||||
exposes [
|
||||
Set,
|
||||
empty,
|
||||
withCapacity,
|
||||
reserve,
|
||||
releaseExcessCapacity,
|
||||
single,
|
||||
walk,
|
||||
walkUntil,
|
||||
keepIf,
|
||||
dropIf,
|
||||
insert,
|
||||
len,
|
||||
isEmpty,
|
||||
capacity,
|
||||
remove,
|
||||
contains,
|
||||
toList,
|
||||
fromList,
|
||||
union,
|
||||
intersection,
|
||||
difference,
|
||||
map,
|
||||
joinMap,
|
||||
]
|
||||
imports []
|
||||
module [
|
||||
Set,
|
||||
empty,
|
||||
withCapacity,
|
||||
reserve,
|
||||
releaseExcessCapacity,
|
||||
single,
|
||||
walk,
|
||||
walkUntil,
|
||||
keepIf,
|
||||
dropIf,
|
||||
insert,
|
||||
len,
|
||||
isEmpty,
|
||||
capacity,
|
||||
remove,
|
||||
contains,
|
||||
toList,
|
||||
fromList,
|
||||
union,
|
||||
intersection,
|
||||
difference,
|
||||
map,
|
||||
joinMap,
|
||||
]
|
||||
|
||||
import List
|
||||
import Bool exposing [Bool, Eq]
|
||||
|
|
|
@ -326,50 +326,48 @@
|
|||
## 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.
|
||||
interface Str
|
||||
exposes [
|
||||
Utf8Problem,
|
||||
Utf8ByteProblem,
|
||||
concat,
|
||||
isEmpty,
|
||||
joinWith,
|
||||
split,
|
||||
repeat,
|
||||
countUtf8Bytes,
|
||||
toUtf8,
|
||||
fromUtf8,
|
||||
startsWith,
|
||||
endsWith,
|
||||
trim,
|
||||
trimStart,
|
||||
trimEnd,
|
||||
toDec,
|
||||
toF64,
|
||||
toF32,
|
||||
toU128,
|
||||
toI128,
|
||||
toU64,
|
||||
toI64,
|
||||
toU32,
|
||||
toI32,
|
||||
toU16,
|
||||
toI16,
|
||||
toU8,
|
||||
toI8,
|
||||
replaceEach,
|
||||
replaceFirst,
|
||||
replaceLast,
|
||||
splitFirst,
|
||||
splitLast,
|
||||
walkUtf8,
|
||||
walkUtf8WithIndex,
|
||||
reserve,
|
||||
releaseExcessCapacity,
|
||||
withCapacity,
|
||||
withPrefix,
|
||||
contains,
|
||||
]
|
||||
imports []
|
||||
module [
|
||||
Utf8Problem,
|
||||
Utf8ByteProblem,
|
||||
concat,
|
||||
isEmpty,
|
||||
joinWith,
|
||||
split,
|
||||
repeat,
|
||||
countUtf8Bytes,
|
||||
toUtf8,
|
||||
fromUtf8,
|
||||
startsWith,
|
||||
endsWith,
|
||||
trim,
|
||||
trimStart,
|
||||
trimEnd,
|
||||
toDec,
|
||||
toF64,
|
||||
toF32,
|
||||
toU128,
|
||||
toI128,
|
||||
toU64,
|
||||
toI64,
|
||||
toU32,
|
||||
toI32,
|
||||
toU16,
|
||||
toI16,
|
||||
toU8,
|
||||
toI8,
|
||||
replaceEach,
|
||||
replaceFirst,
|
||||
replaceLast,
|
||||
splitFirst,
|
||||
splitLast,
|
||||
walkUtf8,
|
||||
walkUtf8WithIndex,
|
||||
reserve,
|
||||
releaseExcessCapacity,
|
||||
withCapacity,
|
||||
withPrefix,
|
||||
contains,
|
||||
]
|
||||
|
||||
import Bool exposing [Bool]
|
||||
import Result exposing [Result]
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
## THIS MODULE IS DEPRECATED AND CURRENTLY IN THE PROCESS OF BEING REMOVED
|
||||
## FROM STD LIBRARY
|
||||
interface TotallyNotJson
|
||||
exposes [
|
||||
Json,
|
||||
json,
|
||||
jsonWithOptions,
|
||||
]
|
||||
imports []
|
||||
module [
|
||||
Json,
|
||||
json,
|
||||
jsonWithOptions,
|
||||
]
|
||||
|
||||
import List
|
||||
import Str
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
package "builtins"
|
||||
exposes [Str, Num, Bool, Result, List, Dict, Set, Decode, Encode, Hash, Box, TotallyNotJson, Inspect]
|
||||
packages {}
|
||||
package [
|
||||
Str,
|
||||
Num,
|
||||
Bool,
|
||||
Result,
|
||||
List,
|
||||
Dict,
|
||||
Set,
|
||||
Decode,
|
||||
Encode,
|
||||
Hash,
|
||||
Box,
|
||||
TotallyNotJson,
|
||||
Inspect,
|
||||
] {}
|
||||
|
|
|
@ -506,7 +506,7 @@ fn canonicalize_claimed_ability_impl<'a>(
|
|||
// OPTION-1: The implementation identifier is the only identifier of that name in the
|
||||
// scope. For example,
|
||||
//
|
||||
// interface F imports [] exposes []
|
||||
// module []
|
||||
//
|
||||
// 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,
|
||||
// which has also been explicitly imported. For example,
|
||||
//
|
||||
// interface F imports [Encoding.{ toEncoder }] exposes []
|
||||
// module []
|
||||
//
|
||||
// import Encoding exposing [toEncoder]
|
||||
//
|
||||
// Hello := {} implements [Encoding.{ toEncoder }]
|
||||
//
|
||||
|
|
|
@ -5,12 +5,13 @@ use crate::spaces::RemoveSpaces;
|
|||
use crate::spaces::{fmt_comments_only, fmt_default_spaces, fmt_spaces, NewlineAt, INDENT};
|
||||
use crate::Buf;
|
||||
use bumpalo::Bump;
|
||||
use roc_parse::ast::{Collection, Header, Module, Spaced, Spaces};
|
||||
use roc_parse::ast::{Collection, CommentOrNewline, Header, Module, Spaced, Spaces};
|
||||
use roc_parse::header::{
|
||||
AppHeader, ExposedName, ExposesKeyword, GeneratesKeyword, HostedHeader, ImportsEntry,
|
||||
ImportsKeyword, InterfaceHeader, Keyword, KeywordItem, ModuleName, PackageEntry, PackageHeader,
|
||||
PackageKeyword, PackageName, PackagesKeyword, PlatformHeader, PlatformRequires,
|
||||
ProvidesKeyword, ProvidesTo, RequiresKeyword, To, ToKeyword, TypedIdent, WithKeyword,
|
||||
ImportsKeyword, Keyword, KeywordItem, ModuleHeader, ModuleName, PackageEntry, PackageHeader,
|
||||
PackageKeyword, PackageName, PackagesKeyword, PlatformHeader, PlatformKeyword,
|
||||
PlatformRequires, ProvidesKeyword, ProvidesTo, RequiresKeyword, To, ToKeyword, TypedIdent,
|
||||
WithKeyword,
|
||||
};
|
||||
use roc_parse::ident::UppercaseIdent;
|
||||
use roc_region::all::Loc;
|
||||
|
@ -18,8 +19,8 @@ use roc_region::all::Loc;
|
|||
pub fn fmt_module<'a>(buf: &mut Buf<'_>, module: &'a Module<'a>) {
|
||||
fmt_comments_only(buf, module.comments.iter(), NewlineAt::Bottom, 0);
|
||||
match &module.header {
|
||||
Header::Interface(header) => {
|
||||
fmt_interface_header(buf, header);
|
||||
Header::Module(header) => {
|
||||
fmt_module_header(buf, header);
|
||||
}
|
||||
Header::App(header) => {
|
||||
fmt_app_header(buf, header);
|
||||
|
@ -75,6 +76,7 @@ keywords! {
|
|||
RequiresKeyword,
|
||||
ProvidesKeyword,
|
||||
ToKeyword,
|
||||
PlatformKeyword,
|
||||
}
|
||||
|
||||
impl<V: Formattable> Formattable for Option<V> {
|
||||
|
@ -171,20 +173,12 @@ 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.push_str("interface");
|
||||
let indent = INDENT;
|
||||
fmt_default_spaces(buf, header.before_name, indent);
|
||||
buf.push_str("module");
|
||||
|
||||
// module name
|
||||
buf.indent(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);
|
||||
let indent = fmt_spaces_with_outdent(buf, header.before_exposes, INDENT);
|
||||
fmt_exposes(buf, header.exposes, indent);
|
||||
}
|
||||
|
||||
pub fn fmt_hosted_header<'a>(buf: &mut Buf, header: &'a HostedHeader<'a>) {
|
||||
|
@ -207,34 +201,33 @@ pub fn fmt_hosted_header<'a>(buf: &mut Buf, header: &'a HostedHeader<'a>) {
|
|||
pub fn fmt_app_header<'a>(buf: &mut Buf, header: &'a AppHeader<'a>) {
|
||||
buf.indent(0);
|
||||
buf.push_str("app");
|
||||
let indent = INDENT;
|
||||
fmt_default_spaces(buf, header.before_name, indent);
|
||||
|
||||
fmt_str_literal(buf, header.name.value, indent);
|
||||
let indent = fmt_spaces_with_outdent(buf, header.before_provides, INDENT);
|
||||
fmt_exposes(buf, header.provides, indent);
|
||||
|
||||
if let Some(packages) = &header.packages {
|
||||
packages.keyword.format(buf, indent);
|
||||
fmt_packages(buf, packages.item, indent);
|
||||
let indent = fmt_spaces_with_outdent(buf, header.before_packages, INDENT);
|
||||
fmt_packages(buf, header.packages.value, indent);
|
||||
}
|
||||
|
||||
pub fn fmt_spaces_with_outdent(buf: &mut Buf, spaces: &[CommentOrNewline], indent: u16) -> u16 {
|
||||
if spaces.iter().all(|c| c.is_newline()) {
|
||||
buf.spaces(1);
|
||||
0
|
||||
} else {
|
||||
fmt_default_spaces(buf, spaces, indent);
|
||||
indent
|
||||
}
|
||||
if let Some(imports) = &header.imports {
|
||||
imports.keyword.format(buf, indent);
|
||||
fmt_imports(buf, imports.item, indent);
|
||||
}
|
||||
header.provides.format(buf, indent);
|
||||
}
|
||||
|
||||
pub fn fmt_package_header<'a>(buf: &mut Buf, header: &'a PackageHeader<'a>) {
|
||||
buf.indent(0);
|
||||
buf.push_str("package");
|
||||
let indent = INDENT;
|
||||
fmt_default_spaces(buf, header.before_name, indent);
|
||||
|
||||
fmt_package_name(buf, header.name.value, indent);
|
||||
let indent = fmt_spaces_with_outdent(buf, header.before_exposes, INDENT);
|
||||
fmt_exposes(buf, header.exposes, indent);
|
||||
|
||||
header.exposes.keyword.format(buf, indent);
|
||||
fmt_exposes(buf, header.exposes.item, indent);
|
||||
header.packages.keyword.format(buf, indent);
|
||||
fmt_packages(buf, header.packages.item, indent);
|
||||
let indent = fmt_spaces_with_outdent(buf, header.before_packages, INDENT);
|
||||
fmt_packages(buf, header.packages.value, indent);
|
||||
}
|
||||
|
||||
pub fn fmt_platform_header<'a>(buf: &mut Buf, header: &'a PlatformHeader<'a>) {
|
||||
|
@ -465,6 +458,15 @@ fn fmt_packages_entry(buf: &mut Buf, entry: &PackageEntry, indent: u16) {
|
|||
buf.push_str(entry.shorthand);
|
||||
buf.push(':');
|
||||
fmt_default_spaces(buf, entry.spaces_after_shorthand, indent);
|
||||
|
||||
let indent = indent + INDENT;
|
||||
|
||||
if let Some(spaces_after) = entry.platform_marker {
|
||||
buf.indent(indent);
|
||||
buf.push_str(roc_parse::keyword::PLATFORM);
|
||||
fmt_default_spaces(buf, spaces_after, indent);
|
||||
}
|
||||
|
||||
fmt_package_name(buf, entry.package_name.value, indent);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@ use roc_parse::{
|
|||
StrSegment, Tag, TypeAnnotation, TypeDef, TypeHeader, ValueDef, WhenBranch,
|
||||
},
|
||||
header::{
|
||||
AppHeader, ExposedName, HostedHeader, ImportsEntry, InterfaceHeader, KeywordItem,
|
||||
ModuleName, PackageEntry, PackageHeader, PackageName, PlatformHeader, PlatformRequires,
|
||||
ProvidesTo, To, TypedIdent,
|
||||
AppHeader, ExposedName, HostedHeader, ImportsEntry, KeywordItem, ModuleHeader, ModuleName,
|
||||
PackageEntry, PackageHeader, PackageName, PlatformHeader, PlatformRequires, ProvidesTo, To,
|
||||
TypedIdent,
|
||||
},
|
||||
ident::{BadIdent, UppercaseIdent},
|
||||
};
|
||||
|
@ -283,23 +283,25 @@ impl<'a> RemoveSpaces<'a> for ProvidesTo<'a> {
|
|||
impl<'a> RemoveSpaces<'a> for Module<'a> {
|
||||
fn remove_spaces(&self, arena: &'a Bump) -> Self {
|
||||
let header = match &self.header {
|
||||
Header::Interface(header) => Header::Interface(InterfaceHeader {
|
||||
before_name: &[],
|
||||
name: header.name.remove_spaces(arena),
|
||||
Header::Module(header) => Header::Module(ModuleHeader {
|
||||
before_exposes: &[],
|
||||
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 {
|
||||
before_name: &[],
|
||||
name: header.name.remove_spaces(arena),
|
||||
packages: header.packages.remove_spaces(arena),
|
||||
imports: header.imports.remove_spaces(arena),
|
||||
before_provides: &[],
|
||||
provides: header.provides.remove_spaces(arena),
|
||||
before_packages: &[],
|
||||
packages: header.packages.remove_spaces(arena),
|
||||
old_imports: header.old_imports.remove_spaces(arena),
|
||||
old_provides_to_new_package: header
|
||||
.old_provides_to_new_package
|
||||
.remove_spaces(arena),
|
||||
}),
|
||||
Header::Package(header) => Header::Package(PackageHeader {
|
||||
before_name: &[],
|
||||
name: header.name.remove_spaces(arena),
|
||||
before_exposes: &[],
|
||||
exposes: header.exposes.remove_spaces(arena),
|
||||
before_packages: &[],
|
||||
packages: header.packages.remove_spaces(arena),
|
||||
}),
|
||||
Header::Platform(header) => Header::Platform(PlatformHeader {
|
||||
|
@ -406,6 +408,10 @@ impl<'a> RemoveSpaces<'a> for PackageEntry<'a> {
|
|||
PackageEntry {
|
||||
shorthand: self.shorthand,
|
||||
spaces_after_shorthand: &[],
|
||||
platform_marker: match self.platform_marker {
|
||||
Some(_) => Some(&[]),
|
||||
None => None,
|
||||
},
|
||||
package_name: self.package_name.remove_spaces(arena),
|
||||
}
|
||||
}
|
||||
|
|
8
crates/compiler/load/tests/platform.roc
Normal file
8
crates/compiler/load/tests/platform.roc
Normal file
|
@ -0,0 +1,8 @@
|
|||
platform "test-platform"
|
||||
requires {} { main : * }
|
||||
exposes []
|
||||
packages {}
|
||||
provides [mainForHost]
|
||||
|
||||
mainForHost : {} -> {}
|
||||
mainForHost = \{} -> {}
|
|
@ -6109,9 +6109,7 @@ In roc, functions are always written as a lambda, like{}
|
|||
report_header_problem_as(
|
||||
indoc!(
|
||||
r"
|
||||
interface Foobar
|
||||
exposes [main, @Foo]
|
||||
imports [pf.Task, Base64]
|
||||
module [main, @Foo]
|
||||
"
|
||||
),
|
||||
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:
|
||||
|
||||
1│ interface Foobar
|
||||
2│ exposes [main, @Foo]
|
||||
^
|
||||
1│ module [main, @Foo]
|
||||
^
|
||||
|
||||
I was expecting a type name, value name or function name next, like
|
||||
|
||||
exposes [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.
|
||||
[Animal, default, tame]
|
||||
"
|
||||
),
|
||||
)
|
||||
|
|
|
@ -49,8 +49,8 @@ use roc_mono::{drop_specialization, inc_dec};
|
|||
use roc_packaging::cache::RocCacheDir;
|
||||
use roc_parse::ast::{self, CommentOrNewline, ExtractSpaces, Spaced, ValueDef};
|
||||
use roc_parse::header::{
|
||||
ExposedName, HeaderType, ImportsKeywordItem, PackageEntry, PackageHeader, PlatformHeader, To,
|
||||
TypedIdent,
|
||||
self, ExposedName, HeaderType, ImportsKeywordItem, PackageEntry, PackageHeader, PlatformHeader,
|
||||
To, TypedIdent,
|
||||
};
|
||||
use roc_parse::module::parse_module_defs;
|
||||
use roc_parse::parser::{FileError, SourceError, SyntaxError};
|
||||
|
@ -644,7 +644,7 @@ struct CanAndCon {
|
|||
enum PlatformPath<'a> {
|
||||
NotSpecified,
|
||||
Valid(To<'a>),
|
||||
RootIsInterface,
|
||||
RootIsModule,
|
||||
RootIsHosted,
|
||||
RootIsPlatformModule,
|
||||
}
|
||||
|
@ -948,6 +948,18 @@ pub enum LoadingProblem<'a> {
|
|||
},
|
||||
ParsingFailed(FileError<'a, SyntaxError<'a>>),
|
||||
UnexpectedHeader(String),
|
||||
MultiplePlatformPackages {
|
||||
filename: PathBuf,
|
||||
module_id: ModuleId,
|
||||
source: &'a [u8],
|
||||
region: Region,
|
||||
},
|
||||
NoPlatformPackage {
|
||||
filename: PathBuf,
|
||||
module_id: ModuleId,
|
||||
source: &'a [u8],
|
||||
region: Region,
|
||||
},
|
||||
|
||||
ErrJoiningWorkerThreads,
|
||||
TriedToImportAppModule,
|
||||
|
@ -1204,8 +1216,9 @@ fn adjust_header_paths<'a>(
|
|||
{
|
||||
debug_assert_eq!(*header_id, header_output.module_id);
|
||||
|
||||
if let HeaderType::Interface { name, .. } = header_type {
|
||||
// Interface modules can have names like Foo.Bar.Baz,
|
||||
if let HeaderType::Module { name, .. } = header_type {
|
||||
// [modules-revamp] TODO: Privacy changes
|
||||
// Modules can have names like Foo.Bar.Baz,
|
||||
// in which case we need to adjust the src_dir to
|
||||
// remove the "Bar/Baz" directories in order to correctly
|
||||
// resolve this interface module's imports!
|
||||
|
@ -1666,6 +1679,34 @@ pub fn report_loading_problem(
|
|||
LoadingProblem::FileProblem { filename, error } => {
|
||||
to_file_problem_report_string(filename, error)
|
||||
}
|
||||
LoadingProblem::NoPlatformPackage {
|
||||
filename,
|
||||
module_id,
|
||||
source,
|
||||
region,
|
||||
} => to_no_platform_package_report(
|
||||
module_ids,
|
||||
IdentIds::exposed_builtins(0),
|
||||
module_id,
|
||||
filename,
|
||||
region,
|
||||
source,
|
||||
render,
|
||||
),
|
||||
LoadingProblem::MultiplePlatformPackages {
|
||||
filename,
|
||||
module_id,
|
||||
source,
|
||||
region,
|
||||
} => to_multiple_platform_packages_report(
|
||||
module_ids,
|
||||
IdentIds::exposed_builtins(0),
|
||||
module_id,
|
||||
filename,
|
||||
region,
|
||||
source,
|
||||
render,
|
||||
),
|
||||
err => todo!("Loading error: {:?}", err),
|
||||
}
|
||||
}
|
||||
|
@ -2313,13 +2354,13 @@ fn update<'a>(
|
|||
state.exposed_modules = exposes_ids;
|
||||
}
|
||||
}
|
||||
Builtin { .. } | Interface { .. } => {
|
||||
Builtin { .. } | Module { .. } => {
|
||||
if header.is_root_module {
|
||||
debug_assert!(matches!(
|
||||
state.platform_path,
|
||||
PlatformPath::NotSpecified
|
||||
));
|
||||
state.platform_path = PlatformPath::RootIsInterface;
|
||||
state.platform_path = PlatformPath::RootIsModule;
|
||||
}
|
||||
}
|
||||
Hosted { .. } => {
|
||||
|
@ -2956,7 +2997,7 @@ fn update<'a>(
|
|||
// This happens due to abilities. In detail, consider
|
||||
//
|
||||
// # Default module
|
||||
// interface Default exposes [default, getDefault]
|
||||
// module [default, getDefault]
|
||||
//
|
||||
// Default implements default : {} -> a where a implements Default
|
||||
//
|
||||
|
@ -3198,7 +3239,7 @@ fn finish_specialization<'a>(
|
|||
let module_id = state.root_id;
|
||||
let uses_prebuilt_platform = match platform_data {
|
||||
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!
|
||||
None => false,
|
||||
};
|
||||
|
@ -3346,12 +3387,12 @@ fn load_package_from_disk<'a>(
|
|||
match parsed {
|
||||
Ok((
|
||||
ast::Module {
|
||||
header: ast::Header::Interface(header),
|
||||
header: ast::Header::Module(header),
|
||||
..
|
||||
},
|
||||
_parse_state,
|
||||
)) => 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((
|
||||
ast::Module {
|
||||
|
@ -3477,23 +3518,25 @@ fn load_builtin_module_help<'a>(
|
|||
match parsed {
|
||||
Ok((
|
||||
ast::Module {
|
||||
header: ast::Header::Interface(header),
|
||||
header: ast::Header::Module(header),
|
||||
comments,
|
||||
},
|
||||
parse_state,
|
||||
)) => {
|
||||
let name_stem = arena.alloc_str(filename.file_stem().unwrap().to_str().unwrap());
|
||||
|
||||
let info = HeaderInfo {
|
||||
filename,
|
||||
is_root_module,
|
||||
opt_shorthand,
|
||||
packages: &[],
|
||||
header_type: HeaderType::Builtin {
|
||||
name: header.name.value,
|
||||
exposes: unspace(arena, header.exposes.item.items),
|
||||
name: header::ModuleName::new(name_stem),
|
||||
exposes: unspace(arena, header.exposes.items),
|
||||
generates_with: &[],
|
||||
},
|
||||
module_comments: comments,
|
||||
header_imports: Some(header.imports),
|
||||
header_imports: header.interface_imports,
|
||||
};
|
||||
|
||||
(info, parse_state)
|
||||
|
@ -3693,45 +3736,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)]
|
||||
struct HeaderOutput<'a> {
|
||||
module_id: ModuleId,
|
||||
|
@ -3798,48 +3802,35 @@ fn parse_header<'a>(
|
|||
match parsed {
|
||||
Ok((
|
||||
ast::Module {
|
||||
header: ast::Header::Interface(header),
|
||||
header: ast::Header::Module(header),
|
||||
comments,
|
||||
},
|
||||
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 {
|
||||
filename,
|
||||
is_root_module,
|
||||
opt_shorthand,
|
||||
packages: &[],
|
||||
header_type: HeaderType::Interface {
|
||||
name: header.name.value,
|
||||
exposes: unspace(arena, header.exposes.item.items),
|
||||
header_type: HeaderType::Module {
|
||||
name: roc_parse::header::ModuleName::new(module_name),
|
||||
exposes: unspace(arena, header.exposes.items),
|
||||
},
|
||||
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)?;
|
||||
|
||||
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 {
|
||||
module_id,
|
||||
msg: Msg::Header(header),
|
||||
|
@ -3887,24 +3878,60 @@ fn parse_header<'a>(
|
|||
let mut app_file_dir = filename.clone();
|
||||
app_file_dir.pop();
|
||||
|
||||
let packages = if let Some(packages) = header.packages {
|
||||
unspace(arena, packages.item.items)
|
||||
} else {
|
||||
&[]
|
||||
let packages = unspace(arena, header.packages.value.items);
|
||||
|
||||
let mut platform_shorthand = None;
|
||||
|
||||
for package in packages.iter() {
|
||||
if package.value.platform_marker.is_some() {
|
||||
if platform_shorthand.is_some() {
|
||||
let mut module_ids = (*module_ids).lock();
|
||||
|
||||
let module_id = module_ids.get_or_insert(
|
||||
arena.alloc(PQModuleName::Unqualified(ModuleName::APP.into())),
|
||||
);
|
||||
|
||||
return Err(LoadingProblem::MultiplePlatformPackages {
|
||||
module_id,
|
||||
filename,
|
||||
source: src_bytes,
|
||||
region: header.packages.region,
|
||||
});
|
||||
}
|
||||
|
||||
platform_shorthand = Some(package.value.shorthand);
|
||||
}
|
||||
}
|
||||
|
||||
let to_platform = match platform_shorthand {
|
||||
Some(shorthand) => To::ExistingPackage(shorthand),
|
||||
None => {
|
||||
if let Some(new_pkg) = header.old_provides_to_new_package {
|
||||
// This is a piece of old syntax that's used by the REPL and a number of
|
||||
// tests where an ephemeral platform package is specified that is never
|
||||
// loaded.
|
||||
// We can remove this when we have upgraded everything to the new syntax.
|
||||
To::NewPackage(new_pkg)
|
||||
} else {
|
||||
let mut module_ids = (*module_ids).lock();
|
||||
|
||||
let module_id = module_ids.get_or_insert(
|
||||
arena.alloc(PQModuleName::Unqualified(ModuleName::APP.into())),
|
||||
);
|
||||
|
||||
return Err(LoadingProblem::NoPlatformPackage {
|
||||
module_id,
|
||||
filename,
|
||||
region: header.packages.region,
|
||||
source: src_bytes,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut provides = bumpalo::collections::Vec::new_in(arena);
|
||||
|
||||
provides.extend(unspace(arena, header.provides.entries.items));
|
||||
|
||||
if let Some(provided_types) = header.provides.types {
|
||||
for provided_type in unspace(arena, provided_types.items) {
|
||||
let string: &str = provided_type.value.into();
|
||||
let exposed_name = ExposedName::new(string);
|
||||
|
||||
provides.push(Loc::at(provided_type.region, exposed_name));
|
||||
}
|
||||
}
|
||||
provides.extend(unspace(arena, header.provides.items));
|
||||
|
||||
let info = HeaderInfo {
|
||||
filename,
|
||||
|
@ -3913,11 +3940,10 @@ fn parse_header<'a>(
|
|||
packages,
|
||||
header_type: HeaderType::App {
|
||||
provides: provides.into_bump_slice(),
|
||||
output_name: header.name.value,
|
||||
to_platform: header.provides.to.value,
|
||||
to_platform,
|
||||
},
|
||||
module_comments: comments,
|
||||
header_imports: header.imports,
|
||||
header_imports: header.old_imports,
|
||||
};
|
||||
|
||||
let (module_id, _, resolved_header) =
|
||||
|
@ -3941,28 +3967,11 @@ fn parse_header<'a>(
|
|||
filename,
|
||||
);
|
||||
|
||||
// Look at the app module's `to` keyword to determine which package was the platform.
|
||||
match header.provides.to.value {
|
||||
To::ExistingPackage(shorthand) => {
|
||||
if !packages
|
||||
.iter()
|
||||
.any(|loc_package_entry| loc_package_entry.value.shorthand == shorthand)
|
||||
{
|
||||
todo!("Gracefully handle platform shorthand after `to` that didn't map to a shorthand specified in `packages`");
|
||||
}
|
||||
|
||||
Ok(HeaderOutput {
|
||||
module_id,
|
||||
msg: Msg::Many(messages),
|
||||
opt_platform_shorthand: Some(shorthand),
|
||||
})
|
||||
}
|
||||
To::NewPackage(_package_name) => Ok(HeaderOutput {
|
||||
module_id,
|
||||
msg: Msg::Many(messages),
|
||||
opt_platform_shorthand: None,
|
||||
}),
|
||||
}
|
||||
Ok(HeaderOutput {
|
||||
module_id,
|
||||
msg: Msg::Many(messages),
|
||||
opt_platform_shorthand: platform_shorthand,
|
||||
})
|
||||
}
|
||||
Ok((
|
||||
ast::Module {
|
||||
|
@ -4217,14 +4226,9 @@ fn build_header<'a>(
|
|||
// Package modules do not have names.
|
||||
String::new().into()
|
||||
}
|
||||
HeaderType::Interface { name, .. }
|
||||
HeaderType::Module { name, .. }
|
||||
| HeaderType::Builtin { name, .. }
|
||||
| HeaderType::Hosted { name, .. } => {
|
||||
// TODO check to see if name is consistent with filename.
|
||||
// If it isn't, report a problem!
|
||||
|
||||
name.as_str().into()
|
||||
}
|
||||
| HeaderType::Hosted { name, .. } => name.as_str().into(),
|
||||
};
|
||||
|
||||
let (name, home) = {
|
||||
|
@ -4847,12 +4851,12 @@ fn build_package_header<'a>(
|
|||
module_timing: ModuleTiming,
|
||||
) -> Result<(ModuleId, PQModuleName<'a>, ModuleHeader<'a>), LoadingProblem<'a>> {
|
||||
let exposes = bumpalo::collections::Vec::from_iter_in(
|
||||
unspace(arena, header.exposes.item.items).iter().copied(),
|
||||
unspace(arena, header.exposes.items).iter().copied(),
|
||||
arena,
|
||||
);
|
||||
let packages = unspace(arena, header.packages.item.items);
|
||||
let packages = unspace(arena, header.packages.value.items);
|
||||
let exposes_ids = get_exposes_ids(
|
||||
header.exposes.item.items,
|
||||
header.exposes.items,
|
||||
arena,
|
||||
&module_ids,
|
||||
&ident_ids_by_module,
|
||||
|
@ -5172,7 +5176,7 @@ fn parse<'a>(
|
|||
}
|
||||
HeaderType::App { .. }
|
||||
| HeaderType::Package { .. }
|
||||
| HeaderType::Interface { .. }
|
||||
| HeaderType::Module { .. }
|
||||
| HeaderType::Builtin { .. }
|
||||
| HeaderType::Hosted { .. } => {}
|
||||
};
|
||||
|
@ -6331,6 +6335,96 @@ fn to_incorrect_module_name_report<'a>(
|
|||
buf
|
||||
}
|
||||
|
||||
fn to_no_platform_package_report(
|
||||
module_ids: ModuleIds,
|
||||
all_ident_ids: IdentIdsByModule,
|
||||
module_id: ModuleId,
|
||||
filename: PathBuf,
|
||||
region: Region,
|
||||
src: &[u8],
|
||||
render: RenderTarget,
|
||||
) -> String {
|
||||
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
|
||||
use ven_pretty::DocAllocator;
|
||||
|
||||
// SAFETY: if the module was not UTF-8, that would be reported as a parsing problem, rather
|
||||
// than an incorrect module name problem (the latter can happen only after parsing).
|
||||
let src = unsafe { from_utf8_unchecked(src) };
|
||||
let src_lines = src.lines().collect::<Vec<_>>();
|
||||
let lines = LineInfo::new(src);
|
||||
|
||||
let interns = Interns {
|
||||
module_ids,
|
||||
all_ident_ids,
|
||||
};
|
||||
let alloc = RocDocAllocator::new(&src_lines, module_id, &interns);
|
||||
|
||||
let doc = alloc.stack([
|
||||
alloc.reflow("This app does not specify a platform:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.reflow("Make sure you have exactly one package specified as `platform`:"),
|
||||
alloc
|
||||
.parser_suggestion(" app [main] {\n pf: platform \"…path or URL to platform…\"\n ^^^^^^^^\n }"),
|
||||
alloc.reflow("Tip: See an example in the tutorial:\n\n<https://www.roc-lang.org/tutorial#building-an-application>"),
|
||||
|
||||
]);
|
||||
|
||||
let report = Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "UNSPECIFIED PLATFORM".to_string(),
|
||||
severity: Severity::RuntimeError,
|
||||
};
|
||||
|
||||
let mut buf = String::new();
|
||||
let palette = DEFAULT_PALETTE;
|
||||
report.render(render, &mut buf, &alloc, &palette);
|
||||
buf
|
||||
}
|
||||
|
||||
fn to_multiple_platform_packages_report(
|
||||
module_ids: ModuleIds,
|
||||
all_ident_ids: IdentIdsByModule,
|
||||
module_id: ModuleId,
|
||||
filename: PathBuf,
|
||||
region: Region,
|
||||
src: &[u8],
|
||||
render: RenderTarget,
|
||||
) -> String {
|
||||
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
|
||||
use ven_pretty::DocAllocator;
|
||||
|
||||
// SAFETY: if the module was not UTF-8, that would be reported as a parsing problem, rather
|
||||
// than an incorrect module name problem (the latter can happen only after parsing).
|
||||
let src = unsafe { from_utf8_unchecked(src) };
|
||||
let src_lines = src.lines().collect::<Vec<_>>();
|
||||
let lines = LineInfo::new(src);
|
||||
|
||||
let interns = Interns {
|
||||
module_ids,
|
||||
all_ident_ids,
|
||||
};
|
||||
let alloc = RocDocAllocator::new(&src_lines, module_id, &interns);
|
||||
|
||||
let doc = alloc.stack([
|
||||
alloc.reflow("This app specifies multiple packages as `platform`:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.reflow("Roc apps must specify exactly one platform."),
|
||||
]);
|
||||
|
||||
let report = Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "MULTIPLE PLATFORMS".to_string(),
|
||||
severity: Severity::RuntimeError,
|
||||
};
|
||||
|
||||
let mut buf = String::new();
|
||||
let palette = DEFAULT_PALETTE;
|
||||
report.render(render, &mut buf, &alloc, &palette);
|
||||
buf
|
||||
}
|
||||
|
||||
fn to_parse_problem_report<'a>(
|
||||
problem: FileError<'a, SyntaxError<'a>>,
|
||||
mut module_ids: ModuleIds,
|
||||
|
@ -6396,7 +6490,7 @@ fn report_cannot_run(
|
|||
alloc.reflow("I could not find a platform based on your input file."),
|
||||
alloc.reflow(r"Does the module header have an entry that looks like this?"),
|
||||
alloc
|
||||
.parser_suggestion("packages { blah: \"…path or URL to platform…\" }")
|
||||
.parser_suggestion("app [main] { pf: platform \"…path or URL to platform…\" }")
|
||||
.indent(4),
|
||||
alloc.reflow("Tip: The following part of the tutorial has an example of specifying a platform:\n\n<https://www.roc-lang.org/tutorial#building-an-application>"),
|
||||
]);
|
||||
|
@ -6408,12 +6502,12 @@ fn report_cannot_run(
|
|||
severity: Severity::RuntimeError,
|
||||
}
|
||||
}
|
||||
RootIsInterface => {
|
||||
RootIsModule => {
|
||||
let doc = alloc.stack([
|
||||
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 {
|
||||
|
|
|
@ -272,6 +272,7 @@ fn expect_types(mut loaded_module: LoadedModule, mut expected_types: HashMap<&st
|
|||
|
||||
let interns = &loaded_module.interns;
|
||||
let declarations = loaded_module.declarations_by_id.remove(&home).unwrap();
|
||||
|
||||
for index in 0..declarations.len() {
|
||||
use roc_can::expr::DeclarationTag::*;
|
||||
|
||||
|
@ -339,7 +340,7 @@ fn import_transitive_alias() {
|
|||
"RBTree.roc",
|
||||
indoc!(
|
||||
r"
|
||||
interface RBTree exposes [RedBlackTree, empty] imports []
|
||||
module [RedBlackTree, empty]
|
||||
|
||||
# The color of a node. Leaves are considered Black.
|
||||
NodeColor : [Red, Black]
|
||||
|
@ -357,7 +358,7 @@ fn import_transitive_alias() {
|
|||
"Other.roc",
|
||||
indoc!(
|
||||
r"
|
||||
interface Other exposes [empty] imports []
|
||||
module [empty]
|
||||
|
||||
import RBTree
|
||||
|
||||
|
@ -372,9 +373,9 @@ fn import_transitive_alias() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn interface_with_deps() {
|
||||
fn module_with_deps() {
|
||||
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 arena = Bump::new();
|
||||
let loaded = load_and_typecheck(
|
||||
|
@ -488,7 +489,7 @@ fn load_docs() {
|
|||
#[test]
|
||||
fn import_alias() {
|
||||
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(
|
||||
loaded_module,
|
||||
|
@ -501,7 +502,7 @@ fn import_alias() {
|
|||
#[test]
|
||||
fn import_inside_def() {
|
||||
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(
|
||||
loaded_module,
|
||||
|
@ -517,7 +518,7 @@ fn import_inside_def() {
|
|||
fn exposed_used_outside_scope() {
|
||||
let subs_by_module = Default::default();
|
||||
load_fixture(
|
||||
"interface_with_deps",
|
||||
"module_with_deps",
|
||||
"ExposedUsedOutsideScope",
|
||||
subs_by_module,
|
||||
);
|
||||
|
@ -527,17 +528,13 @@ fn exposed_used_outside_scope() {
|
|||
#[should_panic(expected = "MODULE NOT IMPORTED")]
|
||||
fn import_used_outside_scope() {
|
||||
let subs_by_module = Default::default();
|
||||
load_fixture(
|
||||
"interface_with_deps",
|
||||
"ImportUsedOutsideScope",
|
||||
subs_by_module,
|
||||
);
|
||||
load_fixture("module_with_deps", "ImportUsedOutsideScope", subs_by_module);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_load_and_typecheck() {
|
||||
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(
|
||||
loaded_module,
|
||||
|
@ -558,7 +555,7 @@ fn test_load_and_typecheck() {
|
|||
#[test]
|
||||
fn iface_quicksort() {
|
||||
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(
|
||||
loaded_module,
|
||||
|
@ -574,7 +571,7 @@ fn iface_quicksort() {
|
|||
#[test]
|
||||
fn load_astar() {
|
||||
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(
|
||||
loaded_module,
|
||||
|
@ -606,7 +603,7 @@ fn load_principal_types() {
|
|||
#[test]
|
||||
fn iface_dep_types() {
|
||||
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(
|
||||
loaded_module,
|
||||
|
@ -650,7 +647,7 @@ fn app_dep_types() {
|
|||
#[test]
|
||||
fn imported_dep_regression() {
|
||||
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(
|
||||
loaded_module,
|
||||
|
@ -663,7 +660,7 @@ fn imported_dep_regression() {
|
|||
#[test]
|
||||
fn ingested_file() {
|
||||
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(
|
||||
loaded_module,
|
||||
|
@ -678,7 +675,7 @@ fn ingested_file() {
|
|||
#[test]
|
||||
fn ingested_file_bytes() {
|
||||
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(
|
||||
loaded_module,
|
||||
|
@ -695,7 +692,7 @@ fn parse_problem() {
|
|||
"Main.roc",
|
||||
indoc!(
|
||||
r"
|
||||
interface Main exposes [main] imports []
|
||||
module [main]
|
||||
|
||||
main = [
|
||||
"
|
||||
|
@ -732,7 +729,7 @@ fn parse_problem() {
|
|||
#[should_panic(expected = "FILE NOT FOUND")]
|
||||
fn file_not_found() {
|
||||
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(
|
||||
loaded_module,
|
||||
|
@ -887,7 +884,7 @@ fn opaque_wrapped_unwrapped_outside_defining_module() {
|
|||
"Age.roc",
|
||||
indoc!(
|
||||
r"
|
||||
interface Age exposes [Age] imports []
|
||||
module [Age]
|
||||
|
||||
Age := U32
|
||||
"
|
||||
|
@ -897,7 +894,7 @@ fn opaque_wrapped_unwrapped_outside_defining_module() {
|
|||
"Main.roc",
|
||||
indoc!(
|
||||
r"
|
||||
interface Main exposes [twenty, readAge] imports []
|
||||
module [twenty, readAge]
|
||||
|
||||
import Age exposing [Age]
|
||||
|
||||
|
@ -965,7 +962,8 @@ fn unused_imports() {
|
|||
"Dep1.roc",
|
||||
indoc!(
|
||||
r#"
|
||||
interface Dep1 exposes [one] imports []
|
||||
module [one]
|
||||
|
||||
one = 1
|
||||
"#
|
||||
),
|
||||
|
@ -974,7 +972,8 @@ fn unused_imports() {
|
|||
"Dep2.roc",
|
||||
indoc!(
|
||||
r#"
|
||||
interface Dep2 exposes [two] imports []
|
||||
module [two]
|
||||
|
||||
two = 2
|
||||
"#
|
||||
),
|
||||
|
@ -983,7 +982,7 @@ fn unused_imports() {
|
|||
"Dep3.roc",
|
||||
indoc!(
|
||||
r#"
|
||||
interface Dep3 exposes [Three, three] imports []
|
||||
module [Three, three]
|
||||
|
||||
Three : [Three]
|
||||
|
||||
|
@ -995,7 +994,7 @@ fn unused_imports() {
|
|||
"Main.roc",
|
||||
indoc!(
|
||||
r#"
|
||||
interface Main exposes [usedModule, unusedModule, unusedExposed, unusedWithAlias, usingThreeValue] imports []
|
||||
module [usedModule, unusedModule, unusedExposed, usingThreeValue, unusedWithAlias]
|
||||
|
||||
import Dep1
|
||||
import Dep3 exposing [Three]
|
||||
|
@ -1663,48 +1662,13 @@ fn import_builtin_in_platform_and_check_app() {
|
|||
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]
|
||||
fn module_cyclic_import_itself() {
|
||||
let modules = vec![(
|
||||
"Age.roc",
|
||||
indoc!(
|
||||
r"
|
||||
interface Age exposes [] imports []
|
||||
module []
|
||||
|
||||
import Age
|
||||
"
|
||||
|
@ -1742,7 +1706,8 @@ fn module_cyclic_import_transitive() {
|
|||
"Age.roc",
|
||||
indoc!(
|
||||
r"
|
||||
interface Age exposes [] imports []
|
||||
module []
|
||||
|
||||
import Person
|
||||
"
|
||||
),
|
||||
|
@ -1751,7 +1716,8 @@ fn module_cyclic_import_transitive() {
|
|||
"Person.roc",
|
||||
indoc!(
|
||||
r"
|
||||
interface Person exposes [] imports []
|
||||
module []
|
||||
|
||||
import Age
|
||||
"
|
||||
),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::fmt::Debug;
|
||||
|
||||
use crate::header::{
|
||||
self, AppHeader, HostedHeader, InterfaceHeader, ModuleName, PackageHeader, PlatformHeader,
|
||||
self, AppHeader, HostedHeader, ModuleHeader, ModuleName, PackageHeader, PlatformHeader,
|
||||
};
|
||||
use crate::ident::Accessor;
|
||||
use crate::parser::ESingleQuote;
|
||||
|
@ -48,6 +48,18 @@ impl<'a, T> Spaced<'a, T> {
|
|||
Spaced::SpaceBefore(next, _spaces) | Spaced::SpaceAfter(next, _spaces) => next.item(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map<U, F: Fn(&T) -> U>(&self, arena: &'a Bump, f: F) -> Spaced<'a, U> {
|
||||
match self {
|
||||
Spaced::Item(item) => Spaced::Item(f(item)),
|
||||
Spaced::SpaceBefore(next, spaces) => {
|
||||
Spaced::SpaceBefore(arena.alloc(next.map(arena, f)), spaces)
|
||||
}
|
||||
Spaced::SpaceAfter(next, spaces) => {
|
||||
Spaced::SpaceAfter(arena.alloc(next.map(arena, f)), spaces)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Debug> Debug for Spaced<'a, T> {
|
||||
|
@ -99,6 +111,30 @@ pub struct 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::App(header) => (
|
||||
Header::App(AppHeader {
|
||||
old_imports: None,
|
||||
..header
|
||||
}),
|
||||
Self::header_imports_to_defs(arena, header.old_imports),
|
||||
),
|
||||
Header::Package(_) | Header::Platform(_) | Header::Hosted(_) => {
|
||||
(self.header, Defs::default())
|
||||
}
|
||||
};
|
||||
|
||||
(Module { header, ..self }, defs)
|
||||
}
|
||||
|
||||
pub fn header_imports_to_defs(
|
||||
arena: &'a Bump,
|
||||
imports: Option<
|
||||
|
@ -159,6 +195,7 @@ impl<'a> Module<'a> {
|
|||
},
|
||||
if index == len - 1 {
|
||||
let mut after = spaced.after.to_vec();
|
||||
after.extend_from_slice(imports.item.final_comments());
|
||||
after.push(CommentOrNewline::Newline);
|
||||
after.push(CommentOrNewline::Newline);
|
||||
arena.alloc(after)
|
||||
|
@ -209,7 +246,7 @@ impl<'a> Module<'a> {
|
|||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Header<'a> {
|
||||
Interface(InterfaceHeader<'a>),
|
||||
Module(ModuleHeader<'a>),
|
||||
App(AppHeader<'a>),
|
||||
Package(PackageHeader<'a>),
|
||||
Platform(PlatformHeader<'a>),
|
||||
|
@ -2272,7 +2309,7 @@ impl<'a> Malformed for Module<'a> {
|
|||
impl<'a> Malformed for Header<'a> {
|
||||
fn is_malformed(&self) -> bool {
|
||||
match self {
|
||||
Header::Interface(header) => header.is_malformed(),
|
||||
Header::Module(header) => header.is_malformed(),
|
||||
Header::App(header) => header.is_malformed(),
|
||||
Header::Package(header) => header.is_malformed(),
|
||||
Header::Platform(header) => header.is_malformed(),
|
||||
|
|
|
@ -19,7 +19,7 @@ impl<'a> HeaderType<'a> {
|
|||
}
|
||||
| HeaderType::Hosted { exposes, .. }
|
||||
| HeaderType::Builtin { exposes, .. }
|
||||
| HeaderType::Interface { exposes, .. } => exposes,
|
||||
| HeaderType::Module { exposes, .. } => exposes,
|
||||
HeaderType::Platform { .. } | HeaderType::Package { .. } => &[],
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ impl<'a> HeaderType<'a> {
|
|||
HeaderType::Builtin { .. } => "builtin",
|
||||
HeaderType::Package { .. } => "package",
|
||||
HeaderType::Platform { .. } => "platform",
|
||||
HeaderType::Interface { .. } => "interface",
|
||||
HeaderType::Module { .. } => "module",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,6 @@ impl<'a> HeaderType<'a> {
|
|||
#[derive(Debug)]
|
||||
pub enum HeaderType<'a> {
|
||||
App {
|
||||
output_name: StrLiteral<'a>,
|
||||
provides: &'a [Loc<ExposedName<'a>>],
|
||||
to_platform: To<'a>,
|
||||
},
|
||||
|
@ -73,7 +72,7 @@ pub enum HeaderType<'a> {
|
|||
/// usually `pf`
|
||||
config_shorthand: &'a str,
|
||||
},
|
||||
Interface {
|
||||
Module {
|
||||
name: ModuleName<'a>,
|
||||
exposes: &'a [Loc<ExposedName<'a>>],
|
||||
},
|
||||
|
@ -82,14 +81,10 @@ pub enum HeaderType<'a> {
|
|||
impl<'a> HeaderType<'a> {
|
||||
pub fn get_name(self) -> Option<&'a str> {
|
||||
match self {
|
||||
Self::Interface { name, .. }
|
||||
| Self::Builtin { name, .. }
|
||||
| Self::Hosted { name, .. } => Some(name.into()),
|
||||
Self::App {
|
||||
output_name: StrLiteral::PlainLine(name),
|
||||
..
|
||||
Self::Module { name, .. } | Self::Builtin { name, .. } | Self::Hosted { name, .. } => {
|
||||
Some(name.into())
|
||||
}
|
||||
| Self::Platform {
|
||||
Self::Platform {
|
||||
config_shorthand: name,
|
||||
..
|
||||
}
|
||||
|
@ -106,13 +101,11 @@ impl<'a> HeaderType<'a> {
|
|||
|
||||
pub fn to_maybe_builtin(self, module_id: ModuleId) -> Self {
|
||||
match self {
|
||||
HeaderType::Interface { name, exposes } if module_id.is_builtin() => {
|
||||
HeaderType::Builtin {
|
||||
name,
|
||||
exposes,
|
||||
generates_with: &[],
|
||||
}
|
||||
}
|
||||
HeaderType::Module { name, exposes } if module_id.is_builtin() => HeaderType::Builtin {
|
||||
name,
|
||||
exposes,
|
||||
generates_with: &[],
|
||||
},
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
|
@ -236,6 +229,8 @@ keywords! {
|
|||
RequiresKeyword => "requires",
|
||||
ProvidesKeyword => "provides",
|
||||
ToKeyword => "to",
|
||||
PlatformKeyword => "platform",
|
||||
// Deprecated
|
||||
ImportsKeyword => "imports",
|
||||
}
|
||||
|
||||
|
@ -246,12 +241,12 @@ pub struct KeywordItem<'a, K, V> {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct InterfaceHeader<'a> {
|
||||
pub before_name: &'a [CommentOrNewline<'a>],
|
||||
pub name: Loc<ModuleName<'a>>,
|
||||
pub struct ModuleHeader<'a> {
|
||||
pub before_exposes: &'a [CommentOrNewline<'a>],
|
||||
pub exposes: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
||||
|
||||
pub exposes: KeywordItem<'a, ExposesKeyword, Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>>,
|
||||
pub imports: KeywordItem<'a, ImportsKeyword, Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>>,
|
||||
// Keeping this so we can format old interface header into module headers
|
||||
pub interface_imports: Option<KeywordItem<'a, ImportsKeyword, ImportsCollection<'a>>>,
|
||||
}
|
||||
|
||||
pub type ImportsKeywordItem<'a> = KeywordItem<'a, ImportsKeyword, ImportsCollection<'a>>;
|
||||
|
@ -278,14 +273,13 @@ pub enum To<'a> {
|
|||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct AppHeader<'a> {
|
||||
pub before_name: &'a [CommentOrNewline<'a>],
|
||||
pub name: Loc<StrLiteral<'a>>,
|
||||
|
||||
pub packages:
|
||||
Option<KeywordItem<'a, PackagesKeyword, Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>>>,
|
||||
pub imports:
|
||||
Option<KeywordItem<'a, ImportsKeyword, Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>>>,
|
||||
pub provides: ProvidesTo<'a>,
|
||||
pub before_provides: &'a [CommentOrNewline<'a>],
|
||||
pub provides: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
||||
pub before_packages: &'a [CommentOrNewline<'a>],
|
||||
pub packages: Loc<Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>>,
|
||||
// Old header pieces
|
||||
pub old_imports: Option<KeywordItem<'a, ImportsKeyword, ImportsCollection<'a>>>,
|
||||
pub old_provides_to_new_package: Option<PackageName<'a>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
@ -300,12 +294,10 @@ pub struct ProvidesTo<'a> {
|
|||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct PackageHeader<'a> {
|
||||
pub before_name: &'a [CommentOrNewline<'a>],
|
||||
pub name: Loc<PackageName<'a>>,
|
||||
|
||||
pub exposes: KeywordItem<'a, ExposesKeyword, Collection<'a, Loc<Spaced<'a, ModuleName<'a>>>>>,
|
||||
pub packages:
|
||||
KeywordItem<'a, PackagesKeyword, Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>>,
|
||||
pub before_exposes: &'a [CommentOrNewline<'a>],
|
||||
pub exposes: Collection<'a, Loc<Spaced<'a, ModuleName<'a>>>>,
|
||||
pub before_packages: &'a [CommentOrNewline<'a>],
|
||||
pub packages: Loc<Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
@ -361,6 +353,7 @@ pub struct TypedIdent<'a> {
|
|||
pub struct PackageEntry<'a> {
|
||||
pub shorthand: &'a str,
|
||||
pub spaces_after_shorthand: &'a [CommentOrNewline<'a>],
|
||||
pub platform_marker: Option<&'a [CommentOrNewline<'a>]>,
|
||||
pub package_name: Loc<PackageName<'a>>,
|
||||
}
|
||||
|
||||
|
@ -381,9 +374,15 @@ pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPac
|
|||
),
|
||||
space0_e(EPackageEntry::IndentPackage)
|
||||
)),
|
||||
loc!(specialize_err(EPackageEntry::BadPackage, package_name()))
|
||||
and!(
|
||||
optional(skip_first!(
|
||||
crate::parser::keyword(crate::keyword::PLATFORM, EPackageEntry::Platform),
|
||||
space0_e(EPackageEntry::IndentPackage)
|
||||
)),
|
||||
loc!(specialize_err(EPackageEntry::BadPackage, package_name()))
|
||||
)
|
||||
),
|
||||
move |arena, (opt_shorthand, package_or_path)| {
|
||||
move |arena, (opt_shorthand, (platform_marker, package_or_path))| {
|
||||
let entry = match opt_shorthand {
|
||||
Some(((shorthand, spaces_before_colon), spaces_after_colon)) => PackageEntry {
|
||||
shorthand,
|
||||
|
@ -392,11 +391,13 @@ pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPac
|
|||
spaces_before_colon,
|
||||
spaces_after_colon,
|
||||
),
|
||||
platform_marker,
|
||||
package_name: package_or_path,
|
||||
},
|
||||
None => PackageEntry {
|
||||
shorthand: "",
|
||||
spaces_after_shorthand: &[],
|
||||
platform_marker,
|
||||
package_name: package_or_path,
|
||||
},
|
||||
};
|
||||
|
@ -430,7 +431,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Malformed for InterfaceHeader<'a> {
|
||||
impl<'a> Malformed for ModuleHeader<'a> {
|
||||
fn is_malformed(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
@ -444,7 +445,7 @@ impl<'a> Malformed for HostedHeader<'a> {
|
|||
|
||||
impl<'a> Malformed for AppHeader<'a> {
|
||||
fn is_malformed(&self) -> bool {
|
||||
self.name.is_malformed()
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,9 @@ pub const EXPOSING: &str = "exposing";
|
|||
pub const IMPLEMENTS: &str = "implements";
|
||||
pub const WHERE: &str = "where";
|
||||
|
||||
// These keywords are valid in headers
|
||||
pub const PLATFORM: &str = "platform";
|
||||
|
||||
pub const KEYWORDS: [&str; 11] = [
|
||||
IF, THEN, ELSE, WHEN, AS, IS, DBG, IMPORT, EXPECT, EXPECT_FX, CRASH,
|
||||
];
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
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::expr::merge_spaces;
|
||||
use crate::header::{
|
||||
package_entry, package_name, AppHeader, ExposedName, ExposesKeyword, GeneratesKeyword,
|
||||
HostedHeader, ImportsEntry, ImportsKeyword, InterfaceHeader, Keyword, KeywordItem, ModuleName,
|
||||
PackageEntry, PackageHeader, PackagesKeyword, PlatformHeader, PlatformRequires,
|
||||
ProvidesKeyword, ProvidesTo, RequiresKeyword, To, ToKeyword, TypedIdent, WithKeyword,
|
||||
HostedHeader, ImportsCollection, ImportsEntry, ImportsKeyword, ImportsKeywordItem, Keyword,
|
||||
KeywordItem, ModuleHeader, ModuleName, PackageEntry, PackageHeader, PackagesKeyword,
|
||||
PlatformHeader, PlatformRequires, ProvidesKeyword, ProvidesTo, RequiresKeyword, To, ToKeyword,
|
||||
TypedIdent, WithKeyword,
|
||||
};
|
||||
use crate::ident::{self, lowercase_ident, unqualified_ident, uppercase, UppercaseIdent};
|
||||
use crate::parser::Progress::{self, *};
|
||||
|
@ -16,7 +18,7 @@ use crate::parser::{
|
|||
use crate::state::State;
|
||||
use crate::string_literal::{self, parse_str_literal};
|
||||
use crate::type_annotation;
|
||||
use roc_region::all::{Loc, Position};
|
||||
use roc_region::all::{Loc, Position, Region};
|
||||
|
||||
fn end_of_file<'a>() -> impl Parser<'a, (), SyntaxError<'a>> {
|
||||
|_arena, state: State<'a>, _min_indent: u32| {
|
||||
|
@ -60,24 +62,31 @@ pub fn header<'a>() -> impl Parser<'a, Module<'a>, EHeader<'a>> {
|
|||
record!(Module {
|
||||
comments: space0_e(EHeader::IndentStart),
|
||||
header: one_of![
|
||||
map!(
|
||||
skip_first!(
|
||||
keyword("module", EHeader::Start),
|
||||
increment_min_indent(module_header())
|
||||
),
|
||||
Header::Module
|
||||
),
|
||||
map!(
|
||||
skip_first!(
|
||||
keyword("interface", EHeader::Start),
|
||||
increment_min_indent(interface_header())
|
||||
),
|
||||
Header::Interface
|
||||
Header::Module
|
||||
),
|
||||
map!(
|
||||
skip_first!(
|
||||
keyword("app", EHeader::Start),
|
||||
increment_min_indent(app_header())
|
||||
increment_min_indent(one_of![app_header(), old_app_header()])
|
||||
),
|
||||
Header::App
|
||||
),
|
||||
map!(
|
||||
skip_first!(
|
||||
keyword("package", EHeader::Start),
|
||||
increment_min_indent(package_header())
|
||||
increment_min_indent(one_of![package_header(), old_package_header()])
|
||||
),
|
||||
Header::Package
|
||||
),
|
||||
|
@ -100,22 +109,68 @@ pub fn header<'a>() -> impl Parser<'a, Module<'a>, EHeader<'a>> {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn interface_header<'a>() -> impl Parser<'a, InterfaceHeader<'a>, EHeader<'a>> {
|
||||
record!(InterfaceHeader {
|
||||
before_name: space0_e(EHeader::IndentStart),
|
||||
name: loc!(module_name_help(EHeader::ModuleName)),
|
||||
exposes: specialize_err(EHeader::Exposes, exposes_values()),
|
||||
imports: specialize_err(EHeader::Imports, imports()),
|
||||
fn module_header<'a>() -> impl Parser<'a, ModuleHeader<'a>, EHeader<'a>> {
|
||||
record!(ModuleHeader {
|
||||
before_exposes: space0_e(EHeader::IndentStart),
|
||||
exposes: specialize_err(EHeader::Exposes, exposes_list()),
|
||||
interface_imports: succeed!(None)
|
||||
})
|
||||
.trace("module_header")
|
||||
}
|
||||
|
||||
macro_rules! merge_n_spaces {
|
||||
($arena:expr, $($slice:expr),*) => {
|
||||
{
|
||||
let mut merged = bumpalo::collections::Vec::with_capacity_in(0 $(+ $slice.len())*, $arena);
|
||||
$(merged.extend_from_slice($slice);)*
|
||||
merged.into_bump_slice()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// 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>> {
|
||||
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>)| {
|
||||
merge_n_spaces!(arena, before_name, kw.before, kw.after)
|
||||
}
|
||||
);
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
fn imports_none_if_empty(value: ImportsKeywordItem<'_>) -> Option<ImportsKeywordItem<'_>> {
|
||||
if value.item.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn hosted_header<'a>() -> impl Parser<'a, HostedHeader<'a>, EHeader<'a>> {
|
||||
record!(HostedHeader {
|
||||
before_name: space0_e(EHeader::IndentStart),
|
||||
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()),
|
||||
generates: specialize_err(EHeader::Generates, generates()),
|
||||
generates_with: specialize_err(EHeader::GeneratesWith, generates_with()),
|
||||
|
@ -185,29 +240,194 @@ fn module_name<'a>() -> impl Parser<'a, ModuleName<'a>, ()> {
|
|||
#[inline(always)]
|
||||
fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
|
||||
record!(AppHeader {
|
||||
before_name: space0_e(EHeader::IndentStart),
|
||||
name: loc!(crate::parser::specialize_err(
|
||||
EHeader::AppName,
|
||||
string_literal::parse_str_literal()
|
||||
)),
|
||||
packages: optional(specialize_err(EHeader::Packages, packages())),
|
||||
imports: optional(specialize_err(EHeader::Imports, imports())),
|
||||
provides: specialize_err(EHeader::Provides, provides_to()),
|
||||
before_provides: space0_e(EHeader::IndentStart),
|
||||
provides: specialize_err(EHeader::Exposes, exposes_list()),
|
||||
before_packages: space0_e(EHeader::IndentStart),
|
||||
packages: specialize_err(EHeader::Packages, loc!(packages_collection())),
|
||||
old_imports: succeed!(None),
|
||||
old_provides_to_new_package: succeed!(None),
|
||||
})
|
||||
.trace("app_header")
|
||||
}
|
||||
|
||||
struct OldAppHeader<'a> {
|
||||
pub before_name: &'a [CommentOrNewline<'a>],
|
||||
pub packages: Option<Loc<OldAppPackages<'a>>>,
|
||||
pub imports: Option<KeywordItem<'a, ImportsKeyword, ImportsCollection<'a>>>,
|
||||
pub provides: ProvidesTo<'a>,
|
||||
}
|
||||
|
||||
type OldAppPackages<'a> =
|
||||
KeywordItem<'a, PackagesKeyword, Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>>;
|
||||
|
||||
#[inline(always)]
|
||||
fn old_app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
|
||||
let old = record!(OldAppHeader {
|
||||
before_name: skip_second!(
|
||||
space0_e(EHeader::IndentStart),
|
||||
loc!(crate::parser::specialize_err(
|
||||
EHeader::AppName,
|
||||
string_literal::parse_str_literal()
|
||||
))
|
||||
),
|
||||
packages: optional(specialize_err(EHeader::Packages, loc!(packages()))),
|
||||
imports: optional(specialize_err(EHeader::Imports, imports())),
|
||||
provides: specialize_err(EHeader::Provides, provides_to()),
|
||||
});
|
||||
|
||||
map_with_arena!(old, |arena: &'a bumpalo::Bump, old: OldAppHeader<'a>| {
|
||||
let mut before_packages: &'a [CommentOrNewline] = &[];
|
||||
|
||||
let packages = match old.packages {
|
||||
Some(packages) => {
|
||||
before_packages = merge_spaces(
|
||||
arena,
|
||||
packages.value.keyword.before,
|
||||
packages.value.keyword.after,
|
||||
);
|
||||
|
||||
if let To::ExistingPackage(platform_shorthand) = old.provides.to.value {
|
||||
packages.map(|coll| {
|
||||
coll.item.map_items(arena, |loc_spaced_pkg| {
|
||||
if loc_spaced_pkg.value.item().shorthand == platform_shorthand {
|
||||
loc_spaced_pkg.map(|spaced_pkg| {
|
||||
spaced_pkg.map(arena, |pkg| {
|
||||
let mut new_pkg = *pkg;
|
||||
new_pkg.platform_marker = Some(merge_spaces(
|
||||
arena,
|
||||
old.provides.to_keyword.before,
|
||||
old.provides.to_keyword.after,
|
||||
));
|
||||
new_pkg
|
||||
})
|
||||
})
|
||||
} else {
|
||||
*loc_spaced_pkg
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
packages.map(|kw| kw.item)
|
||||
}
|
||||
}
|
||||
None => Loc {
|
||||
region: Region::zero(),
|
||||
value: Collection::empty(),
|
||||
},
|
||||
};
|
||||
|
||||
let provides = match old.provides.types {
|
||||
Some(types) => {
|
||||
let mut combined_items = bumpalo::collections::Vec::with_capacity_in(
|
||||
old.provides.entries.items.len() + types.items.len(),
|
||||
arena,
|
||||
);
|
||||
|
||||
combined_items.extend_from_slice(old.provides.entries.items);
|
||||
|
||||
for loc_spaced_type_ident in types.items {
|
||||
combined_items.push(loc_spaced_type_ident.map(|spaced_type_ident| {
|
||||
spaced_type_ident.map(arena, |type_ident| {
|
||||
ExposedName::new(From::from(*type_ident))
|
||||
})
|
||||
}));
|
||||
}
|
||||
|
||||
let value_comments = old.provides.entries.final_comments();
|
||||
let type_comments = types.final_comments();
|
||||
|
||||
let mut combined_comments = bumpalo::collections::Vec::with_capacity_in(
|
||||
value_comments.len() + type_comments.len(),
|
||||
arena,
|
||||
);
|
||||
combined_comments.extend_from_slice(value_comments);
|
||||
combined_comments.extend_from_slice(type_comments);
|
||||
|
||||
Collection::with_items_and_comments(
|
||||
arena,
|
||||
combined_items.into_bump_slice(),
|
||||
combined_comments.into_bump_slice(),
|
||||
)
|
||||
}
|
||||
None => old.provides.entries,
|
||||
};
|
||||
|
||||
AppHeader {
|
||||
before_provides: merge_spaces(
|
||||
arena,
|
||||
old.before_name,
|
||||
old.provides.provides_keyword.before,
|
||||
),
|
||||
provides,
|
||||
before_packages: merge_spaces(
|
||||
arena,
|
||||
before_packages,
|
||||
old.provides.provides_keyword.after,
|
||||
),
|
||||
packages,
|
||||
old_imports: old.imports.and_then(imports_none_if_empty),
|
||||
old_provides_to_new_package: match old.provides.to.value {
|
||||
To::NewPackage(new_pkg) => Some(new_pkg),
|
||||
To::ExistingPackage(_) => None,
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn package_header<'a>() -> impl Parser<'a, PackageHeader<'a>, EHeader<'a>> {
|
||||
record!(PackageHeader {
|
||||
before_name: space0_e(EHeader::IndentStart),
|
||||
name: loc!(specialize_err(EHeader::PackageName, package_name())),
|
||||
exposes: specialize_err(EHeader::Exposes, exposes_modules()),
|
||||
packages: specialize_err(EHeader::Packages, packages()),
|
||||
before_exposes: space0_e(EHeader::IndentStart),
|
||||
exposes: specialize_err(EHeader::Exposes, exposes_module_collection()),
|
||||
before_packages: space0_e(EHeader::IndentStart),
|
||||
packages: specialize_err(EHeader::Packages, loc!(packages_collection())),
|
||||
})
|
||||
.trace("package_header")
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
struct OldPackageHeader<'a> {
|
||||
before_name: &'a [CommentOrNewline<'a>],
|
||||
exposes: KeywordItem<'a, ExposesKeyword, Collection<'a, Loc<Spaced<'a, ModuleName<'a>>>>>,
|
||||
packages:
|
||||
Loc<KeywordItem<'a, PackagesKeyword, Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>>>,
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn old_package_header<'a>() -> impl Parser<'a, PackageHeader<'a>, EHeader<'a>> {
|
||||
map_with_arena!(
|
||||
record!(OldPackageHeader {
|
||||
before_name: skip_second!(
|
||||
space0_e(EHeader::IndentStart),
|
||||
specialize_err(EHeader::PackageName, package_name())
|
||||
),
|
||||
exposes: specialize_err(EHeader::Exposes, exposes_modules()),
|
||||
packages: specialize_err(EHeader::Packages, loc!(packages())),
|
||||
}),
|
||||
|arena: &'a bumpalo::Bump, old: OldPackageHeader<'a>| {
|
||||
let before_exposes = merge_n_spaces!(
|
||||
arena,
|
||||
old.before_name,
|
||||
old.exposes.keyword.before,
|
||||
old.exposes.keyword.after
|
||||
);
|
||||
let before_packages = merge_spaces(
|
||||
arena,
|
||||
old.packages.value.keyword.before,
|
||||
old.packages.value.keyword.after,
|
||||
);
|
||||
|
||||
PackageHeader {
|
||||
before_exposes,
|
||||
exposes: old.exposes.item,
|
||||
before_packages,
|
||||
packages: old.packages.map(|kw| kw.item),
|
||||
}
|
||||
}
|
||||
)
|
||||
.trace("old_package_header")
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn platform_header<'a>() -> impl Parser<'a, PlatformHeader<'a>, EHeader<'a>> {
|
||||
record!(PlatformHeader {
|
||||
|
@ -388,28 +608,39 @@ fn requires_typed_ident<'a>() -> impl Parser<'a, Loc<Spaced<'a, TypedIdent<'a>>>
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn exposes_values<'a>() -> impl Parser<
|
||||
fn exposes_values_kw<'a>() -> impl Parser<
|
||||
'a,
|
||||
KeywordItem<'a, ExposesKeyword, Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>>,
|
||||
EExposes,
|
||||
> {
|
||||
record!(KeywordItem {
|
||||
keyword: spaces_around_keyword(
|
||||
ExposesKeyword,
|
||||
EExposes::Exposes,
|
||||
EExposes::IndentExposes,
|
||||
EExposes::IndentListStart
|
||||
),
|
||||
item: collection_trailing_sep_e!(
|
||||
byte(b'[', EExposes::ListStart),
|
||||
exposes_entry(EExposes::Identifier),
|
||||
byte(b',', EExposes::ListEnd),
|
||||
byte(b']', EExposes::ListEnd),
|
||||
Spaced::SpaceBefore
|
||||
)
|
||||
keyword: exposes_kw(),
|
||||
item: exposes_list()
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn exposes_kw<'a>() -> impl Parser<'a, Spaces<'a, ExposesKeyword>, EExposes> {
|
||||
spaces_around_keyword(
|
||||
ExposesKeyword,
|
||||
EExposes::Exposes,
|
||||
EExposes::IndentExposes,
|
||||
EExposes::IndentListStart,
|
||||
)
|
||||
}
|
||||
|
||||
#[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),
|
||||
exposes_entry(EExposes::Identifier),
|
||||
byte(b',', EExposes::ListEnd),
|
||||
byte(b']', EExposes::ListEnd),
|
||||
Spaced::SpaceBefore
|
||||
)
|
||||
}
|
||||
|
||||
pub fn spaces_around_keyword<'a, K: Keyword, E>(
|
||||
keyword_item: K,
|
||||
expectation: fn(Position) -> E,
|
||||
|
@ -450,16 +681,21 @@ fn exposes_modules<'a>() -> impl Parser<
|
|||
EExposes::IndentExposes,
|
||||
EExposes::IndentListStart
|
||||
),
|
||||
item: collection_trailing_sep_e!(
|
||||
byte(b'[', EExposes::ListStart),
|
||||
exposes_module(EExposes::Identifier),
|
||||
byte(b',', EExposes::ListEnd),
|
||||
byte(b']', EExposes::ListEnd),
|
||||
Spaced::SpaceBefore
|
||||
),
|
||||
item: exposes_module_collection(),
|
||||
})
|
||||
}
|
||||
|
||||
fn exposes_module_collection<'a>(
|
||||
) -> impl Parser<'a, Collection<'a, Loc<Spaced<'a, ModuleName<'a>>>>, EExposes> {
|
||||
collection_trailing_sep_e!(
|
||||
byte(b'[', EExposes::ListStart),
|
||||
exposes_module(EExposes::Identifier),
|
||||
byte(b',', EExposes::ListEnd),
|
||||
byte(b']', EExposes::ListEnd),
|
||||
Spaced::SpaceBefore
|
||||
)
|
||||
}
|
||||
|
||||
fn exposes_module<'a, F, E>(
|
||||
to_expectation: F,
|
||||
) -> impl Parser<'a, Loc<Spaced<'a, ModuleName<'a>>>, E>
|
||||
|
@ -481,22 +717,33 @@ fn packages<'a>() -> impl Parser<
|
|||
EPackages<'a>,
|
||||
> {
|
||||
record!(KeywordItem {
|
||||
keyword: spaces_around_keyword(
|
||||
PackagesKeyword,
|
||||
EPackages::Packages,
|
||||
EPackages::IndentPackages,
|
||||
EPackages::IndentListStart
|
||||
),
|
||||
item: collection_trailing_sep_e!(
|
||||
byte(b'{', EPackages::ListStart),
|
||||
specialize_err(EPackages::PackageEntry, loc!(package_entry())),
|
||||
byte(b',', EPackages::ListEnd),
|
||||
byte(b'}', EPackages::ListEnd),
|
||||
Spaced::SpaceBefore
|
||||
)
|
||||
keyword: packages_kw(),
|
||||
item: packages_collection()
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn packages_kw<'a>() -> impl Parser<'a, Spaces<'a, PackagesKeyword>, EPackages<'a>> {
|
||||
spaces_around_keyword(
|
||||
PackagesKeyword,
|
||||
EPackages::Packages,
|
||||
EPackages::IndentPackages,
|
||||
EPackages::IndentListStart,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn packages_collection<'a>(
|
||||
) -> impl Parser<'a, Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>, EPackages<'a>> {
|
||||
collection_trailing_sep_e!(
|
||||
byte(b'{', EPackages::ListStart),
|
||||
specialize_err(EPackages::PackageEntry, loc!(package_entry())),
|
||||
byte(b',', EPackages::ListEnd),
|
||||
byte(b'}', EPackages::ListEnd),
|
||||
Spaced::SpaceBefore
|
||||
)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn generates<'a>(
|
||||
) -> impl Parser<'a, KeywordItem<'a, GeneratesKeyword, UppercaseIdent<'a>>, EGenerates> {
|
||||
|
|
|
@ -211,6 +211,8 @@ pub enum EPackageEntry<'a> {
|
|||
Shorthand(Position),
|
||||
Colon(Position),
|
||||
IndentPackage(Position),
|
||||
IndentPlatform(Position),
|
||||
Platform(Position),
|
||||
Space(BadInputError, Position),
|
||||
}
|
||||
|
||||
|
|
|
@ -37,4 +37,4 @@
|
|||
":="
|
||||
":"
|
||||
"@"
|
||||
"->"
|
||||
"->"
|
||||
|
|
|
@ -170,7 +170,9 @@ impl<'a> Input<'a> {
|
|||
.parse(arena, state.clone(), min_indent)
|
||||
.map_err(|(_, fail)| SyntaxError::Header(fail))?;
|
||||
|
||||
let module_defs = parse_module_defs(arena, state, Defs::default()).unwrap();
|
||||
let (header, defs) = header.upgrade_header_imports(arena);
|
||||
|
||||
let module_defs = parse_module_defs(arena, state, defs).unwrap();
|
||||
|
||||
Ok(Output::Full {
|
||||
header,
|
||||
|
|
|
@ -1 +1 @@
|
|||
Header(Imports(ListEnd(@87), @65))
|
||||
Header(Exposes(ListEnd(@11), @4))
|
|
@ -1,4 +1 @@
|
|||
app "test-missing-comma"
|
||||
packages { pf: "platform/main.roc" }
|
||||
imports [pf.Task Base64]
|
||||
provides [main, @Foo] to pf
|
||||
app [main, @Foo] { pf: platform "platform/main.roc" }
|
||||
|
|
|
@ -1 +1 @@
|
|||
app "test-app" packages {} imports [] provides [] to blah
|
||||
app [] {}
|
||||
|
|
|
@ -2,47 +2,12 @@ Module {
|
|||
comments: [],
|
||||
header: App(
|
||||
AppHeader {
|
||||
before_name: [],
|
||||
name: @4-14 PlainLine(
|
||||
"test-app",
|
||||
),
|
||||
packages: Some(
|
||||
KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [],
|
||||
item: PackagesKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [],
|
||||
},
|
||||
),
|
||||
imports: Some(
|
||||
KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [],
|
||||
item: ImportsKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [],
|
||||
},
|
||||
),
|
||||
provides: ProvidesTo {
|
||||
provides_keyword: Spaces {
|
||||
before: [],
|
||||
item: ProvidesKeyword,
|
||||
after: [],
|
||||
},
|
||||
entries: [],
|
||||
types: None,
|
||||
to_keyword: Spaces {
|
||||
before: [],
|
||||
item: ToKeyword,
|
||||
after: [],
|
||||
},
|
||||
to: @53-57 ExistingPackage(
|
||||
"blah",
|
||||
),
|
||||
},
|
||||
before_provides: [],
|
||||
provides: [],
|
||||
before_packages: [],
|
||||
packages: @14-26 [],
|
||||
old_imports: None,
|
||||
old_provides_to_new_package: None,
|
||||
},
|
||||
),
|
||||
}
|
||||
|
|
|
@ -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 +1 @@
|
|||
package "rtfeldman/blah" exposes [] packages {}
|
||||
package [] {}
|
||||
|
|
|
@ -2,26 +2,10 @@ Module {
|
|||
comments: [],
|
||||
header: Package(
|
||||
PackageHeader {
|
||||
before_name: [],
|
||||
name: @8-24 PackageName(
|
||||
"rtfeldman/blah",
|
||||
),
|
||||
exposes: KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [],
|
||||
item: ExposesKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [],
|
||||
},
|
||||
packages: KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [],
|
||||
item: PackagesKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [],
|
||||
},
|
||||
before_exposes: [],
|
||||
exposes: [],
|
||||
before_packages: [],
|
||||
packages: @11-13 [],
|
||||
},
|
||||
),
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
package "rtfeldman/blah" exposes [] packages {}
|
||||
package [] {}
|
||||
|
|
|
@ -1,4 +1 @@
|
|||
app "quicksort"
|
||||
packages { pf: "./platform" }
|
||||
imports [foo.Bar.Baz]
|
||||
provides [quicksort] to pf
|
||||
app [quicksort] { pf: platform "./platform" }
|
||||
|
|
|
@ -2,73 +2,27 @@ Module {
|
|||
comments: [],
|
||||
header: App(
|
||||
AppHeader {
|
||||
before_name: [],
|
||||
name: @4-15 PlainLine(
|
||||
"quicksort",
|
||||
),
|
||||
packages: Some(
|
||||
KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: PackagesKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [
|
||||
@31-47 PackageEntry {
|
||||
shorthand: "pf",
|
||||
spaces_after_shorthand: [],
|
||||
package_name: @35-47 PackageName(
|
||||
"./platform",
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
imports: Some(
|
||||
KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: ImportsKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [
|
||||
@64-75 Package(
|
||||
"foo",
|
||||
ModuleName(
|
||||
"Bar.Baz",
|
||||
),
|
||||
[],
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
provides: ProvidesTo {
|
||||
provides_keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: ProvidesKeyword,
|
||||
after: [],
|
||||
},
|
||||
entries: [
|
||||
@93-102 ExposedName(
|
||||
"quicksort",
|
||||
),
|
||||
],
|
||||
types: None,
|
||||
to_keyword: Spaces {
|
||||
before: [],
|
||||
item: ToKeyword,
|
||||
after: [],
|
||||
},
|
||||
to: @108-110 ExistingPackage(
|
||||
"pf",
|
||||
before_provides: [],
|
||||
provides: [
|
||||
@6-15 ExposedName(
|
||||
"quicksort",
|
||||
),
|
||||
},
|
||||
],
|
||||
before_packages: [],
|
||||
packages: @18-47 [
|
||||
@20-45 PackageEntry {
|
||||
shorthand: "pf",
|
||||
spaces_after_shorthand: [],
|
||||
platform_marker: Some(
|
||||
[],
|
||||
),
|
||||
package_name: @33-45 PackageName(
|
||||
"./platform",
|
||||
),
|
||||
},
|
||||
],
|
||||
old_imports: None,
|
||||
old_provides_to_new_package: None,
|
||||
},
|
||||
),
|
||||
}
|
||||
|
|
|
@ -1,4 +1 @@
|
|||
app "quicksort"
|
||||
packages { pf: "./platform" }
|
||||
imports [ foo.Bar.Baz ]
|
||||
provides [ quicksort ] to pf
|
||||
app [ quicksort ] { pf: platform "./platform" }
|
||||
|
|
|
@ -1,8 +1 @@
|
|||
app "quicksort"
|
||||
packages { pf: "./platform" }
|
||||
imports [foo.Bar.{
|
||||
Baz,
|
||||
FortyTwo,
|
||||
# I'm a happy comment
|
||||
}]
|
||||
provides [quicksort] to pf
|
||||
app [quicksort] { pf: platform "./platform" }
|
||||
|
|
|
@ -2,98 +2,27 @@ Module {
|
|||
comments: [],
|
||||
header: App(
|
||||
AppHeader {
|
||||
before_name: [],
|
||||
name: @4-15 PlainLine(
|
||||
"quicksort",
|
||||
),
|
||||
packages: Some(
|
||||
KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: PackagesKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [
|
||||
@31-47 PackageEntry {
|
||||
shorthand: "pf",
|
||||
spaces_after_shorthand: [],
|
||||
package_name: @35-47 PackageName(
|
||||
"./platform",
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
imports: Some(
|
||||
KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: ImportsKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [
|
||||
@65-141 Package(
|
||||
"foo",
|
||||
ModuleName(
|
||||
"Bar",
|
||||
),
|
||||
Collection {
|
||||
items: [
|
||||
@83-86 SpaceBefore(
|
||||
ExposedName(
|
||||
"Baz",
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
@96-104 SpaceBefore(
|
||||
ExposedName(
|
||||
"FortyTwo",
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
final_comments: [
|
||||
Newline,
|
||||
LineComment(
|
||||
" I'm a happy comment",
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
provides: ProvidesTo {
|
||||
provides_keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: ProvidesKeyword,
|
||||
after: [],
|
||||
},
|
||||
entries: [
|
||||
@159-168 ExposedName(
|
||||
"quicksort",
|
||||
),
|
||||
],
|
||||
types: None,
|
||||
to_keyword: Spaces {
|
||||
before: [],
|
||||
item: ToKeyword,
|
||||
after: [],
|
||||
},
|
||||
to: @175-177 ExistingPackage(
|
||||
"pf",
|
||||
before_provides: [],
|
||||
provides: [
|
||||
@6-15 ExposedName(
|
||||
"quicksort",
|
||||
),
|
||||
},
|
||||
],
|
||||
before_packages: [],
|
||||
packages: @19-49 [
|
||||
@21-46 PackageEntry {
|
||||
shorthand: "pf",
|
||||
spaces_after_shorthand: [],
|
||||
platform_marker: Some(
|
||||
[],
|
||||
),
|
||||
package_name: @34-46 PackageName(
|
||||
"./platform",
|
||||
),
|
||||
},
|
||||
],
|
||||
old_imports: None,
|
||||
old_provides_to_new_package: None,
|
||||
},
|
||||
),
|
||||
}
|
||||
|
|
|
@ -1,8 +1 @@
|
|||
app "quicksort"
|
||||
packages { pf: "./platform", }
|
||||
imports [ foo.Bar.{
|
||||
Baz,
|
||||
FortyTwo,
|
||||
# I'm a happy comment
|
||||
} ]
|
||||
provides [ quicksort, ] to pf
|
||||
app [ quicksort, ] { pf: platform "./platform", }
|
||||
|
|
|
@ -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 []
|
|
@ -1 +1 @@
|
|||
app "test-app" provides [] to "./blah"
|
||||
app [] {}
|
||||
|
|
|
@ -2,31 +2,12 @@ Module {
|
|||
comments: [],
|
||||
header: App(
|
||||
AppHeader {
|
||||
before_name: [],
|
||||
name: @4-14 PlainLine(
|
||||
"test-app",
|
||||
),
|
||||
packages: None,
|
||||
imports: None,
|
||||
provides: ProvidesTo {
|
||||
provides_keyword: Spaces {
|
||||
before: [],
|
||||
item: ProvidesKeyword,
|
||||
after: [],
|
||||
},
|
||||
entries: [],
|
||||
types: None,
|
||||
to_keyword: Spaces {
|
||||
before: [],
|
||||
item: ToKeyword,
|
||||
after: [],
|
||||
},
|
||||
to: @30-38 NewPackage(
|
||||
PackageName(
|
||||
"./blah",
|
||||
),
|
||||
),
|
||||
},
|
||||
before_provides: [],
|
||||
provides: [],
|
||||
before_packages: [],
|
||||
packages: @7-9 [],
|
||||
old_imports: None,
|
||||
old_provides_to_new_package: None,
|
||||
},
|
||||
),
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
app "test-app" provides [] to "./blah"
|
||||
app [] {}
|
||||
|
|
|
@ -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 []
|
|
@ -1,10 +1,7 @@
|
|||
app "hello"
|
||||
packages {
|
||||
pf:
|
||||
app [main] {
|
||||
pf:
|
||||
"https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br",
|
||||
}
|
||||
imports [pf.Stdout]
|
||||
provides [main] to pf
|
||||
}
|
||||
|
||||
main =
|
||||
Stdout.line "I'm a Roc application!"
|
||||
|
|
|
@ -3,80 +3,32 @@ Full {
|
|||
comments: [],
|
||||
header: App(
|
||||
AppHeader {
|
||||
before_name: [],
|
||||
name: @4-11 PlainLine(
|
||||
"hello",
|
||||
),
|
||||
packages: Some(
|
||||
KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [
|
||||
before_provides: [],
|
||||
provides: [
|
||||
@5-9 ExposedName(
|
||||
"main",
|
||||
),
|
||||
],
|
||||
before_packages: [],
|
||||
packages: @11-134 [
|
||||
@13-132 SpaceAfter(
|
||||
PackageEntry {
|
||||
shorthand: "pf",
|
||||
spaces_after_shorthand: [
|
||||
Newline,
|
||||
],
|
||||
item: PackagesKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [
|
||||
@27-146 SpaceAfter(
|
||||
PackageEntry {
|
||||
shorthand: "pf",
|
||||
spaces_after_shorthand: [
|
||||
Newline,
|
||||
],
|
||||
package_name: @31-146 PackageName(
|
||||
"https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br",
|
||||
),
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
platform_marker: None,
|
||||
package_name: @17-132 PackageName(
|
||||
"https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br",
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
imports: Some(
|
||||
KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: ImportsKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [
|
||||
@162-171 Package(
|
||||
"pf",
|
||||
ModuleName(
|
||||
"Stdout",
|
||||
),
|
||||
[],
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
provides: ProvidesTo {
|
||||
provides_keyword: Spaces {
|
||||
before: [
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
item: ProvidesKeyword,
|
||||
after: [],
|
||||
},
|
||||
entries: [
|
||||
@187-191 ExposedName(
|
||||
"main",
|
||||
),
|
||||
],
|
||||
types: None,
|
||||
to_keyword: Spaces {
|
||||
before: [],
|
||||
item: ToKeyword,
|
||||
after: [],
|
||||
},
|
||||
to: @196-198 ExistingPackage(
|
||||
"pf",
|
||||
),
|
||||
},
|
||||
],
|
||||
old_imports: None,
|
||||
old_provides_to_new_package: None,
|
||||
},
|
||||
),
|
||||
},
|
||||
|
@ -85,7 +37,7 @@ Full {
|
|||
Index(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@200-247,
|
||||
@136-183,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 2),
|
||||
|
@ -100,17 +52,17 @@ Full {
|
|||
type_defs: [],
|
||||
value_defs: [
|
||||
Body(
|
||||
@200-204 Identifier {
|
||||
@136-140 Identifier {
|
||||
ident: "main",
|
||||
},
|
||||
@211-247 SpaceBefore(
|
||||
@147-183 SpaceBefore(
|
||||
Apply(
|
||||
@211-222 Var {
|
||||
@147-158 Var {
|
||||
module_name: "Stdout",
|
||||
ident: "line",
|
||||
},
|
||||
[
|
||||
@223-247 Str(
|
||||
@159-183 Str(
|
||||
PlainLine(
|
||||
"I'm a Roc application!",
|
||||
),
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
app "hello"
|
||||
packages { pf:
|
||||
app [main] { pf:
|
||||
"https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br"
|
||||
}
|
||||
imports [pf.Stdout]
|
||||
provides [main] to pf
|
||||
|
||||
main =
|
||||
Stdout.line "I'm a Roc application!"
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
package "foo/barbaz"
|
||||
exposes [Foo, Bar]
|
||||
packages { foo: "./foo" }
|
||||
package [Foo, Bar] {
|
||||
foo: "./foo",
|
||||
}
|
||||
|
|
|
@ -2,45 +2,36 @@ Module {
|
|||
comments: [],
|
||||
header: Package(
|
||||
PackageHeader {
|
||||
before_name: [],
|
||||
name: @8-20 PackageName(
|
||||
"foo/barbaz",
|
||||
),
|
||||
exposes: KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [
|
||||
before_exposes: [],
|
||||
exposes: [
|
||||
@9-12 ModuleName(
|
||||
"Foo",
|
||||
),
|
||||
@14-17 ModuleName(
|
||||
"Bar",
|
||||
),
|
||||
],
|
||||
before_packages: [],
|
||||
packages: @19-39 [
|
||||
@25-37 SpaceBefore(
|
||||
SpaceAfter(
|
||||
PackageEntry {
|
||||
shorthand: "foo",
|
||||
spaces_after_shorthand: [],
|
||||
platform_marker: None,
|
||||
package_name: @30-37 PackageName(
|
||||
"./foo",
|
||||
),
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
item: ExposesKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [
|
||||
@34-37 ModuleName(
|
||||
"Foo",
|
||||
),
|
||||
@39-42 ModuleName(
|
||||
"Bar",
|
||||
),
|
||||
],
|
||||
},
|
||||
packages: KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: PackagesKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [
|
||||
@59-71 PackageEntry {
|
||||
shorthand: "foo",
|
||||
spaces_after_shorthand: [],
|
||||
package_name: @64-71 PackageName(
|
||||
"./foo",
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
package "foo/barbaz"
|
||||
exposes [Foo, Bar]
|
||||
packages { foo: "./foo" }
|
||||
package [Foo, Bar] {
|
||||
foo: "./foo"
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ Module {
|
|||
@87-99 PackageEntry {
|
||||
shorthand: "foo",
|
||||
spaces_after_shorthand: [],
|
||||
platform_marker: None,
|
||||
package_name: @92-99 PackageName(
|
||||
"./foo",
|
||||
),
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
app [main] {
|
||||
cli: platform "../basic-cli/platform/main.roc",
|
||||
}
|
||||
|
||||
import cli.Stdout
|
||||
|
||||
main =
|
||||
Stdout.line "hello"
|
|
@ -0,0 +1,114 @@
|
|||
Full {
|
||||
header: Module {
|
||||
comments: [],
|
||||
header: App(
|
||||
AppHeader {
|
||||
before_provides: [
|
||||
Newline,
|
||||
],
|
||||
provides: [
|
||||
@143-147 ExposedName(
|
||||
"main",
|
||||
),
|
||||
],
|
||||
before_packages: [
|
||||
Newline,
|
||||
],
|
||||
packages: @20-88 Collection {
|
||||
items: [
|
||||
@44-81 SpaceBefore(
|
||||
PackageEntry {
|
||||
shorthand: "cli",
|
||||
spaces_after_shorthand: [],
|
||||
platform_marker: Some(
|
||||
[],
|
||||
),
|
||||
package_name: @49-81 PackageName(
|
||||
"../basic-cli/platform/main.roc",
|
||||
),
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
final_comments: [
|
||||
Newline,
|
||||
],
|
||||
},
|
||||
old_imports: None,
|
||||
old_provides_to_new_package: None,
|
||||
},
|
||||
),
|
||||
},
|
||||
module_defs: Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
Index(2147483649),
|
||||
],
|
||||
regions: [
|
||||
@111-121,
|
||||
@157-187,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 3),
|
||||
Slice(start = 6, length = 2),
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 3, length = 3),
|
||||
Slice(start = 8, length = 0),
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
ModuleImport(
|
||||
ModuleImport {
|
||||
before_name: [],
|
||||
name: @111-121 ImportedModuleName {
|
||||
package: Some(
|
||||
"cli",
|
||||
),
|
||||
name: ModuleName(
|
||||
"Stdout",
|
||||
),
|
||||
},
|
||||
alias: None,
|
||||
exposed: None,
|
||||
},
|
||||
),
|
||||
Body(
|
||||
@157-161 Identifier {
|
||||
ident: "main",
|
||||
},
|
||||
@168-187 SpaceBefore(
|
||||
Apply(
|
||||
@168-179 Var {
|
||||
module_name: "Stdout",
|
||||
ident: "line",
|
||||
},
|
||||
[
|
||||
@180-187 Str(
|
||||
PlainLine(
|
||||
"hello",
|
||||
),
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
},
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
app "old-app-header"
|
||||
packages {
|
||||
cli: "../basic-cli/platform/main.roc",
|
||||
}
|
||||
imports [
|
||||
cli.Stdout,
|
||||
]
|
||||
provides [main] to cli
|
||||
|
||||
main =
|
||||
Stdout.line "hello"
|
||||
|
|
@ -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 []
|
|
@ -1,4 +1 @@
|
|||
app "test"
|
||||
packages { pf: "./platform" }
|
||||
imports [foo.Bar.Baz]
|
||||
provides [quicksort] { Flags, Model } to pf
|
||||
app [quicksort, Flags, Model] { pf: "./platform" }
|
||||
|
|
|
@ -2,82 +2,31 @@ Module {
|
|||
comments: [],
|
||||
header: App(
|
||||
AppHeader {
|
||||
before_name: [],
|
||||
name: @4-10 PlainLine(
|
||||
"test",
|
||||
),
|
||||
packages: Some(
|
||||
KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: PackagesKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [
|
||||
@26-42 PackageEntry {
|
||||
shorthand: "pf",
|
||||
spaces_after_shorthand: [],
|
||||
package_name: @30-42 PackageName(
|
||||
"./platform",
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
imports: Some(
|
||||
KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: ImportsKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [
|
||||
@59-70 Package(
|
||||
"foo",
|
||||
ModuleName(
|
||||
"Bar.Baz",
|
||||
),
|
||||
[],
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
provides: ProvidesTo {
|
||||
provides_keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: ProvidesKeyword,
|
||||
after: [],
|
||||
},
|
||||
entries: [
|
||||
@88-97 ExposedName(
|
||||
"quicksort",
|
||||
before_provides: [],
|
||||
provides: [
|
||||
@5-14 ExposedName(
|
||||
"quicksort",
|
||||
),
|
||||
@16-21 ExposedName(
|
||||
"Flags",
|
||||
),
|
||||
@23-28 ExposedName(
|
||||
"Model",
|
||||
),
|
||||
],
|
||||
before_packages: [],
|
||||
packages: @30-50 [
|
||||
@32-48 PackageEntry {
|
||||
shorthand: "pf",
|
||||
spaces_after_shorthand: [],
|
||||
platform_marker: None,
|
||||
package_name: @36-48 PackageName(
|
||||
"./platform",
|
||||
),
|
||||
],
|
||||
types: Some(
|
||||
[
|
||||
@102-107 UppercaseIdent(
|
||||
"Flags",
|
||||
),
|
||||
@109-114 UppercaseIdent(
|
||||
"Model",
|
||||
),
|
||||
],
|
||||
),
|
||||
to_keyword: Spaces {
|
||||
before: [],
|
||||
item: ToKeyword,
|
||||
after: [],
|
||||
},
|
||||
to: @121-123 ExistingPackage(
|
||||
"pf",
|
||||
),
|
||||
},
|
||||
],
|
||||
old_imports: None,
|
||||
old_provides_to_new_package: None,
|
||||
},
|
||||
),
|
||||
}
|
||||
|
|
|
@ -1,4 +1 @@
|
|||
app "test"
|
||||
packages { pf: "./platform" }
|
||||
imports [ foo.Bar.Baz ]
|
||||
provides [ quicksort ] { Flags, Model, } to pf
|
||||
app [quicksort, Flags, Model] { pf: "./platform" }
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
app "example"
|
||||
packages { pf: "path" }
|
||||
imports [pf.Stdout]
|
||||
provides [main] to pf
|
||||
app [main] { pf: platform "path" }
|
||||
|
||||
main = Stdout.line "Hello"
|
||||
|
|
|
@ -3,73 +3,27 @@ Full {
|
|||
comments: [],
|
||||
header: App(
|
||||
AppHeader {
|
||||
before_name: [],
|
||||
name: @4-13 PlainLine(
|
||||
"example",
|
||||
),
|
||||
packages: Some(
|
||||
KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: PackagesKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [
|
||||
@29-40 PackageEntry {
|
||||
shorthand: "pf",
|
||||
spaces_after_shorthand: [],
|
||||
package_name: @34-40 PackageName(
|
||||
"path",
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
imports: Some(
|
||||
KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: ImportsKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: [
|
||||
@57-66 Package(
|
||||
"pf",
|
||||
ModuleName(
|
||||
"Stdout",
|
||||
),
|
||||
[],
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
provides: ProvidesTo {
|
||||
provides_keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: ProvidesKeyword,
|
||||
after: [],
|
||||
},
|
||||
entries: [
|
||||
@84-88 ExposedName(
|
||||
"main",
|
||||
),
|
||||
],
|
||||
types: None,
|
||||
to_keyword: Spaces {
|
||||
before: [],
|
||||
item: ToKeyword,
|
||||
after: [],
|
||||
},
|
||||
to: @94-96 ExistingPackage(
|
||||
"pf",
|
||||
before_provides: [],
|
||||
provides: [
|
||||
@6-10 ExposedName(
|
||||
"main",
|
||||
),
|
||||
},
|
||||
],
|
||||
before_packages: [],
|
||||
packages: @13-37 [
|
||||
@15-35 PackageEntry {
|
||||
shorthand: "pf",
|
||||
spaces_after_shorthand: [],
|
||||
platform_marker: Some(
|
||||
[],
|
||||
),
|
||||
package_name: @29-35 PackageName(
|
||||
"path",
|
||||
),
|
||||
},
|
||||
],
|
||||
old_imports: None,
|
||||
old_provides_to_new_package: None,
|
||||
},
|
||||
),
|
||||
},
|
||||
|
@ -78,7 +32,7 @@ Full {
|
|||
Index(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@98-124,
|
||||
@39-65,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 2),
|
||||
|
@ -93,16 +47,16 @@ Full {
|
|||
type_defs: [],
|
||||
value_defs: [
|
||||
Body(
|
||||
@98-102 Identifier {
|
||||
@39-43 Identifier {
|
||||
ident: "main",
|
||||
},
|
||||
@105-124 Apply(
|
||||
@105-116 Var {
|
||||
@46-65 Apply(
|
||||
@46-57 Var {
|
||||
module_name: "Stdout",
|
||||
ident: "line",
|
||||
},
|
||||
[
|
||||
@117-124 Str(
|
||||
@58-65 Str(
|
||||
PlainLine(
|
||||
"Hello",
|
||||
),
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
app "example"
|
||||
packages { pf : "path" }
|
||||
imports [ pf.Stdout ]
|
||||
provides [ main ] to pf
|
||||
app [ main ] { pf : platform "path" }
|
||||
|
||||
main = Stdout.line "Hello"
|
||||
main = Stdout.line "Hello"
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
app "desugar-bang"
|
||||
packages {
|
||||
cli: "../basic-cli/platform/main.roc",
|
||||
}
|
||||
imports [
|
||||
cli.Stdout,
|
||||
]
|
||||
provides [main] to cli
|
||||
app [main] {
|
||||
cli: "../basic-cli/platform/main.roc",
|
||||
}
|
||||
|
||||
import cli.Stdout
|
||||
|
||||
main =
|
||||
# is this a valid statement?
|
||||
|
|
|
@ -3,120 +3,83 @@ Full {
|
|||
comments: [],
|
||||
header: App(
|
||||
AppHeader {
|
||||
before_name: [],
|
||||
name: @4-18 PlainLine(
|
||||
"desugar-bang",
|
||||
),
|
||||
packages: Some(
|
||||
KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: PackagesKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: Collection {
|
||||
items: [
|
||||
@42-79 SpaceBefore(
|
||||
PackageEntry {
|
||||
shorthand: "cli",
|
||||
spaces_after_shorthand: [],
|
||||
package_name: @47-79 PackageName(
|
||||
"../basic-cli/platform/main.roc",
|
||||
),
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
before_provides: [],
|
||||
provides: [
|
||||
@5-9 ExposedName(
|
||||
"main",
|
||||
),
|
||||
],
|
||||
before_packages: [],
|
||||
packages: @11-55 Collection {
|
||||
items: [
|
||||
@15-52 SpaceBefore(
|
||||
PackageEntry {
|
||||
shorthand: "cli",
|
||||
spaces_after_shorthand: [],
|
||||
platform_marker: None,
|
||||
package_name: @20-52 PackageName(
|
||||
"../basic-cli/platform/main.roc",
|
||||
),
|
||||
],
|
||||
final_comments: [
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
},
|
||||
},
|
||||
),
|
||||
imports: Some(
|
||||
KeywordItem {
|
||||
keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: ImportsKeyword,
|
||||
after: [],
|
||||
},
|
||||
item: Collection {
|
||||
items: [
|
||||
@109-119 SpaceBefore(
|
||||
Package(
|
||||
"cli",
|
||||
ModuleName(
|
||||
"Stdout",
|
||||
),
|
||||
[],
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
final_comments: [
|
||||
Newline,
|
||||
],
|
||||
},
|
||||
},
|
||||
),
|
||||
provides: ProvidesTo {
|
||||
provides_keyword: Spaces {
|
||||
before: [
|
||||
Newline,
|
||||
],
|
||||
item: ProvidesKeyword,
|
||||
after: [],
|
||||
},
|
||||
entries: [
|
||||
@141-145 ExposedName(
|
||||
"main",
|
||||
),
|
||||
],
|
||||
types: None,
|
||||
to_keyword: Spaces {
|
||||
before: [],
|
||||
item: ToKeyword,
|
||||
after: [],
|
||||
},
|
||||
to: @150-153 ExistingPackage(
|
||||
"cli",
|
||||
),
|
||||
final_comments: [
|
||||
Newline,
|
||||
],
|
||||
},
|
||||
old_imports: None,
|
||||
old_provides_to_new_package: None,
|
||||
},
|
||||
),
|
||||
},
|
||||
module_defs: Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
Index(2147483649),
|
||||
],
|
||||
regions: [
|
||||
@155-299,
|
||||
@57-74,
|
||||
@76-220,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 2),
|
||||
Slice(start = 2, length = 2),
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 2, length = 0),
|
||||
Slice(start = 4, length = 0),
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
ModuleImport(
|
||||
ModuleImport {
|
||||
before_name: [],
|
||||
name: @64-74 ImportedModuleName {
|
||||
package: Some(
|
||||
"cli",
|
||||
),
|
||||
name: ModuleName(
|
||||
"Stdout",
|
||||
),
|
||||
},
|
||||
alias: None,
|
||||
exposed: None,
|
||||
},
|
||||
),
|
||||
Body(
|
||||
@155-159 Identifier {
|
||||
@76-80 Identifier {
|
||||
ident: "main",
|
||||
},
|
||||
@199-299 SpaceBefore(
|
||||
@120-220 SpaceBefore(
|
||||
Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
|
@ -124,8 +87,8 @@ Full {
|
|||
Index(2147483649),
|
||||
],
|
||||
regions: [
|
||||
@199-211,
|
||||
@241-284,
|
||||
@120-132,
|
||||
@162-205,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
|
@ -139,18 +102,18 @@ Full {
|
|||
type_defs: [],
|
||||
value_defs: [
|
||||
Stmt(
|
||||
@199-211 BinOps(
|
||||
@120-132 BinOps(
|
||||
[
|
||||
(
|
||||
@199-204 Str(
|
||||
@120-125 Str(
|
||||
PlainLine(
|
||||
"Foo",
|
||||
),
|
||||
),
|
||||
@205-207 Pizza,
|
||||
@126-128 Pizza,
|
||||
),
|
||||
],
|
||||
@208-211 TaskAwaitBang(
|
||||
@129-132 TaskAwaitBang(
|
||||
Var {
|
||||
module_name: "A",
|
||||
ident: "x",
|
||||
|
@ -159,33 +122,33 @@ Full {
|
|||
),
|
||||
),
|
||||
Stmt(
|
||||
@241-284 SpaceBefore(
|
||||
@162-205 SpaceBefore(
|
||||
BinOps(
|
||||
[
|
||||
(
|
||||
@241-246 Str(
|
||||
@162-167 Str(
|
||||
PlainLine(
|
||||
"Bar",
|
||||
),
|
||||
),
|
||||
@247-249 Pizza,
|
||||
@168-170 Pizza,
|
||||
),
|
||||
],
|
||||
@250-284 Apply(
|
||||
@250-253 TaskAwaitBang(
|
||||
@171-205 Apply(
|
||||
@171-174 TaskAwaitBang(
|
||||
Var {
|
||||
module_name: "B",
|
||||
ident: "y",
|
||||
},
|
||||
),
|
||||
[
|
||||
@264-284 SpaceBefore(
|
||||
@185-205 SpaceBefore(
|
||||
Record(
|
||||
[
|
||||
@266-282 RequiredValue(
|
||||
@266-272 "config",
|
||||
@187-203 RequiredValue(
|
||||
@187-193 "config",
|
||||
[],
|
||||
@274-282 Str(
|
||||
@195-203 Str(
|
||||
PlainLine(
|
||||
"config",
|
||||
),
|
||||
|
@ -212,14 +175,14 @@ Full {
|
|||
),
|
||||
],
|
||||
},
|
||||
@290-299 SpaceBefore(
|
||||
@211-220 SpaceBefore(
|
||||
Apply(
|
||||
@290-293 Var {
|
||||
@211-214 Var {
|
||||
module_name: "C",
|
||||
ident: "z",
|
||||
},
|
||||
[
|
||||
@294-299 Str(
|
||||
@215-220 Str(
|
||||
PlainLine(
|
||||
"Bar",
|
||||
),
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue