Use colon instead of as to cast
This commit is contained in:
parent
c564847c6b
commit
ee4ebf64b9
22
README.md
22
README.md
@ -21,3 +21,25 @@ and a possbility to compile Elna programs for different platforms.
|
|||||||
|
|
||||||
Flex and bison grammar specifications, `lexer.ll` and `parser.yy`, can be found
|
Flex and bison grammar specifications, `lexer.ll` and `parser.yy`, can be found
|
||||||
in the `boot/` directory.
|
in the `boot/` directory.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
The frontend requires GCC 14.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
|
||||||
|
```
|
||||||
|
|
||||||
|
See `rake -T` for more tasks. The GCC source is under `build/tools`. The
|
||||||
|
installation path is `build/host/install`.
|
||||||
|
110
boot/ast.cc
110
boot/ast.cc
@ -61,7 +61,7 @@ namespace boot
|
|||||||
expression->value().accept(this);
|
expression->value().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(size_of_expression *expression)
|
void empty_visitor::visit(type_expression *expression)
|
||||||
{
|
{
|
||||||
expression->body().accept(this);
|
expression->body().accept(this);
|
||||||
}
|
}
|
||||||
@ -152,21 +152,21 @@ namespace boot
|
|||||||
expression->operand().accept(this);
|
expression->operand().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(basic_type_expression *)
|
void empty_visitor::visit(basic_type *)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(array_type_expression *expression)
|
void empty_visitor::visit(array_type *expression)
|
||||||
{
|
{
|
||||||
expression->base().accept(this);
|
expression->base().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(pointer_type_expression *expression)
|
void empty_visitor::visit(pointer_type *expression)
|
||||||
{
|
{
|
||||||
expression->base().accept(this);
|
expression->base().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(record_type_expression *expression)
|
void empty_visitor::visit(record_type *expression)
|
||||||
{
|
{
|
||||||
for (auto& field : expression->fields)
|
for (auto& field : expression->fields)
|
||||||
{
|
{
|
||||||
@ -174,7 +174,7 @@ namespace boot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(union_type_expression *expression)
|
void empty_visitor::visit(union_type *expression)
|
||||||
{
|
{
|
||||||
for (auto& field : expression->fields)
|
for (auto& field : expression->fields)
|
||||||
{
|
{
|
||||||
@ -250,115 +250,113 @@ namespace boot
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
type_expression::type_expression(const struct position position)
|
top_type::top_type(const struct position position)
|
||||||
: node(position)
|
: node(position)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
basic_type_expression *type_expression::is_basic()
|
basic_type *top_type::is_basic()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
array_type_expression *type_expression::is_array()
|
array_type *top_type::is_array()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
record_type_expression *type_expression::is_record()
|
record_type *top_type::is_record()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
union_type_expression *type_expression::is_union()
|
union_type *top_type::is_union()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer_type_expression *type_expression::is_pointer()
|
pointer_type *top_type::is_pointer()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
basic_type_expression::basic_type_expression(
|
basic_type::basic_type(const struct position position, const std::string& name)
|
||||||
const struct position position, const std::string& name)
|
: top_type(position), m_name(name)
|
||||||
: type_expression(position), m_name(name)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void basic_type_expression::accept(parser_visitor *visitor)
|
void basic_type::accept(parser_visitor *visitor)
|
||||||
{
|
{
|
||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& basic_type_expression::base_name()
|
const std::string& basic_type::base_name()
|
||||||
{
|
{
|
||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
basic_type_expression *basic_type_expression::is_basic()
|
basic_type *basic_type::is_basic()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
array_type_expression::array_type_expression(const struct position position, type_expression *base,
|
array_type::array_type(const struct position position, top_type *base,
|
||||||
const std::uint32_t size)
|
const std::uint32_t size)
|
||||||
: type_expression(position), m_base(base), size(size)
|
: top_type(position), m_base(base), size(size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void array_type_expression::accept(parser_visitor *visitor)
|
void array_type::accept(parser_visitor *visitor)
|
||||||
{
|
{
|
||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_expression& array_type_expression::base()
|
top_type& array_type::base()
|
||||||
{
|
{
|
||||||
return *m_base;
|
return *m_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
array_type_expression *array_type_expression::is_array()
|
array_type*array_type::is_array()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
array_type_expression::~array_type_expression()
|
array_type::~array_type()
|
||||||
{
|
{
|
||||||
delete m_base;
|
delete m_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer_type_expression::pointer_type_expression(const struct position position, type_expression *base)
|
pointer_type::pointer_type(const struct position position, top_type *base)
|
||||||
: type_expression(position), m_base(base)
|
: top_type(position), m_base(base)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void pointer_type_expression::accept(parser_visitor *visitor)
|
void pointer_type::accept(parser_visitor *visitor)
|
||||||
{
|
{
|
||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_expression& pointer_type_expression::base()
|
top_type& pointer_type::base()
|
||||||
{
|
{
|
||||||
return *m_base;
|
return *m_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer_type_expression *pointer_type_expression::is_pointer()
|
pointer_type *pointer_type::is_pointer()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer_type_expression::~pointer_type_expression()
|
pointer_type::~pointer_type()
|
||||||
{
|
{
|
||||||
delete m_base;
|
delete m_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
composite_type_expression::composite_type_expression(const struct position position,
|
composite_type::composite_type(const struct position position, fields_t&& fields)
|
||||||
fields_t&& fields)
|
: top_type(position), fields(std::move(fields))
|
||||||
: type_expression(position), fields(std::move(fields))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
composite_type_expression::~composite_type_expression()
|
composite_type::~composite_type()
|
||||||
{
|
{
|
||||||
for (auto& field_declaration : fields)
|
for (auto& field_declaration : fields)
|
||||||
{
|
{
|
||||||
@ -366,40 +364,38 @@ namespace boot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record_type_expression::record_type_expression(const struct position position,
|
record_type::record_type(const struct position position, fields_t&& fields)
|
||||||
fields_t&& fields)
|
: composite_type(position, std::move(fields))
|
||||||
: composite_type_expression(position, std::move(fields))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void record_type_expression::accept(parser_visitor *visitor)
|
void record_type::accept(parser_visitor *visitor)
|
||||||
{
|
{
|
||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
record_type_expression *record_type_expression::is_record()
|
record_type *record_type::is_record()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
union_type_expression::union_type_expression(const struct position position,
|
union_type::union_type(const struct position position, fields_t&& fields)
|
||||||
fields_t&& fields)
|
: composite_type(position, std::move(fields))
|
||||||
: composite_type_expression(position, std::move(fields))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
union_type_expression *union_type_expression::is_union()
|
union_type *union_type::is_union()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void union_type_expression::accept(parser_visitor *visitor)
|
void union_type::accept(parser_visitor *visitor)
|
||||||
{
|
{
|
||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
variable_declaration::variable_declaration(const struct position position, const std::string& identifier,
|
variable_declaration::variable_declaration(const struct position position, const std::string& identifier,
|
||||||
const bool exported, type_expression *type)
|
const bool exported, top_type *type)
|
||||||
: definition(position, identifier, exported), m_type(type)
|
: definition(position, identifier, exported), m_type(type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -414,7 +410,7 @@ namespace boot
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_expression& variable_declaration::type()
|
top_type& variable_declaration::variable_type()
|
||||||
{
|
{
|
||||||
return *m_type;
|
return *m_type;
|
||||||
}
|
}
|
||||||
@ -446,7 +442,7 @@ namespace boot
|
|||||||
}
|
}
|
||||||
|
|
||||||
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
|
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
|
||||||
const bool exported, type_expression *return_type)
|
const bool exported, top_type *return_type)
|
||||||
: definition(position, identifier, exported), m_return_type(return_type)
|
: definition(position, identifier, exported), m_return_type(return_type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -467,7 +463,7 @@ namespace boot
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
type_expression *procedure_definition::return_type()
|
top_type *procedure_definition::return_type()
|
||||||
{
|
{
|
||||||
return m_return_type;
|
return m_return_type;
|
||||||
}
|
}
|
||||||
@ -485,7 +481,7 @@ namespace boot
|
|||||||
}
|
}
|
||||||
|
|
||||||
type_definition::type_definition(const struct position position, const std::string& identifier,
|
type_definition::type_definition(const struct position position, const std::string& identifier,
|
||||||
const bool exported, type_expression *body)
|
const bool exported, top_type *body)
|
||||||
: definition(position, identifier, exported), m_body(body)
|
: definition(position, identifier, exported), m_body(body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -495,7 +491,7 @@ namespace boot
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_expression& type_definition::body()
|
top_type& type_definition::body()
|
||||||
{
|
{
|
||||||
return *m_body;
|
return *m_body;
|
||||||
}
|
}
|
||||||
@ -776,7 +772,7 @@ namespace boot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cast_expression::cast_expression(const struct position position, type_expression *target, expression *value)
|
cast_expression::cast_expression(const struct position position, top_type *target, expression *value)
|
||||||
: expression(position), m_target(target), m_value(value)
|
: expression(position), m_target(target), m_value(value)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -786,7 +782,7 @@ namespace boot
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_expression& cast_expression::target()
|
top_type& cast_expression::target()
|
||||||
{
|
{
|
||||||
return *m_target;
|
return *m_target;
|
||||||
}
|
}
|
||||||
@ -802,22 +798,22 @@ namespace boot
|
|||||||
delete m_value;
|
delete m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_of_expression::size_of_expression(const struct position position, type_expression *body)
|
type_expression::type_expression(const struct position position, top_type *body)
|
||||||
: expression(position), m_body(body)
|
: expression(position), m_body(body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void size_of_expression::accept(parser_visitor *visitor)
|
void type_expression::accept(parser_visitor *visitor)
|
||||||
{
|
{
|
||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_expression& size_of_expression::body()
|
top_type& type_expression::body()
|
||||||
{
|
{
|
||||||
return *m_body;
|
return *m_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_of_expression::~size_of_expression()
|
type_expression::~type_expression()
|
||||||
{
|
{
|
||||||
delete m_body;
|
delete m_body;
|
||||||
}
|
}
|
||||||
@ -1014,6 +1010,8 @@ namespace boot
|
|||||||
return "and";
|
return "and";
|
||||||
case binary_operator::disjunction:
|
case binary_operator::disjunction:
|
||||||
return "or";
|
return "or";
|
||||||
|
case binary_operator::exclusive_disjunction:
|
||||||
|
return "xor";
|
||||||
}
|
}
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
};
|
};
|
||||||
|
@ -122,6 +122,9 @@ nil {
|
|||||||
and {
|
and {
|
||||||
return yy::parser::make_AND(this->location);
|
return yy::parser::make_AND(this->location);
|
||||||
}
|
}
|
||||||
|
xor {
|
||||||
|
return yy::parser::make_XOR(this->location);
|
||||||
|
}
|
||||||
or {
|
or {
|
||||||
return yy::parser::make_OR(this->location);
|
return yy::parser::make_OR(this->location);
|
||||||
}
|
}
|
||||||
@ -134,9 +137,6 @@ return {
|
|||||||
cast {
|
cast {
|
||||||
return yy::parser::make_CAST(this->location);
|
return yy::parser::make_CAST(this->location);
|
||||||
}
|
}
|
||||||
as {
|
|
||||||
return yy::parser::make_AS(this->location);
|
|
||||||
}
|
|
||||||
sizeof {
|
sizeof {
|
||||||
return yy::parser::make_SIZEOF(this->location);
|
return yy::parser::make_SIZEOF(this->location);
|
||||||
}
|
}
|
||||||
|
@ -85,12 +85,12 @@ along with GCC; see the file COPYING3. If not see
|
|||||||
%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO UNION
|
%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO UNION
|
||||||
%token BEGIN_BLOCK END_BLOCK EXTERN DEFER
|
%token BEGIN_BLOCK END_BLOCK EXTERN DEFER
|
||||||
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
|
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
|
||||||
%token AND OR NOT CAST AS SIZEOF
|
%token AND OR NOT CAST SIZEOF
|
||||||
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
|
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
|
||||||
%token PLUS MINUS MULTIPLICATION DIVISION REMAINDER
|
%token PLUS MINUS MULTIPLICATION DIVISION REMAINDER
|
||||||
%token ASSIGNMENT COLON HAT AT NIL ARROW
|
%token ASSIGNMENT COLON HAT AT NIL ARROW
|
||||||
|
|
||||||
%left OR AND
|
%left OR AND XOR
|
||||||
%left EQUALS NOT_EQUAL LESS_THAN GREATER_THAN LESS_EQUAL GREATER_EQUAL
|
%left EQUALS NOT_EQUAL LESS_THAN GREATER_THAN LESS_EQUAL GREATER_EQUAL
|
||||||
%left PLUS MINUS
|
%left PLUS MINUS
|
||||||
%left MULTIPLICATION DIVISION REMAINDER
|
%left MULTIPLICATION DIVISION REMAINDER
|
||||||
@ -101,7 +101,7 @@ along with GCC; see the file COPYING3. If not see
|
|||||||
%type <elna::boot::variable_declaration *> variable_declaration;
|
%type <elna::boot::variable_declaration *> variable_declaration;
|
||||||
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part
|
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part
|
||||||
formal_parameter_list;
|
formal_parameter_list;
|
||||||
%type <elna::boot::type_expression *> type_expression;
|
%type <elna::boot::top_type *> type_expression;
|
||||||
%type <elna::boot::expression *> expression operand unary;
|
%type <elna::boot::expression *> expression operand unary;
|
||||||
%type <std::vector<elna::boot::expression *>> expressions actual_parameter_list;
|
%type <std::vector<elna::boot::expression *>> expressions actual_parameter_list;
|
||||||
%type <elna::boot::designator_expression *> designator_expression;
|
%type <elna::boot::designator_expression *> designator_expression;
|
||||||
@ -117,8 +117,8 @@ along with GCC; see the file COPYING3. If not see
|
|||||||
%type <elna::boot::type_definition *> type_definition;
|
%type <elna::boot::type_definition *> type_definition;
|
||||||
%type <std::vector<elna::boot::type_definition *>> type_definitions type_part;
|
%type <std::vector<elna::boot::type_definition *>> type_definitions type_part;
|
||||||
%type <elna::boot::block *> block;
|
%type <elna::boot::block *> block;
|
||||||
%type <std::pair<std::string, elna::boot::type_expression *>> field_declaration;
|
%type <std::pair<std::string, elna::boot::top_type *>> field_declaration;
|
||||||
%type <std::vector<std::pair<std::string, elna::boot::type_expression *>>> field_list;
|
%type <std::vector<std::pair<std::string, elna::boot::top_type *>>> field_list;
|
||||||
%type <std::vector<elna::boot::conditional_statements *>> elsif_statement_list;
|
%type <std::vector<elna::boot::conditional_statements *>> elsif_statement_list;
|
||||||
%type <elna::boot::cast_expression *> cast_expression;
|
%type <elna::boot::cast_expression *> cast_expression;
|
||||||
%type <elna::boot::defer_statement *> defer_statement;
|
%type <elna::boot::defer_statement *> defer_statement;
|
||||||
@ -189,7 +189,7 @@ call_expression: IDENTIFIER actual_parameter_list
|
|||||||
$$ = new elna::boot::call_expression(elna::boot::make_position(@1), $1);
|
$$ = new elna::boot::call_expression(elna::boot::make_position(@1), $1);
|
||||||
std::swap($$->arguments(), $2);
|
std::swap($$->arguments(), $2);
|
||||||
}
|
}
|
||||||
cast_expression: CAST LEFT_PAREN expression AS type_expression RIGHT_PAREN
|
cast_expression: CAST LEFT_PAREN expression COLON type_expression RIGHT_PAREN
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::cast_expression(elna::boot::make_position(@1), $5, $3);
|
$$ = new elna::boot::cast_expression(elna::boot::make_position(@1), $5, $3);
|
||||||
}
|
}
|
||||||
@ -265,9 +265,9 @@ literal:
|
|||||||
operand:
|
operand:
|
||||||
literal { $$ = $1; }
|
literal { $$ = $1; }
|
||||||
| designator_expression { $$ = $1; }
|
| designator_expression { $$ = $1; }
|
||||||
| SIZEOF LEFT_PAREN type_expression RIGHT_PAREN
|
| LEFT_PAREN type_expression RIGHT_PAREN
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::size_of_expression(elna::boot::make_position(@1), $3);
|
$$ = new elna::boot::type_expression(elna::boot::make_position(@1), $2);
|
||||||
}
|
}
|
||||||
| cast_expression { $$ = $1; }
|
| cast_expression { $$ = $1; }
|
||||||
| call_expression { $$ = $1; }
|
| call_expression { $$ = $1; }
|
||||||
@ -339,6 +339,11 @@ expression:
|
|||||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||||
elna::boot::binary_operator::disjunction);
|
elna::boot::binary_operator::disjunction);
|
||||||
}
|
}
|
||||||
|
| expression XOR expression
|
||||||
|
{
|
||||||
|
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||||
|
elna::boot::binary_operator::exclusive_disjunction);
|
||||||
|
}
|
||||||
unary:
|
unary:
|
||||||
AT operand
|
AT operand
|
||||||
{
|
{
|
||||||
@ -403,32 +408,32 @@ optional_statements:
|
|||||||
field_declaration:
|
field_declaration:
|
||||||
IDENTIFIER COLON type_expression { $$ = std::make_pair($1, $3); }
|
IDENTIFIER COLON type_expression { $$ = std::make_pair($1, $3); }
|
||||||
field_list:
|
field_list:
|
||||||
field_declaration SEMICOLON field_list
|
field_declaration field_list
|
||||||
{
|
{
|
||||||
std::swap($$, $3);
|
std::swap($$, $2);
|
||||||
$$.emplace($$.cbegin(), $1);
|
$$.emplace($$.cbegin(), $1);
|
||||||
}
|
}
|
||||||
| field_declaration { $$.emplace_back($1); }
|
| field_declaration { $$.emplace_back($1); }
|
||||||
type_expression:
|
type_expression:
|
||||||
ARRAY INTEGER OF type_expression
|
ARRAY INTEGER OF type_expression
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::array_type_expression(elna::boot::make_position(@1), $4, $2);
|
$$ = new elna::boot::array_type(elna::boot::make_position(@1), $4, $2);
|
||||||
}
|
}
|
||||||
| POINTER TO type_expression
|
| POINTER TO type_expression
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::pointer_type_expression(elna::boot::make_position(@1), $3);
|
$$ = new elna::boot::pointer_type(elna::boot::make_position(@1), $3);
|
||||||
}
|
}
|
||||||
| RECORD field_list END_BLOCK
|
| RECORD field_list END_BLOCK
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::record_type_expression(elna::boot::make_position(@1), std::move($2));
|
$$ = new elna::boot::record_type(elna::boot::make_position(@1), std::move($2));
|
||||||
}
|
}
|
||||||
| UNION field_list END_BLOCK
|
| UNION field_list END_BLOCK
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::union_type_expression(elna::boot::make_position(@1), std::move($2));
|
$$ = new elna::boot::union_type(elna::boot::make_position(@1), std::move($2));
|
||||||
}
|
}
|
||||||
| IDENTIFIER
|
| IDENTIFIER
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::basic_type_expression(elna::boot::make_position(@1), $1);
|
$$ = new elna::boot::basic_type(elna::boot::make_position(@1), $1);
|
||||||
}
|
}
|
||||||
variable_declaration: identifier_definition COLON type_expression
|
variable_declaration: identifier_definition COLON type_expression
|
||||||
{
|
{
|
||||||
|
@ -43,6 +43,94 @@ namespace gcc
|
|||||||
this->symbol_map = symbol_table;
|
this->symbol_map = symbol_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generic_visitor::build_procedure_call(location_t call_location,
|
||||||
|
tree symbol, const std::vector<boot::expression *>& arguments)
|
||||||
|
{
|
||||||
|
vec<tree, va_gc> *argument_trees = nullptr;
|
||||||
|
tree current_parameter = TYPE_ARG_TYPES(TREE_TYPE(symbol));
|
||||||
|
|
||||||
|
vec_alloc(argument_trees, arguments.size());
|
||||||
|
for (boot::expression *const argument : arguments)
|
||||||
|
{
|
||||||
|
location_t argument_location = get_location(&argument->position());
|
||||||
|
if (is_void_type(TREE_VALUE(current_parameter)))
|
||||||
|
{
|
||||||
|
error_at(argument_location, "too many arguments, expected %i, got %lu",
|
||||||
|
list_length(TYPE_ARG_TYPES(TREE_TYPE(symbol))) - 1, arguments.size());
|
||||||
|
this->current_expression = error_mark_node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
argument->accept(this);
|
||||||
|
if (!is_assignable_from(TREE_VALUE(current_parameter), this->current_expression))
|
||||||
|
{
|
||||||
|
error_at(argument_location,
|
||||||
|
"cannot assign value of type '%s' to variable of type '%s'",
|
||||||
|
print_type(TREE_TYPE(this->current_expression)).c_str(),
|
||||||
|
print_type(TREE_VALUE(current_parameter)).c_str());
|
||||||
|
this->current_expression = error_mark_node;
|
||||||
|
}
|
||||||
|
current_parameter = TREE_CHAIN(current_parameter);
|
||||||
|
argument_trees->quick_push(this->current_expression);
|
||||||
|
}
|
||||||
|
tree stmt = build_call_expr_loc_vec(call_location, symbol, argument_trees);
|
||||||
|
|
||||||
|
if (!is_void_type(TREE_VALUE(current_parameter)))
|
||||||
|
{
|
||||||
|
error_at(call_location, "too few arguments, expected %i, got %lu",
|
||||||
|
list_length(TYPE_ARG_TYPES(TREE_TYPE(symbol))) - 1, arguments.size());
|
||||||
|
this->current_expression = error_mark_node;
|
||||||
|
}
|
||||||
|
else if (TREE_TYPE(TREE_TYPE(symbol)) == void_type_node)
|
||||||
|
{
|
||||||
|
append_statement(stmt);
|
||||||
|
this->current_expression = NULL_TREE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->current_expression = stmt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void generic_visitor::build_record_call(location_t call_location,
|
||||||
|
tree symbol, const std::vector<boot::expression *>& arguments)
|
||||||
|
{
|
||||||
|
vec<constructor_elt, va_gc> *tree_arguments = nullptr;
|
||||||
|
tree record_fields = TYPE_FIELDS(symbol);
|
||||||
|
for (boot::expression *const argument : arguments)
|
||||||
|
{
|
||||||
|
location_t argument_location = get_location(&argument->position());
|
||||||
|
|
||||||
|
if (is_void_type(record_fields))
|
||||||
|
{
|
||||||
|
error_at(argument_location, "too many arguments, expected %i, got %lu",
|
||||||
|
list_length(TYPE_FIELDS(symbol)), arguments.size());
|
||||||
|
this->current_expression = error_mark_node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
argument->accept(this);
|
||||||
|
if (!is_assignable_from(TREE_TYPE(record_fields), this->current_expression))
|
||||||
|
{
|
||||||
|
error_at(argument_location,
|
||||||
|
"cannot assign value of type '%s' to variable of type '%s'",
|
||||||
|
print_type(TREE_TYPE(this->current_expression)).c_str(),
|
||||||
|
print_type(TREE_TYPE(record_fields)).c_str());
|
||||||
|
this->current_expression = error_mark_node;
|
||||||
|
}
|
||||||
|
CONSTRUCTOR_APPEND_ELT(tree_arguments, record_fields, this->current_expression);
|
||||||
|
record_fields = TREE_CHAIN(record_fields);
|
||||||
|
}
|
||||||
|
if (!is_void_type(record_fields))
|
||||||
|
{
|
||||||
|
error_at(call_location, "too few arguments, expected %i, got %lu",
|
||||||
|
list_length(TYPE_FIELDS(symbol)), arguments.size());
|
||||||
|
this->current_expression = error_mark_node;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->current_expression = build_constructor(symbol, tree_arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::call_expression *expression)
|
void generic_visitor::visit(boot::call_expression *expression)
|
||||||
{
|
{
|
||||||
tree symbol = this->lookup(expression->name());
|
tree symbol = this->lookup(expression->name());
|
||||||
@ -56,37 +144,11 @@ namespace gcc
|
|||||||
}
|
}
|
||||||
else if (DECL_P(symbol) && is_procedure_type(TREE_TYPE(symbol)))
|
else if (DECL_P(symbol) && is_procedure_type(TREE_TYPE(symbol)))
|
||||||
{
|
{
|
||||||
vec<tree, va_gc> *arguments = nullptr;
|
build_procedure_call(call_location, symbol, expression->arguments());
|
||||||
|
|
||||||
vec_alloc(arguments, expression->arguments().size());
|
|
||||||
for (boot::expression *const argument : expression->arguments())
|
|
||||||
{
|
|
||||||
argument->accept(this);
|
|
||||||
arguments->quick_push(this->current_expression);
|
|
||||||
}
|
}
|
||||||
tree stmt = build_call_expr_loc_vec(get_location(&expression->position()), symbol, arguments);
|
else if (TYPE_P(symbol) && TREE_CODE(symbol) == RECORD_TYPE)
|
||||||
|
|
||||||
if (TREE_TYPE(TREE_TYPE(symbol)) == void_type_node)
|
|
||||||
{
|
{
|
||||||
append_statement(stmt);
|
build_record_call(call_location, symbol, expression->arguments());
|
||||||
this->current_expression = NULL_TREE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->current_expression = stmt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (TYPE_P(symbol) && is_record_type(symbol))
|
|
||||||
{
|
|
||||||
vec<constructor_elt, va_gc> *arguments = nullptr;
|
|
||||||
tree record_fields = TYPE_FIELDS(symbol);
|
|
||||||
for (boot::expression *const argument : expression->arguments())
|
|
||||||
{
|
|
||||||
argument->accept(this);
|
|
||||||
CONSTRUCTOR_APPEND_ELT(arguments, record_fields, this->current_expression);
|
|
||||||
record_fields = TREE_CHAIN(record_fields);
|
|
||||||
}
|
|
||||||
this->current_expression = build_constructor(symbol, arguments);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -107,11 +169,9 @@ namespace gcc
|
|||||||
cast_target, this->current_expression);
|
cast_target, this->current_expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::size_of_expression *expression)
|
void generic_visitor::visit(boot::type_expression *expression)
|
||||||
{
|
{
|
||||||
auto body_type = build_type(expression->body());
|
this->current_expression = build_type(expression->body());
|
||||||
|
|
||||||
this->current_expression = build1(CONVERT_EXPR, elna_word_type_node, size_in_bytes(body_type));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::program *program)
|
void generic_visitor::visit(boot::program *program)
|
||||||
@ -185,7 +245,7 @@ namespace gcc
|
|||||||
|
|
||||||
for (std::size_t i = 0; i < definition->parameters.size(); ++i)
|
for (std::size_t i = 0; i < definition->parameters.size(); ++i)
|
||||||
{
|
{
|
||||||
parameter_types[i] = build_type(definition->parameters.at(i)->type());
|
parameter_types[i] = build_type(definition->parameters.at(i)->variable_type());
|
||||||
}
|
}
|
||||||
tree return_type = definition->return_type() == nullptr
|
tree return_type = definition->return_type() == nullptr
|
||||||
? void_type_node
|
? void_type_node
|
||||||
@ -315,12 +375,12 @@ namespace gcc
|
|||||||
|
|
||||||
void generic_visitor::visit(boot::number_literal<std::int32_t> *literal)
|
void generic_visitor::visit(boot::number_literal<std::int32_t> *literal)
|
||||||
{
|
{
|
||||||
this->current_expression = build_int_cst(elna_int_type_node, literal->number());
|
this->current_expression = build_int_cst(elna_int_type_node, literal->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::number_literal<std::uint32_t> *literal)
|
void generic_visitor::visit(boot::number_literal<std::uint32_t> *literal)
|
||||||
{
|
{
|
||||||
this->current_expression = build_int_cstu(elna_word_type_node, literal->number());
|
this->current_expression = build_int_cstu(elna_word_type_node, literal->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::number_literal<double> *literal)
|
void generic_visitor::visit(boot::number_literal<double> *literal)
|
||||||
@ -329,7 +389,7 @@ namespace gcc
|
|||||||
|
|
||||||
mpfr_t number;
|
mpfr_t number;
|
||||||
mpfr_init2(number, SIGNIFICAND_BITS);
|
mpfr_init2(number, SIGNIFICAND_BITS);
|
||||||
mpfr_set_d(number, literal->number(), MPFR_RNDN);
|
mpfr_set_d(number, literal->value, MPFR_RNDN);
|
||||||
|
|
||||||
real_from_mpfr(&real_value1, number, double_type_node, MPFR_RNDN);
|
real_from_mpfr(&real_value1, number, double_type_node, MPFR_RNDN);
|
||||||
|
|
||||||
@ -340,12 +400,12 @@ namespace gcc
|
|||||||
|
|
||||||
void generic_visitor::visit(boot::number_literal<bool> *boolean)
|
void generic_visitor::visit(boot::number_literal<bool> *boolean)
|
||||||
{
|
{
|
||||||
this->current_expression = boolean->number() ? boolean_true_node : boolean_false_node;
|
this->current_expression = boolean->value ? boolean_true_node : boolean_false_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::number_literal<unsigned char> *character)
|
void generic_visitor::visit(boot::number_literal<unsigned char> *character)
|
||||||
{
|
{
|
||||||
this->current_expression = build_int_cstu(elna_char_type_node, character->number());
|
this->current_expression = build_int_cstu(elna_char_type_node, character->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::number_literal<nullptr_t> *)
|
void generic_visitor::visit(boot::number_literal<nullptr_t> *)
|
||||||
@ -355,10 +415,10 @@ namespace gcc
|
|||||||
|
|
||||||
void generic_visitor::visit(boot::number_literal<std::string> *string)
|
void generic_visitor::visit(boot::number_literal<std::string> *string)
|
||||||
{
|
{
|
||||||
tree index_constant = build_int_cstu(elna_word_type_node, string->number().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));
|
||||||
|
|
||||||
tree string_literal = build_string(string->number().size(), string->number().c_str());
|
tree string_literal = build_string(string->value.size(), string->value.c_str());
|
||||||
TREE_TYPE(string_literal) = string_type;
|
TREE_TYPE(string_literal) = string_type;
|
||||||
TREE_CONSTANT(string_literal) = 1;
|
TREE_CONSTANT(string_literal) = 1;
|
||||||
TREE_READONLY(string_literal) = 1;
|
TREE_READONLY(string_literal) = 1;
|
||||||
@ -390,11 +450,49 @@ namespace gcc
|
|||||||
expression, operator_code, left, right, elna_bool_type_node);
|
expression, operator_code, left, right, elna_bool_type_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
tree generic_visitor::build_logic_operation(boot::binary_expression *expression,
|
tree generic_visitor::build_bit_logic_operation(boot::binary_expression *expression, tree left, tree right)
|
||||||
tree_code operator_code, tree left, tree right)
|
|
||||||
{
|
{
|
||||||
return build_binary_operation(TREE_TYPE(left) == elna_bool_type_node,
|
location_t expression_location = get_location(&expression->position());
|
||||||
expression, operator_code, left, right, elna_bool_type_node);
|
tree left_type = TREE_TYPE(left);
|
||||||
|
tree right_type = TREE_TYPE(right);
|
||||||
|
tree_code logical_code, bit_code;
|
||||||
|
|
||||||
|
if (expression->operation() == boot::binary_operator::conjunction)
|
||||||
|
{
|
||||||
|
bit_code = BIT_AND_EXPR;
|
||||||
|
logical_code = TRUTH_ANDIF_EXPR;
|
||||||
|
}
|
||||||
|
else if (expression->operation() == boot::binary_operator::disjunction)
|
||||||
|
{
|
||||||
|
bit_code = BIT_IOR_EXPR;
|
||||||
|
logical_code = TRUTH_ORIF_EXPR;
|
||||||
|
}
|
||||||
|
else if (expression->operation() == boot::binary_operator::exclusive_disjunction)
|
||||||
|
{
|
||||||
|
bit_code = BIT_XOR_EXPR;
|
||||||
|
logical_code = TRUTH_XOR_EXPR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gcc_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left_type == elna_bool_type_node)
|
||||||
|
{
|
||||||
|
return build2_loc(expression_location, logical_code, elna_bool_type_node, left, right);
|
||||||
|
}
|
||||||
|
else if (is_integral_type(left_type))
|
||||||
|
{
|
||||||
|
return build2_loc(expression_location, bit_code, left_type, left, right);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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(),
|
||||||
|
elna::boot::print_binary_operator(expression->operation()));
|
||||||
|
return error_mark_node;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tree generic_visitor::build_equality_operation(boot::binary_expression *expression, tree left, tree right)
|
tree generic_visitor::build_equality_operation(boot::binary_expression *expression, tree left, tree right)
|
||||||
@ -475,7 +573,9 @@ namespace gcc
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (left_type != right_type && !are_compatible_pointers(left, right) && !are_compatible_pointers(right, left))
|
if (left_type != right_type
|
||||||
|
&& !are_compatible_pointers(left_type, right)
|
||||||
|
&& !are_compatible_pointers(right_type, left))
|
||||||
{
|
{
|
||||||
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",
|
||||||
@ -514,10 +614,13 @@ namespace gcc
|
|||||||
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 boot::binary_operator::conjunction:
|
||||||
this->current_expression = build_logic_operation(expression, TRUTH_ANDIF_EXPR, left, right);
|
this->current_expression = build_bit_logic_operation(expression, left, right);
|
||||||
break;
|
break;
|
||||||
case boot::binary_operator::disjunction:
|
case boot::binary_operator::disjunction:
|
||||||
this->current_expression = build_logic_operation(expression, TRUTH_ORIF_EXPR, left, right);
|
this->current_expression = build_bit_logic_operation(expression, left, right);
|
||||||
|
break;
|
||||||
|
case boot::binary_operator::exclusive_disjunction:
|
||||||
|
this->current_expression = build_bit_logic_operation(expression, left, right);
|
||||||
break;
|
break;
|
||||||
case boot::binary_operator::equals:
|
case boot::binary_operator::equals:
|
||||||
this->current_expression = build_equality_operation(expression, left, right);
|
this->current_expression = build_equality_operation(expression, left, right);
|
||||||
@ -531,24 +634,48 @@ namespace gcc
|
|||||||
void generic_visitor::visit(boot::unary_expression *expression)
|
void generic_visitor::visit(boot::unary_expression *expression)
|
||||||
{
|
{
|
||||||
expression->operand().accept(this);
|
expression->operand().accept(this);
|
||||||
|
location_t location = get_location(&expression->position());
|
||||||
|
|
||||||
switch (expression->operation())
|
switch (expression->operation())
|
||||||
{
|
{
|
||||||
case boot::unary_operator::reference:
|
case boot::unary_operator::reference:
|
||||||
TREE_ADDRESSABLE(this->current_expression) = 1;
|
TREE_ADDRESSABLE(this->current_expression) = 1;
|
||||||
this->current_expression = build_fold_addr_expr_with_type_loc(get_location(&expression->position()),
|
this->current_expression = build_fold_addr_expr_with_type_loc(location,
|
||||||
this->current_expression,
|
this->current_expression,
|
||||||
build_pointer_type_for_mode(TREE_TYPE(this->current_expression), VOIDmode, true));
|
build_pointer_type_for_mode(TREE_TYPE(this->current_expression), VOIDmode, true));
|
||||||
TREE_NO_TRAMPOLINE(this->current_expression) = 1;
|
TREE_NO_TRAMPOLINE(this->current_expression) = 1;
|
||||||
break;
|
break;
|
||||||
case boot::unary_operator::negation:
|
case boot::unary_operator::negation:
|
||||||
this->current_expression = build1_loc(get_location(&expression->position()), TRUTH_NOT_EXPR,
|
if (TREE_TYPE(this->current_expression) == elna_bool_type_node)
|
||||||
|
{
|
||||||
|
this->current_expression = build1_loc(location, TRUTH_NOT_EXPR,
|
||||||
boolean_type_node, this->current_expression);
|
boolean_type_node, this->current_expression);
|
||||||
|
}
|
||||||
|
else if (is_integral_type(TREE_TYPE(this->current_expression)))
|
||||||
|
{
|
||||||
|
this->current_expression = build1_loc(location, BIT_NOT_EXPR,
|
||||||
|
TREE_TYPE(this->current_expression), this->current_expression);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error_at(location, "type '%s' cannot be negated",
|
||||||
|
print_type(TREE_TYPE(this->current_expression)).c_str());
|
||||||
|
this->current_expression = error_mark_node;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case boot::unary_operator::minus:
|
case boot::unary_operator::minus:
|
||||||
|
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),
|
||||||
this->current_expression);
|
this->current_expression);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error_at(location, "type '%s' cannot be negated",
|
||||||
|
print_type(TREE_TYPE(this->current_expression)).c_str());
|
||||||
|
this->current_expression = error_mark_node;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::constant_definition *definition)
|
void generic_visitor::visit(boot::constant_definition *definition)
|
||||||
@ -603,9 +730,9 @@ namespace gcc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tree generic_visitor::build_type(boot::type_expression& type)
|
tree generic_visitor::build_type(boot::top_type& type)
|
||||||
{
|
{
|
||||||
if (boot::basic_type_expression *basic_type = type.is_basic())
|
if (boot::basic_type *basic_type = type.is_basic())
|
||||||
{
|
{
|
||||||
tree symbol = this->lookup(basic_type->base_name());
|
tree symbol = this->lookup(basic_type->base_name());
|
||||||
|
|
||||||
@ -618,7 +745,7 @@ namespace gcc
|
|||||||
|
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
else if (boot::array_type_expression *array_type = type.is_array())
|
else if (boot::array_type *array_type = type.is_array())
|
||||||
{
|
{
|
||||||
tree lower_bound = build_int_cst_type(integer_type_node, 0);
|
tree lower_bound = build_int_cst_type(integer_type_node, 0);
|
||||||
tree upper_bound = build_int_cst_type(integer_type_node, array_type->size);
|
tree upper_bound = build_int_cst_type(integer_type_node, array_type->size);
|
||||||
@ -632,7 +759,7 @@ namespace gcc
|
|||||||
|
|
||||||
return build_array_type(base_type, range_type);
|
return build_array_type(base_type, range_type);
|
||||||
}
|
}
|
||||||
else if (boot::pointer_type_expression *pointer_type = type.is_pointer())
|
else if (boot::pointer_type *pointer_type = type.is_pointer())
|
||||||
{
|
{
|
||||||
tree base_type = build_type(pointer_type->base());
|
tree base_type = build_type(pointer_type->base());
|
||||||
|
|
||||||
@ -642,7 +769,7 @@ namespace gcc
|
|||||||
}
|
}
|
||||||
return build_pointer_type_for_mode(base_type, VOIDmode, true);
|
return build_pointer_type_for_mode(base_type, VOIDmode, true);
|
||||||
}
|
}
|
||||||
else if (boot::record_type_expression *record_type = type.is_record())
|
else if (boot::record_type *record_type = type.is_record())
|
||||||
{
|
{
|
||||||
std::set<std::string> field_names;
|
std::set<std::string> field_names;
|
||||||
tree record_type_node = make_node(RECORD_TYPE);
|
tree record_type_node = make_node(RECORD_TYPE);
|
||||||
@ -669,7 +796,7 @@ namespace gcc
|
|||||||
|
|
||||||
return record_type_node;
|
return record_type_node;
|
||||||
}
|
}
|
||||||
else if (boot::union_type_expression *union_type = type.is_union())
|
else if (boot::union_type *union_type = type.is_union())
|
||||||
{
|
{
|
||||||
std::set<std::string> field_names;
|
std::set<std::string> field_names;
|
||||||
tree union_type_node = make_node(UNION_TYPE);
|
tree union_type_node = make_node(UNION_TYPE);
|
||||||
@ -701,7 +828,7 @@ namespace gcc
|
|||||||
|
|
||||||
void generic_visitor::visit(boot::variable_declaration *declaration)
|
void generic_visitor::visit(boot::variable_declaration *declaration)
|
||||||
{
|
{
|
||||||
tree declaration_type = build_type(declaration->type());
|
tree declaration_type = build_type(declaration->variable_type());
|
||||||
gcc_assert(declaration_type != NULL_TREE);
|
gcc_assert(declaration_type != NULL_TREE);
|
||||||
|
|
||||||
location_t declaration_location = get_location(&declaration->position());
|
location_t declaration_location = get_location(&declaration->position());
|
||||||
@ -709,6 +836,10 @@ namespace gcc
|
|||||||
get_identifier(declaration->identifier.c_str()), declaration_type);
|
get_identifier(declaration->identifier.c_str()), declaration_type);
|
||||||
bool result = this->symbol_map->enter(declaration->identifier, declaration_tree);
|
bool result = this->symbol_map->enter(declaration->identifier, declaration_tree);
|
||||||
|
|
||||||
|
if (is_pointer_type(declaration_type))
|
||||||
|
{
|
||||||
|
DECL_INITIAL(declaration_tree) = elna_pointer_nil_node;
|
||||||
|
}
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
error_at(declaration_location, "variable '%s' already declared in this scope",
|
error_at(declaration_location, "variable '%s' already declared in this scope",
|
||||||
@ -795,6 +926,30 @@ namespace gcc
|
|||||||
void generic_visitor::visit(boot::field_access_expression *expression)
|
void generic_visitor::visit(boot::field_access_expression *expression)
|
||||||
{
|
{
|
||||||
expression->base().accept(this);
|
expression->base().accept(this);
|
||||||
|
location_t expression_location = get_location(&expression->position());
|
||||||
|
|
||||||
|
if (TYPE_P(this->current_expression))
|
||||||
|
{
|
||||||
|
if (expression->field() == "size")
|
||||||
|
{
|
||||||
|
this->current_expression = build1(CONVERT_EXPR, elna_word_type_node,
|
||||||
|
size_in_bytes(this->current_expression));
|
||||||
|
}
|
||||||
|
else if (expression->field() == "alignment")
|
||||||
|
{
|
||||||
|
this->current_expression = build_int_cstu(elna_word_type_node,
|
||||||
|
TYPE_ALIGN_UNIT(this->current_expression));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error_at(expression_location, "type '%s' does not have property '%s'",
|
||||||
|
print_type(this->current_expression).c_str(), expression->field().c_str());
|
||||||
|
this->current_expression = error_mark_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (is_aggregate_type(TREE_TYPE(this->current_expression)))
|
||||||
|
{
|
||||||
tree field_declaration = TYPE_FIELDS(TREE_TYPE(this->current_expression));
|
tree field_declaration = TYPE_FIELDS(TREE_TYPE(this->current_expression));
|
||||||
|
|
||||||
while (field_declaration != NULL_TREE)
|
while (field_declaration != NULL_TREE)
|
||||||
@ -808,7 +963,6 @@ namespace gcc
|
|||||||
}
|
}
|
||||||
field_declaration = TREE_CHAIN(field_declaration);
|
field_declaration = TREE_CHAIN(field_declaration);
|
||||||
}
|
}
|
||||||
location_t expression_location = get_location(&expression->position());
|
|
||||||
if (field_declaration == NULL_TREE)
|
if (field_declaration == NULL_TREE)
|
||||||
{
|
{
|
||||||
error_at(expression_location,
|
error_at(expression_location,
|
||||||
@ -823,6 +977,7 @@ namespace gcc
|
|||||||
field_declaration, NULL_TREE);
|
field_declaration, NULL_TREE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::dereference_expression *expression)
|
void generic_visitor::visit(boot::dereference_expression *expression)
|
||||||
{
|
{
|
||||||
@ -848,8 +1003,7 @@ namespace gcc
|
|||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (TREE_TYPE(this->current_expression) == TREE_TYPE(lvalue)
|
if (is_assignable_from(TREE_TYPE(lvalue), this->current_expression))
|
||||||
|| are_compatible_pointers(lvalue, this->current_expression))
|
|
||||||
{
|
{
|
||||||
tree assignment = build2_loc(statement_location, MODIFY_EXPR,
|
tree assignment = build2_loc(statement_location, MODIFY_EXPR,
|
||||||
void_type_node, lvalue, this->current_expression);
|
void_type_node, lvalue, this->current_expression);
|
||||||
|
@ -62,20 +62,27 @@ namespace gcc
|
|||||||
return type == NULL_TREE || type == void_type_node;
|
return type == NULL_TREE || type == void_type_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_record_type(tree type)
|
bool is_aggregate_type(tree type)
|
||||||
{
|
{
|
||||||
return TREE_CODE(type) == RECORD_TYPE;
|
gcc_assert(TYPE_P(type));
|
||||||
|
return TREE_CODE(type) == RECORD_TYPE || TREE_CODE(type) == UNION_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool are_compatible_pointers(tree lhs, tree rhs)
|
bool are_compatible_pointers(tree lhs_type, tree rhs)
|
||||||
{
|
{
|
||||||
tree lhs_type = TREE_TYPE(lhs);
|
gcc_assert(TYPE_P(lhs_type));
|
||||||
tree rhs_type = TREE_TYPE(rhs);
|
tree rhs_type = TREE_TYPE(rhs);
|
||||||
|
|
||||||
return (is_pointer_type(lhs_type) && rhs == elna_pointer_nil_node)
|
return (is_pointer_type(lhs_type) && rhs == elna_pointer_nil_node)
|
||||||
|| (is_pointer_type(lhs_type) && lhs_type == rhs_type);
|
|| (is_pointer_type(lhs_type) && lhs_type == rhs_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_assignable_from(tree assignee, tree assignment)
|
||||||
|
{
|
||||||
|
return TREE_TYPE(assignment) == assignee
|
||||||
|
|| are_compatible_pointers(assignee, assignment);
|
||||||
|
}
|
||||||
|
|
||||||
void append_statement(tree statement_tree)
|
void append_statement(tree statement_tree)
|
||||||
{
|
{
|
||||||
if (!vec_safe_is_empty(f_binding_level->defers))
|
if (!vec_safe_is_empty(f_binding_level->defers))
|
||||||
|
@ -41,7 +41,8 @@ namespace boot
|
|||||||
less_equal,
|
less_equal,
|
||||||
greater_equal,
|
greater_equal,
|
||||||
disjunction,
|
disjunction,
|
||||||
conjunction
|
conjunction,
|
||||||
|
exclusive_disjunction
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class unary_operator
|
enum class unary_operator
|
||||||
@ -57,7 +58,7 @@ namespace boot
|
|||||||
class type_definition;
|
class type_definition;
|
||||||
class call_expression;
|
class call_expression;
|
||||||
class cast_expression;
|
class cast_expression;
|
||||||
class size_of_expression;
|
class type_expression;
|
||||||
class assign_statement;
|
class assign_statement;
|
||||||
class if_statement;
|
class if_statement;
|
||||||
class while_statement;
|
class while_statement;
|
||||||
@ -67,11 +68,11 @@ namespace boot
|
|||||||
class program;
|
class program;
|
||||||
class binary_expression;
|
class binary_expression;
|
||||||
class unary_expression;
|
class unary_expression;
|
||||||
class basic_type_expression;
|
class basic_type;
|
||||||
class array_type_expression;
|
class array_type;
|
||||||
class pointer_type_expression;
|
class pointer_type;
|
||||||
class record_type_expression;
|
class record_type;
|
||||||
class union_type_expression;
|
class union_type;
|
||||||
class variable_expression;
|
class variable_expression;
|
||||||
class array_access_expression;
|
class array_access_expression;
|
||||||
class field_access_expression;
|
class field_access_expression;
|
||||||
@ -91,7 +92,7 @@ namespace boot
|
|||||||
virtual void visit(type_definition *) = 0;
|
virtual void visit(type_definition *) = 0;
|
||||||
virtual void visit(call_expression *) = 0;
|
virtual void visit(call_expression *) = 0;
|
||||||
virtual void visit(cast_expression *) = 0;
|
virtual void visit(cast_expression *) = 0;
|
||||||
virtual void visit(size_of_expression *) = 0;
|
virtual void visit(type_expression *) = 0;
|
||||||
virtual void visit(call_statement *) = 0;
|
virtual void visit(call_statement *) = 0;
|
||||||
virtual void visit(assign_statement *) = 0;
|
virtual void visit(assign_statement *) = 0;
|
||||||
virtual void visit(if_statement *) = 0;
|
virtual void visit(if_statement *) = 0;
|
||||||
@ -102,11 +103,11 @@ namespace boot
|
|||||||
virtual void visit(program *) = 0;
|
virtual void visit(program *) = 0;
|
||||||
virtual void visit(binary_expression *) = 0;
|
virtual void visit(binary_expression *) = 0;
|
||||||
virtual void visit(unary_expression *) = 0;
|
virtual void visit(unary_expression *) = 0;
|
||||||
virtual void visit(basic_type_expression *) = 0;
|
virtual void visit(basic_type *) = 0;
|
||||||
virtual void visit(array_type_expression *) = 0;
|
virtual void visit(array_type *) = 0;
|
||||||
virtual void visit(pointer_type_expression *) = 0;
|
virtual void visit(pointer_type *) = 0;
|
||||||
virtual void visit(record_type_expression *) = 0;
|
virtual void visit(record_type *) = 0;
|
||||||
virtual void visit(union_type_expression *) = 0;
|
virtual void visit(union_type *) = 0;
|
||||||
virtual void visit(variable_expression *) = 0;
|
virtual void visit(variable_expression *) = 0;
|
||||||
virtual void visit(array_access_expression *) = 0;
|
virtual void visit(array_access_expression *) = 0;
|
||||||
virtual void visit(field_access_expression *is_field_access) = 0;
|
virtual void visit(field_access_expression *is_field_access) = 0;
|
||||||
@ -131,7 +132,7 @@ namespace boot
|
|||||||
virtual void visit(type_definition *definition) override;
|
virtual void visit(type_definition *definition) override;
|
||||||
virtual void visit(call_expression *expression) override;
|
virtual void visit(call_expression *expression) override;
|
||||||
virtual void visit(cast_expression *expression) override;
|
virtual void visit(cast_expression *expression) override;
|
||||||
virtual void visit(size_of_expression *expression) override;
|
virtual void visit(type_expression *expression) override;
|
||||||
virtual void visit(call_statement *statement) override;
|
virtual void visit(call_statement *statement) override;
|
||||||
virtual void visit(assign_statement *statement) override;
|
virtual void visit(assign_statement *statement) override;
|
||||||
virtual void visit(if_statement *) override;
|
virtual void visit(if_statement *) override;
|
||||||
@ -142,11 +143,11 @@ namespace boot
|
|||||||
virtual void visit(program *program) override;
|
virtual void visit(program *program) override;
|
||||||
virtual void visit(binary_expression *expression) override;
|
virtual void visit(binary_expression *expression) override;
|
||||||
virtual void visit(unary_expression *expression) override;
|
virtual void visit(unary_expression *expression) override;
|
||||||
virtual void visit(basic_type_expression *) override;
|
virtual void visit(basic_type *) override;
|
||||||
virtual void visit(array_type_expression *expression) override;
|
virtual void visit(array_type *expression) override;
|
||||||
virtual void visit(pointer_type_expression *) override;
|
virtual void visit(pointer_type *) override;
|
||||||
virtual void visit(record_type_expression *expression) override;
|
virtual void visit(record_type *expression) override;
|
||||||
virtual void visit(union_type_expression *expression) override;
|
virtual void visit(union_type *expression) override;
|
||||||
virtual void visit(variable_expression *) override;
|
virtual void visit(variable_expression *) override;
|
||||||
virtual void visit(array_access_expression *expression) override;
|
virtual void visit(array_access_expression *expression) override;
|
||||||
virtual void visit(field_access_expression *expression) override;
|
virtual void visit(field_access_expression *expression) override;
|
||||||
@ -217,23 +218,23 @@ namespace boot
|
|||||||
/**
|
/**
|
||||||
* Some type expression.
|
* Some type expression.
|
||||||
*/
|
*/
|
||||||
class type_expression : public node
|
class top_type : public node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual basic_type_expression *is_basic();
|
virtual basic_type *is_basic();
|
||||||
virtual array_type_expression *is_array();
|
virtual array_type *is_array();
|
||||||
virtual pointer_type_expression *is_pointer();
|
virtual pointer_type *is_pointer();
|
||||||
virtual record_type_expression *is_record();
|
virtual record_type *is_record();
|
||||||
virtual union_type_expression *is_union();
|
virtual union_type *is_union();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
type_expression(const struct position position);
|
top_type(const struct position position);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expression defining a basic type.
|
* Expression defining a basic type.
|
||||||
*/
|
*/
|
||||||
class basic_type_expression final : public type_expression
|
class basic_type : public top_type
|
||||||
{
|
{
|
||||||
const std::string m_name;
|
const std::string m_name;
|
||||||
|
|
||||||
@ -242,76 +243,76 @@ namespace boot
|
|||||||
* \param position Source code position.
|
* \param position Source code position.
|
||||||
* \param name Type name.
|
* \param name Type name.
|
||||||
*/
|
*/
|
||||||
basic_type_expression(const struct position position, const std::string& name);
|
basic_type(const struct position position, const std::string& name);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
const std::string& base_name();
|
const std::string& base_name();
|
||||||
|
|
||||||
basic_type_expression *is_basic() override;
|
basic_type *is_basic() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class array_type_expression final : public type_expression
|
class array_type : public top_type
|
||||||
{
|
{
|
||||||
type_expression *m_base;
|
top_type *m_base;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const std::uint32_t size;
|
const std::uint32_t size;
|
||||||
|
|
||||||
array_type_expression(const struct position position, type_expression *base, const std::uint32_t size);
|
array_type(const struct position position, top_type*base, const std::uint32_t size);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
type_expression& base();
|
top_type& base();
|
||||||
|
|
||||||
array_type_expression *is_array() override;
|
array_type *is_array() override;
|
||||||
|
|
||||||
virtual ~array_type_expression() override;
|
virtual ~array_type() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class pointer_type_expression final : public type_expression
|
class pointer_type : public top_type
|
||||||
{
|
{
|
||||||
type_expression *m_base;
|
top_type *m_base;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
pointer_type_expression(const struct position position, type_expression *base);
|
pointer_type(const struct position position, top_type *base);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
type_expression& base();
|
top_type& base();
|
||||||
|
|
||||||
pointer_type_expression *is_pointer() override;
|
pointer_type *is_pointer() override;
|
||||||
|
|
||||||
virtual ~pointer_type_expression() override;
|
virtual ~pointer_type() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
using field_t = std::pair<std::string, type_expression *>;
|
using field_t = std::pair<std::string, top_type *>;
|
||||||
using fields_t = std::vector<field_t>;
|
using fields_t = std::vector<field_t>;
|
||||||
|
|
||||||
class composite_type_expression : public type_expression
|
class composite_type : public top_type
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
composite_type_expression(const struct position position, fields_t&& fields);
|
composite_type(const struct position position, fields_t&& fields);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
fields_t fields;
|
fields_t fields;
|
||||||
|
|
||||||
virtual ~composite_type_expression() override;
|
virtual ~composite_type() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class record_type_expression final : public composite_type_expression
|
class record_type : public composite_type
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
record_type_expression(const struct position position, fields_t&& fields);
|
record_type(const struct position position, fields_t&& fields);
|
||||||
|
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
record_type_expression *is_record() override;
|
record_type *is_record() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class union_type_expression final : public composite_type_expression
|
class union_type : public composite_type
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
union_type_expression(const struct position position, fields_t&& fields);
|
union_type(const struct position position, fields_t&& fields);
|
||||||
|
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
union_type_expression *is_union() override;
|
union_type *is_union() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -319,14 +320,14 @@ namespace boot
|
|||||||
*/
|
*/
|
||||||
class variable_declaration : public definition
|
class variable_declaration : public definition
|
||||||
{
|
{
|
||||||
type_expression *m_type;
|
top_type *m_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
variable_declaration(const struct position position, const std::string& identifier,
|
variable_declaration(const struct position position, const std::string& identifier,
|
||||||
const bool exported, type_expression *type);
|
const bool exported, top_type *type);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
type_expression& type();
|
top_type& variable_type();
|
||||||
|
|
||||||
virtual ~variable_declaration() override;
|
virtual ~variable_declaration() override;
|
||||||
};
|
};
|
||||||
@ -367,17 +368,17 @@ namespace boot
|
|||||||
*/
|
*/
|
||||||
class procedure_definition : public definition
|
class procedure_definition : public definition
|
||||||
{
|
{
|
||||||
type_expression *m_return_type{ nullptr };
|
top_type *m_return_type{ nullptr };
|
||||||
block *m_body{ nullptr };
|
block *m_body{ nullptr };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<variable_declaration *> parameters;
|
std::vector<variable_declaration *> parameters;
|
||||||
|
|
||||||
procedure_definition(const struct position position, const std::string& identifier,
|
procedure_definition(const struct position position, const std::string& identifier,
|
||||||
const bool exported, type_expression *return_type = nullptr);
|
const bool exported, top_type *return_type = nullptr);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
type_expression *return_type();
|
top_type *return_type();
|
||||||
|
|
||||||
block *body();
|
block *body();
|
||||||
procedure_definition *add_body(block *procedure_body);
|
procedure_definition *add_body(block *procedure_body);
|
||||||
@ -390,14 +391,14 @@ namespace boot
|
|||||||
*/
|
*/
|
||||||
class type_definition : public definition
|
class type_definition : public definition
|
||||||
{
|
{
|
||||||
type_expression *m_body;
|
top_type *m_body;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
type_definition(const struct position position, const std::string& identifier,
|
type_definition(const struct position position, const std::string& identifier,
|
||||||
const bool exported, type_expression *expression);
|
const bool exported, top_type *expression);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
type_expression& body();
|
top_type& body();
|
||||||
|
|
||||||
virtual ~type_definition() override;
|
virtual ~type_definition() override;
|
||||||
};
|
};
|
||||||
@ -429,33 +430,33 @@ namespace boot
|
|||||||
*/
|
*/
|
||||||
class cast_expression : public expression
|
class cast_expression : public expression
|
||||||
{
|
{
|
||||||
type_expression *m_target;
|
top_type *m_target;
|
||||||
expression *m_value;
|
expression *m_value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cast_expression(const struct position position, type_expression *target, expression *value);
|
cast_expression(const struct position position, top_type *target, expression *value);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
type_expression& target();
|
top_type& target();
|
||||||
expression& value();
|
expression& value();
|
||||||
|
|
||||||
virtual ~cast_expression() override;
|
virtual ~cast_expression() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sizeOf operator.
|
* Type inside an expression.
|
||||||
*/
|
*/
|
||||||
class size_of_expression : public expression
|
class type_expression : public expression
|
||||||
{
|
{
|
||||||
type_expression *m_body;
|
top_type *m_body;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
size_of_expression(const struct position position, type_expression *body);
|
type_expression(const struct position position, top_type *body);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
type_expression& body();
|
top_type& body();
|
||||||
|
|
||||||
virtual ~size_of_expression() override;
|
virtual ~type_expression() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class call_statement : public statement
|
class call_statement : public statement
|
||||||
@ -662,11 +663,11 @@ namespace boot
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
class number_literal : public literal
|
class number_literal : public literal
|
||||||
{
|
{
|
||||||
T m_value;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
T value;
|
||||||
|
|
||||||
number_literal(const struct position position, const T& value)
|
number_literal(const struct position position, const T& value)
|
||||||
: literal(position), m_value(value)
|
: literal(position), value(value)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -674,11 +675,6 @@ namespace boot
|
|||||||
{
|
{
|
||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& number() const
|
|
||||||
{
|
|
||||||
return m_value;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class defer_statement : public statement
|
class defer_statement : public statement
|
||||||
|
@ -40,7 +40,7 @@ namespace gcc
|
|||||||
std::shared_ptr<boot::symbol_table<tree>> symbol_map;
|
std::shared_ptr<boot::symbol_table<tree>> symbol_map;
|
||||||
|
|
||||||
tree build_label_decl(const char *name, location_t loc);
|
tree build_label_decl(const char *name, location_t loc);
|
||||||
tree build_type(boot::type_expression& type);
|
tree build_type(boot::top_type& type);
|
||||||
|
|
||||||
void enter_scope();
|
void enter_scope();
|
||||||
tree leave_scope();
|
tree leave_scope();
|
||||||
@ -53,9 +53,12 @@ namespace gcc
|
|||||||
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(boot::binary_expression *expression,
|
||||||
tree_code operator_code, tree left, tree right);
|
tree_code operator_code, tree left, tree right);
|
||||||
tree build_logic_operation(boot::binary_expression *expression,
|
tree build_bit_logic_operation(boot::binary_expression *expression, tree left, tree right);
|
||||||
tree_code operator_code, tree left, tree right);
|
|
||||||
tree build_equality_operation(boot::binary_expression *expression, tree left, tree right);
|
tree build_equality_operation(boot::binary_expression *expression, tree left, tree right);
|
||||||
|
void build_procedure_call(location_t call_location,
|
||||||
|
tree symbol, const std::vector<boot::expression *>& arguments);
|
||||||
|
void build_record_call(location_t call_location,
|
||||||
|
tree symbol, const std::vector<boot::expression *>& arguments);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
generic_visitor(std::shared_ptr<boot::symbol_table<tree>> symbol_table);
|
generic_visitor(std::shared_ptr<boot::symbol_table<tree>> symbol_table);
|
||||||
@ -64,7 +67,7 @@ namespace gcc
|
|||||||
void visit(boot::procedure_definition *definition) override;
|
void visit(boot::procedure_definition *definition) override;
|
||||||
void visit(boot::call_expression *expression) override;
|
void visit(boot::call_expression *expression) override;
|
||||||
void visit(boot::cast_expression *expression) override;
|
void visit(boot::cast_expression *expression) override;
|
||||||
void visit(boot::size_of_expression *expression) override;
|
void visit(boot::type_expression *expression) override;
|
||||||
void visit(boot::number_literal<std::int32_t> *literal) override;
|
void visit(boot::number_literal<std::int32_t> *literal) override;
|
||||||
void visit(boot::number_literal<std::uint32_t> *literal) override;
|
void visit(boot::number_literal<std::uint32_t> *literal) override;
|
||||||
void visit(boot::number_literal<double> *literal) override;
|
void visit(boot::number_literal<double> *literal) override;
|
||||||
|
@ -39,14 +39,26 @@ namespace gcc
|
|||||||
bool is_array_type(tree type);
|
bool is_array_type(tree type);
|
||||||
bool is_procedure_type(tree type);
|
bool is_procedure_type(tree type);
|
||||||
bool is_void_type(tree type);
|
bool is_void_type(tree type);
|
||||||
bool is_record_type(tree type);
|
|
||||||
|
/**
|
||||||
|
* \param type The type to evaluate.
|
||||||
|
* \return Whether the given type is record or union.
|
||||||
|
*/
|
||||||
|
bool is_aggregate_type(tree type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \param lhs Left hand value.
|
* \param lhs Left hand value.
|
||||||
* \param rhs Right hand value.
|
* \param rhs Right hand value.
|
||||||
* \return Whether rhs can be assigned to lhs.
|
* \return Whether rhs can be assigned to lhs.
|
||||||
*/
|
*/
|
||||||
bool are_compatible_pointers(tree lhs, tree rhs);
|
bool are_compatible_pointers(tree lhs_type, tree rhs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \param assignee Assignee.
|
||||||
|
* \param assignee Assignment.
|
||||||
|
* \return Whether an expression assignment can be assigned to a variable of type assignee.
|
||||||
|
*/
|
||||||
|
bool is_assignable_from(tree assignee, tree assignment);
|
||||||
|
|
||||||
void append_statement(tree statement_tree);
|
void append_statement(tree statement_tree);
|
||||||
void defer(tree statement_tree);
|
void defer(tree statement_tree);
|
||||||
|
91
source.elna
91
source.elna
@ -63,46 +63,46 @@ const
|
|||||||
|
|
||||||
type
|
type
|
||||||
Position* = record
|
Position* = record
|
||||||
line: Word;
|
line: Word
|
||||||
column: Word
|
column: Word
|
||||||
end
|
end
|
||||||
Location* = record
|
Location* = record
|
||||||
first: Position;
|
first: Position
|
||||||
last: Position
|
last: Position
|
||||||
end
|
end
|
||||||
SourceCode = record
|
SourceCode = record
|
||||||
position: Position;
|
position: Position
|
||||||
text: String
|
text: String
|
||||||
end
|
end
|
||||||
TokenValue* = union
|
TokenValue* = union
|
||||||
int_value: Int;
|
int_value: Int
|
||||||
string_value: pointer to Char;
|
string_value: pointer to Char
|
||||||
string: String;
|
string: String
|
||||||
boolean_value: Bool;
|
boolean_value: Bool
|
||||||
char_value: Char
|
char_value: Char
|
||||||
end
|
end
|
||||||
Token* = record
|
Token* = record
|
||||||
kind: Int;
|
kind: Int
|
||||||
value: TokenValue;
|
value: TokenValue
|
||||||
location: Location
|
location: Location
|
||||||
end
|
end
|
||||||
FILE* = record
|
FILE* = record
|
||||||
dummy: Int
|
dummy: Int
|
||||||
end
|
end
|
||||||
CommandLine* = record
|
CommandLine* = record
|
||||||
input: pointer to Char;
|
input: pointer to Char
|
||||||
tokenize: Bool;
|
tokenize: Bool
|
||||||
syntax_tree: Bool
|
syntax_tree: Bool
|
||||||
end
|
end
|
||||||
Literal* = record
|
Literal* = record
|
||||||
value: Int
|
value: Int
|
||||||
end
|
end
|
||||||
ConstantDefinition* = record
|
ConstantDefinition* = record
|
||||||
name: pointer to Char;
|
name: pointer to Char
|
||||||
body: pointer to Literal
|
body: pointer to Literal
|
||||||
end
|
end
|
||||||
ConstantPart* = record
|
ConstantPart* = record
|
||||||
elements: pointer to pointer to ConstantDefinition;
|
elements: pointer to pointer to ConstantDefinition
|
||||||
count: Word
|
count: Word
|
||||||
end
|
end
|
||||||
Program* = record
|
Program* = record
|
||||||
@ -148,12 +148,12 @@ end
|
|||||||
|
|
||||||
proc write_s(value: String);
|
proc write_s(value: String);
|
||||||
begin
|
begin
|
||||||
write(0, value.ptr, value.length)
|
write(0, cast(value.ptr: pointer to Byte), cast(value.length: Int))
|
||||||
end
|
end
|
||||||
|
|
||||||
proc write_z(value: pointer to Char);
|
proc write_z(value: pointer to Char);
|
||||||
begin
|
begin
|
||||||
write(0, value, strlen(value))
|
write(0, cast(value: pointer to Byte), cast(strlen(value): Int))
|
||||||
end
|
end
|
||||||
|
|
||||||
proc write_b(value: Bool);
|
proc write_b(value: Bool);
|
||||||
@ -167,7 +167,7 @@ end
|
|||||||
|
|
||||||
proc write_c(value: Char);
|
proc write_c(value: Char);
|
||||||
begin
|
begin
|
||||||
write(0, @value, 1)
|
write(0, cast(@value: pointer to Byte), 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
proc write_i(value: Int);
|
proc write_i(value: Int);
|
||||||
@ -184,7 +184,7 @@ begin
|
|||||||
digit := value % 10;
|
digit := value % 10;
|
||||||
value := value / 10;
|
value := value / 10;
|
||||||
|
|
||||||
buffer[n] := cast(cast('0' as Int) + digit as Char);
|
buffer[n] := cast(cast('0': Int) + digit: Char);
|
||||||
n := n - 1u
|
n := n - 1u
|
||||||
end;
|
end;
|
||||||
while n < 10u do
|
while n < 10u do
|
||||||
@ -195,17 +195,17 @@ end
|
|||||||
|
|
||||||
proc write_u(value: Word);
|
proc write_u(value: Word);
|
||||||
begin
|
begin
|
||||||
write_i(value)
|
write_i(cast(value: Int))
|
||||||
end
|
end
|
||||||
|
|
||||||
proc is_digit(c: Char) -> Bool;
|
proc is_digit(c: Char) -> Bool;
|
||||||
begin
|
begin
|
||||||
return cast(c as Int) >= cast('0' as Int) and cast(c as Int) <= cast('9' as Int)
|
return cast(c: Int) >= cast('0': Int) and cast(c: Int) <= cast('9': Int)
|
||||||
end
|
end
|
||||||
|
|
||||||
proc is_alpha(c: Char) -> Bool;
|
proc is_alpha(c: Char) -> Bool;
|
||||||
begin
|
begin
|
||||||
return cast(c as Int) >= cast('A' as Int) and cast(c as Int) <= cast('z' as Int)
|
return cast(c: Int) >= cast('A': Int) and cast(c: Int) <= cast('z': Int)
|
||||||
end
|
end
|
||||||
|
|
||||||
proc is_alnum(c: Char) -> Bool;
|
proc is_alnum(c: Char) -> Bool;
|
||||||
@ -232,7 +232,7 @@ proc string_dup(origin: String) -> String;
|
|||||||
var
|
var
|
||||||
copy: pointer to Char;
|
copy: pointer to Char;
|
||||||
begin
|
begin
|
||||||
copy := cast(malloc(origin.length) as pointer to Char);
|
copy := cast(malloc(origin.length): pointer to Char);
|
||||||
strncpy(copy, origin.ptr, origin.length);
|
strncpy(copy, origin.ptr, origin.length);
|
||||||
|
|
||||||
return String(copy, origin.length)
|
return String(copy, origin.length)
|
||||||
@ -246,9 +246,7 @@ proc make_position() -> Position;
|
|||||||
var
|
var
|
||||||
result: Position;
|
result: Position;
|
||||||
begin
|
begin
|
||||||
result.line := 1u;
|
return Position(1u, 1u)
|
||||||
result.column := 1u;
|
|
||||||
return result
|
|
||||||
end
|
end
|
||||||
|
|
||||||
proc read_source(filename: pointer to Char, result: pointer to String) -> Bool;
|
proc read_source(filename: pointer to Char, result: pointer to String) -> Bool;
|
||||||
@ -274,12 +272,12 @@ begin
|
|||||||
end;
|
end;
|
||||||
rewind(input_file);
|
rewind(input_file);
|
||||||
|
|
||||||
input := malloc(source_size);
|
input := malloc(cast(source_size: Word));
|
||||||
if fread(input, source_size, 1, input_file) <> 1u then
|
if fread(input, cast(source_size: Word), 1u, input_file) <> 1u then
|
||||||
return false
|
return false
|
||||||
end;
|
end;
|
||||||
result^.length := cast(source_size as Word);
|
result^.length := cast(source_size: Word);
|
||||||
result^.ptr := cast(input as pointer to Char);
|
result^.ptr := cast(input: pointer to Char);
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@ -373,12 +371,12 @@ begin
|
|||||||
while source_code^.text.length > 1u do
|
while source_code^.text.length > 1u do
|
||||||
if source_code^.text[1u] = '*' and source_code^.text[2u] = ')' then
|
if source_code^.text[1u] = '*' and source_code^.text[2u] = ')' then
|
||||||
source_code^ := advance_source(source_code^, 2u);
|
source_code^ := advance_source(source_code^, 2u);
|
||||||
token_content^ := substring(token_content^, 0, content_length);
|
token_content^ := substring(token_content^, 0u, content_length);
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end;
|
end;
|
||||||
content_length := content_length + 1u;
|
content_length := content_length + 1u;
|
||||||
source_code^ := advance_source(source_code^, 1)
|
source_code^ := advance_source(source_code^, 1u)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
return false
|
return false
|
||||||
@ -413,8 +411,8 @@ begin
|
|||||||
if token_end^ <> '\"' then
|
if token_end^ <> '\"' then
|
||||||
return input
|
return input
|
||||||
end;
|
end;
|
||||||
token_length := cast(token_end - input as Word);
|
token_length := cast(token_end - input: Word);
|
||||||
current_token^.value.string_value := cast(calloc(token_length, 1) as pointer to Char);
|
current_token^.value.string_value := cast(calloc(token_length, 1u): pointer to Char);
|
||||||
|
|
||||||
is_valid := true;
|
is_valid := true;
|
||||||
constructed_string := current_token^.value.string_value;
|
constructed_string := current_token^.value.string_value;
|
||||||
@ -565,7 +563,7 @@ begin
|
|||||||
write_s("u>")
|
write_s("u>")
|
||||||
elsif current_token^.kind = TOKEN_CHARACTER then
|
elsif current_token^.kind = TOKEN_CHARACTER then
|
||||||
write_c('<');
|
write_c('<');
|
||||||
write_i(current_token^.value.char_value);
|
write_i(cast(current_token^.value.char_value: Int));
|
||||||
write_s("c>")
|
write_s("c>")
|
||||||
elsif current_token^.kind = TOKEN_STRING then
|
elsif current_token^.kind = TOKEN_STRING then
|
||||||
write_s("\"...\"")
|
write_s("\"...\"")
|
||||||
@ -671,7 +669,7 @@ begin
|
|||||||
source_code := skip_spaces(source_code);
|
source_code := skip_spaces(source_code);
|
||||||
|
|
||||||
while source_code.text.length <> 0u do
|
while source_code.text.length <> 0u do
|
||||||
tokens := cast(reallocarray(tokens, tokens_size^ + 1u, sizeof(Token)) as pointer to Token);
|
tokens := cast(reallocarray(cast(tokens: pointer to Byte), tokens_size^ + 1u, Token.size): pointer to Token);
|
||||||
current_token := tokens + tokens_size^;
|
current_token := tokens + tokens_size^;
|
||||||
first_char := source_code.text[1u];
|
first_char := source_code.text[1u];
|
||||||
|
|
||||||
@ -681,7 +679,7 @@ begin
|
|||||||
elsif is_digit(first_char) then
|
elsif is_digit(first_char) then
|
||||||
token_end := nil;
|
token_end := nil;
|
||||||
current_token^.value.int_value := strtol(source_code.text.ptr, @token_end, 10);
|
current_token^.value.int_value := strtol(source_code.text.ptr, @token_end, 10);
|
||||||
token_length := cast(token_end - source_code.text.ptr as Word);
|
token_length := cast(token_end - source_code.text.ptr: Word);
|
||||||
|
|
||||||
if token_end^ = 'u' then
|
if token_end^ = 'u' then
|
||||||
current_token^.kind := TOKEN_WORD;
|
current_token^.kind := TOKEN_WORD;
|
||||||
@ -712,7 +710,7 @@ begin
|
|||||||
source_code := advance_source(source_code, 1u)
|
source_code := advance_source(source_code, 1u)
|
||||||
elsif first_char = '\'' then
|
elsif first_char = '\'' then
|
||||||
token_end := lex_character(source_code.text.ptr + 1, current_token);
|
token_end := lex_character(source_code.text.ptr + 1, current_token);
|
||||||
token_length := cast(token_end - source_code.text.ptr as Word);
|
token_length := cast(token_end - source_code.text.ptr: Word);
|
||||||
|
|
||||||
if token_end^ = '\'' then
|
if token_end^ = '\'' then
|
||||||
current_token^.kind := TOKEN_CHARACTER;
|
current_token^.kind := TOKEN_CHARACTER;
|
||||||
@ -725,7 +723,7 @@ begin
|
|||||||
|
|
||||||
if token_end^ = '"' then
|
if token_end^ = '"' then
|
||||||
current_token^.kind := TOKEN_STRING;
|
current_token^.kind := TOKEN_STRING;
|
||||||
token_length := cast(token_end - source_code.text.ptr as Word);
|
token_length := cast(token_end - source_code.text.ptr: Word);
|
||||||
source_code := advance_source(source_code, token_length + 1u)
|
source_code := advance_source(source_code, token_length + 1u)
|
||||||
end
|
end
|
||||||
elsif first_char = '[' then
|
elsif first_char = '[' then
|
||||||
@ -823,7 +821,7 @@ end
|
|||||||
|
|
||||||
proc parse_literal(tokens: pointer to pointer to Token, tokens_size: pointer to Word) -> pointer to Literal;
|
proc parse_literal(tokens: pointer to pointer to Token, tokens_size: pointer to Word) -> pointer to Literal;
|
||||||
begin
|
begin
|
||||||
return cast(calloc(1, sizeof(Literal)) as pointer to Literal)
|
return cast(calloc(1u, Literal.size): pointer to Literal)
|
||||||
end
|
end
|
||||||
|
|
||||||
proc parse_constant_definition(tokens: pointer to pointer to Token,
|
proc parse_constant_definition(tokens: pointer to pointer to Token,
|
||||||
@ -831,9 +829,9 @@ proc parse_constant_definition(tokens: pointer to pointer to Token,
|
|||||||
var
|
var
|
||||||
result: pointer to ConstantDefinition;
|
result: pointer to ConstantDefinition;
|
||||||
begin
|
begin
|
||||||
result := cast(calloc(1, sizeof(ConstantDefinition)) as pointer to ConstantDefinition);
|
result := cast(calloc(1u, ConstantDefinition.size): pointer to ConstantDefinition);
|
||||||
|
|
||||||
result^.name := cast(malloc(strlen(tokens^^.value.string_value)) as pointer to Char);
|
result^.name := cast(malloc(strlen(tokens^^.value.string_value)): pointer to Char);
|
||||||
strcpy(result^.name, tokens^^.value.string_value);
|
strcpy(result^.name, tokens^^.value.string_value);
|
||||||
|
|
||||||
tokens^ := tokens^ + 2u;
|
tokens^ := tokens^ + 2u;
|
||||||
@ -855,7 +853,7 @@ var
|
|||||||
result: pointer to Program,
|
result: pointer to Program,
|
||||||
current_constant: pointer to pointer to ConstantDefinition;
|
current_constant: pointer to pointer to ConstantDefinition;
|
||||||
begin
|
begin
|
||||||
result := cast(calloc(1, sizeof(Program)) as pointer to Program);
|
result := cast(calloc(1u, Program.size): pointer to Program);
|
||||||
|
|
||||||
result^.constants.elements := nil;
|
result^.constants.elements := nil;
|
||||||
result^.constants.count := 0u;
|
result^.constants.count := 0u;
|
||||||
@ -866,8 +864,11 @@ begin
|
|||||||
|
|
||||||
while tokens_size^ > 0u and tokens^^.kind = TOKEN_IDENTIFIER do
|
while tokens_size^ > 0u and tokens^^.kind = TOKEN_IDENTIFIER do
|
||||||
result^.constants.elements := cast(
|
result^.constants.elements := cast(
|
||||||
reallocarray(result^.constants.elements, result^.constants.count + 1u, sizeof(pointer to ConstantDefinition))
|
reallocarray(
|
||||||
as pointer to pointer to ConstantDefinition);
|
cast(result^.constants.elements: pointer to Byte),
|
||||||
|
result^.constants.count + 1u,
|
||||||
|
(pointer to ConstantDefinition).size
|
||||||
|
) : pointer to pointer to ConstantDefinition);
|
||||||
current_constant := result^.constants.elements + result^.constants.count;
|
current_constant := result^.constants.elements + result^.constants.count;
|
||||||
|
|
||||||
result^.constants.count := result^.constants.count + 1u;
|
result^.constants.count := result^.constants.count + 1u;
|
||||||
@ -887,7 +888,7 @@ var
|
|||||||
result: pointer to CommandLine;
|
result: pointer to CommandLine;
|
||||||
begin
|
begin
|
||||||
i := 1;
|
i := 1;
|
||||||
result := cast(malloc(sizeof(CommandLine)) as pointer to CommandLine);
|
result := cast(malloc(CommandLine.size): pointer to CommandLine);
|
||||||
result^.tokenize := false;
|
result^.tokenize := false;
|
||||||
result^.syntax_tree := false;
|
result^.syntax_tree := false;
|
||||||
result^.input := nil;
|
result^.input := nil;
|
||||||
@ -950,5 +951,5 @@ begin
|
|||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
exit(process(count, parameters))
|
exit(process(cast(count: Int), cast(parameters: pointer to pointer to Char)))
|
||||||
end.
|
end.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user