Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(compiler)!: Require module prefix on use/provide for modules #1868

Merged
merged 1 commit into from
Jul 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions compiler/src/formatting/format.re
Original file line number Diff line number Diff line change
Expand Up @@ -3956,8 +3956,9 @@ and print_expression_inner =
};

switch (item) {
| PUseValue({name, alias})
| PUseModule({name, alias}) => item_name(name, alias)
| PUseValue({name, alias}) => item_name(name, alias)
| PUseModule({name, alias}) =>
Doc.concat([Doc.text("module "), item_name(name, alias)])
| PUseType({name, alias}) =>
Doc.concat([Doc.text("type "), item_name(name, alias)])
};
Expand Down Expand Up @@ -5106,8 +5107,9 @@ let rec toplevel_print =
};

switch (item) {
| PProvideValue({name, alias})
| PProvideModule({name, alias}) => item_name(name, alias)
| PProvideValue({name, alias}) => item_name(name, alias)
| PProvideModule({name, alias}) =>
Doc.concat([Doc.text("module "), item_name(name, alias)])
| PProvideType({name, alias}) =>
Doc.concat([Doc.text("type "), item_name(name, alias)])
};
Expand Down
40 changes: 29 additions & 11 deletions compiler/src/parsing/parser.messages
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ program: MODULE UIDENT EOL INCLUDE STRING AS YIELD
## The known suffix of the stack is as follows:
## AS
##
program: MODULE UIDENT EOL PROVIDE LBRACE MODULE YIELD
##
## Ends in an error in state: 829.
##
## provide_item -> MODULE . aliasable(uid) [ RBRACE EOL COMMA ]
##
## The known suffix of the stack is as follows:
## MODULE
##

Expected an uppercase module identifier.

Expand Down Expand Up @@ -269,22 +278,21 @@ program: MODULE UIDENT EOL FOREIGN WASM LIDENT COLON UIDENT AS YIELD
## The known suffix of the stack is as follows:
## AS
##
program: MODULE UIDENT EOL PROVIDE LBRACE UIDENT AS EOL YIELD
program: MODULE UIDENT EOL PROVIDE LBRACE MODULE UIDENT AS EOL YIELD
##
## Ends in an error in state: 51.
## Ends in an error in state: 52.
##
## as_prefix(uid) -> AS option(eols) . uid [ RBRACE EOL COMMA ]
## as_prefix(uid) -> AS eols . uid [ RBRACE EOL COMMA ]
##
## The known suffix of the stack is as follows:
## AS option(eols)
## AS eols
##
## WARNING: This example involves spurious reductions.
## This implies that, although the LR(1) items shown above provide an
## accurate view of the past (what has been recognized so far), they
## may provide an INCOMPLETE view of the future (what was expected next).
## In state 3, spurious reduction of production nonempty_list(eol) -> EOL
## In state 6, spurious reduction of production eols -> nonempty_list(eol)
## In state 53, spurious reduction of production option(eols) -> eols
##
program: MODULE UIDENT EOL PROVIDE LBRACE LIDENT AS EOL YIELD
##
Expand Down Expand Up @@ -424,7 +432,7 @@ program: MODULE UIDENT EOL FROM UIDENT USE LBRACE YIELD
## In state 31, spurious reduction of production lbrace -> LBRACE
##

Expected a lowercase identifier to use a value, an uppercase identifier to use a module, or the keyword `type` followed by an uppercase identifier to use a type.
Expected a lowercase identifier to use a value, the keyword `module` followed by an uppercase identifier to use a module, or the keyword `type` followed by an uppercase identifier to use a type.

program: MODULE UIDENT EOL FROM UIDENT USE LBRACE TYPE YIELD
##
Expand All @@ -435,10 +443,19 @@ program: MODULE UIDENT EOL FROM UIDENT USE LBRACE TYPE YIELD
## The known suffix of the stack is as follows:
## TYPE
##
program: MODULE UIDENT EOL FROM UIDENT USE LBRACE MODULE YIELD
##
## Ends in an error in state: 57.
##
## use_item -> MODULE . aliasable(uid) [ RBRACE EOL COMMA ]
##
## The known suffix of the stack is as follows:
## MODULE
##

Expected an uppercase type identifier.

