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): Providing, including, reproviding exceptions #1849

Merged
merged 4 commits into from
Jan 28, 2024
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
8 changes: 7 additions & 1 deletion compiler/src/formatting/format.re
Original file line number Diff line number Diff line change
Expand Up @@ -3917,7 +3917,8 @@ and print_expression_inner =
switch (item) {
| PUseValue({loc})
| PUseModule({loc})
| PUseType({loc}) => loc
| PUseType({loc})
| PUseException({loc}) => loc
};
};

Expand Down Expand Up @@ -3961,6 +3962,8 @@ and print_expression_inner =
Doc.concat([Doc.text("module "), item_name(name, alias)])
| PUseType({name, alias}) =>
Doc.concat([Doc.text("type "), item_name(name, alias)])
| PUseException({name, alias}) =>
Doc.concat([Doc.text("exception "), item_name(name, alias)])
};
};

Expand Down Expand Up @@ -5068,6 +5071,7 @@ let rec toplevel_print =
switch (item) {
| PProvideValue({loc})
| PProvideModule({loc})
| PProvideException({loc})
| PProvideType({loc}) => loc
};
};
Expand Down Expand Up @@ -5112,6 +5116,8 @@ let rec toplevel_print =
Doc.concat([Doc.text("module "), item_name(name, alias)])
| PProvideType({name, alias}) =>
Doc.concat([Doc.text("type "), item_name(name, alias)])
| PProvideException({name, alias}) =>
Doc.concat([Doc.text("exception "), item_name(name, alias)])
};
};

