mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-09 08:28:44 +00:00
folder structure refactoring
This commit is contained in:
parent
ef88e6af86
commit
78c696b99a
30 changed files with 40 additions and 22 deletions
160
include/nodes/basic_nodes.hpp
Normal file
160
include/nodes/basic_nodes.hpp
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
namespace nodes {
|
||||
|
||||
// replace enum with structure ??
|
||||
enum class Modifier {
|
||||
IN, // <- x
|
||||
REF, // <> x
|
||||
CONST, // -- x (or nothing sometimes)
|
||||
OUT, // -> x
|
||||
//
|
||||
IN_OR_REF, // <-|<> x
|
||||
IN_OR_CONST, // <-|-- x
|
||||
REF_OR_OUT, // <>|-> x
|
||||
CONST_OR_OUT, // --|-> x
|
||||
REF_OR_CONST, // <>|-- x
|
||||
IN_OR_OUT, // <-|-> x
|
||||
//
|
||||
IN_OR_REF_OR_OUT, // <-|<>|-> x
|
||||
IN_OR_CONST_OR_OUT, // <-|--|-> x
|
||||
IN_OR_REF_OR_CONST, // <-|<>|-- x
|
||||
REF_OR_CONST_OR_OUT, //<>|--|-> x
|
||||
//
|
||||
IN_OR_REF_OR_CONST_OR_OUT, //<-|<>|--|-> x
|
||||
OPTIONAL, // x?
|
||||
RESULT, // x!
|
||||
NONE,
|
||||
};
|
||||
|
||||
class Node {
|
||||
public:
|
||||
Node(std::pair<size_t, size_t> start_position,
|
||||
std::pair<size_t, size_t> end_position)
|
||||
: start_position_(start_position), end_position_(end_position) {}
|
||||
|
||||
std::pair<size_t, size_t> get_start_position() const {
|
||||
return start_position_;
|
||||
}
|
||||
|
||||
std::pair<size_t, size_t> get_end_position() const { return end_position_; }
|
||||
|
||||
protected:
|
||||
std::pair<size_t, size_t> start_position_;
|
||||
std::pair<size_t, size_t> end_position_;
|
||||
};
|
||||
|
||||
struct unit {};
|
||||
struct null {};
|
||||
|
||||
class Literal : public Node {
|
||||
public:
|
||||
template <typename T>
|
||||
Literal(Node node, T &&value) : Node(node), value_(std::forward<T>(value)) {}
|
||||
|
||||
template <typename T> std::optional<T *> get() {
|
||||
if (std::holds_alternative<T>(value_)) {
|
||||
return &std::get<T>(value_);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template <typename T> std::optional<const T *> get() const {
|
||||
if (std::holds_alternative<T>(value_)) {
|
||||
return &std::get<T>(value_);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto get_any() { return &value_; }
|
||||
|
||||
auto get_any() const { return &value_; }
|
||||
|
||||
private:
|
||||
std::variant<double, long long, std::string, char, bool, unit, null> value_;
|
||||
};
|
||||
|
||||
class Identifier : public Node {
|
||||
public:
|
||||
enum IdentifierType {
|
||||
SIMPLE_NAME,
|
||||
SIMPLE_TYPE,
|
||||
TYPECLASS,
|
||||
ARGUMENT_NAME,
|
||||
ARGUMENT_TYPE,
|
||||
// ANNOTATION, used as std::string
|
||||
OPERATOR,
|
||||
PLACEHOLDER,
|
||||
};
|
||||
|
||||
Identifier(Node node, IdentifierType type, std::string &&value)
|
||||
: Node(node), type_(type), value_(std::move(value)) {}
|
||||
|
||||
Identifier(Node node, IdentifierType type, const std::string &value)
|
||||
: Node(node), type_(type), value_(value) {}
|
||||
|
||||
IdentifierType get_type() const { return type_; }
|
||||
|
||||
//
|
||||
|
||||
std::string *get() { return &value_; }
|
||||
|
||||
const std::string *get() const { return &value_; }
|
||||
|
||||
//
|
||||
|
||||
void append_before(const std::string &name) { value_ = name + "." + value_; }
|
||||
|
||||
void append_after(const std::string &name) {
|
||||
value_ += ".";
|
||||
value_ += name;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
bool operator==(const Identifier &other_identifier) const {
|
||||
return type_ == other_identifier.type_ && value_ == other_identifier.value_;
|
||||
}
|
||||
|
||||
bool operator!=(const Identifier &other_identifier) const {
|
||||
return !(*this == other_identifier);
|
||||
}
|
||||
|
||||
private:
|
||||
IdentifierType type_;
|
||||
std::string value_;
|
||||
};
|
||||
|
||||
class Extra : public Node {
|
||||
public:
|
||||
Extra(Node node, std::string &&content)
|
||||
: Node(node), content_(std::move(content)) {}
|
||||
|
||||
Extra(Node node, const std::string &content)
|
||||
: Node(node), content_(content) {}
|
||||
|
||||
std::string *content() { return &content_; }
|
||||
|
||||
const std::string *content() const { return &content_; }
|
||||
|
||||
private:
|
||||
std::string content_;
|
||||
};
|
||||
|
||||
class EmptyLines : public Node {
|
||||
public:
|
||||
EmptyLines(Node node, size_t line_count)
|
||||
: Node(node), line_count_(line_count) {}
|
||||
|
||||
size_t line_count() const { return line_count_; }
|
||||
|
||||
private:
|
||||
size_t line_count_;
|
||||
};
|
||||
|
||||
} // namespace nodes
|
||||
102
include/nodes/doc_nodes.hpp
Normal file
102
include/nodes/doc_nodes.hpp
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace nodes {
|
||||
|
||||
class SymbolDocs {
|
||||
public:
|
||||
SymbolDocs() {}
|
||||
|
||||
SymbolDocs(std::string &&description)
|
||||
: description_(std::move(description)) {}
|
||||
|
||||
SymbolDocs(const std::string &description) : description_(description) {}
|
||||
|
||||
bool add_annotation_info(const std::string &annotation, std::string &&info) {
|
||||
if (annotations_info_ids_.count(annotation) == 0) {
|
||||
annotations_info_ids_[annotation] = annotations_info_.size();
|
||||
annotations_info_.emplace_back(annotation, std::move(info));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool add_annotation_info(const std::string &annotation,
|
||||
const std::string &info) {
|
||||
if (annotations_info_ids_.count(annotation) == 0) {
|
||||
annotations_info_ids_[annotation] = annotations_info_.size();
|
||||
annotations_info_.emplace_back(annotation, std::move(info));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
std::optional<std::string *> get_description() {
|
||||
if (description_.has_value()) {
|
||||
return &description_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const std::string *> get_description() const {
|
||||
if (description_.has_value()) {
|
||||
return &description_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
std::optional<std::string *>
|
||||
get_annotation_info(const std::string &annotation) {
|
||||
auto info_iterator = annotations_info_ids_.find(annotation);
|
||||
if (info_iterator != annotations_info_ids_.end()) {
|
||||
return &annotations_info_[info_iterator->second].second;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const std::string *>
|
||||
get_annotation_info(const std::string &annotation) const {
|
||||
auto info_iterator = annotations_info_ids_.find(annotation);
|
||||
if (info_iterator != annotations_info_ids_.end()) {
|
||||
return &annotations_info_[info_iterator->second].second;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
size_t get_annotations_info_size() const { return annotations_info_.size(); }
|
||||
|
||||
std::string *get_annotation(size_t id) {
|
||||
return &annotations_info_[id].first;
|
||||
}
|
||||
|
||||
const std::string *get_annotation(size_t id) const {
|
||||
return &annotations_info_[id].first;
|
||||
}
|
||||
|
||||
std::string *get_annotation_info(size_t id) {
|
||||
return &annotations_info_[id].second;
|
||||
}
|
||||
|
||||
const std::string *get_annotation_info(size_t id) const {
|
||||
return &annotations_info_[id].second;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
private:
|
||||
std::optional<std::string> description_;
|
||||
std::vector<std::pair<std::string, std::string>> annotations_info_;
|
||||
std::unordered_map<std::string, size_t> annotations_info_ids_;
|
||||
};
|
||||
|
||||
} // namespace nodes
|
||||
597
include/nodes/expression_nodes.hpp
Normal file
597
include/nodes/expression_nodes.hpp
Normal file
|
|
@ -0,0 +1,597 @@
|
|||
#pragma once
|
||||
|
||||
#include "basic_nodes.hpp"
|
||||
#include "type_nodes.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace nodes {
|
||||
|
||||
class Expression;
|
||||
class ExpressionStorage;
|
||||
|
||||
class ExpressionProxy {
|
||||
friend ExpressionStorage;
|
||||
|
||||
public:
|
||||
ExpressionProxy() = delete;
|
||||
|
||||
Expression *get();
|
||||
|
||||
const Expression *get() const;
|
||||
|
||||
private:
|
||||
ExpressionProxy(ExpressionStorage &expression_storage, size_t id)
|
||||
: expression_storage_(&expression_storage), id_(id) {}
|
||||
|
||||
private:
|
||||
ExpressionStorage *expression_storage_;
|
||||
size_t id_;
|
||||
};
|
||||
|
||||
namespace utils {
|
||||
|
||||
inline std::optional<nodes::Expression *>
|
||||
proxy_to_expr_optional(std::optional<nodes::ExpressionProxy> &proxy) {
|
||||
if (proxy.has_value()) {
|
||||
return proxy.value().get();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
inline std::optional<const nodes::Expression *>
|
||||
proxy_to_expr_optional(const std::optional<nodes::ExpressionProxy> &proxy) {
|
||||
if (proxy.has_value()) {
|
||||
return proxy.value().get();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
||||
// --- flow control
|
||||
|
||||
class Match : public Node {
|
||||
public:
|
||||
class Case : public Node {
|
||||
public:
|
||||
enum CaseType {
|
||||
PATTERN_VALUE,
|
||||
VALUE_PATTERN,
|
||||
};
|
||||
|
||||
Case(Node node, CaseType case_type, ExpressionProxy value,
|
||||
std::optional<ExpressionProxy> condition = std::nullopt,
|
||||
std::optional<ExpressionProxy> expression = std::nullopt)
|
||||
: Node(node), case_type_(case_type), value_(value),
|
||||
condition_(condition), expression_(expression) {}
|
||||
|
||||
CaseType case_type() const { return case_type_; }
|
||||
|
||||
Expression *get_value() { return value_.get(); }
|
||||
|
||||
const Expression *get_value() const { return value_.get(); }
|
||||
|
||||
std::optional<Expression *> get_condition() {
|
||||
return utils::proxy_to_expr_optional(condition_);
|
||||
}
|
||||
|
||||
std::optional<const Expression *> get_condition() const {
|
||||
return utils::proxy_to_expr_optional(condition_);
|
||||
}
|
||||
|
||||
std::optional<Expression *> get_expression() {
|
||||
return utils::proxy_to_expr_optional(expression_);
|
||||
}
|
||||
|
||||
std::optional<const Expression *> get_expression() const {
|
||||
return utils::proxy_to_expr_optional(expression_);
|
||||
}
|
||||
|
||||
private:
|
||||
CaseType case_type_;
|
||||
ExpressionProxy value_;
|
||||
std::optional<ExpressionProxy> condition_;
|
||||
std::optional<ExpressionProxy> expression_;
|
||||
};
|
||||
|
||||
Match(Node node, ExpressionProxy value, std::vector<Case> &&cases)
|
||||
: Node(node), value_(value), cases_(std::move(cases)) {}
|
||||
|
||||
Match(Node node, ExpressionProxy value, const std::vector<Case> &cases)
|
||||
: Node(node), value_(value), cases_(cases) {}
|
||||
|
||||
Expression *get_value() { return value_.get(); }
|
||||
|
||||
const Expression *get_value() const { return value_.get(); }
|
||||
|
||||
size_t cases_size() const { return cases_.size(); }
|
||||
|
||||
Case *get_case(size_t id) { return &cases_.at(id); }
|
||||
|
||||
const Case *get_case(size_t id) const { return &cases_.at(id); }
|
||||
|
||||
private:
|
||||
ExpressionProxy value_;
|
||||
std::vector<Case> cases_;
|
||||
};
|
||||
|
||||
class Condition : public Node {
|
||||
public:
|
||||
Condition(Node node,
|
||||
std::vector<std::pair<ExpressionProxy, ExpressionProxy>> &&cases,
|
||||
std::optional<ExpressionProxy> else_case = std::nullopt)
|
||||
: Node(node), cases_(std::move(cases)), else_case_(else_case) {}
|
||||
|
||||
Condition(
|
||||
Node node,
|
||||
const std::vector<std::pair<ExpressionProxy, ExpressionProxy>> &cases,
|
||||
std::optional<ExpressionProxy> else_case = std::nullopt)
|
||||
: Node(node), cases_(cases), else_case_(else_case) {}
|
||||
|
||||
size_t cases_size() const { return cases_.size(); }
|
||||
|
||||
std::pair<Expression *, Expression *> get_case(size_t id) {
|
||||
return {cases_.at(id).first.get(), cases_[id].second.get()};
|
||||
}
|
||||
|
||||
std::pair<const Expression *, const Expression *> get_case(size_t id) const {
|
||||
return {cases_.at(id).first.get(), cases_[id].second.get()};
|
||||
}
|
||||
|
||||
std::optional<Expression *> get_else_case() {
|
||||
return utils::proxy_to_expr_optional(else_case_);
|
||||
}
|
||||
|
||||
std::optional<const Expression *> get_else_case() const {
|
||||
return utils::proxy_to_expr_optional(else_case_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::pair<ExpressionProxy, ExpressionProxy>> cases_;
|
||||
std::optional<ExpressionProxy> else_case_;
|
||||
};
|
||||
|
||||
class Loop : public Node {
|
||||
public:
|
||||
enum LoopType {
|
||||
LOOP,
|
||||
WHILE,
|
||||
FOR,
|
||||
};
|
||||
|
||||
// LOOP
|
||||
Loop(Node node, ExpressionProxy expression)
|
||||
: Node(node), type_(LOOP), expression_(expression) {}
|
||||
|
||||
// WHILE
|
||||
Loop(Node node, ExpressionProxy condition, ExpressionProxy expression)
|
||||
: Node(node), type_(WHILE), expression_(expression),
|
||||
condition_(condition) {}
|
||||
|
||||
// FOR
|
||||
Loop(Node node, ExpressionProxy variable, ExpressionProxy interval,
|
||||
ExpressionProxy expression)
|
||||
: Node(node), type_(FOR), expression_(expression), variable_(variable),
|
||||
interval_(interval) {}
|
||||
|
||||
LoopType get_type() const { return type_; }
|
||||
|
||||
Expression *get_expression() { return expression_.get(); }
|
||||
|
||||
const Expression *get_expression() const { return expression_.get(); }
|
||||
|
||||
std::optional<Expression *> get_condition() {
|
||||
return utils::proxy_to_expr_optional(condition_);
|
||||
}
|
||||
|
||||
std::optional<const Expression *> get_condition() const {
|
||||
return utils::proxy_to_expr_optional(condition_);
|
||||
}
|
||||
|
||||
std::optional<Expression *> get_variable() {
|
||||
return utils::proxy_to_expr_optional(variable_);
|
||||
}
|
||||
|
||||
std::optional<const Expression *> get_variable() const {
|
||||
return utils::proxy_to_expr_optional(variable_);
|
||||
}
|
||||
|
||||
std::optional<Expression *> get_interval() {
|
||||
return utils::proxy_to_expr_optional(interval_);
|
||||
}
|
||||
|
||||
std::optional<const Expression *> get_interval() const {
|
||||
return utils::proxy_to_expr_optional(interval_);
|
||||
}
|
||||
|
||||
private:
|
||||
LoopType type_;
|
||||
|
||||
ExpressionProxy expression_;
|
||||
|
||||
std::optional<ExpressionProxy> condition_;
|
||||
std::optional<ExpressionProxy> variable_;
|
||||
std::optional<ExpressionProxy> interval_;
|
||||
};
|
||||
|
||||
// --- containers
|
||||
|
||||
class Container : public Node {
|
||||
public:
|
||||
enum ContainerType {
|
||||
BLOCK,
|
||||
ARRAY,
|
||||
};
|
||||
|
||||
Container(Node node, ContainerType type,
|
||||
std::vector<ExpressionProxy> &&expressions)
|
||||
: Node(node), type_(type), expressions_(std::move(expressions)) {}
|
||||
|
||||
Container(Node node, ContainerType type,
|
||||
const std::vector<ExpressionProxy> &expressions)
|
||||
: Node(node), type_(type), expressions_(expressions) {}
|
||||
|
||||
ContainerType get_type() const { return type_; }
|
||||
|
||||
size_t expressions_size() const { return expressions_.size(); }
|
||||
|
||||
Expression *get_expression(size_t id) { return expressions_.at(id).get(); }
|
||||
|
||||
const Expression *get_expression(size_t id) const {
|
||||
return expressions_.at(id).get();
|
||||
}
|
||||
|
||||
private:
|
||||
ContainerType type_;
|
||||
|
||||
std::vector<ExpressionProxy> expressions_;
|
||||
};
|
||||
|
||||
// --- modifiers
|
||||
|
||||
class Return : public Node {
|
||||
public:
|
||||
enum ReturnType {
|
||||
RETURN,
|
||||
BRING,
|
||||
};
|
||||
|
||||
Return(Node node, ReturnType type, ExpressionProxy expression)
|
||||
: Node(node), type_(type), expression_(expression) {}
|
||||
|
||||
ReturnType get_type() const { return type_; }
|
||||
|
||||
Expression *get_expression() { return expression_.get(); }
|
||||
|
||||
const Expression *get_expression() const { return expression_.get(); }
|
||||
|
||||
private:
|
||||
ReturnType type_;
|
||||
|
||||
ExpressionProxy expression_;
|
||||
};
|
||||
|
||||
class NameDefinition : public Node {
|
||||
public:
|
||||
enum Modifier {
|
||||
LET, // %
|
||||
VAR, // $
|
||||
};
|
||||
|
||||
NameDefinition(Node node, Modifier modifier, Identifier &&name)
|
||||
: Node(node), modifier_(modifier), name_(std::move(name)) {}
|
||||
|
||||
NameDefinition(Node node, Modifier modifier, const Identifier &name)
|
||||
: Node(node), modifier_(modifier), name_(name) {}
|
||||
|
||||
Modifier get_modifier() const { return modifier_; }
|
||||
|
||||
Identifier *get_name() { return &name_; }
|
||||
|
||||
const Identifier *get_name() const { return &name_; }
|
||||
|
||||
private:
|
||||
Modifier modifier_;
|
||||
|
||||
Identifier name_;
|
||||
};
|
||||
|
||||
class Access : public Node {
|
||||
public:
|
||||
enum AccessType {
|
||||
ARRAY,
|
||||
TUPLE, // only number literal index allowed
|
||||
};
|
||||
|
||||
Access(Node node, AccessType type, ExpressionProxy value,
|
||||
ExpressionProxy index)
|
||||
: Node(node), type_(type), value_(value), index_(index) {}
|
||||
|
||||
AccessType get_type() const { return type_; }
|
||||
|
||||
Expression *get_value() { return value_.get(); }
|
||||
|
||||
const Expression *get_value() const { return value_.get(); }
|
||||
|
||||
Expression *get_index() { return index_.get(); }
|
||||
|
||||
const Expression *get_index() const { return index_.get(); }
|
||||
|
||||
private:
|
||||
AccessType type_;
|
||||
|
||||
ExpressionProxy value_;
|
||||
ExpressionProxy index_;
|
||||
};
|
||||
|
||||
class LoopControl : public Node {
|
||||
public:
|
||||
enum LoopControlType {
|
||||
BREAK,
|
||||
CONTINUE,
|
||||
};
|
||||
|
||||
LoopControl(Node node, LoopControlType type) : Node(node), type_(type) {}
|
||||
|
||||
LoopControlType get_type() const { return type_; }
|
||||
|
||||
private:
|
||||
LoopControlType type_;
|
||||
};
|
||||
|
||||
class ModifierExpression : public Node {
|
||||
public:
|
||||
ModifierExpression(Node node, Modifier modifier, ExpressionProxy expression)
|
||||
: Node(node), modifier_(modifier), expression_(expression) {}
|
||||
|
||||
Modifier get_modifier() const { return modifier_; }
|
||||
|
||||
Expression *get_expression() { return expression_.get(); }
|
||||
|
||||
const Expression *get_expression() const { return expression_.get(); }
|
||||
|
||||
private:
|
||||
Modifier modifier_;
|
||||
|
||||
ExpressionProxy expression_;
|
||||
};
|
||||
|
||||
// --- other
|
||||
|
||||
class NameExpression : public Node {
|
||||
public:
|
||||
NameExpression(Node node, Identifier &&name)
|
||||
: Node(node), name_(std::move(name)) {}
|
||||
|
||||
NameExpression(Node node, const Identifier &name) : Node(node), name_(name) {}
|
||||
|
||||
NameExpression(
|
||||
Node node, Identifier &&name,
|
||||
std::vector<std::pair<std::optional<std::string>, ExpressionProxy>>
|
||||
&&arguments,
|
||||
std::optional<TypeProxy> &&prefix, bool is_point_call = false,
|
||||
bool is_operator_call = false)
|
||||
: Node(node), name_(std::move(name)), arguments_(std::move(arguments)),
|
||||
prefix_(std::move(prefix)), is_point_call_(is_point_call),
|
||||
is_operator_call_(is_operator_call) {}
|
||||
|
||||
Identifier *get_name() { return &name_; }
|
||||
|
||||
const Identifier *get_name() const { return &name_; }
|
||||
|
||||
std::optional<Type *> get_prefix() {
|
||||
if (prefix_.has_value()) {
|
||||
return prefix_.value().get();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const Type *> get_prefix() const {
|
||||
if (prefix_.has_value()) {
|
||||
return prefix_.value().get();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
size_t arguments_size() const { return arguments_.size(); }
|
||||
|
||||
Expression *get_argument_value(size_t id) {
|
||||
return arguments_.at(id).second.get();
|
||||
}
|
||||
|
||||
const Expression *get_argument_value(size_t id) const {
|
||||
return arguments_.at(id).second.get();
|
||||
}
|
||||
|
||||
std::optional<std::string *> get_argument_annotation(size_t id) {
|
||||
if (arguments_.at(id).first.has_value()) {
|
||||
return &arguments_[id].first.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const std::string *> get_argument_annotation(size_t id) const {
|
||||
if (arguments_.at(id).first.has_value()) {
|
||||
return &arguments_[id].first.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool is_point_call() const { return is_point_call_; }
|
||||
|
||||
bool is_operator_call() const { return is_operator_call_; }
|
||||
|
||||
private:
|
||||
Identifier name_;
|
||||
// universal function call syntax
|
||||
std::vector<std::pair<std::optional<std::string>, ExpressionProxy>>
|
||||
arguments_;
|
||||
std::optional<TypeProxy> prefix_;
|
||||
// for static methods
|
||||
bool is_point_call_ = false; // x.f ... or f x ...
|
||||
bool is_operator_call_ = false; // ... operator ...
|
||||
};
|
||||
|
||||
class Constructor : public Node {
|
||||
public:
|
||||
Constructor(
|
||||
Node node, TypeProxy type,
|
||||
std::vector<std::pair<std::optional<std::string>, ExpressionProxy>>
|
||||
&&arguments)
|
||||
: Node(node), type_(type), arguments_(std::move(arguments)) {}
|
||||
|
||||
Constructor(
|
||||
Node node, TypeProxy type,
|
||||
const std::vector<std::pair<std::optional<std::string>, ExpressionProxy>>
|
||||
&arguments)
|
||||
: Node(node), type_(type), arguments_(arguments) {}
|
||||
|
||||
Type *get_type() { return type_.get(); }
|
||||
|
||||
const Type *get_type() const { return type_.get(); }
|
||||
|
||||
size_t arguments_size() const { return arguments_.size(); }
|
||||
|
||||
Expression *get_argument_value(size_t id) {
|
||||
return arguments_.at(id).second.get();
|
||||
}
|
||||
|
||||
const Expression *get_argument_value(size_t id) const {
|
||||
return arguments_.at(id).second.get();
|
||||
}
|
||||
|
||||
std::optional<std::string *> get_argument_annotation(size_t id) {
|
||||
if (arguments_.at(id).first.has_value()) {
|
||||
return &arguments_[id].first.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const std::string *> get_argument_annotation(size_t id) const {
|
||||
if (arguments_.at(id).first.has_value()) {
|
||||
return &arguments_[id].first.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
private:
|
||||
TypeProxy type_;
|
||||
std::vector<std::pair<std::optional<std::string>, ExpressionProxy>>
|
||||
arguments_;
|
||||
};
|
||||
|
||||
class Lambda : public Node {
|
||||
public:
|
||||
Lambda(Node node, std::vector<Identifier> &&arguments,
|
||||
ExpressionProxy expression)
|
||||
: Node(node), arguments_(std::move(arguments)), expression_(expression) {}
|
||||
|
||||
Lambda(Node node, const std::vector<Identifier> &arguments,
|
||||
ExpressionProxy expression)
|
||||
: Node(node), arguments_(arguments), expression_(expression) {}
|
||||
|
||||
size_t arguments_size() const { return arguments_.size(); }
|
||||
|
||||
Identifier *get_argument(size_t id) { return &arguments_.at(id); }
|
||||
|
||||
const Identifier *get_argument(size_t id) const { return &arguments_.at(id); }
|
||||
|
||||
Expression *get_expression() { return expression_.get(); }
|
||||
|
||||
const Expression *get_expression() const { return expression_.get(); }
|
||||
|
||||
private:
|
||||
std::vector<Identifier> arguments_;
|
||||
ExpressionProxy expression_;
|
||||
};
|
||||
|
||||
class Expression {
|
||||
public:
|
||||
template <typename T>
|
||||
Expression(T &&expression, bool is_scoped)
|
||||
: expression_(std::forward<T>(expression)), is_scoped_(is_scoped) {}
|
||||
|
||||
template <typename T> std::optional<T *> get() {
|
||||
if (std::holds_alternative<T>(expression_)) {
|
||||
return &std::get<T>(expression_);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template <typename T> std::optional<const T *> get() const {
|
||||
if (std::holds_alternative<T>(expression_)) {
|
||||
return &std::get<T>(expression_);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto get_any() { return &expression_; }
|
||||
|
||||
auto get_any() const { return &expression_; }
|
||||
|
||||
bool is_scoped() const { return is_scoped_; }
|
||||
|
||||
private:
|
||||
std::variant<
|
||||
// --- flow control
|
||||
Match, Condition, Loop,
|
||||
|
||||
// --- operators
|
||||
// CommaExpression is OperatorExpression for operator ','
|
||||
// OperatorExpression is NameExpression with two arguments
|
||||
|
||||
// --- containers
|
||||
// Block value is brought value ("bring x")
|
||||
// Array value is array of expression's values
|
||||
Container,
|
||||
|
||||
// --- modifiers
|
||||
Return, NameDefinition,
|
||||
// TupleAccess - Access with nmber Literal index
|
||||
Access, LoopControl,
|
||||
// Reference or SuffixExpression is ModifierExpression
|
||||
ModifierExpression,
|
||||
|
||||
// --- other
|
||||
NameExpression, Constructor, Lambda,
|
||||
|
||||
// --- literal
|
||||
Literal,
|
||||
|
||||
// --- extra
|
||||
Extra,
|
||||
|
||||
// --- empty lines
|
||||
EmptyLines>
|
||||
expression_;
|
||||
|
||||
bool is_scoped_ = false;
|
||||
};
|
||||
|
||||
class ExpressionStorage {
|
||||
friend ExpressionProxy;
|
||||
|
||||
public:
|
||||
ExpressionProxy add_expression(const Expression &expression) {
|
||||
storage_.push_back(expression);
|
||||
return ExpressionProxy(*this, storage_.size() - 1);
|
||||
}
|
||||
|
||||
ExpressionProxy add_expression(Expression &&expression) {
|
||||
storage_.push_back(std::move(expression));
|
||||
return ExpressionProxy(*this, storage_.size() - 1);
|
||||
}
|
||||
|
||||
private:
|
||||
Expression *get_expression(size_t id) { return &storage_.at(id); }
|
||||
|
||||
const Expression *get_expression(size_t id) const { return &storage_.at(id); }
|
||||
|
||||
private:
|
||||
std::vector<Expression> storage_;
|
||||
};
|
||||
|
||||
} // namespace nodes
|
||||
439
include/nodes/statement_nodes.hpp
Normal file
439
include/nodes/statement_nodes.hpp
Normal file
|
|
@ -0,0 +1,439 @@
|
|||
#pragma once
|
||||
|
||||
#include "basic_nodes.hpp"
|
||||
#include "doc_nodes.hpp"
|
||||
#include "expression_nodes.hpp"
|
||||
#include "type_nodes.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
// IN PROGRESS
|
||||
|
||||
namespace nodes {
|
||||
|
||||
enum class CombineResult {
|
||||
DIFFERENT_NAME_ERROR,
|
||||
DIFFERNENT_MODIFIER_ERROR,
|
||||
MORE_THEN_ONE_DOCS_ERROR,
|
||||
MORE_THEN_ONE_CONSTRAINTS_ERROR,
|
||||
MORE_THEN_ONE_DEFINITION_BODY_ERROR,
|
||||
TYPECLASSES_ERROR,
|
||||
ARGUMENTS_ERROR,
|
||||
DIFFERENT_STATEMENT_TYPES,
|
||||
STATEMENTS_CANT_BE_COMBINED_ERROR,
|
||||
GENERIC_ERROR,
|
||||
OK,
|
||||
};
|
||||
|
||||
// IN PROGRESS: add another constructors ??
|
||||
class Import : public Node {
|
||||
public:
|
||||
Import(Node node, const Identifier &import_name,
|
||||
const Identifier &module_name, std::vector<Identifier> &&symbols = {})
|
||||
: Node(node), import_name_(import_name), module_name_(module_name),
|
||||
symbols_(std::move(symbols)) {}
|
||||
|
||||
//
|
||||
|
||||
Identifier *get_import_name() { return &import_name_; }
|
||||
|
||||
const Identifier *get_import_name() const { return &import_name_; }
|
||||
|
||||
//
|
||||
|
||||
Identifier *get_module_name() { return &module_name_; }
|
||||
|
||||
const Identifier *get_module_name() const { return &module_name_; }
|
||||
|
||||
//
|
||||
|
||||
size_t symbols_size() const { return symbols_.size(); }
|
||||
|
||||
Identifier *get_symbol(size_t id) { return &symbols_.at(id); }
|
||||
|
||||
const Identifier *get_symbol(size_t id) const { return &symbols_.at(id); }
|
||||
|
||||
private:
|
||||
Identifier import_name_;
|
||||
Identifier module_name_;
|
||||
std::vector<Identifier> symbols_;
|
||||
};
|
||||
|
||||
class Constraint : public Node {
|
||||
public:
|
||||
Constraint(Node node, ExpressionProxy expression)
|
||||
: Node(node), expression_(expression) {}
|
||||
|
||||
Expression *get_expression() { return expression_.get(); }
|
||||
|
||||
const Expression *get_expression() const { return expression_.get(); }
|
||||
|
||||
private:
|
||||
ExpressionProxy expression_;
|
||||
};
|
||||
|
||||
class FunctionDefinition : public Node {
|
||||
public:
|
||||
class Argument {
|
||||
public:
|
||||
Argument(const std::optional<std::string> &annotation, Identifier &&name,
|
||||
Modifier before_modifier = Modifier::NONE,
|
||||
Modifier after_modifier = Modifier::NONE)
|
||||
: annotation_(annotation), name_(std::move(name)),
|
||||
before_modifier_(before_modifier), after_modifier_(after_modifier) {}
|
||||
|
||||
Argument(const std::optional<std::string> &annotation,
|
||||
const Identifier &name, Modifier before_modifier = Modifier::NONE,
|
||||
Modifier after_modifier = Modifier::NONE)
|
||||
: annotation_(annotation), name_(name),
|
||||
before_modifier_(before_modifier), after_modifier_(after_modifier) {}
|
||||
|
||||
Argument(const std::optional<std::string> &annotation, TypeProxy type,
|
||||
Modifier before_modifier = Modifier::NONE)
|
||||
: annotation_(annotation), type_(type),
|
||||
before_modifier_(before_modifier),
|
||||
after_modifier_(type.get()->get_modifier()) {}
|
||||
|
||||
//
|
||||
|
||||
// add type with same annotation and same before_modifier
|
||||
bool update_type_from(const Argument &other_argument) {
|
||||
if (type_.has_value() || !other_argument.type_.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (annotation_.has_value() &&
|
||||
(!other_argument.annotation_.has_value() ||
|
||||
annotation_.value() != other_argument.annotation_.value())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (before_modifier_ != other_argument.before_modifier_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (after_modifier_ != other_argument.after_modifier_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
annotation_ = other_argument.annotation_;
|
||||
type_ = other_argument.type_;
|
||||
before_modifier_ = other_argument.before_modifier_;
|
||||
after_modifier_ = other_argument.after_modifier_;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// check, that argument modifiers are none or same to different from type
|
||||
// modifiers
|
||||
bool add_type(const std::optional<std::string> &annotation, TypeProxy type,
|
||||
nodes::Modifier before_modifier = Modifier::NONE) {
|
||||
if (type_.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (annotation_.has_value() &&
|
||||
(!annotation.has_value() ||
|
||||
annotation_.value() != annotation.value())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (before_modifier_ != Modifier::NONE &&
|
||||
before_modifier_ != before_modifier) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (after_modifier_ != Modifier::NONE &&
|
||||
after_modifier_ != type.get()->get_modifier()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
annotation_ = annotation;
|
||||
type_ = type;
|
||||
before_modifier_ = before_modifier;
|
||||
after_modifier_ = type.get()->get_modifier();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool add_annotation(const std::string &annotation) {
|
||||
if (annotation_.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
annotation_ = annotation;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
std::optional<std::string *> get_annotation() {
|
||||
if (annotation_.has_value()) {
|
||||
return &annotation_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const std::string *> get_annotation() const {
|
||||
if (annotation_.has_value()) {
|
||||
return &annotation_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
std::optional<Identifier *> get_name() {
|
||||
if (name_.has_value()) {
|
||||
return &name_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const Identifier *> get_name() const {
|
||||
if (name_.has_value()) {
|
||||
return &name_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
std::optional<Type *> get_type() {
|
||||
if (type_.has_value()) {
|
||||
return type_.value().get();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const Type *> get_type() const {
|
||||
if (type_.has_value()) {
|
||||
return type_.value().get();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Modifier get_before_modifier() const { return before_modifier_; }
|
||||
|
||||
Modifier get_after_modifier() const { return after_modifier_; }
|
||||
|
||||
private:
|
||||
std::optional<std::string> annotation_;
|
||||
std::optional<Identifier> name_; // no name for output arguments
|
||||
std::optional<TypeProxy> type_; // no type if it is deduced
|
||||
Modifier before_modifier_ =
|
||||
Modifier::NONE; // in, out, ref, none // sync with type
|
||||
Modifier after_modifier_ =
|
||||
Modifier::NONE; // optional, result, none // sync with type
|
||||
};
|
||||
|
||||
FunctionDefinition(Node node, SymbolDocs &&docs,
|
||||
std::vector<Constraint> &&constraints,
|
||||
Modifier return_modifier, bool is_method,
|
||||
const std::optional<Identifier> &name_prefix,
|
||||
const Identifier &name, std::vector<Argument> &&arguments,
|
||||
bool are_annotations_same_to_names,
|
||||
std::optional<ExpressionProxy> expression)
|
||||
: Node(node), docs_(std::move(docs)),
|
||||
constraints_(std::move(constraints)), return_modifier_(return_modifier),
|
||||
is_method_(is_method), name_(name), full_name_(name),
|
||||
arguments_(std::move(arguments)),
|
||||
are_annotations_same_to_names_(are_annotations_same_to_names),
|
||||
expression_(expression) {
|
||||
if (name_prefix.has_value()) {
|
||||
full_name_.append_before(*name_prefix.value().get());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
SymbolDocs *get_docs() { return &docs_; }
|
||||
|
||||
const SymbolDocs *get_docs() const { return &docs_; }
|
||||
|
||||
//
|
||||
|
||||
size_t get_constraints_size() const { return constraints_.size(); }
|
||||
|
||||
Constraint *get_constraint(size_t id) { return &constraints_.at(id); }
|
||||
|
||||
const Constraint *get_constraint(size_t id) const {
|
||||
return &constraints_.at(id);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Modifier get_return_modifier() const { return return_modifier_; }
|
||||
|
||||
bool is_method() const { return is_method_; }
|
||||
|
||||
//
|
||||
|
||||
Identifier *get_name() { return &name_; }
|
||||
|
||||
const Identifier *get_name() const { return &name_; }
|
||||
|
||||
//
|
||||
|
||||
Identifier *get_full_name() { return &full_name_; }
|
||||
|
||||
const Identifier *get_full_name() const { return &full_name_; }
|
||||
|
||||
//
|
||||
|
||||
size_t get_arguments_size() const { return arguments_.size(); }
|
||||
|
||||
Argument *get_argument(size_t id) { return &arguments_.at(id); }
|
||||
|
||||
const Argument *get_argument(size_t id) const { return &arguments_.at(id); }
|
||||
|
||||
//
|
||||
|
||||
std::optional<Expression *> get_expression() {
|
||||
if (expression_.has_value()) {
|
||||
return expression_.value().get();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const Expression *> get_expression() const {
|
||||
if (expression_.has_value()) {
|
||||
return expression_.value().get();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
bool are_annotations_same_to_names() const {
|
||||
return are_annotations_same_to_names_;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
bool is_same_to(const FunctionDefinition &other_function_definition) const;
|
||||
|
||||
CombineResult combine(FunctionDefinition &&other_function_definition);
|
||||
|
||||
private:
|
||||
SymbolDocs docs_;
|
||||
std::vector<Constraint> constraints_;
|
||||
Modifier return_modifier_;
|
||||
bool is_method_;
|
||||
Identifier name_;
|
||||
Identifier full_name_;
|
||||
std::vector<Argument> arguments_;
|
||||
bool are_annotations_same_to_names_; // needed for easier prinitng process
|
||||
std::optional<ExpressionProxy> expression_;
|
||||
}; // refactor ??
|
||||
|
||||
class TypeDefinition : public Node {
|
||||
public:
|
||||
TypeDefinition(Node node, SymbolDocs &&docs, bool is_on_heap,
|
||||
const Identifier &name, std::vector<Identifier> &&typeclasses,
|
||||
std::vector<Identifier> &&arguments,
|
||||
std::optional<VariantType> &&type)
|
||||
: Node(node), docs_(std::move(docs)), is_on_heap_(is_on_heap),
|
||||
name_(name), typeclasses_(typeclasses),
|
||||
arguments_(std::move(arguments)), type_(std::move(type)) {}
|
||||
|
||||
//
|
||||
|
||||
SymbolDocs *get_docs() { return &docs_; }
|
||||
|
||||
const SymbolDocs *get_docs() const { return &docs_; }
|
||||
|
||||
//
|
||||
|
||||
bool is_on_heap() const { return is_on_heap_; }
|
||||
|
||||
//
|
||||
|
||||
Identifier *get_name() { return &name_; }
|
||||
|
||||
const Identifier *get_name() const { return &name_; }
|
||||
|
||||
//
|
||||
|
||||
size_t get_arguments_size() const { return arguments_.size(); }
|
||||
|
||||
Identifier *get_argument(size_t id) { return &arguments_.at(id); }
|
||||
|
||||
const Identifier *get_argument(size_t id) const { return &arguments_.at(id); }
|
||||
|
||||
//
|
||||
|
||||
std::optional<VariantType *> get_type() {
|
||||
if (type_.has_value()) {
|
||||
return &type_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const VariantType *> get_type() const {
|
||||
if (type_.has_value()) {
|
||||
return &type_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
bool is_typeclass() { return name_.get_type() == Identifier::TYPECLASS; }
|
||||
|
||||
//
|
||||
|
||||
bool is_same_to(const TypeDefinition &other_type_definition) const;
|
||||
|
||||
CombineResult combine(TypeDefinition &&other_type_definition);
|
||||
|
||||
private:
|
||||
SymbolDocs docs_;
|
||||
bool is_on_heap_;
|
||||
Identifier name_;
|
||||
std::vector<Identifier> typeclasses_;
|
||||
std::vector<Identifier> arguments_;
|
||||
std::optional<VariantType> type_; // TupleType is VariantType with one variant
|
||||
};
|
||||
|
||||
class Statement {
|
||||
public:
|
||||
Statement(const Statement &) = default;
|
||||
Statement(Statement &&) = default;
|
||||
Statement &operator=(const Statement &) = default;
|
||||
Statement &operator=(Statement &&) = default;
|
||||
|
||||
template <typename T>
|
||||
explicit Statement(T &&statement) : expression_(std::forward<T>(statement)) {}
|
||||
|
||||
template <typename T> std::optional<T *> get() {
|
||||
if (std::holds_alternative<T>(expression_)) {
|
||||
return &std::get<T>(expression_);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template <typename T> std::optional<const T *> get() const {
|
||||
if (std::holds_alternative<T>(expression_)) {
|
||||
return &std::get<T>(expression_);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto get_any() { return &expression_; }
|
||||
|
||||
auto get_any() const { return &expression_; }
|
||||
|
||||
bool is_same_to(const Statement &other_statement) const;
|
||||
|
||||
CombineResult combine(Statement &&other_statement);
|
||||
|
||||
private:
|
||||
std::variant<Import, TypeDefinition, FunctionDefinition, Extra, EmptyLines>
|
||||
expression_;
|
||||
};
|
||||
|
||||
} // namespace nodes
|
||||
215
include/nodes/type_nodes.hpp
Normal file
215
include/nodes/type_nodes.hpp
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
#pragma once
|
||||
|
||||
#include "basic_nodes.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace nodes {
|
||||
|
||||
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_;
|
||||
};
|
||||
|
||||
// can't have both optional and result modifiers ??
|
||||
class Type : public Node {
|
||||
public:
|
||||
Type(Node node, Identifier &&identifier, bool is_on_heap = false,
|
||||
Modifier modifier = Modifier::NONE)
|
||||
: Node(node), name_(std::move(identifier)), is_on_heap_(is_on_heap),
|
||||
modifier_(modifier) {}
|
||||
|
||||
Type(Node node, const Identifier &identifier, bool is_on_heap = false,
|
||||
Modifier modifier = Modifier::NONE)
|
||||
: Node(node), name_(identifier), is_on_heap_(is_on_heap),
|
||||
modifier_(modifier) {}
|
||||
|
||||
Type(Node node, Identifier &&identifier, std::vector<TypeProxy> &¶meters,
|
||||
bool is_on_heap = false, Modifier modifier = Modifier::NONE)
|
||||
: Node(node), name_(std::move(identifier)),
|
||||
parameters_(std::move(parameters)), is_on_heap_(is_on_heap),
|
||||
modifier_(modifier) {}
|
||||
|
||||
Type(Node node, const Identifier &identifier,
|
||||
std::vector<TypeProxy> &¶meters, bool is_on_heap = false,
|
||||
Modifier modifier = Modifier::NONE)
|
||||
: Node(node), name_(identifier), parameters_(std::move(parameters)),
|
||||
is_on_heap_(is_on_heap), modifier_(modifier) {}
|
||||
|
||||
//
|
||||
|
||||
Identifier *get_name() { return &name_; }
|
||||
|
||||
const Identifier *get_name() const { return &name_; }
|
||||
|
||||
//
|
||||
|
||||
size_t get_parametrs_size() const { return parameters_.size(); }
|
||||
|
||||
Type *get_parameter(size_t id) { return parameters_.at(id).get(); }
|
||||
|
||||
const Type *get_parameter(size_t id) const {
|
||||
return parameters_.at(id).get();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
bool is_on_heap() const { return is_on_heap_; }
|
||||
|
||||
Modifier get_modifier() const { return modifier_; }
|
||||
|
||||
//
|
||||
|
||||
bool operator==(const Type &other_type) const {
|
||||
if (name_ != other_type.name_ || is_on_heap_ != other_type.is_on_heap_ ||
|
||||
modifier_ != other_type.modifier_ ||
|
||||
parameters_.size() != other_type.parameters_.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < parameters_.size(); ++i) {
|
||||
if (*parameters_[i].get() != *other_type.parameters_[i].get()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator!=(const Type &other_type) const {
|
||||
return !(*this == other_type);
|
||||
}
|
||||
|
||||
private:
|
||||
Identifier name_;
|
||||
std::vector<TypeProxy> parameters_;
|
||||
// or use allocator ??
|
||||
bool is_on_heap_ = false;
|
||||
Modifier modifier_ = Modifier::NONE; // optional, result or none
|
||||
};
|
||||
|
||||
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_;
|
||||
};
|
||||
|
||||
class TupleType : public Node {
|
||||
public:
|
||||
TupleType(Node node,
|
||||
const std::vector<std::pair<std::optional<std::string>, TypeProxy>>
|
||||
&fields)
|
||||
: Node(node) {
|
||||
annotations_.reserve(fields.size());
|
||||
fields_.reserve(fields.size());
|
||||
for (auto &field : fields) {
|
||||
if (field.first.has_value()) {
|
||||
annotation_fields_[field.first.value()] = fields_.size();
|
||||
}
|
||||
annotations_.push_back(field.first);
|
||||
fields_.push_back(field.second);
|
||||
}
|
||||
}
|
||||
|
||||
size_t size() const { return fields_.size(); }
|
||||
|
||||
std::optional<std::string *> get_annotation(size_t id) {
|
||||
if (annotations_.at(id).has_value()) {
|
||||
return &annotations_[id].value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const std::string *> get_annotation(size_t id) const {
|
||||
if (annotations_.at(id).has_value()) {
|
||||
return &annotations_[id].value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Type *get(size_t id) { return fields_.at(id).get(); }
|
||||
|
||||
const Type *get(size_t id) const { return fields_.at(id).get(); }
|
||||
|
||||
Type *get(const std::string &annotation) {
|
||||
return fields_.at(annotation_fields_.at(annotation)).get();
|
||||
}
|
||||
|
||||
const Type *get(const std::string &annotation) const {
|
||||
return fields_.at(annotation_fields_.at(annotation)).get();
|
||||
}
|
||||
|
||||
std::vector<std::string> get_all_annotations() {
|
||||
std::vector<std::string> annotations;
|
||||
|
||||
annotations.reserve(annotation_fields_.size());
|
||||
for (auto &annotation_with_field : annotation_fields_) {
|
||||
annotations.push_back(annotation_with_field.first);
|
||||
}
|
||||
|
||||
return annotations;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, size_t> annotation_fields_;
|
||||
std::vector<TypeProxy> fields_;
|
||||
std::vector<std::optional<std::string>> annotations_;
|
||||
};
|
||||
|
||||
class VariantType : public Node {
|
||||
public:
|
||||
VariantType(Node node, std::vector<TupleType> &&constructors_)
|
||||
: Node(node), constructors_(std::move(constructors_)) {}
|
||||
|
||||
VariantType(Node node, const std::vector<TupleType> &constructors_)
|
||||
: Node(node), constructors_(constructors_) {}
|
||||
|
||||
size_t size() const { return constructors_.size(); }
|
||||
|
||||
TupleType *get(size_t id) { return &constructors_.at(id); }
|
||||
|
||||
const TupleType *get(size_t id) const { return &constructors_.at(id); }
|
||||
|
||||
private:
|
||||
// named constructors ??
|
||||
std::vector<TupleType> constructors_;
|
||||
};
|
||||
|
||||
} // namespace nodes
|
||||
Loading…
Add table
Add a link
Reference in a new issue