Rename boot namespace to frontend

This commit is contained in:
2025-11-26 20:46:41 +01:00
parent c95466622a
commit 4746bf8242
29 changed files with 421 additions and 421 deletions

View File

@@ -9,44 +9,3 @@ representation for a such high-level hypothetical programming language.
## File extension ## File extension
.elna .elna
## Current implementation
This repository contains a GCC frontend for Elna. After finishing the frontend
I'm planning to rewrite the compiler in Elna itself with its own backend and
a hand-written parser. So GCC gives a way to have a simple bootstrap compiler
and a possbility to compile Elna programs for different platforms.
## Grammar
Flex and bison grammar specifications, `lexer.ll` and `parser.yy`, can be found
in the `boot/` directory.
## Build
The frontend requires GCC 15.1.0 (not tested with other versions).
Download the GCC source. Copy the contents of this repository into `gcc/elna`
inside GCC. Finally build GCC enabling the frontend with
`--enable-languages=c,c++,elna`. After the installation the compiler can be
invoked with `$prefix/bin/gelna`.
There is also a `Rakefile` that downloads, builds and installs GCC into the
`./build/` subdirectory. The `Rakefile` assumes that ruby and rake, as well as
all GCC dependencies are already available in the system. It works under Linux
and Mac OS. In the latter case GCC is patched with the patches used by Homebrew
(official GCC doesn't support Apple silicon targets). Invoke with
```sh
rake boot
```
`gcc` binary is used by default, but a different gcc version can be specified
by passing `CC` and `CXX` environment variables to rake, e.g.:
```sh
rake CC=gcc-15 CXX=g++-15 boot
```
See `rake -T` for more tasks. The GCC source is under `build/tools`. The
installation path is `build/host/install`.

View File

@@ -2,42 +2,8 @@
# v. 2.0. If a copy of the MPL was not distributed with this file, You can # v. 2.0. If a copy of the MPL was not distributed with this file, You can
# obtain one at https://mozilla.org/MPL/2.0/. # obtain one at https://mozilla.org/MPL/2.0/.
require 'pathname'
require 'rake/clean' require 'rake/clean'
TMP = Pathname.new('./build') CLOBBER.include 'build'
HOST_INSTALL = TMP + 'host/install'
CLOBBER.include TMP task default: :source
CLEAN.include(TMP + 'boot')
directory HOST_INSTALL
task default: ['source/main.elna', TMP + 'boot/elna'] do |t|
sources, compiler = t.prerequisites.partition { |f| f.end_with? '.elna' }
sh *compiler, '--parse', *sources
end
rule(/boot\/.+\.o$/ => ->(file) {
source = Pathname.new('source') +
Pathname.new(file).relative_path_from(TMP + 'boot').sub_ext('.elna')
[HOST_INSTALL + 'bin/gelna', source]
}) do |t|
Pathname.new(t.name).dirname.mkpath
sources, compiler = t.prerequisites.partition { |source| source.end_with? '.elna' }
sh *compiler, '-c', '-O0', '-g', '-o', t.name, *sources
end
file TMP + 'boot/elna' => FileList['source/**/*.elna'].reject { |file|
file != file.downcase
}.map { |file|
TMP + 'boot' +
Pathname.new(file).relative_path_from('source').sub_ext('.o')
} do |t|
compiler = HOST_INSTALL + 'bin/gcc'
sh compiler.to_path, '-o', t.name, *t.prerequisites
end

View File

@@ -15,9 +15,9 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include "elna/boot/ast.h" #include "elna/frontend/ast.h"
namespace elna::boot namespace elna::frontend
{ {
void empty_visitor::not_implemented() void empty_visitor::not_implemented()
{ {

View File

@@ -15,17 +15,17 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include "elna/boot/dependency.h" #include "elna/frontend/dependency.h"
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <string.h> #include <string.h>
#include "elna/boot/driver.h" #include "elna/frontend/driver.h"
#include "elna/boot/semantic.h" #include "elna/frontend/semantic.h"
#include "parser.hh" #include "parser.hh"
namespace elna::boot namespace elna::frontend
{ {
dependency::dependency(const char *path) dependency::dependency(const char *path)
: error_container(path) : error_container(path)

View File

@@ -15,9 +15,9 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include "elna/boot/driver.h" #include "elna/frontend/driver.h"
namespace elna::boot namespace elna::frontend
{ {
position make_position(const yy::location& location) position make_position(const yy::location& location)
{ {

View File

@@ -23,7 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "parser.hh" #include "parser.hh"
#undef YY_DECL #undef YY_DECL
#define YY_DECL yy::parser::symbol_type elna::boot::lexer::lex(driver& driver) #define YY_DECL yy::parser::symbol_type elna::frontend::lexer::lex(driver& driver)
#define yyterminate() return yy::parser::make_YYEOF(this->location) #define yyterminate() return yy::parser::make_YYEOF(this->location)
%} %}

View File

@@ -25,25 +25,20 @@ along with GCC; see the file COPYING3. If not see
%code requires { %code requires {
#include <cstdint> #include <cstdint>
#include <iostream> #include <iostream>
#include "elna/boot/driver.h" #include "elna/frontend/driver.h"
#if !defined(yyFlexLexerOnce) #if !defined(yyFlexLexerOnce)
#include <FlexLexer.h> #include <FlexLexer.h>
#endif #endif
namespace elna namespace elna::frontend
{
namespace boot
{ {
class lexer; class lexer;
} }
}
} }
%code provides { %code provides {
namespace elna namespace elna::frontend
{
namespace boot
{ {
class lexer: public yyFlexLexer class lexer: public yyFlexLexer
@@ -60,15 +55,14 @@ along with GCC; see the file COPYING3. If not see
}; };
} }
}
} }
%define api.token.raw %define api.token.raw
%define api.token.constructor %define api.token.constructor
%define api.value.type variant %define api.value.type variant
%parse-param {elna::boot::lexer& lexer} %parse-param {elna::frontend::lexer& lexer}
%param {elna::boot::driver& driver} %param {elna::frontend::driver& driver}
%locations %locations
%header %header
@@ -129,48 +123,48 @@ along with GCC; see the file COPYING3. If not see
%left "+" "-" %left "+" "-"
%left "*" "/" "%" %left "*" "/" "%"
%type <elna::boot::literal_expression *> literal; %type <elna::frontend::literal_expression *> literal;
%type <std::vector<elna::boot::expression *>> case_labels; %type <std::vector<elna::frontend::expression *>> case_labels;
%type <elna::boot::switch_case> switch_case; %type <elna::frontend::switch_case> switch_case;
%type <std::vector<elna::boot::switch_case>> switch_cases; %type <std::vector<elna::frontend::switch_case>> switch_cases;
%type <elna::boot::constant_declaration *> constant_declaration; %type <elna::frontend::constant_declaration *> constant_declaration;
%type <std::vector<elna::boot::constant_declaration *>> constant_part constant_declarations; %type <std::vector<elna::frontend::constant_declaration *>> constant_part constant_declarations;
%type <elna::boot::variable_declaration *> variable_declaration; %type <elna::frontend::variable_declaration *> variable_declaration;
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part; %type <std::vector<elna::frontend::variable_declaration *>> variable_declarations variable_part;
%type <elna::boot::type_expression *> type_expression; %type <elna::frontend::type_expression *> type_expression;
%type <std::vector<elna::boot::type_expression *>> type_expressions; %type <std::vector<elna::frontend::type_expression *>> type_expressions;
%type <elna::boot::traits_expression *> traits_expression; %type <elna::frontend::traits_expression *> traits_expression;
%type <elna::boot::expression *> expression operand simple_expression; %type <elna::frontend::expression *> expression operand simple_expression;
%type <elna::boot::unary_expression *> unary_expression; %type <elna::frontend::unary_expression *> unary_expression;
%type <elna::boot::binary_expression *> binary_expression; %type <elna::frontend::binary_expression *> binary_expression;
%type <std::vector<elna::boot::expression *>> expressions actual_parameter_list; %type <std::vector<elna::frontend::expression *>> expressions actual_parameter_list;
%type <elna::boot::designator_expression *> designator_expression; %type <elna::frontend::designator_expression *> designator_expression;
%type <elna::boot::procedure_call*> call_expression; %type <elna::frontend::procedure_call*> call_expression;
%type <elna::boot::return_statement *> return_statement; %type <elna::frontend::return_statement *> return_statement;
%type <elna::boot::statement *> statement; %type <elna::frontend::statement *> statement;
%type <std::vector<elna::boot::statement *>> required_statements optional_statements statement_part; %type <std::vector<elna::frontend::statement *>> required_statements optional_statements statement_part;
%type <elna::boot::procedure_declaration *> procedure_declaration; %type <elna::frontend::procedure_declaration *> procedure_declaration;
%type <std::pair<std::vector<std::string>, elna::boot::procedure_type_expression *>> procedure_heading; %type <std::pair<std::vector<std::string>, elna::frontend::procedure_type_expression *>> procedure_heading;
%type <elna::boot::procedure_type_expression::return_t> return_declaration; %type <elna::frontend::procedure_type_expression::return_t> return_declaration;
%type <std::vector<elna::boot::procedure_declaration *>> procedure_declarations procedure_part; %type <std::vector<elna::frontend::procedure_declaration *>> procedure_declarations procedure_part;
%type <elna::boot::type_declaration *> type_declaration; %type <elna::frontend::type_declaration *> type_declaration;
%type <std::vector<elna::boot::type_declaration *>> type_declarations type_part; %type <std::vector<elna::frontend::type_declaration *>> type_declarations type_part;
%type <std::unique_ptr<elna::boot::block>> block; %type <std::unique_ptr<elna::frontend::block>> block;
%type <elna::boot::field_declaration> field_declaration formal_parameter; %type <elna::frontend::field_declaration> field_declaration formal_parameter;
%type <std::vector<std::pair<std::string, elna::boot::type_expression *>>> %type <std::vector<std::pair<std::string, elna::frontend::type_expression *>>>
optional_fields required_fields formal_parameters formal_parameter_list; optional_fields required_fields formal_parameters formal_parameter_list;
%type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements; %type <std::vector<elna::frontend::conditional_statements *>> elsif_then_statements elsif_do_statements;
%type <std::vector<elna::boot::statement *> *> else_statements; %type <std::vector<elna::frontend::statement *> *> else_statements;
%type <elna::boot::cast_expression *> cast_expression; %type <elna::frontend::cast_expression *> cast_expression;
%type <elna::boot::identifier_definition> identifier_definition; %type <elna::frontend::identifier_definition> identifier_definition;
%type <std::vector<elna::boot::identifier_definition>> identifier_definitions; %type <std::vector<elna::frontend::identifier_definition>> identifier_definitions;
%type <std::vector<std::string>> identifiers import_declaration; %type <std::vector<std::string>> identifiers import_declaration;
%type <std::vector<elna::boot::import_declaration *>> import_declarations import_part; %type <std::vector<elna::frontend::import_declaration *>> import_declarations import_part;
%% %%
program: program:
"program" ";" import_part constant_part type_part variable_part procedure_part statement_part "end" "." "program" ";" import_part constant_part type_part variable_part procedure_part statement_part "end" "."
{ {
auto tree = new boot::program(boot::make_position(@1)); auto tree = new frontend::program(frontend::make_position(@1));
std::swap(tree->imports, $3); std::swap(tree->imports, $3);
std::swap(tree->constants, $4); std::swap(tree->constants, $4);
@@ -183,7 +177,7 @@ program:
} }
| "module" ";" import_part constant_part type_part variable_part procedure_part "end" "." | "module" ";" import_part constant_part type_part variable_part procedure_part "end" "."
{ {
auto tree = new boot::unit(boot::make_position(@1)); auto tree = new frontend::unit(frontend::make_position(@1));
std::swap(tree->imports, $3); std::swap(tree->imports, $3);
std::swap(tree->constants, $4); std::swap(tree->constants, $4);
@@ -195,7 +189,7 @@ program:
} }
block: constant_part variable_part statement_part "end" block: constant_part variable_part statement_part "end"
{ {
$$ = std::make_unique<boot::block>(std::move($1), std::move($2), std::move($3)); $$ = std::make_unique<frontend::block>(std::move($1), std::move($2), std::move($3));
} }
statement_part: statement_part:
/* no statements */ {} /* no statements */ {}
@@ -207,8 +201,8 @@ statement_part:
$$.push_back($4); $$.push_back($4);
} }
identifier_definition: identifier_definition:
IDENTIFIER "*" { $$ = boot::identifier_definition{ $1, true }; } IDENTIFIER "*" { $$ = frontend::identifier_definition{ $1, true }; }
| IDENTIFIER { $$ = boot::identifier_definition{ $1, false }; } | IDENTIFIER { $$ = frontend::identifier_definition{ $1, false }; }
identifier_definitions: identifier_definitions:
identifier_definition "," identifier_definitions identifier_definition "," identifier_definitions
{ {
@@ -218,11 +212,11 @@ identifier_definitions:
| identifier_definition { $$.emplace_back(std::move($1)); } | identifier_definition { $$.emplace_back(std::move($1)); }
return_declaration: return_declaration:
/* proper procedure */ {} /* proper procedure */ {}
| "->" "!" { $$ = boot::procedure_type_expression::return_t(std::monostate{}); } | "->" "!" { $$ = frontend::procedure_type_expression::return_t(std::monostate{}); }
| "->" type_expression { $$ = boot::procedure_type_expression::return_t($2); } | "->" type_expression { $$ = frontend::procedure_type_expression::return_t($2); }
procedure_heading: formal_parameter_list return_declaration procedure_heading: formal_parameter_list return_declaration
{ {
$$.second = new boot::procedure_type_expression(boot::make_position(@1), std::move($2)); $$.second = new frontend::procedure_type_expression(frontend::make_position(@1), std::move($2));
for (auto& [name, type] : $1) for (auto& [name, type] : $1)
{ {
$$.first.emplace_back(std::move(name)); $$.first.emplace_back(std::move(name));
@@ -232,12 +226,12 @@ procedure_heading: formal_parameter_list return_declaration
procedure_declaration: procedure_declaration:
"proc" identifier_definition procedure_heading ";" block ";" "proc" identifier_definition procedure_heading ";" block ";"
{ {
$$ = new boot::procedure_declaration(boot::make_position(@1), std::move($2), $3.second, std::move(*$5)); $$ = new frontend::procedure_declaration(frontend::make_position(@1), std::move($2), $3.second, std::move(*$5));
std::swap($3.first, $$->parameter_names); std::swap($3.first, $$->parameter_names);
} }
| "proc" identifier_definition procedure_heading ";" "extern" ";" | "proc" identifier_definition procedure_heading ";" "extern" ";"
{ {
$$ = new boot::procedure_declaration(boot::make_position(@1), std::move($2), $3.second); $$ = new frontend::procedure_declaration(frontend::make_position(@1), std::move($2), $3.second);
std::swap($3.first, $$->parameter_names); std::swap($3.first, $$->parameter_names);
} }
procedure_declarations: procedure_declarations:
@@ -252,44 +246,44 @@ procedure_part:
| procedure_declarations { std::swap($$, $1); } | procedure_declarations { std::swap($$, $1); }
call_expression: designator_expression actual_parameter_list call_expression: designator_expression actual_parameter_list
{ {
$$ = new boot::procedure_call(boot::make_position(@1), $1); $$ = new frontend::procedure_call(frontend::make_position(@1), $1);
std::swap($$->arguments, $2); std::swap($$->arguments, $2);
} }
cast_expression: "cast" "(" expression ":" type_expression ")" cast_expression: "cast" "(" expression ":" type_expression ")"
{ $$ = new boot::cast_expression(boot::make_position(@1), $5, $3); } { $$ = new frontend::cast_expression(frontend::make_position(@1), $5, $3); }
elsif_do_statements: elsif_do_statements:
"elsif" expression "do" optional_statements elsif_do_statements "elsif" expression "do" optional_statements elsif_do_statements
{ {
boot::conditional_statements *branch = new boot::conditional_statements($2, std::move($4)); frontend::conditional_statements *branch = new frontend::conditional_statements($2, std::move($4));
std::swap($5, $$); std::swap($5, $$);
$$.emplace($$.begin(), branch); $$.emplace($$.begin(), branch);
} }
| {} | {}
else_statements: else_statements:
"else" optional_statements { $$ = new std::vector<boot::statement *>(std::move($2)); } "else" optional_statements { $$ = new std::vector<frontend::statement *>(std::move($2)); }
| { $$ = nullptr; } | { $$ = nullptr; }
elsif_then_statements: elsif_then_statements:
"elsif" expression "then" optional_statements elsif_then_statements "elsif" expression "then" optional_statements elsif_then_statements
{ {
boot::conditional_statements *branch = new boot::conditional_statements($2, std::move($4)); frontend::conditional_statements *branch = new frontend::conditional_statements($2, std::move($4));
std::swap($5, $$); std::swap($5, $$);
$$.emplace($$.begin(), branch); $$.emplace($$.begin(), branch);
} }
| {} | {}
return_statement: "return" expression return_statement: "return" expression
{ $$ = new boot::return_statement(boot::make_position(@1), $2); } { $$ = new frontend::return_statement(frontend::make_position(@1), $2); }
literal: literal:
INTEGER { $$ = new boot::literal<std::int32_t>(boot::make_position(@1), $1); } INTEGER { $$ = new frontend::literal<std::int32_t>(frontend::make_position(@1), $1); }
| WORD { $$ = new boot::literal<std::uint32_t>(boot::make_position(@1), $1); } | WORD { $$ = new frontend::literal<std::uint32_t>(frontend::make_position(@1), $1); }
| FLOAT { $$ = new boot::literal<double>(boot::make_position(@1), $1); } | FLOAT { $$ = new frontend::literal<double>(frontend::make_position(@1), $1); }
| BOOLEAN { $$ = new boot::literal<bool>(boot::make_position(@1), $1); } | BOOLEAN { $$ = new frontend::literal<bool>(frontend::make_position(@1), $1); }
| CHARACTER { $$ = new boot::literal<unsigned char>(boot::make_position(@1), $1.at(0)); } | CHARACTER { $$ = new frontend::literal<unsigned char>(frontend::make_position(@1), $1.at(0)); }
| "nil" { $$ = new boot::literal<std::nullptr_t>(boot::make_position(@1), nullptr); } | "nil" { $$ = new frontend::literal<std::nullptr_t>(frontend::make_position(@1), nullptr); }
| STRING { $$ = new boot::literal<std::string>(boot::make_position(@1), $1); } | STRING { $$ = new frontend::literal<std::string>(frontend::make_position(@1), $1); }
traits_expression: traits_expression:
TRAIT "(" type_expressions ")" TRAIT "(" type_expressions ")"
{ {
$$ = new boot::traits_expression(boot::make_position(@1), $1); $$ = new frontend::traits_expression(frontend::make_position(@1), $1);
std::swap($3, $$->parameters); std::swap($3, $$->parameters);
} }
simple_expression: simple_expression:
@@ -308,82 +302,82 @@ expression:
binary_expression: binary_expression:
expression "*" expression expression "*" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::multiplication); $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::multiplication);
} }
| expression "/" expression | expression "/" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::division); $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::division);
} }
| expression "%" expression | expression "%" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::remainder); $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::remainder);
} }
| expression "+" expression | expression "+" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::sum); $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::sum);
} }
| expression "-" expression | expression "-" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::subtraction); $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::subtraction);
} }
| expression "=" expression | expression "=" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::equals); $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::equals);
} }
| expression "<>" expression | expression "<>" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::not_equals); $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::not_equals);
} }
| expression "<" expression | expression "<" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::less); $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::less);
} }
| expression ">" expression | expression ">" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::greater); $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::greater);
} }
| expression "<=" expression | expression "<=" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3,
boot::binary_operator::less_equal); frontend::binary_operator::less_equal);
} }
| expression ">=" expression | expression ">=" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::greater_equal); $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::greater_equal);
} }
| expression "&" expression | expression "&" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::conjunction); $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::conjunction);
} }
| expression "or" expression | expression "or" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::disjunction); $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::disjunction);
} }
| expression "xor" expression | expression "xor" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3,
boot::binary_operator::exclusive_disjunction); frontend::binary_operator::exclusive_disjunction);
} }
| expression "<<" expression | expression "<<" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::shift_left); $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::shift_left);
} }
| expression ">>" expression | expression ">>" expression
{ {
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::shift_right); $$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::shift_right);
} }
unary_expression: unary_expression:
"@" operand "@" operand
{ {
$$ = new boot::unary_expression(boot::make_position(@1), $2, boot::unary_operator::reference); $$ = new frontend::unary_expression(frontend::make_position(@1), $2, frontend::unary_operator::reference);
} }
| "~" operand | "~" operand
{ {
$$ = new boot::unary_expression(boot::make_position(@1), $2, boot::unary_operator::negation); $$ = new frontend::unary_expression(frontend::make_position(@1), $2, frontend::unary_operator::negation);
} }
| "-" operand | "-" operand
{ {
$$ = new boot::unary_expression(boot::make_position(@1), $2, boot::unary_operator::minus); $$ = new frontend::unary_expression(frontend::make_position(@1), $2, frontend::unary_operator::minus);
} }
expressions: expressions:
expression "," expressions expression "," expressions
@@ -401,31 +395,31 @@ type_expressions:
| type_expression { $$.push_back($1); } | type_expression { $$.push_back($1); }
designator_expression: designator_expression:
simple_expression "[" expression "]" simple_expression "[" expression "]"
{ $$ = new boot::array_access_expression(boot::make_position(@2), $1, $3); } { $$ = new frontend::array_access_expression(frontend::make_position(@2), $1, $3); }
| simple_expression "." IDENTIFIER | simple_expression "." IDENTIFIER
{ $$ = new boot::field_access_expression(boot::make_position(@2), $1, $3); } { $$ = new frontend::field_access_expression(frontend::make_position(@2), $1, $3); }
| simple_expression "^" | simple_expression "^"
{ $$ = new boot::dereference_expression(boot::make_position(@1), $1); } { $$ = new frontend::dereference_expression(frontend::make_position(@1), $1); }
| IDENTIFIER | IDENTIFIER
{ $$ = new boot::variable_expression(boot::make_position(@1), $1); } { $$ = new frontend::variable_expression(frontend::make_position(@1), $1); }
statement: statement:
designator_expression ":=" expression designator_expression ":=" expression
{ $$ = new boot::assign_statement(boot::make_position(@1), $1, $3); } { $$ = new frontend::assign_statement(frontend::make_position(@1), $1, $3); }
| "while" expression "do" optional_statements elsif_do_statements "end" | "while" expression "do" optional_statements elsif_do_statements "end"
{ {
boot::conditional_statements *body = new boot::conditional_statements($2, std::move($4)); frontend::conditional_statements *body = new frontend::conditional_statements($2, std::move($4));
$$ = new boot::while_statement(boot::make_position(@1), body, std::move($5)); $$ = new frontend::while_statement(frontend::make_position(@1), body, std::move($5));
} }
| "if" expression "then" optional_statements elsif_then_statements else_statements "end" | "if" expression "then" optional_statements elsif_then_statements else_statements "end"
{ {
boot::conditional_statements *then = new boot::conditional_statements($2, std::move($4)); frontend::conditional_statements *then = new frontend::conditional_statements($2, std::move($4));
$$ = new boot::if_statement(boot::make_position(@1), then, std::move($5), $6); $$ = new frontend::if_statement(frontend::make_position(@1), then, std::move($5), $6);
} }
| call_expression { $$ = $1; } | call_expression { $$ = $1; }
| "defer" optional_statements "end" | "defer" optional_statements "end"
{ $$ = new boot::defer_statement(boot::make_position(@1), std::move($2)); } { $$ = new frontend::defer_statement(frontend::make_position(@1), std::move($2)); }
| "case" expression "of" switch_cases else_statements "end" | "case" expression "of" switch_cases else_statements "end"
{ $$ = new boot::case_statement(boot::make_position(@1), $2, std::move($4), $5); } { $$ = new frontend::case_statement(frontend::make_position(@1), $2, std::move($4), $5); }
switch_case: case_labels ":" optional_statements switch_case: case_labels ":" optional_statements
{ $$ = { .labels = std::move($1), .statements = std::move($3) }; } { $$ = { .labels = std::move($1), .statements = std::move($3) }; }
switch_cases: switch_cases:
@@ -467,33 +461,33 @@ optional_fields:
type_expression: type_expression:
"[" INTEGER "]" type_expression "[" INTEGER "]" type_expression
{ {
$$ = new boot::array_type_expression(boot::make_position(@1), $4, $2); $$ = new frontend::array_type_expression(frontend::make_position(@1), $4, $2);
} }
| "^" type_expression | "^" type_expression
{ {
$$ = new boot::pointer_type_expression(boot::make_position(@1), $2); $$ = new frontend::pointer_type_expression(frontend::make_position(@1), $2);
} }
| "record" optional_fields "end" | "record" optional_fields "end"
{ {
$$ = new boot::record_type_expression(boot::make_position(@1), std::move($2)); $$ = new frontend::record_type_expression(frontend::make_position(@1), std::move($2));
} }
| "union" required_fields "end" | "union" required_fields "end"
{ {
$$ = new boot::union_type_expression(boot::make_position(@1), std::move($2)); $$ = new frontend::union_type_expression(frontend::make_position(@1), std::move($2));
} }
| "proc" "(" type_expressions ")" return_declaration | "proc" "(" type_expressions ")" return_declaration
{ {
auto result = new boot::procedure_type_expression(boot::make_position(@1), std::move($5)); auto result = new frontend::procedure_type_expression(frontend::make_position(@1), std::move($5));
std::swap(result->parameters, $3); std::swap(result->parameters, $3);
$$ = result; $$ = result;
} }
| "(" identifiers ")" | "(" identifiers ")"
{ {
$$ = new boot::enumeration_type_expression(boot::make_position(@1), std::move($2)); $$ = new frontend::enumeration_type_expression(frontend::make_position(@1), std::move($2));
} }
| IDENTIFIER | IDENTIFIER
{ {
$$ = new boot::named_type_expression(boot::make_position(@1), $1); $$ = new frontend::named_type_expression(frontend::make_position(@1), $1);
} }
identifiers: identifiers:
IDENTIFIER "," identifiers IDENTIFIER "," identifiers
@@ -505,19 +499,19 @@ identifiers:
variable_declaration: variable_declaration:
identifier_definitions ":" type_expression ";" identifier_definitions ":" type_expression ";"
{ {
std::shared_ptr<boot::type_expression> shared_type{ $3 }; std::shared_ptr<frontend::type_expression> shared_type{ $3 };
$$ = new boot::variable_declaration( boot::make_position(@2), std::move($1), shared_type); $$ = new frontend::variable_declaration( frontend::make_position(@2), std::move($1), shared_type);
} }
| identifier_definitions ":" type_expression ":=" "extern" ";" | identifier_definitions ":" type_expression ":=" "extern" ";"
{ {
std::shared_ptr<boot::type_expression> shared_type{ $3 }; std::shared_ptr<frontend::type_expression> shared_type{ $3 };
$$ = new boot::variable_declaration( boot::make_position(@2), std::move($1), shared_type, $$ = new frontend::variable_declaration( frontend::make_position(@2), std::move($1), shared_type,
std::monostate{}); std::monostate{});
} }
| identifier_definitions ":" type_expression ":=" expression ";" | identifier_definitions ":" type_expression ":=" expression ";"
{ {
std::shared_ptr<boot::type_expression> shared_type{ $3 }; std::shared_ptr<frontend::type_expression> shared_type{ $3 };
$$ = new boot::variable_declaration( boot::make_position(@2), std::move($1), shared_type, $5); $$ = new frontend::variable_declaration( frontend::make_position(@2), std::move($1), shared_type, $5);
} }
variable_declarations: variable_declarations:
/* no variable declarations */ {} /* no variable declarations */ {}
@@ -531,7 +525,7 @@ variable_part:
| "var" variable_declarations { std::swap($$, $2); } | "var" variable_declarations { std::swap($$, $2); }
constant_declaration: identifier_definition ":=" expression ";" constant_declaration: identifier_definition ":=" expression ";"
{ {
$$ = new boot::constant_declaration(boot::make_position(@1), std::move($1), $3); $$ = new frontend::constant_declaration(frontend::make_position(@1), std::move($1), $3);
} }
constant_declarations: constant_declarations:
constant_declaration constant_declarations constant_declaration constant_declarations
@@ -554,18 +548,18 @@ import_declarations:
import_declaration "," import_declarations import_declaration "," import_declarations
{ {
std::swap($$, $3); std::swap($$, $3);
$$.emplace($$.cbegin(), new boot::import_declaration(boot::make_position(@1), std::move($1))); $$.emplace($$.cbegin(), new frontend::import_declaration(frontend::make_position(@1), std::move($1)));
} }
| import_declaration | import_declaration
{ {
$$.emplace_back(new boot::import_declaration(boot::make_position(@1), std::move($1))); $$.emplace_back(new frontend::import_declaration(frontend::make_position(@1), std::move($1)));
} }
import_part: import_part:
/* no import declarations */ {} /* no import declarations */ {}
| "import" import_declarations ";" { std::swap($$, $2); } | "import" import_declarations ";" { std::swap($$, $2); }
type_declaration: identifier_definition "=" type_expression ";" type_declaration: identifier_definition "=" type_expression ";"
{ {
$$ = new boot::type_declaration(boot::make_position(@1), std::move($1), $3); $$ = new frontend::type_declaration(frontend::make_position(@1), std::move($1), $3);
} }
type_declarations: type_declarations:
type_declaration type_declarations type_declaration type_declarations
@@ -596,5 +590,5 @@ actual_parameter_list:
void yy::parser::error(const location_type& loc, const std::string& message) void yy::parser::error(const location_type& loc, const std::string& message)
{ {
driver.add_error<boot::syntax_error>(message, driver.input_file, loc); driver.add_error<frontend::syntax_error>(message, driver.input_file, loc);
} }