Expand Down
1 change: 1 addition & 0 deletions compiler/src/language_server/definition.re
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ let process =
| [Pattern({definition}), ..._]
| [Type({definition}), ..._]
| [Declaration({definition}), ..._]
| [Exception({definition}), ..._]
| [Module({definition}), ..._] =>
switch (definition) {
| None => send_no_result(~id)
Expand Down
13 changes: 13 additions & 0 deletions compiler/src/language_server/hover.re
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ let declaration_lens = (ident: Ident.t, decl: Types.type_declaration) => {
grain_type_code_block(Printtyp.string_of_type_declaration(~ident, decl));
};

let exception_declaration_lens =
(ident: Ident.t, ext: Types.extension_constructor) => {
grain_type_code_block(
Printtyp.string_of_extension_constructor(~ident, ext),
);
};

let process =
(
~id: Protocol.message_id,
Expand Down Expand Up @@ -161,6 +168,12 @@ let process =
~range=Utils.loc_to_range(loc),
declaration_lens(ident, decl),
)
| [Exception({ident, ext, loc}), ..._] =>
send_hover(
~id,
~range=Utils.loc_to_range(loc),
exception_declaration_lens(ident, ext),
)
| [Module({path, decl, loc}), ..._] =>
send_hover(~id, ~range=Utils.loc_to_range(loc), module_lens(decl))
| _ => send_no_result(~id)
Expand Down
21 changes: 21 additions & 0 deletions compiler/src/language_server/sourcetree.re
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,12 @@ module type Sourcetree = {
loc: Location.t,
definition: option(Location.t),
})
| Exception({
ident: Ident.t,
ext: Types.extension_constructor,
loc: Location.t,
definition: option(Location.t),
})
| Module({
path: Path.t,
decl: Types.module_declaration,
Expand Down Expand Up @@ -236,6 +242,12 @@ module Sourcetree: Sourcetree = {
loc: Location.t,
definition: option(Location.t),
})
| Exception({
ident: Ident.t,
ext: Types.extension_constructor,
loc: Location.t,
definition: option(Location.t),
})
| Module({
path: Path.t,
decl: Types.module_declaration,
Expand Down Expand Up @@ -387,6 +399,15 @@ module Sourcetree: Sourcetree = {
definition: Some(value.val_loc),
}),
)
| TUseException({name, ext, loc}) => (
loc_to_interval(loc),
Exception({
ident: Ident.create(name),
ext,
loc,
definition: Some(ext.ext_loc),
}),
)
}
},
items,
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/middle_end/linearize.re
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ let compile_constructor_tag =
fun
| CstrConstant(i) => i
| CstrBlock(i) => i
| CstrExtension(i, _, _) => i
| CstrExtension(i, _, _, _) => i
| CstrUnboxed =>
failwith("compile_constructor_tag: cannot compile CstrUnboxed")
);
Expand Down
12 changes: 12 additions & 0 deletions compiler/src/parsing/ast_mapper.re
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,12 @@ module E = {
alias: Option.map(map_identifier(sub), alias),
loc: sub.location(sub, loc),
})
| PUseException({name, alias, loc}) =>
PUseException({
name: map_identifier(sub, name),
alias: Option.map(map_identifier(sub), alias),
loc: sub.location(sub, loc),
})
| PUseModule({name, alias, loc}) =>
PUseModule({
name: map_identifier(sub, name),
Expand Down Expand Up @@ -432,6 +438,12 @@ module Pr = {
alias: Option.map(map_identifier(sub), alias),
loc: sub.location(sub, loc),
})
| PProvideException({name, alias, loc}) =>
PProvideException({
name: map_identifier(sub, name),
alias: Option.map(map_identifier(sub), alias),
loc: sub.location(sub, loc),
})
| PProvideModule({name, alias, loc}) =>
PProvideModule({
name: map_identifier(sub, name),
Expand Down
24 changes: 24 additions & 0 deletions compiler/src/parsing/parser.messages
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,18 @@ program: MODULE UIDENT EOL FROM UIDENT USE LBRACE MODULE YIELD

Expected an uppercase type identifier.

program: MODULE UIDENT EOL FROM UIDENT USE LBRACE EXCEPTION YIELD
##
## Ends in an error in state: 57.
##
## use_item -> EXCEPTION . aliasable(uid) [ RBRACE EOL COMMA ]
##
## The known suffix of the stack is as follows:
## EXCEPTION
##

Expected an uppercase exception identifier.

program: MODULE UIDENT EOL PROVIDE LBRACE MODULE UIDENT YIELD
##
## Ends in an error in state: 49.
Expand Down Expand Up @@ -558,6 +570,18 @@ program: MODULE UIDENT EOL PROVIDE LBRACE TYPE YIELD

Expected a type identifier to provide.

program: MODULE UIDENT EOL PROVIDE LBRACE EXCEPTION YIELD
##
## Ends in an error in state: 825.
##
## provide_item -> EXCEPTION . aliasable(uid) [ RBRACE EOL COMMA ]
##
## The known suffix of the stack is as follows:
## EXCEPTION
##

Expected an exception identifier to provide.

program: MODULE UIDENT EOL FROM UIDENT USE LBRACE LIDENT AS LIDENT YIELD
##
## Ends in an error in state: 62.
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/parsing/parser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ aliasable(X):
use_item:
| TYPE aliasable(uid) { PUseType { name=fst $2; alias = snd $2; loc=to_loc $loc} }
| MODULE aliasable(uid) { PUseModule { name=fst $2; alias = snd $2; loc=to_loc $loc} }
| EXCEPTION aliasable(uid) { PUseException { 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 @@ -372,6 +373,7 @@ data_declaration_stmts:
provide_item:
| TYPE aliasable(uid) { PProvideType { name=fst $2; alias = snd $2; loc=to_loc $loc} }
| MODULE aliasable(uid) { PProvideModule { name=fst $2; alias = snd $2; loc=to_loc $loc} }
| EXCEPTION aliasable(uid) { PProvideException { 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
10 changes: 10 additions & 0 deletions compiler/src/parsing/parsetree.re
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,11 @@ and use_item =
alias: option(loc(Identifier.t)),
loc: Location.t,
})
| PUseException({
name: loc(Identifier.t),
alias: option(loc(Identifier.t)),
loc: Location.t,
})
| PUseModule({
name: loc(Identifier.t),
alias: option(loc(Identifier.t)),
Expand Down Expand Up @@ -595,6 +600,11 @@ type provide_item =
alias: option(loc(Identifier.t)),
loc: Location.t,
})
| PProvideException({
name: loc(Identifier.t),
alias: option(loc(Identifier.t)),
loc: Location.t,
})
| PProvideModule({
name: loc(Identifier.t),
alias: option(loc(Identifier.t)),
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/parsing/parsetree_iter.re
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ and iter_provide = (hooks, items) => {
item => {
switch (item) {
| PProvideType({name, alias, loc})
| PProvideException({name, alias, loc})
| PProvideModule({name, alias, loc})
| PProvideValue({name, alias, loc}) =>
iter_ident(hooks, name);
Expand Down Expand Up @@ -290,6 +291,7 @@ and iter_expression =
item => {
switch (item) {
| PUseType({name, alias, loc})
| PUseException({name, alias, loc})
| PUseModule({name, alias, loc})
| PUseValue({name, alias, loc}) =>
iter_ident(hooks, name);
Expand Down
12 changes: 11 additions & 1 deletion compiler/src/parsing/well_formedness.re
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,7 @@ let no_local_include = (errs, super) => {
type provided_multiple_times_ctx = {
modules: Hashtbl.t(string, unit),
types: Hashtbl.t(string, unit),
exceptions: Hashtbl.t(string, unit),
values: Hashtbl.t(string, unit),
};

Expand Down Expand Up @@ -637,6 +638,7 @@ let provided_multiple_times = (errs, super) => {
{
modules: Hashtbl.create(64),
types: Hashtbl.create(64),
exceptions: Hashtbl.create(64),
values: Hashtbl.create(64),
},
]);
Expand All @@ -647,6 +649,7 @@ let provided_multiple_times = (errs, super) => {
{
modules: Hashtbl.create(64),
types: Hashtbl.create(64),
exceptions: Hashtbl.create(64),
values: Hashtbl.create(64),
},
...ctx^,
Expand All @@ -660,7 +663,7 @@ let provided_multiple_times = (errs, super) => {
};

let enter_toplevel_stmt = ({ptop_desc: desc} as top) => {
let {values, modules, types} = List.hd(ctx^);
let {values, modules, types, exceptions} = List.hd(ctx^);
switch (desc) {
| PTopModule(Provided | Abstract, {pmod_name, pmod_loc}) =>
if (Hashtbl.mem(modules, pmod_name.txt)) {
Expand Down Expand Up @@ -745,6 +748,13 @@ let provided_multiple_times = (errs, super) => {
} else {
Hashtbl.add(types, name, ());
};
| PProvideException({name, alias, loc}) =>
let (_, name) = apply_alias(name, alias);
if (Hashtbl.mem(exceptions, name)) {
errs := [ProvidedMultipleTimes(name, loc), ...errs^];
} else {
Hashtbl.add(exceptions, name, ());
};
| PProvideModule({name, alias, loc}) =>
let (_, name) = apply_alias(name, alias);
if (Hashtbl.mem(modules, name)) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/typed/datarepr.re
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ let extension_descr = (path_ext, ext) => {
cstr_existentials: existentials,
cstr_args,
cstr_arity: List.length(cstr_args),
cstr_tag: CstrExtension(ext.ext_name.stamp, path_ext, cstr_ext_type),
cstr_tag: CstrExtension(ext.ext_name.stamp, path_ext, cstr_ext_type, ext),
cstr_consts: (-1),
cstr_nonconsts: (-1),
cstr_loc: ext.ext_loc,
Expand Down
35 changes: 35 additions & 0 deletions compiler/src/typed/env.re
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ type error =
| Value_not_found_in_module(Location.t, string, string)
| Module_not_found_in_module(Location.t, string, string, option(string))
| Type_not_found_in_module(Location.t, string, string)
| Exception_not_found_in_module(Location.t, string, string)
| Illegal_value_name(Location.t, string)
| Cyclic_dependencies(string, dependency_chain);

Expand Down Expand Up @@ -941,6 +942,7 @@ let check_pers_struct = (~loc, name, filename) =>
| Value_not_found_in_module(_) => assert(false)
| Module_not_found_in_module(_) => assert(false)
| Type_not_found_in_module(_) => assert(false)
| Exception_not_found_in_module(_) => assert(false)
| Illegal_value_name(_) => assert(false)
| Cyclic_dependencies(_) => assert(false)
};
Expand Down Expand Up @@ -2222,6 +2224,37 @@ let use_partial_signature = (root, items, env0) => {
);
TUseType({name: new_name, declaration: decl, loc});
};
| PUseException({name, alias, loc}) =>
let (old_name, new_name) = apply_alias(name, alias);
switch (Tbl.find(old_name, comps.comp_constrs)) {
| exception Not_found =>
error(
Exception_not_found_in_module(
name.loc,
old_name,
Path.name(root),
),
)
| cstrs =>
let (ext, cstr_name) =
List.find_map(
cstr =>
switch (cstr.cstr_tag) {
| CstrExtension(_, _, _, ext) =>
Some((ext, cstr.cstr_name))
| _ => None
},
cstrs,
)
|> Option.get;
new_comps.comp_constrs =
Tbl.add(
new_name,
Tbl.find(cstr_name, comps.comp_constrs),
new_comps.comp_constrs,
);
TUseException({name: new_name, ext, loc});
};
}
},
items,
Expand Down Expand Up @@ -2609,6 +2642,8 @@ let report_error = ppf =>
)
| Type_not_found_in_module(_, name, path) =>
fprintf(ppf, "Unbound type %s in module %s", name, path)
| Exception_not_found_in_module(_, name, path) =>
fprintf(ppf, "Unbound exception %s in module %s", name, path)
| Cyclic_dependencies(dep, chain) =>
fprintf(
ppf,
Expand Down
1 change: 1 addition & 0 deletions compiler/src/typed/env.rei
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type error =
| Value_not_found_in_module(Location.t, string, string)
| Module_not_found_in_module(Location.t, string, string, option(string))
| Type_not_found_in_module(Location.t, string, string)
| Exception_not_found_in_module(Location.t, string, string)
| Illegal_value_name(Location.t, string)
| Cyclic_dependencies(string, dependency_chain);

Expand Down
6 changes: 5 additions & 1 deletion compiler/src/typed/printtyp.re
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,7 @@ let tree_of_extension_constructor = (id, ext, es) => {
let extension_constructor = (id, ppf, ext) =>
Oprint.out_sig_item^(
ppf,
tree_of_extension_constructor(id, ext, TExtFirst),
tree_of_extension_constructor(id, ext, TExtException),
);

let extension_only_constructor = (id, ppf, ext) => {
Expand All @@ -1035,6 +1035,10 @@ let extension_only_constructor = (id, ppf, ext) => {
Format.fprintf(ppf, "@[<hv>%a@]", Oprint.out_constr^, (name, args, None));
};

let string_of_extension_constructor = (~ident, ext) => {
asprintf("%a", extension_constructor(ident), ext);
};

/* Print a value declaration */
let tree_of_value_description = (id, decl) => {
let id = Ident.name(id);
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/typed/printtyp.rei
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ let tree_of_type_declaration:
let type_declaration: (Ident.t, formatter, type_declaration) => unit;
let string_of_type_declaration: (~ident: Ident.t, type_declaration) => string;
let extension_constructor: (Ident.t, formatter, extension_constructor) => unit;
let string_of_extension_constructor:
(~ident: Ident.t, extension_constructor) => string;
let tree_of_module:
(Ident.t, ~ellipsis: bool=?, module_type, rec_status) => out_sig_item;
let modtype: (formatter, module_type) => unit;
Expand Down
Loading
Loading