Compare commits
2 Commits
ec0b4be1f7
...
82b3806fd2
Author | SHA1 | Date | |
---|---|---|---|
82b3806fd2
|
|||
ee4ebf64b9
|
112
boot/ast.cc
112
boot/ast.cc
@ -61,7 +61,7 @@ namespace boot
|
||||
expression->value().accept(this);
|
||||
}
|
||||
|
||||
void empty_visitor::visit(size_of_expression *expression)
|
||||
void empty_visitor::visit(type_expression *expression)
|
||||
{
|
||||
expression->body().accept(this);
|
||||
}
|
||||
@ -152,21 +152,21 @@ namespace boot
|
||||
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);
|
||||
}
|
||||
|
||||
void empty_visitor::visit(pointer_type_expression *expression)
|
||||
void empty_visitor::visit(pointer_type *expression)
|
||||
{
|
||||
expression->base().accept(this);
|
||||
}
|
||||
|
||||
void empty_visitor::visit(record_type_expression *expression)
|
||||
void empty_visitor::visit(record_type *expression)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -250,115 +250,113 @@ namespace boot
|
||||
{
|
||||
}
|
||||
|
||||
type_expression::type_expression(const struct position position)
|
||||
top_type::top_type(const struct position position)
|
||||
: node(position)
|
||||
{
|
||||
}
|
||||
|
||||
basic_type_expression *type_expression::is_basic()
|
||||
basic_type *top_type::is_basic()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
array_type_expression *type_expression::is_array()
|
||||
array_type *top_type::is_array()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
record_type_expression *type_expression::is_record()
|
||||
record_type *top_type::is_record()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
union_type_expression *type_expression::is_union()
|
||||
union_type *top_type::is_union()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
pointer_type_expression *type_expression::is_pointer()
|
||||
pointer_type *top_type::is_pointer()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
basic_type_expression::basic_type_expression(
|
||||
const struct position position, const std::string& name)
|
||||
: type_expression(position), m_name(name)
|
||||
basic_type::basic_type(const struct position position, const std::string& name)
|
||||
: top_type(position), m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
void basic_type_expression::accept(parser_visitor *visitor)
|
||||
void basic_type::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
const std::string& basic_type_expression::base_name()
|
||||
const std::string& basic_type::base_name()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
basic_type_expression *basic_type_expression::is_basic()
|
||||
basic_type *basic_type::is_basic()
|
||||
{
|
||||
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)
|
||||
: 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);
|
||||
}
|
||||
|
||||
type_expression& array_type_expression::base()
|
||||
top_type& array_type::base()
|
||||
{
|
||||
return *m_base;
|
||||
}
|
||||
|
||||
array_type_expression *array_type_expression::is_array()
|
||||
array_type*array_type::is_array()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
array_type_expression::~array_type_expression()
|
||||
array_type::~array_type()
|
||||
{
|
||||
delete m_base;
|
||||
}
|
||||
|
||||
pointer_type_expression::pointer_type_expression(const struct position position, type_expression *base)
|
||||
: type_expression(position), m_base(base)
|
||||
pointer_type::pointer_type(const struct position position, top_type *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);
|
||||
}
|
||||
|
||||
type_expression& pointer_type_expression::base()
|
||||
top_type& pointer_type::base()
|
||||
{
|
||||
return *m_base;
|
||||
}
|
||||
|
||||
pointer_type_expression *pointer_type_expression::is_pointer()
|
||||
pointer_type *pointer_type::is_pointer()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
pointer_type_expression::~pointer_type_expression()
|
||||
pointer_type::~pointer_type()
|
||||
{
|
||||
delete m_base;
|
||||
}
|
||||
|
||||
composite_type_expression::composite_type_expression(const struct position position,
|
||||
fields_t&& fields)
|
||||
: type_expression(position), fields(std::move(fields))
|
||||
composite_type::composite_type(const struct position position, fields_t&& fields)
|
||||
: top_type(position), fields(std::move(fields))
|
||||
{
|
||||
}
|
||||
|
||||
composite_type_expression::~composite_type_expression()
|
||||
composite_type::~composite_type()
|
||||
{
|
||||
for (auto& field_declaration : fields)
|
||||
{
|
||||
@ -366,40 +364,38 @@ namespace boot
|
||||
}
|
||||
}
|
||||
|
||||
record_type_expression::record_type_expression(const struct position position,
|
||||
fields_t&& fields)
|
||||
: composite_type_expression(position, std::move(fields))
|
||||
record_type::record_type(const struct position position, fields_t&& fields)
|
||||
: composite_type(position, std::move(fields))
|
||||
{
|
||||
}
|
||||
|
||||
void record_type_expression::accept(parser_visitor *visitor)
|
||||
void record_type::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
record_type_expression *record_type_expression::is_record()
|
||||
record_type *record_type::is_record()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
union_type_expression::union_type_expression(const struct position position,
|
||||
fields_t&& fields)
|
||||
: composite_type_expression(position, std::move(fields))
|
||||
union_type::union_type(const struct position position, fields_t&& fields)
|
||||
: composite_type(position, std::move(fields))
|
||||
{
|
||||
}
|
||||
|
||||
union_type_expression *union_type_expression::is_union()
|
||||
union_type *union_type::is_union()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void union_type_expression::accept(parser_visitor *visitor)
|
||||
void union_type::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
@ -414,7 +410,7 @@ namespace boot
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
type_expression& variable_declaration::type()
|
||||
top_type& variable_declaration::variable_type()
|
||||
{
|
||||
return *m_type;
|
||||
}
|
||||
@ -446,7 +442,7 @@ namespace boot
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
@ -467,7 +463,7 @@ namespace boot
|
||||
return this;
|
||||
}
|
||||
|
||||
type_expression *procedure_definition::return_type()
|
||||
top_type *procedure_definition::return_type()
|
||||
{
|
||||
return m_return_type;
|
||||
}
|
||||
@ -485,7 +481,7 @@ namespace boot
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
@ -495,7 +491,7 @@ namespace boot
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
type_expression& type_definition::body()
|
||||
top_type& type_definition::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)
|
||||
{
|
||||
}
|
||||
@ -786,7 +782,7 @@ namespace boot
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
type_expression& cast_expression::target()
|
||||
top_type& cast_expression::target()
|
||||
{
|
||||
return *m_target;
|
||||
}
|
||||
@ -802,22 +798,22 @@ namespace boot
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
void size_of_expression::accept(parser_visitor *visitor)
|
||||
void type_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
type_expression& size_of_expression::body()
|
||||
top_type& type_expression::body()
|
||||
{
|
||||
return *m_body;
|
||||
}
|
||||
|
||||
size_of_expression::~size_of_expression()
|
||||
type_expression::~type_expression()
|
||||
{
|
||||
delete m_body;
|
||||
}
|
||||
@ -1016,6 +1012,10 @@ namespace boot
|
||||
return "or";
|
||||
case binary_operator::exclusive_disjunction:
|
||||
return "xor";
|
||||
case binary_operator::shift_left:
|
||||
return "<<";
|
||||
case binary_operator::shift_right:
|
||||
return ">>";
|
||||
}
|
||||
__builtin_unreachable();
|
||||
};
|
||||
|
@ -137,9 +137,6 @@ return {
|
||||
cast {
|
||||
return yy::parser::make_CAST(this->location);
|
||||
}
|
||||
sizeof {
|
||||
return yy::parser::make_SIZEOF(this->location);
|
||||
}
|
||||
defer {
|
||||
return yy::parser::make_DEFER(this->location);
|
||||
}
|
||||
@ -232,6 +229,12 @@ defer {
|
||||
\] {
|
||||
return yy::parser::make_RIGHT_SQUARE(this->location);
|
||||
}
|
||||
\<\< {
|
||||
return yy::parser::make_SHIFT_LEFT(this->location);
|
||||
}
|
||||
\>\> {
|
||||
return yy::parser::make_SHIFT_RIGHT(this->location);
|
||||
}
|
||||
\>= {
|
||||
return yy::parser::make_GREATER_EQUAL(this->location);
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO UNION
|
||||
%token BEGIN_BLOCK END_BLOCK EXTERN DEFER
|
||||
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
|
||||
%token AND OR NOT CAST SIZEOF
|
||||
%token AND OR NOT CAST SHIFT_LEFT SHIFT_RIGHT
|
||||
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
|
||||
%token PLUS MINUS MULTIPLICATION DIVISION REMAINDER
|
||||
%token ASSIGNMENT COLON HAT AT NIL ARROW
|
||||
@ -101,7 +101,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
%type <elna::boot::variable_declaration *> variable_declaration;
|
||||
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part
|
||||
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 <std::vector<elna::boot::expression *>> expressions actual_parameter_list;
|
||||
%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 <std::vector<elna::boot::type_definition *>> type_definitions type_part;
|
||||
%type <elna::boot::block *> block;
|
||||
%type <std::pair<std::string, elna::boot::type_expression *>> field_declaration;
|
||||
%type <std::vector<std::pair<std::string, elna::boot::type_expression *>>> field_list;
|
||||
%type <std::pair<std::string, elna::boot::top_type *>> field_declaration;
|
||||
%type <std::vector<std::pair<std::string, elna::boot::top_type *>>> field_list;
|
||||
%type <std::vector<elna::boot::conditional_statements *>> elsif_statement_list;
|
||||
%type <elna::boot::cast_expression *> cast_expression;
|
||||
%type <elna::boot::defer_statement *> defer_statement;
|
||||
@ -265,9 +265,9 @@ literal:
|
||||
operand:
|
||||
literal { $$ = $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; }
|
||||
| call_expression { $$ = $1; }
|
||||
@ -344,6 +344,16 @@ expression:
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::exclusive_disjunction);
|
||||
}
|
||||
| expression SHIFT_LEFT expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::shift_left);
|
||||
}
|
||||
| expression SHIFT_RIGHT expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::shift_right);
|
||||
}
|
||||
unary:
|
||||
AT operand
|
||||
{
|
||||
@ -417,23 +427,23 @@ field_list:
|
||||
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
|
||||
{
|
||||
$$ = 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
|
||||
{
|
||||
$$ = 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
|
||||
{
|
||||
$$ = 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
|
||||
{
|
||||
$$ = 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
|
||||
{
|
||||
@ -448,7 +458,7 @@ variable_declarations:
|
||||
| variable_declaration { $$.emplace_back(std::move($1)); }
|
||||
variable_part:
|
||||
/* no variable declarations */ {}
|
||||
| VAR variable_declarations SEMICOLON { std::swap($$, $2); }
|
||||
| VAR variable_declarations { std::swap($$, $2); }
|
||||
constant_definition: identifier_definition EQUALS literal
|
||||
{
|
||||
$$ = new elna::boot::constant_definition(elna::boot::make_position(@1), $1.first, $1.second, $3);
|
||||
|
@ -146,7 +146,7 @@ namespace gcc
|
||||
{
|
||||
build_procedure_call(call_location, symbol, expression->arguments());
|
||||
}
|
||||
else if (TYPE_P(symbol) && is_record_type(symbol))
|
||||
else if (TYPE_P(symbol) && TREE_CODE(symbol) == RECORD_TYPE)
|
||||
{
|
||||
build_record_call(call_location, symbol, expression->arguments());
|
||||
}
|
||||
@ -169,11 +169,9 @@ namespace gcc
|
||||
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 = build1(CONVERT_EXPR, elna_word_type_node, size_in_bytes(body_type));
|
||||
this->current_expression = build_type(expression->body());
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::program *program)
|
||||
@ -247,7 +245,7 @@ namespace gcc
|
||||
|
||||
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
|
||||
? void_type_node
|
||||
@ -577,10 +575,11 @@ namespace gcc
|
||||
}
|
||||
if (left_type != right_type
|
||||
&& !are_compatible_pointers(left_type, right)
|
||||
&& !are_compatible_pointers(right_type, left))
|
||||
&& !are_compatible_pointers(right_type, left)
|
||||
&& !(is_integral_type(left_type) && right_type == elna_word_type_node))
|
||||
{
|
||||
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(),
|
||||
boot::print_binary_operator(expression->operation()));
|
||||
this->current_expression = error_mark_node;
|
||||
@ -630,6 +629,16 @@ namespace gcc
|
||||
case boot::binary_operator::not_equals:
|
||||
this->current_expression = build_equality_operation(expression, left, right);
|
||||
break;
|
||||
case boot::binary_operator::shift_left:
|
||||
this->current_expression = build_binary_operation(
|
||||
is_numeric_type(left_type) && right_type == elna_word_type_node,
|
||||
expression, LSHIFT_EXPR, left, right, left_type);
|
||||
break;
|
||||
case boot::binary_operator::shift_right:
|
||||
this->current_expression = build_binary_operation(
|
||||
is_numeric_type(left_type) && right_type == elna_word_type_node,
|
||||
expression, RSHIFT_EXPR, left, right, left_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -732,9 +741,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());
|
||||
|
||||
@ -747,7 +756,7 @@ namespace gcc
|
||||
|
||||
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 upper_bound = build_int_cst_type(integer_type_node, array_type->size);
|
||||
@ -761,7 +770,7 @@ namespace gcc
|
||||
|
||||
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());
|
||||
|
||||
@ -771,7 +780,7 @@ namespace gcc
|
||||
}
|
||||
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;
|
||||
tree record_type_node = make_node(RECORD_TYPE);
|
||||
@ -798,7 +807,7 @@ namespace gcc
|
||||
|
||||
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;
|
||||
tree union_type_node = make_node(UNION_TYPE);
|
||||
@ -830,7 +839,7 @@ namespace gcc
|
||||
|
||||
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);
|
||||
|
||||
location_t declaration_location = get_location(&declaration->position());
|
||||
@ -928,32 +937,56 @@ namespace gcc
|
||||
void generic_visitor::visit(boot::field_access_expression *expression)
|
||||
{
|
||||
expression->base().accept(this);
|
||||
tree field_declaration = TYPE_FIELDS(TREE_TYPE(this->current_expression));
|
||||
|
||||
while (field_declaration != NULL_TREE)
|
||||
{
|
||||
tree declaration_name = DECL_NAME(field_declaration);
|
||||
const char *identifier_pointer = IDENTIFIER_POINTER(declaration_name);
|
||||
|
||||
if (expression->field() == identifier_pointer)
|
||||
{
|
||||
break;
|
||||
}
|
||||
field_declaration = TREE_CHAIN(field_declaration);
|
||||
}
|
||||
location_t expression_location = get_location(&expression->position());
|
||||
if (field_declaration == NULL_TREE)
|
||||
|
||||
if (TYPE_P(this->current_expression))
|
||||
{
|
||||
error_at(expression_location,
|
||||
"record type does not have a field named '%s'",
|
||||
expression->field().c_str());
|
||||
this->current_expression = error_mark_node;
|
||||
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
|
||||
else if (is_aggregate_type(TREE_TYPE(this->current_expression)))
|
||||
{
|
||||
this->current_expression = build3_loc(expression_location, COMPONENT_REF,
|
||||
TREE_TYPE(field_declaration), this->current_expression,
|
||||
field_declaration, NULL_TREE);
|
||||
tree field_declaration = TYPE_FIELDS(TREE_TYPE(this->current_expression));
|
||||
|
||||
while (field_declaration != NULL_TREE)
|
||||
{
|
||||
tree declaration_name = DECL_NAME(field_declaration);
|
||||
const char *identifier_pointer = IDENTIFIER_POINTER(declaration_name);
|
||||
|
||||
if (expression->field() == identifier_pointer)
|
||||
{
|
||||
break;
|
||||
}
|
||||
field_declaration = TREE_CHAIN(field_declaration);
|
||||
}
|
||||
if (field_declaration == NULL_TREE)
|
||||
{
|
||||
error_at(expression_location,
|
||||
"record type does not have a field named '%s'",
|
||||
expression->field().c_str());
|
||||
this->current_expression = error_mark_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->current_expression = build3_loc(expression_location, COMPONENT_REF,
|
||||
TREE_TYPE(field_declaration), this->current_expression,
|
||||
field_declaration, NULL_TREE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,9 +62,10 @@ namespace gcc
|
||||
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_type, tree rhs)
|
||||
@ -194,7 +195,7 @@ namespace gcc
|
||||
else
|
||||
{
|
||||
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(),
|
||||
elna::boot::print_binary_operator(expression->operation()));
|
||||
return error_mark_node;
|
||||
|
@ -42,7 +42,9 @@ namespace boot
|
||||
greater_equal,
|
||||
disjunction,
|
||||
conjunction,
|
||||
exclusive_disjunction
|
||||
exclusive_disjunction,
|
||||
shift_left,
|
||||
shift_right
|
||||
};
|
||||
|
||||
enum class unary_operator
|
||||
@ -58,7 +60,7 @@ namespace boot
|
||||
class type_definition;
|
||||
class call_expression;
|
||||
class cast_expression;
|
||||
class size_of_expression;
|
||||
class type_expression;
|
||||
class assign_statement;
|
||||
class if_statement;
|
||||
class while_statement;
|
||||
@ -68,11 +70,11 @@ namespace boot
|
||||
class program;
|
||||
class binary_expression;
|
||||
class unary_expression;
|
||||
class basic_type_expression;
|
||||
class array_type_expression;
|
||||
class pointer_type_expression;
|
||||
class record_type_expression;
|
||||
class union_type_expression;
|
||||
class basic_type;
|
||||
class array_type;
|
||||
class pointer_type;
|
||||
class record_type;
|
||||
class union_type;
|
||||
class variable_expression;
|
||||
class array_access_expression;
|
||||
class field_access_expression;
|
||||
@ -92,7 +94,7 @@ namespace boot
|
||||
virtual void visit(type_definition *) = 0;
|
||||
virtual void visit(call_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(assign_statement *) = 0;
|
||||
virtual void visit(if_statement *) = 0;
|
||||
@ -103,11 +105,11 @@ namespace boot
|
||||
virtual void visit(program *) = 0;
|
||||
virtual void visit(binary_expression *) = 0;
|
||||
virtual void visit(unary_expression *) = 0;
|
||||
virtual void visit(basic_type_expression *) = 0;
|
||||
virtual void visit(array_type_expression *) = 0;
|
||||
virtual void visit(pointer_type_expression *) = 0;
|
||||
virtual void visit(record_type_expression *) = 0;
|
||||
virtual void visit(union_type_expression *) = 0;
|
||||
virtual void visit(basic_type *) = 0;
|
||||
virtual void visit(array_type *) = 0;
|
||||
virtual void visit(pointer_type *) = 0;
|
||||
virtual void visit(record_type *) = 0;
|
||||
virtual void visit(union_type *) = 0;
|
||||
virtual void visit(variable_expression *) = 0;
|
||||
virtual void visit(array_access_expression *) = 0;
|
||||
virtual void visit(field_access_expression *is_field_access) = 0;
|
||||
@ -132,7 +134,7 @@ namespace boot
|
||||
virtual void visit(type_definition *definition) override;
|
||||
virtual void visit(call_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(assign_statement *statement) override;
|
||||
virtual void visit(if_statement *) override;
|
||||
@ -143,11 +145,11 @@ namespace boot
|
||||
virtual void visit(program *program) override;
|
||||
virtual void visit(binary_expression *expression) override;
|
||||
virtual void visit(unary_expression *expression) override;
|
||||
virtual void visit(basic_type_expression *) override;
|
||||
virtual void visit(array_type_expression *expression) override;
|
||||
virtual void visit(pointer_type_expression *) override;
|
||||
virtual void visit(record_type_expression *expression) override;
|
||||
virtual void visit(union_type_expression *expression) override;
|
||||
virtual void visit(basic_type *) override;
|
||||
virtual void visit(array_type *expression) override;
|
||||
virtual void visit(pointer_type *) override;
|
||||
virtual void visit(record_type *expression) override;
|
||||
virtual void visit(union_type *expression) override;
|
||||
virtual void visit(variable_expression *) override;
|
||||
virtual void visit(array_access_expression *expression) override;
|
||||
virtual void visit(field_access_expression *expression) override;
|
||||
@ -218,23 +220,23 @@ namespace boot
|
||||
/**
|
||||
* Some type expression.
|
||||
*/
|
||||
class type_expression : public node
|
||||
class top_type : public node
|
||||
{
|
||||
public:
|
||||
virtual basic_type_expression *is_basic();
|
||||
virtual array_type_expression *is_array();
|
||||
virtual pointer_type_expression *is_pointer();
|
||||
virtual record_type_expression *is_record();
|
||||
virtual union_type_expression *is_union();
|
||||
virtual basic_type *is_basic();
|
||||
virtual array_type *is_array();
|
||||
virtual pointer_type *is_pointer();
|
||||
virtual record_type *is_record();
|
||||
virtual union_type *is_union();
|
||||
|
||||
protected:
|
||||
type_expression(const struct position position);
|
||||
top_type(const struct position position);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expression defining a basic type.
|
||||
*/
|
||||
class basic_type_expression final : public type_expression
|
||||
class basic_type : public top_type
|
||||
{
|
||||
const std::string m_name;
|
||||
|
||||
@ -243,76 +245,76 @@ namespace boot
|
||||
* \param position Source code position.
|
||||
* \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;
|
||||
|
||||
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:
|
||||
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;
|
||||
|
||||
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:
|
||||
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;
|
||||
|
||||
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>;
|
||||
|
||||
class composite_type_expression : public type_expression
|
||||
class composite_type : public top_type
|
||||
{
|
||||
protected:
|
||||
composite_type_expression(const struct position position, fields_t&& fields);
|
||||
composite_type(const struct position position, fields_t&& fields);
|
||||
|
||||
public:
|
||||
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:
|
||||
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;
|
||||
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:
|
||||
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;
|
||||
union_type_expression *is_union() override;
|
||||
union_type *is_union() override;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -320,14 +322,14 @@ namespace boot
|
||||
*/
|
||||
class variable_declaration : public definition
|
||||
{
|
||||
type_expression *m_type;
|
||||
top_type *m_type;
|
||||
|
||||
public:
|
||||
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;
|
||||
|
||||
type_expression& type();
|
||||
top_type& variable_type();
|
||||
|
||||
virtual ~variable_declaration() override;
|
||||
};
|
||||
@ -368,17 +370,17 @@ namespace boot
|
||||
*/
|
||||
class procedure_definition : public definition
|
||||
{
|
||||
type_expression *m_return_type{ nullptr };
|
||||
top_type *m_return_type{ nullptr };
|
||||
block *m_body{ nullptr };
|
||||
|
||||
public:
|
||||
std::vector<variable_declaration *> parameters;
|
||||
|
||||
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;
|
||||
|
||||
type_expression *return_type();
|
||||
top_type *return_type();
|
||||
|
||||
block *body();
|
||||
procedure_definition *add_body(block *procedure_body);
|
||||
@ -391,14 +393,14 @@ namespace boot
|
||||
*/
|
||||
class type_definition : public definition
|
||||
{
|
||||
type_expression *m_body;
|
||||
top_type *m_body;
|
||||
|
||||
public:
|
||||
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;
|
||||
|
||||
type_expression& body();
|
||||
top_type& body();
|
||||
|
||||
virtual ~type_definition() override;
|
||||
};
|
||||
@ -430,33 +432,33 @@ namespace boot
|
||||
*/
|
||||
class cast_expression : public expression
|
||||
{
|
||||
type_expression *m_target;
|
||||
top_type *m_target;
|
||||
expression *m_value;
|
||||
|
||||
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;
|
||||
|
||||
type_expression& target();
|
||||
top_type& target();
|
||||
expression& value();
|
||||
|
||||
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:
|
||||
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;
|
||||
|
||||
type_expression& body();
|
||||
top_type& body();
|
||||
|
||||
virtual ~size_of_expression() override;
|
||||
virtual ~type_expression() override;
|
||||
};
|
||||
|
||||
class call_statement : public statement
|
||||
|
@ -40,7 +40,7 @@ namespace gcc
|
||||
std::shared_ptr<boot::symbol_table<tree>> symbol_map;
|
||||
|
||||
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();
|
||||
tree leave_scope();
|
||||
@ -67,7 +67,7 @@ namespace gcc
|
||||
void visit(boot::procedure_definition *definition) override;
|
||||
void visit(boot::call_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::uint32_t> *literal) override;
|
||||
void visit(boot::number_literal<double> *literal) override;
|
||||
|
@ -39,7 +39,12 @@ namespace gcc
|
||||
bool is_array_type(tree type);
|
||||
bool is_procedure_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.
|
||||
|
40
source.elna
40
source.elna
@ -173,7 +173,7 @@ end
|
||||
proc write_i(value: Int);
|
||||
var
|
||||
digit: Int, n: Word,
|
||||
buffer: array 10 of Char;
|
||||
buffer: array 10 of Char
|
||||
begin
|
||||
n := 10u;
|
||||
|
||||
@ -230,7 +230,7 @@ end
|
||||
|
||||
proc string_dup(origin: String) -> String;
|
||||
var
|
||||
copy: pointer to Char;
|
||||
copy: pointer to Char
|
||||
begin
|
||||
copy := cast(malloc(origin.length): pointer to Char);
|
||||
strncpy(copy, origin.ptr, origin.length);
|
||||
@ -244,7 +244,7 @@ end
|
||||
|
||||
proc make_position() -> Position;
|
||||
var
|
||||
result: Position;
|
||||
result: Position
|
||||
begin
|
||||
return Position(1u, 1u)
|
||||
end
|
||||
@ -253,7 +253,7 @@ proc read_source(filename: pointer to Char, result: pointer to String) -> Bool;
|
||||
var
|
||||
input_file: pointer to FILE,
|
||||
source_size: Int,
|
||||
input: pointer to Byte;
|
||||
input: pointer to Byte
|
||||
begin
|
||||
input_file := fopen(filename, "rb\0".ptr);
|
||||
|
||||
@ -349,7 +349,7 @@ end
|
||||
|
||||
proc lex_identifier(source_code: pointer to SourceCode, token_content: pointer to String);
|
||||
var
|
||||
content_length: Word;
|
||||
content_length: Word
|
||||
begin
|
||||
content_length := 0u;
|
||||
token_content^ := source_code^.text;
|
||||
@ -363,7 +363,7 @@ end
|
||||
|
||||
proc lex_comment(source_code: pointer to SourceCode, token_content: pointer to String) -> Bool;
|
||||
var
|
||||
content_length: Word;
|
||||
content_length: Word
|
||||
begin
|
||||
content_length := 0u;
|
||||
token_content^ := source_code^.text;
|
||||
@ -401,7 +401,7 @@ var
|
||||
token_end: pointer to Char,
|
||||
constructed_string: pointer to Char,
|
||||
token_length: Word,
|
||||
is_valid: Bool;
|
||||
is_valid: Bool
|
||||
begin
|
||||
token_end := input;
|
||||
|
||||
@ -439,7 +439,7 @@ end
|
||||
proc print_tokens(tokens: pointer to Token, tokens_size: Word);
|
||||
var
|
||||
current_token: pointer to Token,
|
||||
i: Word;
|
||||
i: Word
|
||||
begin
|
||||
i := 0u;
|
||||
while i < tokens_size do
|
||||
@ -583,7 +583,7 @@ end
|
||||
|
||||
proc categorize_identifier(token_content: String) -> Token;
|
||||
var
|
||||
current_token: Token;
|
||||
current_token: Token
|
||||
begin
|
||||
if "if" = token_content then
|
||||
current_token.kind := TOKEN_IF
|
||||
@ -662,14 +662,14 @@ var
|
||||
current_token: pointer to Token,
|
||||
token_length: Word,
|
||||
first_char: Char,
|
||||
token_content: String;
|
||||
token_content: String
|
||||
begin
|
||||
tokens_size^ := 0u;
|
||||
tokens := nil;
|
||||
source_code := skip_spaces(source_code);
|
||||
|
||||
while source_code.text.length <> 0u do
|
||||
tokens := cast(reallocarray(cast(tokens: pointer to Byte), tokens_size^ + 1u, sizeof(Token)): pointer to Token);
|
||||
tokens := cast(reallocarray(cast(tokens: pointer to Byte), tokens_size^ + 1u, Token.size): pointer to Token);
|
||||
current_token := tokens + tokens_size^;
|
||||
first_char := source_code.text[1u];
|
||||
|
||||
@ -821,15 +821,15 @@ end
|
||||
|
||||
proc parse_literal(tokens: pointer to pointer to Token, tokens_size: pointer to Word) -> pointer to Literal;
|
||||
begin
|
||||
return cast(calloc(1u, sizeof(Literal)): pointer to Literal)
|
||||
return cast(calloc(1u, Literal.size): pointer to Literal)
|
||||
end
|
||||
|
||||
proc parse_constant_definition(tokens: pointer to pointer to Token,
|
||||
tokens_size: pointer to Word) -> pointer to ConstantDefinition;
|
||||
var
|
||||
result: pointer to ConstantDefinition;
|
||||
result: pointer to ConstantDefinition
|
||||
begin
|
||||
result := cast(calloc(1u, sizeof(ConstantDefinition)): pointer to ConstantDefinition);
|
||||
result := cast(calloc(1u, ConstantDefinition.size): pointer to ConstantDefinition);
|
||||
|
||||
result^.name := cast(malloc(strlen(tokens^^.value.string_value)): pointer to Char);
|
||||
strcpy(result^.name, tokens^^.value.string_value);
|
||||
@ -851,9 +851,9 @@ end
|
||||
proc parse_program(tokens: pointer to pointer to Token, tokens_size: pointer to Word) -> pointer to Program;
|
||||
var
|
||||
result: pointer to Program,
|
||||
current_constant: pointer to pointer to ConstantDefinition;
|
||||
current_constant: pointer to pointer to ConstantDefinition
|
||||
begin
|
||||
result := cast(calloc(1u, sizeof(Program)): pointer to Program);
|
||||
result := cast(calloc(1u, Program.size): pointer to Program);
|
||||
|
||||
result^.constants.elements := nil;
|
||||
result^.constants.count := 0u;
|
||||
@ -867,7 +867,7 @@ begin
|
||||
reallocarray(
|
||||
cast(result^.constants.elements: pointer to Byte),
|
||||
result^.constants.count + 1u,
|
||||
sizeof(pointer to ConstantDefinition)
|
||||
(pointer to ConstantDefinition).size
|
||||
) : pointer to pointer to ConstantDefinition);
|
||||
current_constant := result^.constants.elements + result^.constants.count;
|
||||
|
||||
@ -885,10 +885,10 @@ proc parse_command_line*(argc: Int, argv: pointer to pointer to Char) -> pointer
|
||||
var
|
||||
parameter: pointer to pointer to Char,
|
||||
i: Int,
|
||||
result: pointer to CommandLine;
|
||||
result: pointer to CommandLine
|
||||
begin
|
||||
i := 1;
|
||||
result := cast(malloc(sizeof(CommandLine)): pointer to CommandLine);
|
||||
result := cast(malloc(CommandLine.size): pointer to CommandLine);
|
||||
result^.tokenize := false;
|
||||
result^.syntax_tree := false;
|
||||
result^.input := nil;
|
||||
@ -927,7 +927,7 @@ var
|
||||
tokens: pointer to Token,
|
||||
tokens_size: Word,
|
||||
source_code: SourceCode,
|
||||
command_line: pointer to CommandLine;
|
||||
command_line: pointer to CommandLine
|
||||
begin
|
||||
command_line := parse_command_line(argc, argv);
|
||||
if command_line = nil then
|
||||
|
Reference in New Issue
Block a user