View File

@@ -15,9 +15,9 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include "elna/boot/result.h" #include "elna/frontend/result.h"
namespace elna::boot namespace elna::frontend
{ {
error::error(const char *path, const struct position position) error::error(const char *path, const struct position position)
: position(position), path(path) : position(position), path(path)
@@ -60,8 +60,8 @@ namespace elna::boot
} }
} }
std::size_t std::hash<elna::boot::identifier_definition>::operator()( std::size_t std::hash<elna::frontend::identifier_definition>::operator()(
const elna::boot::identifier_definition& key) const const elna::frontend::identifier_definition& key) const
{ {
return std::hash<std::string>{}(key.name); return std::hash<std::string>{}(key.name);
} }

View File

@@ -15,12 +15,12 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include "elna/boot/semantic.h" #include "elna/frontend/semantic.h"
#include <algorithm> #include <algorithm>
#include <set> #include <set>
namespace elna::boot namespace elna::frontend
{ {
undeclared_error::undeclared_error(const std::string& identifier, const char *path, const struct position position) undeclared_error::undeclared_error(const std::string& identifier, const char *path, const struct position position)
: error(path, position), identifier(identifier) : error(path, position), identifier(identifier)
@@ -636,7 +636,7 @@ namespace elna::boot
{ {
return; return;
} }
for (boot::variable_declaration *const variable : definition->body.value().variables()) for (variable_declaration *const variable : definition->body.value().variables())
{ {
variable->accept(this); variable->accept(this);
} }

View File

@@ -15,9 +15,9 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include "elna/boot/symbol.h" #include "elna/frontend/symbol.h"
namespace elna::boot namespace elna::frontend
{ {
type::type() type::type()
{ {

View File

@@ -150,7 +150,7 @@ elna.stagefeedback: stagefeedback-start
ELNA_INCLUDES = -I $(srcdir)/elna/include -I elna/generated ELNA_INCLUDES = -I $(srcdir)/elna/include -I elna/generated
ELNA_CXXFLAGS = -std=c++17 ELNA_CXXFLAGS = -std=c++17
elna/%.o: elna/boot/%.cc elna/generated/parser.hh elna/generated/location.hh elna/%.o: elna/frontend/%.cc elna/generated/parser.hh elna/generated/location.hh
$(COMPILE) $(ELNA_CXXFLAGS) $(ELNA_INCLUDES) $< $(COMPILE) $(ELNA_CXXFLAGS) $(ELNA_INCLUDES) $<
$(POSTCOMPILE) $(POSTCOMPILE)
@@ -162,13 +162,13 @@ elna/%.o: elna/gcc/%.cc elna/generated/parser.hh elna/generated/location.hh
$(COMPILE) $(ELNA_CXXFLAGS) $(ELNA_INCLUDES) $< $(COMPILE) $(ELNA_CXXFLAGS) $(ELNA_INCLUDES) $<
$(POSTCOMPILE) $(POSTCOMPILE)
elna/generated/parser.cc: elna/boot/parser.yy elna/generated/parser.cc: elna/frontend/parser.yy
mkdir -p $(dir $@) mkdir -p $(dir $@)
$(BISON) -d -o $@ $< $(BISON) -d -o $@ $<
elna/generated/parser.hh elna/generated/location.hh: elna/generated/parser.cc elna/generated/parser.hh elna/generated/location.hh: elna/generated/parser.cc
@touch $@ @touch $@
elna/generated/lexer.cc: elna/boot/lexer.ll elna/generated/lexer.cc: elna/frontend/lexer.ll
mkdir -p $(dir $@) mkdir -p $(dir $@)
$(FLEX) -o $@ $< $(FLEX) -o $@ $<

42
gcc/README.md Normal file
View File

@@ -0,0 +1,42 @@
# Elna programming language
## Current implementation
This repository contains a GCC frontend for Elna. After finishing the frontend
I'm planning to rewrite the compiler in Elna itself with its own backend and
a hand-written parser. So GCC gives a way to have a simple bootstrap compiler
and a possbility to compile Elna programs for different platforms.
## Grammar
Flex and bison grammar specifications, `lexer.ll` and `parser.yy`, can be found
in the `boot/` directory.
## Build
The frontend requires GCC 15.2.0 (not tested with other versions).
Download the GCC source. Copy the contents of this repository into `gcc/elna`
inside GCC. Finally build GCC enabling the frontend with
`--enable-languages=c,c++,elna`. After the installation the compiler can be
invoked with `$prefix/bin/gelna`.
There is also a `Rakefile` that downloads, builds and installs GCC into the
`./build/` subdirectory. The `Rakefile` assumes that ruby and rake, as well as
all GCC dependencies are already available in the system. It works under Linux
and Mac OS. In the latter case GCC is patched with the patches used by Homebrew
(official GCC doesn't support Apple silicon targets). Invoke with
```sh
rake boot
```
`gcc` binary is used by default, but a different gcc version can be specified
by passing `CC` and `CXX` environment variables to rake, e.g.:
```sh
rake CC=gcc-15 CXX=g++-15 boot
```
See `rake -T` for more tasks. The GCC source is under `build/tools`. The
installation path is `build/host/install`.

View File

@@ -80,7 +80,7 @@ namespace elna::gcc
return symbol_table; return symbol_table;
} }
tree build_composite_type(const std::vector<boot::type_field>& fields, tree composite_type_node, tree build_composite_type(const std::vector<frontend::type_field>& fields, tree composite_type_node,
std::shared_ptr<symbol_table> symbols) std::shared_ptr<symbol_table> symbols)
{ {
for (auto& field : fields) for (auto& field : fields)
@@ -94,7 +94,7 @@ namespace elna::gcc
return composite_type_node; return composite_type_node;
} }
tree build_procedure_type(const boot::procedure_type& procedure, std::shared_ptr<symbol_table> symbols) tree build_procedure_type(const frontend::procedure_type& procedure, std::shared_ptr<symbol_table> symbols)
{ {
std::vector<tree> parameter_types(procedure.parameters.size()); std::vector<tree> parameter_types(procedure.parameters.size());
@@ -111,16 +111,16 @@ namespace elna::gcc
return build_function_type_array(return_type, procedure.parameters.size(), parameter_types.data()); return build_function_type_array(return_type, procedure.parameters.size(), parameter_types.data());
} }
tree get_inner_alias(const boot::type& type, std::shared_ptr<symbol_table> symbols) tree get_inner_alias(const frontend::type& type, std::shared_ptr<symbol_table> symbols)
{ {
if (auto reference = type.get<boot::primitive_type>()) if (auto reference = type.get<frontend::primitive_type>())
{ {
auto looked_up = symbols->lookup(reference->identifier); auto looked_up = symbols->lookup(reference->identifier);
gcc_assert(looked_up != NULL_TREE); gcc_assert(looked_up != NULL_TREE);
return TREE_TYPE(looked_up); return TREE_TYPE(looked_up);
} }
else if (auto reference = type.get<boot::record_type>()) else if (auto reference = type.get<frontend::record_type>())
{ {
tree composite_type_node = make_node(RECORD_TYPE); tree composite_type_node = make_node(RECORD_TYPE);
@@ -128,7 +128,7 @@ namespace elna::gcc
return composite_type_node; return composite_type_node;
} }
else if (auto reference = type.get<boot::union_type>()) else if (auto reference = type.get<frontend::union_type>())
{ {
tree composite_type_node = make_node(UNION_TYPE); tree composite_type_node = make_node(UNION_TYPE);
@@ -136,34 +136,34 @@ namespace elna::gcc
return composite_type_node; return composite_type_node;
} }
else if (auto reference = type.get<boot::enumeration_type>()) else if (auto reference = type.get<frontend::enumeration_type>())
{ {
return build_enumeration_type(reference->members); return build_enumeration_type(reference->members);
} }
else if (auto reference = type.get<boot::pointer_type>()) else if (auto reference = type.get<frontend::pointer_type>())
{ {
return build_global_pointer_type(get_inner_alias(reference->base, symbols)); return build_global_pointer_type(get_inner_alias(reference->base, symbols));
} }
else if (auto reference = type.get<boot::array_type>()) else if (auto reference = type.get<frontend::array_type>())
{ {
tree base = get_inner_alias(reference->base, symbols); tree base = get_inner_alias(reference->base, symbols);
return build_static_array_type(base, reference->size); return build_static_array_type(base, reference->size);
} }
else if (auto reference = type.get<boot::procedure_type>()) else if (auto reference = type.get<frontend::procedure_type>())
{ {
auto procedure = build_procedure_type(*reference, symbols); auto procedure = build_procedure_type(*reference, symbols);
return build_global_pointer_type(procedure); return build_global_pointer_type(procedure);
} }
else if (auto reference = type.get<boot::alias_type>()) else if (auto reference = type.get<frontend::alias_type>())
{ {
return TREE_TYPE(handle_symbol(reference->name, reference, symbols)); return TREE_TYPE(handle_symbol(reference->name, reference, symbols));
} }
return error_mark_node; return error_mark_node;
} }
tree handle_symbol(const std::string& symbol_name, std::shared_ptr<boot::alias_type> reference, tree handle_symbol(const std::string& symbol_name, std::shared_ptr<frontend::alias_type> reference,
std::shared_ptr<symbol_table> symbols) std::shared_ptr<symbol_table> symbols)
{ {
tree looked_up = symbols->lookup(symbol_name); tree looked_up = symbols->lookup(symbol_name);
@@ -189,7 +189,7 @@ namespace elna::gcc
return looked_up; return looked_up;
} }
void declare_procedure(const std::string& name, const boot::procedure_info& info, void declare_procedure(const std::string& name, const frontend::procedure_info& info,
std::shared_ptr<symbol_table> symbols) std::shared_ptr<symbol_table> symbols)
{ {
tree declaration_type = gcc::build_procedure_type(info.symbol, symbols); tree declaration_type = gcc::build_procedure_type(info.symbol, symbols);
@@ -210,7 +210,7 @@ namespace elna::gcc
std::vector<std::string>::const_iterator parameter_name = info.names.cbegin(); std::vector<std::string>::const_iterator parameter_name = info.names.cbegin();
for (boot::type parameter : info.symbol.parameters) for (frontend::type parameter : info.symbol.parameters)
{ {
tree declaration_tree = build_decl(UNKNOWN_LOCATION, PARM_DECL, tree declaration_tree = build_decl(UNKNOWN_LOCATION, PARM_DECL,
get_identifier(parameter_name->c_str()), function_args_iter_cond(&parameter_type)); get_identifier(parameter_name->c_str()), function_args_iter_cond(&parameter_type));
@@ -227,7 +227,7 @@ namespace elna::gcc
TREE_PUBLIC(fndecl) = info.exported; TREE_PUBLIC(fndecl) = info.exported;
} }
tree declare_variable(const std::string& name, const boot::variable_info& info, tree declare_variable(const std::string& name, const frontend::variable_info& info,
std::shared_ptr<symbol_table> symbols) std::shared_ptr<symbol_table> symbols)
{ {
auto variable_type = get_inner_alias(info.symbol, symbols); auto variable_type = get_inner_alias(info.symbol, symbols);
@@ -242,10 +242,10 @@ namespace elna::gcc
return declaration_tree; return declaration_tree;
} }
void declare_type(const std::string& name, const boot::type_info& info, std::shared_ptr<symbol_table> symbols) void declare_type(const std::string& name, const frontend::type_info& info, std::shared_ptr<symbol_table> symbols)
{ {
// The top level symbol table has basic (builtin) types in it which are not aliases. // The top level symbol table has basic (builtin) types in it which are not aliases.
if (auto alias_type = info.symbol.get<boot::alias_type>()) if (auto alias_type = info.symbol.get<frontend::alias_type>())
{ {
tree type_declaration = handle_symbol(name, alias_type, symbols); tree type_declaration = handle_symbol(name, alias_type, symbols);
@@ -253,7 +253,7 @@ namespace elna::gcc
} }
} }
void rewrite_symbol_table(std::shared_ptr<boot::symbol_table> info_table, std::shared_ptr<symbol_table> symbols) void rewrite_symbol_table(std::shared_ptr<frontend::symbol_table> info_table, std::shared_ptr<symbol_table> symbols)
{ {
for (auto& [symbol_name, symbol_info] : *info_table) for (auto& [symbol_name, symbol_info] : *info_table)
{ {

View File

@@ -31,7 +31,7 @@ namespace elna::gcc
linemap_add(line_table, LC_LEAVE, 0, NULL, 0); linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
} }
location_t get_location(const boot::position *position) location_t get_location(const frontend::position *position)
{ {
linemap_line_start(line_table, position->line, 0); linemap_line_start(line_table, position->line, 0);
@@ -151,7 +151,7 @@ namespace elna::gcc
gcc_unreachable(); gcc_unreachable();
} }
void report_errors(const std::deque<std::unique_ptr<boot::error>>& errors) void report_errors(const std::deque<std::unique_ptr<frontend::error>>& errors)
{ {
for (const auto& error : errors) for (const auto& error : errors)
{ {

View File

@@ -35,13 +35,13 @@ along with GCC; see the file COPYING3. If not see
namespace elna::gcc namespace elna::gcc
{ {
generic_visitor::generic_visitor(std::shared_ptr<symbol_table> symbol_table, elna::boot::symbol_bag bag) generic_visitor::generic_visitor(std::shared_ptr<symbol_table> symbol_table, elna::frontend::symbol_bag bag)
: bag(bag), symbols(symbol_table) : bag(bag), symbols(symbol_table)
{ {
} }
void generic_visitor::build_procedure_call(location_t call_location, void generic_visitor::build_procedure_call(location_t call_location,
tree procedure_address, const std::vector<boot::expression *>& arguments) tree procedure_address, const std::vector<frontend::expression *>& arguments)
{ {
vec<tree, va_gc> *argument_trees = nullptr; vec<tree, va_gc> *argument_trees = nullptr;
tree symbol_type = TREE_TYPE(TREE_TYPE(procedure_address)); tree symbol_type = TREE_TYPE(TREE_TYPE(procedure_address));
@@ -49,7 +49,7 @@ namespace elna::gcc
tree current_parameter = TYPE_ARG_TYPES(symbol_type); tree current_parameter = TYPE_ARG_TYPES(symbol_type);
vec_alloc(argument_trees, arguments.size()); vec_alloc(argument_trees, arguments.size());
for (boot::expression *const argument : arguments) for (frontend::expression *const argument : arguments)
{ {
location_t argument_location = get_location(&argument->position()); location_t argument_location = get_location(&argument->position());
if (VOID_TYPE_P(TREE_VALUE(current_parameter))) if (VOID_TYPE_P(TREE_VALUE(current_parameter)))
@@ -88,11 +88,11 @@ namespace elna::gcc
} }
void generic_visitor::build_record_call(location_t call_location, void generic_visitor::build_record_call(location_t call_location,
tree symbol, const std::vector<boot::expression *>& arguments) tree symbol, const std::vector<frontend::expression *>& arguments)
{ {
vec<constructor_elt, va_gc> *tree_arguments = nullptr; vec<constructor_elt, va_gc> *tree_arguments = nullptr;
tree record_fields = TYPE_FIELDS(symbol); tree record_fields = TYPE_FIELDS(symbol);
for (boot::expression *const argument : arguments) for (frontend::expression *const argument : arguments)
{ {
location_t argument_location = get_location(&argument->position()); location_t argument_location = get_location(&argument->position());
@@ -129,7 +129,7 @@ namespace elna::gcc
} }
void generic_visitor::build_assert_builtin(location_t call_location, void generic_visitor::build_assert_builtin(location_t call_location,
const std::vector<boot::expression *>& arguments) const std::vector<frontend::expression *>& arguments)
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
{ {
@@ -165,11 +165,11 @@ namespace elna::gcc
} }
} }
bool generic_visitor::build_builtin_procedures(boot::procedure_call *call) bool generic_visitor::build_builtin_procedures(frontend::procedure_call *call)
{ {
location_t call_location = get_location(&call->position()); location_t call_location = get_location(&call->position());
if (boot::variable_expression *named_call = call->callable().is_variable()) if (frontend::variable_expression *named_call = call->callable().is_variable())
{ {
if (named_call->name == "assert") if (named_call->name == "assert")
{ {
@@ -180,7 +180,7 @@ namespace elna::gcc
return false; return false;
} }
void generic_visitor::visit(boot::procedure_call *call) void generic_visitor::visit(frontend::procedure_call *call)
{ {
if (build_builtin_procedures(call)) if (build_builtin_procedures(call))
{ {
@@ -215,7 +215,7 @@ namespace elna::gcc
} }
} }
void generic_visitor::visit(boot::cast_expression *expression) void generic_visitor::visit(frontend::cast_expression *expression)
{ {
tree cast_target = get_inner_alias(expression->expression_type, this->symbols->scope()); tree cast_target = get_inner_alias(expression->expression_type, this->symbols->scope());
@@ -235,9 +235,9 @@ namespace elna::gcc
} }
} }
void generic_visitor::visit(boot::program *program) void generic_visitor::visit(frontend::program *program)
{ {
visit(static_cast<boot::unit *>(program)); visit(static_cast<frontend::unit *>(program));
tree declaration_type = build_function_type_list(elna_int_type_node, tree declaration_type = build_function_type_list(elna_int_type_node,
elna_int_type_node, elna_int_type_node,
@@ -285,27 +285,27 @@ namespace elna::gcc
cgraph_node::finalize_function(fndecl, true); cgraph_node::finalize_function(fndecl, true);
} }
void generic_visitor::visit(boot::unit *unit) void generic_visitor::visit(frontend::unit *unit)
{ {
for (boot::import_declaration *const declaration : unit->imports) for (frontend::import_declaration *const declaration : unit->imports)
{ {
declaration->accept(this); declaration->accept(this);
} }
for (boot::constant_declaration *const constant : unit->constants) for (frontend::constant_declaration *const constant : unit->constants)
{ {
constant->accept(this); constant->accept(this);
} }
for (boot::variable_declaration *const variable : unit->variables) for (frontend::variable_declaration *const variable : unit->variables)
{ {
variable->accept(this); variable->accept(this);
} }
for (boot::procedure_declaration *const procedure : unit->procedures) for (frontend::procedure_declaration *const procedure : unit->procedures)
{ {
procedure->accept(this); procedure->accept(this);
} }
} }
void generic_visitor::visit(boot::procedure_declaration *definition) void generic_visitor::visit(frontend::procedure_declaration *definition)
{ {
tree fndecl = this->symbols->lookup(definition->identifier.name); tree fndecl = this->symbols->lookup(definition->identifier.name);
@@ -324,11 +324,11 @@ namespace elna::gcc
{ {
this->symbols->enter(IDENTIFIER_POINTER(DECL_NAME(argument_chain)), argument_chain); this->symbols->enter(IDENTIFIER_POINTER(DECL_NAME(argument_chain)), argument_chain);
} }
for (boot::constant_declaration *const constant : definition->body.value().constants()) for (frontend::constant_declaration *const constant : definition->body.value().constants())
{ {
constant->accept(this); constant->accept(this);
} }
for (boot::variable_declaration *const variable : definition->body.value().variables()) for (frontend::variable_declaration *const variable : definition->body.value().variables())
{ {
variable->accept(this); variable->accept(this);
} }
@@ -381,17 +381,17 @@ namespace elna::gcc
return bind_expr; return bind_expr;
} }
void generic_visitor::visit(boot::literal<std::int32_t> *literal) void generic_visitor::visit(frontend::literal<std::int32_t> *literal)
{ {
this->current_expression = build_int_cst(elna_int_type_node, literal->value); this->current_expression = build_int_cst(elna_int_type_node, literal->value);
} }
void generic_visitor::visit(boot::literal<std::uint32_t> *literal) void generic_visitor::visit(frontend::literal<std::uint32_t> *literal)
{ {
this->current_expression = build_int_cstu(elna_word_type_node, literal->value); this->current_expression = build_int_cstu(elna_word_type_node, literal->value);
} }
void generic_visitor::visit(boot::literal<double> *literal) void generic_visitor::visit(frontend::literal<double> *literal)
{ {
REAL_VALUE_TYPE real_value1; REAL_VALUE_TYPE real_value1;
@@ -406,22 +406,22 @@ namespace elna::gcc
mpfr_clear(number); mpfr_clear(number);
} }
void generic_visitor::visit(boot::literal<bool> *boolean) void generic_visitor::visit(frontend::literal<bool> *boolean)
{ {
this->current_expression = boolean->value ? boolean_true_node : boolean_false_node; this->current_expression = boolean->value ? boolean_true_node : boolean_false_node;
} }
void generic_visitor::visit(boot::literal<unsigned char> *character) void generic_visitor::visit(frontend::literal<unsigned char> *character)
{ {
this->current_expression = build_int_cstu(elna_char_type_node, character->value); this->current_expression = build_int_cstu(elna_char_type_node, character->value);
} }
void generic_visitor::visit(boot::literal<nullptr_t> *) void generic_visitor::visit(frontend::literal<nullptr_t> *)
{ {
this->current_expression = elna_pointer_nil_node; this->current_expression = elna_pointer_nil_node;
} }
void generic_visitor::visit(boot::literal<std::string> *string) void generic_visitor::visit(frontend::literal<std::string> *string)
{ {
tree index_constant = build_int_cstu(elna_word_type_node, string->value.size()); tree index_constant = build_int_cstu(elna_word_type_node, string->value.size());
tree string_type = build_array_type(elna_char_type_node, build_index_type(index_constant)); tree string_type = build_array_type(elna_char_type_node, build_index_type(index_constant));
@@ -444,38 +444,38 @@ namespace elna::gcc
this->current_expression = build_constructor(elna_string_type_node, elms); this->current_expression = build_constructor(elna_string_type_node, elms);
} }
tree generic_visitor::build_arithmetic_operation(boot::binary_expression *expression, tree generic_visitor::build_arithmetic_operation(frontend::binary_expression *expression,
tree_code operator_code, tree left, tree right) tree_code operator_code, tree left, tree right)
{ {
return build_binary_operation(is_numeric_type(TREE_TYPE(left)), return build_binary_operation(is_numeric_type(TREE_TYPE(left)),
expression, operator_code, left, right, TREE_TYPE(left)); expression, operator_code, left, right, TREE_TYPE(left));
} }
tree generic_visitor::build_comparison_operation(boot::binary_expression *expression, tree generic_visitor::build_comparison_operation(frontend::binary_expression *expression,
tree_code operator_code, tree left, tree right) tree_code operator_code, tree left, tree right)
{ {
return build_binary_operation(is_numeric_type(TREE_TYPE(left)) || POINTER_TYPE_P(TREE_TYPE(left)), return build_binary_operation(is_numeric_type(TREE_TYPE(left)) || POINTER_TYPE_P(TREE_TYPE(left)),
expression, operator_code, left, right, elna_bool_type_node); expression, operator_code, left, right, elna_bool_type_node);
} }
tree generic_visitor::build_bit_logic_operation(boot::binary_expression *expression, tree left, tree right) tree generic_visitor::build_bit_logic_operation(frontend::binary_expression *expression, tree left, tree right)
{ {
location_t expression_location = get_location(&expression->position()); location_t expression_location = get_location(&expression->position());
tree left_type = TREE_TYPE(left); tree left_type = TREE_TYPE(left);
tree right_type = TREE_TYPE(right); tree right_type = TREE_TYPE(right);
tree_code logical_code, bit_code; tree_code logical_code, bit_code;
if (expression->operation() == boot::binary_operator::conjunction) if (expression->operation() == frontend::binary_operator::conjunction)
{ {
bit_code = BIT_AND_EXPR; bit_code = BIT_AND_EXPR;
logical_code = TRUTH_ANDIF_EXPR; logical_code = TRUTH_ANDIF_EXPR;
} }
else if (expression->operation() == boot::binary_operator::disjunction) else if (expression->operation() == frontend::binary_operator::disjunction)
{ {
bit_code = BIT_IOR_EXPR; bit_code = BIT_IOR_EXPR;
logical_code = TRUTH_ORIF_EXPR; logical_code = TRUTH_ORIF_EXPR;
} }
else if (expression->operation() == boot::binary_operator::exclusive_disjunction) else if (expression->operation() == frontend::binary_operator::exclusive_disjunction)
{ {
bit_code = BIT_XOR_EXPR; bit_code = BIT_XOR_EXPR;
logical_code = TRUTH_XOR_EXPR; logical_code = TRUTH_XOR_EXPR;
@@ -496,22 +496,22 @@ namespace elna::gcc
{ {
error_at(expression_location, "Invalid operands of type '%s' and '%s' for operator %s", error_at(expression_location, "Invalid operands of type '%s' and '%s' for operator %s",
print_type(left_type).c_str(), print_type(right_type).c_str(), print_type(left_type).c_str(), print_type(right_type).c_str(),
elna::boot::print_binary_operator(expression->operation())); elna::frontend::print_binary_operator(expression->operation()));
return error_mark_node; return error_mark_node;
} }
} }
tree generic_visitor::build_equality_operation(boot::binary_expression *expression, tree left, tree right) tree generic_visitor::build_equality_operation(frontend::binary_expression *expression, tree left, tree right)
{ {
location_t expression_location = get_location(&expression->position()); location_t expression_location = get_location(&expression->position());
tree_code equality_code, combination_code; tree_code equality_code, combination_code;
if (expression->operation() == boot::binary_operator::equals) if (expression->operation() == frontend::binary_operator::equals)
{ {
equality_code = EQ_EXPR; equality_code = EQ_EXPR;
combination_code = TRUTH_ANDIF_EXPR; combination_code = TRUTH_ANDIF_EXPR;
} }
else if (expression->operation() == boot::binary_operator::not_equals) else if (expression->operation() == frontend::binary_operator::not_equals)
{ {
equality_code = NE_EXPR; equality_code = NE_EXPR;
combination_code = TRUTH_ORIF_EXPR; combination_code = TRUTH_ORIF_EXPR;
@@ -545,7 +545,7 @@ namespace elna::gcc
} }
} }
void generic_visitor::visit(boot::binary_expression *expression) void generic_visitor::visit(frontend::binary_expression *expression)
{ {
expression->lhs().accept(this); expression->lhs().accept(this);
tree left = this->current_expression; tree left = this->current_expression;
@@ -558,8 +558,8 @@ namespace elna::gcc
location_t expression_location = get_location(&expression->position()); location_t expression_location = get_location(&expression->position());
if ((POINTER_TYPE_P(left_type) || POINTER_TYPE_P(right_type)) if ((POINTER_TYPE_P(left_type) || POINTER_TYPE_P(right_type))
&& (expression->operation() == boot::binary_operator::sum && (expression->operation() == frontend::binary_operator::sum
|| expression->operation() == boot::binary_operator::subtraction)) || expression->operation() == frontend::binary_operator::subtraction))
{ {
this->current_expression = do_pointer_arithmetic(expression->operation(), this->current_expression = do_pointer_arithmetic(expression->operation(),
left, right, expression_location); left, right, expression_location);
@@ -567,7 +567,7 @@ namespace elna::gcc
{ {
error_at(expression_location, error_at(expression_location,
"invalid operation %s on a pointer and an integral type", "invalid operation %s on a pointer and an integral type",
boot::print_binary_operator(expression->operation())); frontend::print_binary_operator(expression->operation()));
} }
else if (TREE_TYPE(this->current_expression) == ssizetype) else if (TREE_TYPE(this->current_expression) == ssizetype)
{ {
@@ -583,60 +583,60 @@ namespace elna::gcc
error_at(expression_location, error_at(expression_location,
"invalid operands of type '%s' and '%s' for operator %s", "invalid operands of type '%s' and '%s' for operator %s",
print_type(left_type).c_str(), print_type(right_type).c_str(), print_type(left_type).c_str(), print_type(right_type).c_str(),
boot::print_binary_operator(expression->operation())); frontend::print_binary_operator(expression->operation()));
this->current_expression = error_mark_node; this->current_expression = error_mark_node;
return; return;
} }
switch (expression->operation()) switch (expression->operation())
{ {
case boot::binary_operator::sum: case frontend::binary_operator::sum:
this->current_expression = build_arithmetic_operation(expression, PLUS_EXPR, left, right); this->current_expression = build_arithmetic_operation(expression, PLUS_EXPR, left, right);
break; break;
case boot::binary_operator::subtraction: case frontend::binary_operator::subtraction:
this->current_expression = build_arithmetic_operation(expression, MINUS_EXPR, left, right); this->current_expression = build_arithmetic_operation(expression, MINUS_EXPR, left, right);
break; break;
case boot::binary_operator::division: case frontend::binary_operator::division:
this->current_expression = build_arithmetic_operation(expression, TRUNC_DIV_EXPR, left, right); this->current_expression = build_arithmetic_operation(expression, TRUNC_DIV_EXPR, left, right);
break; break;
case boot::binary_operator::remainder: case frontend::binary_operator::remainder:
this->current_expression = build_arithmetic_operation(expression, TRUNC_MOD_EXPR, left, right); this->current_expression = build_arithmetic_operation(expression, TRUNC_MOD_EXPR, left, right);
break; break;
case boot::binary_operator::multiplication: case frontend::binary_operator::multiplication:
this->current_expression = build_arithmetic_operation(expression, MULT_EXPR, left, right); this->current_expression = build_arithmetic_operation(expression, MULT_EXPR, left, right);
break; break;
case boot::binary_operator::less: case frontend::binary_operator::less:
this->current_expression = build_comparison_operation(expression, LT_EXPR, left, right); this->current_expression = build_comparison_operation(expression, LT_EXPR, left, right);
break; break;
case boot::binary_operator::greater: case frontend::binary_operator::greater:
this->current_expression = build_comparison_operation(expression, GT_EXPR, left, right); this->current_expression = build_comparison_operation(expression, GT_EXPR, left, right);
break; break;
case boot::binary_operator::less_equal: case frontend::binary_operator::less_equal:
this->current_expression = build_comparison_operation(expression, LE_EXPR, left, right); this->current_expression = build_comparison_operation(expression, LE_EXPR, left, right);
break; break;
case boot::binary_operator::greater_equal: case frontend::binary_operator::greater_equal:
this->current_expression = build_comparison_operation(expression, GE_EXPR, left, right); this->current_expression = build_comparison_operation(expression, GE_EXPR, left, right);
break; break;
case boot::binary_operator::conjunction: case frontend::binary_operator::conjunction:
this->current_expression = build_bit_logic_operation(expression, left, right); this->current_expression = build_bit_logic_operation(expression, left, right);
break; break;
case boot::binary_operator::disjunction: case frontend::binary_operator::disjunction:
this->current_expression = build_bit_logic_operation(expression, left, right); this->current_expression = build_bit_logic_operation(expression, left, right);
break; break;
case boot::binary_operator::exclusive_disjunction: case frontend::binary_operator::exclusive_disjunction:
this->current_expression = build_bit_logic_operation(expression, left, right); this->current_expression = build_bit_logic_operation(expression, left, right);
break; break;
case boot::binary_operator::equals: case frontend::binary_operator::equals:
this->current_expression = build_equality_operation(expression, left, right); this->current_expression = build_equality_operation(expression, left, right);
break; break;
case boot::binary_operator::not_equals: case frontend::binary_operator::not_equals:
this->current_expression = build_equality_operation(expression, left, right); this->current_expression = build_equality_operation(expression, left, right);
break; break;
case boot::binary_operator::shift_left: case frontend::binary_operator::shift_left:
this->current_expression = build_binary_operation( this->current_expression = build_binary_operation(
is_numeric_type(left_type) && right_type == elna_word_type_node, is_numeric_type(left_type) && right_type == elna_word_type_node,
expression, LSHIFT_EXPR, left, right, left_type); expression, LSHIFT_EXPR, left, right, left_type);
break; break;
case boot::binary_operator::shift_right: case frontend::binary_operator::shift_right:
this->current_expression = build_binary_operation( this->current_expression = build_binary_operation(
is_numeric_type(left_type) && right_type == elna_word_type_node, is_numeric_type(left_type) && right_type == elna_word_type_node,
expression, RSHIFT_EXPR, left, right, left_type); expression, RSHIFT_EXPR, left, right, left_type);
@@ -644,14 +644,14 @@ namespace elna::gcc
} }
} }
void generic_visitor::visit(boot::unary_expression *expression) void generic_visitor::visit(frontend::unary_expression *expression)
{ {
expression->operand().accept(this); expression->operand().accept(this);
location_t location = get_location(&expression->position()); location_t location = get_location(&expression->position());
switch (expression->operation()) switch (expression->operation())
{ {
case boot::unary_operator::reference: case frontend::unary_operator::reference:
this->current_expression = prepare_rvalue(this->current_expression); this->current_expression = prepare_rvalue(this->current_expression);
TREE_ADDRESSABLE(this->current_expression) = 1; TREE_ADDRESSABLE(this->current_expression) = 1;
this->current_expression = build_fold_addr_expr_with_type_loc(location, this->current_expression = build_fold_addr_expr_with_type_loc(location,
@@ -659,7 +659,7 @@ namespace elna::gcc
build_global_pointer_type(TREE_TYPE(this->current_expression))); build_global_pointer_type(TREE_TYPE(this->current_expression)));
TREE_NO_TRAMPOLINE(this->current_expression) = 1; TREE_NO_TRAMPOLINE(this->current_expression) = 1;
break; break;
case boot::unary_operator::negation: case frontend::unary_operator::negation:
if (TREE_TYPE(this->current_expression) == elna_bool_type_node) if (TREE_TYPE(this->current_expression) == elna_bool_type_node)
{ {
this->current_expression = build1_loc(location, TRUTH_NOT_EXPR, this->current_expression = build1_loc(location, TRUTH_NOT_EXPR,
@@ -677,7 +677,7 @@ namespace elna::gcc
this->current_expression = error_mark_node; this->current_expression = error_mark_node;
} }
break; break;
case boot::unary_operator::minus: case frontend::unary_operator::minus:
if (is_integral_type(TREE_TYPE(this->current_expression))) if (is_integral_type(TREE_TYPE(this->current_expression)))
{ {
this->current_expression = fold_build1(NEGATE_EXPR, TREE_TYPE(this->current_expression), this->current_expression = fold_build1(NEGATE_EXPR, TREE_TYPE(this->current_expression),
@@ -692,7 +692,7 @@ namespace elna::gcc
} }
} }
void generic_visitor::visit(boot::constant_declaration *definition) void generic_visitor::visit(frontend::constant_declaration *definition)
{ {
location_t definition_location = get_location(&definition->position()); location_t definition_location = get_location(&definition->position());
definition->body().accept(this); definition->body().accept(this);
@@ -732,7 +732,7 @@ namespace elna::gcc
this->current_expression = NULL_TREE; this->current_expression = NULL_TREE;
} }
void generic_visitor::visit(boot::variable_declaration *declaration) void generic_visitor::visit(frontend::variable_declaration *declaration)
{ {
for (const auto& variable_identifier : declaration->identifiers) for (const auto& variable_identifier : declaration->identifiers)
{ {
@@ -784,7 +784,7 @@ namespace elna::gcc
} }
} }
void generic_visitor::visit(boot::variable_expression *expression) void generic_visitor::visit(frontend::variable_expression *expression)
{ {
auto symbol = this->symbols->lookup(expression->name); auto symbol = this->symbols->lookup(expression->name);
@@ -800,7 +800,7 @@ namespace elna::gcc
} }
} }
void generic_visitor::visit(boot::array_access_expression *expression) void generic_visitor::visit(frontend::array_access_expression *expression)
{ {
expression->base().accept(this); expression->base().accept(this);
tree designator = this->current_expression; tree designator = this->current_expression;
@@ -829,7 +829,7 @@ namespace elna::gcc
tree string_ptr = build3_loc(location, COMPONENT_REF, TREE_TYPE(elna_string_ptr_field_node), tree string_ptr = build3_loc(location, COMPONENT_REF, TREE_TYPE(elna_string_ptr_field_node),
designator, elna_string_ptr_field_node, NULL_TREE); designator, elna_string_ptr_field_node, NULL_TREE);
tree target_pointer = do_pointer_arithmetic(boot::binary_operator::sum, string_ptr, offset, location); tree target_pointer = do_pointer_arithmetic(frontend::binary_operator::sum, string_ptr, offset, location);
this->current_expression = build1_loc(location, INDIRECT_REF, this->current_expression = build1_loc(location, INDIRECT_REF,
elna_char_type_node, target_pointer); elna_char_type_node, target_pointer);
@@ -842,7 +842,7 @@ namespace elna::gcc
} }
} }
bool generic_visitor::expect_trait_type_only(boot::traits_expression *trait) bool generic_visitor::expect_trait_type_only(frontend::traits_expression *trait)
{ {
if (trait->parameters.size() != 1) if (trait->parameters.size() != 1)
{ {
@@ -856,7 +856,7 @@ namespace elna::gcc
return this->current_expression != error_mark_node; return this->current_expression != error_mark_node;
} }
bool generic_visitor::expect_trait_for_integral_type(boot::traits_expression *trait) bool generic_visitor::expect_trait_for_integral_type(frontend::traits_expression *trait)
{ {
if (!expect_trait_type_only(trait)) if (!expect_trait_type_only(trait))
{ {
@@ -872,7 +872,7 @@ namespace elna::gcc
return true; return true;
} }
void generic_visitor::visit(boot::traits_expression *trait) void generic_visitor::visit(frontend::traits_expression *trait)
{ {
location_t trait_location = get_location(&trait->position()); location_t trait_location = get_location(&trait->position());
@@ -945,7 +945,7 @@ namespace elna::gcc
} }
} }
void generic_visitor::visit(boot::field_access_expression *expression) void generic_visitor::visit(frontend::field_access_expression *expression)
{ {
expression->base().accept(this); expression->base().accept(this);
location_t expression_location = get_location(&expression->position()); location_t expression_location = get_location(&expression->position());
@@ -991,7 +991,7 @@ namespace elna::gcc
} }
} }
void generic_visitor::visit(boot::dereference_expression *expression) void generic_visitor::visit(frontend::dereference_expression *expression)
{ {
expression->base().accept(this); expression->base().accept(this);
location_t expression_location = get_location(&expression->position()); location_t expression_location = get_location(&expression->position());
@@ -1010,7 +1010,7 @@ namespace elna::gcc
} }
} }
void generic_visitor::visit(boot::assign_statement *statement) void generic_visitor::visit(frontend::assign_statement *statement)
{ {
statement->lvalue().accept(this); statement->lvalue().accept(this);
@@ -1045,7 +1045,7 @@ namespace elna::gcc
this->current_expression = NULL_TREE; this->current_expression = NULL_TREE;
} }
void generic_visitor::visit(boot::if_statement *statement) void generic_visitor::visit(frontend::if_statement *statement)
{ {
tree endif_label_decl = create_artificial_label(UNKNOWN_LOCATION); tree endif_label_decl = create_artificial_label(UNKNOWN_LOCATION);
tree goto_endif = build1(GOTO_EXPR, void_type_node, endif_label_decl); tree goto_endif = build1(GOTO_EXPR, void_type_node, endif_label_decl);
@@ -1068,7 +1068,7 @@ namespace elna::gcc
this->current_expression = NULL_TREE; this->current_expression = NULL_TREE;
} }
void generic_visitor::make_if_branch(boot::conditional_statements& branch, tree goto_endif) void generic_visitor::make_if_branch(frontend::conditional_statements& branch, tree goto_endif)
{ {
branch.prerequisite().accept(this); branch.prerequisite().accept(this);
@@ -1102,11 +1102,11 @@ namespace elna::gcc
append_statement(else_label_expr); append_statement(else_label_expr);
} }
void generic_visitor::visit(boot::import_declaration *) void generic_visitor::visit(frontend::import_declaration *)
{ {
} }
void generic_visitor::visit(boot::while_statement *statement) void generic_visitor::visit(frontend::while_statement *statement)
{ {
location_t prerequisite_location = get_location(&statement->body().prerequisite().position()); location_t prerequisite_location = get_location(&statement->body().prerequisite().position());
tree prerequisite_label_decl = build_label_decl("while_do", prerequisite_location); tree prerequisite_label_decl = build_label_decl("while_do", prerequisite_location);
@@ -1127,9 +1127,9 @@ namespace elna::gcc
this->current_expression = NULL_TREE; this->current_expression = NULL_TREE;
} }
void generic_visitor::visit_statements(const std::vector<boot::statement *>& statements) void generic_visitor::visit_statements(const std::vector<frontend::statement *>& statements)
{ {
for (boot::statement *const statement : statements) for (frontend::statement *const statement : statements)
{ {
statement->accept(this); statement->accept(this);
@@ -1141,9 +1141,9 @@ namespace elna::gcc
} }
} }
void generic_visitor::visit(boot::return_statement *statement) void generic_visitor::visit(frontend::return_statement *statement)
{ {
boot::expression *return_expression = &statement->return_expression(); frontend::expression *return_expression = &statement->return_expression();
location_t statement_position = get_location(&statement->position()); location_t statement_position = get_location(&statement->position());
tree set_result{ NULL_TREE }; tree set_result{ NULL_TREE };
tree return_type = TREE_TYPE(TREE_TYPE(current_function_decl)); tree return_type = TREE_TYPE(TREE_TYPE(current_function_decl));
@@ -1183,14 +1183,14 @@ namespace elna::gcc
this->current_expression = NULL_TREE; this->current_expression = NULL_TREE;
} }
void generic_visitor::visit(boot::defer_statement *statement) void generic_visitor::visit(frontend::defer_statement *statement)
{ {
enter_scope(); enter_scope();
visit_statements(statement->statements); visit_statements(statement->statements);
defer(leave_scope()); defer(leave_scope());
} }
void generic_visitor::visit(boot::case_statement *statement) void generic_visitor::visit(frontend::case_statement *statement)
{ {
statement->condition().accept(this); statement->condition().accept(this);
tree condition_expression = this->current_expression; tree condition_expression = this->current_expression;
@@ -1207,9 +1207,9 @@ namespace elna::gcc
tree end_label_declaration = create_artificial_label(get_location(&statement->position())); tree end_label_declaration = create_artificial_label(get_location(&statement->position()));
tree switch_statements = alloc_stmt_list(); tree switch_statements = alloc_stmt_list();
for (const boot::switch_case& case_block : statement->cases) for (const frontend::switch_case& case_block : statement->cases)
{ {
for (boot::expression *const case_label : case_block.labels) for (frontend::expression *const case_label : case_block.labels)
{ {
case_label->accept(this); case_label->accept(this);
location_t case_location = get_location(&case_label->position()); location_t case_location = get_location(&case_label->position());

View File

@@ -128,12 +128,12 @@ namespace elna::gcc
return field_declaration; return field_declaration;
} }
tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree do_pointer_arithmetic(frontend::binary_operator binary_operator,
tree left, tree right, location_t operation_location) tree left, tree right, location_t operation_location)
{ {
tree left_type = get_qualified_type(TREE_TYPE(left), TYPE_UNQUALIFIED); tree left_type = get_qualified_type(TREE_TYPE(left), TYPE_UNQUALIFIED);
tree right_type = get_qualified_type(TREE_TYPE(right), TYPE_UNQUALIFIED); tree right_type = get_qualified_type(TREE_TYPE(right), TYPE_UNQUALIFIED);
if (binary_operator == boot::binary_operator::sum) if (binary_operator == frontend::binary_operator::sum)
{ {
tree pointer{ NULL_TREE }; tree pointer{ NULL_TREE };
tree offset{ NULL_TREE }; tree offset{ NULL_TREE };
@@ -164,7 +164,7 @@ namespace elna::gcc
return fold_build2_loc(operation_location, POINTER_PLUS_EXPR, TREE_TYPE(pointer), pointer, offset); return fold_build2_loc(operation_location, POINTER_PLUS_EXPR, TREE_TYPE(pointer), pointer, offset);
} }
else if (binary_operator == boot::binary_operator::subtraction) else if (binary_operator == frontend::binary_operator::subtraction)
{ {
if (POINTER_TYPE_P(left_type) && is_integral_type(right_type)) if (POINTER_TYPE_P(left_type) && is_integral_type(right_type))
{ {
@@ -186,7 +186,7 @@ namespace elna::gcc
gcc_unreachable(); gcc_unreachable();
} }
tree build_binary_operation(bool condition, boot::binary_expression *expression, tree build_binary_operation(bool condition, frontend::binary_expression *expression,
tree_code operator_code, tree left, tree right, tree target_type) tree_code operator_code, tree left, tree right, tree target_type)
{ {
location_t expression_location = get_location(&expression->position()); location_t expression_location = get_location(&expression->position());
@@ -202,7 +202,7 @@ namespace elna::gcc
error_at(expression_location, error_at(expression_location,
"invalid operands of type '%s' and '%s' for operator %s", "invalid operands of type '%s' and '%s' for operator %s",
print_type(left_type).c_str(), print_type(right_type).c_str(), print_type(left_type).c_str(), print_type(right_type).c_str(),
elna::boot::print_binary_operator(expression->operation())); elna::frontend::print_binary_operator(expression->operation()));
return error_mark_node; return error_mark_node;
} }
} }

View File

@@ -29,7 +29,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks-def.h" #include "langhooks-def.h"
#include <fstream> #include <fstream>
#include "elna/boot/dependency.h" #include "elna/frontend/dependency.h"
#include "elna/gcc/elna-tree.h" #include "elna/gcc/elna-tree.h"
#include "elna/gcc/elna-generic.h" #include "elna/gcc/elna-generic.h"
#include "elna/gcc/elna-diagnostic.h" #include "elna/gcc/elna-diagnostic.h"
@@ -62,9 +62,9 @@ static bool elna_langhook_init(void)
return true; return true;
} }
using dependency_state = elna::boot::dependency_state<std::shared_ptr<elna::gcc::symbol_table>>; using dependency_state = elna::frontend::dependency_state<std::shared_ptr<elna::gcc::symbol_table>>;
static elna::boot::dependency elna_parse_file(dependency_state& state, const char *filename) static elna::frontend::dependency elna_parse_file(dependency_state& state, const char *filename)
{ {
std::ifstream entry_point{ filename, std::ios::in }; std::ifstream entry_point{ filename, std::ios::in };
@@ -73,19 +73,19 @@ static elna::boot::dependency elna_parse_file(dependency_state& state, const cha
fatal_error(UNKNOWN_LOCATION, "Cannot open filename %s: %m", filename); fatal_error(UNKNOWN_LOCATION, "Cannot open filename %s: %m", filename);
} }
elna::gcc::linemap_guard{ filename }; elna::gcc::linemap_guard{ filename };
elna::boot::dependency outcome = elna::boot::read_source(entry_point, filename); elna::frontend::dependency outcome = elna::frontend::read_source(entry_point, filename);
if (outcome.has_errors()) if (outcome.has_errors())
{ {
elna::gcc::report_errors(outcome.errors()); elna::gcc::report_errors(outcome.errors());
return outcome; return outcome;
} }
elna::boot::symbol_bag outcome_bag = elna::boot::symbol_bag{ std::move(outcome.unresolved), state.globals }; elna::frontend::symbol_bag outcome_bag = elna::frontend::symbol_bag{ std::move(outcome.unresolved), state.globals };
for (const auto& sub_tree : outcome.tree->imports) for (const auto& sub_tree : outcome.tree->imports)
{ {
std::filesystem::path sub_path = "source" / elna::boot::build_path(sub_tree->segments); std::filesystem::path sub_path = "source" / elna::frontend::build_path(sub_tree->segments);
std::unordered_map<std::filesystem::path, elna::boot::symbol_bag>::const_iterator cached_import = std::unordered_map<std::filesystem::path, elna::frontend::symbol_bag>::const_iterator cached_import =
state.cache.find(sub_path); state.cache.find(sub_path);
if (cached_import == state.cache.end()) if (cached_import == state.cache.end())
@@ -114,7 +114,7 @@ static void elna_langhook_parse_file(void)
for (unsigned int i = 0; i < num_in_fnames; i++) for (unsigned int i = 0; i < num_in_fnames; i++)
{ {
elna::boot::dependency outcome = elna_parse_file(state, in_fnames[i]); elna::frontend::dependency outcome = elna_parse_file(state, in_fnames[i]);
linemap_add(line_table, LC_ENTER, 0, in_fnames[i], 1); linemap_add(line_table, LC_ENTER, 0, in_fnames[i], 1);
elna::gcc::generic_visitor generic_visitor{ state.custom, state.cache.find(in_fnames[i])->second }; elna::gcc::generic_visitor generic_visitor{ state.custom, state.cache.find(in_fnames[i])->second };

View File

@@ -22,10 +22,10 @@ along with GCC; see the file COPYING3. If not see
#include <string> #include <string>
#include <vector> #include <vector>
#include <optional> #include <optional>
#include "elna/boot/symbol.h" #include "elna/frontend/symbol.h"
#include "elna/boot/result.h" #include "elna/frontend/result.h"
namespace elna::boot namespace elna::frontend
{ {
enum class binary_operator enum class binary_operator
{ {

View File

@@ -19,11 +19,11 @@ along with GCC; see the file COPYING3. If not see
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include "elna/boot/result.h" #include "elna/frontend/result.h"
#include "elna/boot/ast.h" #include "elna/frontend/ast.h"
#include "elna/boot/symbol.h" #include "elna/frontend/symbol.h"
namespace elna::boot namespace elna::frontend
{ {
class dependency : public error_container class dependency : public error_container
{ {
@@ -48,7 +48,7 @@ namespace elna::boot
std::unordered_map<std::filesystem::path, symbol_bag> cache; std::unordered_map<std::filesystem::path, symbol_bag> cache;
explicit dependency_state(T custom) explicit dependency_state(T custom)
: globals(elna::boot::builtin_symbol_table()), custom(custom) : globals(builtin_symbol_table()), custom(custom)
{ {
} }
}; };

View File

@@ -18,10 +18,10 @@ along with GCC; see the file COPYING3. If not see
#pragma once #pragma once
#include <optional> #include <optional>
#include "elna/boot/ast.h" #include "elna/frontend/ast.h"
#include "location.hh" #include "location.hh"
namespace elna::boot namespace elna::frontend
{ {
position make_position(const yy::location& location); position make_position(const yy::location& location);

View File

@@ -23,7 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include <memory> #include <memory>
#include <variant> #include <variant>
namespace elna::boot namespace elna::frontend
{ {
/** /**
* Position in the source text. * Position in the source text.
@@ -118,7 +118,7 @@ namespace elna::boot
} }
template<> template<>
struct std::hash<elna::boot::identifier_definition> struct std::hash<elna::frontend::identifier_definition>
{ {
std::size_t operator()(const elna::boot::identifier_definition& key) const noexcept; std::size_t operator()(const elna::frontend::identifier_definition& key) const noexcept;
}; };

View File

@@ -22,11 +22,11 @@ along with GCC; see the file COPYING3. If not see
#include <memory> #include <memory>
#include <deque> #include <deque>
#include "elna/boot/ast.h" #include "elna/frontend/ast.h"
#include "elna/boot/result.h" #include "elna/frontend/result.h"
#include "elna/boot/symbol.h" #include "elna/frontend/symbol.h"
namespace elna::boot namespace elna::frontend
{ {
class undeclared_error : public error class undeclared_error : public error
{ {

View File

@@ -24,9 +24,9 @@ along with GCC; see the file COPYING3. If not see
#include <vector> #include <vector>
#include <forward_list> #include <forward_list>
#include "elna/boot/result.h" #include "elna/frontend/result.h"
namespace elna::boot namespace elna::frontend
{ {
class alias_type; class alias_type;
class primitive_type; class primitive_type;

View File

@@ -30,12 +30,12 @@ namespace elna::gcc
void init_ttree(); void init_ttree();
std::shared_ptr<symbol_table> builtin_symbol_table(); std::shared_ptr<symbol_table> builtin_symbol_table();
void rewrite_symbol_table(std::shared_ptr<boot::symbol_table> info_table, std::shared_ptr<symbol_table> symbols); void rewrite_symbol_table(std::shared_ptr<frontend::symbol_table> info_table, std::shared_ptr<symbol_table> symbols);
tree handle_symbol(const std::string& symbol_name, std::shared_ptr<boot::alias_type> reference, tree handle_symbol(const std::string& symbol_name, std::shared_ptr<frontend::alias_type> reference,
std::shared_ptr<symbol_table> symbols); std::shared_ptr<symbol_table> symbols);
tree get_inner_alias(const boot::type& type, std::shared_ptr<symbol_table> symbols); tree get_inner_alias(const frontend::type& type, std::shared_ptr<symbol_table> symbols);
void declare_procedure(const std::string& name, const boot::procedure_info& info, void declare_procedure(const std::string& name, const frontend::procedure_info& info,
std::shared_ptr<symbol_table> symbols); std::shared_ptr<symbol_table> symbols);
tree declare_variable(const std::string& name, const boot::variable_info& info, tree declare_variable(const std::string& name, const frontend::variable_info& info,
std::shared_ptr<symbol_table> symbols); std::shared_ptr<symbol_table> symbols);
} }

View File

@@ -27,7 +27,7 @@ along with GCC; see the file COPYING3. If not see
#include <deque> #include <deque>
#include <memory> #include <memory>
#include "elna/boot/result.h" #include "elna/frontend/result.h"
namespace elna::gcc namespace elna::gcc
{ {
@@ -40,7 +40,7 @@ namespace elna::gcc
~linemap_guard(); ~linemap_guard();
}; };
location_t get_location(const boot::position *position); location_t get_location(const frontend::position *position);
std::string print_type(tree type); std::string print_type(tree type);
void report_errors(const std::deque<std::unique_ptr<boot::error>>& errors); void report_errors(const std::deque<std::unique_ptr<frontend::error>>& errors);
} }

View File

@@ -17,9 +17,9 @@ along with GCC; see the file COPYING3. If not see
#pragma once #pragma once
#include "elna/boot/ast.h" #include "elna/frontend/ast.h"
#include "elna/boot/symbol.h" #include "elna/frontend/symbol.h"
#include "elna/boot/semantic.h" #include "elna/frontend/semantic.h"
#include "elna/gcc/elna-tree.h" #include "elna/gcc/elna-tree.h"
#include "config.h" #include "config.h"
@@ -33,65 +33,65 @@ along with GCC; see the file COPYING3. If not see
namespace elna::gcc namespace elna::gcc
{ {
class generic_visitor final : public boot::empty_visitor class generic_visitor final : public frontend::empty_visitor
{ {
tree current_expression{ NULL_TREE }; tree current_expression{ NULL_TREE };
elna::boot::symbol_bag bag; elna::frontend::symbol_bag bag;
std::shared_ptr<symbol_table> symbols; std::shared_ptr<symbol_table> symbols;
void enter_scope(); void enter_scope();
tree leave_scope(); tree leave_scope();
void make_if_branch(boot::conditional_statements& branch, tree goto_endif); void make_if_branch(frontend::conditional_statements& branch, tree goto_endif);
tree build_arithmetic_operation(boot::binary_expression *expression, tree build_arithmetic_operation(frontend::binary_expression *expression,
tree_code operator_code, tree left, tree right); tree_code operator_code, tree left, tree right);
tree build_comparison_operation(boot::binary_expression *expression, tree build_comparison_operation(frontend::binary_expression *expression,
tree_code operator_code, tree left, tree right); tree_code operator_code, tree left, tree right);
tree build_bit_logic_operation(boot::binary_expression *expression, tree left, tree right); tree build_bit_logic_operation(frontend::binary_expression *expression, tree left, tree right);
tree build_equality_operation(boot::binary_expression *expression, tree left, tree right); tree build_equality_operation(frontend::binary_expression *expression, tree left, tree right);
void build_procedure_call(location_t call_location, void build_procedure_call(location_t call_location,
tree procedure_address, const std::vector<boot::expression *>& arguments); tree procedure_address, const std::vector<frontend::expression *>& arguments);
void build_record_call(location_t call_location, void build_record_call(location_t call_location,
tree symbol, const std::vector<boot::expression *>& arguments); tree symbol, const std::vector<frontend::expression *>& arguments);
bool build_builtin_procedures(boot::procedure_call *call); bool build_builtin_procedures(frontend::procedure_call *call);
void build_assert_builtin(location_t call_location, const std::vector<boot::expression *>& arguments); void build_assert_builtin(location_t call_location, const std::vector<frontend::expression *>& arguments);
bool expect_trait_type_only(boot::traits_expression *trait); bool expect_trait_type_only(frontend::traits_expression *trait);
bool expect_trait_for_integral_type(boot::traits_expression *trait); bool expect_trait_for_integral_type(frontend::traits_expression *trait);
void visit_statements(const std::vector<boot::statement *>& statements); void visit_statements(const std::vector<frontend::statement *>& statements);
bool assert_constant(location_t expression_location); bool assert_constant(location_t expression_location);
public: public:
generic_visitor(std::shared_ptr<symbol_table> symbol_table, elna::boot::symbol_bag bag); generic_visitor(std::shared_ptr<symbol_table> symbol_table, elna::frontend::symbol_bag bag);
void visit(boot::program *program) override; void visit(frontend::program *program) override;
void visit(boot::procedure_declaration *definition) override; void visit(frontend::procedure_declaration *definition) override;
void visit(boot::procedure_call *call) override; void visit(frontend::procedure_call *call) override;
void visit(boot::cast_expression *expression) override; void visit(frontend::cast_expression *expression) override;
void visit(boot::traits_expression *trait) override; void visit(frontend::traits_expression *trait) override;
void visit(boot::literal<std::int32_t> *literal) override; void visit(frontend::literal<std::int32_t> *literal) override;
void visit(boot::literal<std::uint32_t> *literal) override; void visit(frontend::literal<std::uint32_t> *literal) override;
void visit(boot::literal<double> *literal) override; void visit(frontend::literal<double> *literal) override;
void visit(boot::literal<bool> *boolean) override; void visit(frontend::literal<bool> *boolean) override;
void visit(boot::literal<unsigned char> *character) override; void visit(frontend::literal<unsigned char> *character) override;
void visit(boot::literal<std::nullptr_t> *) override; void visit(frontend::literal<std::nullptr_t> *) override;
void visit(boot::literal<std::string> *string) override; void visit(frontend::literal<std::string> *string) override;
void visit(boot::binary_expression *expression) override; void visit(frontend::binary_expression *expression) override;
void visit(boot::unary_expression *expression) override; void visit(frontend::unary_expression *expression) override;
void visit(boot::constant_declaration *definition) override; void visit(frontend::constant_declaration *definition) override;
void visit(boot::variable_declaration *declaration) override; void visit(frontend::variable_declaration *declaration) override;
void visit(boot::variable_expression *expression) override; void visit(frontend::variable_expression *expression) override;
void visit(boot::array_access_expression *expression) override; void visit(frontend::array_access_expression *expression) override;
void visit(boot::field_access_expression *expression) override; void visit(frontend::field_access_expression *expression) override;
void visit(boot::dereference_expression *expression) override; void visit(frontend::dereference_expression *expression) override;
void visit(boot::unit *unit) override; void visit(frontend::unit *unit) override;
void visit(boot::assign_statement *statement) override; void visit(frontend::assign_statement *statement) override;
void visit(boot::if_statement *statement) override; void visit(frontend::if_statement *statement) override;
void visit(boot::import_declaration *) override; void visit(frontend::import_declaration *) override;
void visit(boot::while_statement *statement) override; void visit(frontend::while_statement *statement) override;
void visit(boot::return_statement *statement) override; void visit(frontend::return_statement *statement) override;
void visit(boot::defer_statement *statement) override; void visit(frontend::defer_statement *statement) override;
void visit(boot::case_statement *statement) override; void visit(frontend::case_statement *statement) override;
}; };
} }

View File

@@ -27,13 +27,13 @@ along with GCC; see the file COPYING3. If not see
#include "stringpool.h" #include "stringpool.h"
#include "fold-const.h" #include "fold-const.h"
#include "elna/boot/ast.h" #include "elna/frontend/ast.h"
#include "elna/boot/symbol.h" #include "elna/frontend/symbol.h"
#include "elna/gcc/elna1.h" #include "elna/gcc/elna1.h"
namespace elna::gcc namespace elna::gcc
{ {
using symbol_table = boot::symbol_map<tree, tree, NULL_TREE>; using symbol_table = frontend::symbol_map<tree, tree, NULL_TREE>;
bool is_integral_type(tree type); bool is_integral_type(tree type);
bool is_numeric_type(tree type); bool is_numeric_type(tree type);
@@ -74,11 +74,11 @@ namespace elna::gcc
void defer(tree statement_tree); void defer(tree statement_tree);
tree chain_defer(); tree chain_defer();
tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree do_pointer_arithmetic(frontend::binary_operator binary_operator,
tree left, tree right, location_t expression_location); tree left, tree right, location_t expression_location);
tree build_binary_operation(bool condition, boot::binary_expression *expression, tree build_binary_operation(bool condition, frontend::binary_expression *expression,
tree_code operator_code, tree left, tree right, tree target_type); tree_code operator_code, tree left, tree right, tree target_type);
tree build_arithmetic_operation(boot::binary_expression *expression, tree build_arithmetic_operation(frontend::binary_expression *expression,
tree_code operator_code, tree left, tree right); tree_code operator_code, tree left, tree right);
tree build_field(location_t location, tree record_type, const std::string name, tree type); tree build_field(location_t location, tree record_type, const std::string name, tree type);
tree find_field_by_name(location_t expression_location, tree type, const std::string& field_name); tree find_field_by_name(location_t expression_location, tree type, const std::string& field_name);

View File

@@ -6,6 +6,7 @@
require 'uri' require 'uri'
require 'net/http' require 'net/http'
require 'open3' require 'open3'
require 'pathname'
def gcc_verbose(gcc_binary) def gcc_verbose(gcc_binary)
read, write = IO.pipe read, write = IO.pipe
@@ -59,18 +60,20 @@ end
namespace :boot do namespace :boot do
# Dependencies. # Dependencies.
GCC_VERSION = "15.1.0" GCC_VERSION = "15.2.0"
HOST_GCC = TMP + 'host/gcc' HOST_GCC = 'build/host/gcc'
HOST_INSTALL = 'build/host/install'
GCC_PATCH = 'https://raw.githubusercontent.com/Homebrew/formula-patches/575ffcaed6d3112916fed77d271dd3799a7255c4/gcc/gcc-15.1.0.diff' GCC_PATCH = 'https://raw.githubusercontent.com/Homebrew/formula-patches/575ffcaed6d3112916fed77d271dd3799a7255c4/gcc/gcc-15.1.0.diff'
directory HOST_GCC directory HOST_GCC
directory(TMP + 'tools') directory HOST_INSTALL
directory 'build/tools'
desc 'Download and configure the bootstrap compiler' desc 'Download and configure the bootstrap compiler'
task configure: [TMP + 'tools', HOST_GCC, HOST_INSTALL] do task configure: ['build/tools', HOST_GCC, HOST_INSTALL] do
url = URI.parse "https://gcc.gnu.org/pub/gcc/releases/gcc-#{GCC_VERSION}/gcc-#{GCC_VERSION}.tar.xz" url = URI.parse "https://gcc.gnu.org/pub/gcc/releases/gcc-#{GCC_VERSION}/gcc-#{GCC_VERSION}.tar.xz"
build_target = find_build_target build_target = find_build_target
source_directory = TMP + "tools/gcc-#{GCC_VERSION}" source_directory = Pathname.new "build/tools/gcc-#{GCC_VERSION}"
frontend_link = source_directory + 'gcc' frontend_link = source_directory + 'gcc'
download_and_pipe url, source_directory.dirname, ['tar', '-Jxv'] download_and_pipe url, source_directory.dirname, ['tar', '-Jxv']
@@ -80,7 +83,7 @@ namespace :boot do
File.symlink Pathname.new('.').relative_path_from(frontend_link), (frontend_link + 'elna') File.symlink Pathname.new('.').relative_path_from(frontend_link), (frontend_link + 'elna')
configure_options = [ configure_options = [
"--prefix=#{HOST_INSTALL.realpath}", "--prefix=#{File.realpath HOST_INSTALL}",
'--enable-languages=c,c++,elna', '--enable-languages=c,c++,elna',
'--disable-bootstrap', '--disable-bootstrap',
'--disable-multilib', '--disable-multilib',

36
rakelib/gcc.rake Normal file
View File

@@ -0,0 +1,36 @@
# This Source Code Form is subject to the terms of the Mozilla Public License,
# v. 2.0. If a copy of the MPL was not distributed with this file, You can
# obtain one at https://mozilla.org/MPL/2.0/. -}
# frozen_string_literal: true
require 'pathname'
require 'rake/clean'
CLEAN.include 'build/gcc'
task source: ['source/main.elna', 'build/gcc/elna'] do |t|
sources, compiler = t.prerequisites.partition { |f| f.end_with? '.elna' }
sh *compiler, '--parse', *sources
end
rule(/gcc\/.+\.o$/ => ->(file) {
source = Pathname.new('source') +
Pathname.new(file).relative_path_from('build/gcc').sub_ext('.elna')
['build/host/install/bin/gelna', source]
}) do |t|
Pathname.new(t.name).dirname.mkpath
sources, compiler = t.prerequisites.partition { |source| source.end_with? '.elna' }
sh *compiler, '-c', '-O0', '-g', '-o', t.name, *sources
end
file 'build/gcc/elna' => FileList['source/**/*.elna'].reject { |file|
file != file.downcase
}.map { |file|
Pathname.new('build/gcc') +
Pathname.new(file).relative_path_from('source').sub_ext('.o')
} do |t|
sh 'build/host/install/bin/gcc', '-o', t.name, *t.prerequisites
end