Read the input filename from the command line
This commit is contained in:
@ -36,10 +36,6 @@ namespace gcc
|
||||
{
|
||||
return "Char";
|
||||
}
|
||||
else if (is_string_type(type))
|
||||
{
|
||||
return "String";
|
||||
}
|
||||
else if (is_pointer_type(type))
|
||||
{
|
||||
return "pointer";
|
||||
|
@ -86,16 +86,44 @@ namespace gcc
|
||||
|| type == this->symbol_map->lookup("Word")->payload;
|
||||
}
|
||||
|
||||
bool generic_visitor::is_numeric_type(tree type)
|
||||
{
|
||||
return is_integral_type(type)
|
||||
|| type == this->symbol_map->lookup("Float")->payload;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::program *program)
|
||||
{
|
||||
for (const auto definition : program->value_definitions)
|
||||
for (const auto& type_definition : program->type_definitions)
|
||||
{
|
||||
definition->accept(this);
|
||||
type_definition->accept(this);
|
||||
}
|
||||
for (const auto& constant : program->type_definitions)
|
||||
for (const auto constant : program->constants)
|
||||
{
|
||||
constant->accept(this);
|
||||
}
|
||||
for (const auto declaration : program->variables)
|
||||
{
|
||||
tree declaration_type = build_type(declaration->type());
|
||||
gcc_assert(declaration_type != NULL_TREE);
|
||||
|
||||
auto declaration_location = get_location(&declaration->position());
|
||||
tree declaration_tree = build_decl(declaration_location, VAR_DECL,
|
||||
get_identifier(declaration->identifier().c_str()), declaration_type);
|
||||
auto result = this->symbol_map->enter(declaration->identifier(), boot::make_info(declaration_tree));
|
||||
|
||||
if (result)
|
||||
{
|
||||
TREE_STATIC(declaration_tree) = 1;
|
||||
varpool_node::get_create(declaration_tree);
|
||||
varpool_node::finalize_decl(declaration_tree);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at(declaration_location, "variable '%s' already declared in this scope",
|
||||
declaration->identifier().c_str());
|
||||
}
|
||||
}
|
||||
std::array<tree, 2> parameter_types{
|
||||
integer_type_node,
|
||||
build_pointer_type(build_pointer_type(char_type_node))
|
||||
@ -278,49 +306,57 @@ namespace gcc
|
||||
this->current_expression = build_string_literal(string->string().size() + 1, string->string().c_str());
|
||||
}
|
||||
|
||||
void generic_visitor::build_binary_operation(bool condition, boot::binary_expression *expression,
|
||||
tree_code operator_code, tree left, tree right, tree target_type)
|
||||
tree generic_visitor::build_arithmetic_operation(boot::binary_expression *expression,
|
||||
tree_code operator_code, tree left, tree right)
|
||||
{
|
||||
auto expression_location = get_location(&expression->position());
|
||||
auto left_type = TREE_TYPE(left);
|
||||
auto right_type = TREE_TYPE(right);
|
||||
return build_binary_operation(is_numeric_type(TREE_TYPE(left)),
|
||||
expression, operator_code, left, right, TREE_TYPE(left));
|
||||
}
|
||||
|
||||
if (condition)
|
||||
{
|
||||
this->current_expression = build2_loc(expression_location,
|
||||
operator_code, target_type, left, right);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at(expression_location,
|
||||
"invalid operands of type %s and %s for operator %s",
|
||||
print_type(left_type), print_type(right_type),
|
||||
elna::boot::print_binary_operator(expression->operation()));
|
||||
this->current_expression = error_mark_node;
|
||||
}
|
||||
tree generic_visitor::build_comparison_operation(boot::binary_expression *expression,
|
||||
tree_code operator_code, tree left, tree right)
|
||||
{
|
||||
return build_binary_operation(is_numeric_type(TREE_TYPE(left)) || is_pointer_type(TREE_TYPE(left)),
|
||||
expression, operator_code, left, right, this->symbol_map->lookup("Bool")->payload);
|
||||
}
|
||||
|
||||
tree generic_visitor::build_logic_operation(boot::binary_expression *expression,
|
||||
tree_code operator_code, tree left, tree right)
|
||||
{
|
||||
auto symbol = this->symbol_map->lookup("Bool");
|
||||
|
||||
return build_binary_operation(TREE_TYPE(left) == symbol->payload,
|
||||
expression, operator_code, left, right, symbol->payload);
|
||||
}
|
||||
|
||||
tree generic_visitor::build_equality_operation(boot::binary_expression *expression,
|
||||
tree_code operator_code, tree left, tree right)
|
||||
{
|
||||
return build_binary_operation(true, expression,
|
||||
operator_code, left, right, this->symbol_map->lookup("Bool")->payload);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::binary_expression *expression)
|
||||
{
|
||||
expression->lhs().accept(this);
|
||||
auto left = this->current_expression;
|
||||
auto left_type = TREE_TYPE(left);
|
||||
tree left = this->current_expression;
|
||||
tree left_type = TREE_TYPE(left);
|
||||
|
||||
expression->rhs().accept(this);
|
||||
auto right = this->current_expression;
|
||||
auto right_type = TREE_TYPE(right);
|
||||
tree right = this->current_expression;
|
||||
tree right_type = TREE_TYPE(right);
|
||||
|
||||
auto expression_location = get_location(&expression->position());
|
||||
tree_code operator_code = ERROR_MARK;
|
||||
tree target_type = error_mark_node;
|
||||
location_t expression_location = get_location(&expression->position());
|
||||
|
||||
if (is_pointer_type(left_type) && is_integral_type(right_type)
|
||||
&& expression->operation() == boot::binary_operator::sum)
|
||||
if (is_pointer_type(left_type) && is_integral_type(right_type))
|
||||
{
|
||||
tree convert_expression = build1_loc(expression_location, CONVERT_EXPR,
|
||||
sizetype, right);
|
||||
this->current_expression = build2_loc(expression_location,
|
||||
POINTER_PLUS_EXPR, left_type, left, convert_expression);
|
||||
this->current_expression = do_pointer_arithmetic(expression->operation(), left, right);
|
||||
if (this->current_expression == error_mark_node)
|
||||
{
|
||||
error_at(expression_location,
|
||||
"invalid operation %s on a pointer and an integral type",
|
||||
boot::print_binary_operator(expression->operation()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (left_type != right_type)
|
||||
@ -335,87 +371,45 @@ namespace gcc
|
||||
switch (expression->operation())
|
||||
{
|
||||
case boot::binary_operator::sum:
|
||||
operator_code = PLUS_EXPR;
|
||||
target_type = left_type;
|
||||
this->current_expression = build_arithmetic_operation(expression, PLUS_EXPR, left, right);
|
||||
break;
|
||||
case boot::binary_operator::subtraction:
|
||||
operator_code = MINUS_EXPR;
|
||||
target_type = left_type;
|
||||
this->current_expression = build_arithmetic_operation(expression, MINUS_EXPR, left, right);
|
||||
break;
|
||||
case boot::binary_operator::division:
|
||||
operator_code = TRUNC_DIV_EXPR;
|
||||
target_type = left_type;
|
||||
this->current_expression = build_arithmetic_operation(expression, TRUNC_DIV_EXPR, left, right);
|
||||
break;
|
||||
case boot::binary_operator::remainder:
|
||||
operator_code = TRUNC_MOD_EXPR;
|
||||
target_type = left_type;
|
||||
this->current_expression = build_arithmetic_operation(expression, TRUNC_MOD_EXPR, left, right);
|
||||
break;
|
||||
case boot::binary_operator::multiplication:
|
||||
operator_code = MULT_EXPR;
|
||||
target_type = left_type;
|
||||
this->current_expression = build_arithmetic_operation(expression, MULT_EXPR, left, right);
|
||||
break;
|
||||
case boot::binary_operator::less:
|
||||
operator_code = LT_EXPR;
|
||||
target_type = boolean_type_node;
|
||||
this->current_expression = build_comparison_operation(expression, LT_EXPR, left, right);
|
||||
break;
|
||||
case boot::binary_operator::greater:
|
||||
operator_code = GT_EXPR;
|
||||
target_type = boolean_type_node;
|
||||
this->current_expression = build_comparison_operation(expression, GT_EXPR, left, right);
|
||||
break;
|
||||
case boot::binary_operator::less_equal:
|
||||
operator_code = LE_EXPR;
|
||||
target_type = boolean_type_node;
|
||||
this->current_expression = build_comparison_operation(expression, LE_EXPR, left, right);
|
||||
break;
|
||||
case boot::binary_operator::greater_equal:
|
||||
operator_code = GE_EXPR;
|
||||
target_type = boolean_type_node;
|
||||
this->current_expression = build_comparison_operation(expression, GE_EXPR, left, right);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (operator_code != ERROR_MARK) // An arithmetic operation.
|
||||
{
|
||||
build_binary_operation(is_integral_type(left_type) || left_type == double_type_node,
|
||||
expression, operator_code, left, right, target_type);
|
||||
return;
|
||||
}
|
||||
switch (expression->operation())
|
||||
{
|
||||
case boot::binary_operator::conjunction:
|
||||
operator_code = TRUTH_ANDIF_EXPR;
|
||||
target_type = boolean_type_node;
|
||||
this->current_expression = build_logic_operation(expression, TRUTH_ANDIF_EXPR, left, right);
|
||||
break;
|
||||
case boot::binary_operator::disjunction:
|
||||
operator_code = TRUTH_ORIF_EXPR;
|
||||
target_type = boolean_type_node;
|
||||
this->current_expression = build_logic_operation(expression, TRUTH_ORIF_EXPR, left, right);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (operator_code != ERROR_MARK) // A logical operation.
|
||||
{
|
||||
build_binary_operation(left_type == boolean_type_node,
|
||||
expression, operator_code, left, right, target_type);
|
||||
return;
|
||||
}
|
||||
switch (expression->operation())
|
||||
{
|
||||
case boot::binary_operator::equals:
|
||||
operator_code = EQ_EXPR;
|
||||
target_type = boolean_type_node;
|
||||
this->current_expression = build_equality_operation(expression, EQ_EXPR, left, right);
|
||||
break;
|
||||
case boot::binary_operator::not_equals:
|
||||
operator_code = NE_EXPR;
|
||||
target_type = boolean_type_node;
|
||||
break;
|
||||
default:
|
||||
this->current_expression = build_equality_operation(expression, NE_EXPR, left, right);
|
||||
break;
|
||||
}
|
||||
gcc_assert(operator_code != ERROR_MARK);
|
||||
gcc_assert(target_type != error_mark_node);
|
||||
|
||||
this->current_expression = build2_loc(expression_location,
|
||||
operator_code, target_type, left, right);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::unary_expression *expression)
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include "elna/gcc/elna-tree.h"
|
||||
#include "elna/gcc/elna-diagnostic.h"
|
||||
|
||||
#include "stor-layout.h"
|
||||
#include "fold-const.h"
|
||||
#include "diagnostic-core.h"
|
||||
|
||||
tree elna_global_trees[ELNA_TI_MAX];
|
||||
|
||||
@ -20,12 +23,6 @@ namespace gcc
|
||||
return TREE_CODE(type) == POINTER_TYPE;
|
||||
}
|
||||
|
||||
bool is_string_type(tree type)
|
||||
{
|
||||
return is_pointer_type(type)
|
||||
&& TYPE_MAIN_VARIANT(TREE_TYPE(type)) == char_type_node;
|
||||
}
|
||||
|
||||
tree tree_chain_base::head()
|
||||
{
|
||||
return first;
|
||||
@ -81,5 +78,43 @@ namespace gcc
|
||||
|
||||
return initial_table;
|
||||
}
|
||||
|
||||
tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right)
|
||||
{
|
||||
tree result = error_mark_node;
|
||||
tree convert_expression = fold_convert(sizetype, right);
|
||||
|
||||
if (binary_operator == boot::binary_operator::sum)
|
||||
{
|
||||
result = fold_build2(POINTER_PLUS_EXPR, TREE_TYPE(left), left, convert_expression);
|
||||
}
|
||||
else if (binary_operator == boot::binary_operator::subtraction)
|
||||
{
|
||||
convert_expression = fold_build1(NEGATE_EXPR, sizetype, convert_expression);
|
||||
result = fold_build2(POINTER_PLUS_EXPR, TREE_TYPE(left), left, convert_expression);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
tree build_binary_operation(bool condition, boot::binary_expression *expression,
|
||||
tree_code operator_code, tree left, tree right, tree target_type)
|
||||
{
|
||||
location_t expression_location = get_location(&expression->position());
|
||||
tree left_type = TREE_TYPE(left);
|
||||
tree right_type = TREE_TYPE(right);
|
||||
|
||||
if (condition)
|
||||
{
|
||||
return build2_loc(expression_location, operator_code, target_type, left, right);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at(expression_location,
|
||||
"invalid operands of type %s and %s for operator %s",
|
||||
print_type(left_type), print_type(right_type),
|
||||
elna::boot::print_binary_operator(expression->operation()));
|
||||
return error_mark_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user