Skip to content
Open
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
1 change: 1 addition & 0 deletions compiler/src/middle_end/anf_utils.re
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module ClearLocationsArg: Anf_mapper.MapArgument = {
| Disable_gc => Disable_gc
| Unsafe => Unsafe
| External_name(name) => External_name(Location.mknoloc(name.txt))
| Elide_type_info => Elide_type_info
};
Location.mknoloc(attr);
},
Expand Down
193 changes: 100 additions & 93 deletions compiler/src/middle_end/linearize.re
Original file line number Diff line number Diff line change
Expand Up @@ -1997,99 +1997,102 @@ let rec transl_anf_statement =

let rec gather_type_metadata = statements => {
List.fold_left(
(metadata, {ttop_desc, ttop_env}) => {
switch (ttop_desc) {
| TTopData(decls) =>
let info =
List.filter_map(
decl => {
let typath = decl.data_type.type_path;
let id = get_type_id(typath, ttop_env);
switch (decl.data_kind) {
| TDataVariant(cnstrs) =>
let type_hash = get_type_hash(decl.data_type);
let descrs =
Datarepr.constructors_of_type(typath, decl.data_type);
let meta =
List.map(
((_, cstr)) =>
(
compile_constructor_tag(cstr.cstr_tag),
cstr.cstr_name,
switch (cstr.cstr_inlined) {
| None => TupleConstructor
| Some(t) =>
let label_names =
switch (t.type_kind) {
| TDataRecord(rfs) =>
List.map(
rf => Ident.name(rf.Types.rf_name),
rfs,
)
| _ =>
failwith(
"Impossible: inlined record constructor with non-record underlying type",
)
};
RecordConstructor(label_names);
},
),
descrs,
);
Some((ADTMetadata(id, meta), type_hash));
| TDataRecord(fields) =>
let type_hash = get_type_hash(decl.data_type);
Some((
RecordMetadata(
id,
List.map(field => Ident.name(field.rf_name), fields),
),
type_hash,
));
| TDataAbstract => None
};
},
decls,
);
List.append(info, metadata);
| TTopException(ext) =>
let ty_id = get_type_id(ext.ext_type.ext_type_path, ttop_env);
let id = ext.ext_id;
let cstr = Datarepr.extension_descr(Path.PIdent(id), ext.ext_type);
[
(
ExceptionMetadata(
ty_id,
compile_constructor_tag(cstr.cstr_tag),
cstr.cstr_name,
switch (cstr.cstr_inlined) {
| None => TupleConstructor
| Some(t) =>
let label_names =
switch (t.type_kind) {
| TDataRecord(rfs) =>
List.map(rf => Ident.name(rf.Types.rf_name), rfs)
| _ =>
failwith(
"Impossible: inlined exception record constructor with non-record underlying type",
)
};
RecordConstructor(label_names);
(metadata, {ttop_desc, ttop_env, ttop_attributes}) =>
if (List.exists(attr => attr.txt == Elide_type_info, ttop_attributes)) {
metadata;
} else {
switch (ttop_desc) {
| TTopData(decls) =>
let info =
List.filter_map(
decl => {
let typath = decl.data_type.type_path;
let id = get_type_id(typath, ttop_env);
switch (decl.data_kind) {
| TDataVariant(cnstrs) =>
let type_hash = get_type_hash(decl.data_type);
let descrs =
Datarepr.constructors_of_type(typath, decl.data_type);
let meta =
List.map(
((_, cstr)) =>
(
compile_constructor_tag(cstr.cstr_tag),
cstr.cstr_name,
switch (cstr.cstr_inlined) {
| None => TupleConstructor
| Some(t) =>
let label_names =
switch (t.type_kind) {
| TDataRecord(rfs) =>
List.map(
rf => Ident.name(rf.Types.rf_name),
rfs,
)
| _ =>
failwith(
"Impossible: inlined record constructor with non-record underlying type",
)
};
RecordConstructor(label_names);
},
),
descrs,
);
Some((ADTMetadata(id, meta), type_hash));
| TDataRecord(fields) =>
let type_hash = get_type_hash(decl.data_type);
Some((
RecordMetadata(
id,
List.map(field => Ident.name(field.rf_name), fields),
),
type_hash,
));
| TDataAbstract => None
};
},
decls,
);
List.append(info, metadata);
| TTopException(ext) =>
let ty_id = get_type_id(ext.ext_type.ext_type_path, ttop_env);
let id = ext.ext_id;
let cstr = Datarepr.extension_descr(Path.PIdent(id), ext.ext_type);
[
(
ExceptionMetadata(
ty_id,
compile_constructor_tag(cstr.cstr_tag),
cstr.cstr_name,
switch (cstr.cstr_inlined) {
| None => TupleConstructor
| Some(t) =>
let label_names =
switch (t.type_kind) {
| TDataRecord(rfs) =>
List.map(rf => Ident.name(rf.Types.rf_name), rfs)
| _ =>
failwith(
"Impossible: inlined exception record constructor with non-record underlying type",
)
};
RecordConstructor(label_names);
},
),
exception_type_hash,
),
exception_type_hash,
),
...metadata,
];
| TTopModule(decl) =>
List.append(gather_type_metadata(decl.tmod_statements), metadata)
| TTopExpr(_)
| TTopInclude(_)
| TTopProvide(_)
| TTopForeign(_)
| TTopLet(_) => metadata
}
},
...metadata,
];
| TTopModule(decl) =>
List.append(gather_type_metadata(decl.tmod_statements), metadata)
| TTopExpr(_)
| TTopInclude(_)
| TTopProvide(_)
| TTopForeign(_)
| TTopLet(_) => metadata
};
},
[],
statements,
);
Expand Down Expand Up @@ -2283,7 +2286,8 @@ let construct_type_metadata_buffer = type_metadata => {
};

let transl_anf_module =
({statements, env, signature, prog_loc}: typed_program): anf_program => {
({attributes, statements, env, signature, prog_loc}: typed_program)
: anf_program => {
Path_tbl.clear(type_map);
Path_tbl.clear(include_map);
Path_tbl.clear(module_symbol_map);
Expand All @@ -2307,7 +2311,10 @@ let transl_anf_module =
specs: imports @ value_imports^,
path_map: Path_tbl.copy(include_map),
};
let type_metadata_and_hashes = gather_type_metadata(statements);
let elideTypeInfo =
List.exists(attr => attr.txt == Elide_type_info, attributes);
let type_metadata_and_hashes =
elideTypeInfo ? [] : gather_type_metadata(statements);
let type_metadata =
List.map(((meta, _)) => meta, type_metadata_and_hashes);
let metadata = construct_type_metadata_buffer(type_metadata_and_hashes);
Expand Down
45 changes: 45 additions & 0 deletions compiler/src/parsing/well_formedness.re
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,10 @@ let disallowed_attributes = (errs, super) => {
name: "externalName",
arity: 1,
},
{
name: "elideTypeInfo",
arity: 0,
},
];

let enter_expression = ({pexp_attributes: attrs} as e) => {
Expand All @@ -338,6 +342,22 @@ let disallowed_attributes = (errs, super) => {
]
| None => ()
};
switch (
List.find_opt(
({Asttypes.attr_name: {txt}}) => txt == "elideTypeInfo",
attrs,
)
) {
| Some({Asttypes.attr_name: {txt, loc}}) =>
errs :=
[
AttributeDisallowed(
"`elideTypeInfo` is only allowed on module, record, and variant declarations.",
loc,
),
]
Comment on lines +352 to +358

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason these aren't prepended to the error list and instead replaces it?

| None => ()
};
validate_against_known(attrs, known_expr_attributes, "expression");
super.enter_expression(e);
};
Expand Down Expand Up @@ -395,6 +415,27 @@ let disallowed_attributes = (errs, super) => {
}
| None => ()
};
switch (
List.find_opt(
({Asttypes.attr_name: {txt}}) => txt == "elideTypeInfo",
attrs,
)
) {
| Some({Asttypes.attr_name: {txt, loc}}) =>
switch (desc) {
| PTopModule(_)
| PTopData(_) => ()
| _ =>
errs :=
[
AttributeDisallowed(
"`elideTypeInfo` is only allowed on module, record, and variant declarations.",
loc,
),
]
}
Comment on lines +429 to +436

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

| None => ()
};
validate_against_known(attrs, known_expr_attributes, "top-level");
super.enter_toplevel_stmt(top);
};
Expand All @@ -413,6 +454,10 @@ let disallowed_attributes = (errs, super) => {
name: "noExceptions",
arity: 0,
},
{
name: "elideTypeInfo",
arity: 0,
},
];
validate_against_known(attributes, known_module_attributes, "module");
super.enter_parsed_program(prog);
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/typed/typedtree.re
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ type attributes = list(loc(attribute))
and attribute =
| Disable_gc
| Unsafe
| External_name(loc(string));
| External_name(loc(string))
| Elide_type_info;

