diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index 852463a..c6ba2df 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -7,6 +7,8 @@ #include "stringpool.h" #include "diagnostic.h" #include "realmpfr.h" +#include "stor-layout.h" +#include namespace elna { @@ -357,6 +359,38 @@ namespace gcc return build_array_type(base_type, range_type); } + else if (source::record_type_expression *record_type = type.is_record()) + { + std::set field_names; + tree record_type_node = make_node(RECORD_TYPE); + tree_chain record_chain; + + for (auto& field : record_type->fields()) + { + if (field_names.find(field.first) != field_names.cend()) + { + error_at(get_location(&field.second->position()), "repeated field name"); + return error_mark_node; + } + field_names.insert(field.first); + + tree field_type = build_type(*field.second); + if (field_type == NULL_TREE || field_type == error_mark_node) + { + return field_type; + } + tree field_declaration = build_decl(get_location(&field.second->position()), + FIELD_DECL, get_identifier(field.first.c_str()), field_type); + TREE_ADDRESSABLE(field_declaration) = 1; + DECL_CONTEXT(field_declaration) = record_type_node; + + record_chain.append(field_declaration); + } + TYPE_FIELDS(record_type_node) = record_chain.head(); + layout_type(record_type_node); + + return record_type_node; + } return NULL_TREE; } diff --git a/gcc/elna-tree.cc b/gcc/elna-tree.cc index 9b0be60..ffb8a69 100644 --- a/gcc/elna-tree.cc +++ b/gcc/elna-tree.cc @@ -29,6 +29,12 @@ namespace gcc return TREE_CODE(type) == ARRAY_TYPE; } + bool is_record_type(tree type) + { + gcc_assert(TYPE_P(type)); + return TREE_CODE(type) == RECORD_TYPE; + } + tree tree_chain_base::head() { return first; diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h index 031e786..017777f 100644 --- a/include/elna/gcc/elna-tree.h +++ b/include/elna/gcc/elna-tree.h @@ -4,6 +4,7 @@ #include "system.h" #include "coretypes.h" #include "tree.h" +#include "tree.h" enum elna_tree_index { @@ -24,6 +25,7 @@ namespace gcc void init_ttree(); bool is_string_type(tree type); bool is_array_type(tree type); + bool is_record_type(tree type); class tree_chain_base { diff --git a/source/parser.yy b/source/parser.yy index db04bdb..25f8899 100644 --- a/source/parser.yy +++ b/source/parser.yy @@ -79,14 +79,13 @@ %type character_literal; %type string_literal; %type constant_definition; -%type > constant_definition_part constant_definitions; +%type > constant_part constant_definitions; %type variable_declaration; -%type > variable_declarations variable_declaration_part +%type > variable_declarations variable_part formal_parameter_list; %type type_expression; -%type expression pointer summand factor address comparand; +%type expression pointer summand factor comparand; %type > expressions actual_parameter_list; -%type variable_expression; %type designator_expression; %type compound_statement; %type assign_statement; @@ -96,13 +95,13 @@ %type statement; %type > statements optional_statements; %type procedure_definition; -%type > procedure_definitions procedure_definition_part; +%type > procedure_definitions procedure_part; %type type_definition; -%type > type_definitions type_definition_part; +%type > type_definitions type_part; %type block; %% program: - type_definition_part constant_definition_part procedure_definition_part variable_declaration_part statement DOT + type_part constant_part procedure_part variable_part compound_statement DOT { std::vector definitions($1.size() + $2.size() + $3.size()); std::vector::iterator definition = definitions.begin(); @@ -122,7 +121,7 @@ program: driver.tree = std::make_unique(elna::source::position{}, std::move(definitions), std::move($4), std::move($5)); } -block: constant_definition_part variable_declaration_part statement +block: constant_part variable_part statement { std::vector definitions($1.size()); std::vector::iterator definition = definitions.begin(); @@ -148,7 +147,7 @@ procedure_definitions: $$.emplace($$.cbegin(), std::move($1)); } | procedure_definition { $$.emplace_back(std::move($1)); } -procedure_definition_part: +procedure_part: /* no procedure definitions */ {} | procedure_definitions { std::swap($$, $1); } integer_literal: INTEGER @@ -221,20 +220,13 @@ summand: $$ = new elna::source::binary_expression(elna::source::make_position(@1), $1, $3, '/'); } -address: - pointer HAT - { - $$ = new elna::source::unary_expression(elna::source::make_position(@1), - $1, '^'); - } - | pointer { $$ = $1; } factor: - AT address + AT pointer { $$ = new elna::source::unary_expression(elna::source::make_position(@1), $2, '@'); } - | address { $$ = $1; } + | pointer { $$ = $1; } comparand: summand PLUS summand { @@ -286,14 +278,23 @@ expressions: $$.emplace($$.cbegin(), $1); } | expression { $$.emplace_back(std::move($1)); } -variable_expression: - IDENTIFIER { $$ = new elna::source::variable_expression(elna::source::make_position(@1), $1); } designator_expression: - variable_expression LEFT_SQUARE expression RIGHT_SQUARE + designator_expression LEFT_SQUARE expression RIGHT_SQUARE { $$ = new elna::source::array_access_expression(elna::source::make_position(@1), $1, $3); } - | variable_expression { $$ = $1; } + | designator_expression DOT IDENTIFIER + { + $$ = new elna::source::field_access_expression(elna::source::make_position(@1), $1, $3); + } + | designator_expression HAT + { + $$ = new elna::source::dereference_expression(elna::source::make_position(@1), $1); + } + | IDENTIFIER + { + $$ = new elna::source::variable_expression(elna::source::make_position(@1), $1); + } statement: compound_statement { $$ = $1; } | assign_statement { $$ = $1; } @@ -334,7 +335,7 @@ variable_declarations: $$.emplace($$.cbegin(), $1); } | variable_declaration { $$.emplace_back(std::move($1)); } -variable_declaration_part: +variable_part: /* no variable declarations */ {} | VAR variable_declarations SEMICOLON { std::swap($$, $2); } constant_definition: IDENTIFIER EQUALS integer_literal @@ -348,7 +349,7 @@ constant_definitions: $$.emplace($$.cbegin(), std::move($1)); } | constant_definition { $$.emplace_back(std::move($1)); } -constant_definition_part: +constant_part: /* no constant definitions */ {} | CONST constant_definitions SEMICOLON { std::swap($$, $2); } type_definition: IDENTIFIER EQUALS type_expression @@ -362,7 +363,7 @@ type_definitions: $$.emplace($$.cbegin(), std::move($1)); } | type_definition { $$.emplace_back(std::move($1)); } -type_definition_part: +type_part: /* no type definitions */ {} | TYPE type_definitions SEMICOLON { std::swap($$, $2); } formal_parameter_list: