mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2026-01-25 13:07:13 +00:00
types for typecheck, sources manager
This commit is contained in:
parent
4714a05467
commit
ef88e6af86
9 changed files with 353 additions and 104 deletions
|
|
@ -11,28 +11,78 @@
|
||||||
|
|
||||||
namespace names {
|
namespace names {
|
||||||
|
|
||||||
// IN PROGRESS
|
class NameTree;
|
||||||
|
|
||||||
|
class AnyStatementProxy {
|
||||||
|
friend NameTree;
|
||||||
|
|
||||||
|
public:
|
||||||
|
nodes::Statement *get();
|
||||||
|
|
||||||
|
const nodes::Statement *get() const;
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
bool operator==(const AnyStatementProxy &other_any_statement_proxy) const {
|
||||||
|
return name_tree_ == other_any_statement_proxy.name_tree_ &&
|
||||||
|
id_ == other_any_statement_proxy.id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const AnyStatementProxy &other_any_statement_proxy) const {
|
||||||
|
return !(*this == other_any_statement_proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
AnyStatementProxy(NameTree &name_tree, size_t id)
|
||||||
|
: name_tree_(&name_tree), id_(id) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
NameTree *name_tree_;
|
||||||
|
size_t id_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> class StatementProxy {
|
||||||
|
public:
|
||||||
|
StatementProxy(AnyStatementProxy proxy) : proxy_(proxy) {}
|
||||||
|
|
||||||
|
T *get() { proxy_.get()->get<T>().value(); }
|
||||||
|
|
||||||
|
const T *get() const { proxy_.get()->get<T>().value(); }
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
bool operator==(const StatementProxy &other_statement_proxy) const {
|
||||||
|
return proxy_ == other_statement_proxy.proxy_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const StatementProxy &other_statement_proxy) const {
|
||||||
|
return !(*this == other_statement_proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
AnyStatementProxy proxy_;
|
||||||
|
};
|
||||||
|
|
||||||
class NameTree {
|
class NameTree {
|
||||||
|
friend AnyStatementProxy;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NameTree() {
|
NameTree() {
|
||||||
nodes_.emplace_back(); // root
|
nodes_.emplace_back(); // root
|
||||||
}
|
}
|
||||||
|
|
||||||
bool insert(const std::string &path, nodes::Statement &&statement);
|
std::optional<AnyStatementProxy> insert(const std::string &path,
|
||||||
|
nodes::Statement &&statement);
|
||||||
|
|
||||||
// bool insert(const std::string &path, const nodes::Statement &statement);
|
std::pair<std::optional<AnyStatementProxy>, nodes::CombineResult>
|
||||||
|
insert_combine(const std::string &path, nodes::Statement &&statement);
|
||||||
|
|
||||||
nodes::CombineResult insert_combine(const std::string &path,
|
std::optional<AnyStatementProxy> find(const std::string &path);
|
||||||
nodes::Statement &&statement);
|
|
||||||
|
|
||||||
std::optional<nodes::Statement *> find(const std::string &path);
|
|
||||||
|
|
||||||
std::optional<const nodes::Statement *> find(const std::string &path) const;
|
|
||||||
|
|
||||||
void print(printers::Printer &printer) const;
|
void print(printers::Printer &printer) const;
|
||||||
|
|
||||||
// TODO
|
// // TODO
|
||||||
void add_statement_children_to_tree();
|
// void add_statement_children_to_tree();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Node {
|
struct Node {
|
||||||
|
|
|
||||||
85
include/sources_manager.hpp
Normal file
85
include/sources_manager.hpp
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "basic_printers.hpp"
|
||||||
|
#include "error_handling.hpp"
|
||||||
|
#include "expression_nodes.hpp"
|
||||||
|
#include "name_tree.hpp"
|
||||||
|
#include "statement_builders.hpp"
|
||||||
|
#include "statement_nodes.hpp"
|
||||||
|
#include "statement_printers.hpp"
|
||||||
|
#include "tree_sitter_wrapper.hpp"
|
||||||
|
#include "type_nodes.hpp"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
class SourcesManager {
|
||||||
|
public:
|
||||||
|
void add_file(const std::string &filename) {
|
||||||
|
std::ifstream in;
|
||||||
|
in.open(filename);
|
||||||
|
|
||||||
|
std::stringstream source_stream;
|
||||||
|
|
||||||
|
source_stream << in.rdbuf();
|
||||||
|
|
||||||
|
in.close();
|
||||||
|
|
||||||
|
std::string source = source_stream.str();
|
||||||
|
|
||||||
|
parser::ParseTree parse_tree(source);
|
||||||
|
|
||||||
|
if (!parse_tree.is_properly_parsed()) {
|
||||||
|
error_handling::handle_parsing_error(
|
||||||
|
"There are some parsing errors in file", parse_tree.get_root());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto new_statements = builders::build_source_file(
|
||||||
|
parse_tree.get_root(), expression_storage_, type_storage_, name_tree_);
|
||||||
|
|
||||||
|
statements_.reserve(statements_.size() + new_statements.size());
|
||||||
|
for (auto &new_statement : new_statements) {
|
||||||
|
statements_.push_back(std::move(new_statement));
|
||||||
|
}
|
||||||
|
|
||||||
|
new_statements.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(std::ostream &out) {
|
||||||
|
printers::Printer printer(out, 2, 80, true);
|
||||||
|
printers::print_source_file(statements_, printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
nodes::ExpressionStorage *get_expression_storage() {
|
||||||
|
return &expression_storage_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodes::ExpressionStorage *get_expression_storage() const {
|
||||||
|
return &expression_storage_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
nodes::TypeStorage *get_type_storage() { return &type_storage_; }
|
||||||
|
|
||||||
|
const nodes::TypeStorage *get_type_storage() const { return &type_storage_; }
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
size_t get_statements_size() const { return statements_.size(); }
|
||||||
|
|
||||||
|
nodes::Statement *get_statement(size_t id) { return &statements_.at(id); }
|
||||||
|
|
||||||
|
const nodes::Statement *get_statement(size_t id) const {
|
||||||
|
return &statements_.at(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nodes::ExpressionStorage expression_storage_;
|
||||||
|
nodes::TypeStorage type_storage_;
|
||||||
|
names::NameTree name_tree_;
|
||||||
|
std::vector<nodes::Statement> statements_;
|
||||||
|
};
|
||||||
|
|
@ -404,6 +404,7 @@ public:
|
||||||
Statement(const Statement &) = default;
|
Statement(const Statement &) = default;
|
||||||
Statement(Statement &&) = default;
|
Statement(Statement &&) = default;
|
||||||
Statement &operator=(const Statement &) = default;
|
Statement &operator=(const Statement &) = default;
|
||||||
|
Statement &operator=(Statement &&) = default;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
explicit Statement(T &&statement) : expression_(std::forward<T>(statement)) {}
|
explicit Statement(T &&statement) : expression_(std::forward<T>(statement)) {}
|
||||||
|
|
|
||||||
134
include/types.hpp
Normal file
134
include/types.hpp
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "basic_nodes.hpp"
|
||||||
|
#include "name_tree.hpp"
|
||||||
|
#include "statement_nodes.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace types {
|
||||||
|
|
||||||
|
class Type;
|
||||||
|
class TypeStorage;
|
||||||
|
|
||||||
|
class TypeProxy {
|
||||||
|
friend TypeStorage;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Type *get();
|
||||||
|
|
||||||
|
const Type *get() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
TypeProxy(TypeStorage &type_storage, size_t id)
|
||||||
|
: type_storage_(&type_storage), id_(id) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TypeStorage *type_storage_;
|
||||||
|
size_t id_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Defined {
|
||||||
|
public:
|
||||||
|
Defined(nodes::Modifier modifier,
|
||||||
|
names::StatementProxy<nodes::TypeDefinition> definition)
|
||||||
|
: modifier_(modifier), definition_(definition) {}
|
||||||
|
|
||||||
|
nodes::Modifier get_modifier() const { return modifier_; }
|
||||||
|
|
||||||
|
nodes::TypeDefinition *get_definition() { return definition_.get(); }
|
||||||
|
|
||||||
|
const nodes::TypeDefinition *get_definition() const {
|
||||||
|
return definition_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nodes::Modifier modifier_;
|
||||||
|
names::StatementProxy<nodes::TypeDefinition> definition_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Container {
|
||||||
|
public:
|
||||||
|
enum ContainerType {
|
||||||
|
OR,
|
||||||
|
AND,
|
||||||
|
};
|
||||||
|
|
||||||
|
Container(ContainerType type, std::vector<TypeProxy> &&fields)
|
||||||
|
: type_(type), fields_(std::move(fields)) {}
|
||||||
|
|
||||||
|
Container(ContainerType type, const std::vector<TypeProxy> &fields)
|
||||||
|
: type_(type), fields_(std::move(fields)) {}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
ContainerType get_type() const { return type_; }
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
size_t fields_size() const { return fields_.size(); }
|
||||||
|
|
||||||
|
Type *get_field(size_t id) { return fields_.at(id).get(); }
|
||||||
|
|
||||||
|
const Type *get_field(size_t id) const { return fields_.at(id).get(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ContainerType type_;
|
||||||
|
std::vector<TypeProxy> fields_; // or constructors
|
||||||
|
};
|
||||||
|
|
||||||
|
class Type {
|
||||||
|
public:
|
||||||
|
Type(const Type &) = default;
|
||||||
|
Type(Type &&) = default;
|
||||||
|
Type &operator=(const Type &) = default;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
explicit Type(T &&type) : type_(std::forward<T>(type)) {}
|
||||||
|
|
||||||
|
template <typename T> std::optional<T *> get() {
|
||||||
|
if (std::holds_alternative<T>(type_)) {
|
||||||
|
return &std::get<T>(type_);
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> std::optional<const T *> get() const {
|
||||||
|
if (std::holds_alternative<T>(type_)) {
|
||||||
|
return &std::get<T>(type_);
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto get_any() { return &type_; }
|
||||||
|
|
||||||
|
auto get_any() const { return &type_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::variant<Defined, Container> type_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TypeStorage {
|
||||||
|
friend TypeProxy;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TypeProxy add_type(const Type &type) {
|
||||||
|
storage_.push_back(type);
|
||||||
|
return TypeProxy(*this, storage_.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeProxy add_type(Type &&type) {
|
||||||
|
storage_.push_back(std::move(type));
|
||||||
|
return TypeProxy(*this, storage_.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type *get_type(size_t id) { return &storage_.at(id); }
|
||||||
|
|
||||||
|
const Type *get_type(size_t id) const { return &storage_.at(id); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Type> storage_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace types
|
||||||
41
src/main.cpp
41
src/main.cpp
|
|
@ -1,14 +1,4 @@
|
||||||
#include <fstream>
|
#include "sources_manager.hpp"
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include "basic_printers.hpp"
|
|
||||||
#include "error_handling.hpp"
|
|
||||||
#include "expression_nodes.hpp"
|
|
||||||
#include "name_tree.hpp"
|
|
||||||
#include "statement_builders.hpp"
|
|
||||||
#include "statement_printers.hpp"
|
|
||||||
#include "type_nodes.hpp"
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
if (argc < 2 || argc > 2) {
|
if (argc < 2 || argc > 2) {
|
||||||
|
|
@ -19,31 +9,10 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
std::string filename = argv[1];
|
std::string filename = argv[1];
|
||||||
|
|
||||||
std::ifstream in;
|
//
|
||||||
in.open(filename);
|
|
||||||
|
|
||||||
std::stringstream source_stream;
|
SourcesManager sources_manager;
|
||||||
|
|
||||||
source_stream << in.rdbuf();
|
sources_manager.add_file(filename);
|
||||||
|
sources_manager.print(std::cout);
|
||||||
in.close();
|
|
||||||
|
|
||||||
std::string source = source_stream.str();
|
|
||||||
|
|
||||||
parser::ParseTree parse_tree(source);
|
|
||||||
|
|
||||||
if (!parse_tree.is_properly_parsed()) {
|
|
||||||
error_handling::handle_parsing_error(
|
|
||||||
"There are some parsing errors in file", parse_tree.get_root());
|
|
||||||
}
|
|
||||||
|
|
||||||
nodes::ExpressionStorage expression_storage;
|
|
||||||
nodes::TypeStorage type_storage;
|
|
||||||
names::NameTree name_tree;
|
|
||||||
|
|
||||||
auto statements = builders::build_source_file(
|
|
||||||
parse_tree.get_root(), expression_storage, type_storage, name_tree);
|
|
||||||
|
|
||||||
printers::Printer printer(std::cout, 2, 80, true);
|
|
||||||
printers::print_source_file(statements, printer);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,36 +5,51 @@
|
||||||
|
|
||||||
namespace names {
|
namespace names {
|
||||||
|
|
||||||
|
// --- AnyStatementProxy
|
||||||
|
|
||||||
|
nodes::Statement *AnyStatementProxy::get() {
|
||||||
|
return name_tree_->nodes_.at(id_).get_statement().value();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodes::Statement *AnyStatementProxy::get() const {
|
||||||
|
return name_tree_->nodes_.at(id_).get_statement().value();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- NameTree
|
||||||
|
|
||||||
// --- public
|
// --- public
|
||||||
|
|
||||||
bool NameTree::insert(const std::string &path, nodes::Statement &&statement) {
|
std::optional<AnyStatementProxy>
|
||||||
|
NameTree::insert(const std::string &path, nodes::Statement &&statement) {
|
||||||
auto name_ids = slice_path_to_name_ids(path);
|
auto name_ids = slice_path_to_name_ids(path);
|
||||||
|
|
||||||
size_t node_id = add_node(get_root(), name_ids);
|
size_t node_id = add_node(get_root(), name_ids);
|
||||||
|
|
||||||
if (nodes_[node_id].get_statement().has_value()) {
|
if (nodes_[node_id].get_statement().has_value()) {
|
||||||
return false;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes_[node_id].set_statement(std::move(statement));
|
nodes_[node_id].set_statement(std::move(statement));
|
||||||
return true;
|
return AnyStatementProxy(*this, node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes::CombineResult NameTree::insert_combine(const std::string &path,
|
std::pair<std::optional<AnyStatementProxy>, nodes::CombineResult>
|
||||||
nodes::Statement &&statement) {
|
NameTree::insert_combine(const std::string &path,
|
||||||
|
nodes::Statement &&statement) {
|
||||||
auto name_ids = slice_path_to_name_ids(path);
|
auto name_ids = slice_path_to_name_ids(path);
|
||||||
|
|
||||||
size_t node_id = add_node(get_root(), name_ids);
|
size_t node_id = add_node(get_root(), name_ids);
|
||||||
|
|
||||||
if (!nodes_[node_id].get_statement().has_value()) {
|
if (!nodes_[node_id].get_statement().has_value()) {
|
||||||
nodes_[node_id].set_statement(std::move(statement));
|
nodes_[node_id].set_statement(std::move(statement));
|
||||||
return nodes::CombineResult::OK;
|
return {AnyStatementProxy(*this, node_id), nodes::CombineResult::OK};
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodes_[node_id].get_statement().value()->combine(std::move(statement));
|
return {std::nullopt, nodes_[node_id].get_statement().value()->combine(
|
||||||
|
std::move(statement))};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<nodes::Statement *> NameTree::find(const std::string &path) {
|
std::optional<AnyStatementProxy> NameTree::find(const std::string &path) {
|
||||||
auto name_ids = slice_path_to_existing_name_ids(path);
|
auto name_ids = slice_path_to_existing_name_ids(path);
|
||||||
|
|
||||||
if (!name_ids.has_value()) {
|
if (!name_ids.has_value()) {
|
||||||
|
|
@ -44,24 +59,7 @@ std::optional<nodes::Statement *> NameTree::find(const std::string &path) {
|
||||||
auto node_id = find_node(get_root(), name_ids.value());
|
auto node_id = find_node(get_root(), name_ids.value());
|
||||||
|
|
||||||
if (node_id.has_value()) {
|
if (node_id.has_value()) {
|
||||||
return nodes_[node_id.value()].get_statement();
|
return AnyStatementProxy(*this, node_id.value());
|
||||||
}
|
|
||||||
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<const nodes::Statement *>
|
|
||||||
NameTree::find(const std::string &path) const {
|
|
||||||
auto name_ids = slice_path_to_existing_name_ids(path);
|
|
||||||
|
|
||||||
if (!name_ids.has_value()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto node_id = find_node(get_root(), name_ids.value());
|
|
||||||
|
|
||||||
if (node_id.has_value()) {
|
|
||||||
return nodes_[node_id.value()].get_statement();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
@ -71,33 +69,34 @@ void NameTree::print(printers::Printer &printer) const {
|
||||||
nodes_[get_root()].print(nodes_, printer);
|
nodes_[get_root()].print(nodes_, printer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// // TODO
|
||||||
void NameTree::add_statement_children_to_tree() {
|
// void NameTree::add_statement_children_to_tree() {
|
||||||
for (auto &node : nodes_) {
|
// for (auto &node : nodes_) {
|
||||||
if (!node.get_statement().has_value()) {
|
// if (!node.get_statement().has_value()) {
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
switch (node.get_statement().value()->get_any()->index()) {
|
// switch (node.get_statement().value()->get_any()->index()) {
|
||||||
case 0: // Import
|
// case 0: // Import
|
||||||
// TODO: link imported symbols, if named import, otherwise link imported
|
// // TODO: link imported symbols, if named import, otherwise link
|
||||||
// symbols to root
|
// imported
|
||||||
break;
|
// // symbols to root
|
||||||
case 1: // FunctionDefinition
|
// break;
|
||||||
// TODO: link to result type
|
// case 1: // FunctionDefinition
|
||||||
break;
|
// // TODO: link to result type
|
||||||
case 2: // TypeDefinition
|
// break;
|
||||||
// TODO: link methods + link children to types + connect to typeclasses
|
// case 2: // TypeDefinition
|
||||||
break;
|
// // TODO: link methods + link children to types + connect to typeclasses
|
||||||
case 3: // EmptyLines
|
// break;
|
||||||
break;
|
// case 3: // EmptyLines
|
||||||
default:
|
// break;
|
||||||
error_handling::handle_general_error(
|
// default:
|
||||||
"Unexpected statement type in name tree");
|
// error_handling::handle_general_error(
|
||||||
break;
|
// "Unexpected statement type in name tree");
|
||||||
}
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// --- private
|
// --- private
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,11 +96,13 @@ build_statement(parser::ParseTree::Node parser_node,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (statement_name.has_value()) {
|
if (statement_name.has_value()) {
|
||||||
// TODO: combine statements with same name
|
|
||||||
auto statement_copy = statement.value();
|
auto statement_copy = statement.value();
|
||||||
if (!name_tree.insert(statement_name.value(), std::move(statement_copy))) {
|
if (name_tree
|
||||||
|
.insert_combine(statement_name.value(), std::move(statement_copy))
|
||||||
|
.second != nodes::CombineResult::OK) {
|
||||||
|
// TODO: more detailed errors
|
||||||
error_handling::handle_parsing_error(
|
error_handling::handle_parsing_error(
|
||||||
"Two or more statements in file have the same name", parser_node);
|
"Can't combine statements with same name", parser_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#include "../include/type_nodes.hpp"
|
#include "type_nodes.hpp"
|
||||||
|
|
||||||
namespace nodes {
|
namespace nodes {
|
||||||
|
|
||||||
|
|
|
||||||
9
src/types.cpp
Normal file
9
src/types.cpp
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#include "types.hpp"
|
||||||
|
|
||||||
|
namespace types {
|
||||||
|
|
||||||
|
Type *TypeProxy::get() { return type_storage_->get_type(id_); }
|
||||||
|
|
||||||
|
const Type *TypeProxy::get() const { return type_storage_->get_type(id_); }
|
||||||
|
|
||||||
|
} // namespace types
|
||||||
Loading…
Add table
Add a link
Reference in a new issue