From bd0e8f1ef19e47c077453add25d9fd4a9de1bdfa Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 20 Oct 2022 23:54:36 +0200 Subject: [PATCH] Allow imports anywhere in the module outside of ct statements. --- src/compiler/parse_global.c | 35 ++++++++++--------- src/compiler/parser.c | 3 +- src/compiler/parser_internal.h | 3 +- src/version.h | 2 +- .../import/import_error_out_of_order.c3 | 6 +++- .../import/import_error_out_of_order.c3 | 6 +++- 6 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 64ab28431..0cfce026d 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -90,7 +90,8 @@ static inline bool parse_top_level_block(ParseContext *c, Decl ***decls, TokenTy CONSUME_OR_RET(TOKEN_COLON, false); while (!tok_is(c, end1) && !tok_is(c, end2) && !tok_is(c, end3) && !tok_is(c, TOKEN_EOF)) { - Decl *decl = parse_top_level_statement(c); + Decl *decl = parse_top_level_statement(c, false); + if (!decl) continue; assert(decl); if (decl_ok(decl)) { @@ -172,7 +173,7 @@ static inline Decl *parse_ct_case(ParseContext *c) { TokenType type = c->tok; if (type == TOKEN_CT_DEFAULT || type == TOKEN_CT_CASE || type == TOKEN_CT_ENDSWITCH) break; - ASSIGN_DECL_OR_RET(Decl * stmt, parse_top_level_statement(c), poisoned_decl); + ASSIGN_DECL_OR_RET(Decl * stmt, parse_top_level_statement(c, false), poisoned_decl); vec_add(decl->ct_case_decl.body, stmt); } return decl; @@ -2280,17 +2281,6 @@ static inline bool parse_import(ParseContext *c) } -/** - * imports ::= import* - */ -void parse_imports(ParseContext *c) -{ - while (tok_is(c, TOKEN_IMPORT)) - { - if (!parse_import(c)) recover_top_level(c); - } -} - static inline bool parse_doc_contract(ParseContext *c, AstId **docs_ref, DocDirectiveKind kind) @@ -2529,7 +2519,7 @@ static bool parse_docs(ParseContext *c, AstId *docs_ref) * @param visibility * @return Decl* or a poison value if parsing failed */ -Decl *parse_top_level_statement(ParseContext *c) +Decl *parse_top_level_statement(ParseContext *c, bool allow_import) { AstId docs = 0; if (!parse_docs(c, &docs)) return poisoned_decl; @@ -2604,6 +2594,20 @@ Decl *parse_top_level_statement(ParseContext *c) } break; } + case TOKEN_IMPORT: + if (!check_no_visibility_before(c, visibility)) return poisoned_decl; + if (!allow_import) + { + SEMA_ERROR_HERE("'import' may not appear inside a compile time statement."); + return poisoned_decl; + } + if (!parse_import(c)) return poisoned_decl; + if (docs) + { + SEMA_ERROR(astptr(docs), "Unexpected doc comment before import, did you mean to use a regular comment?"); + return poisoned_decl; + } + return NULL; case TOKEN_CT_SWITCH: { if (!check_no_visibility_before(c, visibility)) return poisoned_decl; @@ -2664,9 +2668,6 @@ Decl *parse_top_level_statement(ParseContext *c) } } return poisoned_decl; - case TOKEN_IMPORT: - SEMA_ERROR_HERE("Imports are only allowed directly after the module declaration."); - return poisoned_decl; case TOKEN_TLOCAL: case TYPELIKE_TOKENS: { diff --git a/src/compiler/parser.c b/src/compiler/parser.c index 053a6c7ac..1b20cfd55 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -66,7 +66,6 @@ static inline void parse_translation_unit(ParseContext *c) advance(c); NEXT_CONTEXT: if (!parse_module(c)) return; - parse_imports(c); while (!tok_is(c, TOKEN_EOF)) { if (tok_is(c, TOKEN_MODULE)) @@ -77,7 +76,7 @@ static inline void parse_translation_unit(ParseContext *c) c = new_context; goto NEXT_CONTEXT; } - Decl *decl = parse_top_level_statement(c); + Decl *decl = parse_top_level_statement(c, true); if (!decl) continue; if (decl_ok(decl)) { diff --git a/src/compiler/parser_internal.h b/src/compiler/parser_internal.h index b6e22567f..2b6a76696 100644 --- a/src/compiler/parser_internal.h +++ b/src/compiler/parser_internal.h @@ -16,7 +16,7 @@ #define TRY_CONSUME_AFTER(_tok, _message, _type) do { if (!try_consume(c, _tok)) { sema_error_at_after(c->prev_span, _message); return _type; } } while(0) #define CHECK_EXPR_OR_RET(_expr) do { if (!expr_ok(_expr)) return _expr; } while(0) -Decl *parse_top_level_statement(ParseContext *c); +Decl *parse_top_level_statement(ParseContext *c, bool allow_import); Ast *parse_ct_assert_stmt(ParseContext *c); Ast *parse_stmt(ParseContext *c); Path *parse_path_prefix(ParseContext *c, bool *had_error); @@ -27,7 +27,6 @@ TypeInfo *parse_type(ParseContext *c); TypeInfo *parse_optional_type(ParseContext *c); TypeInfo *parse_type_with_base(ParseContext *c, TypeInfo *type_info); Expr* parse_constant_expr(ParseContext *c); -void parse_imports(ParseContext *c); Decl *parse_decl(ParseContext *c); Expr *parse_integer(ParseContext *c, Expr *left); Expr *parse_decl_or_expr(ParseContext *c, Decl **decl_ref); diff --git a/src/version.h b/src/version.h index 2b872268b..28b3a48a3 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.3.91" \ No newline at end of file +#define COMPILER_VERSION "0.3.92" \ No newline at end of file diff --git a/test/test_suite/import/import_error_out_of_order.c3 b/test/test_suite/import/import_error_out_of_order.c3 index 63e28ae0c..cee46debc 100644 --- a/test/test_suite/import/import_error_out_of_order.c3 +++ b/test/test_suite/import/import_error_out_of_order.c3 @@ -2,4 +2,8 @@ module foo; fn void hello() {} -import bar; // #error: Imports are only allowed directly after the module declaration \ No newline at end of file +$if (true): + +import bar; // #error: 'import' may not appear inside a compile + +$endif; \ No newline at end of file diff --git a/test/test_suite2/import/import_error_out_of_order.c3 b/test/test_suite2/import/import_error_out_of_order.c3 index 63e28ae0c..cee46debc 100644 --- a/test/test_suite2/import/import_error_out_of_order.c3 +++ b/test/test_suite2/import/import_error_out_of_order.c3 @@ -2,4 +2,8 @@ module foo; fn void hello() {} -import bar; // #error: Imports are only allowed directly after the module declaration \ No newline at end of file +$if (true): + +import bar; // #error: 'import' may not appear inside a compile + +$endif; \ No newline at end of file