Implement noreturn procedure declarations

This commit is contained in:
Eugen Wissner 2025-02-18 16:09:27 +01:00
parent 39750f4656
commit 0b835abfa9
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
7 changed files with 70 additions and 85 deletions

View File

@ -419,7 +419,13 @@ namespace boot
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
const bool exported, std::shared_ptr<top_type> 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 }
{
}

View File

@ -280,6 +280,9 @@ defer {
@ {
return yy::parser::make_AT(this->location);
}
! {
return yy::parser::make_EXCLAMATION(this->location);
}
. {
std::stringstream ss;

View File

@ -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),

View File

@ -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);

23
gcc/lang.opt Normal file
View File

@ -0,0 +1,23 @@
; lang.opt -- Options for the Elna front end.
; Copyright (C) 2025 Free Software Foundation, Inc.
;
; GCC is free software; you can redistribute it and/or modify it under
; the terms of the GNU General Public License as published by the Free
; Software Foundation; either version 3, or (at your option) any later
; version.
;
; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
; WARRANTY; without even the implied warranty of MERCHANTABILITY or
; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
; for more details.
;
; You should have received a copy of the GNU General Public License
; along with GCC; see the file COPYING3. If not see
; <http://www.gnu.org/licenses/>.
; See the GCC internals manual for a description of this file's format.
; Please try to keep this file in ASCII collating order.
Language
Elna

View File

@ -366,10 +366,16 @@ namespace boot
block *m_body{ nullptr };
public:
struct no_return_t
{
};
const bool no_return{ false };
std::vector<variable_declaration *> parameters;
procedure_definition(const struct position position, const std::string& identifier,
const bool exported, std::shared_ptr<top_type> 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<top_type> return_type();

View File

@ -60,6 +60,8 @@ const
TOKEN_CHARACTER* = 55
TOKEN_STRING* = 56
TOKEN_DEFER* = 57
TOKEN_EXCLAMATION* = 58
TOKEN_ARROW = 59
type
Position* = record
@ -92,20 +94,6 @@ type
tokenize: Bool
syntax_tree: Bool
end
Literal* = record
value: Int
end
ConstantDefinition* = record
name: ^Char
body: ^Literal
end
ConstantPart* = record
elements: ^^ConstantDefinition
count: Word
end
Program* = record
constants: ConstantPart
end
(*
External procedures.
@ -134,7 +122,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 +555,10 @@ begin
write_s("\"...\"")
elsif current_token^.kind = TOKEN_DEFER then
write_s("DEFER")
elsif current_token^.kind = TOKEN_EXCLAMATION then
write_c('!')
elsif current_token^.kind = TOKEN_ARROW then
write_s("->")
else
write_s("UNKNOWN<")
write_i(current_token^.kind)
@ -772,8 +764,16 @@ begin
current_token^.kind := TOKEN_PLUS
source_code := advance_source(source_code, 1u)
elsif first_char = '-' then
current_token^.kind := TOKEN_MINUS
source_code := advance_source(source_code, 1u)
if source_code.text.length = 0u then
current_token^.kind := TOKEN_MINUS
elsif source_code.text[1u] = '>' then
current_token^.kind := TOKEN_ARROW
source_code := advance_source(source_code, 1u)
else
current_token^.kind := TOKEN_MINUS
end
elsif first_char = '*' then
current_token^.kind := TOKEN_MULTIPLICATION
source_code := advance_source(source_code, 1u)
@ -800,6 +800,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,68 +821,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
result: ^ConstantDefinition
begin
result := cast(calloc(1u, ConstantDefinition.size): ^ConstantDefinition)
result^.name := cast(malloc(strlen(tokens^^.value.string_value)): ^Char)
strcpy(result^.name, tokens^^.value.string_value)
tokens^ := tokens^ + 2u
tokens_size := tokens_size - 2u
write_z(result^.name)
write_c('\n')
result^.body := parse_literal(tokens, tokens_size)
tokens^ := tokens^ + 2u
tokens_size := tokens_size - 2u
return result
end
proc parse_program(tokens: ^^Token, tokens_size: ^Word) -> ^Program;
var
result: ^Program
current_constant: ^^ConstantDefinition
begin
result := cast(calloc(1u, Program.size): ^Program)
result^.constants.elements := nil
result^.constants.count := 0u
if tokens^^.kind = TOKEN_CONST then
tokens^ := tokens^ + 1
tokens_size^ := tokens_size^ - 1u
while tokens_size^ > 0u and tokens^^.kind = TOKEN_IDENTIFIER do
result^.constants.elements := cast(
reallocarray(
cast(result^.constants.elements: ^Byte),
result^.constants.count + 1u,
(^ConstantDefinition).size
) : ^^ConstantDefinition)
current_constant := result^.constants.elements + result^.constants.count
result^.constants.count := result^.constants.count + 1u
current_constant^ := parse_constant_definition(tokens, tokens_size)
if current_constant^ = nil then
return nil
end
end
end
end
proc parse_command_line*(argc: Int, argv: ^^Char) -> ^CommandLine;
var
parameter: ^^Char
@ -943,9 +884,6 @@ begin
if command_line^.tokenize then
print_tokens(tokens, tokens_size)
end
if command_line^.syntax_tree then
parse_program(@tokens, @tokens_size)
end
return 0
end