From 5fe9ae4429e4537ce0fa76111cbe9f6af3f692dd Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Fri, 4 Sep 2026 19:37:10 -0400 Subject: [PATCH 1/2] feat: Allow `@elideTypeInfo` as an attribute This PR adds a new `@elideTypeInfo` attribute. It is similar to eliding type information at the CLI level, but is intended more for use within the runtime or library internals where we only want to elide type information from specific parts of a program. The attribute can be applied in the following places: **Above a record definition**: * Elides the type information for that record specifically. **Above an enum definition** * Elides the type information for that enum specifically. **Above a submodule definition**: * Elides the type information for everything within the submodule. **Above a module definition**: * This might initially seem equivalent to eliding type information for the entire program, but it only affects the module itself. * For example, if you have a Main module with type information elided, you can still print records from other modules where type information has not been elided. It should be pretty easy in the future to enable this on exceptions as well, but that requires a parser change to allow attributes above exception definitions. While working on #2385, I noticed that a significant portion of the added program size came from the use of higher-level types such as records and enums. Some of that additional size comes from the type information associated with those types. This attribute gives us a way to selectively strip type information from specific modules, submodules, records, or enums. This should be particularly useful for runtime and internal library code where we know that the type information is not needed and want to reduce the resulting program size. Closes: #2365 --- compiler/src/middle_end/anf_utils.re | 1 + compiler/src/middle_end/linearize.re | 193 ++++++++++---------- compiler/src/parsing/well_formedness.re | 45 +++++ compiler/src/typed/typedtree.re | 4 +- compiler/src/typed/typedtree.rei | 4 +- compiler/src/typed/typemod.re | 7 + compiler/src/typed/typetexp.re | 1 + compiler/test/suites/basic_functionality.re | 65 +++++++ 8 files changed, 225 insertions(+), 95 deletions(-) diff --git a/compiler/src/middle_end/anf_utils.re b/compiler/src/middle_end/anf_utils.re index 521b2bc8f5..a09eeeadc8 100644 --- a/compiler/src/middle_end/anf_utils.re +++ b/compiler/src/middle_end/anf_utils.re @@ -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); }, diff --git a/compiler/src/middle_end/linearize.re b/compiler/src/middle_end/linearize.re index 520f016db2..cd23adad61 100644 --- a/compiler/src/middle_end/linearize.re +++ b/compiler/src/middle_end/linearize.re @@ -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, ); @@ -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); @@ -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); diff --git a/compiler/src/parsing/well_formedness.re b/compiler/src/parsing/well_formedness.re index 99780b4431..b32206f903 100644 --- a/compiler/src/parsing/well_formedness.re +++ b/compiler/src/parsing/well_formedness.re @@ -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) => { @@ -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, + ), + ] + | None => () + }; validate_against_known(attrs, known_expr_attributes, "expression"); super.enter_expression(e); }; @@ -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, + ), + ] + } + | None => () + }; validate_against_known(attrs, known_expr_attributes, "top-level"); super.enter_toplevel_stmt(top); }; @@ -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); diff --git a/compiler/src/typed/typedtree.re b/compiler/src/typed/typedtree.re index d363ff6516..5affae9f69 100644 --- a/compiler/src/typed/typedtree.re +++ b/compiler/src/typed/typedtree.re @@ -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 = @@ -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, diff --git a/compiler/src/typed/typedtree.rei b/compiler/src/typed/typedtree.rei index f1d9e1ad6d..6c0bbfea08 100644 --- a/compiler/src/typed/typedtree.rei +++ b/compiler/src/typed/typedtree.rei @@ -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 @@ -595,6 +596,7 @@ type comment = [@deriving sexp] type typed_program = { + attributes, module_name: loc(string), statements: list(toplevel_stmt), env: Env.t, diff --git a/compiler/src/typed/typemod.re b/compiler/src/typed/typemod.re index 0bf726dd5a..a515430d06 100644 --- a/compiler/src/typed/typemod.re +++ b/compiler/src/typed/typemod.re @@ -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, diff --git a/compiler/src/typed/typetexp.re b/compiler/src/typed/typetexp.re index 60fbebbf7c..892cb3f1e2 100644 --- a/compiler/src/typed/typetexp.re +++ b/compiler/src/typed/typetexp.re @@ -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, diff --git a/compiler/test/suites/basic_functionality.re b/compiler/test/suites/basic_functionality.re index babefd6e10..e86260ea8d 100644 --- a/compiler/test/suites/basic_functionality.re +++ b/compiler/test/suites/basic_functionality.re @@ -485,6 +485,71 @@ describe("basic functionality", ({test, testSkip}) => { -1, ); + // @elideTypeInfo attribute + + assertRun( + "type_metadata_elided_individual", + {| + @elideTypeInfo + record NoInfoRecord { + noInfo: Number, + } + @elideTypeInfo + enum NoInfoEnum { + NoInfo, + } + record InfoRecord { + info: Number, + } + enum InfoEnum { + Info, + } + assert toString({ noInfo: 2, }: NoInfoRecord) == "" + assert toString(NoInfo: NoInfoEnum) == "" + assert toString({ info: 2, }: InfoRecord) == "{\n info: 2\n}" + assert toString(Info: InfoEnum) == "Info" + |}, + "", + ); + + assertRun( + "type_metadata_elided_submodule", + {| + record Info { + info: Number, + } + + @elideTypeInfo + module NoInfo { + provide record NoInfo { + noInfo: Number, + } + } + assert toString({ noInfo: 2, }: NoInfo.NoInfo) == "" + assert toString({ info: 2, }: Info) == "{\n info: 2\n}" + |}, + "", + ); + + assertRun( + "type_metadata_elided_inside_submodule", + {| + module SubModule { + @elideTypeInfo + provide record NoInfo { + noInfo: Number, + } + + provide record Info { + info: Number, + } + } + assert toString({ noInfo: 2, }: SubModule.NoInfo) == "" + assert toString({ info: 2, }: SubModule.Info) == "{\n info: 2\n}" + |}, + "", + ); + assertFilesize( ~config_fn=smallestFileConfig, "smallest_grain_program", From 7f0ffb4d3ed23caeec9a65ad29bb47c8d717a595 Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Fri, 4 Sep 2026 19:39:51 -0400 Subject: [PATCH 2/2] feat: Strip type info from stdlib internals --- stdlib/array.gr | 1 + stdlib/fs.gr | 61 +++++++++++++++++++++++++------------------------ stdlib/json.gr | 4 ++++ stdlib/path.gr | 7 +++--- stdlib/regex.gr | 13 ++++++++++- stdlib/uri.gr | 1 + 6 files changed, 53 insertions(+), 34 deletions(-) diff --git a/stdlib/array.gr b/stdlib/array.gr index 16330899a5..986e2ece57 100644 --- a/stdlib/array.gr +++ b/stdlib/array.gr @@ -1287,6 +1287,7 @@ provide module Immutable { } // a helper data structure used for building an array piece by piece + @elideTypeInfo record Builder { btail: Array, nodes: List>, diff --git a/stdlib/fs.gr b/stdlib/fs.gr index 9b3aca2843..3c9d6d73c1 100644 --- a/stdlib/fs.gr +++ b/stdlib/fs.gr @@ -1,11 +1,11 @@ /** * Utilities for high-level file system interactions. Utilizes WASI Preview 1 for underlying API - * + * * @example from "fs" include Fs * @example Fs.Utf8.readFile(Path.fromString("baz.txt")) * @example Fs.Utf8.writeFile(Path.fromString("baz.txt"), "Hello World\n") * @example Fs.copy(Path.fromString("foo.txt"), Path.fromString("foocopy.txt")) - * + * * @since v0.7.0 */ module Fs @@ -247,6 +247,7 @@ provide enum WriteMode { Append, } +@elideTypeInfo enum OpenMode { Unlink, RmDir, @@ -538,16 +539,16 @@ let rec removeRecursive = (parentFd, path) => { /** * Removes a file or directory. - * + * * @param removeMode: The type of removal to perform; `RemoveFile` by default * @param baseDirPath: The path to the directory in which path resolution starts * @param path: The path of the file or directory to remove * @returns `Ok(void)` if the operation succeeds, `Err(err)` if a file system error is encountered - * + * * @example Fs.remove(Path.fromString("file.txt")) // removes a file * @example Fs.remove(removeMode=Fs.RemoveEmptyDirectory, Path.fromString("dir")) // removes an empty directory * @example Fs.remove(removeMode=Fs.RemoveRecursive, Path.fromString("dir")) // removes the directory and its contents - * + * * @since v0.7.0 */ provide let remove = (removeMode=RemoveFile, baseDirPath=None, path) => { @@ -576,11 +577,11 @@ provide let remove = (removeMode=RemoveFile, baseDirPath=None, path) => { /** * Reads the contents of a directory. - * + * * @param baseDirPath: The path to the directory in which resolution should begin * @param path: The path to the directory to read * @returns `Ok(contents)` containing the directory contents or `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let readDir = (baseDirPath=None, path) => { @@ -598,11 +599,11 @@ provide let readDir = (baseDirPath=None, path) => { /** * Creates a new empty directory at the given path. - * + * * @param baseDirPath: The path to the directory in which resolution should begin * @param path: The path to create the new directory, relative to the base directory * @returns `Ok(void)` if the operation succeeds, `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let createDir = (baseDirPath=None, path) => { @@ -616,12 +617,12 @@ provide let createDir = (baseDirPath=None, path) => { /** * Creates a new symbolic link with the given contents. - * + * * @param linkContents: The path to store into the link * @param targetBaseDirPath: The path to the directory in which the target path resolution starts * @param targetPath: The path to the target of the link * @returns `Ok(void)` if the operation succeeds, `Err(err)` if a file system error or relativization error is encountered - * + * * @since v0.7.0 */ provide let createSymlink = (linkContents, targetBaseDirPath=None, targetPath) => { @@ -643,12 +644,12 @@ provide let createSymlink = (linkContents, targetBaseDirPath=None, targetPath) = /** * Queries information about a file. - * + * * @param followSymlink: Whether to follow symlinks or not; if `true` then the stats of a valid symlink's underlying file will be returned. `true` by default * @param baseDirPath: The path to the directory in which the path resolution starts * @param path: The path of the file to query * @returns `Ok(stats)` containing metadata or `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let stats = (followSymlink=true, baseDirPath=None, path) => { @@ -675,11 +676,11 @@ provide let stats = (followSymlink=true, baseDirPath=None, path) => { /** * Polls whether or not a file or directory exists at the given path. - * + * * @param baseDirPath: The path to the directory in which the path resolution starts * @param path: The path of the file to query * @returns `true` if a file or directory exists at the path or `false` otherwise - * + * * @since v0.7.0 */ provide let exists = (baseDirPath=None, path) => { @@ -701,11 +702,11 @@ let readLinkHelper = (dirFd, path, stats: File.Filestats) => { /** * Reads the contents of a symbolic link. - * + * * @param baseDirPath: The path to the directory to begin path resolution * @param path: The path to the link to read * @returns `Ok(path)` containing the link contents or `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let readLink = (baseDirPath=None, path) => { @@ -876,7 +877,7 @@ let rec copyRecursive = ( /** * Copies a file or directory. - * + * * @param copyMode: The type of copy to perform; `CopyFile` by default * @param followSymlink: Whether to follow symlinks or not; if `true` then the stats of a valid symlink's underlying file will be returned. `true` by default * @param sourceBaseDirPath: The path to the directory in which the source path resolution starts @@ -918,13 +919,13 @@ provide let copy = ( /** * Renames a file or directory. - * + * * @param sourceBaseDirPath: The path to the directory in which the source path resolution starts * @param sourcePath: The path of the file to rename * @param targetBaseDirPath: The path to the directory in which the target path resolution starts * @param targetPath: The new path of the file * @returns `Ok(void)` if the operation succeeds, `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let rename = ( @@ -961,18 +962,18 @@ provide let rename = ( /** * Functionality for reading and writing `Bytes` to files. - * + * * @since v0.7.0 */ provide module Binary { /** * Read the contents of a file as `Bytes`. - * + * * @param sync: Whether to synchronously read; `true` by default * @param baseDirPath: The path to the directory to begin path resolution * @param path: The file path to read from * @returns `Ok(contents)` containing the bytes read if successful or `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let readFile = (sync=true, baseDirPath=None, path) => { @@ -990,14 +991,14 @@ provide module Binary { /** * Write `Bytes` to a file. - * + * * @param writeMode: The type of write operation to perform; `Truncate` by default * @param sync: Whether to synchronously write; `true` by default * @param baseDirPath: The path to the directory to begin path resolution * @param path: The file path to write to * @param data: The bytes to write to the file * @returns `Ok(void)` if the operation is successful or `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let writeFile = ( @@ -1032,18 +1033,18 @@ provide module Binary { /** * Functionality for reading and writing `String`s to files. - * + * * @since v0.7.0 */ provide module Utf8 { /** * Read the contents of a file as a `String`. - * + * * @param sync: Whether to synchronously read; `true` by default * @param baseDirPath: The path to the directory to begin path resolution * @param path: The file path to read from * @returns `Ok(contents)` containing the string read if successful or `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let readFile = (sync=true, baseDirPath=None, path) => { @@ -1053,14 +1054,14 @@ provide module Utf8 { /** * Write a `String` to a file. - * + * * @param writeMode: The type of write operation to perform; `Truncate` by default * @param sync: Whether to synchronously write; `true` by default * @param baseDirPath: The path to the directory to begin path resolution * @param path: The file path to write to * @param data: The string to write to the file * @returns `Ok(void)` if the operation is successful or `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let writeFile = ( diff --git a/stdlib/json.gr b/stdlib/json.gr index 2146c8c9ff..2be8eddfcb 100644 --- a/stdlib/json.gr +++ b/stdlib/json.gr @@ -294,6 +294,7 @@ provide enum LineEnding { /* * Allows fine-grained control of formatting in JSON output. */ +@elideTypeInfo record FormattingSettings { indentation: IndentationFormat, arrayFormat: ArrayFormat, @@ -437,6 +438,7 @@ provide enum FormattingChoices { }, } +@elideTypeInfo record JsonWriterConfig { format: FormattingSettings, buffer: Buffer.Buffer, @@ -449,6 +451,7 @@ record JsonWriterConfig { // For now this is not exposed and remains an internal implementation detail. // It may make sense in the future to expose it and let the user reuse a writer for multiple // JSON emit operations without reallocating new closures and buffers each time. +@elideTypeInfo record JsonWriter { emit: Json => Option, } @@ -1289,6 +1292,7 @@ provide enum JsonParseError { /* * Internal data structure used during parsing. */ +@elideTypeInfo record JsonParserState { string: String, bufferParse: Buffer.Buffer, diff --git a/stdlib/path.gr b/stdlib/path.gr index 9973e9615c..5300f10a02 100644 --- a/stdlib/path.gr +++ b/stdlib/path.gr @@ -53,7 +53,7 @@ from "char" include Char // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. - +@elideTypeInfo enum Token { Slash, Dot, @@ -61,12 +61,12 @@ enum Token { DriveTok(Char), Text(String), } - +@elideTypeInfo enum DirsUp { Zero, Positive, } - +@elideTypeInfo enum FileType { File, Dir, @@ -74,6 +74,7 @@ enum FileType { // hack to be able to concretely distinguish TypedPath from PathInfo and // enforce TypedPath's type parameters +@elideTypeInfo record TFileType { fileType: FileType, } diff --git a/stdlib/regex.gr b/stdlib/regex.gr index cc0a9a6377..51f734406b 100644 --- a/stdlib/regex.gr +++ b/stdlib/regex.gr @@ -39,7 +39,7 @@ REGEX PARSER CONFIG DEFINITIONS case-insensitive while still having the same group number and reference counter. */ - +@elideTypeInfo record RegExParserConfig { // Whether to use Perl-based regexp syntax isPerlRegExp: Bool, @@ -90,6 +90,7 @@ let configIncGroupNumber = (config: RegExParserConfig) => { config } +@elideTypeInfo record RegExBuf { input: String, inputExploded: Array, @@ -341,12 +342,14 @@ REGEX AST DEFINITIONS */ +@elideTypeInfo enum RepeatQuantifier { ZeroOrMore, OnceOrMore, ZeroOrOne, } +@elideTypeInfo enum GroupModeFlag { GMFCaseSensitive, GMFCaseInsensitive, @@ -354,6 +357,7 @@ enum GroupModeFlag { GMFMulti, } +@elideTypeInfo enum LookMode { LMMatches, LMDoesntMatch, @@ -361,12 +365,14 @@ enum LookMode { LMDoesntMatchPreceding, } +@elideTypeInfo enum PCEMode { PCEOnce, PCELongest, PCEShortest, } +@elideTypeInfo enum UnicodeCategory { LetterLowercase, LetterUppercase, @@ -400,6 +406,7 @@ enum UnicodeCategory { OtherPrivateUse, } +@elideTypeInfo enum rec ParsedRegularExpression { RENever, REEmpty, @@ -461,6 +468,7 @@ let makeRERange = (rng: CharRange, limitC) => { } } +@elideTypeInfo enum MergeMode { MMChar, } @@ -2000,6 +2008,7 @@ let rec startRange = re => { // validate: +@elideTypeInfo enum ValidateError { MightBeEmpty, DoesNotMatchBounded, @@ -2163,6 +2172,7 @@ REGEX MATCHER COMPILATION */ +@elideTypeInfo record MatchBuf { matchInput: String, matchInputExploded: Array, @@ -2184,6 +2194,7 @@ let matchBufChar = (buf: MatchBuf, pos: Number) => { } } +@elideTypeInfo enum StackElt { SEPositionProducer(Number => Option), SESavedGroup(Number, Option<(Number, Number)>), diff --git a/stdlib/uri.gr b/stdlib/uri.gr index cac6a15710..2795086f88 100644 --- a/stdlib/uri.gr +++ b/stdlib/uri.gr @@ -902,6 +902,7 @@ provide let make = ( return Ok({ scheme, userinfo, host, port, path, query, fragment }) } +@elideTypeInfo enum UpdateAction { KeepOriginal, UpdateTo(a),