[PART] most of builders and nodes changed to use new system

This commit is contained in:
ProgramSnail 2024-08-29 14:56:49 +03:00
parent 8f96a818ff
commit d02c3a637b
22 changed files with 1397 additions and 1536 deletions

View file

@ -17,7 +17,7 @@
class SourcesManager {
public:
void AddFile(const std::string &filename) {
Log::Context logc(executor_.log(), utils::Log::Area::kParse);
Log::Context logc(executor_.log(), Log::Area::kParse);
std::ifstream in;
in.open(filename);
@ -64,6 +64,6 @@ public:
private:
builders::Executor executor_ =
builders::Executor(utils::BuildPrintLog(std::cout), {}, {}, {}, {});
builders::Executor(utils::BuildPrintLog(std::cout), {}, {}, {}, {}, {});
std::vector<nodes::Statement> statements_ = {};
};

View file

@ -1,69 +1,260 @@
#pragma once
#include "basic_nodes.hpp"
#include "builders_utils.hpp"
#include "tree_sitter_wrapper.hpp"
namespace utils {
struct SimpleNameIdTag {};
struct SimpleTypeIdTag {};
struct TypeclassIdTag {};
struct ArgNameIdTag {};
struct ArgTypeIdTag {};
struct OperatorIdTag {};
struct PlaceholderIdTag {};
struct GenericTypeIdTag {};
}; // namespace utils
namespace builders {
// returns Modifier::NONE for incorrecnt input
nodes::Modifier build_modifier(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Modifier>
: public BasicBuilderTaskBase<nodes::Modifier> {
using BasicBuilderTaskBase<nodes::Modifier>::BasicBuilderTaskBase;
nodes::Node build_node(parser::ParseTree::Node parser_node);
nodes::Modifier operator()(const ParserNode &parser_node,
const Args &args) override;
};
// --- literals
nodes::Literal build_float_literal(parser::ParseTree::Node parser_node);
// nodes::Literal build_float_literal(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Literal, float>
: public BasicBuilderTaskBase<nodes::Literal> {
using BasicBuilderTaskBase<nodes::Literal>::BasicBuilderTaskBase;
nodes::Literal build_double_literal(parser::ParseTree::Node parser_node);
nodes::Literal operator()(const ParserNode &parser_node,
const Args &args) override;
};
nodes::Literal build_int_literal(parser::ParseTree::Node parser_node);
// nodes::Literal build_double_literal(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Literal, double>
: public BasicBuilderTaskBase<nodes::Literal> {
using BasicBuilderTaskBase<nodes::Literal>::BasicBuilderTaskBase;
nodes::Literal build_long_literal(parser::ParseTree::Node parser_node);
nodes::Literal operator()(const ParserNode &parser_node,
const Args &args) override;
};
nodes::Literal build_index_literal(parser::ParseTree::Node parser_node);
// nodes::Literal build_int_literal(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Literal, int32_t> // int
: public BasicBuilderTaskBase<nodes::Literal> {
using BasicBuilderTaskBase<nodes::Literal>::BasicBuilderTaskBase;
nodes::Literal build_string_literal(parser::ParseTree::Node parser_node);
nodes::Literal operator()(const ParserNode &parser_node,
const Args &args) override;
};
nodes::Literal
build_unicode_string_literal(parser::ParseTree::Node parser_node);
// nodes::Literal build_long_literal(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Literal, int64_t> // long
: public BasicBuilderTaskBase<nodes::Literal> {
using BasicBuilderTaskBase<nodes::Literal>::BasicBuilderTaskBase;
nodes::Literal build_char_literal(parser::ParseTree::Node parser_node);
nodes::Literal operator()(const ParserNode &parser_node,
const Args &args) override;
};
nodes::Literal build_unicode_literal(parser::ParseTree::Node parser_node);
// nodes::Literal build_index_literal(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Literal, size_t> // index
: public BasicBuilderTaskBase<nodes::Literal> {
using BasicBuilderTaskBase<nodes::Literal>::BasicBuilderTaskBase;
nodes::Literal build_bool_literal(parser::ParseTree::Node parser_node);
nodes::Literal operator()(const ParserNode &parser_node,
const Args &args) override;
};
nodes::Literal build_unit_literal(parser::ParseTree::Node parser_node);
// nodes::Literal build_string_literal(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Literal, std::string> // string
: public BasicBuilderTaskBase<nodes::Literal> {
using BasicBuilderTaskBase<nodes::Literal>::BasicBuilderTaskBase;
nodes::Literal build_null_literal(parser::ParseTree::Node parser_node);
nodes::Literal operator()(const ParserNode &parser_node,
const Args &args) override;
};
// nodes::Literal
// build_unicode_string_literal(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Literal, nodes::unicode_string>
: public BasicBuilderTaskBase<nodes::Literal> {
using BasicBuilderTaskBase<nodes::Literal>::BasicBuilderTaskBase;
nodes::Literal operator()(const ParserNode &parser_node,
const Args &args) override;
};
// nodes::Literal build_char_literal(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Literal, char>
: public BasicBuilderTaskBase<nodes::Literal> {
using BasicBuilderTaskBase<nodes::Literal>::BasicBuilderTaskBase;
nodes::Literal operator()(const ParserNode &parser_node,
const Args &args) override;
};
// nodes::Literal build_unicode_literal(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Literal, nodes::unicode>
: public BasicBuilderTaskBase<nodes::Literal> {
using BasicBuilderTaskBase<nodes::Literal>::BasicBuilderTaskBase;
nodes::Literal operator()(const ParserNode &parser_node,
const Args &args) override;
};
// nodes::Literal build_bool_literal(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Literal, bool>
: public BasicBuilderTaskBase<nodes::Literal> {
using BasicBuilderTaskBase<nodes::Literal>::BasicBuilderTaskBase;
nodes::Literal operator()(const ParserNode &parser_node,
const Args &args) override;
};
// nodes::Literal build_unit_literal(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Literal, nodes::unit>
: public BasicBuilderTaskBase<nodes::Literal> {
using BasicBuilderTaskBase<nodes::Literal>::BasicBuilderTaskBase;
nodes::Literal operator()(const ParserNode &parser_node,
const Args &args) override;
};
// nodes::Literal build_null_literal(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Literal, nodes::null>
: public BasicBuilderTaskBase<nodes::Literal> {
using BasicBuilderTaskBase<nodes::Literal>::BasicBuilderTaskBase;
nodes::Literal operator()(const ParserNode &parser_node,
const Args &args) override;
};
// --- identifiers
nodes::Identifier build_identifier(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Identifier>
: public BasicBuilderTaskBase<nodes::Identifier> {
using BasicBuilderTaskBase<nodes::Identifier>::BasicBuilderTaskBase;
nodes::Identifier build_simple_name(parser::ParseTree::Node parser_node);
nodes::Identifier operator()(const ParserNode &parser_node,
const Args &args) override;
};
nodes::Identifier build_simple_type(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Identifier, utils::SimpleNameIdTag>
: public BasicBuilderTaskBase<nodes::Identifier> {
using BasicBuilderTaskBase<nodes::Identifier>::BasicBuilderTaskBase;
nodes::Identifier build_typeclass(parser::ParseTree::Node parser_node);
nodes::Identifier operator()(const ParserNode &parser_node,
const Args &args) override;
};
nodes::Identifier build_argument_name(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Identifier, utils::SimpleTypeIdTag>
: public BasicBuilderTaskBase<nodes::Identifier> {
using BasicBuilderTaskBase<nodes::Identifier>::BasicBuilderTaskBase;
nodes::Identifier build_argument_type(parser::ParseTree::Node parser_node);
nodes::Identifier operator()(const ParserNode &parser_node,
const Args &args) override;
};
template <>
struct BuilderTask<nodes::Identifier, utils::TypeclassIdTag>
: public BasicBuilderTaskBase<nodes::Identifier> {
using BasicBuilderTaskBase<nodes::Identifier>::BasicBuilderTaskBase;
nodes::Identifier operator()(const ParserNode &parser_node,
const Args &args) override;
};
template <>
struct BuilderTask<nodes::Identifier, utils::ArgNameIdTag>
: public BasicBuilderTaskBase<nodes::Identifier> {
using BasicBuilderTaskBase<nodes::Identifier>::BasicBuilderTaskBase;
nodes::Identifier operator()(const ParserNode &parser_node,
const Args &args) override;
};
template <>
struct BuilderTask<nodes::Identifier, utils::ArgTypeIdTag>
: public BasicBuilderTaskBase<nodes::Identifier> {
using BasicBuilderTaskBase<nodes::Identifier>::BasicBuilderTaskBase;
nodes::Identifier operator()(const ParserNode &parser_node,
const Args &args) override;
};
// Annotations are used as strings
std::string build_annotation(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Annotation>
: public BasicBuilderTaskBase<nodes::Annotation> {
using BasicBuilderTaskBase<nodes::Annotation>::BasicBuilderTaskBase;
nodes::Identifier build_operator(parser::ParseTree::Node parser_node);
nodes::Annotation operator()(const ParserNode &parser_node,
const Args &args) override;
};
nodes::Identifier build_placeholder(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Identifier, utils::OperatorIdTag>
: public BasicBuilderTaskBase<nodes::Identifier> {
using BasicBuilderTaskBase<nodes::Identifier>::BasicBuilderTaskBase;
nodes::Identifier operator()(const ParserNode &parser_node,
const Args &args) override;
};
template <>
struct BuilderTask<nodes::Identifier, utils::PlaceholderIdTag>
: public BasicBuilderTaskBase<nodes::Identifier> {
using BasicBuilderTaskBase<nodes::Identifier>::BasicBuilderTaskBase;
nodes::Identifier operator()(const ParserNode &parser_node,
const Args &args) override;
};
// --- extra
nodes::Extra build_extra(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::Extra> : public BasicBuilderTaskBase<nodes::Extra> {
using BasicBuilderTaskBase<nodes::Extra>::BasicBuilderTaskBase;
nodes::Extra operator()(const ParserNode &parser_node,
const Args &args) override;
};
// --- empty lines
nodes::EmptyLines build_empty_lines(parser::ParseTree::Node parser_node);
template <>
struct BuilderTask<nodes::EmptyLines>
: public BasicBuilderTaskBase<nodes::EmptyLines> {
using BasicBuilderTaskBase<nodes::EmptyLines>::BasicBuilderTaskBase;
nodes::EmptyLines operator()(const ParserNode &parser_node,
const Args &args) override;
};
} // namespace builders

View file

@ -7,26 +7,28 @@
namespace builders {
// using Code = parser::ParseTree;
using Exprs = nodes::ExprStorage;
using Exprs = nodes::NodeStorage; // nodes::ExprStorage;
using Types = nodes::TypeStorage;
using Names = names::NameTree;
using Positions = core::DependentStorage<utils::Pos>;
//
struct State {
std::optional<nodes::Identifier> last_defined_type_name;
};
//
using Executor = utils::Executor<Exprs, Types, Names, State>;
using Executor = utils::Executor<Exprs, Types, Names, State, Positions>;
using ParserNode = parser::ParseTree::Node;
// using Node = nodes::Node_<nodes::NodePart<utils::Pos>>; // TODO
using Node = nodes::Node_<nodes::NodePart<utils::Pos>>;
using Args = utils::None;
struct Args {
bool is_scoped = false;
};
template <typename N>
using Task = utils::Task<Executor, N, Args, parser::ParseTree::Node>;
@ -35,11 +37,71 @@ template <typename N, typename Tag = utils::None> struct BuilderTask {
static_assert(false);
};
template <typename N> struct BuilderTaskBase : public Task<N> {
template <typename N> struct BuilderTaskUtils : public Task<N> {
using Task<N>::Task;
template <typename OtherN, typename OtherTag = utils::None>
OtherN Run(const parser::ParseTree::Node &node, const Args &args = {}) {
Node Ext(storage::Id id) const {
return Node(id, this->template state<Exprs>(),
this->template state<Positions>());
}
template <typename T>
Node Expect(Node value, Log::Context &logc,
std::source_location source_location =
std::source_location::current()) const {
logc.Expect<Log::kProc>(value.Holds<T>(),
{{"value type requirement failed"}}, {},
source_location);
return value;
}
template <typename T> Node Build(T value, utils::Pos pos) {
auto id = this->template state<Exprs>().Insert(std::move(value));
this->template state<Positions>().ForceInsert(id, pos);
return GetNode(id);
}
};
//
template <typename N> struct BasicBuilderTaskBase : public BuilderTaskUtils<N> {
using BuilderTaskUtils<N>::BuilderTaskUtils;
template <typename OtherN, typename OtherTag = utils::None,
typename Ret = OtherN>
Ret Run(const parser::ParseTree::Node &node, const Args &args = {}) {
BuilderTask<OtherN, OtherTag> task(this->executor);
return task(node, args);
}
};
template <typename N>
struct ExprBuilderTaskBase : public BuilderTaskUtils<Node> {
using BuilderTaskUtils<Node>::BuilderTaskUtils;
template <typename OtherN, typename OtherTag = utils::None,
typename Ret = Node>
Ret Run(const parser::ParseTree::Node &node, const Args &args = {}) {
BuilderTask<OtherN, OtherTag> task(this->executor);
return task(node, args);
}
// TODO: rename
template <typename OtherN, typename OtherTag = utils::None,
typename Ret = OtherN>
Ret RunOther(const parser::ParseTree::Node &node, const Args &args = {}) {
BuilderTask<OtherN, OtherTag> task(this->executor);
return task(node, args);
}
};
template <typename N>
struct StatementBuilderTaskBase : public BuilderTaskUtils<N> {
using BuilderTaskUtils<N>::BuilderTaskUtils;
template <typename OtherN, typename OtherTag = utils::None,
typename Ret = OtherN>
Ret Run(const parser::ParseTree::Node &node, const Args &args = {}) {
BuilderTask<OtherN, OtherTag> task(this->executor);
return task(node, args);
}

View file

@ -23,66 +23,58 @@ namespace builders {
// --- flow control
template <>
struct BuilderTask<nodes::Expr> : public BuilderTaskBase<nodes::Expr> {
using BuilderTaskBase<nodes::Expr>::BuilderTaskBase;
template <> struct BuilderTask<Node> : public ExprBuilderTaskBase<Node> {
using ExprBuilderTaskBase<Node>::ExprBuilderTaskBase;
nodes::Expr operator()(const ParserNode &parser_node,
const Args &args) override;
Node operator()(const ParserNode &parser_node, const Args &args) override;
};
template <>
struct BuilderTask<nodes::Match::Case>
: public BuilderTaskBase<nodes::Match::Case> {
using BuilderTaskBase<nodes::Match::Case>::BuilderTaskBase;
: public ExprBuilderTaskBase<nodes::Match::Case> {
using ExprBuilderTaskBase<nodes::Match::Case>::ExprBuilderTaskBase;
nodes::Match::Case operator()(const ParserNode &parser_node,
const Args &args) override;
Node operator()(const ParserNode &parser_node, const Args &args) override;
};
template <>
struct BuilderTask<nodes::Match> : public BuilderTaskBase<nodes::Match> {
using BuilderTaskBase<nodes::Match>::BuilderTaskBase;
struct BuilderTask<nodes::Match> : public ExprBuilderTaskBase<nodes::Match> {
using ExprBuilderTaskBase<nodes::Match>::ExprBuilderTaskBase;
nodes::Match operator()(const ParserNode &parser_node,
const Args &args) override;
Node operator()(const ParserNode &parser_node, const Args &args) override;
};
template <>
struct BuilderTask<nodes::Condition>
: public BuilderTaskBase<nodes::Condition> {
using BuilderTaskBase<nodes::Condition>::BuilderTaskBase;
: public ExprBuilderTaskBase<nodes::Condition> {
using ExprBuilderTaskBase<nodes::Condition>::ExprBuilderTaskBase;
nodes::Condition operator()(const ParserNode &parser_node,
const Args &args) override;
Node operator()(const ParserNode &parser_node, const Args &args) override;
};
template <>
struct BuilderTask<nodes::Loop> : public BuilderTaskBase<nodes::Loop> {
using BuilderTaskBase<nodes::Loop>::BuilderTaskBase;
struct BuilderTask<nodes::Loop> : public ExprBuilderTaskBase<nodes::Loop> {
using ExprBuilderTaskBase<nodes::Loop>::ExprBuilderTaskBase;
nodes::Loop operator()(const ParserNode &parser_node,
const Args &args) override;
Node operator()(const ParserNode &parser_node, const Args &args) override;
};
// --- operators
template <>
struct BuilderTask<nodes::NameExpression, utils::CommaTag>
: public BuilderTaskBase<nodes::NameExpression> {
using BuilderTaskBase<nodes::NameExpression>::BuilderTaskBase;
: public ExprBuilderTaskBase<nodes::NameExpression> {
using ExprBuilderTaskBase<nodes::NameExpression>::ExprBuilderTaskBase;
nodes::NameExpression operator()(const ParserNode &parser_node,
const Args &args) override;
Node operator()(const ParserNode &parser_node, const Args &args) override;
};
template <>
struct BuilderTask<nodes::NameExpression, utils::OperatorTag>
: public BuilderTaskBase<nodes::NameExpression> {
using BuilderTaskBase<nodes::NameExpression>::BuilderTaskBase;
: public ExprBuilderTaskBase<nodes::NameExpression> {
using ExprBuilderTaskBase<nodes::NameExpression>::ExprBuilderTaskBase;
nodes::NameExpression operator()(const ParserNode &parser_node,
const Args &args) override;
Node operator()(const ParserNode &parser_node, const Args &args) override;
};
// --- continers
@ -91,97 +83,92 @@ template <typename T>
requires std::is_same_v<T, utils::BlockTag> or
std::is_same_v<T, utils::ArrayTag>
struct BuilderTask<nodes::Container, T>
: public BuilderTaskBase<nodes::Container> {
using BuilderTaskBase<nodes::Container>::BuilderTaskBase;
: public ExprBuilderTaskBase<nodes::Container> {
using ExprBuilderTaskBase<nodes::Container>::ExprBuilderTaskBase;
// '{' (expression ';')* '}'
// or
// '[[' expression+ ']]'
nodes::Container operator()(const ParserNode &parser_node,
const Args &) override {
const auto container_type = std::is_same_v<T, utils::BlockTag>
? nodes::Container::BLOCK
: nodes::Container::ARRAY;
Node operator()(const ParserNode &parser_node, const Args &) override {
const auto kind = std::is_same_v<T, utils::BlockTag>
? nodes::Container::BLOCK
: nodes::Container::ARRAY;
std::vector<nodes::Expr> expressions;
std::vector<nodes::NodeId> exprs;
auto current_node = parser_node.nth_named_child(0);
while (!current_node.is_null()) {
expressions.push_back(Run<nodes::Expr>(current_node));
exprs.push_back(Run<Node>(current_node));
current_node = current_node.next_named_sibling();
}
return nodes::Container(build_node(parser_node), container_type,
std::move(expressions));
return state<Exprs>().Insert(nodes::Container{
.kind = kind,
.exprs = std::move(exprs),
});
}
};
// --- modifiers
template <>
struct BuilderTask<nodes::Return> : public BuilderTaskBase<nodes::Return> {
using BuilderTaskBase<nodes::Return>::BuilderTaskBase;
struct BuilderTask<nodes::Return> : public ExprBuilderTaskBase<nodes::Return> {
using ExprBuilderTaskBase<nodes::Return>::ExprBuilderTaskBase;
nodes::Return operator()(const ParserNode &parser_node,
const Args &args) override;
Node operator()(const ParserNode &parser_node, const Args &args) override;
};
template <>
struct BuilderTask<nodes::NameDefinition>
: public BuilderTaskBase<nodes::NameDefinition> {
using BuilderTaskBase<nodes::NameDefinition>::BuilderTaskBase;
: public ExprBuilderTaskBase<nodes::NameDefinition> {
using ExprBuilderTaskBase<nodes::NameDefinition>::ExprBuilderTaskBase;
nodes::NameDefinition operator()(const ParserNode &parser_node,
const Args &args) override;
Node operator()(const ParserNode &parser_node, const Args &args) override;
};
template <>
struct BuilderTask<nodes::Access, utils::ArrayAccessTag>
: public BuilderTaskBase<nodes::Access> {
using BuilderTaskBase<nodes::Access>::BuilderTaskBase;
: public ExprBuilderTaskBase<nodes::Access> {
using ExprBuilderTaskBase<nodes::Access>::ExprBuilderTaskBase;
nodes::Access operator()(const ParserNode &parser_node,
const Args &args) override;
Node operator()(const ParserNode &parser_node, const Args &args) override;
};
template <>
struct BuilderTask<nodes::Access, utils::TupleAccessTag>
: public BuilderTaskBase<nodes::Access> {
using BuilderTaskBase<nodes::Access>::BuilderTaskBase;
: public ExprBuilderTaskBase<nodes::Access> {
using ExprBuilderTaskBase<nodes::Access>::ExprBuilderTaskBase;
nodes::Access operator()(const ParserNode &parser_node,
const Args &args) override;
Node operator()(const ParserNode &parser_node, const Args &args) override;
};
template <>
struct BuilderTask<nodes::LoopControl>
: public BuilderTaskBase<nodes::LoopControl> {
using BuilderTaskBase<nodes::LoopControl>::BuilderTaskBase;
: public ExprBuilderTaskBase<nodes::LoopControl> {
using ExprBuilderTaskBase<nodes::LoopControl>::ExprBuilderTaskBase;
nodes::LoopControl operator()(const ParserNode &parser_node,
const Args &args) override;
Node operator()(const ParserNode &parser_node, const Args &args) override;
};
template <typename T>
requires std::is_same_v<T, utils::RefTag> or
std::is_same_v<T, utils::SuffixTag>
struct BuilderTask<nodes::ModifierExpression, T>
: public BuilderTaskBase<nodes::ModifierExpression> {
using BuilderTaskBase<nodes::ModifierExpression>::BuilderTaskBase;
: public ExprBuilderTaskBase<nodes::ModifierExpression> {
using ExprBuilderTaskBase<nodes::ModifierExpression>::ExprBuilderTaskBase;
// _reference_ expression
// or
// expression ('?' | '!')
nodes::ModifierExpression operator()(const ParserNode &parser_node,
const Args &) override {
Node operator()(const ParserNode &parser_node, const Args &) override {
const size_t modifier_pos =
std::is_same_v<T, utils::RefTag> ? 0 : parser_node.child_count() - 1;
return nodes::ModifierExpression(
build_node(parser_node),
build_modifier(parser_node.nth_child(modifier_pos)),
Run<nodes::Expr>(parser_node.nth_named_child(0)));
return state<Exprs>().Insert(nodes::ModifierExpression{
.modifier = Run<nodes::Modifier>(parser_node.nth_child(modifier_pos)),
.expr = Run<Node>(parser_node.nth_named_child(0)),
});
}
};
@ -189,28 +176,25 @@ struct BuilderTask<nodes::ModifierExpression, T>
template <>
struct BuilderTask<nodes::NameExpression, utils::FuncCallTag>
: public BuilderTaskBase<nodes::NameExpression> {
using BuilderTaskBase<nodes::NameExpression>::BuilderTaskBase;
: public ExprBuilderTaskBase<nodes::NameExpression> {
using ExprBuilderTaskBase<nodes::NameExpression>::ExprBuilderTaskBase;
nodes::NameExpression operator()(const ParserNode &parser_node,
const Args &args) override;
Node operator()(const ParserNode &parser_node, const Args &args) override;
};
template <>
struct BuilderTask<nodes::Constructor>
: public BuilderTaskBase<nodes::Constructor> {
using BuilderTaskBase<nodes::Constructor>::BuilderTaskBase;
: public ExprBuilderTaskBase<nodes::Constructor> {
using ExprBuilderTaskBase<nodes::Constructor>::ExprBuilderTaskBase;
nodes::Constructor operator()(const ParserNode &parser_node,
const Args &args) override;
Node operator()(const ParserNode &parser_node, const Args &args) override;
};
template <>
struct BuilderTask<nodes::Lambda> : public BuilderTaskBase<nodes::Lambda> {
using BuilderTaskBase<nodes::Lambda>::BuilderTaskBase;
struct BuilderTask<nodes::Lambda> : public ExprBuilderTaskBase<nodes::Lambda> {
using ExprBuilderTaskBase<nodes::Lambda>::ExprBuilderTaskBase;
nodes::Lambda operator()(const ParserNode &parser_node,
const Args &args) override;
Node operator()(const ParserNode &parser_node, const Args &args) override;
};
} // namespace builders

View file

@ -16,8 +16,8 @@ namespace builders {
// translate them in required order
template <>
struct BuilderTask<nodes::Statements>
: public BuilderTaskBase<nodes::Statements> {
using BuilderTaskBase<nodes::Statements>::BuilderTaskBase;
: public StatementBuilderTaskBase<nodes::Statements> {
using StatementBuilderTaskBase<nodes::Statements>::StatementBuilderTaskBase;
nodes::Statements operator()(const ParserNode &parser_node,
const Args &args) override;
@ -26,16 +26,17 @@ struct BuilderTask<nodes::Statements>
// copy of statement inserted into name_tree
template <>
struct BuilderTask<nodes::Statement>
: public BuilderTaskBase<nodes::Statement> {
using BuilderTaskBase<nodes::Statement>::BuilderTaskBase;
: public StatementBuilderTaskBase<nodes::Statement> {
using StatementBuilderTaskBase<nodes::Statement>::StatementBuilderTaskBase;
nodes::Statement operator()(const ParserNode &parser_node,
const Args &args) override;
};
template <>
struct BuilderTask<nodes::Import> : public BuilderTaskBase<nodes::Import> {
using BuilderTaskBase<nodes::Import>::BuilderTaskBase;
struct BuilderTask<nodes::Import>
: public StatementBuilderTaskBase<nodes::Import> {
using StatementBuilderTaskBase<nodes::Import>::StatementBuilderTaskBase;
nodes::Import operator()(const ParserNode &parser_node,
const Args &args) override;
@ -43,8 +44,8 @@ struct BuilderTask<nodes::Import> : public BuilderTaskBase<nodes::Import> {
template <>
struct BuilderTask<nodes::Constraint>
: public BuilderTaskBase<nodes::Constraint> {
using BuilderTaskBase<nodes::Constraint>::BuilderTaskBase;
: public StatementBuilderTaskBase<nodes::Constraint> {
using StatementBuilderTaskBase<nodes::Constraint>::StatementBuilderTaskBase;
nodes::Constraint operator()(const ParserNode &parser_node,
const Args &args) override;
@ -52,8 +53,9 @@ struct BuilderTask<nodes::Constraint>
template <>
struct BuilderTask<nodes::TypeDefinition>
: public BuilderTaskBase<nodes::TypeDefinition> {
using BuilderTaskBase<nodes::TypeDefinition>::BuilderTaskBase;
: public StatementBuilderTaskBase<nodes::TypeDefinition> {
using StatementBuilderTaskBase<
nodes::TypeDefinition>::StatementBuilderTaskBase;
nodes::TypeDefinition operator()(const ParserNode &parser_node,
const Args &args) override;
@ -61,8 +63,9 @@ struct BuilderTask<nodes::TypeDefinition>
template <>
struct BuilderTask<nodes::FunctionDefinition>
: public BuilderTaskBase<nodes::FunctionDefinition> {
using BuilderTaskBase<nodes::FunctionDefinition>::BuilderTaskBase;
: public StatementBuilderTaskBase<nodes::FunctionDefinition> {
using StatementBuilderTaskBase<
nodes::FunctionDefinition>::StatementBuilderTaskBase;
nodes::FunctionDefinition operator()(const ParserNode &parser_node,
const Args &args) override;

View file

@ -1,7 +1,6 @@
#include "basic_builders.hpp"
#include "basic_nodes.hpp"
#include "error_handling.hpp"
#include "tokens.hpp"
#include "tree_sitter_wrapper.hpp"
@ -39,7 +38,11 @@ std::optional<char> to_escape_symbol(char ch) {
} // namespace utils
nodes::Modifier build_modifier(parser::ParseTree::Node parser_node) {
nodes::Modifier
BuilderTask<nodes::Modifier>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
std::string modifier = parser_node.get_value();
if (modifier == "?") {
@ -81,45 +84,60 @@ nodes::Modifier build_modifier(parser::ParseTree::Node parser_node) {
}
}
nodes::Node build_node(parser::ParseTree::Node parser_node) {
return nodes::Node(parser_node.get_start_point(),
parser_node.get_end_point());
}
// --- literals
nodes::Literal build_float_literal(parser::ParseTree::Node parser_node) {
nodes::Literal
BuilderTask<nodes::Literal, float>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
std::string literal = parser_node.get_value();
return nodes::Literal(
build_node(parser_node),
std::stof(literal.substr(0, literal.size() - 1))); // remove 'f' suffix
return nodes::Literal{
.value =
std::stof(literal.substr(0, literal.size() - 1)) // remove 'f' suffix
};
}
nodes::Literal build_double_literal(parser::ParseTree::Node parser_node) {
return nodes::Literal(build_node(parser_node),
std::stod(parser_node.get_value()));
nodes::Literal
BuilderTask<nodes::Literal, double>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return nodes::Literal{.value = std::stod(parser_node.get_value())};
}
nodes::Literal build_int_literal(parser::ParseTree::Node parser_node) {
nodes::Literal
BuilderTask<nodes::Literal, int32_t>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
std::string literal = parser_node.get_value();
return nodes::Literal(build_node(parser_node),
(int32_t)std::stoll(literal.substr(
0, literal.size() - 1))); // remove 'i' suffix
return nodes::Literal{.value = (int32_t)std::stoll(literal.substr(
0, literal.size() - 1))}; // remove 'i' suffix
}
nodes::Literal build_long_literal(parser::ParseTree::Node parser_node) {
nodes::Literal
BuilderTask<nodes::Literal, int64_t>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
std::string literal = parser_node.get_value();
return nodes::Literal(build_node(parser_node),
(int64_t)std::stoll(literal.substr(
0, literal.size() - 1))); // remove 'l' suffix
return nodes::Literal{.value = (int64_t)std::stoll(literal.substr(
0, literal.size() - 1))}; // remove 'l' suffix
}
nodes::Literal build_index_literal(parser::ParseTree::Node parser_node) {
return nodes::Literal(build_node(parser_node),
(size_t)std::stoull(parser_node.get_value()));
nodes::Literal
BuilderTask<nodes::Literal, size_t>::operator()(const ParserNode &parser_node,
const Args &) { // index
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return nodes::Literal{.value = (size_t)std::stoull(parser_node.get_value())};
}
nodes::Literal build_string_literal(parser::ParseTree::Node parser_node) {
nodes::Literal BuilderTask<nodes::Literal, std::string>::operator()(
const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
std::string literal = parser_node.get_value();
// remove " from both sides ("string")
@ -149,20 +167,25 @@ nodes::Literal build_string_literal(parser::ParseTree::Node parser_node) {
}
literal.resize(j);
return nodes::Literal(build_node(parser_node), literal);
return nodes::Literal{.value = literal};
}
// TODO: decode escape characters, etc.
nodes::Literal
build_unicode_string_literal(parser::ParseTree::Node parser_node) {
nodes::Literal BuilderTask<nodes::Literal, nodes::unicode_string>::operator()(
const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
std::string literal = parser_node.get_value();
// remove " from both sides + 'u' ("string"u)
return nodes::Literal(build_node(parser_node),
literal.substr(1, literal.size() - 3));
return nodes::Literal{.value = literal.substr(1, literal.size() - 3)};
}
nodes::Literal build_char_literal(parser::ParseTree::Node parser_node) {
nodes::Literal
BuilderTask<nodes::Literal, char>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
std::string literal = parser_node.get_value();
// remove '' from both sides (''x'')
@ -182,108 +205,156 @@ nodes::Literal build_char_literal(parser::ParseTree::Node parser_node) {
ch = literal.back();
}
return nodes::Literal(build_node(parser_node), ch);
return nodes::Literal{ch};
}
// TODO: decode escape characters, etc.
nodes::Literal build_unicode_literal(parser::ParseTree::Node parser_node) {
nodes::Literal BuilderTask<nodes::Literal, nodes::unicode>::operator()(
const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
std::string literal = parser_node.get_value();
// remove '' from both sides + 'u' (''x''u)
return nodes::Literal(build_node(parser_node),
nodes::unicode{literal.substr(2, literal.size() - 5)});
return nodes::Literal{
.value = nodes::unicode{literal.substr(2, literal.size() - 5)}};
}
nodes::Literal build_bool_literal(parser::ParseTree::Node parser_node) {
nodes::Literal
BuilderTask<nodes::Literal, bool>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
std::string literal = parser_node.get_value();
return nodes::Literal(build_node(parser_node),
literal == "true" ? true : false);
return nodes::Literal{literal == "true" ? true : false};
}
nodes::Literal build_unit_literal(parser::ParseTree::Node parser_node) {
return nodes::Literal(build_node(parser_node), nodes::unit{});
nodes::Literal
BuilderTask<nodes::Literal, nodes::unit>::operator()(const ParserNode &,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return nodes::Literal{.value = nodes::unit{}};
}
nodes::Literal build_null_literal(parser::ParseTree::Node parser_node) {
return nodes::Literal(build_node(parser_node), nodes::null{});
nodes::Literal
BuilderTask<nodes::Literal, nodes::null>::operator()(const ParserNode &,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return nodes::Literal{.value = nodes::null{}};
}
// --- identifiers
nodes::Identifier build_identifier(parser::ParseTree::Node parser_node) {
nodes::Identifier
BuilderTask<nodes::Identifier>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
tokens::Type type = tokens::string_to_type(parser_node.get_type());
switch (type) {
case tokens::Type::PLACEHOLDER:
return build_placeholder(parser_node);
return Run<nodes::Identifier, ::utils::PlaceholderIdTag>(parser_node);
case tokens::Type::SIMPLE_NAME_IDENTIFIER:
return build_simple_name(parser_node);
return Run<nodes::Identifier, ::utils::SimpleNameIdTag>(parser_node);
case tokens::Type::SIMPLE_TYPE_IDENTIFIER:
return build_simple_type(parser_node);
return Run<nodes::Identifier, ::utils::SimpleTypeIdTag>(parser_node);
case tokens::Type::TYPECLASS_IDENTIFIER:
return build_typeclass(parser_node);
return Run<nodes::Identifier, ::utils::TypeclassIdTag>(parser_node);
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
return build_argument_name(parser_node);
return Run<nodes::Identifier, ::utils::ArgNameIdTag>(parser_node);
case tokens::Type::ARGUMENT_TYPE_IDENTIFIER:
return build_argument_type(parser_node);
return Run<nodes::Identifier, ::utils::ArgTypeIdTag>(parser_node);
case tokens::Type::OPERATOR:
case tokens::Type::OPERATOR_TAIL1:
case tokens::Type::OPERATOR_TAIL2:
case tokens::Type::OPERATOR_TAIL3:
return build_operator(parser_node);
return Run<nodes::Identifier, ::utils::OperatorIdTag>(parser_node);
// [used as string]
// case tokens::Type::ANNOTATION_IDENTIFIER:
// return build_annotation(parser_node);
default:
error_handling::handle_parsing_error("Unexprected identifier node type",
parser_node);
logc.Fatal<Log::kProc>({{"Unexprected identifier node type"}},
parser_node.get_pos());
}
error_handling::handle_general_error("Unreachable");
::utils::Assert(false, "Unreachable");
exit(1); // unreachable
}
nodes::Identifier build_simple_name(parser::ParseTree::Node parser_node) {
return nodes::Identifier(build_node(parser_node),
nodes::Identifier::SIMPLE_NAME,
parser_node.get_value());
nodes::Identifier
BuilderTask<nodes::Identifier, ::utils::SimpleNameIdTag>::operator()(
const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return nodes::Identifier{
.kind = nodes::Identifier::kSimpleName,
.value = parser_node.get_value(),
};
}
nodes::Identifier build_simple_type(parser::ParseTree::Node parser_node) {
return nodes::Identifier(build_node(parser_node),
nodes::Identifier::SIMPLE_TYPE,
parser_node.get_value());
nodes::Identifier
BuilderTask<nodes::Identifier, ::utils::SimpleTypeIdTag>::operator()(
const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return nodes::Identifier{.kind = nodes::Identifier::kSimpleType,
.value = parser_node.get_value()};
}
nodes::Identifier build_typeclass(parser::ParseTree::Node parser_node) {
return nodes::Identifier(build_node(parser_node),
nodes::Identifier::TYPECLASS,
parser_node.get_value());
nodes::Identifier
BuilderTask<nodes::Identifier, ::utils::TypeclassIdTag>::operator()(
const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return nodes::Identifier{
.kind = nodes::Identifier::kTypeclass,
.value = parser_node.get_value(),
};
}
nodes::Identifier build_argument_name(parser::ParseTree::Node parser_node) {
return nodes::Identifier(build_node(parser_node),
nodes::Identifier::ARGUMENT_NAME,
parser_node.get_value());
nodes::Identifier
BuilderTask<nodes::Identifier, ::utils::ArgNameIdTag>::operator()(
const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return nodes::Identifier{
.kind = nodes::Identifier::kArgName,
.value = parser_node.get_value(),
};
}
nodes::Identifier build_argument_type(parser::ParseTree::Node parser_node) {
return nodes::Identifier(build_node(parser_node),
nodes::Identifier::ARGUMENT_TYPE,
parser_node.get_value());
nodes::Identifier
BuilderTask<nodes::Identifier, ::utils::ArgTypeIdTag>::operator()(
const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return nodes::Identifier{.kind = nodes::Identifier::kArgType,
.value = parser_node.get_value()};
}
// Annotations are used as strings
std::string build_annotation(parser::ParseTree::Node parser_node) {
// TODO
nodes::Annotation
BuilderTask<nodes::Annotation>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
std::string identifier = parser_node.get_value();
// identifier.size() > 0 by parsing convention
identifier = identifier.substr(1, identifier.size() - 1);
return identifier;
return nodes::Annotation{.value = identifier};
}
nodes::Identifier build_operator(parser::ParseTree::Node parser_node) {
nodes::Identifier
BuilderTask<nodes::Identifier, ::utils::OperatorIdTag>::operator()(
const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
std::string identifier = parser_node.get_value();
// --- points needed for proper printing
@ -295,24 +366,38 @@ nodes::Identifier build_operator(parser::ParseTree::Node parser_node) {
// }
// ---
return nodes::Identifier(build_node(parser_node), nodes::Identifier::OPERATOR,
identifier);
return nodes::Identifier{.kind = nodes::Identifier::kOperator,
.value = identifier};
}
nodes::Identifier build_placeholder(parser::ParseTree::Node parser_node) {
return nodes::Identifier(build_node(parser_node),
nodes::Identifier::PLACEHOLDER, "_");
nodes::Identifier
BuilderTask<nodes::Identifier, ::utils::PlaceholderIdTag>::operator()(
const ParserNode &, const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return nodes::Identifier{
.kind = nodes::Identifier::kPlaceholder,
.value = "_",
};
}
// --- extra
nodes::Extra build_extra(parser::ParseTree::Node parser_node) {
return nodes::Extra(build_node(parser_node), parser_node.get_value());
nodes::Extra
BuilderTask<nodes::Extra>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return nodes::Extra{.content = parser_node.get_value()};
}
// --- empty lines
nodes::EmptyLines build_empty_lines(parser::ParseTree::Node parser_node) {
nodes::EmptyLines
BuilderTask<nodes::EmptyLines>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
std::string empty_lines = parser_node.get_value();
size_t empty_lines_count = 0;
@ -324,11 +409,11 @@ nodes::EmptyLines build_empty_lines(parser::ParseTree::Node parser_node) {
}
if (empty_lines_count == 0) {
error_handling::handle_parsing_error("Empty lines node with zero new lines",
parser_node);
logc.Fatal<Log::kProc>({{"Empty lines node with zero new lines"}},
parser_node.get_pos());
}
return nodes::EmptyLines(build_node(parser_node), empty_lines_count - 1);
return nodes::EmptyLines{.count = empty_lines_count - 1};
}
} // namespace builders

View file

@ -2,154 +2,129 @@
#include "basic_builders.hpp"
#include "basic_nodes.hpp"
#include "error_handling.hpp"
#include "expression_nodes.hpp"
#include "log.hpp"
#include "tokens.hpp"
#include "type_builders.hpp"
#include "type_nodes.hpp"
// TODO: insert is_scoped everywere
namespace builders {
nodes::Expr BuilderTask<nodes::Expr>::operator()(const ParserNode &parser_node,
const Args &) {
Node BuilderTask<Node>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse);
tokens::Type type = tokens::string_to_type(parser_node.get_type());
auto maybe_parenthesis = parser_node.previous_sibling();
// FIXME TODO
bool is_scoped =
(!maybe_parenthesis.is_null() && !maybe_parenthesis.is_named() &&
maybe_parenthesis.get_value() == "(");
std::optional<nodes::ExprData::Type> expr;
switch (type) {
// --- flow control
case tokens::Type::MATCH:
expr = Run<nodes::Match>(parser_node);
break;
return Run<nodes::Match>(parser_node, {is_scoped});
case tokens::Type::CONDITION:
return state<Exprs>().add_expr({build_node(parser_node),
Run<nodes::Condition>(parser_node),
is_scoped});
expr = Run<nodes::Match>(parser_node);
break;
return Run<nodes::Condition>(parser_node, {is_scoped});
case tokens::Type::LOOP:
return state<Exprs>().add_expr(
{build_node(parser_node), Run<nodes::Loop>(parser_node), is_scoped});
expr = Run<nodes::Match>(parser_node);
break;
return Run<nodes::Loop>(parser_node, {is_scoped});
// --- operators
case tokens::Type::COMMA_EXPRESSION:
expr = Run<nodes::NameExpression, utils::CommaTag>(parser_node);
break;
return Run<nodes::NameExpression, utils::CommaTag>(parser_node,
{is_scoped});
case tokens::Type::OPERATOR_EXPRESSION:
expr = Run<nodes::NameExpression, utils::OperatorTag>(parser_node);
break;
return Run<nodes::NameExpression, utils::OperatorTag>(parser_node,
{is_scoped});
// --- containers
case tokens::Type::BLOCK:
expr = Run<nodes::Container, utils::BlockTag>(parser_node);
break;
return Run<nodes::Container, utils::BlockTag>(parser_node, {is_scoped});
case tokens::Type::ARRAY:
expr = Run<nodes::Container, utils::ArrayTag>(parser_node);
break;
return Run<nodes::Container, utils::ArrayTag>(parser_node, {is_scoped});
// --- modifiers
case tokens::Type::RETURN:
expr = Run<nodes::Return>(parser_node);
break;
return Run<nodes::Return>(parser_node, {is_scoped});
case tokens::Type::NAME_DEFINITION:
expr = Run<nodes::NameDefinition>(parser_node);
break;
return Run<nodes::NameDefinition>(parser_node, {is_scoped});
case tokens::Type::ARRAY_ACCESS:
expr = Run<nodes::Access, utils::ArrayAccessTag>(parser_node);
break;
return Run<nodes::Access, utils::ArrayAccessTag>(parser_node, {is_scoped});
case tokens::Type::TUPLE_ACCESS:
expr = Run<nodes::Access, utils::TupleAccessTag>(parser_node);
break;
return Run<nodes::Access, utils::TupleAccessTag>(parser_node, {is_scoped});
case tokens::Type::LOOP_CONTROL:
expr = Run<nodes::LoopControl>(parser_node);
break;
return Run<nodes::LoopControl>(parser_node, {is_scoped});
case tokens::Type::REFERENCE_EXPRESSION:
expr = Run<nodes::ModifierExpression, utils::RefTag>(parser_node);
break;
return Run<nodes::ModifierExpression, utils::RefTag>(parser_node,
{is_scoped});
case tokens::Type::SUFFIX_EXPRESSION:
expr = Run<nodes::ModifierExpression, utils::SuffixTag>(parser_node);
break;
return Run<nodes::ModifierExpression, utils::SuffixTag>(parser_node,
{is_scoped});
// --- other
case tokens::Type::NAME_EXPRESSION:
expr = Run<nodes::NameExpression, utils::FuncCallTag>(parser_node);
break;
return Run<nodes::NameExpression, utils::FuncCallTag>(parser_node,
{is_scoped});
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
case tokens::Type::SIMPLE_NAME_IDENTIFIER:
case tokens::Type::PLACEHOLDER:
expr = nodes::NameExpression(build_node(parser_node),
build_identifier(parser_node));
break;
return Build(
nodes::NameExpression{
.name = RunOther<nodes::Identifier>(parser_node),
},
parser_node.get_pos()); // TODO: is_scoped
case tokens::Type::CONSTRUCTOR:
expr = Run<nodes::Constructor>(parser_node);
break;
return Run<nodes::Constructor>(parser_node);
case tokens::Type::LAMBDA:
expr = Run<nodes::Lambda>(parser_node);
break;
return Run<nodes::Lambda>(parser_node);
// --- literals
case tokens::Type::FLOAT_LITERAL:
expr = build_float_literal(parser_node);
break;
case tokens::Type::DOUBLE_LITERAL:
expr = build_double_literal(parser_node);
break;
case tokens::Type::INT_LITERAL:
expr = build_int_literal(parser_node);
break;
case tokens::Type::LONG_LITERAL:
expr = build_long_literal(parser_node);
break;
case tokens::Type::INDEX_LITERAL:
expr = build_index_literal(parser_node);
break;
case tokens::Type::STRING_LITERAL:
expr = build_string_literal(parser_node);
break;
case tokens::Type::UNICODE_STRING_LITERAL:
expr = build_unicode_string_literal(parser_node);
break;
case tokens::Type::CHAR_LITERAL:
expr = build_char_literal(parser_node);
break;
case tokens::Type::UNICODE_LITERAL:
expr = build_unicode_literal(parser_node);
break;
case tokens::Type::BOOL_LITERAL:
expr = build_bool_literal(parser_node);
break;
case tokens::Type::UNIT_LITERAL:
expr = build_unit_literal(parser_node);
break;
case tokens::Type::NULL_LITERAL:
expr = build_null_literal(parser_node);
break;
case tokens::Type::EXTRA:
expr = build_extra(parser_node);
break;
case tokens::Type::EMPTY_LINES:
expr = build_empty_lines(parser_node);
break;
// TODO: FIXME:
// case tokens::Type::FLOAT_LITERAL:
// return BUILD : build_float_literal(parser_node);
// case tokens::Type::DOUBLE_LITERAL:
// return BUILD : build_double_literal(parser_node);
// case tokens::Type::INT_LITERAL:
// return BUILD : build_int_literal(parser_node);
// case tokens::Type::LONG_LITERAL:
// return BUILD : build_long_literal(parser_node);
// case tokens::Type::INDEX_LITERAL:
// return BUILD : build_index_literal(parser_node);
// case tokens::Type::STRING_LITERAL:
// return BUILD : build_string_literal(parser_node);
// case tokens::Type::UNICODE_STRING_LITERAL:
// return BUILD : build_unicode_string_literal(parser_node);
// case tokens::Type::CHAR_LITERAL:
// return BUILD : build_char_literal(parser_node);
// case tokens::Type::UNICODE_LITERAL:
// return BUILD : build_unicode_literal(parser_node);
// case tokens::Type::BOOL_LITERAL:
// return BUILD : build_bool_literal(parser_node);
// case tokens::Type::UNIT_LITERAL:
// return BUILD : build_unit_literal(parser_node);
// case tokens::Type::NULL_LITERAL:
// return BUILD : build_null_literal(parser_node);
// case tokens::Type::EXTRA:
// return BUILD : build_extra(parser_node);
// case tokens::Type::EMPTY_LINES:
// return BUILD : build_empty_lines(parser_node);
default:
utils::Assert(true,
std::format("Unexpected expression node type {}",
static_cast<int>(type))); // TODO: magic_enum
// FIXME: change to fatal error ?
break;
}
utils::Assert(expr.has_value(), "Expression should have value");
return state<Exprs>().add_expr(
{build_node(parser_node), expr.value(), is_scoped});
utils::Assert(true, std::format("Unexpected expression node type {}",
static_cast<int>(type))); // TODO: magic_enum
// FIXME: change to fatal error ?
throw std::exception();
}
// --- flow control
// (':=' | '=:') expression (('??' | 'if') expression)? (_do_ expression)?
nodes::Match::Case
BuilderTask<nodes::Match::Case>::operator()(const ParserNode &parser_node,
const Args &) {
Node BuilderTask<nodes::Match::Case>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse);
std::string case_type = parser_node.nth_child(0).get_value();
std::optional<ParserNode> condition_node;
@ -169,49 +144,59 @@ BuilderTask<nodes::Match::Case>::operator()(const ParserNode &parser_node,
}
}
return nodes::Match::Case(
build_node(parser_node),
case_type == ":=" ? nodes::Match::Case::PATTERN_VALUE
: nodes::Match::Case::VALUE_PATTERN,
Run<nodes::Expr>(parser_node.nth_named_child(0)),
condition_node.has_value() ? Run<nodes::Expr>(condition_node.value())
: std::optional<nodes::Expr>(),
expression_node.has_value() ? Run<nodes::Expr>(expression_node.value())
: std::optional<nodes::Expr>());
return Build(
nodes::Match::Case{
.kind = case_type == ":=" ? nodes::Match::Case::PATTERN_VALUE
: nodes::Match::Case::VALUE_PATTERN,
.value = Run<Node>(parser_node.nth_named_child(0)),
.condition = condition_node.has_value()
? Run<Node>(condition_node.value())
: std::optional<storage::Id>(),
.expr = expression_node.has_value()
? Run<Node>(expression_node.value())
: std::optional<storage::Id>(),
},
parser_node.get_pos());
}
// expression case+
nodes::Match
BuilderTask<nodes::Match>::operator()(const ParserNode &parser_node,
const Args &) {
std::vector<nodes::Match::Case> cases;
Node BuilderTask<nodes::Match>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse);
std::vector<storage::Id /*nodes::Match::Case*/> cases; // TODO
auto current_node = parser_node.nth_named_child(1);
while (!current_node.is_null()) {
cases.push_back(Run<nodes::Match::Case>(current_node));
cases.push_back(
Run<nodes::Match::Case>(current_node, {.is_scoped = false}));
current_node = current_node.next_named_sibling();
}
return nodes::Match(build_node(parser_node),
Run<nodes::Expr>(parser_node.nth_named_child(0)),
std::move(cases));
return Build(
nodes::Match{
.value = Run<Node>(parser_node.nth_named_child(0)),
.cases = std::move(cases),
},
parser_node.get_pos());
}
// ('??' | 'if') expression _do_ expression (('!!' | 'elif') expression _do_
// expression)* (('!!=>', 'else') expression)?
nodes::Condition
BuilderTask<nodes::Condition>::operator()(const ParserNode &parser_node,
const Args &) {
Node BuilderTask<nodes::Condition>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse);
size_t named_child_count = parser_node.named_child_count();
std::vector<std::pair<nodes::Expr, nodes::Expr>> cases;
std::vector<std::pair<storage::Id, storage::Id>> cases;
auto current_node = parser_node.nth_named_child(0);
auto next_node = current_node.next_named_sibling();
while (!current_node.is_null() && !next_node.is_null()) {
cases.push_back(
{Run<nodes::Expr>(current_node), Run<nodes::Expr>(next_node)});
{Run<storage::Id>(current_node), Run<storage::Id>(next_node)});
current_node = next_node.next_named_sibling();
if (current_node.is_null()) {
break;
@ -219,97 +204,102 @@ BuilderTask<nodes::Condition>::operator()(const ParserNode &parser_node,
next_node = current_node.next_named_sibling();
}
return nodes::Condition(
build_node(parser_node), std::move(cases),
named_child_count % 2 == 1
? Run<nodes::Expr>(parser_node.nth_named_child(named_child_count - 1))
: std::optional<nodes::Expr>());
return Build(
nodes::Condition{
.cases = std::move(cases),
.else_case = named_child_count % 2 == 1
? Run<Node>(parser_node.nth_named_child(
named_child_count - 1))
: std::optional<Node>(),
},
parser_node.get_pos());
}
// ('@' | 'for') (expression | expression ':' expression)? _do_ expression
nodes::Loop BuilderTask<nodes::Loop>::operator()(const ParserNode &parser_node,
const Args &) {
Node BuilderTask<nodes::Loop>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse);
size_t named_child_count = parser_node.named_child_count();
if (named_child_count == 1) { // body
return nodes::Loop(build_node(parser_node),
Run<nodes::Expr>(parser_node.nth_named_child(0)));
return Build(nodes::Loop(Run<Node>(parser_node.nth_named_child(0))),
parser_node.get_pos());
} else if (named_child_count == 2) { // condition,
// body
return nodes::Loop(build_node(parser_node),
Run<nodes::Expr>(parser_node.nth_named_child(0)),
Run<nodes::Expr>(parser_node.nth_named_child(1)));
return Build(nodes::Loop(Run<Node>(parser_node.nth_named_child(0)),
Run<Node>(parser_node.nth_named_child(1))),
parser_node.get_pos());
} else if (named_child_count == 3) { // variable,
// interval,
// body
return nodes::Loop(build_node(parser_node),
Run<nodes::Expr>(parser_node.nth_named_child(0)),
Run<nodes::Expr>(parser_node.nth_named_child(1)),
Run<nodes::Expr>(parser_node.nth_named_child(2)));
return Build(nodes::Loop(Run<Node>(parser_node.nth_named_child(0)),
Run<Node>(parser_node.nth_named_child(1)),
Run<Node>(parser_node.nth_named_child(2))),
parser_node.get_pos());
} else {
error_handling::handle_parsing_error("Unex"
"prec"
"ted "
"name"
"d "
"expr"
"essi"
"on "
"amou"
"nt "
"in "
"loo"
"p",
parser_node);
logc.Fatal<Log::kProc>({{"Unexpected named expression amount in loop"}},
parser_node.get_pos());
}
error_handling::handle_general_error("Unreac"
"habl"
"e");
error_handling::handle_general_error("Unreachable");
exit(1); // unreachable
}
// --- operators
// expression ',' expression
nodes::NameExpression
BuilderTask<nodes::NameExpression, utils::CommaTag>::operator()(
Node BuilderTask<nodes::NameExpression, utils::CommaTag>::operator()(
const ParserNode &parser_node, const Args &) {
std::vector<std::pair<std::optional<std::string>, nodes::Expr>> args;
Log::Context logc(executor.log(), Log::Area::kParse);
std::vector<std::pair<std::optional<std::string>, storage::Id>> args;
args.emplace_back(std::nullopt,
Run<nodes::Expr>(parser_node.nth_named_child(0)));
Run<storage::Id>(parser_node.nth_named_child(0)));
args.emplace_back(std::nullopt,
Run<nodes::Expr>(parser_node.nth_named_child(1)));
Run<storage::Id>(parser_node.nth_named_child(1)));
return nodes::NameExpression(
build_node(parser_node),
nodes::Identifier(
build_node(parser_node), // can't find more precise location
nodes::Identifier::SIMPLE_NAME, ","),
std::move(args), std::nullopt, false, true);
return Build(
nodes::NameExpression{
.name =
nodes::Identifier{
// can't find more precise location
.kind = nodes::Identifier::kSimpleName,
.value = ",",
},
.args = std::move(args),
.prefix = {},
.is_point_call = false,
.is_operator_call = true,
},
parser_node.get_pos());
}
// expression operator expression
nodes::NameExpression
BuilderTask<nodes::NameExpression, utils::OperatorTag>::operator()(
Node BuilderTask<nodes::NameExpression, utils::OperatorTag>::operator()(
const ParserNode &parser_node, const Args &) {
auto name_node = parser_node.child_by_field_name("na"
"m"
"e");
Log::Context logc(executor.log(), Log::Area::kParse);
std::vector<std::pair<std::optional<std::string>, nodes::Expr>> args;
auto name_node = parser_node.child_by_field_name("name");
std::vector<std::pair<std::optional<std::string>, storage::Id>> args;
args.emplace_back(std::nullopt,
Run<nodes::Expr>(name_node.previous_named_sibling()));
Run<Node>(name_node.previous_named_sibling()));
args.emplace_back(std::nullopt,
Run<nodes::Expr>(name_node.next_named_sibling()));
args.emplace_back(std::nullopt, Run<Node>(name_node.next_named_sibling()));
return nodes::NameExpression(build_node(parser_node),
build_operator(name_node), std::move(args),
std::nullopt, false, true);
return Build(
nodes::NameExpression{
.name = RunOther<nodes::Identifier, utils::OperatorIdTag>(name_node),
.args = std::move(args),
.prefix = {},
.is_point_call = false,
.is_operator_call = true,
},
parser_node.get_pos());
}
// --- continers
@ -319,64 +309,84 @@ BuilderTask<nodes::NameExpression, utils::OperatorTag>::operator()(
// --- modifiers
// ('return' | 'bring') expression
nodes::Return
BuilderTask<nodes::Return>::operator()(const ParserNode &parser_node,
const Args &) {
Node BuilderTask<nodes::Return>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse);
std::string modifier = parser_node.nth_child(0).get_value();
return nodes::Return(build_node(parser_node),
modifier == "re"
"tu"
"rn"
? nodes::Return::RETURN
: nodes::Return::BRING,
Run<nodes::Expr>(parser_node.nth_named_child(0)));
return Build(
nodes::Return{
.kind = modifier == "return" ? nodes::Return::RETURN
: nodes::Return::BRING,
.expr = Run<Node>(parser_node.nth_named_child(0)),
},
parser_node.get_pos());
}
// _var_let_ (simple_name_identifier | placeholder)
nodes::NameDefinition
BuilderTask<nodes::NameDefinition>::operator()(const ParserNode &parser_node,
const Args &) {
Node BuilderTask<nodes::NameDefinition>::operator()(
const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse);
std::string modifier = parser_node.nth_child(0).get_value();
auto name_node = parser_node.nth_named_child(0);
return nodes::NameDefinition(build_node(parser_node),
(modifier == "%" || modifier == "let")
? nodes::NameDefinition::LET
: nodes::NameDefinition::VAR,
build_identifier(name_node));
return Build(
nodes::NameDefinition{
.kind = (modifier == "%" || modifier == "let")
? nodes::NameDefinition::LET
: nodes::NameDefinition::VAR,
.name =
Run<nodes::Identifier, utils::None, nodes::Identifier>(name_node),
},
parser_node.get_pos());
} // IN PROGRESS
// expression '[' expression ']'
nodes::Access BuilderTask<nodes::Access, utils::ArrayAccessTag>::operator()(
Node BuilderTask<nodes::Access, utils::ArrayAccessTag>::operator()(
const ParserNode &parser_node, const Args &) {
return nodes::Access(build_node(parser_node), nodes::Access::ARRAY,
Run<nodes::Expr>(parser_node.nth_named_child(0)),
Run<nodes::Expr>(parser_node.nth_named_child(1)));
Log::Context logc(executor.log(), Log::Area::kParse);
return Build(
nodes::Access{.kind = nodes::Access::ARRAY,
.value = Run<Node>(parser_node.nth_named_child(0)),
.index = Run<Node>(parser_node.nth_named_child(1))},
parser_node.get_pos());
}
// expression '.' number_literal
nodes::Access BuilderTask<nodes::Access, utils::TupleAccessTag>::operator()(
Node BuilderTask<nodes::Access, utils::TupleAccessTag>::operator()(
const ParserNode &parser_node, const Args &) {
return nodes::Access(
build_node(parser_node), nodes::Access::TUPLE,
Run<nodes::Expr>(parser_node.nth_named_child(0)),
state<Exprs>().add_expr(
{build_node(parser_node.nth_named_child(1)),
build_index_literal(parser_node.nth_named_child(1)), false}));
Log::Context logc(executor.log(), Log::Area::kParse);
auto const node = Build(
nodes::Access{
.kind = nodes::Access::TUPLE,
.value = Run<Node>(parser_node.nth_named_child(0)),
.index = Run<Node>(parser_node.nth_named_child(1)),
// TODO: FIXME:
// .index = Build(build_index_literal(parser_node.nth_named_child(
// 1)) /*, false}*/, // ?? is_scoped ??
},
parser_node.get_pos());
return node;
}
// 'break' | 'continue'
nodes::LoopControl
BuilderTask<nodes::LoopControl>::operator()(const ParserNode &parser_node,
const Args &) {
return nodes::LoopControl(build_node(parser_node),
parser_node.get_value() == "br"
"ea"
"k"
? nodes::LoopControl::BREAK
: nodes::LoopControl::CONTINUE);
Node BuilderTask<nodes::LoopControl>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse);
return Build(
nodes::LoopControl{
.kind = parser_node.get_value() == "break"
? nodes::LoopControl::BREAK
: nodes::LoopControl::CONTINUE,
},
parser_node.get_pos());
}
// // ModifierExpression -> .hpp
@ -391,10 +401,12 @@ void build_args_until_end(ParserNode first_parse_node, Executor &executor,
while (!current_node.is_null()) {
if (tokens::string_to_type(current_node.get_type()) ==
tokens::Type::ANNOTATION_IDENTIFIER) {
last_annotation = build_annotation(current_node);
last_annotation =
BuilderTask<nodes::Annotation>{executor}(current_node, {})
.value; // TODO
} else {
args.emplace_back(std::move(last_annotation),
BuilderTask<nodes::Expr>{executor}(current_node, {}));
BuilderTask<Node>{executor}(current_node, {}));
last_annotation = std::nullopt;
}
current_node = current_node.next_named_sibling();
@ -403,18 +415,17 @@ void build_args_until_end(ParserNode first_parse_node, Executor &executor,
// (type '.' simple_name | expression '.' simple_name | name | '(' operator
// ')') (annotation? expression)*
nodes::NameExpression
BuilderTask<nodes::NameExpression, utils::FuncCallTag>::operator()(
Node BuilderTask<nodes::NameExpression, utils::FuncCallTag>::operator()(
const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse);
std::vector<nodes::AnnotatedArgument> args;
std::optional<nodes::TypeData> prefix;
bool is_point_call = false;
auto name_node = parser_node.child_by_field_name("na"
"m"
"e");
auto name_node = parser_node.child_by_field_name("name");
std::optional<ParserNode> prefix_node;
@ -433,23 +444,30 @@ BuilderTask<nodes::NameExpression, utils::FuncCallTag>::operator()(
prefix_node = current_node;
} else {
is_point_call = true;
args.emplace_back(std::nullopt, Run<nodes::Expr>(current_node));
args.emplace_back(std::nullopt, Run<Node>(current_node));
}
}
build_args_until_end(name_node.next_named_sibling(), executor, args);
return nodes::NameExpression(
build_node(parser_node), build_identifier(name_node), std::move(args),
prefix_node.has_value() ? build_type(prefix_node.value(), state<Types>())
: nodes::MaybeType(),
is_point_call, false);
return Build(
nodes::NameExpression{
.name = RunOther<nodes::Identifier>(name_node),
.args = std::move(args),
.prefix = prefix_node.has_value()
? build_type(prefix_node.value(), state<Types>())
: nodes::MaybeType(),
.is_point_call = is_point_call,
.is_operator_call = false,
},
parser_node.get_pos());
}
// type (annotation? expression)*
nodes::Constructor
BuilderTask<nodes::Constructor>::operator()(const ParserNode &parser_node,
const Args &) {
Node BuilderTask<nodes::Constructor>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse);
std::vector<nodes::AnnotatedArgument> args;
build_args_until_end(parser_node
@ -459,31 +477,39 @@ BuilderTask<nodes::Constructor>::operator()(const ParserNode &parser_node,
.next_named_sibling(),
executor, args);
return nodes::Constructor(
build_node(parser_node),
build_type(parser_node.child_by_field_name("type"), state<Types>()),
std::move(args));
return Build(
nodes::Constructor{
.type = build_type(parser_node.child_by_field_name("type"),
state<Types>()),
.args = std::move(args),
},
parser_node.get_pos());
}
// '\\' argument_name* _do_ expression
nodes::Lambda
BuilderTask<nodes::Lambda>::operator()(const ParserNode &parser_node,
const Args &) {
Node BuilderTask<nodes::Lambda>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse);
std::vector<nodes::Identifier> args;
auto current_node =
parser_node.nth_child(1); // next to '\\', not null ('=>' should present)
while (current_node.is_named()) { // until _do_
args.emplace_back(build_identifier(current_node));
args.emplace_back(RunOther<nodes::Identifier>(current_node));
current_node = current_node.next_sibling();
}
// skip '=>'
current_node = current_node.next_named_sibling();
return nodes::Lambda(build_node(parser_node), std::move(args),
Run<nodes::Expr>(current_node));
return Build(
nodes::Lambda{
.args = std::move(args),
.expr = Run<Node>(current_node),
},
parser_node.get_pos());
}
} // namespace builders

View file

@ -4,7 +4,6 @@
#include "basic_nodes.hpp"
#include "doc_builders.hpp"
#include "doc_nodes.hpp"
#include "error_handling.hpp"
#include "expression_builders.hpp"
#include "statement_nodes.hpp"
#include "tokens.hpp"
@ -22,6 +21,8 @@ namespace builders {
nodes::Statements
BuilderTask<nodes::Statements>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
std::vector<nodes::Statement> statements;
std::optional<nodes::Identifier> last_defined_type_name;
@ -39,6 +40,8 @@ BuilderTask<nodes::Statements>::operator()(const ParserNode &parser_node,
nodes::Statement
BuilderTask<nodes::Statement>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
tokens::Type type = tokens::string_to_type(parser_node.get_type());
std::optional<std::string> statement_name;
@ -46,45 +49,33 @@ BuilderTask<nodes::Statement>::operator()(const ParserNode &parser_node,
switch (type) {
case tokens::Type::IMPORT:
statement = nodes::Statement(build_node(parser_node),
Run<nodes::Import>(parser_node));
statement_name = *statement.value()
.get<nodes::Import>()
.value()
->get_module_name()
->get();
statement = nodes::Statement{Run<nodes::Import>(parser_node)};
statement_name =
statement.value().get<nodes::Import>().value()->module_name.value;
break;
case tokens::Type::TYPE_DEFINITION:
statement = nodes::Statement(build_node(parser_node),
Run<nodes::TypeDefinition>(parser_node));
statement = nodes::Statement{Run<nodes::TypeDefinition>(parser_node)};
state<State>().last_defined_type_name =
*statement.value().get<nodes::TypeDefinition>().value()->get_name();
statement_name = *statement.value()
.get<nodes::TypeDefinition>()
.value()
->get_name()
->get();
statement.value().get<nodes::TypeDefinition>().value()->name;
statement_name =
statement.value().get<nodes::TypeDefinition>().value()->name.value;
break;
case tokens::Type::FUNCTION_DEFINITION:
statement = nodes::Statement(build_node(parser_node),
Run<nodes::FunctionDefinition>(parser_node));
statement_name = *statement.value()
.get<nodes::FunctionDefinition>()
.value()
->get_full_name()
->get();
statement = nodes::Statement{Run<nodes::FunctionDefinition>(parser_node)};
statement_name = statement.value()
.get<nodes::FunctionDefinition>()
.value()
->full_name.value;
break;
case tokens::Type::EXTRA:
statement =
nodes::Statement(build_node(parser_node), build_extra(parser_node));
statement = nodes::Statement{Run<nodes::Extra>(parser_node)};
break;
case tokens::Type::EMPTY_LINES:
statement = nodes::Statement(build_node(parser_node),
build_empty_lines(parser_node));
statement = nodes::Statement{Run<nodes::EmptyLines>(parser_node)};
break;
default:
error_handling::handle_parsing_error("Unexprected statement node type",
parser_node);
logc.Fatal<Log::kProc>({{"Unexprected statement node type"}},
parser_node.get_pos());
}
if (!statement.has_value()) {
@ -97,8 +88,8 @@ BuilderTask<nodes::Statement>::operator()(const ParserNode &parser_node,
.insert_combine(statement_name.value(), std::move(statement_copy))
.second != nodes::CombineResult::OK) {
// TODO: more detailed errors
error_handling::handle_parsing_error(
"Can't combine statements with same name", parser_node);
logc.Fatal<Log::kProc>({{"Can't combine statements with same name"}},
parser_node.get_pos());
}
}
@ -109,6 +100,7 @@ BuilderTask<nodes::Statement>::operator()(const ParserNode &parser_node,
nodes::Import
BuilderTask<nodes::Import>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
auto name_node = parser_node.child_by_field_name("name");
auto module_node = parser_node.child_by_field_name("module");
@ -120,20 +112,21 @@ BuilderTask<nodes::Import>::operator()(const ParserNode &parser_node,
auto current_node = module_node.next_named_sibling();
while (!current_node.is_null()) {
symbols.push_back(build_identifier(current_node));
symbols.push_back(Run<nodes::Identifier>(current_node));
current_node = current_node.next_named_sibling();
}
return nodes::Import(build_node(parser_node), build_identifier(name_node),
build_identifier(module_node), std::move(symbols));
return nodes::Import(Run<nodes::Identifier>(name_node),
Run<nodes::Identifier>(module_node), std::move(symbols));
}
// '?' expression
nodes::Constraint
BuilderTask<nodes::Constraint>::operator()(const ParserNode &parser_node,
const Args &) {
return nodes::Constraint(build_node(parser_node),
Run<nodes::Expr>(parser_node.nth_named_child(0)));
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return nodes::Constraint{.expr = Run<Node>(parser_node.nth_named_child(0))};
}
parser::ParseTree::Node collect_symbol_doc_nodes(
@ -170,6 +163,8 @@ parser::ParseTree::Node collect_symbol_doc_nodes(
nodes::TypeDefinition
BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
std::optional<parser::ParseTree::Node> description_node;
std::vector<parser::ParseTree::Node> annotation_nodes;
@ -179,16 +174,16 @@ BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
bool is_on_heap = !name_node.previous_sibling().is_null() &&
name_node.previous_sibling().get_value() == "<>";
nodes::Identifier name = build_identifier(name_node);
nodes::Identifier name = Run<nodes::Identifier>(name_node);
bool is_typeclass = (name.get_type() == nodes::Identifier::TYPECLASS);
bool is_typeclass = (name.kind == nodes::Identifier::kTypeclass);
//
if (is_typeclass && !annotation_nodes.empty()) {
error_handling::handle_parsing_error(
"Typeclass definition can't have annotation documentation",
parser_node);
logc.Fatal<Log::kProc>(
{{"Typeclass definition can't have annotation documentation"}},
parser_node.get_pos());
}
//
@ -202,10 +197,10 @@ BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
while (!current_node.is_null()) {
switch (tokens::string_to_type(current_node.get_type())) {
case tokens::Type::TYPECLASS_IDENTIFIER:
typeclasses.push_back(build_identifier(current_node));
typeclasses.push_back(Run<nodes::Identifier>(current_node));
break;
case tokens::Type::ARGUMENT_TYPE_IDENTIFIER:
args.push_back(build_identifier(current_node));
args.push_back(Run<nodes::Identifier>(current_node));
break;
case tokens::Type::VARIANT_TYPE:
case tokens::Type::TUPLE_TYPE:
@ -213,33 +208,34 @@ BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
case tokens::Type::MODIFIED_TYPE:
case tokens::Type::SIMPLE_TYPE:
if (type_node.has_value()) {
error_handling::handle_parsing_error(
"More then one type node in type definition", parser_node);
logc.Fatal<Log::kProc>({{"More then one type node in type definition"}},
parser_node.get_pos());
}
type_node = current_node;
break;
default:
error_handling::handle_parsing_error(
"Unexprected node type in type definition", parser_node);
logc.Fatal<Log::kProc>({{"Unexprected node type in type definition"}},
parser_node.get_pos());
}
current_node = current_node.next_named_sibling();
}
if (!type_node.has_value() && !annotation_nodes.empty()) {
error_handling::handle_parsing_error(
"Type declaration can't contain annotation documentation", parser_node);
logc.Fatal<Log::kProc>(
{{"Type declaration can't contain annotation documentation"}},
parser_node.get_pos());
}
if (is_typeclass) {
if (!args.empty()) {
error_handling::handle_parsing_error("Typeclass can't have arguments",
parser_node);
logc.Fatal<Log::kProc>({{"Typeclass can't have arguments"}},
parser_node.get_pos());
}
if (type_node.has_value()) {
error_handling::handle_parsing_error(
"Typeclass can't be type (contain constructors / fields)",
type_node.value());
logc.Fatal<Log::kProc>(
{{"Typeclass can't be type (contain constructors / fields)"}},
type_node.value().get_pos());
}
}
@ -255,11 +251,15 @@ BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
annotations, annotations.begin()));
}
return nodes::TypeDefinition(
build_node(parser_node),
build_symbol_docs(description_node, annotation_nodes, annotations),
is_on_heap, std::move(name), std::move(typeclasses), std::move(args),
type);
return nodes::TypeDefinition{
.docs =
build_symbol_docs(description_node, annotation_nodes, annotations),
.is_on_heap = is_on_heap,
.name = std::move(name),
.typeclasses = std::move(typeclasses),
.args = std::move(args),
.type = type,
};
}
// definition_info? annotation_info* (constraint ';')* '.'? (simple_name
@ -268,6 +268,8 @@ BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
// (((block | array) | '=' expression ';') | ';')
nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
// const std::optional<nodes::Identifier> &last_defined_type_name, // TODO
std::optional<parser::ParseTree::Node> description_node;
@ -296,8 +298,8 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
is_method = true;
if (!state<State>().last_defined_type_name.has_value()) {
error_handling::handle_parsing_error(
"Can't define method without associated type", parser_node);
logc.Fatal<Log::kProc>({{"Can't define method without associated type"}},
parser_node.get_pos());
}
name_prefix = state<State>().last_defined_type_name.value();
@ -307,7 +309,7 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
current_node = name_node.next_sibling();
if (!current_node.is_null() && !current_node.is_named()) {
return_modifier = build_modifier(current_node);
return_modifier = Run<nodes::Modifier>(current_node);
// only optional, result allowed
if (!nodes::utils::is_suffix_modifier(return_modifier)) {
@ -333,7 +335,7 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
// update last before modifier
auto maybe_reference_node = current_node.previous_sibling();
if (!maybe_reference_node.is_null() && !maybe_reference_node.is_named()) {
last_before_modifier = build_modifier(maybe_reference_node);
last_before_modifier = Run<nodes::Modifier>(maybe_reference_node);
// only out, in, ref allowed
if (nodes::utils::is_suffix_modifier(last_before_modifier)) {
@ -343,13 +345,13 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
switch (tokens::string_to_type(current_node.get_type())) {
case tokens::Type::ANNOTATION_IDENTIFIER:
last_annotation = build_annotation(current_node);
last_annotation = Run<nodes::Annotation>(current_node).value; // TODO
break;
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
// update last after modifier
maybe_reference_node = current_node.next_sibling();
if (!maybe_reference_node.is_null() && !maybe_reference_node.is_named()) {
last_after_modifier = build_modifier(maybe_reference_node);
last_after_modifier = Run<nodes::Modifier>(maybe_reference_node);
// only optional, result allowed
if (!nodes::utils::is_suffix_modifier(last_after_modifier)) {
@ -363,8 +365,8 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
}
args.push_back(nodes::FunctionDefinition::Argument(
last_annotation, build_identifier(current_node), last_before_modifier,
last_after_modifier));
last_annotation, Run<nodes::Identifier>(current_node),
last_before_modifier, last_after_modifier));
last_annotation = std::nullopt;
break;
@ -381,12 +383,12 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
if (!args[current_type_id].add_type(
last_annotation, build_type(current_node, state<Types>()),
last_before_modifier)) {
error_handling::handle_parsing_error(
"It is impossible to use argument modifiers (annotations, "
"references, "
"optional markers, result markers) when types explicitely "
"defined. Use type annotations instead.",
current_node);
logc.Fatal<Log::kProc>(
{{"It is impossible to use argument modifiers (annotations, "
"references, "
"optional markers, result markers) when types explicitely "
"defined. Use type annotations instead."}},
current_node.get_pos());
}
}
@ -396,9 +398,9 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
break;
default:
if (expression_node.has_value()) {
error_handling::handle_parsing_error(
"More then one expression found in function definition",
parser_node);
logc.Fatal<Log::kProc>(
{{"More then one expression found in function definition"}},
parser_node.get_pos());
}
expression_node = current_node;
break;
@ -407,15 +409,16 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
}
if (current_type_id > 0 && current_type_id < args.size()) {
error_handling::handle_parsing_error(
"Less types then arguments in function definition", parser_node);
logc.Fatal<Log::kProc>(
{{"Less types then arguments in function definition"}},
parser_node.get_pos());
}
if (current_type_id == 0 && !expression_node.has_value()) {
error_handling::handle_parsing_error(
"Can't declare function without types (types or function body should "
"be added)",
parser_node);
logc.Fatal<Log::kProc>(
{{"Can't declare function without types (types or function body should "
"be added)"}},
parser_node.get_pos());
}
// automatic annotations
@ -424,13 +427,13 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
if (are_annotations_same_to_names) {
for (size_t i = 0; i < args.size(); ++i) {
std::string new_annotation = *args[i].get_name().value()->get();
std::string new_annotation = args[i].get_name().value()->value;
if (!args[i].add_annotation(
new_annotation.substr(1, new_annotation.size() - 1))) {
error_handling::handle_parsing_error(
"no annotations provided ( => all annotations same to names), but "
"can't add name annotation",
current_node);
logc.Fatal<Log::kProc>({{"no annotations provided ( => all annotations "
"same to names), but "
"can't add name annotation"}},
current_node.get_pos());
}
}
}
@ -439,21 +442,20 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
for (auto &arg : args) {
if (arg.get_annotation().has_value()) {
if (!annotations_set.insert(*arg.get_annotation().value()).second) {
error_handling::handle_parsing_error(
"Two or more same annotations found in function definition",
parser_node);
logc.Fatal<Log::kProc>(
{{"Two or more same annotations found in function definition"}},
parser_node.get_pos());
}
}
}
return nodes::FunctionDefinition(
build_node(parser_node),
build_symbol_docs(description_node, annotation_nodes, annotations_set),
std::move(constraints), return_modifier, is_method, name_prefix,
build_identifier(name_node), std::move(args),
Run<nodes::Identifier>(name_node), std::move(args),
are_annotations_same_to_names,
expression_node.has_value() ? Run<nodes::Expr>(expression_node.value())
: std::optional<nodes::Expr>());
expression_node.has_value() ? Run<Node>(expression_node.value())
: std::optional<Node>());
}
} // namespace builders

View file

@ -151,37 +151,37 @@ inline bool can_cast_modifier(Modifier from, Modifier to) {
} // namespace utils
class Node {
public:
Node() : undefined_(true) {}
// class Node {
// public:
// Node() : undefined_(true) {}
Node(std::pair<size_t, size_t> start_position,
std::pair<size_t, size_t> end_position)
: undefined_(false), start_position_(start_position),
end_position_(end_position) {}
// Node(std::pair<size_t, size_t> start_position,
// std::pair<size_t, size_t> end_position)
// : undefined_(false), start_position_(start_position),
// end_position_(end_position) {}
std::pair<size_t, size_t> get_start_position() const {
if (undefined_) {
error_handling::handle_general_error(
"Get start position from undefined node");
}
return start_position_;
}
// std::pair<size_t, size_t> get_start_position() const {
// if (undefined_) {
// error_handling::handle_general_error(
// "Get start position from undefined node");
// }
// return start_position_;
// }
std::pair<size_t, size_t> get_end_position() const {
if (undefined_) {
error_handling::handle_general_error(
"Get end position from undefined node");
}
return end_position_;
}
// std::pair<size_t, size_t> get_end_position() const {
// if (undefined_) {
// error_handling::handle_general_error(
// "Get end position from undefined node");
// }
// return end_position_;
// }
protected:
bool undefined_ = false;
// protected:
// bool undefined_ = false;
std::pair<size_t, size_t> start_position_ = {0, 0};
std::pair<size_t, size_t> end_position_ = {0, 0};
};
// std::pair<size_t, size_t> start_position_ = {0, 0};
// std::pair<size_t, size_t> end_position_ = {0, 0};
// };
struct unit {};
struct null {};
@ -194,162 +194,121 @@ struct unicode {
std::string ch;
};
class Literal : public Node {
struct Literal {
public:
using Type =
std::variant<float, double, int32_t, int64_t, size_t, std::string,
unicode_string, char, unicode, bool, unit, null>;
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_);
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_);
if (std::holds_alternative<T>(value)) {
return &std::get<T>(value);
}
return std::nullopt;
}
Type &get_any() { return value_; }
//
const Type &get_any() const { return value_; }
private:
Type value_;
Type value;
};
class Identifier : public Node {
public:
static constexpr char NAME_DELIMITER = '.';
// TODO: merge with identifier ??
struct Annotation {
auto operator<=>(const Annotation &other) const = default;
enum IdentifierType {
SIMPLE_NAME,
SIMPLE_TYPE,
TYPECLASS,
ARGUMENT_NAME,
ARGUMENT_TYPE,
std::string value;
};
struct Identifier {
public:
static constexpr char kNameDelimiter = '.';
enum Kind {
kSimpleName,
kSimpleType,
kTypeclass,
kArgName,
kArgType,
// ANNOTATION, used as std::string
OPERATOR,
PLACEHOLDER,
kOperator,
kPlaceholder,
//
GENERIC_TYPE,
kGenericType,
};
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_; }
auto operator<=>(const Identifier &other) const = default;
//
std::string *get() { return &value_; }
Kind kind;
std::string value;
const std::string *get() const { return &value_; }
// TODO
//
// void append_before(const std::string &name) {
// value_ = name + NAME_DELIMITER + value_;
// }
void append_before(const std::string &name) {
value_ = name + NAME_DELIMITER + value_;
}
// void append_before(
// const Identifier &identifier,
// std::source_location location = std::source_location::current()) {
// error_handling::expect(identifier.type_ == type_,
// "different Identifier types on append_before",
// location);
// value_ = *identifier.get() + NAME_DELIMITER + value_;
// }
void append_before(
const Identifier &identifier,
std::source_location location = std::source_location::current()) {
error_handling::expect(identifier.type_ == type_,
"different Identifier types on append_before",
location);
value_ = *identifier.get() + NAME_DELIMITER + value_;
}
// void append_after(const std::string &name) {
// value_ += NAME_DELIMITER + name;
// }
void append_after(const std::string &name) {
value_ += NAME_DELIMITER + name;
}
// void append_after(
// const Identifier &identifier,
// std::source_location location = std::source_location::current()) {
// error_handling::expect(identifier.type_ == type_,
// "different Identifier types on append_after",
// location);
// value_ += NAME_DELIMITER + *identifier.get();
// }
void append_after(
const Identifier &identifier,
std::source_location location = std::source_location::current()) {
error_handling::expect(identifier.type_ == type_,
"different Identifier types on append_after",
location);
value_ += NAME_DELIMITER + *identifier.get();
}
// std::vector<Identifier> get_fragments() const {
// std::vector<Identifier> fragments;
// for (auto &&fragment_name :
// std::ranges::views::split(value_, NAME_DELIMITER)) {
// fragments.emplace_back(
// *this, type_,
// std::string(fragment_name.begin(), fragment_name.end()));
// }
// return fragments;
// }
std::vector<Identifier> get_fragments() const {
std::vector<Identifier> fragments;
for (auto &&fragment_name :
std::ranges::views::split(value_, NAME_DELIMITER)) {
fragments.emplace_back(
*this, type_,
std::string(fragment_name.begin(), fragment_name.end()));
}
return fragments;
}
std::pair<Identifier, Identifier> split_first() {
const auto pos = value_.find(NAME_DELIMITER);
if (pos == std::string::npos) {
return {Identifier(*this, type_, ""), *this};
}
return {
Identifier(*this, type_, value_.substr(0, pos)),
Identifier(*this, type_, value_.substr(pos + 1))}; // '.' is leaved out
}
//
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);
}
bool operator<(const Identifier &other_identifier) const {
return type_ < other_identifier.type_ || (type_ == other_identifier.type_ &&
value_ < other_identifier.value_);
}
private:
IdentifierType type_;
std::string value_;
// std::pair<Identifier, Identifier> split_first() {
// const auto pos = value_.find(NAME_DELIMITER);
// if (pos == std::string::npos) {
// return {Identifier(*this, type_, ""), *this};
// }
// return {
// Identifier(*this, type_, value_.substr(0, pos)),
// Identifier(*this, type_, value_.substr(pos + 1))}; // '.' is leaved
// out
// }
};
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_;
struct Extra {
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_;
struct EmptyLines {
size_t count;
};
} // namespace nodes

View file

@ -1,6 +1,7 @@
#pragma once
#include "basic_nodes.hpp"
#include "storage.hpp"
#include "type_nodes.hpp"
#include <optional>
@ -9,504 +10,190 @@
namespace nodes {
class TypedNode : public Node {
public:
TypedNode(Node node) : Node(node) {}
void set_expression_type(Type expression_type) {
expression_type_ = expression_type;
}
std::optional<Type> get_expression_type() const { return expression_type_; }
protected:
std::optional<Type> expression_type_;
};
using NodeId = storage::Id;
class ExprData;
class ExprStorage;
class Expr {
friend ExprStorage;
public:
Expr() = delete;
ExprData *get();
const ExprData *get() const;
private:
Expr(ExprStorage &expression_storage, size_t id)
: expression_storage_(&expression_storage), id_(id) {}
private:
ExprStorage *expression_storage_;
size_t id_;
// TODO: add to all nodes
struct GeneralInfo {
bool is_scoped;
};
namespace utils {
// namespace utils {
inline std::optional<nodes::ExprData *>
proxy_to_expr_optional(std::optional<nodes::Expr> &proxy) {
if (proxy.has_value()) {
return proxy.value().get();
}
return std::nullopt;
}
// inline std::optional<nodes::ExprData *>
// proxy_to_expr_optional(std::optional<nodes::Expr> &proxy) {
// if (proxy.has_value()) {
// return proxy.value().get();
// }
// return std::nullopt;
// }
inline std::optional<const nodes::ExprData *>
proxy_to_expr_optional(const std::optional<nodes::Expr> &proxy) {
if (proxy.has_value()) {
return proxy.value().get();
}
return std::nullopt;
}
// inline std::optional<const nodes::ExprData *>
// proxy_to_expr_optional(const std::optional<nodes::Expr> &proxy) {
// if (proxy.has_value()) {
// return proxy.value().get();
// }
// return std::nullopt;
// }
} // namespace utils
// } // namespace utils
// --- flow control
class Match : public TypedNode {
public:
class Case : public TypedNode {
public:
enum CaseType {
struct Match {
struct Case {
enum Kind {
PATTERN_VALUE,
VALUE_PATTERN,
};
Case(Node node, CaseType case_type, Expr value,
std::optional<Expr> condition = std::nullopt,
std::optional<Expr> expression = std::nullopt)
: TypedNode(node), case_type_(case_type), value_(value),
condition_(condition), expression_(expression) {}
//
CaseType case_type() const { return case_type_; }
ExprData *get_value() { return value_.get(); }
const ExprData *get_value() const { return value_.get(); }
std::optional<ExprData *> get_condition() {
return utils::proxy_to_expr_optional(condition_);
}
std::optional<const ExprData *> get_condition() const {
return utils::proxy_to_expr_optional(condition_);
}
std::optional<ExprData *> get_expression() {
return utils::proxy_to_expr_optional(expression_);
}
std::optional<const ExprData *> get_expression() const {
return utils::proxy_to_expr_optional(expression_);
}
private:
CaseType case_type_;
Expr value_;
std::optional<Expr> condition_;
std::optional<Expr> expression_;
Kind kind;
NodeId value;
std::optional<NodeId> condition;
std::optional<NodeId> expr;
};
Match(Node node, Expr value, std::vector<Case> &&cases)
: TypedNode(node), value_(value), cases_(std::move(cases)) {}
//
Match(Node node, Expr value, const std::vector<Case> &cases)
: TypedNode(node), value_(value), cases_(cases) {}
ExprData *get_value() { return value_.get(); }
const ExprData *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:
Expr value_;
std::vector<Case> cases_;
NodeId value;
std::vector<NodeId /*Case*/> cases;
};
class Condition : public Node {
public:
Condition(Node node, std::vector<std::pair<Expr, Expr>> &&cases,
std::optional<Expr> else_case = std::nullopt)
: Node(node), cases_(std::move(cases)), else_case_(else_case) {}
Condition(Node node, const std::vector<std::pair<Expr, Expr>> &cases,
std::optional<Expr> else_case = std::nullopt)
: Node(node), cases_(cases), else_case_(else_case) {}
size_t cases_size() const { return cases_.size(); }
std::pair<ExprData *, ExprData *> get_case(size_t id) {
return {cases_.at(id).first.get(), cases_[id].second.get()};
}
std::pair<const ExprData *, const ExprData *> get_case(size_t id) const {
return {cases_.at(id).first.get(), cases_[id].second.get()};
}
std::optional<ExprData *> get_else_case() {
return utils::proxy_to_expr_optional(else_case_);
}
std::optional<const ExprData *> get_else_case() const {
return utils::proxy_to_expr_optional(else_case_);
}
private:
std::vector<std::pair<Expr, Expr>> cases_;
std::optional<Expr> else_case_;
struct Condition {
std::vector<std::pair<NodeId, NodeId>> cases;
std::optional<NodeId> else_case;
};
class Loop : public TypedNode {
// TODO: prittier constructors
struct Loop {
public:
enum LoopType {
enum Kind {
LOOP,
WHILE,
FOR,
};
//
// LOOP
Loop(Node node, Expr expression)
: TypedNode(node), loop_type_(LOOP), expression_(expression) {}
Loop(NodeId expr) : kind(LOOP), expr(expr) {}
// WHILE
Loop(Node node, Expr condition, Expr expression)
: TypedNode(node), loop_type_(WHILE), expression_(expression),
condition_(condition) {}
Loop(NodeId condition, NodeId expr)
: kind(WHILE), expr(expr), condition(condition) {}
// FOR
Loop(Node node, Expr variable, Expr interval, Expr expression)
: TypedNode(node), loop_type_(FOR), expression_(expression),
variable_(variable), interval_(interval) {}
Loop(NodeId variable, NodeId interval, NodeId expr)
: kind(FOR), expr(expr), variable(variable), interval(interval) {}
LoopType get_type() const { return loop_type_; }
//
ExprData *get_expression() { return expression_.get(); }
Kind kind;
NodeId expr;
const ExprData *get_expression() const { return expression_.get(); }
std::optional<ExprData *> get_condition() {
return utils::proxy_to_expr_optional(condition_);
}
std::optional<const ExprData *> get_condition() const {
return utils::proxy_to_expr_optional(condition_);
}
std::optional<ExprData *> get_variable() {
return utils::proxy_to_expr_optional(variable_);
}
std::optional<const ExprData *> get_variable() const {
return utils::proxy_to_expr_optional(variable_);
}
std::optional<ExprData *> get_interval() {
return utils::proxy_to_expr_optional(interval_);
}
std::optional<const ExprData *> get_interval() const {
return utils::proxy_to_expr_optional(interval_);
}
private:
LoopType loop_type_;
Expr expression_;
std::optional<Expr> condition_;
std::optional<Expr> variable_;
std::optional<Expr> interval_;
std::optional<NodeId> condition;
std::optional<NodeId> variable;
std::optional<NodeId> interval;
};
// --- containers
class Container : public TypedNode {
public:
enum ContainerType {
struct Container {
enum Kind {
BLOCK,
ARRAY,
};
Container(Node node, ContainerType type, std::vector<Expr> &&expressions)
: TypedNode(node), container_type_(type),
expressions_(std::move(expressions)) {}
//
Container(Node node, ContainerType type, const std::vector<Expr> &expressions)
: TypedNode(node), container_type_(type), expressions_(expressions) {}
ContainerType get_type() const { return container_type_; }
size_t expressions_size() const { return expressions_.size(); }
ExprData *get_expression(size_t id) { return expressions_.at(id).get(); }
const ExprData *get_expression(size_t id) const {
return expressions_.at(id).get();
}
private:
ContainerType container_type_;
std::vector<Expr> expressions_;
Kind kind;
std::vector<NodeId> exprs;
};
// --- modifiers
class Return : public Node {
public:
enum ReturnType {
struct Return {
enum Kind {
RETURN,
BRING,
};
Return(Node node, ReturnType type, Expr expression)
: Node(node), return_type_(type), expression_(expression) {}
//
ReturnType get_type() const { return return_type_; }
ExprData *get_expression() { return expression_.get(); }
const ExprData *get_expression() const { return expression_.get(); }
private:
ReturnType return_type_;
Expr expression_;
Kind kind;
NodeId expr;
};
class NameDefinition : public TypedNode {
public:
enum Modifier {
struct NameDefinition {
enum Kind {
LET, // %
VAR, // $
};
NameDefinition(Node node, Modifier modifier, Identifier &&name)
: TypedNode(node), modifier_(modifier), name_(std::move(name)) {}
//
NameDefinition(Node node, Modifier modifier, const Identifier &name)
: TypedNode(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_;
Kind kind;
Identifier name;
};
class Access : public TypedNode {
public:
enum AccessType {
struct Access {
enum Kind {
ARRAY,
TUPLE, // only number literal index allowed
};
Access(Node node, AccessType type, Expr value, Expr index)
: TypedNode(node), access_type_(type), value_(value), index_(index) {}
//
AccessType get_type() const { return access_type_; }
Kind kind;
ExprData *get_value() { return value_.get(); }
const ExprData *get_value() const { return value_.get(); }
ExprData *get_index() { return index_.get(); }
const ExprData *get_index() const { return index_.get(); }
private:
AccessType access_type_;
Expr value_;
Expr index_;
NodeId value;
NodeId index;
};
class LoopControl : public TypedNode {
public:
enum LoopControlType {
struct LoopControl {
enum Kind {
BREAK,
CONTINUE,
};
LoopControl(Node node, LoopControlType type)
: TypedNode(node), loop_control_type_(type) {}
//
LoopControlType get_type() const { return loop_control_type_; }
private:
LoopControlType loop_control_type_;
Kind kind;
};
class ModifierExpression : public TypedNode {
public:
ModifierExpression(Node node, Modifier modifier, Expr expression)
: TypedNode(node), modifier_(modifier), expression_(expression) {}
Modifier get_modifier() const { return modifier_; }
ExprData *get_expression() { return expression_.get(); }
const ExprData *get_expression() const { return expression_.get(); }
private:
Modifier modifier_;
Expr expression_;
struct ModifierExpression {
Modifier modifier;
NodeId expr;
};
// --- other
using AnnotatedArgument = std::pair<std::optional<std::string>, Expr>;
using AnnotatedArgument = std::pair<std::optional<std::string>, NodeId>;
class NameExpression : public TypedNode {
public:
NameExpression(Node node, Identifier &&name)
: TypedNode(node), name_(std::move(name)) {}
NameExpression(Node node, const Identifier &name)
: TypedNode(node), name_(name) {}
NameExpression(Node node, Identifier &&name,
std::vector<AnnotatedArgument> &&args,
std::optional<Type> &&prefix, bool is_point_call = false,
bool is_operator_call = false)
: TypedNode(node), name_(std::move(name)), args_(std::move(args)),
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<TypeData *> get_prefix() {
if (prefix_.has_value()) {
return prefix_.value().get();
}
return std::nullopt;
}
std::optional<const TypeData *> get_prefix() const {
if (prefix_.has_value()) {
return prefix_.value().get();
}
return std::nullopt;
}
size_t args_size() const { return args_.size(); }
ExprData *get_argument_value(size_t id) { return args_.at(id).second.get(); }
const ExprData *get_argument_value(size_t id) const {
return args_.at(id).second.get();
}
std::optional<std::string *> get_argument_annotation(size_t id) {
if (args_.at(id).first.has_value()) {
return &args_[id].first.value();
}
return std::nullopt;
}
std::optional<const std::string *> get_argument_annotation(size_t id) const {
if (args_.at(id).first.has_value()) {
return &args_[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_;
struct NameExpression {
Identifier name;
// universal function call syntax
std::vector<AnnotatedArgument> args_;
std::optional<Type> prefix_;
std::vector<AnnotatedArgument> args = {};
std::optional<Type> prefix = {};
// for static methods
bool is_point_call_ = false; // x.f ... or f x ...
bool is_operator_call_ = false; // ... operator ...
bool is_point_call = false; // x.f ... or f x ...
bool is_operator_call = false; // ... operator ...
};
class Constructor : public TypedNode {
public:
Constructor(Node node, Type type, std::vector<AnnotatedArgument> &&args)
: TypedNode(node), constructor_type_(type), args_(std::move(args)) {}
Constructor(Node node, Type type, const std::vector<AnnotatedArgument> &args)
: TypedNode(node), constructor_type_(type), args_(args) {}
TypeData *get_type() { return constructor_type_.get(); }
const TypeData *get_type() const { return constructor_type_.get(); }
Type get_type_proxy() const { return constructor_type_; }
size_t args_size() const { return args_.size(); }
ExprData *get_argument_value(size_t id) { return args_.at(id).second.get(); }
const ExprData *get_argument_value(size_t id) const {
return args_.at(id).second.get();
}
std::optional<std::string *> get_argument_annotation(size_t id) {
if (args_.at(id).first.has_value()) {
return &args_[id].first.value();
}
return std::nullopt;
}
std::optional<const std::string *> get_argument_annotation(size_t id) const {
if (args_.at(id).first.has_value()) {
return &args_[id].first.value();
}
return std::nullopt;
}
private:
Type constructor_type_;
std::vector<std::pair<std::optional<std::string>, Expr>> args_;
struct Constructor {
Type type;
std::vector<AnnotatedArgument> args;
};
class Lambda : public TypedNode {
public:
Lambda(Node node, std::vector<Identifier> &&args, Expr expression)
: TypedNode(node), args_(std::move(args)), expression_(expression) {}
Lambda(Node node, const std::vector<Identifier> &args, Expr expression)
: TypedNode(node), args_(args), expression_(expression) {}
size_t args_size() const { return args_.size(); }
Identifier *get_argument(size_t id) { return &args_.at(id); }
const Identifier *get_argument(size_t id) const { return &args_.at(id); }
ExprData *get_expression() { return expression_.get(); }
const ExprData *get_expression() const { return expression_.get(); }
private:
std::vector<Identifier> args_;
Expr expression_;
struct Lambda {
std::vector<Identifier> args;
NodeId expr;
};
class ExprData : public Node {
class ExprData {
public:
using Type = std::variant<
// --- flow control
@ -542,9 +229,8 @@ public:
public:
template <typename T>
ExprData(Node node, T &&expression, bool is_scoped)
: Node(node), expression_(std::forward<T>(expression)),
is_scoped_(is_scoped) {}
ExprData(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_)) {
@ -572,22 +258,22 @@ private:
bool is_scoped_ = false;
};
class ExprStorage {
friend Expr;
// class ExprStorage {
// friend Expr;
public:
Expr add_expr(ExprData expression) {
storage_.push_back(std::move(expression));
return Expr(*this, storage_.size() - 1);
}
// public:
// Expr add_expr(ExprData expression) {
// storage_.push_back(std::move(expression));
// return Expr(*this, storage_.size() - 1);
// }
private:
ExprData *get_expr(size_t id) { return &storage_.at(id); }
// private:
// ExprData *get_expr(size_t id) { return &storage_.at(id); }
const ExprData *get_expr(size_t id) const { return &storage_.at(id); }
// const ExprData *get_expr(size_t id) const { return &storage_.at(id); }
private:
std::vector<ExprData> storage_;
};
// private:
// std::vector<ExprData> storage_;
// };
} // namespace nodes

View file

@ -1,15 +1,38 @@
#pragma once
#include "expression_nodes.hpp"
#include "storage.hpp"
namespace nodes {
// FIXME
struct NodeData {
std::variant<int, bool> value;
}; // TODO: union with nodes
template <typename... Mixins> class Node_;
struct NodeData {
public:
template <typename T> NodeData(T value) : value(std::move(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;
}
template <typename T> bool Holds() const {
return std::holds_alternative<T>(value);
}
public:
nodes::ExprData::Type value;
};
// TODO: replace NodeData with real node
class NodeStorage : public core::Storage<NodeData> {
using Id = storage::Id;
@ -36,7 +59,7 @@ protected:
core::DependentStorage<T> &data_;
};
// TODO: replace all nodes
// FIXME: rename
// Mixins should be NodePart<...> or their children
template <typename... Mixins> class Node_ : public Mixins... {
using Id = storage::Id;
@ -45,9 +68,13 @@ public:
Node_(Id id, NodeStorage &data, Mixins &&...mixins)
: Mixins(std::move(mixins))..., id_(id), data_(data) {}
operator Id() const { return id(); }
//
template <typename T> bool &Has() { return NodePart<T>::data_.Has(id_); }
template <typename T> bool &Has() const {
return NodePart<T>::data_.Has(id_);
}
//
@ -55,6 +82,12 @@ public:
template <typename T> T &get() { return std::get<T>(data_[id_].value); }
Id id() const { return id_; }
template <typename T> bool Holds() const {
return operator*().template Holds<T>();
}
//
const NodeData &operator*() const { return data_[id_]; }

View file

@ -27,54 +27,17 @@ enum class CombineResult {
};
// 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_;
struct Import {
Identifier import_name;
Identifier module_name;
std::vector<Identifier> symbols;
};
class Constraint : public Node {
public:
Constraint(Node node, Expr expression)
: Node(node), expression_(expression) {}
ExprData *get_expression() { return expression_.get(); }
const ExprData *get_expression() const { return expression_.get(); }
private:
Expr expression_;
struct Constraint {
NodeId expr;
};
class FunctionDefinition : public Node {
public:
struct FunctionDefinition {
class Argument {
public:
Argument(const std::optional<std::string> &annotation, Identifier &&name,
@ -242,151 +205,43 @@ public:
Modifier::NONE; // optional, result, none // sync with type
};
FunctionDefinition(Node node, SymbolDocs &&docs,
std::vector<Constraint> &&constraints,
FunctionDefinition(SymbolDocs &&docs, std::vector<Constraint> &&constraints,
Modifier return_modifier, bool is_method,
const std::optional<Identifier> &name_prefix,
const Identifier &name, std::vector<Argument> &&args,
bool are_annotations_same_to_names,
std::optional<Expr> expression)
: Node(node), docs_(std::move(docs)),
constraints_(std::move(constraints)), return_modifier_(return_modifier),
is_method_(is_method), name_(name), full_name_(name),
args_(std::move(args)),
are_annotations_same_to_names_(are_annotations_same_to_names),
expression_(expression) {
std::optional<NodeId> expr)
: docs(std::move(docs)), constraints(std::move(constraints)),
return_modifier(return_modifier), is_method(is_method), name(name),
full_name(name), args(std::move(args)),
are_annotations_same_to_names(are_annotations_same_to_names),
expr(expr) {
if (name_prefix.has_value()) {
full_name_.append_before(*name_prefix.value().get());
full_name.append_before(name_prefix.value().value);
}
}
//
SymbolDocs *get_docs() { return &docs_; }
const SymbolDocs *get_docs() const { return &docs_; }
//
size_t 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 args_size() const { return args_.size(); }
Argument *get_argument(size_t id) { return &args_.at(id); }
const Argument *get_argument(size_t id) const { return &args_.at(id); }
//
std::optional<ExprData *> get_expression() {
if (expression_.has_value()) {
return expression_.value().get();
}
return std::nullopt;
}
std::optional<const ExprData *> 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) const;
CombineResult combine(FunctionDefinition &&other);
private:
SymbolDocs docs_;
std::vector<Constraint> constraints_;
Modifier return_modifier_;
bool is_method_;
Identifier name_;
Identifier full_name_;
std::vector<Argument> args_;
bool are_annotations_same_to_names_; // needed for easier prinitng process
std::optional<Expr> expression_;
//
SymbolDocs docs;
std::vector<Constraint> constraints;
Modifier return_modifier;
bool is_method;
Identifier name;
Identifier full_name;
std::vector<Argument> args;
bool are_annotations_same_to_names; // needed for easier prinitng process
std::optional<NodeId> expr;
}; // 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> &&args, std::optional<Type> type)
: Node(node), docs_(std::move(docs)), is_on_heap_(is_on_heap),
name_(name), typeclasses_(typeclasses), args_(std::move(args)),
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 args_size() const { return args_.size(); }
Identifier *get_argument(size_t id) { return &args_.at(id); }
const Identifier *get_argument(size_t id) const { return &args_.at(id); }
//
std::optional<Type> get_type() const {
if (type_.has_value()) {
return type_.value();
}
return std::nullopt;
}
//
bool is_typeclass() { return name_.get_type() == Identifier::TYPECLASS; }
struct TypeDefinition {
bool is_typeclass() { return name.kind == Identifier::kTypeclass; }
//
@ -394,53 +249,44 @@ public:
CombineResult combine(TypeDefinition &&other);
private:
SymbolDocs docs_;
bool is_on_heap_;
Identifier name_;
std::vector<Identifier> typeclasses_;
std::vector<Identifier> args_;
std::optional<Type> type_;
//
SymbolDocs docs;
bool is_on_heap;
Identifier name;
std::vector<Identifier> typeclasses;
std::vector<Identifier> args;
std::optional<Type> type;
};
class Statement : public Node {
struct Statement {
public:
using Type = std::variant<Import, TypeDefinition, FunctionDefinition, Extra,
EmptyLines>;
// Statement(const Statement &) = default;
// Statement(Statement &&) = default;
// Statement &operator=(const Statement &) = default;
// Statement &operator=(Statement &&) = default;
template <typename T>
Statement(Node node, T &&statement)
: Node(node), expr_(std::forward<T>(statement)) {}
//
template <typename T> std::optional<T *> get() {
if (std::holds_alternative<T>(expr_)) {
return &std::get<T>(expr_);
if (std::holds_alternative<T>(expr)) {
return &std::get<T>(expr);
}
return std::nullopt;
}
template <typename T> std::optional<const T *> get() const {
if (std::holds_alternative<T>(expr_)) {
return &std::get<T>(expr_);
if (std::holds_alternative<T>(expr)) {
return &std::get<T>(expr);
}
return std::nullopt;
}
Type &get_any() { return expr_; }
const Type &get_any() const { return expr_; }
bool is_same_to(const Statement &other) const;
CombineResult combine(Statement &&other);
private:
Type expr_;
//
Type expr;
};
} // namespace nodes

View file

@ -167,7 +167,7 @@ public:
//
bool is_generic() { return name_.get_type() == Identifier::GENERIC_TYPE; }
bool is_generic() { return name_.kind == Identifier::kGenericType; }
//
@ -192,7 +192,7 @@ public:
bool operator<(const TypeData &other) const {
if (name_ != other.name_) {
return *name_.get() < *other.name_.get();
return name_.value < other.name_.value;
}
if (modifier_ != other.modifier_) {
@ -220,7 +220,7 @@ public:
// is parameters count check necessary ??
builtin::Type to_builtin() const {
auto builtin_type = builtin::types::to_type(*name_.get());
auto builtin_type = builtin::types::to_type(name_.value);
auto builtin_type_parameters_count =
builtin::types::get_parameters_count(builtin_type);
@ -249,12 +249,12 @@ class TypeStorage {
public:
Type primitive(builtin::Type type);
Type add_array_of(Type type, Node node = Node());
Type add_array_of(Type type);
Type add_error_of(Type type, Node node = Node());
Type add_error_of(Type type);
nodes::Type add_container_of(std::vector<Type> &&parameters,
builtin::Type container, Node node = Node());
builtin::Type container);
nodes::Type add_modification_of(Type type, Modifier modifier);

View file

@ -1,9 +1,3 @@
#include "expression_nodes.hpp"
namespace nodes {
ExprData *Expr::get() { return expression_storage_->get_expr(id_); }
const ExprData *Expr::get() const { return expression_storage_->get_expr(id_); }
}; // namespace nodes
namespace nodes {}; // namespace nodes

View file

@ -1,5 +1,6 @@
#include "statement_nodes.hpp"
// #include "error_handling.hpp"
#include "error_handling.hpp"
#include "utils.hpp"
#include <algorithm>
@ -7,7 +8,7 @@
namespace nodes {
bool FunctionDefinition::is_same_to(const FunctionDefinition &other) const {
if (name_ != other.name_) {
if (name != other.name) {
return false;
}
return true;
@ -21,96 +22,95 @@ bool FunctionDefinition::is_same_to(const FunctionDefinition &other) const {
// name 'arg1 'arg2 -> 'arg3 = ... // function definition (without types)
CombineResult FunctionDefinition::combine(FunctionDefinition &&other) {
// names should be the same
if (name_ != other.name_) {
if (name != other.name) {
return CombineResult::DIFFERENT_NAME_ERROR;
}
// modifiers should be the same
if (return_modifier_ != other.return_modifier_) {
if (return_modifier != other.return_modifier) {
return CombineResult::DIFFERNENT_MODIFIER_ERROR;
}
if (is_method_ != other.is_method_) {
if (is_method != other.is_method) {
return CombineResult::DIFFERNENT_MODIFIER_ERROR; // other error type ??
}
if (are_annotations_same_to_names_ != other.are_annotations_same_to_names_) {
if (are_annotations_same_to_names != other.are_annotations_same_to_names) {
return CombineResult::ARGUMENTS_ERROR;
}
// only one definition should have constraints
if (!constraints_.empty() && !other.constraints_.empty()) {
if (!constraints.empty() && !other.constraints.empty()) {
return CombineResult::MORE_THEN_ONE_CONSTRAINTS_ERROR;
}
// only one definition should have expression (body)
if (expression_.has_value() && other.expression_.has_value()) {
if (expr.has_value() && other.expr.has_value()) {
return CombineResult::MORE_THEN_ONE_DEFINITION_BODY_ERROR;
}
// only one definition should have documentation
if (docs_.get_description().has_value() &&
other.docs_.get_description().has_value()) {
if (docs.get_description().has_value() &&
other.docs.get_description().has_value()) {
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
}
if (docs_.annotations_info_size() > 0 &&
other.docs_.annotations_info_size() > 0) {
if (docs.annotations_info_size() > 0 &&
other.docs.annotations_info_size() > 0) {
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
}
// check, that function definitions have same named args
for (size_t i = 0; i < std::max(args_.size(), other.args_.size()); ++i) {
if (i < args_.size() && i < other.args_.size()) {
for (size_t i = 0; i < std::max(args.size(), other.args.size()); ++i) {
if (i < args.size() && i < other.args.size()) {
// annotations should be the same
if ((!args_[i].get_annotation().has_value() &&
!other.args_[i].get_annotation().has_value()) ||
(args_[i].get_annotation().has_value() &&
other.args_[i].get_annotation().has_value() &&
*args_[i].get_annotation().value() !=
*other.args_[i].get_annotation().value())) {
if ((!args[i].get_annotation().has_value() &&
!other.args[i].get_annotation().has_value()) ||
(args[i].get_annotation().has_value() &&
other.args[i].get_annotation().has_value() &&
*args[i].get_annotation().value() !=
*other.args[i].get_annotation().value())) {
return CombineResult::ARGUMENTS_ERROR;
}
// argument names should be the same
if ((!args_[i].get_name().has_value() &&
!other.args_[i].get_name().has_value()) ||
(args_[i].get_name().has_value() &&
other.args_[i].get_name().has_value() &&
args_[i].get_name().value() != other.args_[i].get_name().value())) {
if ((!args[i].get_name().has_value() &&
!other.args[i].get_name().has_value()) ||
(args[i].get_name().has_value() &&
other.args[i].get_name().has_value() &&
args[i].get_name().value() != other.args[i].get_name().value())) {
return CombineResult::ARGUMENTS_ERROR;
}
// types should be the same (if present in both definitions)
if (args_[i].get_type().has_value() &&
other.args_[i].get_type().has_value() &&
*args_[i].get_type().value() != *other.args_[i].get_type().value()) {
if (args[i].get_type().has_value() &&
other.args[i].get_type().has_value() &&
*args[i].get_type().value() != *other.args[i].get_type().value()) {
return CombineResult::ARGUMENTS_ERROR;
}
// argument modifiers should be the same
if (args_[i].get_before_modifier() !=
other.args_[i].get_before_modifier() ||
args_[i].get_after_modifier() !=
other.args_[i].get_after_modifier()) {
if (args[i].get_before_modifier() !=
other.args[i].get_before_modifier() ||
args[i].get_after_modifier() != other.args[i].get_after_modifier()) {
return CombineResult::ARGUMENTS_ERROR;
}
} else if (i < args_.size()) {
} else if (i < args.size()) {
// annotations should be the same
if (args_[i].get_annotation().has_value()) {
if (args[i].get_annotation().has_value()) {
return CombineResult::ARGUMENTS_ERROR;
}
// names should be the same
if (args_[i].get_name().has_value()) {
if (args[i].get_name().has_value()) {
return CombineResult::ARGUMENTS_ERROR;
}
} else { // i < other_function_definition.size()
// annotations should be the same
if (other.args_[i].get_annotation().has_value()) {
if (other.args[i].get_annotation().has_value()) {
return CombineResult::ARGUMENTS_ERROR;
}
// names should be the same
if (other.args_[i].get_name().has_value()) {
if (other.args[i].get_name().has_value()) {
return CombineResult::ARGUMENTS_ERROR;
}
}
@ -118,28 +118,28 @@ CombineResult FunctionDefinition::combine(FunctionDefinition &&other) {
// combine docs
// all docs should be in one definition
if (other.docs_.get_description().has_value() ||
other.docs_.annotations_info_size() > 0) {
if (docs_.annotations_info_size() > 0 ||
docs_.get_description().has_value()) {
if (other.docs.get_description().has_value() ||
other.docs.annotations_info_size() > 0) {
if (docs.annotations_info_size() > 0 ||
docs.get_description().has_value()) {
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
}
docs_ = std::move(other.docs_);
docs = std::move(other.docs);
}
if (!other.constraints_.empty()) {
constraints_ = std::move(other.constraints_);
if (!other.constraints.empty()) {
constraints = std::move(other.constraints);
}
if (other.expression_.has_value()) {
expression_ = other.expression_;
if (other.expr.has_value()) {
expr = other.expr;
}
for (size_t i = 0; i < other.args_.size(); ++i) {
if (i < args_.size()) {
if (other.args_[i].get_type().has_value()) {
if (args_[i].update_type_from(other.args_[i])) {
for (size_t i = 0; i < other.args.size(); ++i) {
if (i < args.size()) {
if (other.args[i].get_type().has_value()) {
if (args[i].update_type_from(other.args[i])) {
error_handling::handle_internal_error(
"Function arguments are not properly checked before merging "
"during combination",
@ -147,7 +147,7 @@ CombineResult FunctionDefinition::combine(FunctionDefinition &&other) {
}
}
} else {
args_.push_back(std::move(other.args_[i]));
args.push_back(std::move(other.args[i]));
}
}
@ -155,7 +155,7 @@ CombineResult FunctionDefinition::combine(FunctionDefinition &&other) {
}
bool TypeDefinition::is_same_to(const TypeDefinition &other) const {
if (name_ != other.name_) {
if (name != other.name) {
return false;
}
return true;
@ -167,83 +167,83 @@ bool TypeDefinition::is_same_to(const TypeDefinition &other) const {
// Type[...] 'A 'B 'C = ... // define type
CombineResult TypeDefinition::combine(TypeDefinition &&other) {
// name should be same
if (name_ != other.name_) {
if (name != other.name) {
return CombineResult::DIFFERENT_NAME_ERROR;
}
// modifier should be the same
if (is_on_heap_ != other.is_on_heap_) {
if (is_on_heap != other.is_on_heap) {
return CombineResult::DIFFERNENT_MODIFIER_ERROR;
}
// typeclasses should be the same
if (typeclasses_.size() != other.typeclasses_.size()) {
if (typeclasses.size() != other.typeclasses.size()) {
return CombineResult::ARGUMENTS_ERROR;
}
for (size_t i = 0; i < typeclasses_.size(); ++i) {
if (typeclasses_[i] != other.typeclasses_[i]) {
for (size_t i = 0; i < typeclasses.size(); ++i) {
if (typeclasses[i] != other.typeclasses[i]) {
return CombineResult::ARGUMENTS_ERROR;
}
}
// args should be the same
if (args_.size() != other.args_.size()) {
if (args.size() != other.args.size()) {
return CombineResult::ARGUMENTS_ERROR;
}
for (size_t i = 0; i < args_.size(); ++i) {
if (args_[i] != other.args_[i]) {
for (size_t i = 0; i < args.size(); ++i) {
if (args[i] != other.args[i]) {
return CombineResult::ARGUMENTS_ERROR;
}
}
// only one definition should have documentation
if (docs_.get_description().has_value() &&
other.docs_.get_description().has_value()) {
if (docs.get_description().has_value() &&
other.docs.get_description().has_value()) {
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
}
if (docs_.annotations_info_size() > 0 &&
other.docs_.annotations_info_size() > 0) {
if (docs.annotations_info_size() > 0 &&
other.docs.annotations_info_size() > 0) {
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
}
// only one type should define type / body
if (type_.has_value() && other.type_.has_value()) {
if (type.has_value() && other.type.has_value()) {
return CombineResult::MORE_THEN_ONE_DEFINITION_BODY_ERROR;
}
// combine docs
// all docs should be in one definition
if (other.docs_.get_description().has_value() ||
other.docs_.annotations_info_size() > 0) {
if (docs_.annotations_info_size() > 0 ||
docs_.get_description().has_value()) {
if (other.docs.get_description().has_value() ||
other.docs.annotations_info_size() > 0) {
if (docs.annotations_info_size() > 0 ||
docs.get_description().has_value()) {
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
}
docs_ = std::move(other.docs_);
docs = std::move(other.docs);
}
if (other.type_.has_value()) {
type_ = std::move(other.type_);
if (other.type.has_value()) {
type = std::move(other.type);
}
return CombineResult::OK;
}
bool Statement::is_same_to(const Statement &other) const {
if (expr_.index() != other.expr_.index()) {
if (expr.index() != other.expr.index()) {
return false;
}
switch (expr_.index()) {
switch (expr.index()) {
case 0: // Import
return false;
case 1: // TypeDefinition
return std::get<TypeDefinition>(expr_).is_same_to(
std::move(std::get<TypeDefinition>(other.expr_)));
return std::get<TypeDefinition>(expr).is_same_to(
std::move(std::get<TypeDefinition>(other.expr)));
case 2: // FunctionDefinition
return std::get<FunctionDefinition>(expr_).is_same_to(
std::move(std::get<FunctionDefinition>(other.expr_)));
return std::get<FunctionDefinition>(expr).is_same_to(
std::move(std::get<FunctionDefinition>(other.expr)));
case 3: // Extra
return false;
case 4: // EmptyLines
@ -259,19 +259,19 @@ bool Statement::is_same_to(const Statement &other) const {
}
CombineResult Statement::combine(Statement &&other) {
if (expr_.index() != other.expr_.index()) {
if (expr.index() != other.expr.index()) {
return CombineResult::DIFFERENT_STATEMENT_TYPES;
}
switch (expr_.index()) {
switch (expr.index()) {
case 0: // Import
return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR;
case 1: // TypeDefinition
return std::get<TypeDefinition>(expr_).combine(
std::move(std::get<TypeDefinition>(other.expr_)));
return std::get<TypeDefinition>(expr).combine(
std::move(std::get<TypeDefinition>(other.expr)));
case 2: // FunctionDefinition
return std::get<FunctionDefinition>(expr_).combine(
std::move(std::get<FunctionDefinition>(other.expr_)));
return std::get<FunctionDefinition>(expr).combine(
std::move(std::get<FunctionDefinition>(other.expr)));
case 3: // Extra
return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR;
case 4: // EmptyLines

View file

@ -1,5 +1,7 @@
#include "type_nodes.hpp"
// TODO: replace error system
namespace nodes {
TypeData *Type::get() { return type_storage_->get_type(id_); }
@ -18,12 +20,14 @@ Type TypeStorage::primitive(builtin::Type type) {
return Type(*this, iter->second);
} else {
primitive_type_ids_[type] = storage_.size();
return add_type(TypeData(Identifier(Node(), Identifier::SIMPLE_TYPE,
builtin::types::to_string(type))));
return add_type(TypeData(Identifier{
.kind = Identifier::kSimpleType,
.value = builtin::types::to_string(type),
}));
}
}
Type TypeStorage::add_array_of(Type type, Node node) {
Type TypeStorage::add_array_of(Type type) {
if (type.type_storage_ != this) {
error_handling::handle_general_error(
"TypeStorage: Can't add array of type from another type "
@ -33,12 +37,15 @@ Type TypeStorage::add_array_of(Type type, Node node) {
std::vector<nodes::Type> parameters;
parameters.push_back(type);
return add_type(TypeData(Identifier(node, Identifier::SIMPLE_TYPE,
builtin::types::ARRAY_IDENTIFIER),
std::move(parameters)));
return add_type(TypeData(
Identifier{
.kind = Identifier::kSimpleType,
.value = builtin::types::ARRAY_IDENTIFIER,
},
std::move(parameters)));
}
Type TypeStorage::add_error_of(Type type, Node node) {
Type TypeStorage::add_error_of(Type type) {
if (type.type_storage_ != this) {
error_handling::handle_general_error(
"TypeStorage: Can't add error of type from another type "
@ -48,13 +55,16 @@ Type TypeStorage::add_error_of(Type type, Node node) {
std::vector<nodes::Type> parameters;
parameters.push_back(type);
return add_type(TypeData(Identifier(node, Identifier::SIMPLE_TYPE,
builtin::types::ERROR_IDENTIFIER),
std::move(parameters)));
return add_type(TypeData(
Identifier{
.kind = Identifier::kSimpleType,
.value = builtin::types::ERROR_IDENTIFIER,
},
std::move(parameters)));
}
nodes::Type TypeStorage::add_container_of(std::vector<Type> &&parameters,
builtin::Type container, Node node) {
builtin::Type container) {
for (auto &parameter : parameters) {
if (parameter.type_storage_ != this) {
error_handling::handle_general_error(
@ -64,10 +74,12 @@ nodes::Type TypeStorage::add_container_of(std::vector<Type> &&parameters,
}
}
return add_type(
nodes::TypeData(nodes::Identifier(node, nodes::Identifier::SIMPLE_TYPE,
builtin::types::to_string(container)),
std::move(parameters)));
return add_type(nodes::TypeData(
nodes::Identifier{
.kind = nodes::Identifier::kSimpleType,
.value = builtin::types::to_string(container),
},
std::move(parameters)));
}
nodes::Type TypeStorage::add_modification_of(Type type, Modifier modifier) {
@ -95,7 +107,7 @@ bool TypeStorage::resolve_all_generic_types() {
for (auto &type : storage_) {
if (type.is_generic()) {
auto iter = resolved_generic_names_.find(*type.get_name()->get());
auto iter = resolved_generic_names_.find(type.get_name()->value);
// because of undefined order some types can became resolved earlir
// wirking correctly because each generic type has <= 1 successor, no
@ -280,9 +292,10 @@ bool TypeStorage::resolve(
//
Identifier TypeStorage::generate_generic_type_identifier() {
Identifier identifier =
Identifier(Node(), Identifier::GENERIC_TYPE,
"G_" + std::to_string(last_generic_type_id_));
Identifier identifier = Identifier{
.kind = Identifier::kGenericType,
.value = "G_" + std::to_string(last_generic_type_id_),
};
++last_generic_type_id_;
return identifier;
}

View file

@ -33,7 +33,7 @@ void print(const nodes::ExprData &expression, printers::Printer &printer) {
void print(const nodes::Match::Case &expression, Printer &printer) {
switch (expression.case_type()) {
switch (expression.kind()) {
case nodes::Match::Case::PATTERN_VALUE:
printer.print(":=");
break;
@ -316,7 +316,7 @@ void print(const nodes::NameExpression &expression,
bool operator_called_as_function =
(!expression.is_operator_call() &&
expression.get_name()->get_type() == nodes::Identifier::OPERATOR);
expression.get_name()->get_type() == nodes::Identifier::kOperator);
if (operator_called_as_function) {
printer.print("( ");

View file

@ -18,15 +18,15 @@ class State {
public:
struct VariableInfo {
nodes::Type type;
nodes::NameDefinition::Modifier modifier;
nodes::NameDefinition::Kind modifier;
};
public:
State(Log &log) : log_(log) {}
bool insert_variable(const std::string &name, nodes::Type type,
nodes::NameDefinition::Modifier modifier) {
Log::Context logc(log_, utils::Log::Area::kTypeCheck);
nodes::NameDefinition::Kind modifier) {
Log::Context logc(log_, Log::Area::kTypeCheck);
if (contexts_.empty()) {
logc.Fatal<Log::kSys>(
@ -50,7 +50,7 @@ public:
}
bool bring_type(nodes::Type type) {
Log::Context logc(log_, utils::Log::Area::kTypeCheck);
Log::Context logc(log_, Log::Area::kTypeCheck);
if (contexts_.empty()) {
logc.Fatal<Log::kSys>(
@ -66,7 +66,7 @@ public:
}
bool return_type(nodes::Type type) {
Log::Context logc(log_, utils::Log::Area::kTypeCheck);
Log::Context logc(log_, Log::Area::kTypeCheck);
if (contexts_.empty()) {
logc.Fatal<Log::kSys>(
@ -83,7 +83,7 @@ public:
private:
void enter_context(const nodes::Node &node) {
Log::Context logc(log_, utils::Log::Area::kTypeCheck);
Log::Context logc(log_, Log::Area::kTypeCheck);
contexts_.emplace_back(node);
}
@ -92,7 +92,7 @@ private:
// returns brought type, return type is merged with next context or with
// brought type in last context
nodes::MaybeType exit_context() {
Log::Context logc(log_, utils::Log::Area::kTypeCheck);
Log::Context logc(log_, Log::Area::kTypeCheck);
if (contexts_.empty()) {
logc.Fatal<Log::kSys>(

View file

@ -849,7 +849,7 @@ Result CheckTask<nodes::Lambda>::operator()(const nodes::Lambda &expr,
if (!state<State>().insert_variable(
*expr.get_argument(i)->get(),
expected_type.get()->get_parameter_proxy(i),
nodes::NameDefinition::Modifier::LET)) {
nodes::NameDefinition::Kind::LET)) {
// TODO: which modifier ??
type_check_error("Variable is already defined in this context", expr,
executor);

View file

@ -11,7 +11,7 @@ nodes::Type check_same_to_pass_type_in_args(nodes::Type type, const Args &args,
Executor &executor,
const std::string &message,
bool handle_errors) {
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
if (not args.get_passed().has_value()) {
return type;
@ -27,7 +27,7 @@ nodes::Type check_same_to_pass_type_in_args(nodes::Type type, const Args &args,
bool check_no_pass_type_in_args(const Args &args, const nodes::Node &node,
Executor &executor, const std::string &message,
bool handle_errors) {
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
if (args.get_passed().has_value()) {
type_check_error(message, node, executor, handle_errors);
@ -40,7 +40,7 @@ bool check_no_pass_type_in_args(const Args &args, const nodes::Node &node,
Result type_same_to_expected(nodes::Type type, const Args &args,
const nodes::Node & /*node*/, Executor &executor,
const std::string &message, bool handle_errors) {
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
const auto &expected = args.get_expected();
@ -63,7 +63,7 @@ Result type_same_to_expected(nodes::Type type, const Args &args,
Result type_check_from_args(nodes::Type /*type*/, const Args & /*args*/,
const nodes::Node & /*node*/, Executor &executor,
bool /*handle_errors*/) {
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
/* TODO FIXME */
logc.Fatal<Log::kSys>({{"Not implemented yet"}});
@ -76,7 +76,7 @@ find_statement(const std::string &name, const nodes::Node & /*node*/,
Executor &executor, const std::string &message_not_found,
const std::string &message_different_statement,
bool handle_errors) {
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
const auto maybe_any_statement = executor.state<names::NameTree>().find(name);
if (not maybe_any_statement.has_value()) {
@ -100,7 +100,7 @@ find_statement(const std::string &name, const nodes::Node & /*node*/,
std::optional<const nodes::TypeDefinition *>
find_type_definition(const std::string &name, const nodes::Node &node,
Executor &executor, bool handle_errors) {
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return find_statement<nodes::TypeDefinition>(
name, node, executor, "No type definition found in name tree",
@ -110,7 +110,7 @@ find_type_definition(const std::string &name, const nodes::Node &node,
std::optional<const nodes::FunctionDefinition *>
find_name_definition(const std::string &name, const nodes::Node &node,
Executor &executor, bool handle_errors) {
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return find_statement<nodes::FunctionDefinition>(
name, node, executor, "No name definition found in name tree",
@ -121,7 +121,7 @@ std::optional<nodes::Type> unfold_user_defined_type(nodes::Type type,
const nodes::Node &node,
Executor &executor,
bool handle_errors) {
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
const auto maybe_type_definition = find_type_definition(
*type.get()->get_name()->get(), node, executor, handle_errors);
@ -151,7 +151,7 @@ std::optional<nodes::Type> get_field_type_by_name(nodes::Type type,
const nodes::Node &node,
Executor &executor,
bool handle_errors) {
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
switch (type.get()->to_builtin()) {
case builtin::Type::TUPLE: { // access field
@ -194,7 +194,7 @@ std::optional<nodes::Type> get_field_type_by_name(nodes::Type type,
// FIXME: replace with direct log calls
void type_check_error(const std::string &message, const nodes::Node &,
Executor &executor, bool handle_error) {
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
if (!handle_error) {
return;

View file

@ -2,6 +2,7 @@
#include <string>
#include "log.hpp"
#include "utils.hpp"
#include "tree_sitter/api.h"
@ -18,56 +19,46 @@ public:
: node_(node), source_(source) {}
std::string get_type() const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (get_type)");
}
utils::Assert(not is_null(),
"Null parsing node method called (get_type)");
return ts_node_type(node_);
}
std::pair<size_t, size_t> get_start_point() const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (get_start_point)");
}
utils::Pos::Point get_start_point() const {
utils::Assert(not is_null(),
"Null parsing node method called (get_start_point)");
TSPoint point = ts_node_start_point(node_);
return {point.row, point.column};
}
std::pair<size_t, size_t> get_end_point() const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (get_end_point)");
}
utils::Pos::Point get_end_point() const {
utils::Assert(not is_null(),
"Null parsing node method called (get_end_point)");
TSPoint point = ts_node_end_point(node_);
return {point.row, point.column};
}
utils::Pos get_pos() const { return {get_start_point(), get_end_point()}; }
std::string get_as_sexpression() const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (get_as_sexpression)");
}
utils::Assert(not is_null(),
"Null parsing node method called (get_as_sexpression)");
return ts_node_string(node_);
}
std::string get_value() const { // from source
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (get_value)");
}
utils::Assert(not is_null(),
"Null parsing node method called (get_value)");
size_t start = ts_node_start_byte(node_);
size_t end = ts_node_end_byte(node_);
return source_->substr(start, end - start);
}
size_t get_value_length() const { // from source
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (get_value_length)");
}
utils::Assert(not is_null(),
"Null parsing node method called (get_value_length)");
size_t start = ts_node_start_byte(node_);
size_t end = ts_node_end_byte(node_);
return end - start;
@ -76,106 +67,80 @@ public:
bool is_null() const { return ts_node_is_null(node_); }
bool is_named() const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (is_named)");
}
utils::Assert(not is_null(),
"Null parsing node method called (is_named)");
return ts_node_is_named(node_);
}
bool is_missing() const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (is_missing)");
}
utils::Assert(not is_null(),
"Null parsing node method called (is_missing)");
return ts_node_is_missing(node_);
}
bool is_extra() const { // comments, etc.
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (is_extra)");
}
utils::Assert(not is_null(),
"Null parsing node method called (is_extra)");
return ts_node_is_extra(node_);
}
bool has_error() const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (has_error)");
}
utils::Assert(not is_null(),
"Null parsing node method called (has_error)");
return ts_node_has_error(node_);
}
Node nth_child(size_t n) const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (nth_child)");
}
utils::Assert(not is_null(),
"Null parsing node method called (nth_child)");
return Node(ts_node_child(node_, n), source_);
}
size_t child_count() const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (child_count)");
}
utils::Assert(not is_null(),
"Null parsing node method called (child_count)");
return ts_node_child_count(node_);
}
Node nth_named_child(size_t n) const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (nth_named_child)");
}
utils::Assert(not is_null(),
"Null parsing node method called (nth_named_child)");
return Node(ts_node_named_child(node_, n), source_);
}
size_t named_child_count() const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (named_child_count)");
}
utils::Assert(not is_null(),
"Null parsing node method called (named_child_count)");
return ts_node_named_child_count(node_);
}
Node child_by_field_name(const std::string &name) const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (child_by_field_name)");
}
utils::Assert(not is_null(),
"Null parsing node method called (child_by_field_name)");
return Node(ts_node_child_by_field_name(node_, name.c_str(), name.size()),
source_);
}
Node previous_sibling() const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (previous_sibling)");
}
utils::Assert(not is_null(),
"Null parsing node method called (previous_sibling)");
return Node(ts_node_prev_sibling(node_), source_);
}
Node previous_named_sibling() const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (previous_named_sibling)");
}
utils::Assert(not is_null(),
"Null parsing node method called (previous_named_sibling)");
return Node(ts_node_prev_named_sibling(node_), source_);
}
Node next_sibling() const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (next_sibling)");
}
utils::Assert(not is_null(),
"Null parsing node method called (next_sibling)");
return Node(ts_node_next_sibling(node_), source_);
}
Node next_named_sibling() const {
if (is_null()) {
error_handling::handle_general_error(
"Null parsing node method called (next_named_sibling)");
}
utils::Assert(not is_null(),
"Null parsing node method called (next_named_sibling)");
return Node(ts_node_next_named_sibling(node_), source_);
}

View file

@ -63,6 +63,18 @@ namespace utils {
#else // GCC, Clang
__builtin_unreachable();
#endif
// ---
// // TODO
// template<typename U, typename V>
// inline std::optional<V> carry(std::optional<U> value, std::function<V(U&&)>
// const& f) {
// if (value.has_value()) {
// return f(std::move(value));
// }
// return std::nullopt;
// }
}
} // namespace utils