Add a symbol table with type info

This commit is contained in:
2025-03-09 00:53:13 +01:00
parent 868db6e0bf
commit f739194e06
9 changed files with 471 additions and 342 deletions

View File

@ -42,28 +42,22 @@ namespace boot
class error
{
protected:
/**
* Constructs an error.
*
* \param path Source file name.
* \param position Error position in the source text.
*/
error(const char *path, const struct position position);
public:
const struct position position;
const char *path;
virtual ~error() noexcept = default;
virtual ~error() = default;
/// Error text.
virtual std::string what() const = 0;
/// Error line in the source text.
std::size_t line() const noexcept;
std::size_t line() const;
/// Error column in the source text.
std::size_t column() const noexcept;
std::size_t column() const;
};
}
}

View File

@ -16,119 +16,38 @@ along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <string>
#include <vector>
#include <unordered_map>
#include <memory>
#include "elna/boot/ast.h"
#include "elna/boot/result.h"
#include "elna/boot/symbol.h"
namespace elna
{
namespace boot
{
class alias_type;
class primitive_type;
class record_type;
class union_type;
class pointer_type;
class array_type;
class type
class declaration_error : public error
{
enum class type_tag
{
empty,
alias,
primitive,
record,
_union,
pointer,
array
};
type_tag tag{ type_tag::empty };
union
{
std::weak_ptr<alias_type> alias;
std::weak_ptr<primitive_type> primitive;
std::shared_ptr<record_type> record;
std::shared_ptr<union_type> _union;
std::shared_ptr<pointer_type> pointer;
std::shared_ptr<array_type> array;
};
void copy(const type& other);
void move(type&& other);
std::string identifier;
public:
type();
explicit type(std::shared_ptr<alias_type> alias);
explicit type(std::shared_ptr<primitive_type> primitive);
explicit type(std::shared_ptr<record_type> record);
explicit type(std::shared_ptr<union_type> _union);
explicit type(std::shared_ptr<pointer_type> pointer);
explicit type(std::shared_ptr<array_type> array);
declaration_error(const std::string& identifier, const char *path, const struct position position);
type(const type& other);
type& operator=(const type& other);
type(type&& other);
type& operator=(type&& other);
~type();
template<typename T>
std::shared_ptr<T> get() const;
bool empty() const;
};
struct alias_type
{
type reference;
};
struct pointer_type
{
const type base;
explicit pointer_type(type base);
};
struct array_type
{
const type base;
const std::uint64_t size;
array_type(type base, std::uint64_t size);
};
struct primitive_type
{
const std::string identifier;
explicit primitive_type(const std::string& identifier);
};
using type_field = typename std::pair<std::string, type>;
struct record_type
{
std::vector<type_field> fields;
};
struct union_type
{
std::vector<type_field> fields;
virtual std::string what() const override;
};
class declaration_visitor final : public empty_visitor
{
type current_type;
const char *path;
symbol_table symbols;
std::vector<std::unique_ptr<error>> errors;
public:
std::unordered_map<std::string, std::shared_ptr<alias_type>> unresolved;
declaration_visitor() = default;
explicit declaration_visitor(const char *path, std::shared_ptr<symbol_table> symbols);
void visit(primitive_type_expression *type_expression) override;
void visit(array_type_expression *type_expression) override;

View File

@ -21,11 +21,127 @@ along with GCC; see the file COPYING3. If not see
#include <unordered_map>
#include <string>
#include <memory>
#include <vector>
namespace elna
{
namespace boot
{
class alias_type;
class primitive_type;
class record_type;
class union_type;
class pointer_type;
class array_type;
class type
{
enum class type_tag
{
empty,
alias,
primitive,
record,
_union,
pointer,
array
};
type_tag tag{ type_tag::empty };
union
{
std::weak_ptr<alias_type> alias;
std::weak_ptr<primitive_type> primitive;
std::shared_ptr<record_type> record;
std::shared_ptr<union_type> _union;
std::shared_ptr<pointer_type> pointer;
std::shared_ptr<array_type> array;
};
void copy(const type& other);
void move(type&& other);
public:
type();
explicit type(std::shared_ptr<alias_type> alias);
explicit type(std::shared_ptr<primitive_type> primitive);
explicit type(std::shared_ptr<record_type> record);
explicit type(std::shared_ptr<union_type> _union);
explicit type(std::shared_ptr<pointer_type> pointer);
explicit type(std::shared_ptr<array_type> array);
type(const type& other);
type& operator=(const type& other);
type(type&& other);
type& operator=(type&& other);
~type();
template<typename T>
std::shared_ptr<T> get() const;
bool empty() const;
};
struct alias_type
{
type reference;
};
struct pointer_type
{
const type base;
explicit pointer_type(type base);
};
struct array_type
{
const type base;
const std::uint64_t size;
array_type(type base, std::uint64_t size);
};
struct primitive_type
{
const std::string identifier;
explicit primitive_type(const std::string& identifier);
};
using type_field = typename std::pair<std::string, type>;
struct record_type
{
std::vector<type_field> fields;
};
struct union_type
{
std::vector<type_field> fields;
};
class type_info;
class info : public std::enable_shared_from_this<info>
{
public:
virtual ~info() = 0;
virtual std::shared_ptr<type_info> is_type();
};
class type_info : public info
{
public:
const type symbol;
explicit type_info(const type symbol);
std::shared_ptr<type_info> is_type() override;
};
/**
* Symbol table.
*/
@ -120,5 +236,9 @@ namespace boot
return this->outer_scope;
}
};
using symbol_table = symbol_map<std::shared_ptr<info>, std::nullptr_t, nullptr>;
std::shared_ptr<symbol_table> builtin_symbol_table();
}
}

View File

@ -34,7 +34,8 @@ namespace elna
{
namespace gcc
{
void do_semantic_analysis(std::shared_ptr<symbol_table> symbols, std::unique_ptr<boot::program>& ast);
void do_semantic_analysis(const char *path, std::unique_ptr<boot::program>& ast,
std::shared_ptr<symbol_table> symbols);
class generic_visitor final : public boot::empty_visitor
{