[@deriving sexp]
type partial =
Expand Down Expand Up @@ -635,6 +636,7 @@ type comment =

[@deriving sexp]
type typed_program = {
attributes,
module_name: loc(string),
statements: list(toplevel_stmt),
env: [@sexp.opaque] Env.t,
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/typed/typedtree.rei
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ type attributes = list(loc(attribute))
and attribute =
| Disable_gc
| Unsafe
| External_name(loc(string));
| External_name(loc(string))
| Elide_type_info;

type partial =
| Partial
Expand Down Expand Up @@ -595,6 +596,7 @@ type comment =

[@deriving sexp]
type typed_program = {
attributes,
module_name: loc(string),
statements: list(toplevel_stmt),
env: Env.t,
Expand Down
7 changes: 7 additions & 0 deletions compiler/src/typed/typemod.re
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,13 @@ let type_implementation = (prog: Parsetree.parsed_program) => {
let signature =
Env.build_signature(normalized_sig, module_name, type_metadata);
{
attributes:
Typetexp.type_attributes(
List.filter(
attr => attr.attr_name.txt == "elideTypeInfo",
prog.attributes,
),
),
module_name: prog.module_name,
statements,
env: finalenv,
Expand Down
1 change: 1 addition & 0 deletions compiler/src/typed/typetexp.re
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,7 @@ let type_attributes = attrs => {
| ("unsafe", []) => Location.mkloc(Unsafe, loc)
| ("externalName", [name]) =>
Location.mkloc(External_name(name), loc)
| ("elideTypeInfo", []) => Location.mkloc(Elide_type_info, loc)
| _ => failwith("type_attributes: impossible by well-formedness")
},
attrs,
Expand Down
Loading
Loading