Move type definitions to the program node
This commit is contained in:
		
							
								
								
									
										24
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								README
									
									
									
									
									
								
							| @@ -1,15 +1,26 @@ | |||||||
| # Elna programming language | # Elna programming language | ||||||
|  |  | ||||||
| Elna compiles simple mathematical operations to machine code. | Elna is a simple, imperative, low-level programming language. | ||||||
| The compiled program returns the result of the operation. |  | ||||||
|  | It is intendet to accompany other languages in the areas, where a high-level | ||||||
|  | language doesn't fit well. It is also supposed to be an intermediate | ||||||
|  | representation for a such high-level hypothetical programming language. | ||||||
|  |  | ||||||
| ## File extension | ## File extension | ||||||
|  |  | ||||||
| .elna | .elna | ||||||
|  |  | ||||||
|  | ## Current implementation | ||||||
|  |  | ||||||
|  | This repository contains a GCC frontend for Elna. After finishing the frontend | ||||||
|  | I'm planning to rewrite the compiler in Elna itself with its own backend and | ||||||
|  | a hand-written parser. So GCC gives a way to have a simple bootstrap compiler | ||||||
|  | and a possbility to compile Elna programs for different platforms. | ||||||
|  |  | ||||||
| ## Grammar PL/0 | ## Grammar PL/0 | ||||||
|  |  | ||||||
| program = block "." ; | program = [ "type" type_definitions ";" ] | ||||||
|  |     block "." ; | ||||||
|  |  | ||||||
| block = [ "const" ident "=" number {"," ident "=" number} ";"] | block = [ "const" ident "=" number {"," ident "=" number} ";"] | ||||||
|         [ "var" ident {"," ident} ";"] |         [ "var" ident {"," ident} ";"] | ||||||
| @@ -30,6 +41,13 @@ term = factor {("*"|"/") factor}; | |||||||
|  |  | ||||||
| factor = ident | number | "(" expression ")"; | factor = ident | number | "(" expression ")"; | ||||||
|  |  | ||||||
|  | type_expression = "array" number "of" type_expression | ||||||
|  |                 | "^" type_expression | ||||||
|  |                 | "record" field_list "end" | ||||||
|  |                 | ident | ||||||
|  |  | ||||||
|  | field_list = ident ":" type_expression { ";" field_list } | ||||||
|  |  | ||||||
| ## Operations | ## Operations | ||||||
|  |  | ||||||
| "!" - Write a line. | "!" - Write a line. | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								example.elna
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								example.elna
									
									
									
									
									
								
							| @@ -15,7 +15,7 @@ begin | |||||||
