2023-07-18 16:45:35 +03:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include "basic_nodes.hpp"
|
|
|
|
|
#include "type_nodes.hpp"
|
|
|
|
|
|
|
|
|
|
#include <optional>
|
|
|
|
|
#include <variant>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
namespace nodes {
|
|
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
class TypedNode : public Node {
|
|
|
|
|
public:
|
|
|
|
|
TypedNode(Node node) : Node(node) {}
|
|
|
|
|
|
|
|
|
|
void set_expression_type(TypeProxy expression_type) {
|
|
|
|
|
expression_type_ = expression_type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::optional<TypeProxy> get_expression_type() const {
|
|
|
|
|
return expression_type_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
std::optional<TypeProxy> expression_type_;
|
|
|
|
|
};
|
|
|
|
|
|
2023-07-18 16:45:35 +03:00
|
|
|
class Expression;
|
|
|
|
|
class ExpressionStorage;
|
|
|
|
|
|
|
|
|
|
class ExpressionProxy {
|
2023-07-20 14:38:44 +03:00
|
|
|
friend ExpressionStorage;
|
|
|
|
|
|
2023-07-18 16:45:35 +03:00
|
|
|
public:
|
2023-07-20 14:38:44 +03:00
|
|
|
ExpressionProxy() = delete;
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
Expression *get();
|
|
|
|
|
|
|
|
|
|
const Expression *get() const;
|
|
|
|
|
|
2023-07-20 14:38:44 +03:00
|
|
|
private:
|
|
|
|
|
ExpressionProxy(ExpressionStorage &expression_storage, size_t id)
|
2023-07-26 13:43:14 +03:00
|
|
|
: expression_storage_(&expression_storage), id_(id) {}
|
2023-07-20 14:38:44 +03:00
|
|
|
|
2023-07-18 16:45:35 +03:00
|
|
|
private:
|
2023-07-26 13:43:14 +03:00
|
|
|
ExpressionStorage *expression_storage_;
|
2023-07-18 16:45:35 +03:00
|
|
|
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
|
2023-07-22 13:33:33 +03:00
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
class Match : public TypedNode {
|
2023-07-18 16:45:35 +03:00
|
|
|
public:
|
2023-08-08 20:21:48 +03:00
|
|
|
class Case : public TypedNode {
|
2023-07-18 16:45:35 +03:00
|
|
|
public:
|
2023-07-22 13:33:33 +03:00
|
|
|
enum CaseType {
|
|
|
|
|
PATTERN_VALUE,
|
|
|
|
|
VALUE_PATTERN,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Case(Node node, CaseType case_type, ExpressionProxy value,
|
2023-07-18 16:45:35 +03:00
|
|
|
std::optional<ExpressionProxy> condition = std::nullopt,
|
|
|
|
|
std::optional<ExpressionProxy> expression = std::nullopt)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), case_type_(case_type), value_(value),
|
2023-07-22 13:33:33 +03:00
|
|
|
condition_(condition), expression_(expression) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
2023-07-22 13:33:33 +03:00
|
|
|
CaseType case_type() const { return case_type_; }
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
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:
|
2023-07-22 13:33:33 +03:00
|
|
|
CaseType case_type_;
|
2023-07-18 16:45:35 +03:00
|
|
|
ExpressionProxy value_;
|
|
|
|
|
std::optional<ExpressionProxy> condition_;
|
|
|
|
|
std::optional<ExpressionProxy> expression_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Match(Node node, ExpressionProxy value, std::vector<Case> &&cases)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), value_(value), cases_(std::move(cases)) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
Match(Node node, ExpressionProxy value, const std::vector<Case> &cases)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), value_(value), cases_(cases) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
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_;
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
class Loop : public TypedNode {
|
2023-07-18 16:45:35 +03:00
|
|
|
public:
|
|
|
|
|
enum LoopType {
|
|
|
|
|
LOOP,
|
|
|
|
|
WHILE,
|
|
|
|
|
FOR,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// LOOP
|
|
|
|
|
Loop(Node node, ExpressionProxy expression)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), loop_type_(LOOP), expression_(expression) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
// WHILE
|
2023-07-25 21:33:57 +03:00
|
|
|
Loop(Node node, ExpressionProxy condition, ExpressionProxy expression)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), loop_type_(WHILE), expression_(expression),
|
2023-07-18 16:45:35 +03:00
|
|
|
condition_(condition) {}
|
|
|
|
|
|
|
|
|
|
// FOR
|
2023-07-25 21:33:57 +03:00
|
|
|
Loop(Node node, ExpressionProxy variable, ExpressionProxy interval,
|
|
|
|
|
ExpressionProxy expression)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), loop_type_(FOR), expression_(expression),
|
|
|
|
|
variable_(variable), interval_(interval) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
LoopType get_type() const { return loop_type_; }
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
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:
|
2023-08-08 20:21:48 +03:00
|
|
|
LoopType loop_type_;
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
ExpressionProxy expression_;
|
|
|
|
|
|
|
|
|
|
std::optional<ExpressionProxy> condition_;
|
|
|
|
|
std::optional<ExpressionProxy> variable_;
|
|
|
|
|
std::optional<ExpressionProxy> interval_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// --- containers
|
2023-07-22 13:33:33 +03:00
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
class Container : public TypedNode {
|
2023-07-18 16:45:35 +03:00
|
|
|
public:
|
|
|
|
|
enum ContainerType {
|
|
|
|
|
BLOCK,
|
|
|
|
|
ARRAY,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Container(Node node, ContainerType type,
|
|
|
|
|
std::vector<ExpressionProxy> &&expressions)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), container_type_(type),
|
|
|
|
|
expressions_(std::move(expressions)) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
Container(Node node, ContainerType type,
|
|
|
|
|
const std::vector<ExpressionProxy> &expressions)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), container_type_(type), expressions_(expressions) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
ContainerType get_type() const { return container_type_; }
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
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:
|
2023-08-08 20:21:48 +03:00
|
|
|
ContainerType container_type_;
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
std::vector<ExpressionProxy> expressions_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// --- modifiers
|
2023-07-22 13:33:33 +03:00
|
|
|
|
2023-07-18 16:45:35 +03:00
|
|
|
class Return : public Node {
|
|
|
|
|
public:
|
|
|
|
|
enum ReturnType {
|
|
|
|
|
RETURN,
|
|
|
|
|
BRING,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Return(Node node, ReturnType type, ExpressionProxy expression)
|
2023-08-08 20:21:48 +03:00
|
|
|
: Node(node), return_type_(type), expression_(expression) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
ReturnType get_type() const { return return_type_; }
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
Expression *get_expression() { return expression_.get(); }
|
|
|
|
|
|
|
|
|
|
const Expression *get_expression() const { return expression_.get(); }
|
|
|
|
|
|
|
|
|
|
private:
|
2023-08-08 20:21:48 +03:00
|
|
|
ReturnType return_type_;
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
ExpressionProxy expression_;
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
class NameDefinition : public TypedNode {
|
2023-07-18 16:45:35 +03:00
|
|
|
public:
|
|
|
|
|
enum Modifier {
|
|
|
|
|
LET, // %
|
|
|
|
|
VAR, // $
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
NameDefinition(Node node, Modifier modifier, Identifier &&name)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), modifier_(modifier), name_(std::move(name)) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
NameDefinition(Node node, Modifier modifier, const Identifier &name)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), modifier_(modifier), name_(name) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
2023-07-24 18:47:57 +03:00
|
|
|
Modifier get_modifier() const { return modifier_; }
|
2023-07-18 16:45:35 +03:00
|
|
|
|
2023-07-24 18:47:57 +03:00
|
|
|
Identifier *get_name() { return &name_; }
|
2023-07-18 16:45:35 +03:00
|
|
|
|
2023-07-24 18:47:57 +03:00
|
|
|
const Identifier *get_name() const { return &name_; }
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Modifier modifier_;
|
|
|
|
|
|
|
|
|
|
Identifier name_;
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
class Access : public TypedNode {
|
2023-07-18 16:45:35 +03:00
|
|
|
public:
|
|
|
|
|
enum AccessType {
|
|
|
|
|
ARRAY,
|
|
|
|
|
TUPLE, // only number literal index allowed
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Access(Node node, AccessType type, ExpressionProxy value,
|
|
|
|
|
ExpressionProxy index)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), access_type_(type), value_(value), index_(index) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
AccessType get_type() const { return access_type_; }
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
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:
|
2023-08-08 20:21:48 +03:00
|
|
|
AccessType access_type_;
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
ExpressionProxy value_;
|
|
|
|
|
ExpressionProxy index_;
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
class LoopControl : public TypedNode {
|
2023-07-18 16:45:35 +03:00
|
|
|
public:
|
|
|
|
|
enum LoopControlType {
|
|
|
|
|
BREAK,
|
|
|
|
|
CONTINUE,
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
LoopControl(Node node, LoopControlType type)
|
|
|
|
|
: TypedNode(node), loop_control_type_(type) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
LoopControlType get_type() const { return loop_control_type_; }
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
private:
|
2023-08-08 20:21:48 +03:00
|
|
|
LoopControlType loop_control_type_;
|
2023-07-18 16:45:35 +03:00
|
|
|
};
|
|
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
class ModifierExpression : public TypedNode {
|
2023-07-18 16:45:35 +03:00
|
|
|
public:
|
|
|
|
|
ModifierExpression(Node node, Modifier modifier, ExpressionProxy expression)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), modifier_(modifier), expression_(expression) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
2023-07-24 18:47:57 +03:00
|
|
|
Modifier get_modifier() const { return modifier_; }
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
Expression *get_expression() { return expression_.get(); }
|
|
|
|
|
|
|
|
|
|
const Expression *get_expression() const { return expression_.get(); }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Modifier modifier_;
|
|
|
|
|
|
|
|
|
|
ExpressionProxy expression_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// --- other
|
2023-07-22 13:33:33 +03:00
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
class NameExpression : public TypedNode {
|
2023-07-18 16:45:35 +03:00
|
|
|
public:
|
2023-07-23 19:40:27 +03:00
|
|
|
NameExpression(Node node, Identifier &&name)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), name_(std::move(name)) {}
|
2023-07-24 13:01:34 +03:00
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
NameExpression(Node node, const Identifier &name)
|
|
|
|
|
: TypedNode(node), name_(name) {}
|
2023-07-22 13:33:33 +03:00
|
|
|
|
2023-07-23 19:40:27 +03:00
|
|
|
NameExpression(
|
|
|
|
|
Node node, Identifier &&name,
|
|
|
|
|
std::vector<std::pair<std::optional<std::string>, ExpressionProxy>>
|
|
|
|
|
&&arguments,
|
2023-07-24 18:47:57 +03:00
|
|
|
std::optional<TypeProxy> &&prefix, bool is_point_call = false,
|
|
|
|
|
bool is_operator_call = false)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(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) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
2023-07-24 18:47:57 +03:00
|
|
|
Identifier *get_name() { return &name_; }
|
2023-07-18 16:45:35 +03:00
|
|
|
|
2023-07-24 18:47:57 +03:00
|
|
|
const Identifier *get_name() const { return &name_; }
|
2023-07-18 16:45:35 +03:00
|
|
|
|
2023-07-24 18:47:57 +03:00
|
|
|
std::optional<Type *> get_prefix() {
|
2023-07-18 16:45:35 +03:00
|
|
|
if (prefix_.has_value()) {
|
2023-07-24 18:47:57 +03:00
|
|
|
return prefix_.value().get();
|
2023-07-18 16:45:35 +03:00
|
|
|
}
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-24 18:47:57 +03:00
|
|
|
std::optional<const Type *> get_prefix() const {
|
2023-07-18 16:45:35 +03:00
|
|
|
if (prefix_.has_value()) {
|
2023-07-24 18:47:57 +03:00
|
|
|
return prefix_.value().get();
|
2023-07-18 16:45:35 +03:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-24 18:47:57 +03:00
|
|
|
bool is_point_call() const { return is_point_call_; }
|
|
|
|
|
|
|
|
|
|
bool is_operator_call() const { return is_operator_call_; }
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Identifier name_;
|
2023-07-24 13:01:34 +03:00
|
|
|
// universal function call syntax
|
2023-07-18 16:45:35 +03:00
|
|
|
std::vector<std::pair<std::optional<std::string>, ExpressionProxy>>
|
|
|
|
|
arguments_;
|
2023-07-24 13:01:34 +03:00
|
|
|
std::optional<TypeProxy> prefix_;
|
2023-07-18 16:45:35 +03:00
|
|
|
// for static methods
|
2023-07-24 18:47:57 +03:00
|
|
|
bool is_point_call_ = false; // x.f ... or f x ...
|
|
|
|
|
bool is_operator_call_ = false; // ... operator ...
|
2023-07-18 16:45:35 +03:00
|
|
|
};
|
|
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
class Constructor : public TypedNode {
|
2023-07-18 16:45:35 +03:00
|
|
|
public:
|
|
|
|
|
Constructor(
|
|
|
|
|
Node node, TypeProxy type,
|
|
|
|
|
std::vector<std::pair<std::optional<std::string>, ExpressionProxy>>
|
|
|
|
|
&&arguments)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), constructor_type_(type),
|
|
|
|
|
arguments_(std::move(arguments)) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
Constructor(
|
|
|
|
|
Node node, TypeProxy type,
|
|
|
|
|
const std::vector<std::pair<std::optional<std::string>, ExpressionProxy>>
|
|
|
|
|
&arguments)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), constructor_type_(type), arguments_(arguments) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
Type *get_type() { return constructor_type_.get(); }
|
2023-07-18 16:45:35 +03:00
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
const Type *get_type() const { return constructor_type_.get(); }
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
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:
|
2023-08-08 20:21:48 +03:00
|
|
|
TypeProxy constructor_type_;
|
2023-07-18 16:45:35 +03:00
|
|
|
std::vector<std::pair<std::optional<std::string>, ExpressionProxy>>
|
|
|
|
|
arguments_;
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-08 20:21:48 +03:00
|
|
|
class Lambda : public TypedNode {
|
2023-07-18 16:45:35 +03:00
|
|
|
public:
|
|
|
|
|
Lambda(Node node, std::vector<Identifier> &&arguments,
|
|
|
|
|
ExpressionProxy expression)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), arguments_(std::move(arguments)),
|
|
|
|
|
expression_(expression) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
Lambda(Node node, const std::vector<Identifier> &arguments,
|
|
|
|
|
ExpressionProxy expression)
|
2023-08-08 20:21:48 +03:00
|
|
|
: TypedNode(node), arguments_(arguments), expression_(expression) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
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>
|
2023-07-24 18:47:57 +03:00
|
|
|
Expression(T &&expression, bool is_scoped)
|
|
|
|
|
: expression_(std::forward<T>(expression)), is_scoped_(is_scoped) {}
|
2023-07-18 16:45:35 +03:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-25 21:33:57 +03:00
|
|
|
auto get_any() { return &expression_; }
|
2023-07-24 21:23:18 +03:00
|
|
|
|
2023-07-25 21:33:57 +03:00
|
|
|
auto get_any() const { return &expression_; }
|
2023-07-24 21:23:18 +03:00
|
|
|
|
2023-07-24 18:47:57 +03:00
|
|
|
bool is_scoped() const { return is_scoped_; }
|
|
|
|
|
|
2023-07-18 16:45:35 +03:00
|
|
|
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,
|
2023-08-08 20:21:48 +03:00
|
|
|
// TupleAccess - Access with number Literal index
|
2023-07-18 16:45:35 +03:00
|
|
|
Access, LoopControl,
|
|
|
|
|
// Reference or SuffixExpression is ModifierExpression
|
|
|
|
|
ModifierExpression,
|
|
|
|
|
|
|
|
|
|
// --- other
|
2023-07-22 13:33:33 +03:00
|
|
|
NameExpression, Constructor, Lambda,
|
|
|
|
|
|
|
|
|
|
// --- literal
|
2023-07-25 21:33:57 +03:00
|
|
|
Literal,
|
|
|
|
|
|
2023-07-31 22:07:32 +03:00
|
|
|
// --- extra
|
|
|
|
|
Extra,
|
|
|
|
|
|
2023-07-25 21:33:57 +03:00
|
|
|
// --- empty lines
|
2023-07-26 14:21:33 +03:00
|
|
|
EmptyLines>
|
2023-07-18 16:45:35 +03:00
|
|
|
expression_;
|
2023-07-24 18:47:57 +03:00
|
|
|
|
|
|
|
|
bool is_scoped_ = false;
|
2023-07-18 16:45:35 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class ExpressionStorage {
|
|
|
|
|
friend ExpressionProxy;
|
|
|
|
|
|
|
|
|
|
public:
|
2023-07-20 14:38:44 +03:00
|
|
|
ExpressionProxy add_expression(const Expression &expression) {
|
|
|
|
|
storage_.push_back(expression);
|
2023-07-18 16:45:35 +03:00
|
|
|
return ExpressionProxy(*this, storage_.size() - 1);
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-20 14:38:44 +03:00
|
|
|
ExpressionProxy add_expression(Expression &&expression) {
|
|
|
|
|
storage_.push_back(std::move(expression));
|
2023-07-18 16:45:35 +03:00
|
|
|
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
|