diff --git a/README.md b/README.md index 58f49a7..e0f9b5d 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,8 @@ integer = digit { digit }; float = integer "." integer; boolean = "true" | "false"; +literal = integer | float | boolean | "'" character "'" | """ { character } """; + program = [ "type" type_definitions ";" ] [ constant_part ] { procedure_definition } @@ -64,11 +66,7 @@ comparand = summand { ("+" | "-") summand }; summand = factor { ("*" | "/") factor }; factor = pointer { unary_prefix pointer }; -pointer = integer - | float - | boolean - | "'" character "'" - | """ { character } """ +pointer = literal | designator_expression { $$ = $1; } | "(" expression ")"; diff --git a/example.elna b/example.elna index 3d04501..c2b216c 100644 --- a/example.elna +++ b/example.elna @@ -103,6 +103,22 @@ begin writei("Test not false") end; +proc test_param(d: Int, e: Int); +begin + writei(""); + writei("Test param"); + writei(d); + writei(e) +end; + +proc test_const_char(); +const x = 'u'; +begin + writei(""); + writei("Test constant character"); + writei(x) +end; + begin test_primitive(); test_string(); @@ -111,5 +127,7 @@ begin test_record(); test_const(); test_if(); - test_not() + test_not(); + test_param(8, 7); + test_const_char() end. diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index 0cfbf47..988c82f 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -87,10 +87,17 @@ namespace gcc } else if (symbol) { - tree fndecl_type = build_function_type_list(integer_type_node, NULL_TREE); + tree fndecl_type = build_function_type(void_type_node, TYPE_ARG_TYPES(symbol->payload)); tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol->payload); - tree stmt = build_call_nary(integer_type_node, printf_fn, 0); + std::vector arguments(statement->arguments().size()); + for (std::size_t i = 0; i < statement->arguments().size(); ++i) + { + statement->arguments().at(i)->accept(this); + arguments[i] = this->current_expression; + } + tree stmt = build_call_array_loc(get_location(&statement->position()), + void_type_node, printf_fn, arguments.size(), arguments.data()); append_to_statement_list(stmt, &this->current_statements); this->current_expression = NULL_TREE; @@ -122,7 +129,7 @@ namespace gcc tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(main_fndecl), build_int_cst_type(integer_type_node, 0)); tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result); - + enter_scope(); for (const auto& definition : program->value_definitions) @@ -133,29 +140,29 @@ namespace gcc append_to_statement_list(return_stmt, &this->current_statements); tree_symbol_mapping mapping = leave_scope(); - + BLOCK_SUPERCONTEXT(mapping.block()) = this->main_fndecl; DECL_INITIAL(this->main_fndecl) = mapping.block(); DECL_SAVED_TREE(this->main_fndecl) = mapping.bind_expression(); - + DECL_EXTERNAL(this->main_fndecl) = 0; DECL_PRESERVE_P(this->main_fndecl) = 1; - + gimplify_function_tree(this->main_fndecl); - + cgraph_node::finalize_function(this->main_fndecl, true); } void generic_visitor::visit(source::procedure_definition *definition) { - tree *parameter_types = reinterpret_cast(xmalloc(definition->parameters().size() * sizeof(tree))); + std::vector parameter_types(definition->parameters().size()); for (std::size_t i = 0; i < definition->parameters().size(); ++i) { parameter_types[i] = build_type(definition->parameters().at(i)->type()); } tree declaration_type = build_function_type_array(void_type_node, - definition->parameters().size(), parameter_types); + definition->parameters().size(), parameter_types.data()); this->main_fndecl = build_fn_decl(definition->identifier().c_str(), declaration_type); this->symbol_map->enter(definition->identifier(), source::make_info(this->main_fndecl)); @@ -166,6 +173,21 @@ namespace gcc DECL_RESULT(this->main_fndecl) = resdecl; enter_scope(); + + gcc::tree_chain argument_chain; + for (std::size_t i = 0; i < definition->parameters().size(); ++i) + { + auto parameter = definition->parameters().at(i); + + tree declaration_tree = build_decl(get_location(¶meter->position()), PARM_DECL, + get_identifier(parameter->identifier().c_str()), parameter_types[i]); + DECL_CONTEXT(declaration_tree) = this->main_fndecl; + DECL_ARG_TYPE(declaration_tree) = parameter_types[i]; + + this->symbol_map->enter(parameter->identifier(), source::make_info(declaration_tree)); + argument_chain.append(declaration_tree); + } + DECL_ARGUMENTS(this->main_fndecl) = argument_chain.head(); definition->body().accept(this); tree_symbol_mapping mapping = leave_scope(); @@ -180,8 +202,6 @@ namespace gcc gimplify_function_tree(this->main_fndecl); cgraph_node::finalize_function(this->main_fndecl, true); - - free(parameter_types); } void generic_visitor::enter_scope() @@ -227,9 +247,9 @@ namespace gcc this->current_expression = build_int_cst_type(boolean_type_node, boolean->number()); } - void generic_visitor::visit(source::char_literal *character) + void generic_visitor::visit(source::number_literal *character) { - this->current_expression = build_int_cstu(elna_char_type_node, character->character()); + this->current_expression = build_int_cstu(elna_char_type_node, character->number()); } void generic_visitor::visit(source::string_literal *string) @@ -385,15 +405,15 @@ namespace gcc void generic_visitor::visit(source::constant_definition *definition) { location_t definition_location = get_location(&definition->position()); + definition->body().accept(this); + tree definition_tree = build_decl(definition_location, CONST_DECL, - get_identifier(definition->identifier().c_str()), integer_type_node); + get_identifier(definition->identifier().c_str()), TREE_TYPE(this->current_expression)); auto result = this->symbol_map->enter(definition->identifier(), source::make_info(definition_tree)); if (result) { - definition->body().accept(this); - - DECL_INITIAL(definition_tree) = build_int_cst_type(integer_type_node, definition->body().number()); + DECL_INITIAL(definition_tree) = this->current_expression; TREE_CONSTANT(definition_tree) = 1; TREE_READONLY(definition_tree) = 1; diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index 7019bc9..96d6856 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -43,7 +43,7 @@ namespace gcc void visit(source::number_literal *literal) override; void visit(source::number_literal *literal) override; void visit(source::number_literal *boolean) override; - void visit(source::char_literal *character) override; + void visit(source::number_literal *character) override; void visit(source::string_literal *string) override; void visit(source::binary_expression *expression) override; void visit(source::unary_expression *expression) override; diff --git a/include/elna/source/ast.h b/include/elna/source/ast.h index b30ccb0..99ad8cc 100644 --- a/include/elna/source/ast.h +++ b/include/elna/source/ast.h @@ -90,7 +90,7 @@ namespace source virtual void visit(number_literal *) = 0; virtual void visit(number_literal *) = 0; virtual void visit(number_literal *) = 0; - virtual void visit(char_literal *) = 0; + virtual void visit(number_literal *) = 0; virtual void visit(string_literal *) = 0; }; @@ -123,7 +123,7 @@ namespace source virtual void visit(number_literal *) override; virtual void visit(number_literal *) override; virtual void visit(number_literal *) override; - virtual void visit(char_literal *) override; + virtual void visit(number_literal *) override; virtual void visit(string_literal *) override; }; @@ -353,12 +353,18 @@ namespace source virtual ~variable_declaration() override; }; + class literal : public expression + { + protected: + explicit literal(const struct position position); + }; + /** * Constant definition. */ class constant_definition : public definition { - number_literal *m_body; + literal *m_body; public: /** @@ -367,10 +373,10 @@ namespace source * \param body Constant value. */ constant_definition(const struct position position, const std::string& identifier, - number_literal *body); + literal *body); virtual void accept(parser_visitor *visitor) override; - number_literal& body(); + literal& body(); virtual ~constant_definition() override; }; @@ -624,13 +630,13 @@ namespace source }; template - class number_literal : public expression + class number_literal : public literal { T m_number; public: number_literal(const struct position position, const T value) - : expression(position), m_number(value) + : literal(position), m_number(value) { } @@ -645,18 +651,7 @@ namespace source } }; - class char_literal : public expression - { - unsigned char m_character; - - public: - char_literal(const struct position position, const unsigned char value); - virtual void accept(parser_visitor *visitor) override; - - unsigned char character() const; - }; - - class string_literal : public expression + class string_literal : public literal { std::string m_string; diff --git a/source/ast.cc b/source/ast.cc index 015ed21..26d8480 100644 --- a/source/ast.cc +++ b/source/ast.cc @@ -146,7 +146,7 @@ namespace source { } - void empty_visitor::visit(char_literal *) + void empty_visitor::visit(number_literal *) { } @@ -376,7 +376,7 @@ namespace source } constant_definition::constant_definition(const struct position position, const std::string& identifier, - number_literal *body) + literal *body) : definition(position, identifier), m_body(body) { } @@ -386,7 +386,7 @@ namespace source visitor->visit(this); } - number_literal& constant_definition::body() + literal& constant_definition::body() { return *m_body; } @@ -493,23 +493,13 @@ namespace source } } - char_literal::char_literal(const struct position position, const unsigned char value) - : expression(position), m_character(value) + literal::literal(const struct position position) + : expression(position) { } - void char_literal::accept(parser_visitor *visitor) - { - visitor->visit(this); - } - - unsigned char char_literal::character() const - { - return m_character; - } - string_literal::string_literal(const struct position position, const std::string& value) - : expression(position), m_string(value) + : literal(position), m_string(value) { } diff --git a/source/parser.yy b/source/parser.yy index 6cf86b0..65db0aa 100644 --- a/source/parser.yy +++ b/source/parser.yy @@ -74,11 +74,7 @@ %precedence THEN %precedence ELSE -%type *> integer_literal; -%type *> float_literal; -%type *> boolean_literal; -%type character_literal; -%type string_literal; +%type literal; %type constant_definition; %type > constant_part constant_definitions; %type variable_declaration; @@ -165,26 +161,6 @@ procedure_definitions: procedure_part: /* no procedure definitions */ {} | procedure_definitions { std::swap($$, $1); } -integer_literal: INTEGER - { - $$ = new elna::source::number_literal(elna::source::make_position(@1), $1); - }; -float_literal: FLOAT - { - $$ = new elna::source::number_literal(elna::source::make_position(@1), $1); - }; -character_literal: CHARACTER - { - $$ = new elna::source::char_literal(elna::source::make_position(@1), $1.at(0)); - }; -string_literal: STRING - { - $$ = new elna::source::string_literal(elna::source::make_position(@1), $1); - }; -boolean_literal: BOOLEAN - { - $$ = new elna::source::number_literal(elna::source::make_position(@1), $1); - }; compound_statement: BEGIN_BLOCK optional_statements END_BLOCK { $$ = new elna::source::compound_statement(elna::source::make_position(@1)); @@ -215,12 +191,29 @@ if_statement: $$ = new elna::source::if_statement(elna::source::make_position(@1), $2, $4, $6); } +literal: + INTEGER + { + $$ = new elna::source::number_literal(elna::source::make_position(@1), $1); + } + | FLOAT + { + $$ = new elna::source::number_literal(elna::source::make_position(@1), $1); + } + | BOOLEAN + { + $$ = new elna::source::number_literal(elna::source::make_position(@1), $1); + } + | CHARACTER + { + $$ = new elna::source::number_literal(elna::source::make_position(@1), $1.at(0)); + } + | STRING + { + $$ = new elna::source::string_literal(elna::source::make_position(@1), $1); + } pointer: - integer_literal { $$ = $1; } - | float_literal { $$ = $1; } - | boolean_literal { $$ = $1; } - | character_literal { $$ = $1; } - | string_literal { $$ = $1; } + literal { $$ = $1; } | designator_expression { $$ = $1; } | LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); } summand: @@ -359,7 +352,7 @@ type_expression: } variable_declaration: IDENTIFIER COLON type_expression { - $$ = new elna::source::variable_declaration(elna::source::make_position(@1), $1, $3); + $$ = new elna::source::variable_declaration(elna::source::make_position(@1), $1, $3); }; variable_declarations: variable_declaration COMMA variable_declarations @@ -371,9 +364,9 @@ variable_declarations: variable_part: /* no variable declarations */ {} | VAR variable_declarations SEMICOLON { std::swap($$, $2); } -constant_definition: IDENTIFIER EQUALS integer_literal +constant_definition: IDENTIFIER EQUALS literal { - $$ = new elna::source::constant_definition(elna::source::make_position(@1), $1, $3); + $$ = new elna::source::constant_definition(elna::source::make_position(@1), $1, $3); } constant_definitions: constant_definition COMMA constant_definitions