| end; | end; | ||||||
|  |  | ||||||
| proc test_array(); | proc test_array(); | ||||||
| var a: T, x_3: Int; | var a: T, x: Int; | ||||||
| begin | begin | ||||||
|   a[0] := 2; |   a[0] := 2; | ||||||
|   a[1] := 5; |   a[1] := 5; | ||||||
| @@ -23,19 +23,19 @@ begin | |||||||
|   writei(""); |   writei(""); | ||||||
|   writei("Test array:"); |   writei("Test array:"); | ||||||
|  |  | ||||||
|   x_3 := 0; |   x := 0; | ||||||
|   while x_3 < 2 do |   while x < 2 do | ||||||
|   begin |   begin | ||||||
|     writei(a[x_3]); |     writei(a[x]); | ||||||
| 	x_3 := x_3 + 1 | 	x := x + 1 | ||||||
|   end |   end | ||||||
| end; | end; | ||||||
|  |  | ||||||
| proc test_pointer(); | proc test_pointer(); | ||||||
| var x_2: Int, p: ^Int; | var x: Int, p: ^Int; | ||||||
| begin | begin | ||||||
|   x_2 := 5; |   x := 5; | ||||||
|   p := @x_2; |   p := @x; | ||||||
|  |  | ||||||
|   writei(""); |   writei(""); | ||||||
|   writei("Test pointer:"); |   writei("Test pointer:"); | ||||||
| @@ -69,13 +69,13 @@ end; | |||||||
|  |  | ||||||
| proc test_const(); | proc test_const(); | ||||||
| const t = 5; | const t = 5; | ||||||
| var x_1: Int; | var x: Int; | ||||||
| begin | begin | ||||||
|   x_1 := t; |   x := t; | ||||||
|  |  | ||||||
|   writei(""); |   writei(""); | ||||||
|   writei("Test const:"); |   writei("Test const:"); | ||||||
|   writei(x_1) |   writei(x) | ||||||
| end; | end; | ||||||
|  |  | ||||||
| proc test_if(); | proc test_if(); | ||||||
|   | |||||||
| @@ -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/types.o \ |  | ||||||
| 	$(END) | 	$(END) | ||||||
|  |  | ||||||
| elna1$(exeext): attribs.o $(elna_OBJS) $(BACKEND) $(LIBDEPS) | elna1$(exeext): attribs.o $(elna_OBJS) $(BACKEND) $(LIBDEPS) | ||||||
|   | |||||||
| @@ -15,9 +15,14 @@ namespace elna | |||||||
| { | { | ||||||
| namespace gcc | namespace gcc | ||||||
| { | { | ||||||
|  |     generic_visitor::generic_visitor() | ||||||
|  |     { | ||||||
|  |         this->symbol_map = std::make_shared<source::symbol_table<tree>>(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     void generic_visitor::visit(source::call_statement *statement) |     void generic_visitor::visit(source::call_statement *statement) | ||||||
|     { |     { | ||||||
|         auto symbol = this->symbol_map.find(statement->name()); |         auto symbol = this->symbol_map->lookup(statement->name()); | ||||||
|  |  | ||||||
|         if (statement->name() == "writei") |         if (statement->name() == "writei") | ||||||
|         { |         { | ||||||
| @@ -80,10 +85,10 @@ namespace gcc | |||||||
|             append_to_statement_list(stmt, &this->current_statements); |             append_to_statement_list(stmt, &this->current_statements); | ||||||
|             this->current_expression = NULL_TREE; |             this->current_expression = NULL_TREE; | ||||||
|         } |         } | ||||||
|         else if (symbol != this->symbol_map.end()) |         else if (symbol) | ||||||
|         { |         { | ||||||
|             tree fndecl_type = build_function_type_list(integer_type_node, NULL_TREE); |             tree fndecl_type = build_function_type_list(integer_type_node, NULL_TREE); | ||||||
|             tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol->second); |             tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol->payload); | ||||||
|  |  | ||||||
|             tree stmt = build_call_nary(integer_type_node, printf_fn, 0); |             tree stmt = build_call_nary(integer_type_node, printf_fn, 0); | ||||||
|  |  | ||||||
| @@ -100,7 +105,7 @@ namespace gcc | |||||||
|  |  | ||||||
|     void generic_visitor::visit(source::program *program) |     void generic_visitor::visit(source::program *program) | ||||||
|     { |     { | ||||||
|         for (const auto& constant : program->definitions()) |         for (const auto& constant : program->type_definitions) | ||||||
|         { |         { | ||||||
|             constant->accept(this); |             constant->accept(this); | ||||||
|         } |         } | ||||||
| @@ -153,7 +158,7 @@ namespace gcc | |||||||
|                 definition->parameters().size(), parameter_types); |                 definition->parameters().size(), parameter_types); | ||||||
|         this->main_fndecl = build_fn_decl(definition->identifier().c_str(), declaration_type); |         this->main_fndecl = build_fn_decl(definition->identifier().c_str(), declaration_type); | ||||||
|  |  | ||||||
|         this->symbol_map.insert({ definition->identifier(), this->main_fndecl }); |         this->symbol_map->enter(definition->identifier(), source::make_info(this->main_fndecl)); | ||||||
|  |  | ||||||
|         tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node); |         tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node); | ||||||
|         DECL_CONTEXT(resdecl) = this->main_fndecl; |         DECL_CONTEXT(resdecl) = this->main_fndecl; | ||||||
| @@ -186,6 +191,7 @@ namespace gcc | |||||||
|     { |     { | ||||||
|         this->current_statements = alloc_stmt_list(); |         this->current_statements = alloc_stmt_list(); | ||||||
|         this->variable_chain = tree_chain(); |         this->variable_chain = tree_chain(); | ||||||
|  |         this->symbol_map = std::make_shared<source::symbol_table<tree>>(this->symbol_map); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     tree_symbol_mapping generic_visitor::leave_scope() |     tree_symbol_mapping generic_visitor::leave_scope() | ||||||
| @@ -194,6 +200,7 @@ namespace gcc | |||||||
|                 NULL_TREE, NULL_TREE, NULL_TREE); |                 NULL_TREE, NULL_TREE, NULL_TREE); | ||||||
|         tree bind_expr = build3(BIND_EXPR, void_type_node, variable_chain.head(), |         tree bind_expr = build3(BIND_EXPR, void_type_node, variable_chain.head(), | ||||||
|                 this->current_statements, new_block); |                 this->current_statements, new_block); | ||||||
|  |         this->symbol_map = this->symbol_map->scope(); | ||||||
|  |  | ||||||
|         return tree_symbol_mapping{ bind_expr, new_block }; |         return tree_symbol_mapping{ bind_expr, new_block }; | ||||||
|     } |     } | ||||||
| @@ -344,9 +351,9 @@ namespace gcc | |||||||
|         location_t definition_location = get_location(&definition->position()); |         location_t definition_location = get_location(&definition->position()); | ||||||
|         tree definition_tree = build_decl(definition_location, CONST_DECL, |         tree definition_tree = build_decl(definition_location, CONST_DECL, | ||||||
|                 get_identifier(definition->identifier().c_str()), integer_type_node); |                 get_identifier(definition->identifier().c_str()), integer_type_node); | ||||||
|         auto result = this->symbol_map.insert({ definition->identifier(), definition_tree }); |         auto result = this->symbol_map->enter(definition->identifier(), source::make_info(definition_tree)); | ||||||
|  |  | ||||||
|         if (result.second) |         if (result) | ||||||
|         { |         { | ||||||
|             definition->body().accept(this); |             definition->body().accept(this); | ||||||
|  |  | ||||||
| @@ -378,9 +385,9 @@ namespace gcc | |||||||
|         location_t definition_location = get_location(&definition->position()); |         location_t definition_location = get_location(&definition->position()); | ||||||
|         tree definition_tree = build_decl(definition_location, TYPE_DECL, |         tree definition_tree = build_decl(definition_location, TYPE_DECL, | ||||||
|                 get_identifier(definition->identifier().c_str()), tree_type); |                 get_identifier(definition->identifier().c_str()), tree_type); | ||||||
|         auto result = this->symbol_map.insert({ definition->identifier(), definition_tree }); |         auto result = this->symbol_map->enter(definition->identifier(), source::make_info(definition_tree)); | ||||||
|  |  | ||||||
|         if (result.second) |         if (result) | ||||||
|         { |         { | ||||||
|             DECL_CONTEXT(definition_tree) = this->main_fndecl; |             DECL_CONTEXT(definition_tree) = this->main_fndecl; | ||||||
|             variable_chain.append(definition_tree); |             variable_chain.append(definition_tree); | ||||||
| @@ -421,11 +428,11 @@ namespace gcc | |||||||
|             { |             { | ||||||
|                 return elna_string_type_node; |                 return elna_string_type_node; | ||||||
|             } |             } | ||||||
|             auto symbol = this->symbol_map.find(basic_type->base_name()); |             auto symbol = this->symbol_map->lookup(basic_type->base_name()); | ||||||
|  |  | ||||||
|             if (symbol != this->symbol_map.end()) |             if (symbol) | ||||||
|             { |             { | ||||||
|                 return TREE_TYPE(symbol->second); |                 return TREE_TYPE(symbol->payload); | ||||||
|             } |             } | ||||||
|             error_at(get_location(&basic_type->position()), |             error_at(get_location(&basic_type->position()), | ||||||
|                     "type '%s' not declared", basic_type->base_name().c_str()); |                     "type '%s' not declared", basic_type->base_name().c_str()); | ||||||
| @@ -499,9 +506,9 @@ namespace gcc | |||||||
|         auto declaration_location = get_location(&declaration->position()); |         auto declaration_location = get_location(&declaration->position()); | ||||||
|         tree declaration_tree = build_decl(declaration_location, VAR_DECL, |         tree declaration_tree = build_decl(declaration_location, VAR_DECL, | ||||||
|                 get_identifier(declaration->identifier().c_str()), declaration_type); |                 get_identifier(declaration->identifier().c_str()), declaration_type); | ||||||
|         auto result = this->symbol_map.insert({ declaration->identifier(), declaration_tree }); |         auto result = this->symbol_map->enter(declaration->identifier(), source::make_info(declaration_tree)); | ||||||
|  |  | ||||||
|         if (result.second) |         if (result) | ||||||
|         { |         { | ||||||
|             DECL_CONTEXT(declaration_tree) = this->main_fndecl; |             DECL_CONTEXT(declaration_tree) = this->main_fndecl; | ||||||
|             variable_chain.append(declaration_tree); |             variable_chain.append(declaration_tree); | ||||||
| @@ -520,9 +527,9 @@ namespace gcc | |||||||
|  |  | ||||||
|     void generic_visitor::visit(source::variable_expression *expression) |     void generic_visitor::visit(source::variable_expression *expression) | ||||||
|     { |     { | ||||||
|         auto symbol = this->symbol_map.find(expression->name()); |         auto symbol = this->symbol_map->lookup(expression->name()); | ||||||
|  |  | ||||||
|         if (symbol == this->symbol_map.end()) |         if (!symbol) | ||||||
|         { |         { | ||||||
|             error_at(get_location(&expression->position()), |             error_at(get_location(&expression->position()), | ||||||
|                     "variable '%s' not declared in the current scope", |                     "variable '%s' not declared in the current scope", | ||||||
| @@ -530,7 +537,7 @@ namespace gcc | |||||||
|             this->current_expression = error_mark_node; |             this->current_expression = error_mark_node; | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         this->current_expression = symbol->second; |         this->current_expression = symbol->payload; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void generic_visitor::visit(source::array_access_expression *expression) |     void generic_visitor::visit(source::array_access_expression *expression) | ||||||
|   | |||||||
| @@ -1,3 +1,6 @@ | |||||||
| /* gcc-src/gcc/config/lang-specs.in */ | /* gcc/gcc.cc */ | ||||||
| {".elna",  "@elna", 0, 1, 0}, | {".elna",  "@elna", nullptr, 0, 0}, | ||||||
| {"@elna",  "elna1 %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}", 0, 1, 0}, | {"@elna", | ||||||
|  |     "elna1 %{!Q:-quiet} \ | ||||||
|  |     %i %{!fsyntax-only:%(invoke_as)}", | ||||||
|  |     nullptr, 0, 0}, | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "elna/source/ast.h" | #include "elna/source/ast.h" | ||||||
|  | #include "elna/source/symbol.h" | ||||||
| #include "elna/gcc/elna-tree.h" | #include "elna/gcc/elna-tree.h" | ||||||
|  |  | ||||||
| #include "config.h" | #include "config.h" | ||||||
| @@ -20,7 +21,7 @@ namespace gcc | |||||||
|     { |     { | ||||||
|         tree current_statements{ NULL_TREE }; |         tree current_statements{ NULL_TREE }; | ||||||
|         tree current_expression{ NULL_TREE }; |         tree current_expression{ NULL_TREE }; | ||||||
|         std::unordered_map<std::string, tree> symbol_map; |         std::shared_ptr<source::symbol_table<tree>> symbol_map; | ||||||
|         tree main_fndecl{ NULL_TREE }; |         tree main_fndecl{ NULL_TREE }; | ||||||
|         tree_chain variable_chain; |         tree_chain variable_chain; | ||||||
|  |  | ||||||
| @@ -31,6 +32,8 @@ namespace gcc | |||||||
|         tree_symbol_mapping leave_scope(); |         tree_symbol_mapping leave_scope(); | ||||||
|  |  | ||||||
|     public: |     public: | ||||||
|  |         generic_visitor(); | ||||||
|  |  | ||||||
|         void visit(source::program *program) override; |         void visit(source::program *program) override; | ||||||
|         void visit(source::procedure_definition *definition) override; |         void visit(source::procedure_definition *definition) override; | ||||||
|         void visit(source::call_statement *statement) override; |         void visit(source::call_statement *statement) override; | ||||||
|   | |||||||
| @@ -8,7 +8,6 @@ | |||||||
| #include <string> | #include <string> | ||||||
| #include <vector> | #include <vector> | ||||||
| #include "elna/source/result.h" | #include "elna/source/result.h" | ||||||
| #include "elna/source/types.h" |  | ||||||
|  |  | ||||||
| namespace elna | namespace elna | ||||||
| { | { | ||||||
| @@ -210,7 +209,6 @@ namespace source | |||||||
|     { |     { | ||||||
|     public: |     public: | ||||||
|         std::shared_ptr<operand> place; |         std::shared_ptr<operand> place; | ||||||
|         std::shared_ptr<const type> data_type; |  | ||||||
|  |  | ||||||
|     protected: |     protected: | ||||||
|         /** |         /** | ||||||
| @@ -596,19 +594,16 @@ namespace source | |||||||
|  |  | ||||||
|     class block : public node |     class block : public node | ||||||
|     { |     { | ||||||
|         std::vector<definition *> m_definitions; |  | ||||||
|         statement *m_body; |         statement *m_body; | ||||||
|  |  | ||||||
|     public: |     public: | ||||||
|         std::vector<definition *> value_definitions; |         std::vector<definition *> value_definitions; | ||||||
|  |  | ||||||
|         block(const struct position position, std::vector<definition *>&& definitions, |         block(const struct position position, std::vector<definition *>&& value_definitions, | ||||||
|                 std::vector<definition *>&& value_definitions, |  | ||||||
|                 statement *body); |                 statement *body); | ||||||
|         virtual void accept(parser_visitor *visitor) override; |         virtual void accept(parser_visitor *visitor) override; | ||||||
|  |  | ||||||
|         statement& body(); |         statement& body(); | ||||||
|         std::vector<definition *>& definitions(); |  | ||||||
|  |  | ||||||
|         virtual ~block() override; |         virtual ~block() override; | ||||||
|     }; |     }; | ||||||
| @@ -616,9 +611,13 @@ namespace source | |||||||
|     class program : public block |     class program : public block | ||||||
|     { |     { | ||||||
|     public: |     public: | ||||||
|         program(const struct position position, std::vector<definition *>&& definitions, |         std::vector<definition *> type_definitions; | ||||||
|  |  | ||||||
|  |         program(const struct position position, std::vector<definition *>&& type_definitions, | ||||||
|                 std::vector<definition *>&& value_definitions, statement *body); |                 std::vector<definition *>&& value_definitions, statement *body); | ||||||
|         virtual void accept(parser_visitor *visitor) override; |         virtual void accept(parser_visitor *visitor) override; | ||||||
|  |  | ||||||
|  |         virtual ~program() override; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     template<typename T> |     template<typename T> | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <cstddef> | #include <cstddef> | ||||||
| #include "elna/source/types.h" | #include <string> | ||||||
|  |  | ||||||
| namespace elna | namespace elna | ||||||
| { | { | ||||||
|   | |||||||
							
								
								
									
										106
									
								
								include/elna/source/symbol.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								include/elna/source/symbol.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,106 @@ | |||||||
|  | // This Source Code Form is subject to the terms of the Mozilla Public License | ||||||
|  | // v. 2.0. If a copy of the MPL was not distributed with this file, You can | ||||||
|  | // obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <cstdint> | ||||||
|  | #include <unordered_map> | ||||||
|  | #include <string> | ||||||
|  | #include <memory> | ||||||
|  |  | ||||||
|  | namespace elna | ||||||
|  | { | ||||||
|  | namespace source | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * Generic language entity information. | ||||||
|  |      */ | ||||||
|  |     template<typename T> | ||||||
|  |     class info | ||||||
|  |     { | ||||||
|  |     public: | ||||||
|  |         T payload; | ||||||
|  |  | ||||||
|  |         info(T payload) | ||||||
|  |             : payload(payload) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     template<typename T> | ||||||
|  |     std::shared_ptr<info<T>> make_info(T payload) | ||||||
|  |     { | ||||||
|  |         return std::make_shared<info<T>>(info(payload)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Symbol table. | ||||||
|  |      */ | ||||||
|  |     template<typename T> | ||||||
|  |     class symbol_table | ||||||
|  |     { | ||||||
|  |     public: | ||||||
|  |         using symbol_ptr = std::shared_ptr<info<T>>; | ||||||
|  |  | ||||||
|  |     private: | ||||||
|  |         std::unordered_map<std::string, symbol_ptr> entries; | ||||||
|  |         std::shared_ptr<symbol_table> outer_scope; | ||||||
|  |  | ||||||
|  |     public: | ||||||
|  |         /** | ||||||
|  |          * Constructs a new symbol with an optional outer scope. | ||||||
|  |          * | ||||||
|  |          * \param scope Outer scope. | ||||||
|  |          */ | ||||||
|  |         explicit symbol_table(std::shared_ptr<symbol_table> scope = nullptr) | ||||||
|  |             : outer_scope(scope) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * Looks for symbol in the table by name. Returns nullptr if the symbol | ||||||
|  |          * can not be found. | ||||||
|  |          * | ||||||
|  |          * \param name Symbol name. | ||||||
|  |          * \return Symbol from the table if found. | ||||||
|  |          */ | ||||||
|  |         symbol_ptr lookup(const std::string& name) | ||||||
|  |         { | ||||||
|  |             auto entry = entries.find(name); | ||||||
|  |  | ||||||
|  |             if (entry != entries.cend()) | ||||||
|  |             { | ||||||
|  |                 return entry->second; | ||||||
|  |             } | ||||||
|  |             if (this->outer_scope != nullptr) | ||||||
|  |             { | ||||||
|  |                 return this->outer_scope->lookup(name); | ||||||
|  |             } | ||||||
|  |             return nullptr; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * Registers new symbol. | ||||||
|  |          * | ||||||
|  |          * \param name Symbol name. | ||||||
|  |          * \param entry Symbol information. | ||||||
|  |          * | ||||||
|  |          * \return Whether the insertion took place. | ||||||
|  |          */ | ||||||
|  |         bool enter(const std::string& name, symbol_ptr entry) | ||||||
|  |         { | ||||||
|  |             return entries.insert({ name, entry }).second; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * Returns the outer scope or nullptr if the this is the global scope. | ||||||
|  |          * | ||||||
|  |          * \return Outer scope. | ||||||
|  |          */ | ||||||
|  |         std::shared_ptr<symbol_table> scope() | ||||||
|  |         { | ||||||
|  |             return this->outer_scope; | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | } | ||||||
| @@ -65,10 +65,6 @@ namespace source | |||||||
|  |  | ||||||
|     void empty_visitor::visit(block *block) |     void empty_visitor::visit(block *block) | ||||||
|     { |     { | ||||||
|         for (const auto& constant : block->definitions()) |  | ||||||
|         { |  | ||||||
|             constant->accept(this); |  | ||||||
|         } |  | ||||||
|         for (const auto& definition : block->value_definitions) |         for (const auto& definition : block->value_definitions) | ||||||
|         { |         { | ||||||
|             definition->accept(this); |             definition->accept(this); | ||||||
| @@ -78,6 +74,10 @@ namespace source | |||||||
|  |  | ||||||
|     void empty_visitor::visit(program *program) |     void empty_visitor::visit(program *program) | ||||||
|     { |     { | ||||||
|  |         for (auto definition : program->type_definitions) | ||||||
|  |         { | ||||||
|  |             definition->accept(this); | ||||||
|  |         } | ||||||
|         visit(reinterpret_cast<block *>(program)); |         visit(reinterpret_cast<block *>(program)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -447,11 +447,9 @@ namespace source | |||||||
|         delete m_body; |         delete m_body; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     block::block(const struct position position, std::vector<definition *>&& definitions, |     block::block(const struct position position, std::vector<definition *>&& value_definitions, | ||||||
|             std::vector<definition *>&& value_definitions, |  | ||||||
|             statement *body) |             statement *body) | ||||||
|         : node(position), m_definitions(std::move(definitions)), |         : node(position), m_body(std::move(body)), value_definitions(std::move(value_definitions)) | ||||||
|         m_body(std::move(body)), value_definitions(std::move(value_definitions)) |  | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -460,11 +458,6 @@ namespace source | |||||||
|         visitor->visit(this); |         visitor->visit(this); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     std::vector<definition *>& block::definitions() |  | ||||||
|     { |  | ||||||
|         return m_definitions; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     statement& block::body() |     statement& block::body() | ||||||
|     { |     { | ||||||
|         return *m_body; |         return *m_body; | ||||||
| @@ -472,10 +465,6 @@ namespace source | |||||||
|  |  | ||||||
|     block::~block() |     block::~block() | ||||||
|     { |     { | ||||||
|         for (auto definition : m_definitions) |  | ||||||
|         { |  | ||||||
|             delete definition; |  | ||||||
|         } |  | ||||||
|         for (auto definition : value_definitions) |         for (auto definition : value_definitions) | ||||||
|         { |         { | ||||||
|             delete definition; |             delete definition; | ||||||
| @@ -483,9 +472,11 @@ namespace source | |||||||
|         delete m_body; |         delete m_body; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     program::program(const struct position position, std::vector<definition *>&& definitions, |     program::program(const struct position position, | ||||||
|  |             std::vector<definition *>&& type_definitions, | ||||||
|             std::vector<definition *>&& value_definitions, statement *body) |             std::vector<definition *>&& value_definitions, statement *body) | ||||||
|         : block(position, std::move(definitions), std::move(value_definitions), body) |         : block(position, std::move(value_definitions), body), | ||||||
|  |         type_definitions(std::move(type_definitions)) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -494,6 +485,14 @@ namespace source | |||||||
|         visitor->visit(this); |         visitor->visit(this); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     program::~program() | ||||||
|  |     { | ||||||
|  |         for (auto definition : type_definitions) | ||||||
|  |         { | ||||||
|  |             delete definition; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     char_literal::char_literal(const struct position position, const unsigned char value) |     char_literal::char_literal(const struct position position, const unsigned char value) | ||||||
|         : expression(position), m_character(value) |         : expression(position), m_character(value) | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -126,8 +126,10 @@ program: | |||||||
|             { |             { | ||||||
|                 *value_definition++ = variable; |                 *value_definition++ = variable; | ||||||
|             } |             } | ||||||
|             driver.tree = std::make_unique<elna::source::program>(elna::source::position{}, |             auto tree = new elna::source::program(elna::source::position{}, | ||||||
|                  std::move(definitions), std::move(value_definitions), std::move($5)); |                  std::move(definitions), std::move(value_definitions), std::move($5)); | ||||||
|  |  | ||||||
|  |             driver.tree.reset(tree); | ||||||
|         } |         } | ||||||
| block: constant_part variable_part statement | block: constant_part variable_part statement | ||||||
|         { |         { | ||||||
| @@ -143,7 +145,7 @@ block: constant_part variable_part statement | |||||||
|                 *definition++ = variable; |                 *definition++ = variable; | ||||||
|             } |             } | ||||||
|             $$ = new elna::source::block(elna::source::position{}, |             $$ = new elna::source::block(elna::source::position{}, | ||||||
|                  {}, std::move(definitions), std::move($3)); |                  std::move(definitions), std::move($3)); | ||||||
|         }; |         }; | ||||||
| procedure_definition: | procedure_definition: | ||||||
|     PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON block SEMICOLON |     PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON block SEMICOLON | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user