Cast expressions
This commit is contained in:
parent
18d8ded239
commit
a80ed092b8
@ -68,7 +68,7 @@ begin
|
|||||||
digit := value % 10;
|
digit := value % 10;
|
||||||
value := value / 10;
|
value := value / 10;
|
||||||
|
|
||||||
buffer[n] := Char(Int('0') + digit);
|
buffer[n] := cast(cast('0' as Int) + digit as Char);
|
||||||
n := n - 1
|
n := n - 1
|
||||||
end;
|
end;
|
||||||
while n < 10 do
|
while n < 10 do
|
||||||
|
@ -20,40 +20,21 @@ namespace gcc
|
|||||||
this->symbol_map = symbol_table;
|
this->symbol_map = symbol_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(source::call_expression *statement)
|
void generic_visitor::visit(source::call_expression *expression)
|
||||||
{
|
{
|
||||||
auto symbol = this->symbol_map->lookup(statement->name());
|
if (auto symbol = this->symbol_map->lookup(expression->name()))
|
||||||
|
|
||||||
if (statement->name() == "Int" || statement->name() == "Word" || statement->name() == "Bool"
|
|
||||||
|| statement->name() == "Float" || statement->name() == "Char")
|
|
||||||
{
|
|
||||||
if (statement->arguments().size() != 1)
|
|
||||||
{
|
|
||||||
error_at(get_location(&statement->position()),
|
|
||||||
"procedure '%s' expects 1 argument, %lu given",
|
|
||||||
statement->name().c_str(), statement->arguments().size());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto& argument = statement->arguments().at(0);
|
|
||||||
argument->accept(this);
|
|
||||||
tree argument_type = TREE_TYPE(this->current_expression);
|
|
||||||
|
|
||||||
this->current_expression = build1_loc(get_location(&argument->position()), CONVERT_EXPR,
|
|
||||||
symbol->payload, this->current_expression);
|
|
||||||
}
|
|
||||||
else if (symbol)
|
|
||||||
{
|
{
|
||||||
tree return_type = TREE_TYPE(TREE_TYPE(symbol->payload));
|
tree return_type = TREE_TYPE(TREE_TYPE(symbol->payload));
|
||||||
tree fndecl_type = build_function_type(return_type, TYPE_ARG_TYPES(symbol->payload));
|
tree fndecl_type = build_function_type(return_type, TYPE_ARG_TYPES(symbol->payload));
|
||||||
tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol->payload);
|
tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol->payload);
|
||||||
|
|
||||||
std::vector<tree> arguments(statement->arguments().size());
|
std::vector<tree> arguments(expression->arguments().size());
|
||||||
for (std::size_t i = 0; i < statement->arguments().size(); ++i)
|
for (std::size_t i = 0; i < expression->arguments().size(); ++i)
|
||||||
{
|
{
|
||||||
statement->arguments().at(i)->accept(this);
|
expression->arguments().at(i)->accept(this);
|
||||||
arguments[i] = this->current_expression;
|
arguments[i] = this->current_expression;
|
||||||
}
|
}
|
||||||
tree stmt = build_call_array_loc(get_location(&statement->position()),
|
tree stmt = build_call_array_loc(get_location(&expression->position()),
|
||||||
return_type, printf_fn, arguments.size(), arguments.data());
|
return_type, printf_fn, arguments.size(), arguments.data());
|
||||||
|
|
||||||
if (return_type == void_type_node)
|
if (return_type == void_type_node)
|
||||||
@ -68,12 +49,24 @@ namespace gcc
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error_at(get_location(&statement->position()),
|
error_at(get_location(&expression->position()),
|
||||||
"procedure '%s' not declared",
|
"procedure '%s' not declared",
|
||||||
statement->name().c_str());
|
expression->name().c_str());
|
||||||
|
this->current_expression = error_mark_node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generic_visitor::visit(source::cast_expression *expression)
|
||||||
|
{
|
||||||
|
tree cast_target = build_type(expression->target());
|
||||||
|
gcc_assert(cast_target != NULL_TREE);
|
||||||
|
|
||||||
|
expression->value().accept(this);
|
||||||
|
|
||||||
|
this->current_expression = build1_loc(get_location(&expression->position()), CONVERT_EXPR,
|
||||||
|
cast_target, this->current_expression);
|
||||||
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(source::program *program)
|
void generic_visitor::visit(source::program *program)
|
||||||
{
|
{
|
||||||
for (const auto definition : program->value_definitions)
|
for (const auto definition : program->value_definitions)
|
||||||
|
@ -28,6 +28,12 @@ namespace gcc
|
|||||||
&& TYPE_MAIN_VARIANT(TREE_TYPE(type)) == char_type_node;
|
&& TYPE_MAIN_VARIANT(TREE_TYPE(type)) == char_type_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_integral_type(tree type)
|
||||||
|
{
|
||||||
|
gcc_assert(TYPE_P(type));
|
||||||
|
return type == integer_type_node || type == unsigned_type_node;
|
||||||
|
}
|
||||||
|
|
||||||
tree tree_chain_base::head()
|
tree tree_chain_base::head()
|
||||||
{
|
{
|
||||||
return first;
|
return first;
|
||||||
|
@ -41,7 +41,8 @@ namespace gcc
|
|||||||
|
|
||||||
void visit(source::program *program) override;
|
void visit(source::program *program) override;
|
||||||
void visit(source::procedure_definition *definition) override;
|
void visit(source::procedure_definition *definition) override;
|
||||||
void visit(source::call_expression *statement) override;
|
void visit(source::call_expression *expression) override;
|
||||||
|
void visit(source::cast_expression *expression) override;
|
||||||
void visit(source::number_literal<std::int32_t> *literal) override;
|
void visit(source::number_literal<std::int32_t> *literal) override;
|
||||||
void visit(source::number_literal<std::uint32_t> *literal) override;
|
void visit(source::number_literal<std::uint32_t> *literal) override;
|
||||||
void visit(source::number_literal<double> *literal) override;
|
void visit(source::number_literal<double> *literal) override;
|
||||||
|
@ -27,6 +27,7 @@ namespace gcc
|
|||||||
void init_ttree();
|
void init_ttree();
|
||||||
bool is_pointer_type(tree type);
|
bool is_pointer_type(tree type);
|
||||||
bool is_string_type(tree type);
|
bool is_string_type(tree type);
|
||||||
|
bool is_integral_type(tree type);
|
||||||
|
|
||||||
class tree_chain_base
|
class tree_chain_base
|
||||||
{
|
{
|
||||||
|
@ -41,6 +41,7 @@ namespace source
|
|||||||
class procedure_definition;
|
class procedure_definition;
|
||||||
class type_definition;
|
class type_definition;
|
||||||
class call_expression;
|
class call_expression;
|
||||||
|
class cast_expression;
|
||||||
class assign_statement;
|
class assign_statement;
|
||||||
class if_statement;
|
class if_statement;
|
||||||
class while_statement;
|
class while_statement;
|
||||||
@ -74,6 +75,7 @@ namespace source
|
|||||||
virtual void visit(procedure_definition *) = 0;
|
virtual void visit(procedure_definition *) = 0;
|
||||||
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(expression_statement *) = 0;
|
virtual void visit(expression_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;
|
||||||
@ -109,7 +111,8 @@ namespace source
|
|||||||
virtual void visit(constant_definition *definition) override;
|
virtual void visit(constant_definition *definition) override;
|
||||||
virtual void visit(procedure_definition *definition) override;
|
virtual void visit(procedure_definition *definition) override;
|
||||||
virtual void visit(type_definition *definition) override;
|
virtual void visit(type_definition *definition) override;
|
||||||
virtual void visit(call_expression *statement) override;
|
virtual void visit(call_expression *expression) override;
|
||||||
|
virtual void visit(cast_expression *expression) override;
|
||||||
virtual void visit(expression_statement *statement) override;
|
virtual void visit(expression_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;
|
||||||
@ -136,55 +139,6 @@ namespace source
|
|||||||
virtual void visit(string_literal *) override;
|
virtual void visit(string_literal *) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Operand representing a subexpression in the 3 address code.
|
|
||||||
*/
|
|
||||||
struct operand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~operand() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct integer_operand final : public operand
|
|
||||||
{
|
|
||||||
std::int32_t m_value;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit integer_operand(const std::int32_t value);
|
|
||||||
|
|
||||||
std::int32_t value() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class variable_operand final : public operand
|
|
||||||
{
|
|
||||||
std::string m_name;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit variable_operand(const std::string& name);
|
|
||||||
|
|
||||||
const std::string& name() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct temporary_variable final : public operand
|
|
||||||
{
|
|
||||||
std::size_t m_counter;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit temporary_variable(const std::size_t counter);
|
|
||||||
|
|
||||||
std::size_t counter() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct label_operand final : public operand
|
|
||||||
{
|
|
||||||
std::size_t m_counter;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit label_operand(const std::size_t counter);
|
|
||||||
|
|
||||||
std::size_t counter() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AST node.
|
* AST node.
|
||||||
*/
|
*/
|
||||||
@ -219,9 +173,6 @@ namespace source
|
|||||||
|
|
||||||
class expression : public node
|
class expression : public node
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
std::shared_ptr<operand> place;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* \param position Source code position.
|
* \param position Source code position.
|
||||||
@ -448,7 +399,7 @@ namespace source
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call statement.
|
* Procedure call expression.
|
||||||
*/
|
*/
|
||||||
class call_expression : public expression
|
class call_expression : public expression
|
||||||
{
|
{
|
||||||
@ -469,6 +420,24 @@ namespace source
|
|||||||
virtual ~call_expression() override;
|
virtual ~call_expression() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cast expression.
|
||||||
|
*/
|
||||||
|
class cast_expression : public expression
|
||||||
|
{
|
||||||
|
type_expression *m_target;
|
||||||
|
expression *m_value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
cast_expression(const struct position position, type_expression *target, expression *value);
|
||||||
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
|
type_expression& target();
|
||||||
|
expression& value();
|
||||||
|
|
||||||
|
virtual ~cast_expression() override;
|
||||||
|
};
|
||||||
|
|
||||||
class expression_statement : public statement
|
class expression_statement : public statement
|
||||||
{
|
{
|
||||||
expression *m_body;
|
expression *m_body;
|
||||||
|
@ -33,14 +33,20 @@ namespace source
|
|||||||
definition->body().accept(this);
|
definition->body().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(call_expression *statement)
|
void empty_visitor::visit(call_expression *expression)
|
||||||
{
|
{
|
||||||
for (auto& argument : statement->arguments())
|
for (auto& argument : expression->arguments())
|
||||||
{
|
{
|
||||||
argument->accept(this);
|
argument->accept(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void empty_visitor::visit(cast_expression *expression)
|
||||||
|
{
|
||||||
|
expression->target().accept(this);
|
||||||
|
expression->value().accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(expression_statement *statement)
|
void empty_visitor::visit(expression_statement *statement)
|
||||||
{
|
{
|
||||||
statement->body().accept(this);
|
statement->body().accept(this);
|
||||||
@ -185,50 +191,6 @@ namespace source
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
operand::~operand()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
integer_operand::integer_operand(const std::int32_t value)
|
|
||||||
: m_value(value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::int32_t integer_operand::value() const
|
|
||||||
{
|
|
||||||
return m_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
variable_operand::variable_operand(const std::string& name)
|
|
||||||
: m_name(name)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& variable_operand::name() const
|
|
||||||
{
|
|
||||||
return m_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
temporary_variable::temporary_variable(const std::size_t counter)
|
|
||||||
: m_counter(counter)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t temporary_variable::counter() const
|
|
||||||
{
|
|
||||||
return m_counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
label_operand::label_operand(const std::size_t counter)
|
|
||||||
: m_counter(counter)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t label_operand::counter() const
|
|
||||||
{
|
|
||||||
return m_counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
node::node(const struct position position)
|
node::node(const struct position position)
|
||||||
: source_position(position)
|
: source_position(position)
|
||||||
{
|
{
|
||||||
@ -766,6 +728,32 @@ namespace source
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cast_expression::cast_expression(const struct position position, type_expression *target, expression *value)
|
||||||
|
: expression(position), m_target(target), m_value(value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void cast_expression::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_expression& cast_expression::target()
|
||||||
|
{
|
||||||
|
return *m_target;
|
||||||
|
}
|
||||||
|
|
||||||
|
expression& cast_expression::value()
|
||||||
|
{
|
||||||
|
return *m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
cast_expression::~cast_expression()
|
||||||
|
{
|
||||||
|
delete m_target;
|
||||||
|
delete m_value;
|
||||||
|
}
|
||||||
|
|
||||||
expression_statement::expression_statement(const struct position position, expression *body)
|
expression_statement::expression_statement(const struct position position, expression *body)
|
||||||
: statement(position), m_body(body)
|
: statement(position), m_body(body)
|
||||||
{
|
{
|
||||||
|
@ -106,6 +106,12 @@ not {
|
|||||||
return {
|
return {
|
||||||
return yy::parser::make_RETURN(this->location);
|
return yy::parser::make_RETURN(this->location);
|
||||||
}
|
}
|
||||||
|
cast {
|
||||||
|
return yy::parser::make_CAST(this->location);
|
||||||
|
}
|
||||||
|
as {
|
||||||
|
return yy::parser::make_AS(this->location);
|
||||||
|
}
|
||||||
[A-Za-z_][A-Za-z0-9_]* {
|
[A-Za-z_][A-Za-z0-9_]* {
|
||||||
return yy::parser::make_IDENTIFIER(yytext, this->location);
|
return yy::parser::make_IDENTIFIER(yytext, this->location);
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
%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
|
%token BEGIN_BLOCK END_BLOCK EXTERN
|
||||||
%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
|
%token AND OR NOT CAST AS
|
||||||
%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
|
%token ASSIGNMENT COLON HAT AT
|
||||||
@ -97,6 +97,7 @@
|
|||||||
%type <std::pair<std::string, elna::source::type_expression *>> field_declaration;
|
%type <std::pair<std::string, elna::source::type_expression *>> field_declaration;
|
||||||
%type <std::vector<std::pair<std::string, elna::source::type_expression *>>> field_list;
|
%type <std::vector<std::pair<std::string, elna::source::type_expression *>>> field_list;
|
||||||
%type <std::vector<elna::source::conditional_statements *>> elsif_statement_list;
|
%type <std::vector<elna::source::conditional_statements *>> elsif_statement_list;
|
||||||
|
%type <elna::source::cast_expression *> cast_expression;
|
||||||
%%
|
%%
|
||||||
program:
|
program:
|
||||||
type_part constant_part procedure_part variable_part BEGIN_BLOCK optional_statements END_BLOCK DOT
|
type_part constant_part procedure_part variable_part BEGIN_BLOCK optional_statements END_BLOCK DOT
|
||||||
@ -183,6 +184,10 @@ call_expression: IDENTIFIER actual_parameter_list
|
|||||||
$$ = new elna::source::call_expression(elna::source::make_position(@1), $1);
|
$$ = new elna::source::call_expression(elna::source::make_position(@1), $1);
|
||||||
std::swap($$->arguments(), $2);
|
std::swap($$->arguments(), $2);
|
||||||
}
|
}
|
||||||
|
cast_expression: CAST LEFT_PAREN expression AS type_expression RIGHT_PAREN
|
||||||
|
{
|
||||||
|
$$ = new elna::source::cast_expression(elna::source::make_position(@1), $5, $3);
|
||||||
|
}
|
||||||
while_statement: WHILE expression DO optional_statements END_BLOCK
|
while_statement: WHILE expression DO optional_statements END_BLOCK
|
||||||
{
|
{
|
||||||
auto body = new elna::source::conditional_statements($2);
|
auto body = new elna::source::conditional_statements($2);
|
||||||
@ -247,6 +252,7 @@ literal:
|
|||||||
pointer:
|
pointer:
|
||||||
literal { $$ = $1; }
|
literal { $$ = $1; }
|
||||||
| designator_expression { $$ = $1; }
|
| designator_expression { $$ = $1; }
|
||||||
|
| cast_expression { $$ = $1; }
|
||||||
| call_expression { $$ = $1; }
|
| call_expression { $$ = $1; }
|
||||||
| LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); }
|
| LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); }
|
||||||
summand:
|
summand:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user