program: MODULE UIDENT EOL PROVIDE LBRACE UIDENT YIELD
program: MODULE UIDENT EOL PROVIDE LBRACE MODULE UIDENT YIELD
##
## Ends in an error in state: 49.
##
Expand All @@ -450,11 +467,12 @@ program: MODULE UIDENT EOL PROVIDE LBRACE UIDENT YIELD

Expected the keyword `as` followed by a module alias, a comma followed by more items to use, or `}` to end the statement.

program: MODULE UIDENT EOL PROVIDE LBRACE UIDENT AS YIELD
program: MODULE UIDENT EOL PROVIDE LBRACE MODULE UIDENT AS YIELD
##
## Ends in an error in state: 50.
##
## as_prefix(uid) -> AS . uid [ RBRACE EOL COMMA ]
## as_prefix(uid) -> AS . eols uid [ RBRACE EOL COMMA ]
##
## The known suffix of the stack is as follows:
## AS
Expand Down Expand Up @@ -508,7 +526,7 @@ program: MODULE UIDENT EOL PROVIDE LBRACE LIDENT COMMA YIELD
## In state 63, spurious reduction of production comma -> COMMA
##

Expected more items to provide or `}` to end the provide statement.
Expected a lowercase identifier to provide a value, the keyword `module` followed by an uppercase identifier to provide a module, the keyword `type` followed by an uppercase identifier to provide a type, or `}` to end the provide statement.

program: MODULE UIDENT EOL PROVIDE LBRACE YIELD
##
Expand All @@ -526,7 +544,7 @@ program: MODULE UIDENT EOL PROVIDE LBRACE YIELD
## In state 31, spurious reduction of production lbrace -> LBRACE
##

Expected a comma-separated list of items to provide.
Expected a lowercase identifier to provide a value, the keyword `module` followed by an uppercase identifier to provide a module, or the keyword `type` followed by an uppercase identifier to provide a type.

program: MODULE UIDENT EOL PROVIDE LBRACE TYPE YIELD
##
Expand Down Expand Up @@ -594,7 +612,7 @@ program: MODULE UIDENT EOL FROM UIDENT USE LBRACE LIDENT COMMA YIELD
## In state 63, spurious reduction of production comma -> COMMA
##

Expected more items to use or `}` to end the statement.
Expected a lowercase identifier to use a value, the keyword `module` followed by an uppercase identifier to use a module, the keyword `type` followed by an uppercase identifier to use a type, or `}` to end the use statement.

program: MODULE UIDENT EOL ASSERT WHEN
##
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/parsing/parser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ aliasable(X):

use_item:
| TYPE aliasable(uid) { PUseType { name=fst $2; alias = snd $2; loc=to_loc $loc} }
| aliasable(uid) { PUseModule { name=fst $1; alias = snd $1; loc=to_loc $loc} }
| MODULE aliasable(uid) { PUseModule { name=fst $2; alias = snd $2; loc=to_loc $loc} }
| aliasable(lid) { PUseValue { name=fst $1; alias = snd $1; loc=to_loc $loc} }

use_items:
Expand Down Expand Up @@ -371,7 +371,7 @@ data_declaration_stmts:

provide_item:
| TYPE aliasable(uid) { PProvideType { name=fst $2; alias = snd $2; loc=to_loc $loc} }
| aliasable(uid) { PProvideModule { name=fst $1; alias = snd $1; loc=to_loc $loc} }
| MODULE aliasable(uid) { PProvideModule { name=fst $2; alias = snd $2; loc=to_loc $loc} }
| aliasable(lid) { PProvideValue { name=fst $1; alias = snd $1; loc=to_loc $loc} }

