diff --git a/gcc/Make-lang.in b/gcc/Make-lang.in index ae52ac1..5d4af02 100644 --- a/gcc/Make-lang.in +++ b/gcc/Make-lang.in @@ -24,6 +24,7 @@ elna_OBJS = \ elna/elna-generic.o \ elna/elna-convert.o \ elna/elna-diagnostic.o \ + elna/elna-tree.o \ elna/ast.o \ elna/driver.o \ elna/lexer.o \ diff --git a/gcc/elna-diagnostic.cc b/gcc/elna-diagnostic.cc index c41592a..e388310 100644 --- a/gcc/elna-diagnostic.cc +++ b/gcc/elna-diagnostic.cc @@ -1,4 +1,5 @@ #include "elna/gcc/elna-diagnostic.h" +#include "elna/gcc/elna-tree.h" namespace elna { @@ -23,6 +24,10 @@ namespace gcc { return "Boolean"; } + else if (type == enumeral_node) + { + return "Enum"; + } else { return "<>"; diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index ca8bc87..ac24dcd 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -1,4 +1,5 @@ #include "elna/gcc/elna-generic.h" +#include "elna/gcc/elna-tree.h" #include "elna/gcc/elna-diagnostic.h" #include "input.h" @@ -97,12 +98,12 @@ namespace gcc void generic_visitor::visit(source::integer_literal *literal) { - 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::boolean_literal *literal) { - current_expression = build_int_cst_type(boolean_type_node, literal->boolean()); + this->current_expression = build_int_cst_type(boolean_type_node, literal->boolean()); } void generic_visitor::visit(source::binary_expression *expression) @@ -179,6 +180,34 @@ namespace gcc operator_code, integer_type_node, left, right); } + void generic_visitor::visit(source::constant_definition *definition) + { + location_t definition_location = get_location(&definition->position()); + tree definition_tree = build_decl(definition_location, CONST_DECL, + get_identifier(definition->identifier().c_str()), integer_type_node); + auto result = this->symbol_map.insert({ definition->identifier(), definition_tree }); + + if (result.second) + { + definition->body().accept(this); + + DECL_INITIAL(definition_tree) = build_int_cst_type(integer_type_node, definition->body().number()); + TREE_CONSTANT(definition_tree) = 1; + TREE_READONLY(definition_tree) = 1; + + auto declaration_statement = build1_loc(definition_location, DECL_EXPR, + void_type_node, definition_tree); + append_to_statement_list(declaration_statement, &this->current_statements); + } + else + { + error_at(definition_location, + "variable '%s' already declared in this scope", + definition->identifier().c_str()); + } + this->current_expression = NULL_TREE; + } + void generic_visitor::visit(source::declaration *declaration) { if (declaration->type().base() != "Int" && declaration->type().base() != "Bool") @@ -236,9 +265,16 @@ namespace gcc } statement->rvalue().accept(this); + if (TREE_CODE(lvalue->second) == CONST_DECL) + { + error_at(statement_location, "cannot modify constant '%s'", + statement->lvalue().c_str()); + this->current_expression = error_mark_node; + return; + } if (TREE_TYPE(this->current_expression) != TREE_TYPE(lvalue->second)) { - error_at(get_location(&statement->position()), + error_at(statement_location, "cannot assign value of type %s to variable '%s' of type %s", print_type(TREE_TYPE(this->current_expression)), statement->lvalue().c_str(), diff --git a/gcc/elna-tree.cc b/gcc/elna-tree.cc new file mode 100644 index 0000000..b151e82 --- /dev/null +++ b/gcc/elna-tree.cc @@ -0,0 +1,3 @@ +#include "elna/gcc/elna-tree.h" + +tree elna_global_trees[ELNA_TI_MAX]; diff --git a/gcc/elna1.cc b/gcc/elna1.cc index 574b196..b93b322 100644 --- a/gcc/elna1.cc +++ b/gcc/elna1.cc @@ -16,6 +16,7 @@ #include #include +#include "elna/gcc/elna-tree.h" #include "elna/gcc/elna-generic.h" #include "elna/gcc/elna-diagnostic.h" #include "parser.hh" @@ -64,17 +65,18 @@ struct GTY (()) language_function static bool elna_langhook_init(void) { - build_common_tree_nodes (false); + build_common_tree_nodes(false); + enumeral_node = make_node(ENUMERAL_TYPE); /* I don't know why this has to be done explicitly. */ - void_list_node = build_tree_list (NULL_TREE, void_type_node); + void_list_node = build_tree_list(NULL_TREE, void_type_node); - build_common_builtin_nodes (); + build_common_builtin_nodes(); return true; } -static void elna_parse_file (const char *filename) +static void elna_parse_file(const char *filename) { std::ifstream file{ filename, std::ios::in }; @@ -106,12 +108,11 @@ static void elna_parse_file (const char *filename) linemap_add(line_table, LC_LEAVE, 0, NULL, 0); } -static void -elna_langhook_parse_file (void) +static void elna_langhook_parse_file(void) { - for (int i = 0; i < num_in_fnames; i++) + for (int i = 0; i < num_in_fnames; i++) { - elna_parse_file (in_fnames[i]); + elna_parse_file (in_fnames[i]); } } @@ -161,39 +162,32 @@ elna_langhook_type_for_mode (enum machine_mode mode, int unsignedp) return NULL; } -static tree -elna_langhook_type_for_size (unsigned int bits ATTRIBUTE_UNUSED, - int unsignedp ATTRIBUTE_UNUSED) +static tree elna_langhook_type_for_size(unsigned int bits ATTRIBUTE_UNUSED, + int unsignedp ATTRIBUTE_UNUSED) { - gcc_unreachable (); - return NULL; + gcc_unreachable(); } /* Record a builtin function. We just ignore builtin functions. */ -static tree -elna_langhook_builtin_function (tree decl) +static tree elna_langhook_builtin_function(tree decl) { - return decl; + return decl; } -static bool -elna_langhook_global_bindings_p (void) +static bool elna_langhook_global_bindings_p(void) { - gcc_unreachable (); - return true; + gcc_unreachable(); } -static tree -elna_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED) +static tree elna_langhook_pushdecl(tree decl ATTRIBUTE_UNUSED) { - gcc_unreachable (); + gcc_unreachable(); } -static tree -elna_langhook_getdecls (void) +static tree elna_langhook_getdecls(void) { - return NULL; + return NULL; } #undef LANG_HOOKS_NAME diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index 4254f02..c5ce340 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -30,6 +30,7 @@ namespace gcc void visit(source::integer_literal *literal) override; void visit(source::boolean_literal *literal) override; void visit(source::binary_expression *expression) override; + void visit(source::constant_definition *definition) override; void visit(source::declaration *declaration) override; void visit(source::variable_expression *expression) override; void visit(source::assign_statement *statement) override; diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h new file mode 100644 index 0000000..883f2a2 --- /dev/null +++ b/include/elna/gcc/elna-tree.h @@ -0,0 +1,16 @@ +#pragma once + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" + +enum elna_tree_index +{ + ELNA_TI_ENUMERAL_TYPE, + ELNA_TI_MAX +}; + +extern GTY(()) tree elna_global_trees[ELNA_TI_MAX]; + +#define enumeral_node elna_global_trees[ELNA_TI_ENUMERAL_TYPE]