diff --git a/TODO b/TODO index 95bfc5c..6a0e433 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,7 @@ # Compiler - Catch exceptions thrown by the argument parser and print them normally. -- Provide position information on parse tree nodes. +- Structs or records. - While loop. - Type checking. - Calculate additional stack space needed for subexpressions in the allocator diff --git a/backend/riscv.cpp b/backend/riscv.cpp index 0ca2f67..12ede13 100644 --- a/backend/riscv.cpp +++ b/backend/riscv.cpp @@ -289,6 +289,10 @@ namespace elna::riscv statement->body().accept(this); } + void visitor::visit(source::type_expression *type) + { + } + void visitor::visit(source::variable_expression *variable) { const auto free_register = this->register_in_use ? x_register::a0 : x_register::t0; diff --git a/include/elna/backend/riscv.hpp b/include/elna/backend/riscv.hpp index 8b9eb8a..ed31c20 100644 --- a/include/elna/backend/riscv.hpp +++ b/include/elna/backend/riscv.hpp @@ -187,6 +187,7 @@ namespace elna::riscv virtual void visit(source::while_statement *statement) override; virtual void visit(source::block *block) override; virtual void visit(source::program *program) override; + virtual void visit(source::type_expression *variable) override; virtual void visit(source::variable_expression *variable) override; virtual void visit(source::binary_expression *expression) override; virtual void visit(source::integer_literal *number) override; diff --git a/include/elna/source/lexer.hpp b/include/elna/source/lexer.hpp index ac8197c..bcf288a 100644 --- a/include/elna/source/lexer.hpp +++ b/include/elna/source/lexer.hpp @@ -42,7 +42,9 @@ namespace elna::source loop, _do, procedure, - comparison_operator + comparison_operator, + hat, + at }; /** diff --git a/include/elna/source/parser.hpp b/include/elna/source/parser.hpp index 1adc8eb..55e91f6 100644 --- a/include/elna/source/parser.hpp +++ b/include/elna/source/parser.hpp @@ -31,10 +31,14 @@ namespace elna::source class block; class program; class binary_expression; + class type_expression; class variable_expression; class integer_literal; class boolean_literal; + /** + * Interface for AST visitors. + */ struct parser_visitor { virtual void visit(declaration *) = 0; @@ -48,11 +52,15 @@ namespace elna::source virtual void visit(block *) = 0; virtual void visit(program *) = 0; virtual void visit(binary_expression *) = 0; + virtual void visit(type_expression *) = 0; virtual void visit(variable_expression *) = 0; virtual void visit(integer_literal *) = 0; virtual void visit(boolean_literal *) = 0; }; + /** + * A visitor which visits all nodes but does nothing. + */ struct empty_visitor : parser_visitor { virtual void visit(declaration *declaration) override; @@ -66,6 +74,7 @@ namespace elna::source virtual void visit(block *block) override; virtual void visit(program *program) override; virtual void visit(binary_expression *expression) override; + virtual void visit(type_expression *variable) override; virtual void visit(variable_expression *variable) override; virtual void visit(integer_literal *number) override; virtual void visit(boolean_literal *boolean) override; @@ -76,16 +85,39 @@ namespace elna::source */ class node { + const struct position source_position; + + protected: + /** + * \param position Source code position. + */ + explicit node(const position position); + public: virtual void accept(parser_visitor *) = 0; + + /** + * \return Node position in the source code. + */ + const struct position& position() const noexcept; }; class statement : public node { + protected: + /** + * \param position Source code position. + */ + explicit statement(const struct position position); }; class expression : public node { + protected: + /** + * \param position Source code position. + */ + explicit expression(const struct position position); }; /** @@ -99,9 +131,10 @@ namespace elna::source /** * Constructs a definition identified by some name. * + * \param position Source code position. * \param identifier Definition name. */ - definition(const std::string& identifier); + definition(const struct position position, const std::string& identifier); public: /** @@ -110,18 +143,51 @@ namespace elna::source std::string& identifier() noexcept; }; + class type_expression : public node + { + std::string m_base; + bool m_pointer{ false }; + + public: + /** + * \param position Source code position. + * \param name Type name. + * \param is_pointer Whether it is a pointer type. + */ + type_expression(const struct position position, const std::string& name, const bool is_pointer = false); + virtual void accept(parser_visitor *visitor) override; + + /** + * \return Name of the base type. + */ + const std::string& base() const noexcept; + + /** + * \return Whether the type is a pointer. + */ + bool is_pointer() const noexcept; + }; + /** * Variable declaration. */ class declaration : public definition { - std::string m_type; + std::unique_ptr m_type; public: - declaration(const std::string& identifier, const std::string& type); + /** + * Constructs a declaration with a name and a type. + * + * \param position Source code position. + * \param identifier Definition name. + * \param type Declared type. + */ + declaration(const struct position position, const std::string& identifier, + std::unique_ptr&& type); virtual void accept(parser_visitor *visitor) override; - std::string& type() noexcept; + type_expression& type() noexcept; }; /** @@ -132,32 +198,54 @@ namespace elna::source std::unique_ptr m_body; public: - constant_definition(const std::string& identifier, std::unique_ptr&& body); + /** + * \param position Source code position. + * \param identifier Constant name. + * \param body Constant value. + */ + constant_definition(const struct position position, const std::string& identifier, + std::unique_ptr&& body); virtual void accept(parser_visitor *visitor) override; integer_literal& body(); }; + /** + * Procedure definition. + */ class procedure_definition : public definition { std::unique_ptr m_body; std::vector> m_parameters; public: - procedure_definition(const std::string& identifier, std::unique_ptr&& body); + /** + * \param position Source code position. + * \param identifier Procedure name. + * \param body Procedure body. + */ + procedure_definition(const struct position position, const std::string& identifier, + std::unique_ptr&& body); virtual void accept(parser_visitor *visitor) override; block& body(); std::vector>& parameters() noexcept; }; + /** + * Call statement. + */ class call_statement : public statement { std::string m_name; std::vector> m_arguments; public: - call_statement(const std::string& name); + /** + * \param position Source code position. + * \param name Callable's name. + */ + call_statement(const struct position position, const std::string& name); virtual void accept(parser_visitor *visitor) override; std::string& name() noexcept; @@ -169,8 +257,7 @@ namespace elna::source std::vector> m_statements; public: - compound_statement() = default; - compound_statement(std::vector>&& statements); + explicit compound_statement(const struct position position); virtual void accept(parser_visitor *visitor) override; std::vector>& statements(); @@ -182,33 +269,57 @@ namespace elna::source std::unique_ptr m_rvalue; public: - assign_statement(const std::string& lvalue, std::unique_ptr&& rvalue); + /** + * \param position Source code position. + * \param lvalue Left-hand side. + * \param rvalue Assigned expression. + */ + assign_statement(const struct position position, const std::string& lvalue, + std::unique_ptr&& rvalue); virtual void accept(parser_visitor *visitor) override; std::string& lvalue() noexcept; expression& rvalue(); }; + /** + * If-statement. + */ class if_statement : public statement { std::unique_ptr m_prerequisite; std::unique_ptr m_body; public: - if_statement(std::unique_ptr&& prerequisite, std::unique_ptr&& body); + /** + * \param position Source code position. + * \param prerequisite Condition. + * \param body Statement executed if the condition is met. + */ + if_statement(const struct position position, std::unique_ptr&& prerequisite, + std::unique_ptr&& body); virtual void accept(parser_visitor *visitor) override; expression& prerequisite(); statement& body(); }; + /** + * While-statement. + */ class while_statement : public statement { std::unique_ptr m_prerequisite; std::unique_ptr m_body; public: - while_statement(std::unique_ptr&& prerequisite, std::unique_ptr&& body); + /** + * \param position Source code position. + * \param prerequisite Condition. + * \param body Statement executed while the condition is met. + */ + while_statement(const struct position position, std::unique_ptr&& prerequisite, + std::unique_ptr&& body); virtual void accept(parser_visitor *visitor) override; expression& prerequisite(); @@ -222,7 +333,7 @@ namespace elna::source std::vector> m_declarations; public: - block(std::vector>&& definitions, + block(const struct position position, std::vector>&& definitions, std::vector>&& declarations, std::unique_ptr&& body); virtual void accept(parser_visitor *visitor) override; @@ -235,7 +346,7 @@ namespace elna::source class program : public block { public: - program(std::vector>&& definitions, + program(const struct position position, std::vector>&& definitions, std::vector>&& declarations, std::unique_ptr&& body); virtual void accept(parser_visitor *visitor) override; @@ -246,7 +357,7 @@ namespace elna::source std::int32_t m_number; public: - integer_literal(const std::int32_t value); + integer_literal(const struct position position, const std::int32_t value); virtual void accept(parser_visitor *visitor) override; std::int32_t number() const noexcept; @@ -257,7 +368,7 @@ namespace elna::source bool m_boolean; public: - boolean_literal(const bool value); + boolean_literal(const struct position position, const bool value); virtual void accept(parser_visitor *visitor) override; bool boolean() const noexcept; @@ -268,7 +379,7 @@ namespace elna::source std::string m_name; public: - variable_expression(const std::string& name); + variable_expression(const struct position position, const std::string& name); virtual void accept(parser_visitor *visitor) override; const std::string& name() const noexcept; @@ -281,7 +392,7 @@ namespace elna::source binary_operator m_operator; public: - binary_expression(std::unique_ptr&& lhs, + binary_expression(const struct position position, std::unique_ptr&& lhs, std::unique_ptr&& rhs, const unsigned char operation); virtual void accept(parser_visitor *visitor) override; @@ -298,6 +409,7 @@ namespace elna::source std::unique_ptr parse_condition(); std::unique_ptr parse_constant_definition(); std::unique_ptr parse_procedure_definition(); + std::unique_ptr parse_type_expression(); std::unique_ptr parse_declaration(); std::unique_ptr parse_statement(); std::unique_ptr parse_call_statement(); diff --git a/include/elna/source/result.hpp b/include/elna/source/result.hpp index 0972679..6d0afc9 100644 --- a/include/elna/source/result.hpp +++ b/include/elna/source/result.hpp @@ -149,6 +149,16 @@ namespace elna::source primitive_type(const std::string& type_name, const std::size_t byte_size); }; + /** + * Typed pointer. + */ + struct pointer_type : public type + { + std::shared_ptr base_type; + + pointer_type(std::shared_ptr base_type, const std::size_t byte_size); + }; + inline const primitive_type boolean_type{ "Boolean", 1 }; inline const primitive_type int_type{ "Int", 4 }; @@ -169,12 +179,12 @@ namespace elna::source */ class type_info final : public info { - class type m_type; + std::shared_ptr m_type; public: explicit type_info(const class type& type); ~type_info() override; - const class type& type() const noexcept; + std::shared_ptr type() const noexcept; }; /** @@ -195,14 +205,14 @@ namespace elna::source */ class variable_info final : public info { - class type m_type; + std::shared_ptr m_type; public: std::ptrdiff_t offset{ 0 }; - explicit variable_info(const class type& type); + explicit variable_info(std::shared_ptr type); ~variable_info() override; - const class type& type() const noexcept; + std::shared_ptr type() noexcept; }; /** @@ -210,14 +220,14 @@ namespace elna::source */ class parameter_info final : public info { - class type m_type; + std::shared_ptr m_type; public: std::ptrdiff_t offset{ 0 }; - explicit parameter_info(const class type& type); + explicit parameter_info(std::shared_ptr type); ~parameter_info() override; - const class type& type() const noexcept; + std::shared_ptr type() const noexcept; }; /** diff --git a/include/elna/source/semantic.hpp b/include/elna/source/semantic.hpp index d6af82e..d4aaaa6 100644 --- a/include/elna/source/semantic.hpp +++ b/include/elna/source/semantic.hpp @@ -8,6 +8,8 @@ namespace elna::source { std::shared_ptr table = std::make_shared(); + std::shared_ptr convert_declaration_type(const type_expression& ast_type) const; + public: name_analysis_visitor(std::shared_ptr table); diff --git a/source/parser.cpp b/source/parser.cpp index 3171cb3..6f3a1a7 100644 --- a/source/parser.cpp +++ b/source/parser.cpp @@ -78,6 +78,10 @@ namespace elna::source expression->rhs().accept(this); } + void empty_visitor::visit(type_expression *variable) + { + } + void empty_visitor::visit(variable_expression *variable) { } @@ -90,12 +94,49 @@ namespace elna::source { } - void node::accept(parser_visitor *) + node::node(const struct position position) + : source_position(position) { } - declaration::declaration(const std::string& identifier, const std::string& type) - : definition(identifier), m_type(type) + const struct position& node::position() const noexcept + { + return this->source_position; + } + + statement::statement(const struct position position) + : node(position) + { + } + + expression::expression(const struct position position) + : node(position) + { + } + + type_expression::type_expression(const struct position position, const std::string& name, const bool is_pointer) + : node(position), m_base(name), m_pointer(is_pointer) + { + } + + void type_expression::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + + const std::string& type_expression::base() const noexcept + { + return m_base; + } + + bool type_expression::is_pointer() const noexcept + { + return m_pointer; + } + + declaration::declaration(const struct position position, const std::string& identifier, + std::unique_ptr&& type) + : definition(position, identifier), m_type(std::move(type)) { } @@ -104,13 +145,13 @@ namespace elna::source visitor->visit(this); } - std::string& declaration::type() noexcept + type_expression& declaration::type() noexcept { - return m_type; + return *m_type; } - definition::definition(const std::string& identifier) - : m_identifier(identifier) + definition::definition(const struct position position, const std::string& identifier) + : node(position), m_identifier(identifier) { } @@ -119,8 +160,9 @@ namespace elna::source return m_identifier; } - constant_definition::constant_definition(const std::string& identifier, std::unique_ptr&& body) - : definition(identifier), m_body(std::move(body)) + constant_definition::constant_definition(const struct position position, const std::string& identifier, + std::unique_ptr&& body) + : definition(position, identifier), m_body(std::move(body)) { } @@ -134,8 +176,9 @@ namespace elna::source return *m_body; } - procedure_definition::procedure_definition(const std::string& identifier, std::unique_ptr&& body) - : definition(identifier), m_body(std::move(body)) + procedure_definition::procedure_definition(const struct position position, const std::string& identifier, + std::unique_ptr&& body) + : definition(position, identifier), m_body(std::move(body)) { } @@ -154,10 +197,10 @@ namespace elna::source return m_parameters; } - block::block(std::vector>&& definitions, + block::block(const struct position position, std::vector>&& definitions, std::vector>&& declarations, std::unique_ptr&& body) - : m_definitions(std::move(definitions)), + : node(position), m_definitions(std::move(definitions)), m_declarations(std::move(declarations)), m_body(std::move(body)) { } @@ -182,10 +225,10 @@ namespace elna::source return m_declarations; } - program::program(std::vector>&& definitions, + program::program(const struct position position, std::vector>&& definitions, std::vector>&& declarations, std::unique_ptr&& body) - : block(std::move(definitions), std::move(declarations), std::move(body)) + : block(position, std::move(definitions), std::move(declarations), std::move(body)) { } @@ -194,8 +237,8 @@ namespace elna::source visitor->visit(this); } - integer_literal::integer_literal(const std::int32_t value) - : m_number(value) + integer_literal::integer_literal(const struct position position, const std::int32_t value) + : expression(position), m_number(value) { } @@ -209,8 +252,8 @@ namespace elna::source return m_number; } - boolean_literal::boolean_literal(const bool value) - : m_boolean(value) + boolean_literal::boolean_literal(const struct position position, const bool value) + : expression(position), m_boolean(value) { } @@ -224,8 +267,8 @@ namespace elna::source return m_boolean; } - variable_expression::variable_expression(const std::string& name) - : m_name(name) + variable_expression::variable_expression(const struct position position, const std::string& name) + : expression(position), m_name(name) { } @@ -239,9 +282,9 @@ namespace elna::source return m_name; } - binary_expression::binary_expression(std::unique_ptr&& lhs, + binary_expression::binary_expression(const struct position position, std::unique_ptr&& lhs, std::unique_ptr&& rhs, const unsigned char operation) - : m_lhs(std::move(lhs)), m_rhs(std::move(rhs)) + : expression(position), m_lhs(std::move(lhs)), m_rhs(std::move(rhs)) { switch (operation) { @@ -300,8 +343,8 @@ namespace elna::source return m_operator; } - call_statement::call_statement(const std::string& name) - : m_name(name) + call_statement::call_statement(const struct position position, const std::string& name) + : statement(position), m_name(name) { } @@ -320,8 +363,8 @@ namespace elna::source return m_arguments; } - compound_statement::compound_statement(std::vector>&& statements) - : m_statements(std::move(statements)) + compound_statement::compound_statement(const struct position position) + : statement(position) { } @@ -340,8 +383,9 @@ namespace elna::source visitor->visit(this); } - assign_statement::assign_statement(const std::string& lvalue, std::unique_ptr&& rvalue) - : m_lvalue(lvalue), m_rvalue(std::move(rvalue)) + assign_statement::assign_statement(const struct position position, const std::string& lvalue, + std::unique_ptr&& rvalue) + : statement(position), m_lvalue(lvalue), m_rvalue(std::move(rvalue)) { } @@ -355,8 +399,9 @@ namespace elna::source return *m_rvalue; } - if_statement::if_statement(std::unique_ptr&& prerequisite, std::unique_ptr&& body) - : m_prerequisite(std::move(prerequisite)), m_body(std::move(body)) + if_statement::if_statement(const struct position position, std::unique_ptr&& prerequisite, + std::unique_ptr&& body) + : statement(position), m_prerequisite(std::move(prerequisite)), m_body(std::move(body)) { } @@ -375,8 +420,9 @@ namespace elna::source return *m_body; } - while_statement::while_statement(std::unique_ptr&& prerequisite, std::unique_ptr&& body) - : m_prerequisite(std::move(prerequisite)), m_body(std::move(body)) + while_statement::while_statement(const struct position position, std::unique_ptr&& prerequisite, + std::unique_ptr&& body) + : statement(position), m_prerequisite(std::move(prerequisite)), m_body(std::move(body)) { } @@ -422,7 +468,7 @@ namespace elna::source { *definition++ = std::move(procedure); } - return std::make_unique(std::move(definitions), + return std::make_unique(position(), std::move(definitions), std::move(declarations), std::move(parsed_statement)); } @@ -435,19 +481,19 @@ namespace elna::source { if (iterator->of() == source::token::type::identifier) { - auto result = std::make_unique(iterator->identifier()); + auto result = std::make_unique(iterator->position(), iterator->identifier()); ++iterator; return result; } else if (iterator->of() == source::token::token::type::number) { - auto result = std::make_unique(iterator->number()); + auto result = std::make_unique(iterator->position(), iterator->number()); ++iterator; return result; } else if (iterator->of() == source::token::token::type::boolean) { - auto result = std::make_unique(iterator->number()); + auto result = std::make_unique(iterator->position(), iterator->number()); ++iterator; return result; } @@ -474,10 +520,11 @@ namespace elna::source while (iterator->of() == source::token::type::factor_operator) { auto _operator = iterator->identifier()[0]; + const auto operator_position = iterator->position(); ++iterator; auto rhs = parse_factor(); - lhs = std::make_unique(std::move(lhs), + lhs = std::make_unique(operator_position, std::move(lhs), std::move(rhs), _operator); } return lhs; @@ -493,10 +540,11 @@ namespace elna::source while (iterator->of() == source::token::type::term_operator) { auto _operator = iterator->identifier()[0]; + const auto operator_position = iterator->position(); ++iterator; auto rhs = parse_term(); - term = std::make_unique(std::move(term), + term = std::make_unique(operator_position, std::move(term), std::move(rhs), _operator); } return term; @@ -524,6 +572,7 @@ namespace elna::source { return lhs; } + const auto operator_position = iterator->position(); ++iterator; auto rhs = parse_expression(); @@ -531,12 +580,13 @@ namespace elna::source { return nullptr; } - return std::make_unique(std::move(lhs), std::move(rhs), _operator); + return std::make_unique(operator_position, std::move(lhs), std::move(rhs), _operator); } std::unique_ptr parser::parse_constant_definition() { auto definition_identifier = iterator.advance(token::type::identifier); + const auto identifier_position = iterator->position(); if (!definition_identifier.has_value()) { @@ -549,8 +599,9 @@ namespace elna::source if (iterator->of() == source::token::type::number) { - auto result = std::make_unique(definition_identifier.value().get().identifier(), - std::make_unique(iterator->number())); + auto result = std::make_unique(identifier_position, + definition_identifier.value().get().identifier(), + std::make_unique(iterator->position(), iterator->number())); ++iterator; return result; } @@ -559,6 +610,7 @@ namespace elna::source std::unique_ptr parser::parse_procedure_definition() { + const auto proc_position = iterator->position(); if (!iterator.skip(token::type::procedure)) { return nullptr; @@ -597,13 +649,32 @@ namespace elna::source { return nullptr; } - auto procedure = std::make_unique(definition_identifier->get().identifier(), - std::move(definition_body)); + auto procedure = std::make_unique(proc_position, + definition_identifier->get().identifier(), std::move(definition_body)); procedure->parameters() = std::move(declarations); return procedure; } + std::unique_ptr parser::parse_type_expression() + { + const auto type_position = iterator->position(); + bool is_pointer{ false }; + if (iterator.current(token::type::hat)) + { + is_pointer = true; + ++iterator; + } + auto type_identifier = iterator.advance(token::type::identifier); + + if (!type_identifier.has_value()) + { + return nullptr; + } + return std::make_unique(type_position, type_identifier.value().get().identifier(), + is_pointer); + } + std::unique_ptr parser::parse_declaration() { auto declaration_identifier = iterator.advance(token::type::identifier); @@ -612,14 +683,14 @@ namespace elna::source { return nullptr; } - auto type_identifier = iterator.advance(token::type::identifier); + auto type_identifier = parse_type_expression(); - if (!type_identifier.has_value()) + if (type_identifier == nullptr) { return nullptr; } - return std::make_unique(declaration_identifier.value().get().identifier(), - type_identifier.value().get().identifier()); + return std::make_unique(declaration_identifier.value().get().position(), + declaration_identifier.value().get().identifier(), std::move(type_identifier)); } std::unique_ptr parser::parse_statement() @@ -655,7 +726,8 @@ namespace elna::source { return nullptr; } - auto call = std::make_unique(function_name->get().identifier()); + auto call = std::make_unique(function_name->get().position(), + function_name->get().identifier()); std::unique_ptr argument_expression; if (iterator.current(token::type::right_paren)) @@ -682,11 +754,12 @@ namespace elna::source std::unique_ptr parser::parse_compound_statement() { + const auto begin_position = iterator->position(); if (!iterator.advance(token::type::begin)) { return nullptr; } - auto result = std::make_unique(); + auto result = std::make_unique(begin_position); std::unique_ptr next_statement; while ((next_statement = parse_statement()) != nullptr) @@ -725,11 +798,13 @@ namespace elna::source { return nullptr; } - return std::make_unique(name.value().get().identifier(), std::move(rvalue)); + return std::make_unique(name.value().get().position(), name.value().get().identifier(), + std::move(rvalue)); } std::unique_ptr parser::parse_if_statement() { + const auto if_position = iterator->position(); if (!iterator.skip(token::type::when)) { return nullptr; @@ -746,11 +821,12 @@ namespace elna::source { return nullptr; } - return std::make_unique(std::move(condition), std::move(body)); + return std::make_unique(if_position, std::move(condition), std::move(body)); } std::unique_ptr parser::parse_while_statement() { + const auto while_position = iterator->position(); if (!iterator.skip(token::type::loop)) { return nullptr; @@ -767,7 +843,7 @@ namespace elna::source { return nullptr; } - return std::make_unique(std::move(condition), std::move(body)); + return std::make_unique(while_position, std::move(condition), std::move(body)); } std::vector> parser::parse_constant_definitions() @@ -870,7 +946,7 @@ namespace elna::source { *definition++ = std::move(constant); } - return std::make_unique(std::move(definitions), + return std::make_unique(parsed_statement->position(), std::move(definitions), std::move(declarations), std::move(parsed_statement)); } } diff --git a/source/result.cpp b/source/result.cpp index 182e156..9d8bda0 100644 --- a/source/result.cpp +++ b/source/result.cpp @@ -43,21 +43,28 @@ namespace elna::source { } + pointer_type::pointer_type(std::shared_ptr base_type, const std::size_t byte_size) + : type(byte_size), base_type(base_type) + { + } + symbol_table::symbol_table(std::shared_ptr scope) : outer_scope(scope) { if (scope == nullptr) { + auto boolean_info = std::make_shared(boolean_type); + auto int_info = std::make_shared(int_type); + enter("Boolean", boolean_info); + enter("Int", int_info); + auto writei = std::make_shared(); - writei->parameter_infos.emplace_back(int_type); + writei->parameter_infos.emplace_back(int_info->type()); enter("writei", writei); auto writeb = std::make_shared(); - writeb->parameter_infos.emplace_back(boolean_type); + writeb->parameter_infos.emplace_back(boolean_info->type()); enter("writeb", writeb); - - enter("Boolean", std::make_shared(boolean_type)); - enter("Int", std::make_shared(int_type)); } } @@ -95,7 +102,7 @@ namespace elna::source } type_info::type_info(const class type& type) - : info(), m_type(type) + : info(), m_type(std::make_shared(type)) { } @@ -103,7 +110,7 @@ namespace elna::source { } - const class type& type_info::type() const noexcept + std::shared_ptr type_info::type() const noexcept { return m_type; } @@ -122,7 +129,7 @@ namespace elna::source return m_value; } - variable_info::variable_info(const class type& type) + variable_info::variable_info(std::shared_ptr type) : m_type(type) { } @@ -131,12 +138,12 @@ namespace elna::source { } - const class type& variable_info::type() const noexcept + std::shared_ptr variable_info::type() noexcept { return m_type; } - parameter_info::parameter_info(const class type& type) + parameter_info::parameter_info(std::shared_ptr type) : m_type(type) { } @@ -145,7 +152,7 @@ namespace elna::source { } - const class type& parameter_info::type() const noexcept + std::shared_ptr parameter_info::type() const noexcept { return m_type; } diff --git a/source/scanner.l b/source/scanner.l index 140f8a4..5814000 100644 --- a/source/scanner.l +++ b/source/scanner.l @@ -159,6 +159,16 @@ False { return static_cast(elna::source::token::type::colon); } +\^ { + yylval.nil = nullptr; + + return static_cast(elna::source::token::type::hat); + } +@ { + yylval.nil = nullptr; + + return static_cast(elna::source::token::type::at); + } . { return -1; } @@ -172,10 +182,10 @@ result tokenize(const std::filesystem::path& path) std::vector tokens; yyin = fopen(path.c_str(), "rb"); - if (yyin == nullptr) - { - throw std::ios_base::failure("File does not exist"); - } + if (yyin == nullptr) + { + throw std::ios_base::failure("File does not exist"); + } do { yytoken = yylex(); diff --git a/source/semantic.cpp b/source/semantic.cpp index 1f35058..5275ccb 100644 --- a/source/semantic.cpp +++ b/source/semantic.cpp @@ -1,4 +1,5 @@ #include "elna/source/semantic.hpp" +#include "elna/source/result.hpp" #include namespace elna::source @@ -14,11 +15,28 @@ namespace elna::source std::make_shared(constant_info(definition->body().number()))); } + std::shared_ptr name_analysis_visitor::convert_declaration_type(const type_expression& ast_type) const + { + auto variable_type = std::dynamic_pointer_cast(table->lookup(ast_type.base())) + ->type(); + std::shared_ptr declaration_type; + + if (ast_type.is_pointer()) + { + return std::make_shared(variable_type, 4); + } + else + { + return variable_type; + } + } + void name_analysis_visitor::visit(declaration *declaration) { - auto declaration_type = std::dynamic_pointer_cast(table->lookup(declaration->type())); + std::shared_ptr declaration_type = convert_declaration_type(declaration->type()); + this->table->enter(declaration->identifier(), - std::make_shared(declaration_type->type())); + std::make_shared(declaration_type)); } void name_analysis_visitor::visit(program *program) @@ -35,9 +53,10 @@ namespace elna::source for (auto& parameter : procedure->parameters()) { - auto declaration_type = std::dynamic_pointer_cast(table->lookup(parameter->type())); + auto declaration_type = convert_declaration_type(parameter->type()); + this->table->enter(parameter->identifier(), - std::make_shared(declaration_type->type())); + std::make_shared(declaration_type)); } procedure->body().accept(this);