Implement pointers

This commit is contained in:
2025-01-10 23:17:18 +01:00
parent 954425f4bd
commit 35c32fcf3f
15 changed files with 131 additions and 915 deletions

View File

@ -39,11 +39,14 @@ namespace gcc
void visit(source::char_literal *character) override;
void visit(source::string_literal *string) override;
void visit(source::binary_expression *expression) override;
void visit(source::unary_expression *expression) override;
void visit(source::constant_definition *definition) override;
void visit(source::type_definition *definition) override;
void visit(source::declaration *declaration) override;
void visit(source::variable_expression *expression) override;
void visit(source::array_access_expression *expression) override;
void visit(source::field_access_expression *expression) override;
void visit(source::dereference_expression *expression) override;
void visit(source::assign_statement *statement) override;
void visit(source::if_statement *statement) override;
void visit(source::while_statement *statement) override;

View File

@ -23,6 +23,7 @@ namespace elna
namespace gcc
{
void init_ttree();
bool is_pointer_type(tree type);
bool is_string_type(tree type);
bool is_array_type(tree type);
bool is_record_type(tree type);

View File

@ -30,8 +30,7 @@ namespace source
enum class unary_operator
{
reference,
dereference
reference
};
class declaration;
@ -117,8 +116,8 @@ namespace source
virtual void visit(record_type_expression *expression) override;
virtual void visit(variable_expression *) override;
virtual void visit(array_access_expression *expression) override;
virtual void visit(field_access_expression *is_field_access) override;
virtual void visit(dereference_expression *is_dereference) override;
virtual void visit(field_access_expression *expression) override;
virtual void visit(dereference_expression *expression) override;
virtual void visit(number_literal<std::int32_t> *) override;
virtual void visit(number_literal<double> *) override;
virtual void visit(number_literal<bool> *) override;
@ -249,7 +248,6 @@ namespace source
class type_expression : public node
{
public:
virtual const std::string& base_name() = 0;
virtual basic_type_expression *is_basic();
virtual array_type_expression *is_array();
virtual pointer_type_expression *is_pointer();
@ -262,7 +260,7 @@ namespace source
/**
* Expression defining a basic type.
*/
class basic_type_expression : public type_expression
class basic_type_expression final : public type_expression
{
const std::string m_name;
@ -274,12 +272,12 @@ namespace source
basic_type_expression(const struct position position, const std::string& name);
virtual void accept(parser_visitor *visitor) override;
const std::string& base_name() override;
const std::string& base_name();
basic_type_expression *is_basic() override;
};
class array_type_expression : public type_expression
class array_type_expression final : public type_expression
{
type_expression *m_base;
@ -290,14 +288,13 @@ namespace source
virtual void accept(parser_visitor *visitor) override;
type_expression& base();
const std::string& base_name() override;
array_type_expression *is_array() override;
virtual ~array_type_expression() override;
};
class pointer_type_expression : public type_expression
class pointer_type_expression final : public type_expression
{
type_expression *m_base;
@ -306,14 +303,13 @@ namespace source
virtual void accept(parser_visitor *visitor) override;
type_expression& base();
const std::string& base_name() override;
pointer_type_expression *is_pointer() override;
virtual ~pointer_type_expression() override;
};
class record_type_expression : public type_expression
class record_type_expression final : public type_expression
{
public:
using field_t = std::pair<std::string, type_expression *>;
@ -326,6 +322,8 @@ namespace source
record_type_expression *is_record() override;
virtual ~record_type_expression() override;
private:
fields_t m_fields;
};

View File

@ -1,100 +0,0 @@
// 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 <list>
#include "elna/source/ast.h"
#include "elna/source/symbol_table.h"
namespace elna
{
namespace source
{
class name_analysis_visitor final : public empty_visitor
{
std::shared_ptr<symbol_table> table;
const char *filename;
std::list<std::unique_ptr<error>> m_errors;
const std::size_t pointer_size;
std::shared_ptr<const type> convert_declaration_type(const type_expression& ast_type) const;
public:
/**
* \param table Symbol table.
* \param path Source filename.
* \param target_pointer_size Pointer size on the target platform.
*/
name_analysis_visitor(std::shared_ptr<symbol_table> table, const char *filename,
const std::size_t target_pointer_size);
/**
* \return Collected errors.
*/
const std::list<std::unique_ptr<error>>& errors() const noexcept;
void visit(constant_definition *definition) override;
void visit(declaration *declaration) override;
void visit(program *program) override;
void visit(procedure_definition *procedure) override;
};
/**
* Visitor which allocates registers and stack space for variables and
* parameters.
*/
class allocator_visitor final : public empty_visitor
{
std::ptrdiff_t local_offset;
std::ptrdiff_t argument_offset;
std::shared_ptr<symbol_table> table;
public:
allocator_visitor(std::shared_ptr<symbol_table> table);
void visit(declaration *declaration) override;
void visit(program *program) override;
void visit(procedure_definition *procedure) override;
void visit(call_statement *statement) override;
};
/**
* This visitor performs the type checking.
*/
class type_analysis_visitor final : public empty_visitor
{
std::shared_ptr<symbol_table> table;
const char *filename;
const std::size_t pointer_size;
std::list<std::unique_ptr<error>> m_errors;
public:
/**
* \param table Symbol table.
* \param path Source filename.
* \param target_pointer_size Pointer size on the target platform.
*/
type_analysis_visitor(std::shared_ptr<symbol_table> table, const char *filename,
const std::size_t target_pointer_size);
/**
* \return Collected errors.
*/
const std::list<std::unique_ptr<error>>& errors() const noexcept;
void visit(program *program) override;
void visit(procedure_definition *procedure) override;
void visit(integer_literal *literal) override;
void visit(boolean_literal *literal) override;
void visit(variable_expression *expression) override;
void visit(unary_expression *expression) override;
void visit(binary_expression *expression) override;
void visit(call_statement *statement) override;
void visit(constant_definition *definition) override;
void visit(while_statement *statement) override;
void visit(if_statement *statement) override;
void visit(assign_statement *statement) override;
};
}
}

View File

@ -1,198 +0,0 @@
// 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
{
class symbol_table;
class type_info;
class typed_info;
class constant_info;
class variable_info;
class parameter_info;
class intrinsic_info;
class procedure_info;
/**
* Generic language entity information.
*/
class info
{
public:
virtual ~info() = 0;
virtual type_info *is_type_info() noexcept;
virtual typed_info *is_typed_info() noexcept;
virtual constant_info *is_constant_info() noexcept;
virtual variable_info *is_variable_info() noexcept;
virtual parameter_info *is_parameter_info() noexcept;
virtual intrinsic_info *is_intrinsic_info() noexcept;
virtual procedure_info *is_procedure_info() noexcept;
protected:
info();
};
/**
* Type information.
*/
class type_info final : public info
{
std::shared_ptr<const class type> m_type;
public:
explicit type_info(std::shared_ptr<class type> type);
~type_info() override;
virtual type_info *is_type_info() noexcept override;
std::shared_ptr<const class type> type() const noexcept;
};
/**
* Information for a typed symbol.
*/
class typed_info : public info
{
std::shared_ptr<const class type> m_type;
protected:
typed_info(std::shared_ptr<const class type> type);
public:
~typed_info() override;
virtual typed_info *is_typed_info() noexcept override;
std::shared_ptr<const class type> type() const noexcept;
};
/**
* Constant information.
*/
class constant_info final : public typed_info
{
std::int32_t m_value;
public:
constant_info(std::shared_ptr<const class type> type, const std::int32_t value);
virtual constant_info *is_constant_info() noexcept override;
std::int32_t value() const noexcept;
};
/**
* Variable information.
*/
class variable_info final : public typed_info
{
public:
std::ptrdiff_t offset{ 0 };
explicit variable_info(std::shared_ptr<const class type> type);
virtual variable_info *is_variable_info() noexcept override;
};
/**
* Procedure parameter information.
*/
class parameter_info final : public typed_info
{
public:
std::ptrdiff_t offset{ 0 };
explicit parameter_info(std::shared_ptr<const class type> type);
virtual parameter_info *is_parameter_info() noexcept override;
};
/**
* Intrinsic and external procedure information.
*/
class intrinsic_info : public info
{
std::shared_ptr<const class procedure_type> m_type;
public:
explicit intrinsic_info(const class procedure_type& type);
~intrinsic_info() override;
std::shared_ptr<const class procedure_type> type() const noexcept;
std::size_t parameter_stack_size() const noexcept;
virtual intrinsic_info *is_intrinsic_info() noexcept override;
};
/**
* Procedure information.
*/
class procedure_info final : public intrinsic_info
{
std::shared_ptr<symbol_table> local_table;
public:
std::size_t local_stack_size{ 0 };
std::size_t argument_stack_size{ 0 };
procedure_info(const class procedure_type& type, std::shared_ptr<symbol_table> outer_scope);
~procedure_info() override;
std::shared_ptr<symbol_table> scope();
std::size_t stack_size() const noexcept;
virtual procedure_info *is_procedure_info() noexcept override;
};
/**
* Symbol table.
*/
class symbol_table
{
std::unordered_map<std::string, std::shared_ptr<info>> 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);
/**
* 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.
*/
std::shared_ptr<info> lookup(const std::string& name);
/**
* Registers new symbol.
*
* \param name Symbol name.
* \param entry Symbol information.
*/
void enter(const std::string& name, std::shared_ptr<info> entry);
/**
* Returns the outer scope or nullptr if the this is the global scope.
*
* \return Outer scope.
*/
std::shared_ptr<symbol_table> scope();
};
/**
* Creates a symbol table with predefined symbols.
*
* \return A symbol table with predefined symbols.
*/
std::shared_ptr<source::symbol_table> add_builtin_symbols();}
}