mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-05 22:48:43 +00:00
[PART] most of builders and nodes changed to use new system
This commit is contained in:
parent
8f96a818ff
commit
d02c3a637b
22 changed files with 1397 additions and 1536 deletions
|
|
@ -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_ = {};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_]; }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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> &¶meters,
|
||||
builtin::Type container, Node node = Node());
|
||||
builtin::Type container);
|
||||
|
||||
nodes::Type add_modification_of(Type type, Modifier modifier);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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> &¶meters,
|
||||
builtin::Type container, Node node) {
|
||||
builtin::Type container) {
|
||||
for (auto ¶meter : parameters) {
|
||||
if (parameter.type_storage_ != this) {
|
||||
error_handling::handle_general_error(
|
||||
|
|
@ -64,10 +74,12 @@ nodes::Type TypeStorage::add_container_of(std::vector<Type> &¶meters,
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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("( ");
|
||||
|
|
|
|||
|
|
@ -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>(
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue