From 4d4976b4cd76e84fe1fdeadbea7381c28519d2f4 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Tue, 18 Feb 2025 16:09:27 +0100 Subject: [PATCH] Implement noreturn procedure declarations --- boot/ast.cc | 8 +++++++- boot/lexer.ll | 3 +++ boot/parser.yy | 11 ++++++++--- gcc/elna-generic.cc | 4 ++++ include/elna/boot/ast.h | 6 ++++++ source.elna | 15 +++++++-------- 6 files changed, 35 insertions(+), 12 deletions(-) diff --git a/boot/ast.cc b/boot/ast.cc index a1ff75d..7755998 100644 --- a/boot/ast.cc +++ b/boot/ast.cc @@ -419,7 +419,13 @@ namespace boot procedure_definition::procedure_definition(const struct position position, const std::string& identifier, const bool exported, std::shared_ptr return_type) - : definition(position, identifier, exported), m_return_type(return_type) + : definition(position, identifier, exported), m_return_type(return_type), no_return{ false } + { + } + + procedure_definition::procedure_definition(const struct position position, const std::string& identifier, + const bool exported, no_return_t) + : definition(position, identifier, exported), m_return_type(nullptr), no_return{ true } { } diff --git a/boot/lexer.ll b/boot/lexer.ll index 574cbcf..cb8837a 100644 --- a/boot/lexer.ll +++ b/boot/lexer.ll @@ -280,6 +280,9 @@ defer { @ { return yy::parser::make_AT(this->location); } +! { + return yy::parser::make_EXCLAMATION(this->location); + } . { std::stringstream ss; diff --git a/boot/parser.yy b/boot/parser.yy index bf12292..f5362e0 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -85,13 +85,12 @@ along with GCC; see the file COPYING3. If not see %token CONST VAR PROCEDURE TYPE RECORD UNION %token BEGIN_BLOCK END_BLOCK EXTERN DEFER %token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA -%token AND OR NOT CAST SHIFT_LEFT SHIFT_RIGHT -%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS -%token PLUS MINUS MULTIPLICATION DIVISION REMAINDER +%token NOT CAST EXCLAMATION %token ASSIGNMENT COLON HAT AT NIL ARROW %left OR AND XOR %left EQUALS NOT_EQUAL LESS_THAN GREATER_THAN LESS_EQUAL GREATER_EQUAL +%left SHIFT_LEFT SHIFT_RIGHT %left PLUS MINUS %left MULTIPLICATION DIVISION REMAINDER @@ -169,6 +168,12 @@ procedure_heading: $2.first, $2.second); std::swap($3, $$->parameters); } + | PROCEDURE identifier_definition formal_parameter_list ARROW EXCLAMATION SEMICOLON + { + $$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), + $2.first, $2.second, elna::boot::procedure_definition::no_return_t{}); + std::swap($3, $$->parameters); + } | PROCEDURE identifier_definition formal_parameter_list ARROW type_expression SEMICOLON { $$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index 292c0c6..092d226 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -256,6 +256,10 @@ namespace gcc tree fndecl = build_fn_decl(definition->identifier.c_str(), declaration_type); this->symbol_map->enter(definition->identifier, fndecl); + if (definition->no_return) + { + TREE_THIS_VOLATILE(fndecl) = 1; + } if (definition->body() != nullptr) { tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, return_type); diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index cbb437e..e569503 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -366,10 +366,16 @@ namespace boot block *m_body{ nullptr }; public: + struct no_return_t + { + }; + const bool no_return{ false }; std::vector parameters; procedure_definition(const struct position position, const std::string& identifier, const bool exported, std::shared_ptr return_type = nullptr); + procedure_definition(const struct position position, const std::string& identifier, + const bool exported, no_return_t); virtual void accept(parser_visitor *visitor) override; std::shared_ptr return_type(); diff --git a/source.elna b/source.elna index 1ad15f9..187872e 100644 --- a/source.elna +++ b/source.elna @@ -60,6 +60,7 @@ const TOKEN_CHARACTER* = 55 TOKEN_STRING* = 56 TOKEN_DEFER* = 57 + TOKEN_EXCLAMATION* = 58 type Position* = record @@ -134,7 +135,7 @@ proc strlen(ptr: ^Char) -> Word; extern proc strtol(nptr: ^Char, endptr: ^^Char, base: Int) -> Int; extern proc perror(s: ^Char); extern -proc exit(code: Int); extern +proc exit(code: Int) -> !; extern (* Standard procedures. @@ -567,6 +568,8 @@ begin write_s("\"...\"") elsif current_token^.kind = TOKEN_DEFER then write_s("DEFER") + elsif current_token^.kind = TOKEN_EXCLAMATION then + write_c('!') else write_s("UNKNOWN<") write_i(current_token^.kind) @@ -800,6 +803,9 @@ begin elsif first_char = '@' then current_token^.kind := TOKEN_AT source_code := advance_source(source_code, 1u) + elsif first_char = '!' then + current_token^.kind := TOKEN_EXCLAMATION + source_code := advance_source(source_code, 1u) else current_token^.kind := 0 source_code := advance_source(source_code, 1u) @@ -818,11 +824,6 @@ begin return tokens end -proc parse_literal(tokens: ^^Token, tokens_size: ^Word) -> ^Literal; -begin - return cast(calloc(1u, Literal.size): ^Literal) -end - proc parse_constant_definition(tokens: ^^Token, tokens_size: ^Word) -> ^ConstantDefinition; var @@ -839,8 +840,6 @@ begin write_z(result^.name) write_c('\n') - result^.body := parse_literal(tokens, tokens_size) - tokens^ := tokens^ + 2u tokens_size := tokens_size - 2u