Allow multiple variable declarations with a single type
This commit is contained in:
parent
82b3806fd2
commit
b358f8ba27
52
boot/ast.cc
52
boot/ast.cc
@ -300,8 +300,7 @@ namespace boot
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
array_type::array_type(const struct position position, top_type *base,
|
array_type::array_type(const struct position position, std::shared_ptr<top_type> base, const std::uint32_t size)
|
||||||
const std::uint32_t size)
|
|
||||||
: top_type(position), m_base(base), size(size)
|
: top_type(position), m_base(base), size(size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -321,12 +320,7 @@ namespace boot
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
array_type::~array_type()
|
pointer_type::pointer_type(const struct position position, std::shared_ptr<top_type> base)
|
||||||
{
|
|
||||||
delete m_base;
|
|
||||||
}
|
|
||||||
|
|
||||||
pointer_type::pointer_type(const struct position position, top_type *base)
|
|
||||||
: top_type(position), m_base(base)
|
: top_type(position), m_base(base)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -346,24 +340,11 @@ namespace boot
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer_type::~pointer_type()
|
|
||||||
{
|
|
||||||
delete m_base;
|
|
||||||
}
|
|
||||||
|
|
||||||
composite_type::composite_type(const struct position position, fields_t&& fields)
|
composite_type::composite_type(const struct position position, fields_t&& fields)
|
||||||
: top_type(position), fields(std::move(fields))
|
: top_type(position), fields(std::move(fields))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
composite_type::~composite_type()
|
|
||||||
{
|
|
||||||
for (auto& field_declaration : fields)
|
|
||||||
{
|
|
||||||
delete field_declaration.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
record_type::record_type(const struct position position, fields_t&& fields)
|
record_type::record_type(const struct position position, fields_t&& fields)
|
||||||
: composite_type(position, std::move(fields))
|
: composite_type(position, std::move(fields))
|
||||||
{
|
{
|
||||||
@ -395,16 +376,11 @@ namespace boot
|
|||||||
}
|
}
|
||||||
|
|
||||||
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, top_type *type)
|
std::shared_ptr<top_type> type, const bool exported)
|
||||||
: definition(position, identifier, exported), m_type(type)
|
: definition(position, identifier, exported), m_type(type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
variable_declaration::~variable_declaration()
|
|
||||||
{
|
|
||||||
delete m_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void variable_declaration::accept(parser_visitor *visitor)
|
void variable_declaration::accept(parser_visitor *visitor)
|
||||||
{
|
{
|
||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
@ -442,7 +418,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, top_type *return_type)
|
const bool exported, std::shared_ptr<top_type> return_type)
|
||||||
: definition(position, identifier, exported), m_return_type(return_type)
|
: definition(position, identifier, exported), m_return_type(return_type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -463,7 +439,7 @@ namespace boot
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
top_type *procedure_definition::return_type()
|
std::shared_ptr<top_type> procedure_definition::return_type()
|
||||||
{
|
{
|
||||||
return m_return_type;
|
return m_return_type;
|
||||||
}
|
}
|
||||||
@ -481,7 +457,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, top_type *body)
|
const bool exported, std::shared_ptr<top_type> body)
|
||||||
: definition(position, identifier, exported), m_body(body)
|
: definition(position, identifier, exported), m_body(body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -496,11 +472,6 @@ namespace boot
|
|||||||
return *m_body;
|
return *m_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
type_definition::~type_definition()
|
|
||||||
{
|
|
||||||
delete m_body;
|
|
||||||
}
|
|
||||||
|
|
||||||
block::block(const struct position position)
|
block::block(const struct position position)
|
||||||
: node(position)
|
: node(position)
|
||||||
{
|
{
|
||||||
@ -772,7 +743,8 @@ namespace boot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cast_expression::cast_expression(const struct position position, top_type *target, expression *value)
|
cast_expression::cast_expression(const struct position position,
|
||||||
|
std::shared_ptr<top_type> target, expression *value)
|
||||||
: expression(position), m_target(target), m_value(value)
|
: expression(position), m_target(target), m_value(value)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -794,11 +766,10 @@ namespace boot
|
|||||||
|
|
||||||
cast_expression::~cast_expression()
|
cast_expression::~cast_expression()
|
||||||
{
|
{
|
||||||
delete m_target;
|
|
||||||
delete m_value;
|
delete m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
type_expression::type_expression(const struct position position, top_type *body)
|
type_expression::type_expression(const struct position position, std::shared_ptr<top_type> body)
|
||||||
: expression(position), m_body(body)
|
: expression(position), m_body(body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -813,11 +784,6 @@ namespace boot
|
|||||||
return *m_body;
|
return *m_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
type_expression::~type_expression()
|
|
||||||
{
|
|
||||||
delete m_body;
|
|
||||||
}
|
|
||||||
|
|
||||||
call_statement::call_statement(const struct position position, call_expression *body)
|
call_statement::call_statement(const struct position position, call_expression *body)
|
||||||
: statement(position), m_body(body)
|
: statement(position), m_body(body)
|
||||||
{
|
{
|
||||||
|
@ -98,10 +98,10 @@ along with GCC; see the file COPYING3. If not see
|
|||||||
%type <elna::boot::literal *> literal;
|
%type <elna::boot::literal *> literal;
|
||||||
%type <elna::boot::constant_definition *> constant_definition;
|
%type <elna::boot::constant_definition *> constant_definition;
|
||||||
%type <std::vector<elna::boot::constant_definition *>> constant_part constant_definitions;
|
%type <std::vector<elna::boot::constant_definition *>> constant_part constant_definitions;
|
||||||
%type <elna::boot::variable_declaration *> variable_declaration;
|
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part variable_declaration
|
||||||
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part
|
formal_parameters formal_parameter_list;
|
||||||
formal_parameter_list;
|
%type <elna::boot::variable_declaration *> formal_parameter
|
||||||
%type <elna::boot::top_type *> type_expression;
|
%type <std::shared_ptr<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,12 +117,13 @@ 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::top_type *>> field_declaration;
|
%type <elna::boot::field_t> field_declaration;
|
||||||
%type <std::vector<std::pair<std::string, elna::boot::top_type *>>> field_list;
|
%type <std::vector<std::pair<std::string, std::shared_ptr<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;
|
||||||
%type <std::pair<std::string, bool>> identifier_definition;
|
%type <std::pair<std::string, bool>> identifier_definition;
|
||||||
|
%type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
|
||||||
%%
|
%%
|
||||||
program:
|
program:
|
||||||
constant_part type_part variable_part procedure_part BEGIN_BLOCK optional_statements END_BLOCK DOT
|
constant_part type_part variable_part procedure_part BEGIN_BLOCK optional_statements END_BLOCK DOT
|
||||||
@ -154,6 +155,13 @@ identifier_definition:
|
|||||||
{
|
{
|
||||||
$$ = std::make_pair($1, false);
|
$$ = std::make_pair($1, false);
|
||||||
}
|
}
|
||||||
|
identifier_definitions:
|
||||||
|
identifier_definition COMMA identifier_definitions
|
||||||
|
{
|
||||||
|
std::swap($$, $3);
|
||||||
|
$$.emplace($$.cbegin(), $1);
|
||||||
|
}
|
||||||
|
| identifier_definition { $$.emplace_back(std::move($1)); }
|
||||||
procedure_heading:
|
procedure_heading:
|
||||||
PROCEDURE identifier_definition formal_parameter_list SEMICOLON
|
PROCEDURE identifier_definition formal_parameter_list SEMICOLON
|
||||||
{
|
{
|
||||||
@ -427,35 +435,41 @@ field_list:
|
|||||||
type_expression:
|
type_expression:
|
||||||
ARRAY INTEGER OF type_expression
|
ARRAY INTEGER OF type_expression
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::array_type(elna::boot::make_position(@1), $4, $2);
|
$$ = std::make_shared<elna::boot::array_type>(elna::boot::make_position(@1), $4, $2);
|
||||||
}
|
}
|
||||||
| POINTER TO type_expression
|
| POINTER TO type_expression
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::pointer_type(elna::boot::make_position(@1), $3);
|
$$ = std::make_shared<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(elna::boot::make_position(@1), std::move($2));
|
$$ = std::make_shared<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(elna::boot::make_position(@1), std::move($2));
|
$$ = std::make_shared<elna::boot::union_type>(elna::boot::make_position(@1), std::move($2));
|
||||||
}
|
}
|
||||||
| IDENTIFIER
|
| IDENTIFIER
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::basic_type(elna::boot::make_position(@1), $1);
|
$$ = std::make_shared<elna::boot::basic_type>(elna::boot::make_position(@1), $1);
|
||||||
}
|
}
|
||||||
variable_declaration: identifier_definition COLON type_expression
|
variable_declaration: identifier_definitions COLON type_expression
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::variable_declaration(elna::boot::make_position(@2), $1.first, $1.second, $3);
|
for (const std::pair<std::string, bool>& identifier : $1)
|
||||||
|
{
|
||||||
|
elna::boot::variable_declaration *declaration = new elna::boot::variable_declaration(
|
||||||
|
elna::boot::make_position(@2), identifier.first, $3, identifier.second);
|
||||||
|
$$.push_back(declaration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
variable_declarations:
|
variable_declarations:
|
||||||
variable_declaration COMMA variable_declarations
|
variable_declaration variable_declarations
|
||||||
{
|
{
|
||||||
std::swap($$, $3);
|
std::swap($$, $1);
|
||||||
$$.emplace($$.cbegin(), $1);
|
$$.reserve($$.size() + $2.size());
|
||||||
|
$$.insert(std::end($$), std::begin($2), std::end($2));
|
||||||
}
|
}
|
||||||
| variable_declaration { $$.emplace_back(std::move($1)); }
|
| variable_declaration { std::swap($$, $1); }
|
||||||
variable_part:
|
variable_part:
|
||||||
/* no variable declarations */ {}
|
/* no variable declarations */ {}
|
||||||
| VAR variable_declarations { std::swap($$, $2); }
|
| VAR variable_declarations { std::swap($$, $2); }
|
||||||
@ -489,9 +503,20 @@ type_part:
|
|||||||
/* no type definitions */ {}
|
/* no type definitions */ {}
|
||||||
| TYPE {}
|
| TYPE {}
|
||||||
| TYPE type_definitions { std::swap($$, $2); }
|
| TYPE type_definitions { std::swap($$, $2); }
|
||||||
|
formal_parameter: IDENTIFIER COLON type_expression
|
||||||
|
{
|
||||||
|
$$ = new elna::boot::variable_declaration(elna::boot::make_position(@2), $1, $3);
|
||||||
|
}
|
||||||
|
formal_parameters:
|
||||||
|
formal_parameter COMMA formal_parameters
|
||||||
|
{
|
||||||
|
std::swap($$, $3);
|
||||||
|
$$.emplace($$.cbegin(), $1);
|
||||||
|
}
|
||||||
|
| formal_parameter { $$.emplace_back(std::move($1)); }
|
||||||
formal_parameter_list:
|
formal_parameter_list:
|
||||||
LEFT_PAREN RIGHT_PAREN {}
|
LEFT_PAREN RIGHT_PAREN {}
|
||||||
| LEFT_PAREN variable_declarations RIGHT_PAREN { std::swap($$, $2); }
|
| LEFT_PAREN formal_parameters RIGHT_PAREN { std::swap($$, $2); }
|
||||||
actual_parameter_list:
|
actual_parameter_list:
|
||||||
LEFT_PAREN RIGHT_PAREN {}
|
LEFT_PAREN RIGHT_PAREN {}
|
||||||
| LEFT_PAREN expressions RIGHT_PAREN { std::swap($$, $2); }
|
| LEFT_PAREN expressions RIGHT_PAREN { std::swap($$, $2); }
|
||||||
|
@ -43,9 +43,9 @@ namespace gcc
|
|||||||
tree string_ptr_type = build_pointer_type_for_mode(elna_char_type_node, VOIDmode, true);
|
tree string_ptr_type = build_pointer_type_for_mode(elna_char_type_node, VOIDmode, true);
|
||||||
|
|
||||||
elna_string_length_field_node = build_field(UNKNOWN_LOCATION,
|
elna_string_length_field_node = build_field(UNKNOWN_LOCATION,
|
||||||
elna_string_type_node, "length", elna_word_type_node);
|
elna_string_type_node, "length", build_qualified_type(elna_word_type_node, TYPE_QUAL_CONST));
|
||||||
elna_string_ptr_field_node = build_field(UNKNOWN_LOCATION,
|
elna_string_ptr_field_node = build_field(UNKNOWN_LOCATION,
|
||||||
elna_string_type_node, "ptr", string_ptr_type);
|
elna_string_type_node, "ptr", build_qualified_type(string_ptr_type, TYPE_QUAL_CONST));
|
||||||
|
|
||||||
TYPE_FIELDS(elna_string_type_node) = chainon(elna_string_ptr_field_node, elna_string_length_field_node);
|
TYPE_FIELDS(elna_string_type_node) = chainon(elna_string_ptr_field_node, elna_string_length_field_node);
|
||||||
layout_type(elna_string_type_node);
|
layout_type(elna_string_type_node);
|
||||||
|
@ -108,7 +108,8 @@ namespace gcc
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
argument->accept(this);
|
argument->accept(this);
|
||||||
if (!is_assignable_from(TREE_TYPE(record_fields), this->current_expression))
|
tree unqualified_field = get_qualified_type(TREE_TYPE(record_fields), TYPE_UNQUALIFIED);
|
||||||
|
if (!is_assignable_from(unqualified_field, this->current_expression))
|
||||||
{
|
{
|
||||||
error_at(argument_location,
|
error_at(argument_location,
|
||||||
"cannot assign value of type '%s' to variable of type '%s'",
|
"cannot assign value of type '%s' to variable of type '%s'",
|
||||||
@ -548,11 +549,11 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
expression->lhs().accept(this);
|
expression->lhs().accept(this);
|
||||||
tree left = this->current_expression;
|
tree left = this->current_expression;
|
||||||
tree left_type = TREE_TYPE(left);
|
tree left_type = get_qualified_type(TREE_TYPE(left), TYPE_UNQUALIFIED);
|
||||||
|
|
||||||
expression->rhs().accept(this);
|
expression->rhs().accept(this);
|
||||||
tree right = this->current_expression;
|
tree right = this->current_expression;
|
||||||
tree right_type = TREE_TYPE(right);
|
tree right_type = get_qualified_type(TREE_TYPE(right), TYPE_UNQUALIFIED);
|
||||||
|
|
||||||
location_t expression_location = get_location(&expression->position());
|
location_t expression_location = get_location(&expression->position());
|
||||||
|
|
||||||
@ -1012,9 +1013,8 @@ namespace gcc
|
|||||||
error_at(statement_location, "cannot modify constant '%s'",
|
error_at(statement_location, "cannot modify constant '%s'",
|
||||||
statement->lvalue().is_variable()->name().c_str());
|
statement->lvalue().is_variable()->name().c_str());
|
||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (is_assignable_from(TREE_TYPE(lvalue), this->current_expression))
|
else if (is_assignable_from(TREE_TYPE(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);
|
||||||
|
@ -79,7 +79,7 @@ namespace gcc
|
|||||||
|
|
||||||
bool is_assignable_from(tree assignee, tree assignment)
|
bool is_assignable_from(tree assignee, tree assignment)
|
||||||
{
|
{
|
||||||
return TREE_TYPE(assignment) == assignee
|
return get_qualified_type(TREE_TYPE(assignment), TYPE_UNQUALIFIED) == assignee
|
||||||
|| are_compatible_pointers(assignee, assignment);
|
|| are_compatible_pointers(assignee, assignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,17 +133,19 @@ namespace gcc
|
|||||||
|
|
||||||
tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right)
|
tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right)
|
||||||
{
|
{
|
||||||
|
tree left_type = get_qualified_type(TREE_TYPE(left), TYPE_UNQUALIFIED);
|
||||||
|
tree right_type = get_qualified_type(TREE_TYPE(right), TYPE_UNQUALIFIED);
|
||||||
if (binary_operator == boot::binary_operator::sum)
|
if (binary_operator == boot::binary_operator::sum)
|
||||||
{
|
{
|
||||||
tree pointer{ NULL_TREE };
|
tree pointer{ NULL_TREE };
|
||||||
tree offset{ NULL_TREE };
|
tree offset{ NULL_TREE };
|
||||||
|
|
||||||
if (is_pointer_type(TREE_TYPE(left)) && is_integral_type(TREE_TYPE(right)))
|
if (is_pointer_type(left_type) && is_integral_type(right_type))
|
||||||
{
|
{
|
||||||
pointer = left;
|
pointer = left;
|
||||||
offset = right;
|
offset = right;
|
||||||
}
|
}
|
||||||
else if (is_integral_type(TREE_TYPE(left)) && is_pointer_type(TREE_TYPE(right)))
|
else if (is_integral_type(left_type) && is_pointer_type(right_type))
|
||||||
{
|
{
|
||||||
pointer = right;
|
pointer = right;
|
||||||
offset = left;
|
offset = left;
|
||||||
@ -161,10 +163,10 @@ namespace gcc
|
|||||||
}
|
}
|
||||||
else if (binary_operator == boot::binary_operator::subtraction)
|
else if (binary_operator == boot::binary_operator::subtraction)
|
||||||
{
|
{
|
||||||
if (is_pointer_type(TREE_TYPE(left)) && is_integral_type(TREE_TYPE(right)))
|
if (is_pointer_type(left_type) && is_integral_type(right_type))
|
||||||
{
|
{
|
||||||
tree pointer_type = TREE_TYPE(left);
|
tree pointer_type = left_type;
|
||||||
tree offset_type = TREE_TYPE(right);
|
tree offset_type = right_type;
|
||||||
tree size_exp = fold_convert(offset_type, size_in_bytes(TREE_TYPE(pointer_type)));
|
tree size_exp = fold_convert(offset_type, size_in_bytes(TREE_TYPE(pointer_type)));
|
||||||
|
|
||||||
tree convert_expression = fold_build2(MULT_EXPR, offset_type, right, size_exp);
|
tree convert_expression = fold_build2(MULT_EXPR, offset_type, right, size_exp);
|
||||||
@ -172,8 +174,8 @@ namespace gcc
|
|||||||
|
|
||||||
convert_expression = fold_build1(NEGATE_EXPR, sizetype, convert_expression);
|
convert_expression = fold_build1(NEGATE_EXPR, sizetype, convert_expression);
|
||||||
return fold_build2(POINTER_PLUS_EXPR, pointer_type, left, convert_expression);
|
return fold_build2(POINTER_PLUS_EXPR, pointer_type, left, convert_expression);
|
||||||
} else if (is_pointer_type(TREE_TYPE(left)) && is_pointer_type(TREE_TYPE(right))
|
}
|
||||||
&& TREE_TYPE(left) == TREE_TYPE(right))
|
else if (is_pointer_type(left_type) && is_pointer_type(right_type) && left_type == right_type)
|
||||||
{
|
{
|
||||||
return fold_build2(POINTER_DIFF_EXPR, ssizetype, left, right);
|
return fold_build2(POINTER_DIFF_EXPR, ssizetype, left, right);
|
||||||
}
|
}
|
||||||
@ -185,8 +187,8 @@ namespace gcc
|
|||||||
tree_code operator_code, tree left, tree right, tree target_type)
|
tree_code operator_code, tree left, tree right, tree target_type)
|
||||||
{
|
{
|
||||||
location_t expression_location = get_location(&expression->position());
|
location_t expression_location = get_location(&expression->position());
|
||||||
tree left_type = TREE_TYPE(left);
|
tree left_type = get_qualified_type(TREE_TYPE(left), TYPE_UNQUALIFIED);
|
||||||
tree right_type = TREE_TYPE(right);
|
tree right_type = get_qualified_type(TREE_TYPE(right), TYPE_UNQUALIFIED);
|
||||||
|
|
||||||
if (condition)
|
if (condition)
|
||||||
{
|
{
|
||||||
|
@ -255,37 +255,33 @@ namespace boot
|
|||||||
|
|
||||||
class array_type : public top_type
|
class array_type : public top_type
|
||||||
{
|
{
|
||||||
top_type *m_base;
|
std::shared_ptr<top_type> m_base;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const std::uint32_t size;
|
const std::uint32_t size;
|
||||||
|
|
||||||
array_type(const struct position position, top_type*base, const std::uint32_t size);
|
array_type(const struct position position, std::shared_ptr<top_type> base, const std::uint32_t size);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
top_type& base();
|
top_type& base();
|
||||||
|
|
||||||
array_type *is_array() override;
|
array_type *is_array() override;
|
||||||
|
|
||||||
virtual ~array_type() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class pointer_type : public top_type
|
class pointer_type : public top_type
|
||||||
{
|
{
|
||||||
top_type *m_base;
|
std::shared_ptr<top_type> m_base;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
pointer_type(const struct position position, top_type *base);
|
pointer_type(const struct position position, std::shared_ptr<top_type> base);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
top_type& base();
|
top_type& base();
|
||||||
|
|
||||||
pointer_type *is_pointer() override;
|
pointer_type *is_pointer() override;
|
||||||
|
|
||||||
virtual ~pointer_type() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using field_t = std::pair<std::string, top_type *>;
|
using field_t = std::pair<std::string, std::shared_ptr<top_type>>;
|
||||||
using fields_t = std::vector<field_t>;
|
using fields_t = std::vector<field_t>;
|
||||||
|
|
||||||
class composite_type : public top_type
|
class composite_type : public top_type
|
||||||
@ -295,8 +291,6 @@ namespace boot
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
fields_t fields;
|
fields_t fields;
|
||||||
|
|
||||||
virtual ~composite_type() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class record_type : public composite_type
|
class record_type : public composite_type
|
||||||
@ -322,16 +316,14 @@ namespace boot
|
|||||||
*/
|
*/
|
||||||
class variable_declaration : public definition
|
class variable_declaration : public definition
|
||||||
{
|
{
|
||||||
top_type *m_type;
|
std::shared_ptr<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, top_type *type);
|
std::shared_ptr<top_type> type, const bool exported = false);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
top_type& variable_type();
|
top_type& variable_type();
|
||||||
|
|
||||||
virtual ~variable_declaration() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -370,17 +362,17 @@ namespace boot
|
|||||||
*/
|
*/
|
||||||
class procedure_definition : public definition
|
class procedure_definition : public definition
|
||||||
{
|
{
|
||||||
top_type *m_return_type{ nullptr };
|
std::shared_ptr<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, top_type *return_type = nullptr);
|
const bool exported, std::shared_ptr<top_type> return_type = nullptr);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
top_type *return_type();
|
std::shared_ptr<top_type> return_type();
|
||||||
|
|
||||||
block *body();
|
block *body();
|
||||||
procedure_definition *add_body(block *procedure_body);
|
procedure_definition *add_body(block *procedure_body);
|
||||||
@ -393,16 +385,14 @@ namespace boot
|
|||||||
*/
|
*/
|
||||||
class type_definition : public definition
|
class type_definition : public definition
|
||||||
{
|
{
|
||||||
top_type *m_body;
|
std::shared_ptr<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, top_type *expression);
|
const bool exported, std::shared_ptr<top_type> expression);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
top_type& body();
|
top_type& body();
|
||||||
|
|
||||||
virtual ~type_definition() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -432,11 +422,11 @@ namespace boot
|
|||||||
*/
|
*/
|
||||||
class cast_expression : public expression
|
class cast_expression : public expression
|
||||||
{
|
{
|
||||||
top_type *m_target;
|
std::shared_ptr<top_type> m_target;
|
||||||
expression *m_value;
|
expression *m_value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cast_expression(const struct position position, top_type *target, expression *value);
|
cast_expression(const struct position position, std::shared_ptr<top_type> target, expression *value);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
top_type& target();
|
top_type& target();
|
||||||
@ -450,15 +440,13 @@ namespace boot
|
|||||||
*/
|
*/
|
||||||
class type_expression : public expression
|
class type_expression : public expression
|
||||||
{
|
{
|
||||||
top_type *m_body;
|
std::shared_ptr<top_type> m_body;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
type_expression(const struct position position, top_type *body);
|
type_expression(const struct position position, std::shared_ptr<top_type> body);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
top_type& body();
|
top_type& body();
|
||||||
|
|
||||||
virtual ~type_expression() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class call_statement : public statement
|
class call_statement : public statement
|
||||||
|
62
source.elna
62
source.elna
@ -30,8 +30,8 @@ const
|
|||||||
TOKEN_NOT* = 25
|
TOKEN_NOT* = 25
|
||||||
TOKEN_RETURN* = 26
|
TOKEN_RETURN* = 26
|
||||||
TOKEN_CAST* = 27
|
TOKEN_CAST* = 27
|
||||||
TOKEN_AS* = 28
|
TOKEN_SHIFT_LEFT* = 28
|
||||||
TOKEN_SIZEOF* = 29
|
TOKEN_SHIFT_RIGHT* = 29
|
||||||
TOKEN_LEFT_PAREN* = 30
|
TOKEN_LEFT_PAREN* = 30
|
||||||
TOKEN_RIGHT_PAREN* = 31
|
TOKEN_RIGHT_PAREN* = 31
|
||||||
TOKEN_LEFT_SQUARE* = 32
|
TOKEN_LEFT_SQUARE* = 32
|
||||||
@ -172,7 +172,8 @@ end
|
|||||||
|
|
||||||
proc write_i(value: Int);
|
proc write_i(value: Int);
|
||||||
var
|
var
|
||||||
digit: Int, n: Word,
|
digit: Int
|
||||||
|
n: Word
|
||||||
buffer: array 10 of Char
|
buffer: array 10 of Char
|
||||||
begin
|
begin
|
||||||
n := 10u;
|
n := 10u;
|
||||||
@ -243,16 +244,14 @@ end
|
|||||||
*)
|
*)
|
||||||
|
|
||||||
proc make_position() -> Position;
|
proc make_position() -> Position;
|
||||||
var
|
|
||||||
result: Position
|
|
||||||
begin
|
begin
|
||||||
return Position(1u, 1u)
|
return Position(1u, 1u)
|
||||||
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;
|
||||||
var
|
var
|
||||||
input_file: pointer to FILE,
|
input_file: pointer to FILE
|
||||||
source_size: Int,
|
source_size: Int
|
||||||
input: pointer to Byte
|
input: pointer to Byte
|
||||||
begin
|
begin
|
||||||
input_file := fopen(filename, "rb\0".ptr);
|
input_file := fopen(filename, "rb\0".ptr);
|
||||||
@ -276,8 +275,7 @@ begin
|
|||||||
if fread(input, cast(source_size: Word), 1u, 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: Word);
|
result^ := String(cast(input: pointer to Char), cast(source_size: Word));
|
||||||
result^.ptr := cast(input: pointer to Char);
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@ -398,9 +396,8 @@ end
|
|||||||
|
|
||||||
proc lex_string(input: pointer to Char, current_token: pointer to Token) -> pointer to Char;
|
proc lex_string(input: pointer to Char, current_token: pointer to Token) -> pointer to Char;
|
||||||
var
|
var
|
||||||
token_end: pointer to Char,
|
token_end, constructed_string: pointer to Char
|
||||||
constructed_string: pointer to Char,
|
token_length: Word
|
||||||
token_length: Word,
|
|
||||||
is_valid: Bool
|
is_valid: Bool
|
||||||
begin
|
begin
|
||||||
token_end := input;
|
token_end := input;
|
||||||
@ -438,7 +435,7 @@ end
|
|||||||
|
|
||||||
proc print_tokens(tokens: pointer to Token, tokens_size: Word);
|
proc print_tokens(tokens: pointer to Token, tokens_size: Word);
|
||||||
var
|
var
|
||||||
current_token: pointer to Token,
|
current_token: pointer to Token
|
||||||
i: Word
|
i: Word
|
||||||
begin
|
begin
|
||||||
i := 0u;
|
i := 0u;
|
||||||
@ -499,10 +496,10 @@ begin
|
|||||||
write_s("RETURN")
|
write_s("RETURN")
|
||||||
elsif current_token^.kind = TOKEN_CAST then
|
elsif current_token^.kind = TOKEN_CAST then
|
||||||
write_s("CAST")
|
write_s("CAST")
|
||||||
elsif current_token^.kind = TOKEN_AS then
|
elsif current_token^.kind = TOKEN_SHIFT_LEFT then
|
||||||
write_s("AS")
|
write_s("<<")
|
||||||
elsif current_token^.kind = TOKEN_SIZEOF then
|
elsif current_token^.kind = TOKEN_SHIFT_RIGHT then
|
||||||
write_s("SIZEOF")
|
write_s(">>")
|
||||||
elsif current_token^.kind = TOKEN_IDENTIFIER then
|
elsif current_token^.kind = TOKEN_IDENTIFIER then
|
||||||
write_c('<');
|
write_c('<');
|
||||||
write_s(current_token^.value.string);
|
write_s(current_token^.value.string);
|
||||||
@ -641,10 +638,6 @@ begin
|
|||||||
current_token.kind := TOKEN_RETURN
|
current_token.kind := TOKEN_RETURN
|
||||||
elsif "cast" = token_content then
|
elsif "cast" = token_content then
|
||||||
current_token.kind := TOKEN_CAST
|
current_token.kind := TOKEN_CAST
|
||||||
elsif "as" = token_content then
|
|
||||||
current_token.kind := TOKEN_AS
|
|
||||||
elsif "sizeof" = token_content then
|
|
||||||
current_token.kind := TOKEN_SIZEOF
|
|
||||||
elsif "defer" = token_content then
|
elsif "defer" = token_content then
|
||||||
current_token.kind := TOKEN_DEFER
|
current_token.kind := TOKEN_DEFER
|
||||||
else
|
else
|
||||||
@ -657,11 +650,10 @@ end
|
|||||||
|
|
||||||
proc tokenize(source_code: SourceCode, tokens_size: pointer to Word) -> pointer to Token;
|
proc tokenize(source_code: SourceCode, tokens_size: pointer to Word) -> pointer to Token;
|
||||||
var
|
var
|
||||||
token_end: pointer to Char,
|
token_end: pointer to Char
|
||||||
tokens: pointer to Token,
|
tokens, current_token: pointer to Token
|
||||||
current_token: pointer to Token,
|
token_length: Word
|
||||||
token_length: Word,
|
first_char: Char
|
||||||
first_char: Char,
|
|
||||||
token_content: String
|
token_content: String
|
||||||
begin
|
begin
|
||||||
tokens_size^ := 0u;
|
tokens_size^ := 0u;
|
||||||
@ -740,6 +732,9 @@ begin
|
|||||||
elsif source_code.text[1u] = '=' then
|
elsif source_code.text[1u] = '=' then
|
||||||
current_token^.kind := TOKEN_GREATER_EQUAL;
|
current_token^.kind := TOKEN_GREATER_EQUAL;
|
||||||
source_code := advance_source(source_code, 1u)
|
source_code := advance_source(source_code, 1u)
|
||||||
|
elsif source_code.text[1u] = '>' then
|
||||||
|
current_token^.kind := TOKEN_SHIFT_RIGHT;
|
||||||
|
source_code := advance_source(source_code, 1u)
|
||||||
else
|
else
|
||||||
current_token^.kind := TOKEN_GREATER_THAN
|
current_token^.kind := TOKEN_GREATER_THAN
|
||||||
end
|
end
|
||||||
@ -751,6 +746,9 @@ begin
|
|||||||
elsif source_code.text[1u] = '=' then
|
elsif source_code.text[1u] = '=' then
|
||||||
current_token^.kind := TOKEN_LESS_EQUAL;
|
current_token^.kind := TOKEN_LESS_EQUAL;
|
||||||
source_code := advance_source(source_code, 1u)
|
source_code := advance_source(source_code, 1u)
|
||||||
|
elsif source_code.text[1u] = '<' then
|
||||||
|
current_token^.kind := TOKEN_SHIFT_LEFT;
|
||||||
|
source_code := advance_source(source_code, 1u)
|
||||||
elsif source_code.text[1u] = '>' then
|
elsif source_code.text[1u] = '>' then
|
||||||
current_token^.kind := TOKEN_NOT_EQUAL;
|
current_token^.kind := TOKEN_NOT_EQUAL;
|
||||||
source_code := advance_source(source_code, 1u)
|
source_code := advance_source(source_code, 1u)
|
||||||
@ -850,7 +848,7 @@ end
|
|||||||
|
|
||||||
proc parse_program(tokens: pointer to pointer to Token, tokens_size: pointer to Word) -> pointer to Program;
|
proc parse_program(tokens: pointer to pointer to Token, tokens_size: pointer to Word) -> pointer to Program;
|
||||||
var
|
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(1u, Program.size): pointer to Program);
|
result := cast(calloc(1u, Program.size): pointer to Program);
|
||||||
@ -883,8 +881,8 @@ end
|
|||||||
|
|
||||||
proc parse_command_line*(argc: Int, argv: pointer to pointer to Char) -> pointer to CommandLine;
|
proc parse_command_line*(argc: Int, argv: pointer to pointer to Char) -> pointer to CommandLine;
|
||||||
var
|
var
|
||||||
parameter: pointer to pointer to Char,
|
parameter: pointer to pointer to Char
|
||||||
i: Int,
|
i: Int
|
||||||
result: pointer to CommandLine
|
result: pointer to CommandLine
|
||||||
begin
|
begin
|
||||||
i := 1;
|
i := 1;
|
||||||
@ -924,9 +922,9 @@ end
|
|||||||
|
|
||||||
proc process(argc: Int, argv: pointer to pointer to Char) -> Int;
|
proc process(argc: Int, argv: pointer to pointer to Char) -> Int;
|
||||||
var
|
var
|
||||||
tokens: pointer to Token,
|
tokens: pointer to Token
|
||||||
tokens_size: Word,
|
tokens_size: Word
|
||||||
source_code: SourceCode,
|
source_code: SourceCode
|
||||||
command_line: pointer to CommandLine
|
command_line: pointer to CommandLine
|
||||||
begin
|
begin
|
||||||
command_line := parse_command_line(argc, argv);
|
command_line := parse_command_line(argc, argv);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user