diff --git a/compiler/src/compile.re b/compiler/src/compile.re index 48d298309..50e97354a 100644 --- a/compiler/src/compile.re +++ b/compiler/src/compile.re @@ -127,9 +127,14 @@ let next_state = (~is_root_file=false, {cstate_desc, cstate_filename} as cs) => cleanup(); Parsed(parsed); | Parsed(p) => + let has_attr = name => + List.exists( + attr => attr.Asttypes.attr_name.txt == name, + p.attributes, + ); Grain_utils.Config.apply_attribute_flags( - ~no_pervasives=Option.is_some(p.attributes.no_pervasives), - ~runtime_mode=Option.is_some(p.attributes.runtime_mode), + ~no_pervasives=has_attr("noPervasives"), + ~runtime_mode=has_attr("runtimeMode"), ); if (is_root_file) { Grain_utils.Config.set_root_config(); diff --git a/compiler/src/formatting/fmt.re b/compiler/src/formatting/fmt.re index 7688147ac..3d1de593a 100644 --- a/compiler/src/formatting/fmt.re +++ b/compiler/src/formatting/fmt.re @@ -3921,12 +3921,8 @@ let print_comment_range = }; let print_program = (fmt, parsed_program) => { - let attrs = - Option.to_list(parsed_program.attributes.no_pervasives) - @ Option.to_list(parsed_program.attributes.runtime_mode); - let first_loc = - switch (attrs) { + switch (parsed_program.attributes) { | [fst, ..._] => fst.attr_loc | _ => parsed_program.prog_core_loc }; @@ -3995,38 +3991,37 @@ let print_program = (fmt, parsed_program) => { }; group @@ - fmt.print_comment_range( - fmt, - enclosing_start_location(parsed_program.prog_loc), - first_loc, + concat_map( + ~lead= + _ => + fmt.print_comment_range( + fmt, + enclosing_start_location(parsed_program.prog_loc), + first_loc, + ), + ~sep= + (prev, next) => + fmt.print_comment_range( + fmt, + ~none=hardline, + ~lead=space, + ~trail=hardline, + prev.Asttypes.attr_loc, + next.attr_loc, + ), + ~trail= + prev => + fmt.print_comment_range( + fmt, + ~none=hardline, + ~lead=space, + ~trail=hardline, + prev.Asttypes.attr_loc, + parsed_program.prog_core_loc, + ), + ~f=(~final, a) => fmt.print_attribute(fmt, a), + parsed_program.attributes, ) - ++ group( - concat_map( - ~lead=_ => empty, - ~sep= - (prev, next) => - fmt.print_comment_range( - fmt, - ~none=hardline, - ~lead=space, - ~trail=hardline, - prev.Asttypes.attr_loc, - next.attr_loc, - ), - ~trail= - prev => - fmt.print_comment_range( - fmt, - ~none=hardline, - ~lead=space, - ~trail=hardline, - prev.Asttypes.attr_loc, - parsed_program.prog_core_loc, - ), - ~f=(~final, a) => fmt.print_attribute(fmt, a), - attrs, - ), - ) ++ string("module ") ++ string(parsed_program.module_name.txt) ++ toplevel; diff --git a/compiler/src/parsing/driver.re b/compiler/src/parsing/driver.re index ea08748c5..3c5f0a0a3 100644 --- a/compiler/src/parsing/driver.re +++ b/compiler/src/parsing/driver.re @@ -150,6 +150,11 @@ let parse = (~name=?, lexbuf, source): Parsetree.parsed_program => { let read_imports = (program: Parsetree.parsed_program) => { open Parsetree_iter; + let module_has_attr = name => + List.exists( + attr => attr.Asttypes.attr_name.txt == name, + program.attributes, + ); let implicit_opens = List.map( o => { @@ -159,9 +164,8 @@ let read_imports = (program: Parsetree.parsed_program) => { } }, Grain_utils.Config.with_attribute_flags( - ~on_error=_ => (), - ~no_pervasives=Option.is_some(program.attributes.no_pervasives), - ~runtime_mode=Option.is_some(program.attributes.runtime_mode), + ~no_pervasives=module_has_attr("noPervasives"), + ~runtime_mode=module_has_attr("runtimeMode"), Grain_utils.Config.get_implicit_opens, ), ); diff --git a/compiler/src/parsing/parser_header.re b/compiler/src/parsing/parser_header.re index 65a035822..85d187251 100644 --- a/compiler/src/parsing/parser_header.re +++ b/compiler/src/parsing/parser_header.re @@ -121,36 +121,9 @@ let make_program = (~loc, ~core_loc, ~attributes, module_name, statements) => { // there's whitespace or comments let loc_start = {...loc.loc_start, pos_lnum: 1, pos_cnum: 0, pos_bol: 0}; let prog_loc = {...loc, loc_start}; - let (no_pervasives, runtime_mode) = - List.fold_left( - ((no_pervasives, runtime_mode), attr) => { - switch (attr) { - | Asttypes.{attr_name: {txt: "noPervasives"}, attr_args: []} => ( - Some(attr), - runtime_mode, - ) - | {attr_name: {txt: "runtimeMode"}, attr_args: []} => ( - no_pervasives, - Some(attr), - ) - | {attr_name: {loc}} => - raise( - SyntaxError( - loc, - "@noPervasives and @runtimeMode are the only valid top-level module attributes.", - ), - ) - } - }, - (None, None), - attributes, - ); fix_blocks({ - attributes: { - no_pervasives, - runtime_mode, - }, + attributes, module_name, statements, comments: [], diff --git a/compiler/src/parsing/parsetree.re b/compiler/src/parsing/parsetree.re index 3733ebec1..a500e69b8 100644 --- a/compiler/src/parsing/parsetree.re +++ b/compiler/src/parsing/parsetree.re @@ -501,6 +501,11 @@ type attribute = Asttypes.attribute; [@deriving (sexp, yojson)] type attributes = Asttypes.attributes; +type attribute_context = + | ModuleAttribute + | ToplevelAttribute + | ExpressionAttribute; + /** Type for expressions (i.e. things which evaluate to something) */ [@deriving (sexp, yojson)] @@ -691,15 +696,9 @@ type comment = /** The type for parsed programs */ -[@deriving (sexp, yojson)] -type module_attributes = { - no_pervasives: option(attribute), - runtime_mode: option(attribute), -}; - [@deriving (sexp, yojson)] type parsed_program = { - attributes: module_attributes, + attributes, module_name: loc(string), statements: list(toplevel_stmt), comments: list(comment), diff --git a/compiler/src/parsing/parsetree_iter.re b/compiler/src/parsing/parsetree_iter.re index fcb6d9e3c..57794ccf9 100644 --- a/compiler/src/parsing/parsetree_iter.re +++ b/compiler/src/parsing/parsetree_iter.re @@ -3,8 +3,8 @@ open Parsetree; type hooks = { enter_location: Location.t => unit, leave_location: Location.t => unit, - enter_attribute: attribute => unit, - leave_attribute: attribute => unit, + enter_attribute: (attribute, attribute_context) => unit, + leave_attribute: (attribute, attribute_context) => unit, enter_parsed_program: parsed_program => unit, leave_parsed_program: parsed_program => unit, enter_include: include_declaration => unit, @@ -73,20 +73,21 @@ let iter_ident = (hooks, id) => { }; let iter_attribute = - (hooks, {Asttypes.attr_name, attr_args, attr_loc} as attr) => { - hooks.enter_attribute(attr); + (hooks, attr_context, {Asttypes.attr_name, attr_args, attr_loc} as attr) => { + hooks.enter_attribute(attr, attr_context); iter_loc(hooks, attr_name); List.iter(iter_loc(hooks), attr_args); iter_location(hooks, attr_loc); - hooks.leave_attribute(attr); + hooks.leave_attribute(attr, attr_context); }; -let iter_attributes = (hooks, attrs) => { - List.iter(iter_attribute(hooks), attrs); +let iter_attributes = (hooks, attr_context, attrs) => { + List.iter(iter_attribute(hooks, attr_context), attrs); }; let rec iter_parsed_program = (hooks, {statements} as program) => { hooks.enter_parsed_program(program); + iter_attributes(hooks, ModuleAttribute, program.attributes); iter_toplevel_stmts(hooks, statements); hooks.leave_parsed_program(program); } @@ -108,7 +109,7 @@ and iter_toplevel_stmt = hooks.enter_toplevel_stmt(top); iter_location(hooks, loc); iter_location(hooks, core_loc); - iter_attributes(hooks, attrs); + iter_attributes(hooks, ToplevelAttribute, attrs); switch (desc) { | PTopInclude(id) => iter_include(hooks, id) | PTopProvide(ex) => iter_provide(hooks, ex) @@ -254,7 +255,7 @@ and iter_expression = hooks.enter_expression(expr); iter_location(hooks, loc); iter_location(hooks, core_loc); - iter_attributes(hooks, attrs); + iter_attributes(hooks, ExpressionAttribute, attrs); switch (desc) { | PExpId(i) => iter_ident(hooks, i) | PExpConstant(c) => iter_constant(hooks, c) @@ -524,8 +525,8 @@ let default_hooks = { enter_location: _ => (), leave_location: _ => (), - enter_attribute: _ => (), - leave_attribute: _ => (), + enter_attribute: (_, _) => (), + leave_attribute: (_, _) => (), enter_parsed_program: _ => (), leave_parsed_program: _ => (), diff --git a/compiler/src/parsing/parsetree_iter.rei b/compiler/src/parsing/parsetree_iter.rei index 39fdb965f..55e391533 100644 --- a/compiler/src/parsing/parsetree_iter.rei +++ b/compiler/src/parsing/parsetree_iter.rei @@ -3,8 +3,8 @@ open Parsetree; type hooks = { enter_location: Location.t => unit, leave_location: Location.t => unit, - enter_attribute: attribute => unit, - leave_attribute: attribute => unit, + enter_attribute: (attribute, attribute_context) => unit, + leave_attribute: (attribute, attribute_context) => unit, enter_parsed_program: parsed_program => unit, leave_parsed_program: parsed_program => unit, enter_include: include_declaration => unit, diff --git a/compiler/src/parsing/well_formedness.re b/compiler/src/parsing/well_formedness.re index fdabd97ad..39cbe1f79 100644 --- a/compiler/src/parsing/well_formedness.re +++ b/compiler/src/parsing/well_formedness.re @@ -11,7 +11,7 @@ type wferr = | RHSLetRecMayOnlyBeFunction(Location.t) | NoLetRecMut(Location.t) | RationalZeroDenominator(Location.t) - | UnknownAttribute(string, Location.t) + | UnknownAttribute(string, string, Location.t) | InvalidAttributeArity(string, int, Location.t) | AttributeDisallowed(string, Location.t) | LoopControlOutsideLoop(string, Location.t) @@ -49,8 +49,8 @@ let prepare_error = errorf(~loc, "let rec may not be used with the `mut` keyword.") | RationalZeroDenominator(loc) => errorf(~loc, "Rational numbers may not have a denominator of zero.") - | UnknownAttribute(attr, loc) => - errorf(~loc, "Unknown attribute `%s`.", attr) + | UnknownAttribute(attr_context, attr, loc) => + errorf(~loc, "Unknown %s attribute `%s`.", attr_context, attr) | InvalidAttributeArity(attr, arity, loc) => switch (arity) { | 0 => errorf(~loc, "Attribute `%s` expects no arguments.", attr) @@ -300,22 +300,40 @@ type known_attribute = { arity: int, }; -let known_attributes = [ - {name: "disableGC", arity: 0}, - {name: "unsafe", arity: 0}, - {name: "externalName", arity: 1}, -]; - let valid_attributes = (errs, super) => { let enter_attribute = - ({Asttypes.attr_name: {txt, loc}, attr_args: args} as attr) => { + ( + {Asttypes.attr_name: {txt, loc}, attr_args: args} as attr, + attr_context, + ) => { + let known_attributes = + switch (attr_context) { + | ModuleAttribute => [ + {name: "runtimeMode", arity: 0}, + {name: "noPervasives", arity: 0}, + ] + | ToplevelAttribute + | ExpressionAttribute => [ + {name: "disableGC", arity: 0}, + {name: "unsafe", arity: 0}, + {name: "externalName", arity: 1}, + ] + }; + switch (List.find_opt(({name}) => name == txt, known_attributes)) { | Some({arity}) when List.length(args) != arity => errs := [InvalidAttributeArity(txt, arity, loc), ...errs^] - | None => errs := [UnknownAttribute(txt, loc), ...errs^] + | None => + let context_string = + switch (attr_context) { + | ModuleAttribute => "module" + | ToplevelAttribute => "top-level" + | ExpressionAttribute => "expression" + }; + errs := [UnknownAttribute(context_string, txt, loc), ...errs^]; | _ => () }; - super.enter_attribute(attr); + super.enter_attribute(attr, attr_context); }; { diff --git a/compiler/src/utils/config.re b/compiler/src/utils/config.re index b56358f62..8bcca63f9 100644 --- a/compiler/src/utils/config.re +++ b/compiler/src/utils/config.re @@ -533,7 +533,7 @@ let apply_attribute_flags = (~no_pervasives as np, ~runtime_mode as rm) => { }; }; -let with_attribute_flags = (~on_error, ~no_pervasives, ~runtime_mode, thunk) => { +let with_attribute_flags = (~no_pervasives, ~runtime_mode, thunk) => { preserve_config(() => { apply_attribute_flags(~no_pervasives, ~runtime_mode); thunk(); diff --git a/compiler/src/utils/config.rei b/compiler/src/utils/config.rei index 23ab59080..bab3999d1 100644 --- a/compiler/src/utils/config.rei +++ b/compiler/src/utils/config.rei @@ -183,13 +183,7 @@ let with_cli_options: 'a => Cmdliner.Term.t('a); let apply_attribute_flags: (~no_pervasives: bool, ~runtime_mode: bool) => unit; let with_attribute_flags: - ( - ~on_error: [> | `Help | `Message(string)] => unit, - ~no_pervasives: bool, - ~runtime_mode: bool, - unit => 'a - ) => - 'a; + (~no_pervasives: bool, ~runtime_mode: bool, unit => 'a) => 'a; type implicit_opens = | Pervasives_mod diff --git a/compiler/test/runner.re b/compiler/test/runner.re index ddd5b0db2..af61b95a4 100644 --- a/compiler/test/runner.re +++ b/compiler/test/runner.re @@ -215,13 +215,8 @@ let doc = (file, arguments) => { let module_header = "module Test; "; -let create_module_attributes = attributes => - Grain_parsing.Parsetree.( - (Option.is_some(attributes.no_pervasives) ? "@noPervasives\n" : "") - ++ (Option.is_some(attributes.runtime_mode) ? "@runtimeMode\n" : "") - ); - -let makeSnapshotRunner = (~config_fn=?, test, name, prog) => { +let makeSnapshotRunner = + (~config_fn=?, test, ~default_module_header=true, name, prog) => { test(name, ({expect}) => { Config.preserve_all_configs(() => { ignore @@ @@ -229,17 +224,23 @@ let makeSnapshotRunner = (~config_fn=?, test, name, prog) => { ~hook=stop_after_object_file_emitted, ~config_fn?, name, - module_header ++ prog, + (if (default_module_header) {module_header} else {""}) ++ prog, ); expect.file(watfile(name)).toMatchSnapshot(); }) }); }; -let makeFilesizeRunner = (test, ~config_fn=?, name, prog, size) => { +let makeFilesizeRunner = + (test, ~config_fn=?, ~default_module_header=true, name, prog, size) => { test(name, ({expect}) => { Config.preserve_all_configs(() => { - ignore @@ compile(~config_fn?, name, module_header ++ prog); + ignore @@ + compile( + ~config_fn?, + name, + (if (default_module_header) {module_header} else {""}) ++ prog, + ); let ic = open_in_bin(wasmfile(name)); let filesize = in_channel_length(ic); close_in(ic); @@ -266,14 +267,19 @@ let makeSnapshotFileRunner = (test, ~config_fn=?, name, filename) => { }); }; -let makeCompileErrorRunner = (test, name, prog, msg) => { +let makeCompileErrorRunner = + (test, ~default_module_header=true, name, prog, msg) => { test( name, ({expect}) => { let error = try( { - ignore @@ compile(name, module_header ++ prog); + ignore @@ + compile( + name, + (if (default_module_header) {module_header} else {""}) ++ prog, + ); ""; } ) { @@ -284,21 +290,30 @@ let makeCompileErrorRunner = (test, name, prog, msg) => { ); }; -let makeWarningRunner = (test, name, prog, warning) => { +let makeWarningRunner = + (test, ~default_module_header=true, name, prog, warning) => { test(name, ({expect}) => { Config.preserve_all_configs(() => { Config.print_warnings := false; - ignore @@ compile(name, module_header ++ prog); + ignore @@ + compile( + name, + (if (default_module_header) {module_header} else {""}) ++ prog, + ); expect.ext.warning.toHaveTriggered(warning); }) }); }; -let makeNoWarningRunner = (test, name, prog) => { +let makeNoWarningRunner = (test, ~default_module_header=true, name, prog) => { test(name, ({expect}) => { Config.preserve_all_configs(() => { Config.print_warnings := false; - ignore @@ compile(name, module_header ++ prog); + ignore @@ + compile( + name, + (if (default_module_header) {module_header} else {""}) ++ prog, + ); expect.ext.warning.toHaveTriggeredNoWarnings(); }) }); @@ -310,7 +325,7 @@ let makeRunner = ~num_pages=?, ~config_fn=?, ~extra_args=?, - ~attributes=Test_utils.default_module_attributes, + ~default_module_header=true, name, prog, expected, @@ -322,7 +337,7 @@ let makeRunner = ~num_pages?, ~config_fn?, name, - create_module_attributes(attributes) ++ module_header ++ prog, + (if (default_module_header) {module_header} else {""}) ++ prog, ); let (result, _) = run(~num_pages?, ~extra_args?, wasmfile(name)); expect.string(result).toEqual(expected); @@ -336,13 +351,20 @@ let makeErrorRunner = ~check_exists=true, ~num_pages=?, ~config_fn=?, + ~default_module_header=true, name, prog, expected, ) => { test(name, ({expect}) => { Config.preserve_all_configs(() => { - ignore @@ compile(~num_pages?, ~config_fn?, name, module_header ++ prog); + ignore @@ + compile( + ~num_pages?, + ~config_fn?, + name, + (if (default_module_header) {module_header} else {""}) ++ prog, + ); let (result, _) = run(~num_pages?, wasmfile(name)); if (check_exists) { expect.string(result).toMatch(expected); diff --git a/compiler/test/suites/arrays.re b/compiler/test/suites/arrays.re index 93f5f3f9b..78db8998a 100644 --- a/compiler/test/suites/arrays.re +++ b/compiler/test/suites/arrays.re @@ -130,7 +130,7 @@ describe("arrays", ({test, testSkip}) => { state[0] = 5", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.expr( diff --git a/compiler/test/suites/basic_functionality.re b/compiler/test/suites/basic_functionality.re index 6d8dc9c42..61c0db13c 100644 --- a/compiler/test/suites/basic_functionality.re +++ b/compiler/test/suites/basic_functionality.re @@ -269,7 +269,7 @@ describe("basic functionality", ({test, testSkip}) => { type Über = Number |}, { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.data( diff --git a/compiler/test/suites/blocks.re b/compiler/test/suites/blocks.re index 2cb379d28..84b5b0fd2 100644 --- a/compiler/test/suites/blocks.re +++ b/compiler/test/suites/blocks.re @@ -12,7 +12,7 @@ describe("blocks", ({test}) => { "block_parse_lone_no_args_enum", "module Test; { Foo }", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.expr( diff --git a/compiler/test/suites/chars.re b/compiler/test/suites/chars.re index 9776a3214..eaf6095e2 100644 --- a/compiler/test/suites/chars.re +++ b/compiler/test/suites/chars.re @@ -91,7 +91,7 @@ Did you mean to create the string "\{\\"test\\": 1\}" instead?|}, "char_loc_simple", "module Test\n'a'", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mkloc( "Test", @@ -113,7 +113,7 @@ Did you mean to create the string "\{\\"test\\": 1\}" instead?|}, "char_loc_code", "module Test\n'\\u{1F3F4}'", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mkloc( "Test", @@ -135,7 +135,7 @@ Did you mean to create the string "\{\\"test\\": 1\}" instead?|}, "char_loc_emoji", "module Test\n'πŸ’―'", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mkloc( "Test", diff --git a/compiler/test/suites/comments.re b/compiler/test/suites/comments.re index be551a07f..418e0e5cd 100644 --- a/compiler/test/suites/comments.re +++ b/compiler/test/suites/comments.re @@ -12,7 +12,7 @@ describe("comments", ({test}) => { "comment_parse_1", "// Test\nmodule Test", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [], comments: [ @@ -30,7 +30,7 @@ describe("comments", ({test}) => { "comment_parse_2", "/* Test */module Test", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [], comments: [ @@ -48,7 +48,7 @@ describe("comments", ({test}) => { "comment_parse_block_multiline_trim", "/* Test\n Weird indent\n Normal indent */module Test", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [], comments: [ @@ -66,7 +66,7 @@ describe("comments", ({test}) => { "comment_parse_block_multiline_trim2", "/* Test\r\n Weird indent\r\n Normal indent */module Test", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [], comments: [ @@ -84,7 +84,7 @@ describe("comments", ({test}) => { "comment_parse_3", "/** Test */module Test", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [], comments: [ @@ -102,7 +102,7 @@ describe("comments", ({test}) => { "comment_parse_doc_multiline_trim_all_same_indent", "/**\n Test\n Weird indent\n Normal indent */module Test", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [], comments: [ @@ -120,7 +120,7 @@ describe("comments", ({test}) => { "comment_parse_doc_multiline_trim_keeps_differnt_indent", "/** Test\n Weird indent\n Normal indent */module Test", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [], comments: [ @@ -139,7 +139,7 @@ describe("comments", ({test}) => { // Note: There are explicit tab characters in this string to test them "/**\n Test\r\n Weird indent\r\n Normal indent */module Test", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [], comments: [ @@ -157,7 +157,7 @@ describe("comments", ({test}) => { "comment_parse_4", "#!/bin/grain\nmodule Test", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [], comments: [ @@ -175,7 +175,7 @@ describe("comments", ({test}) => { "comment_parse_block_deasterisk", "/* Test\n* no space before\n * space before\n * tab before\n *no space after */module Test", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [], comments: [ @@ -193,7 +193,7 @@ describe("comments", ({test}) => { "comment_parse_doc_deasterisk", "/** Test\n* no space before\n * space before\n * tab before\n *no space after */module Test", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [], comments: [ @@ -211,7 +211,7 @@ describe("comments", ({test}) => { "comment_parse_doc_deasterisk2", "/** Test\n* no space before\n * space before\n * tab before\n * trailing space after */module Test", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [], comments: [ diff --git a/compiler/test/suites/functions.re b/compiler/test/suites/functions.re index 16ade7c53..6ade12f80 100644 --- a/compiler/test/suites/functions.re +++ b/compiler/test/suites/functions.re @@ -150,9 +150,15 @@ describe("functions", ({test, testSkip}) => { assertCompileError("nonfunction_1", "let x = 5; x(3)", "type"); assertSnapshot("lambda_pat_any", "let x = (_) => 5; x(\"foo\")"); assertCompileError( - "unknown_attribute", + "unknown_toplevel_attribute", "@unknown let x = () => 5", - "Unknown attribute", + "Unknown top-level attribute", + ); + assertCompileError( + ~default_module_header=false, + "unknown_module_attribute", + "@unsafe module Test", + "Unknown module attribute", ); assertSnapshot( "func_record_associativity1", diff --git a/compiler/test/suites/parsing.re b/compiler/test/suites/parsing.re index b68127360..673ce81a0 100644 --- a/compiler/test/suites/parsing.re +++ b/compiler/test/suites/parsing.re @@ -46,7 +46,7 @@ describe("parsing", ({test, testSkip}) => { op, "module Test; a " ++ op ++ " b", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.expr( @@ -123,7 +123,7 @@ describe("parsing", ({test, testSkip}) => { "custom_op_precedence_1", "module Test; a +++ b *** c", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.expr( @@ -168,7 +168,7 @@ describe("parsing", ({test, testSkip}) => { "custom_op_precedence_2", "module Test; a &&-- b &-- c", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.expr( @@ -213,7 +213,7 @@ describe("parsing", ({test, testSkip}) => { "custom_op_precedence_3", "module Test; a ||-- b |-- c", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.expr( @@ -258,7 +258,7 @@ describe("parsing", ({test, testSkip}) => { "regression_issue_1473", "module Test; a << b >> c", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.expr( @@ -303,7 +303,7 @@ describe("parsing", ({test, testSkip}) => { "regression_issue_1609", "module Test; return -1", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.expr( @@ -372,7 +372,7 @@ describe("parsing", ({test, testSkip}) => { \xe2\x80\xa9 ", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [], comments: [], @@ -406,7 +406,7 @@ describe("parsing", ({test, testSkip}) => { "end_of_statement_linefeed", "module Test; a\x0ab", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.expr( @@ -429,7 +429,7 @@ describe("parsing", ({test, testSkip}) => { "end_of_statement_formfeed", "module Test; a\x0cb", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.expr( @@ -452,7 +452,7 @@ describe("parsing", ({test, testSkip}) => { "end_of_statement_carriagereturn", "module Test; a\x0db", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.expr( @@ -475,7 +475,7 @@ describe("parsing", ({test, testSkip}) => { "end_of_statement_crlf", "module Test; a\x0d\x0ab", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.expr( @@ -498,7 +498,7 @@ describe("parsing", ({test, testSkip}) => { "end_of_statement_nextline", "module Test; a\xc2\x85b", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.expr( @@ -521,7 +521,7 @@ describe("parsing", ({test, testSkip}) => { "end_of_statement_lineseparator", "module Test; a\xe2\x80\xa8b", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.expr( @@ -544,7 +544,7 @@ describe("parsing", ({test, testSkip}) => { "end_of_statement_paragraphseparator", "module Test; a\xe2\x80\xa9b", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mknoloc("Test"), statements: [ Toplevel.expr( diff --git a/compiler/test/suites/strings.re b/compiler/test/suites/strings.re index e5fd3bb1d..41f19cfb5 100644 --- a/compiler/test/suites/strings.re +++ b/compiler/test/suites/strings.re @@ -23,7 +23,7 @@ describe("strings", ({test, testSkip}) => { "string_parse_dqs1", "module Test; \"foo\"", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mkloc( "Test", @@ -44,7 +44,7 @@ describe("strings", ({test, testSkip}) => { "string_parse_dqs2", "module Test; \"bar\\nbaz\"", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mkloc( "Test", @@ -65,7 +65,7 @@ describe("strings", ({test, testSkip}) => { "string_parse_sqs1", "module Test; \"foobar\"", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mkloc( "Test", @@ -86,7 +86,7 @@ describe("strings", ({test, testSkip}) => { "string_parse_sqs2", "module Test; \"bar\\u{41}\"", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mkloc( "Test", @@ -107,7 +107,7 @@ describe("strings", ({test, testSkip}) => { "string_parse_sqs3", "module Test; \"bar\\x41\"", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mkloc( "Test", @@ -128,7 +128,7 @@ describe("strings", ({test, testSkip}) => { "string_parse_sqs4", "module Test; \"bar\\101\"", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mkloc( "Test", @@ -149,7 +149,7 @@ describe("strings", ({test, testSkip}) => { "string_parse_sqs5", "module Test; \"bar\\u0041\"", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mkloc( "Test", @@ -170,7 +170,7 @@ describe("strings", ({test, testSkip}) => { "string_parse_emoji_escape", "module Test; \"πŸ˜‚\"", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mkloc( "Test", @@ -192,7 +192,7 @@ describe("strings", ({test, testSkip}) => { "string_parse_emoji_literal", "module Test; \"πŸ’―\"", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mkloc( "Test", @@ -215,7 +215,7 @@ describe("strings", ({test, testSkip}) => { "string_loc_single_line", "module Test\n\"foo\"", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mkloc( "Test", @@ -237,7 +237,7 @@ describe("strings", ({test, testSkip}) => { "string_loc_multi_line", "module Test\n\"foo\nbar\nbaz\nqux\nquux\"", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mkloc( "Test", @@ -259,7 +259,7 @@ describe("strings", ({test, testSkip}) => { "string_loc_single_line_emoji", "module Test\n\"πŸ’―\"", { - attributes: Grain_tests.Test_utils.default_module_attributes, + attributes: [], module_name: Location.mkloc( "Test", diff --git a/compiler/test/test_utils.re b/compiler/test/test_utils.re index 8f759d271..e566f527e 100644 --- a/compiler/test/test_utils.re +++ b/compiler/test/test_utils.re @@ -39,6 +39,3 @@ let mk_loc = loc_ghost: false, }; }; - -let default_module_attributes = - Grain_parsing.Parsetree.{no_pervasives: None, runtime_mode: None};