Introduce float type

This commit is contained in:
Eugen Wissner 2024-12-31 18:10:34 +01:00
parent 75a691134f
commit 8176da5f9b
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
8 changed files with 100 additions and 60 deletions

View File

@ -30,7 +30,6 @@ elna_OBJS = \
elna/lexer.o \ elna/lexer.o \
elna/parser.o \ elna/parser.o \
elna/result.o \ elna/result.o \
elna/semantic.o \
elna/symbol_table.o \ elna/symbol_table.o \
elna/types.o \ elna/types.o \
$(END) $(END)

View File

@ -22,11 +22,11 @@ namespace gcc
} }
else if (type == boolean_type_node) else if (type == boolean_type_node)
{ {
return "Boolean"; return "Bool";
} }
else if (type == enumeral_node) else if (type == double_type_node)
{ {
return "Enum"; return "Float";
} }
else else
{ {

View File

@ -7,6 +7,7 @@
#include "gimplify.h" #include "gimplify.h"
#include "stringpool.h" #include "stringpool.h"
#include "diagnostic.h" #include "diagnostic.h"
#include "realmpfr.h"
namespace elna namespace elna
{ {
@ -31,20 +32,27 @@ namespace gcc
auto& argument = statement->arguments().at(0); auto& argument = statement->arguments().at(0);
argument->accept(this); argument->accept(this);
auto argument_type = TREE_TYPE(this->current_expression); auto argument_type = TREE_TYPE(this->current_expression);
auto argument_tree = this->current_expression;
this->current_expression = NULL_TREE;
if (argument_type != integer_type_node) const char *format_number{ nullptr };
if (argument_type == integer_type_node)
{
format_number = "%d\n";
}
else if (argument_type == double_type_node)
{
format_number = "%f\n";
}
else
{ {
error_at(get_location(&argument->position()), error_at(get_location(&argument->position()),
"invalid argument of type %s for procedure %s", "invalid argument of type %s for procedure %s",
print_type(argument_type), statement->name().c_str()); print_type(argument_type), statement->name().c_str());
this->current_expression = error_mark_node;
return; return;
} }
constexpr const char *format_integer = "%d\n";
tree args[] = { tree args[] = {
build_string_literal(strlen(format_integer) + 1, format_integer), build_string_literal(strlen(format_number) + 1, format_number),
argument_tree this->current_expression
}; };
tree fndecl_type_param[] = { tree fndecl_type_param[] = {
build_pointer_type(build_qualified_type(char_type_node, TYPE_QUAL_CONST)) /* const char* */ build_pointer_type(build_qualified_type(char_type_node, TYPE_QUAL_CONST)) /* const char* */
@ -59,6 +67,7 @@ namespace gcc
tree stmt = build_call_array(integer_type_node, printf_fn, 2, args); tree stmt = build_call_array(integer_type_node, printf_fn, 2, args);
append_to_statement_list(stmt, &this->current_statements); append_to_statement_list(stmt, &this->current_statements);
this->current_expression = NULL_TREE;
} }
void generic_visitor::visit(source::program *program) void generic_visitor::visit(source::program *program)
@ -96,11 +105,26 @@ namespace gcc
cgraph_node::finalize_function(this->main_fndecl, true); cgraph_node::finalize_function(this->main_fndecl, true);
} }
void generic_visitor::visit(source::integer_literal *literal) void generic_visitor::visit(source::number_literal<std::int32_t> *literal)
{ {
this->current_expression = build_int_cst_type(integer_type_node, literal->number()); this->current_expression = build_int_cst_type(integer_type_node, literal->number());
} }
void generic_visitor::visit(source::number_literal<double> *literal)
{
REAL_VALUE_TYPE real_value1;
mpfr_t number;
mpfr_init2(number, SIGNIFICAND_BITS);
mpfr_set_d(number, literal->number(), MPFR_RNDN);
real_from_mpfr(&real_value1, number, double_type_node, MPFR_RNDN);
this->current_expression = build_real(double_type_node, real_value1);
mpfr_clear(number);
}
void generic_visitor::visit(source::boolean_literal *literal) void generic_visitor::visit(source::boolean_literal *literal)
{ {
this->current_expression = build_int_cst_type(boolean_type_node, literal->boolean()); this->current_expression = build_int_cst_type(boolean_type_node, literal->boolean());
@ -120,28 +144,37 @@ namespace gcc
tree_code operator_code = ERROR_MARK; tree_code operator_code = ERROR_MARK;
tree target_type = error_mark_node; tree target_type = error_mark_node;
if (left_type != right_type)
{
error_at(expression_location,
"invalid operands of type %s and %s for operator %s",
print_type(left_type), print_type(right_type),
elna::source::print_binary_operator(expression->operation()));
this->current_expression = error_mark_node;
return;
}
switch (expression->operation()) switch (expression->operation())
{ {
case source::binary_operator::sum: case source::binary_operator::sum:
operator_code = PLUS_EXPR; operator_code = PLUS_EXPR;
target_type = integer_type_node; target_type = left_type;
break; break;
case source::binary_operator::subtraction: case source::binary_operator::subtraction:
operator_code = MINUS_EXPR; operator_code = MINUS_EXPR;
target_type = integer_type_node; target_type = left_type;
break; break;
case source::binary_operator::division: case source::binary_operator::division:
operator_code = TRUNC_DIV_EXPR; operator_code = TRUNC_DIV_EXPR;
target_type = integer_type_node; target_type = left_type;
break; break;
case source::binary_operator::multiplication: case source::binary_operator::multiplication:
operator_code = MULT_EXPR; operator_code = MULT_EXPR;
target_type = integer_type_node; target_type = left_type;
break; break;
} }
if (operator_code != ERROR_MARK) // An arithmetic operation. if (operator_code != ERROR_MARK) // An arithmetic operation.
{ {
if (left_type != integer_type_node || right_type != integer_type_node) if (target_type != integer_type_node && target_type != double_type_node)
{ {
error_at(expression_location, error_at(expression_location,
"invalid operands of type %s and %s for operator %s", "invalid operands of type %s and %s for operator %s",
@ -178,15 +211,6 @@ namespace gcc
target_type = boolean_type_node; target_type = boolean_type_node;
break; break;
} }
if (left_type != right_type)
{
error_at(expression_location,
"invalid operands of type %s and %s for operator %s",
print_type(left_type), print_type(right_type),
elna::source::print_binary_operator(expression->operation()));
this->current_expression = error_mark_node;
return;
}
gcc_assert(operator_code != ERROR_MARK); gcc_assert(operator_code != ERROR_MARK);
gcc_assert(target_type != error_mark_node); gcc_assert(target_type != error_mark_node);
@ -234,6 +258,10 @@ namespace gcc
{ {
declaration_type = boolean_type_node; declaration_type = boolean_type_node;
} }
else if (declaration->type().base() == "Float")
{
declaration_type = double_type_node;
}
else else
{ {
error_at(get_location(&declaration->type().position()), error_at(get_location(&declaration->type().position()),
@ -385,8 +413,7 @@ namespace gcc
{ {
statement->prerequisite().accept(this); statement->prerequisite().accept(this);
if (TREE_TYPE(this->current_expression) != boolean_type_node if (TREE_TYPE(this->current_expression) != boolean_type_node)
&& TREE_TYPE(this->current_expression) != integer_type_node)
{ {
error_at(get_location(&statement->prerequisite().position()), error_at(get_location(&statement->prerequisite().position()),
"expected expression of boolean type but its type is %s", "expected expression of boolean type but its type is %s",

View File

@ -27,7 +27,8 @@ namespace gcc
public: public:
void visit(source::program *program) override; void visit(source::program *program) override;
void visit(source::call_statement *statement) override; void visit(source::call_statement *statement) override;
void visit(source::integer_literal *literal) override; void visit(source::number_literal<std::int32_t> *literal) override;
void visit(source::number_literal<double> *literal) override;
void visit(source::boolean_literal *literal) override; void visit(source::boolean_literal *literal) override;
void visit(source::binary_expression *expression) override; void visit(source::binary_expression *expression) override;
void visit(source::constant_definition *definition) override; void visit(source::constant_definition *definition) override;

View File

@ -46,7 +46,8 @@ namespace source
class unary_expression; class unary_expression;
class type_expression; class type_expression;
class variable_expression; class variable_expression;
class integer_literal; template<typename T>
class number_literal;
class boolean_literal; class boolean_literal;
/** /**
@ -68,7 +69,8 @@ namespace source
virtual void visit(unary_expression *) = 0; virtual void visit(unary_expression *) = 0;
virtual void visit(type_expression *) = 0; virtual void visit(type_expression *) = 0;
virtual void visit(variable_expression *) = 0; virtual void visit(variable_expression *) = 0;
virtual void visit(integer_literal *) = 0; virtual void visit(number_literal<std::int32_t> *) = 0;
virtual void visit(number_literal<double> *) = 0;
virtual void visit(boolean_literal *) = 0; virtual void visit(boolean_literal *) = 0;
}; };
@ -91,7 +93,8 @@ namespace source
virtual void visit(unary_expression *expression) override; virtual void visit(unary_expression *expression) override;
virtual void visit(type_expression *variable) override; virtual void visit(type_expression *variable) override;
virtual void visit(variable_expression *variable) override; virtual void visit(variable_expression *variable) override;
virtual void visit(integer_literal *number) override; virtual void visit(number_literal<std::int32_t> *number) override;
virtual void visit(number_literal<double> *) override;
virtual void visit(boolean_literal *boolean) override; virtual void visit(boolean_literal *boolean) override;
}; };
@ -267,7 +270,7 @@ namespace source
*/ */
class constant_definition : public definition class constant_definition : public definition
{ {
std::unique_ptr<integer_literal> m_body; std::unique_ptr<number_literal<std::int32_t>> m_body;
public: public:
/** /**
@ -276,10 +279,10 @@ namespace source
* \param body Constant value. * \param body Constant value.
*/ */
constant_definition(const struct position position, const std::string& identifier, constant_definition(const struct position position, const std::string& identifier,
std::unique_ptr<integer_literal>&& body); std::unique_ptr<number_literal<std::int32_t>>&& body);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
integer_literal& body(); number_literal<std::int32_t>& body();
}; };
/** /**
@ -427,15 +430,26 @@ namespace source
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
}; };
class integer_literal : public expression template<typename T>
class number_literal : public expression
{ {
std::int32_t m_number; T m_number;
public: public:
integer_literal(const struct position position, const std::int32_t value); number_literal(const struct position position, const T value)
virtual void accept(parser_visitor *visitor) override; : expression(position), m_number(value)
{
}
std::int32_t number() const noexcept; virtual void accept(parser_visitor *visitor) override
{
visitor->visit(this);
}
T number() const noexcept
{
return m_number;
}
}; };
class boolean_literal : public expression class boolean_literal : public expression

View File

@ -95,7 +95,11 @@ namespace source
{ {
} }
void empty_visitor::visit(integer_literal *number) void empty_visitor::visit(number_literal<std::int32_t> *number)
{
}
void empty_visitor::visit(number_literal<double> *number)
{ {
} }
@ -214,7 +218,7 @@ namespace source
} }
constant_definition::constant_definition(const struct position position, const std::string& identifier, constant_definition::constant_definition(const struct position position, const std::string& identifier,
std::unique_ptr<integer_literal>&& body) std::unique_ptr<number_literal<std::int32_t>>&& body)
: definition(position, identifier), m_body(std::move(body)) : definition(position, identifier), m_body(std::move(body))
{ {
} }
@ -224,7 +228,7 @@ namespace source
visitor->visit(this); visitor->visit(this);
} }
integer_literal& constant_definition::body() number_literal<std::int32_t>& constant_definition::body()
{ {
return *m_body; return *m_body;
} }
@ -290,21 +294,6 @@ namespace source
visitor->visit(this); visitor->visit(this);
} }
integer_literal::integer_literal(const struct position position, const std::int32_t value)
: expression(position), m_number(value)
{
}
void integer_literal::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
std::int32_t integer_literal::number() const noexcept
{
return m_number;
}
boolean_literal::boolean_literal(const struct position position, const bool value) boolean_literal::boolean_literal(const struct position position, const bool value)
: expression(position), m_boolean(value) : expression(position), m_boolean(value)
{ {

View File

@ -73,6 +73,9 @@ false {
[0-9]+ { [0-9]+ {
return yy::parser::make_NUMBER(strtol(yytext, NULL, 10), this->location); return yy::parser::make_NUMBER(strtol(yytext, NULL, 10), this->location);
} }
[0-9]+\.[0-9] {
return yy::parser::make_FLOAT(strtof(yytext, NULL), this->location);
}
\( { \( {
return yy::parser::make_LEFT_PAREN(this->location); return yy::parser::make_LEFT_PAREN(this->location);
} }

View File

@ -58,6 +58,7 @@
%token <std::string> IDENTIFIER "identifier" %token <std::string> IDENTIFIER "identifier"
%token <std::int32_t> NUMBER "number" %token <std::int32_t> NUMBER "number"
%token <float> FLOAT "float"
%token <bool> BOOLEAN %token <bool> BOOLEAN
%token IF WHILE DO %token IF WHILE DO
%token CONST VAR PROCEDURE %token CONST VAR PROCEDURE
@ -70,7 +71,8 @@
%precedence THEN %precedence THEN
%precedence ELSE %precedence ELSE
%type <std::unique_ptr<elna::source::integer_literal>> integer_literal; %type <std::unique_ptr<elna::source::number_literal<std::int32_t>>> integer_literal;
%type <std::unique_ptr<elna::source::number_literal<double>>> float_literal;
%type <std::unique_ptr<elna::source::boolean_literal>> boolean_literal; %type <std::unique_ptr<elna::source::boolean_literal>> boolean_literal;
%type <std::unique_ptr<elna::source::constant_definition>> constant_definition; %type <std::unique_ptr<elna::source::constant_definition>> constant_definition;
%type <std::vector<std::unique_ptr<elna::source::constant_definition>>> constant_definition_part constant_definitions; %type <std::vector<std::unique_ptr<elna::source::constant_definition>>> constant_definition_part constant_definitions;
@ -141,7 +143,11 @@ procedure_definition_part:
| procedure_definitions { std::swap($$, $1); } | procedure_definitions { std::swap($$, $1); }
integer_literal: NUMBER integer_literal: NUMBER
{ {
$$ = std::make_unique<elna::source::integer_literal>(elna::source::make_position(@1), $1); $$ = std::make_unique<elna::source::number_literal<std::int32_t>>(elna::source::make_position(@1), $1);
};
float_literal: FLOAT
{
$$ = std::make_unique<elna::source::number_literal<double>>(elna::source::make_position(@1), $1);
}; };
boolean_literal: BOOLEAN boolean_literal: BOOLEAN
{ {
@ -179,6 +185,7 @@ if_statement:
} }
pointer: pointer:
integer_literal { $$ = std::move($1); } integer_literal { $$ = std::move($1); }
| float_literal { $$ = std::move($1); }
| boolean_literal { $$ = std::move($1); } | boolean_literal { $$ = std::move($1); }
| variable_expression { $$ = std::move($1); } | variable_expression { $$ = std::move($1); }
| LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); } | LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); }