Implement noreturn procedure declarations
This commit is contained in:
parent
39750f4656
commit
0b835abfa9
@ -419,7 +419,13 @@ namespace boot
|
|||||||
|
|
||||||
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
|
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
|
||||||
const bool exported, std::shared_ptr<top_type> return_type)
|
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 }
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,6 +280,9 @@ defer {
|
|||||||
@ {
|
@ {
|
||||||
return yy::parser::make_AT(this->location);
|
return yy::parser::make_AT(this->location);
|
||||||
}
|
}
|
||||||
|
! {
|
||||||
|
return yy::parser::make_EXCLAMATION(this->location);
|
||||||
|
}
|
||||||
. {
|
. {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
|
@ -85,13 +85,12 @@ along with GCC; see the file COPYING3. If not see
|
|||||||
%token CONST VAR PROCEDURE TYPE RECORD UNION
|
%token CONST VAR PROCEDURE TYPE RECORD UNION
|
||||||
%token BEGIN_BLOCK END_BLOCK EXTERN DEFER
|
%token BEGIN_BLOCK END_BLOCK EXTERN DEFER
|
||||||
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
|
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
|
||||||
%token AND OR NOT CAST SHIFT_LEFT SHIFT_RIGHT
|
%token NOT CAST EXCLAMATION
|
||||||
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
|
|
||||||
%token PLUS MINUS MULTIPLICATION DIVISION REMAINDER
|
|
||||||
%token ASSIGNMENT COLON HAT AT NIL ARROW
|
%token ASSIGNMENT COLON HAT AT NIL ARROW
|
||||||
|
|
||||||
%left OR AND XOR
|
%left OR AND XOR
|
||||||
%left EQUALS NOT_EQUAL LESS_THAN GREATER_THAN LESS_EQUAL GREATER_EQUAL
|
%left EQUALS NOT_EQUAL LESS_THAN GREATER_THAN LESS_EQUAL GREATER_EQUAL
|
||||||
|
%left SHIFT_LEFT SHIFT_RIGHT
|
||||||
%left PLUS MINUS
|
%left PLUS MINUS
|
||||||
%left MULTIPLICATION DIVISION REMAINDER
|
%left MULTIPLICATION DIVISION REMAINDER
|
||||||
|
|
||||||
@ -169,6 +168,12 @@ procedure_heading:
|
|||||||
$2.first, $2.second);
|
$2.first, $2.second);
|
||||||
std::swap($3, $$->parameters);
|
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
|
| PROCEDURE identifier_definition formal_parameter_list ARROW type_expression SEMICOLON
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1),
|
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1),
|
||||||
|
@ -256,6 +256,10 @@ namespace gcc
|
|||||||
tree fndecl = build_fn_decl(definition->identifier.c_str(), declaration_type);
|
tree fndecl = build_fn_decl(definition->identifier.c_str(), declaration_type);
|
||||||
this->symbol_map->enter(definition->identifier, fndecl);
|
this->symbol_map->enter(definition->identifier, fndecl);
|
||||||
|
|
||||||
|
if (definition->no_return)
|
||||||
|
{
|
||||||
|
TREE_THIS_VOLATILE(fndecl) = 1;
|
||||||
|
}
|
||||||
if (definition->body() != nullptr)
|
if (definition->body() != nullptr)
|
||||||
{
|
{
|
||||||
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, return_type);
|
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, return_type);
|
||||||
|
23
gcc/lang.opt
Normal file
23
gcc/lang.opt
Normal 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
|
@ -366,10 +366,16 @@ namespace boot
|
|||||||
block *m_body{ nullptr };
|
block *m_body{ nullptr };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
struct no_return_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
const bool no_return{ false };
|
||||||
std::vector<variable_declaration *> parameters;
|
std::vector<variable_declaration *> parameters;
|
||||||
|
|
||||||
procedure_definition(const struct position position, const std::string& identifier,
|
procedure_definition(const struct position position, const std::string& identifier,
|
||||||
const bool exported, std::shared_ptr<top_type> return_type = nullptr);
|
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;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
std::shared_ptr<top_type> return_type();
|
std::shared_ptr<top_type> return_type();
|
||||||
|
100
source.elna
100
source.elna
@ -60,6 +60,8 @@ const
|
|||||||
TOKEN_CHARACTER* = 55
|
TOKEN_CHARACTER* = 55
|
||||||
TOKEN_STRING* = 56
|
TOKEN_STRING* = 56
|
||||||
TOKEN_DEFER* = 57
|
TOKEN_DEFER* = 57
|
||||||
|
TOKEN_EXCLAMATION* = 58
|
||||||
|
TOKEN_ARROW = 59
|
||||||
|
|
||||||
type
|
type
|
||||||
Position* = record
|
Position* = record
|
||||||
@ -92,20 +94,6 @@ type
|
|||||||
tokenize: Bool
|
tokenize: Bool
|
||||||
syntax_tree: Bool
|
syntax_tree: Bool
|
||||||
end
|
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.
|
External procedures.
|
||||||
@ -134,7 +122,7 @@ proc strlen(ptr: ^Char) -> Word; extern
|
|||||||
proc strtol(nptr: ^Char, endptr: ^^Char, base: Int) -> Int; extern
|
proc strtol(nptr: ^Char, endptr: ^^Char, base: Int) -> Int; extern
|
||||||
|
|
||||||
proc perror(s: ^Char); extern
|
proc perror(s: ^Char); extern
|
||||||
proc exit(code: Int); extern
|
proc exit(code: Int) -> !; extern
|
||||||
|
|
||||||
(*
|
(*
|
||||||
Standard procedures.
|
Standard procedures.
|
||||||
@ -567,6 +555,10 @@ begin
|
|||||||
write_s("\"...\"")
|
write_s("\"...\"")
|
||||||
elsif current_token^.kind = TOKEN_DEFER then
|
elsif current_token^.kind = TOKEN_DEFER then
|
||||||
write_s("DEFER")
|
write_s("DEFER")
|
||||||
|
elsif current_token^.kind = TOKEN_EXCLAMATION then
|
||||||
|
write_c('!')
|
||||||
|
elsif current_token^.kind = TOKEN_ARROW then
|
||||||
|
write_s("->")
|
||||||
else
|
else
|
||||||
write_s("UNKNOWN<")
|
write_s("UNKNOWN<")
|
||||||
write_i(current_token^.kind)
|
write_i(current_token^.kind)
|
||||||
@ -772,8 +764,16 @@ begin
|
|||||||
current_token^.kind := TOKEN_PLUS
|
current_token^.kind := TOKEN_PLUS
|
||||||
source_code := advance_source(source_code, 1u)
|
source_code := advance_source(source_code, 1u)
|
||||||
elsif first_char = '-' then
|
elsif first_char = '-' then
|
||||||
current_token^.kind := TOKEN_MINUS
|
|
||||||
source_code := advance_source(source_code, 1u)
|
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
|
elsif first_char = '*' then
|
||||||
current_token^.kind := TOKEN_MULTIPLICATION
|
current_token^.kind := TOKEN_MULTIPLICATION
|
||||||
source_code := advance_source(source_code, 1u)
|
source_code := advance_source(source_code, 1u)
|
||||||
@ -800,6 +800,9 @@ begin
|
|||||||
elsif first_char = '@' then
|
elsif first_char = '@' then
|
||||||
current_token^.kind := TOKEN_AT
|
current_token^.kind := TOKEN_AT
|
||||||
source_code := advance_source(source_code, 1u)
|
source_code := advance_source(source_code, 1u)
|
||||||
|
elsif first_char = '!' then
|
||||||
|
current_token^.kind := TOKEN_EXCLAMATION
|
||||||
|
source_code := advance_source(source_code, 1u)
|
||||||
else
|
else
|
||||||
current_token^.kind := 0
|
current_token^.kind := 0
|
||||||
source_code := advance_source(source_code, 1u)
|
source_code := advance_source(source_code, 1u)
|
||||||
@ -818,68 +821,6 @@ begin
|
|||||||
return tokens
|
return tokens
|
||||||
end
|
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;
|
proc parse_command_line*(argc: Int, argv: ^^Char) -> ^CommandLine;
|
||||||
var
|
var
|
||||||
parameter: ^^Char
|
parameter: ^^Char
|
||||||
@ -943,9 +884,6 @@ begin
|
|||||||
if command_line^.tokenize then
|
if command_line^.tokenize then
|
||||||
print_tokens(tokens, tokens_size)
|
print_tokens(tokens, tokens_size)
|
||||||
end
|
end
|
||||||
if command_line^.syntax_tree then
|
|
||||||
parse_program(@tokens, @tokens_size)
|
|
||||||
end
|
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user