provide_items:
Expand Down
11 changes: 8 additions & 3 deletions compiler/test/grainfmt/includes.expected.gr
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ include "option" as Opt
include "array"
include "array" as Foo
from List use { length, map, forEach as each }
from Opt use { MutableOpt, ImmutableOpt as Imm, type Opt, type Opt as OptAlias }
from Opt use {
module MutableOpt,
module ImmutableOpt as Imm,
type Opt,
type Opt as OptAlias,
}
from Opt use { /* comment1 */ /* comment2 */ /* comment3 */ /* comment4 */ /* comment5 */ /* comment6 */ /* comment7 */
MutableOpt,
ImmutableOpt as Imm,
module MutableOpt,
module ImmutableOpt as Imm,
type Opt,
type Opt as OptAlias,
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/test/grainfmt/includes.input.gr
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ include "option" as
include /* special include */ "array"
include "array" as /* special include */ Foo
from List use { length, map, forEach as each }
from Opt use { MutableOpt, ImmutableOpt as Imm, type Opt, type Opt as OptAlias }
from Opt use { MutableOpt, /* comment1 */ ImmutableOpt /* comment2 */ as /* comment3 */ Imm /* comment4 */, /* comment5 */ type /* comment6 */ Opt, type Opt as /* comment7 */ OptAlias }
from Opt use { module MutableOpt, module ImmutableOpt as Imm, type Opt, type Opt as OptAlias }
from Opt use { module MutableOpt, /* comment1 */ module ImmutableOpt /* comment2 */ as /* comment3 */ Imm /* comment4 */, /* comment5 */ type /* comment6 */ Opt, type Opt as /* comment7 */ OptAlias }

include "runtime/unsafe/wasmi32"
from WasmI32 use {
Expand Down
6 changes: 3 additions & 3 deletions compiler/test/input/modules/provideIncludedModule.gr
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ module ProvideIncludedModule
include "option" as Option
include "array" as Array

provide { Option as Smoption }
provide { module Option as Smoption }

module Qux {
provide let val = 9
provide module Quux {
provide { Array }
provide { module Array }
}
}

provide { Qux }
provide { module Qux }
2 changes: 1 addition & 1 deletion compiler/test/input/nestedModules.gr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Foo {
provide let foo = "hello from foo"
provide module Bar {
provide let bar = "hello from bar"
provide { List }
provide { module List }
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/test/stdlib/array.test.gr
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ assert Array.chunk(3, [> 1, 2, 3, 4, 5, 6, 7, 8]) ==
assert Array.chunk(10, [> 1, 2, 3, 4, 5]) == [> [> 1, 2, 3, 4, 5]]

module Immutable {
from Array use { Immutable as Array }
from Array use { module Immutable as Array }

let fromList = Array.fromList
let arr = fromList([1, 2, 3])
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/stdlib/map.test.gr
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ Map.update(
assert Map.contains("c", toUpdate) == false

module Immutable {
from Map use { Immutable as Map }
from Map use { module Immutable as Map }

let strKeys = Map.fromList([("🌾", 1), ("🐑", 2), ("🧱", 3)])
let numKeys = Map.fromList([(1, "🌾"), (2, "🐑"), (3, "🧱")])
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/stdlib/priorityqueue.test.gr
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ assert PriorityQueue.fromList(Array.toList(lotsOfVals), compare) ==
PriorityQueue.fromArray(lotsOfVals, compare)

module Immutable {
from PriorityQueue use { Immutable as PriorityQueue }
from PriorityQueue use { module Immutable as PriorityQueue }

// formatter-ignore
let lotsOfVals = [>
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/stdlib/queue.test.gr
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ assert Queue.pop(queue) == Some(10)
assert Queue.pop(queue) == None

module Immutable {
from Queue use { Immutable as Queue }
from Queue use { module Immutable as Queue }

// 1 <- 2 <- 3
let sampleQueue = Queue.push(3, Queue.push(2, Queue.push(1, Queue.empty)))
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/stdlib/range.test.gr
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ assert Range.map(toString, exclusiveDescendingRange) == ["5", "4", "3", "2"]
assert Range.map(toString, exclusiveSameRange) == []

module Inclusive {
from Range use { Inclusive as Range }
from Range use { module Inclusive as Range }

let inclusiveAscendingRange = { rangeStart: 1, rangeEnd: 5 }
let inclusiveDescendingRange = { rangeStart: 5, rangeEnd: 1 }
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/stdlib/set.test.gr
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ let largeSet = Set.fromArray(Array.init(128, i => i))
assert Set.getInternalStats(largeSet) == (128, 64)

module Immutable {
from Set use { Immutable as Set }
from Set use { module Immutable as Set }

// Set.isEmpty

Expand Down
2 changes: 1 addition & 1 deletion compiler/test/stdlib/stack.test.gr
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Stack.push(0, stack2)
assert stack == stack2

module Immutable {
from Stack use { Immutable as Stack }
from Stack use { module Immutable as Stack }

// 1 <- 2 <- 3
let sampleStack = Stack.push(3, Stack.push(2, Stack.push(1, Stack.empty)))
Expand Down
20 changes: 15 additions & 5 deletions compiler/test/suites/includes.re
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,24 @@ describe("includes", ({test, testSkip}) => {
);
assertCompileError(
"include_some_error3",
"include \"provideAll\" as ProvideAll; from ProvideAll use {Foo}; a",
"include \"provideAll\" as ProvideAll; from ProvideAll use {module Foo}",
"Unbound module Foo in module ProvideAll",
);
assertCompileError(
"include_some_error3",
"include \"provideAll\" as ProvideAll; from ProvideAll use {x, Foo}; a",
"include_some_error4",
"include \"provideAll\" as ProvideAll; from ProvideAll use {x, module Foo}",
"Unbound module Foo in module ProvideAll",
);
assertCompileError(
"include_some_error5",
"include \"provideAll\" as ProvideAll; from ProvideAll use {Foo}",
"Expected a lowercase identifier to use a value, the keyword `module` followed by an uppercase identifier to use a module, or the keyword `type` followed by an uppercase identifier to use a type.",
);
assertCompileError(
"include_some_error6",
"include \"provideAll\" as ProvideAll; from ProvideAll use {a, Foo}",
"Expected a lowercase identifier to use a value, the keyword `module` followed by an uppercase identifier to use a module, the keyword `type` followed by an uppercase identifier to use a type, or `}` to end the use statement.",
);
/* include module tests */
assertSnapshot("include_module", "include \"provideAll\" as Foo; Foo.x");
assertSnapshot(
Expand All @@ -94,12 +104,12 @@ describe("includes", ({test, testSkip}) => {
/* use well-formedness errors */
assertCompileError(
"include_alias_illegal_renaming",
"include \"list\" as List; from List use {Cons as cons, Empty}; cons(3, Empty)",
"include \"list\" as List; from List use {module Cons as cons, module Empty}; cons(3, Empty)",
"Expected an uppercase module alias",
);
assertCompileError(
"include_alias_illegal_renaming2",
"include \"list\" as List; from List use {sum as Sum, Empty}; sum(Empty)",
"include \"list\" as List; from List use {sum as Sum, module Empty}; sum(Empty)",
"Expected a lowercase alias",
);
assertCompileError(
Expand Down
4 changes: 2 additions & 2 deletions compiler/test/suites/modules.re
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ describe("modules", ({test, testSkip}) => {
provide let foo = "foo2"
}
}
from Foo use { foo, type Foo, Foo }
from Foo use { foo, type Foo, module Foo }
print(foo)
print(Foo.foo)
print(Foo)
Expand Down Expand Up @@ -137,7 +137,7 @@ describe("modules", ({test, testSkip}) => {
module ReprovidedSimple

include "simpleModule"
provide { Simple }
provide { module Simple }
|},
);
let ic = open_in_bin(outfile);
Expand Down
14 changes: 12 additions & 2 deletions compiler/test/suites/provides.re
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ describe("provides", ({test, testSkip}) => {
);
assertCompileError(
"provide11",
"enum Foo { Bar }; provide { Bar }",
"enum Foo { Bar }; provide { module Bar }",
"Unbound module Bar",
);
assertSnapshot(
Expand All @@ -99,6 +99,16 @@ describe("provides", ({test, testSkip}) => {
ProvidedType.apply((arg) => print("ok"))
|},
);
assertCompileError(
"provide13",
"module Nested { let val = 1 }; provide { Nested }",
"Expected a lowercase identifier to provide a value, the keyword `module` followed by an uppercase identifier to provide a module, or the keyword `type` followed by an uppercase identifier to provide a type.",
);
assertCompileError(
"provide13",
"let a = 1; module Nested { let val = 1 }; provide { a, Nested }",
"Expected a lowercase identifier to provide a value, the keyword `module` followed by an uppercase identifier to provide a module, the keyword `type` followed by an uppercase identifier to provide a type, or `}` to end the provide statement.",
);
assertCompileError(
"regression_issue_1489",
"provide { foo }",
Expand Down Expand Up @@ -131,7 +141,7 @@ describe("provides", ({test, testSkip}) => {
);
assertCompileError(
"multiple_provides_6",
"provide module Foo {void}; provide {Foo}",
"provide module Foo {void}; provide {module Foo}",
"provided multiple times",
);
assertCompileError(
Expand Down
Loading