mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-06 06:58:46 +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 {
|
class SourcesManager {
|
||||||
public:
|
public:
|
||||||
void AddFile(const std::string &filename) {
|
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;
|
std::ifstream in;
|
||||||
in.open(filename);
|
in.open(filename);
|
||||||
|
|
@ -64,6 +64,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
builders::Executor executor_ =
|
builders::Executor executor_ =
|
||||||
builders::Executor(utils::BuildPrintLog(std::cout), {}, {}, {}, {});
|
builders::Executor(utils::BuildPrintLog(std::cout), {}, {}, {}, {}, {});
|
||||||
std::vector<nodes::Statement> statements_ = {};
|
std::vector<nodes::Statement> statements_ = {};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,69 +1,260 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "basic_nodes.hpp"
|
#include "basic_nodes.hpp"
|
||||||
|
#include "builders_utils.hpp"
|
||||||
#include "tree_sitter_wrapper.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 {
|
namespace builders {
|
||||||
|
|
||||||
// returns Modifier::NONE for incorrecnt input
|
// 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
|
// --- 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
|
// nodes::Literal build_long_literal(parser::ParseTree::Node parser_node);
|
||||||
build_unicode_string_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
|
// --- 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
|
// 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
|
// --- 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
|
// --- 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
|
} // namespace builders
|
||||||
|
|
|
||||||
|
|
@ -7,26 +7,28 @@
|
||||||
namespace builders {
|
namespace builders {
|
||||||
|
|
||||||
// using Code = parser::ParseTree;
|
// using Code = parser::ParseTree;
|
||||||
using Exprs = nodes::ExprStorage;
|
using Exprs = nodes::NodeStorage; // nodes::ExprStorage;
|
||||||
using Types = nodes::TypeStorage;
|
using Types = nodes::TypeStorage;
|
||||||
using Names = names::NameTree;
|
using Names = names::NameTree;
|
||||||
|
using Positions = core::DependentStorage<utils::Pos>;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
|
|
||||||
std::optional<nodes::Identifier> last_defined_type_name;
|
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 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>
|
template <typename N>
|
||||||
using Task = utils::Task<Executor, N, Args, parser::ParseTree::Node>;
|
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);
|
static_assert(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename N> struct BuilderTaskBase : public Task<N> {
|
template <typename N> struct BuilderTaskUtils : public Task<N> {
|
||||||
using Task<N>::Task;
|
using Task<N>::Task;
|
||||||
|
|
||||||
template <typename OtherN, typename OtherTag = utils::None>
|
Node Ext(storage::Id id) const {
|
||||||
OtherN Run(const parser::ParseTree::Node &node, const Args &args = {}) {
|
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);
|
BuilderTask<OtherN, OtherTag> task(this->executor);
|
||||||
return task(node, args);
|
return task(node, args);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,66 +23,58 @@ namespace builders {
|
||||||
|
|
||||||
// --- flow control
|
// --- flow control
|
||||||
|
|
||||||
template <>
|
template <> struct BuilderTask<Node> : public ExprBuilderTaskBase<Node> {
|
||||||
struct BuilderTask<nodes::Expr> : public BuilderTaskBase<nodes::Expr> {
|
using ExprBuilderTaskBase<Node>::ExprBuilderTaskBase;
|
||||||
using BuilderTaskBase<nodes::Expr>::BuilderTaskBase;
|
|
||||||
|
|
||||||
nodes::Expr operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||||
const Args &args) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::Match::Case>
|
struct BuilderTask<nodes::Match::Case>
|
||||||
: public BuilderTaskBase<nodes::Match::Case> {
|
: public ExprBuilderTaskBase<nodes::Match::Case> {
|
||||||
using BuilderTaskBase<nodes::Match::Case>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::Match::Case>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
nodes::Match::Case operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||||
const Args &args) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::Match> : public BuilderTaskBase<nodes::Match> {
|
struct BuilderTask<nodes::Match> : public ExprBuilderTaskBase<nodes::Match> {
|
||||||
using BuilderTaskBase<nodes::Match>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::Match>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
nodes::Match operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||||
const Args &args) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::Condition>
|
struct BuilderTask<nodes::Condition>
|
||||||
: public BuilderTaskBase<nodes::Condition> {
|
: public ExprBuilderTaskBase<nodes::Condition> {
|
||||||
using BuilderTaskBase<nodes::Condition>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::Condition>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
nodes::Condition operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||||
const Args &args) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::Loop> : public BuilderTaskBase<nodes::Loop> {
|
struct BuilderTask<nodes::Loop> : public ExprBuilderTaskBase<nodes::Loop> {
|
||||||
using BuilderTaskBase<nodes::Loop>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::Loop>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
nodes::Loop operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||||
const Args &args) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- operators
|
// --- operators
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::NameExpression, utils::CommaTag>
|
struct BuilderTask<nodes::NameExpression, utils::CommaTag>
|
||||||
: public BuilderTaskBase<nodes::NameExpression> {
|
: public ExprBuilderTaskBase<nodes::NameExpression> {
|
||||||
using BuilderTaskBase<nodes::NameExpression>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::NameExpression>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
nodes::NameExpression operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||||
const Args &args) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::NameExpression, utils::OperatorTag>
|
struct BuilderTask<nodes::NameExpression, utils::OperatorTag>
|
||||||
: public BuilderTaskBase<nodes::NameExpression> {
|
: public ExprBuilderTaskBase<nodes::NameExpression> {
|
||||||
using BuilderTaskBase<nodes::NameExpression>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::NameExpression>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
nodes::NameExpression operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||||
const Args &args) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- continers
|
// --- continers
|
||||||
|
|
@ -91,97 +83,92 @@ template <typename T>
|
||||||
requires std::is_same_v<T, utils::BlockTag> or
|
requires std::is_same_v<T, utils::BlockTag> or
|
||||||
std::is_same_v<T, utils::ArrayTag>
|
std::is_same_v<T, utils::ArrayTag>
|
||||||
struct BuilderTask<nodes::Container, T>
|
struct BuilderTask<nodes::Container, T>
|
||||||
: public BuilderTaskBase<nodes::Container> {
|
: public ExprBuilderTaskBase<nodes::Container> {
|
||||||
using BuilderTaskBase<nodes::Container>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::Container>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
// '{' (expression ';')* '}'
|
// '{' (expression ';')* '}'
|
||||||
// or
|
// or
|
||||||
// '[[' expression+ ']]'
|
// '[[' expression+ ']]'
|
||||||
nodes::Container operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &) override {
|
||||||
const Args &) override {
|
const auto kind = std::is_same_v<T, utils::BlockTag>
|
||||||
const auto container_type = std::is_same_v<T, utils::BlockTag>
|
? nodes::Container::BLOCK
|
||||||
? nodes::Container::BLOCK
|
: nodes::Container::ARRAY;
|
||||||
: nodes::Container::ARRAY;
|
|
||||||
|
|
||||||
std::vector<nodes::Expr> expressions;
|
std::vector<nodes::NodeId> exprs;
|
||||||
|
|
||||||
auto current_node = parser_node.nth_named_child(0);
|
auto current_node = parser_node.nth_named_child(0);
|
||||||
|
|
||||||
while (!current_node.is_null()) {
|
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();
|
current_node = current_node.next_named_sibling();
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodes::Container(build_node(parser_node), container_type,
|
return state<Exprs>().Insert(nodes::Container{
|
||||||
std::move(expressions));
|
.kind = kind,
|
||||||
|
.exprs = std::move(exprs),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- modifiers
|
// --- modifiers
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::Return> : public BuilderTaskBase<nodes::Return> {
|
struct BuilderTask<nodes::Return> : public ExprBuilderTaskBase<nodes::Return> {
|
||||||
using BuilderTaskBase<nodes::Return>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::Return>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
nodes::Return operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||||
const Args &args) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::NameDefinition>
|
struct BuilderTask<nodes::NameDefinition>
|
||||||
: public BuilderTaskBase<nodes::NameDefinition> {
|
: public ExprBuilderTaskBase<nodes::NameDefinition> {
|
||||||
using BuilderTaskBase<nodes::NameDefinition>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::NameDefinition>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
nodes::NameDefinition operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||||
const Args &args) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::Access, utils::ArrayAccessTag>
|
struct BuilderTask<nodes::Access, utils::ArrayAccessTag>
|
||||||
: public BuilderTaskBase<nodes::Access> {
|
: public ExprBuilderTaskBase<nodes::Access> {
|
||||||
using BuilderTaskBase<nodes::Access>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::Access>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
nodes::Access operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||||
const Args &args) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::Access, utils::TupleAccessTag>
|
struct BuilderTask<nodes::Access, utils::TupleAccessTag>
|
||||||
: public BuilderTaskBase<nodes::Access> {
|
: public ExprBuilderTaskBase<nodes::Access> {
|
||||||
using BuilderTaskBase<nodes::Access>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::Access>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
nodes::Access operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||||
const Args &args) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::LoopControl>
|
struct BuilderTask<nodes::LoopControl>
|
||||||
: public BuilderTaskBase<nodes::LoopControl> {
|
: public ExprBuilderTaskBase<nodes::LoopControl> {
|
||||||
using BuilderTaskBase<nodes::LoopControl>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::LoopControl>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
nodes::LoopControl operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||||
const Args &args) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires std::is_same_v<T, utils::RefTag> or
|
requires std::is_same_v<T, utils::RefTag> or
|
||||||
std::is_same_v<T, utils::SuffixTag>
|
std::is_same_v<T, utils::SuffixTag>
|
||||||
struct BuilderTask<nodes::ModifierExpression, T>
|
struct BuilderTask<nodes::ModifierExpression, T>
|
||||||
: public BuilderTaskBase<nodes::ModifierExpression> {
|
: public ExprBuilderTaskBase<nodes::ModifierExpression> {
|
||||||
using BuilderTaskBase<nodes::ModifierExpression>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::ModifierExpression>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
// _reference_ expression
|
// _reference_ expression
|
||||||
// or
|
// or
|
||||||
// expression ('?' | '!')
|
// expression ('?' | '!')
|
||||||
nodes::ModifierExpression operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &) override {
|
||||||
const Args &) override {
|
|
||||||
const size_t modifier_pos =
|
const size_t modifier_pos =
|
||||||
std::is_same_v<T, utils::RefTag> ? 0 : parser_node.child_count() - 1;
|
std::is_same_v<T, utils::RefTag> ? 0 : parser_node.child_count() - 1;
|
||||||
|
|
||||||
return nodes::ModifierExpression(
|
return state<Exprs>().Insert(nodes::ModifierExpression{
|
||||||
build_node(parser_node),
|
.modifier = Run<nodes::Modifier>(parser_node.nth_child(modifier_pos)),
|
||||||
build_modifier(parser_node.nth_child(modifier_pos)),
|
.expr = Run<Node>(parser_node.nth_named_child(0)),
|
||||||
Run<nodes::Expr>(parser_node.nth_named_child(0)));
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -189,28 +176,25 @@ struct BuilderTask<nodes::ModifierExpression, T>
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::NameExpression, utils::FuncCallTag>
|
struct BuilderTask<nodes::NameExpression, utils::FuncCallTag>
|
||||||
: public BuilderTaskBase<nodes::NameExpression> {
|
: public ExprBuilderTaskBase<nodes::NameExpression> {
|
||||||
using BuilderTaskBase<nodes::NameExpression>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::NameExpression>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
nodes::NameExpression operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||||
const Args &args) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::Constructor>
|
struct BuilderTask<nodes::Constructor>
|
||||||
: public BuilderTaskBase<nodes::Constructor> {
|
: public ExprBuilderTaskBase<nodes::Constructor> {
|
||||||
using BuilderTaskBase<nodes::Constructor>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::Constructor>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
nodes::Constructor operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||||
const Args &args) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::Lambda> : public BuilderTaskBase<nodes::Lambda> {
|
struct BuilderTask<nodes::Lambda> : public ExprBuilderTaskBase<nodes::Lambda> {
|
||||||
using BuilderTaskBase<nodes::Lambda>::BuilderTaskBase;
|
using ExprBuilderTaskBase<nodes::Lambda>::ExprBuilderTaskBase;
|
||||||
|
|
||||||
nodes::Lambda operator()(const ParserNode &parser_node,
|
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||||
const Args &args) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace builders
|
} // namespace builders
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ namespace builders {
|
||||||
// translate them in required order
|
// translate them in required order
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::Statements>
|
struct BuilderTask<nodes::Statements>
|
||||||
: public BuilderTaskBase<nodes::Statements> {
|
: public StatementBuilderTaskBase<nodes::Statements> {
|
||||||
using BuilderTaskBase<nodes::Statements>::BuilderTaskBase;
|
using StatementBuilderTaskBase<nodes::Statements>::StatementBuilderTaskBase;
|
||||||
|
|
||||||
nodes::Statements operator()(const ParserNode &parser_node,
|
nodes::Statements operator()(const ParserNode &parser_node,
|
||||||
const Args &args) override;
|
const Args &args) override;
|
||||||
|
|
@ -26,16 +26,17 @@ struct BuilderTask<nodes::Statements>
|
||||||
// copy of statement inserted into name_tree
|
// copy of statement inserted into name_tree
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::Statement>
|
struct BuilderTask<nodes::Statement>
|
||||||
: public BuilderTaskBase<nodes::Statement> {
|
: public StatementBuilderTaskBase<nodes::Statement> {
|
||||||
using BuilderTaskBase<nodes::Statement>::BuilderTaskBase;
|
using StatementBuilderTaskBase<nodes::Statement>::StatementBuilderTaskBase;
|
||||||
|
|
||||||
nodes::Statement operator()(const ParserNode &parser_node,
|
nodes::Statement operator()(const ParserNode &parser_node,
|
||||||
const Args &args) override;
|
const Args &args) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::Import> : public BuilderTaskBase<nodes::Import> {
|
struct BuilderTask<nodes::Import>
|
||||||
using BuilderTaskBase<nodes::Import>::BuilderTaskBase;
|
: public StatementBuilderTaskBase<nodes::Import> {
|
||||||
|
using StatementBuilderTaskBase<nodes::Import>::StatementBuilderTaskBase;
|
||||||
|
|
||||||
nodes::Import operator()(const ParserNode &parser_node,
|
nodes::Import operator()(const ParserNode &parser_node,
|
||||||
const Args &args) override;
|
const Args &args) override;
|
||||||
|
|
@ -43,8 +44,8 @@ struct BuilderTask<nodes::Import> : public BuilderTaskBase<nodes::Import> {
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::Constraint>
|
struct BuilderTask<nodes::Constraint>
|
||||||
: public BuilderTaskBase<nodes::Constraint> {
|
: public StatementBuilderTaskBase<nodes::Constraint> {
|
||||||
using BuilderTaskBase<nodes::Constraint>::BuilderTaskBase;
|
using StatementBuilderTaskBase<nodes::Constraint>::StatementBuilderTaskBase;
|
||||||
|
|
||||||
nodes::Constraint operator()(const ParserNode &parser_node,
|
nodes::Constraint operator()(const ParserNode &parser_node,
|
||||||
const Args &args) override;
|
const Args &args) override;
|
||||||
|
|
@ -52,8 +53,9 @@ struct BuilderTask<nodes::Constraint>
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::TypeDefinition>
|
struct BuilderTask<nodes::TypeDefinition>
|
||||||
: public BuilderTaskBase<nodes::TypeDefinition> {
|
: public StatementBuilderTaskBase<nodes::TypeDefinition> {
|
||||||
using BuilderTaskBase<nodes::TypeDefinition>::BuilderTaskBase;
|
using StatementBuilderTaskBase<
|
||||||
|
nodes::TypeDefinition>::StatementBuilderTaskBase;
|
||||||
|
|
||||||
nodes::TypeDefinition operator()(const ParserNode &parser_node,
|
nodes::TypeDefinition operator()(const ParserNode &parser_node,
|
||||||
const Args &args) override;
|
const Args &args) override;
|
||||||
|
|
@ -61,8 +63,9 @@ struct BuilderTask<nodes::TypeDefinition>
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BuilderTask<nodes::FunctionDefinition>
|
struct BuilderTask<nodes::FunctionDefinition>
|
||||||
: public BuilderTaskBase<nodes::FunctionDefinition> {
|
: public StatementBuilderTaskBase<nodes::FunctionDefinition> {
|
||||||
using BuilderTaskBase<nodes::FunctionDefinition>::BuilderTaskBase;
|
using StatementBuilderTaskBase<
|
||||||
|
nodes::FunctionDefinition>::StatementBuilderTaskBase;
|
||||||
|
|
||||||
nodes::FunctionDefinition operator()(const ParserNode &parser_node,
|
nodes::FunctionDefinition operator()(const ParserNode &parser_node,
|
||||||
const Args &args) override;
|
const Args &args) override;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#include "basic_builders.hpp"
|
#include "basic_builders.hpp"
|
||||||
|
|
||||||
#include "basic_nodes.hpp"
|
#include "basic_nodes.hpp"
|
||||||
#include "error_handling.hpp"
|
|
||||||
#include "tokens.hpp"
|
#include "tokens.hpp"
|
||||||
#include "tree_sitter_wrapper.hpp"
|
#include "tree_sitter_wrapper.hpp"
|
||||||
|
|
||||||
|
|
@ -39,7 +38,11 @@ std::optional<char> to_escape_symbol(char ch) {
|
||||||
|
|
||||||
} // namespace utils
|
} // 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();
|
std::string modifier = parser_node.get_value();
|
||||||
|
|
||||||
if (modifier == "?") {
|
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
|
// --- 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();
|
std::string literal = parser_node.get_value();
|
||||||
return nodes::Literal(
|
return nodes::Literal{
|
||||||
build_node(parser_node),
|
.value =
|
||||||
std::stof(literal.substr(0, literal.size() - 1))); // remove 'f' suffix
|
std::stof(literal.substr(0, literal.size() - 1)) // remove 'f' suffix
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes::Literal build_double_literal(parser::ParseTree::Node parser_node) {
|
nodes::Literal
|
||||||
return nodes::Literal(build_node(parser_node),
|
BuilderTask<nodes::Literal, double>::operator()(const ParserNode &parser_node,
|
||||||
std::stod(parser_node.get_value()));
|
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();
|
std::string literal = parser_node.get_value();
|
||||||
return nodes::Literal(build_node(parser_node),
|
return nodes::Literal{.value = (int32_t)std::stoll(literal.substr(
|
||||||
(int32_t)std::stoll(literal.substr(
|
0, literal.size() - 1))}; // remove 'i' suffix
|
||||||
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();
|
std::string literal = parser_node.get_value();
|
||||||
return nodes::Literal(build_node(parser_node),
|
return nodes::Literal{.value = (int64_t)std::stoll(literal.substr(
|
||||||
(int64_t)std::stoll(literal.substr(
|
0, literal.size() - 1))}; // remove 'l' suffix
|
||||||
0, literal.size() - 1))); // remove 'l' suffix
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes::Literal build_index_literal(parser::ParseTree::Node parser_node) {
|
nodes::Literal
|
||||||
return nodes::Literal(build_node(parser_node),
|
BuilderTask<nodes::Literal, size_t>::operator()(const ParserNode &parser_node,
|
||||||
(size_t)std::stoull(parser_node.get_value()));
|
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();
|
std::string literal = parser_node.get_value();
|
||||||
|
|
||||||
// remove " from both sides ("string")
|
// remove " from both sides ("string")
|
||||||
|
|
@ -149,20 +167,25 @@ nodes::Literal build_string_literal(parser::ParseTree::Node parser_node) {
|
||||||
}
|
}
|
||||||
literal.resize(j);
|
literal.resize(j);
|
||||||
|
|
||||||
return nodes::Literal(build_node(parser_node), literal);
|
return nodes::Literal{.value = literal};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: decode escape characters, etc.
|
// TODO: decode escape characters, etc.
|
||||||
nodes::Literal
|
nodes::Literal BuilderTask<nodes::Literal, nodes::unicode_string>::operator()(
|
||||||
build_unicode_string_literal(parser::ParseTree::Node parser_node) {
|
const ParserNode &parser_node, const Args &) {
|
||||||
|
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||||
|
|
||||||
std::string literal = parser_node.get_value();
|
std::string literal = parser_node.get_value();
|
||||||
|
|
||||||
// remove " from both sides + 'u' ("string"u)
|
// remove " from both sides + 'u' ("string"u)
|
||||||
return nodes::Literal(build_node(parser_node),
|
return nodes::Literal{.value = literal.substr(1, literal.size() - 3)};
|
||||||
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();
|
std::string literal = parser_node.get_value();
|
||||||
|
|
||||||
// remove '' from both sides (''x'')
|
// remove '' from both sides (''x'')
|
||||||
|
|
@ -182,108 +205,156 @@ nodes::Literal build_char_literal(parser::ParseTree::Node parser_node) {
|
||||||
ch = literal.back();
|
ch = literal.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodes::Literal(build_node(parser_node), ch);
|
return nodes::Literal{ch};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: decode escape characters, etc.
|
// 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();
|
std::string literal = parser_node.get_value();
|
||||||
|
|
||||||
// remove '' from both sides + 'u' (''x''u)
|
// remove '' from both sides + 'u' (''x''u)
|
||||||
return nodes::Literal(build_node(parser_node),
|
return nodes::Literal{
|
||||||
nodes::unicode{literal.substr(2, literal.size() - 5)});
|
.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();
|
std::string literal = parser_node.get_value();
|
||||||
|
|
||||||
return nodes::Literal(build_node(parser_node),
|
return nodes::Literal{literal == "true" ? true : false};
|
||||||
literal == "true" ? true : false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes::Literal build_unit_literal(parser::ParseTree::Node parser_node) {
|
nodes::Literal
|
||||||
return nodes::Literal(build_node(parser_node), nodes::unit{});
|
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) {
|
nodes::Literal
|
||||||
return nodes::Literal(build_node(parser_node), nodes::null{});
|
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
|
// --- 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());
|
tokens::Type type = tokens::string_to_type(parser_node.get_type());
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case tokens::Type::PLACEHOLDER:
|
case tokens::Type::PLACEHOLDER:
|
||||||
return build_placeholder(parser_node);
|
return Run<nodes::Identifier, ::utils::PlaceholderIdTag>(parser_node);
|
||||||
case tokens::Type::SIMPLE_NAME_IDENTIFIER:
|
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:
|
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:
|
case tokens::Type::TYPECLASS_IDENTIFIER:
|
||||||
return build_typeclass(parser_node);
|
return Run<nodes::Identifier, ::utils::TypeclassIdTag>(parser_node);
|
||||||
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
|
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:
|
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:
|
||||||
case tokens::Type::OPERATOR_TAIL1:
|
case tokens::Type::OPERATOR_TAIL1:
|
||||||
case tokens::Type::OPERATOR_TAIL2:
|
case tokens::Type::OPERATOR_TAIL2:
|
||||||
case tokens::Type::OPERATOR_TAIL3:
|
case tokens::Type::OPERATOR_TAIL3:
|
||||||
return build_operator(parser_node);
|
return Run<nodes::Identifier, ::utils::OperatorIdTag>(parser_node);
|
||||||
// [used as string]
|
// [used as string]
|
||||||
// case tokens::Type::ANNOTATION_IDENTIFIER:
|
// case tokens::Type::ANNOTATION_IDENTIFIER:
|
||||||
// return build_annotation(parser_node);
|
// return build_annotation(parser_node);
|
||||||
default:
|
default:
|
||||||
error_handling::handle_parsing_error("Unexprected identifier node type",
|
logc.Fatal<Log::kProc>({{"Unexprected identifier node type"}},
|
||||||
parser_node);
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
error_handling::handle_general_error("Unreachable");
|
::utils::Assert(false, "Unreachable");
|
||||||
exit(1); // unreachable
|
exit(1); // unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes::Identifier build_simple_name(parser::ParseTree::Node parser_node) {
|
nodes::Identifier
|
||||||
return nodes::Identifier(build_node(parser_node),
|
BuilderTask<nodes::Identifier, ::utils::SimpleNameIdTag>::operator()(
|
||||||
nodes::Identifier::SIMPLE_NAME,
|
const ParserNode &parser_node, const Args &) {
|
||||||
parser_node.get_value());
|
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) {
|
nodes::Identifier
|
||||||
return nodes::Identifier(build_node(parser_node),
|
BuilderTask<nodes::Identifier, ::utils::SimpleTypeIdTag>::operator()(
|
||||||
nodes::Identifier::SIMPLE_TYPE,
|
const ParserNode &parser_node, const Args &) {
|
||||||
parser_node.get_value());
|
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) {
|
nodes::Identifier
|
||||||
return nodes::Identifier(build_node(parser_node),
|
BuilderTask<nodes::Identifier, ::utils::TypeclassIdTag>::operator()(
|
||||||
nodes::Identifier::TYPECLASS,
|
const ParserNode &parser_node, const Args &) {
|
||||||
parser_node.get_value());
|
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) {
|
nodes::Identifier
|
||||||
return nodes::Identifier(build_node(parser_node),
|
BuilderTask<nodes::Identifier, ::utils::ArgNameIdTag>::operator()(
|
||||||
nodes::Identifier::ARGUMENT_NAME,
|
const ParserNode &parser_node, const Args &) {
|
||||||
parser_node.get_value());
|
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) {
|
nodes::Identifier
|
||||||
return nodes::Identifier(build_node(parser_node),
|
BuilderTask<nodes::Identifier, ::utils::ArgTypeIdTag>::operator()(
|
||||||
nodes::Identifier::ARGUMENT_TYPE,
|
const ParserNode &parser_node, const Args &) {
|
||||||
parser_node.get_value());
|
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
|
// 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();
|
std::string identifier = parser_node.get_value();
|
||||||
|
|
||||||
// identifier.size() > 0 by parsing convention
|
// identifier.size() > 0 by parsing convention
|
||||||
identifier = identifier.substr(1, identifier.size() - 1);
|
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();
|
std::string identifier = parser_node.get_value();
|
||||||
|
|
||||||
// --- points needed for proper printing
|
// --- 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,
|
return nodes::Identifier{.kind = nodes::Identifier::kOperator,
|
||||||
identifier);
|
.value = identifier};
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes::Identifier build_placeholder(parser::ParseTree::Node parser_node) {
|
nodes::Identifier
|
||||||
return nodes::Identifier(build_node(parser_node),
|
BuilderTask<nodes::Identifier, ::utils::PlaceholderIdTag>::operator()(
|
||||||
nodes::Identifier::PLACEHOLDER, "_");
|
const ParserNode &, const Args &) {
|
||||||
|
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||||
|
|
||||||
|
return nodes::Identifier{
|
||||||
|
.kind = nodes::Identifier::kPlaceholder,
|
||||||
|
.value = "_",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- extra
|
// --- extra
|
||||||
|
|
||||||
nodes::Extra build_extra(parser::ParseTree::Node parser_node) {
|
nodes::Extra
|
||||||
return nodes::Extra(build_node(parser_node), parser_node.get_value());
|
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
|
// --- 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();
|
std::string empty_lines = parser_node.get_value();
|
||||||
|
|
||||||
size_t empty_lines_count = 0;
|
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) {
|
if (empty_lines_count == 0) {
|
||||||
error_handling::handle_parsing_error("Empty lines node with zero new lines",
|
logc.Fatal<Log::kProc>({{"Empty lines node with zero new lines"}},
|
||||||
parser_node);
|
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
|
} // namespace builders
|
||||||
|
|
|
||||||
|
|
@ -2,154 +2,129 @@
|
||||||
|
|
||||||
#include "basic_builders.hpp"
|
#include "basic_builders.hpp"
|
||||||
#include "basic_nodes.hpp"
|
#include "basic_nodes.hpp"
|
||||||
#include "error_handling.hpp"
|
|
||||||
#include "expression_nodes.hpp"
|
#include "expression_nodes.hpp"
|
||||||
|
#include "log.hpp"
|
||||||
#include "tokens.hpp"
|
#include "tokens.hpp"
|
||||||
#include "type_builders.hpp"
|
#include "type_builders.hpp"
|
||||||
#include "type_nodes.hpp"
|
#include "type_nodes.hpp"
|
||||||
|
|
||||||
|
// TODO: insert is_scoped everywere
|
||||||
|
|
||||||
namespace builders {
|
namespace builders {
|
||||||
|
|
||||||
nodes::Expr BuilderTask<nodes::Expr>::operator()(const ParserNode &parser_node,
|
Node BuilderTask<Node>::operator()(const ParserNode &parser_node,
|
||||||
const Args &) {
|
const Args &) {
|
||||||
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
|
|
||||||
tokens::Type type = tokens::string_to_type(parser_node.get_type());
|
tokens::Type type = tokens::string_to_type(parser_node.get_type());
|
||||||
|
|
||||||
auto maybe_parenthesis = parser_node.previous_sibling();
|
auto maybe_parenthesis = parser_node.previous_sibling();
|
||||||
|
|
||||||
|
// FIXME TODO
|
||||||
bool is_scoped =
|
bool is_scoped =
|
||||||
(!maybe_parenthesis.is_null() && !maybe_parenthesis.is_named() &&
|
(!maybe_parenthesis.is_null() && !maybe_parenthesis.is_named() &&
|
||||||
maybe_parenthesis.get_value() == "(");
|
maybe_parenthesis.get_value() == "(");
|
||||||
|
|
||||||
std::optional<nodes::ExprData::Type> expr;
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
// --- flow control
|
// --- flow control
|
||||||
case tokens::Type::MATCH:
|
case tokens::Type::MATCH:
|
||||||
expr = Run<nodes::Match>(parser_node);
|
return Run<nodes::Match>(parser_node, {is_scoped});
|
||||||
break;
|
|
||||||
case tokens::Type::CONDITION:
|
case tokens::Type::CONDITION:
|
||||||
return state<Exprs>().add_expr({build_node(parser_node),
|
return Run<nodes::Condition>(parser_node, {is_scoped});
|
||||||
Run<nodes::Condition>(parser_node),
|
|
||||||
is_scoped});
|
|
||||||
expr = Run<nodes::Match>(parser_node);
|
|
||||||
break;
|
|
||||||
case tokens::Type::LOOP:
|
case tokens::Type::LOOP:
|
||||||
return state<Exprs>().add_expr(
|
return Run<nodes::Loop>(parser_node, {is_scoped});
|
||||||
{build_node(parser_node), Run<nodes::Loop>(parser_node), is_scoped});
|
|
||||||
expr = Run<nodes::Match>(parser_node);
|
|
||||||
break;
|
|
||||||
// --- operators
|
// --- operators
|
||||||
case tokens::Type::COMMA_EXPRESSION:
|
case tokens::Type::COMMA_EXPRESSION:
|
||||||
expr = Run<nodes::NameExpression, utils::CommaTag>(parser_node);
|
return Run<nodes::NameExpression, utils::CommaTag>(parser_node,
|
||||||
break;
|
{is_scoped});
|
||||||
case tokens::Type::OPERATOR_EXPRESSION:
|
case tokens::Type::OPERATOR_EXPRESSION:
|
||||||
expr = Run<nodes::NameExpression, utils::OperatorTag>(parser_node);
|
return Run<nodes::NameExpression, utils::OperatorTag>(parser_node,
|
||||||
break;
|
{is_scoped});
|
||||||
// --- containers
|
// --- containers
|
||||||
case tokens::Type::BLOCK:
|
case tokens::Type::BLOCK:
|
||||||
expr = Run<nodes::Container, utils::BlockTag>(parser_node);
|
return Run<nodes::Container, utils::BlockTag>(parser_node, {is_scoped});
|
||||||
break;
|
|
||||||
case tokens::Type::ARRAY:
|
case tokens::Type::ARRAY:
|
||||||
expr = Run<nodes::Container, utils::ArrayTag>(parser_node);
|
return Run<nodes::Container, utils::ArrayTag>(parser_node, {is_scoped});
|
||||||
break;
|
|
||||||
// --- modifiers
|
// --- modifiers
|
||||||
case tokens::Type::RETURN:
|
case tokens::Type::RETURN:
|
||||||
expr = Run<nodes::Return>(parser_node);
|
return Run<nodes::Return>(parser_node, {is_scoped});
|
||||||
break;
|
|
||||||
case tokens::Type::NAME_DEFINITION:
|
case tokens::Type::NAME_DEFINITION:
|
||||||
expr = Run<nodes::NameDefinition>(parser_node);
|
return Run<nodes::NameDefinition>(parser_node, {is_scoped});
|
||||||
break;
|
|
||||||
case tokens::Type::ARRAY_ACCESS:
|
case tokens::Type::ARRAY_ACCESS:
|
||||||
expr = Run<nodes::Access, utils::ArrayAccessTag>(parser_node);
|
return Run<nodes::Access, utils::ArrayAccessTag>(parser_node, {is_scoped});
|
||||||
break;
|
|
||||||
case tokens::Type::TUPLE_ACCESS:
|
case tokens::Type::TUPLE_ACCESS:
|
||||||
expr = Run<nodes::Access, utils::TupleAccessTag>(parser_node);
|
return Run<nodes::Access, utils::TupleAccessTag>(parser_node, {is_scoped});
|
||||||
break;
|
|
||||||
case tokens::Type::LOOP_CONTROL:
|
case tokens::Type::LOOP_CONTROL:
|
||||||
expr = Run<nodes::LoopControl>(parser_node);
|
return Run<nodes::LoopControl>(parser_node, {is_scoped});
|
||||||
break;
|
|
||||||
case tokens::Type::REFERENCE_EXPRESSION:
|
case tokens::Type::REFERENCE_EXPRESSION:
|
||||||
expr = Run<nodes::ModifierExpression, utils::RefTag>(parser_node);
|
return Run<nodes::ModifierExpression, utils::RefTag>(parser_node,
|
||||||
break;
|
{is_scoped});
|
||||||
case tokens::Type::SUFFIX_EXPRESSION:
|
case tokens::Type::SUFFIX_EXPRESSION:
|
||||||
expr = Run<nodes::ModifierExpression, utils::SuffixTag>(parser_node);
|
return Run<nodes::ModifierExpression, utils::SuffixTag>(parser_node,
|
||||||
break;
|
{is_scoped});
|
||||||
// --- other
|
// --- other
|
||||||
case tokens::Type::NAME_EXPRESSION:
|
case tokens::Type::NAME_EXPRESSION:
|
||||||
expr = Run<nodes::NameExpression, utils::FuncCallTag>(parser_node);
|
return Run<nodes::NameExpression, utils::FuncCallTag>(parser_node,
|
||||||
break;
|
{is_scoped});
|
||||||
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
|
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
|
||||||
case tokens::Type::SIMPLE_NAME_IDENTIFIER:
|
case tokens::Type::SIMPLE_NAME_IDENTIFIER:
|
||||||
case tokens::Type::PLACEHOLDER:
|
case tokens::Type::PLACEHOLDER:
|
||||||
expr = nodes::NameExpression(build_node(parser_node),
|
return Build(
|
||||||
build_identifier(parser_node));
|
nodes::NameExpression{
|
||||||
break;
|
.name = RunOther<nodes::Identifier>(parser_node),
|
||||||
|
},
|
||||||
|
parser_node.get_pos()); // TODO: is_scoped
|
||||||
case tokens::Type::CONSTRUCTOR:
|
case tokens::Type::CONSTRUCTOR:
|
||||||
expr = Run<nodes::Constructor>(parser_node);
|
return Run<nodes::Constructor>(parser_node);
|
||||||
break;
|
|
||||||
case tokens::Type::LAMBDA:
|
case tokens::Type::LAMBDA:
|
||||||
expr = Run<nodes::Lambda>(parser_node);
|
return Run<nodes::Lambda>(parser_node);
|
||||||
break;
|
|
||||||
// --- literals
|
// --- literals
|
||||||
case tokens::Type::FLOAT_LITERAL:
|
// TODO: FIXME:
|
||||||
expr = build_float_literal(parser_node);
|
// case tokens::Type::FLOAT_LITERAL:
|
||||||
break;
|
// return BUILD : build_float_literal(parser_node);
|
||||||
case tokens::Type::DOUBLE_LITERAL:
|
// case tokens::Type::DOUBLE_LITERAL:
|
||||||
expr = build_double_literal(parser_node);
|
// return BUILD : build_double_literal(parser_node);
|
||||||
break;
|
// case tokens::Type::INT_LITERAL:
|
||||||
case tokens::Type::INT_LITERAL:
|
// return BUILD : build_int_literal(parser_node);
|
||||||
expr = build_int_literal(parser_node);
|
// case tokens::Type::LONG_LITERAL:
|
||||||
break;
|
// return BUILD : build_long_literal(parser_node);
|
||||||
case tokens::Type::LONG_LITERAL:
|
// case tokens::Type::INDEX_LITERAL:
|
||||||
expr = build_long_literal(parser_node);
|
// return BUILD : build_index_literal(parser_node);
|
||||||
break;
|
// case tokens::Type::STRING_LITERAL:
|
||||||
case tokens::Type::INDEX_LITERAL:
|
// return BUILD : build_string_literal(parser_node);
|
||||||
expr = build_index_literal(parser_node);
|
// case tokens::Type::UNICODE_STRING_LITERAL:
|
||||||
break;
|
// return BUILD : build_unicode_string_literal(parser_node);
|
||||||
case tokens::Type::STRING_LITERAL:
|
// case tokens::Type::CHAR_LITERAL:
|
||||||
expr = build_string_literal(parser_node);
|
// return BUILD : build_char_literal(parser_node);
|
||||||
break;
|
// case tokens::Type::UNICODE_LITERAL:
|
||||||
case tokens::Type::UNICODE_STRING_LITERAL:
|
// return BUILD : build_unicode_literal(parser_node);
|
||||||
expr = build_unicode_string_literal(parser_node);
|
// case tokens::Type::BOOL_LITERAL:
|
||||||
break;
|
// return BUILD : build_bool_literal(parser_node);
|
||||||
case tokens::Type::CHAR_LITERAL:
|
// case tokens::Type::UNIT_LITERAL:
|
||||||
expr = build_char_literal(parser_node);
|
// return BUILD : build_unit_literal(parser_node);
|
||||||
break;
|
// case tokens::Type::NULL_LITERAL:
|
||||||
case tokens::Type::UNICODE_LITERAL:
|
// return BUILD : build_null_literal(parser_node);
|
||||||
expr = build_unicode_literal(parser_node);
|
// case tokens::Type::EXTRA:
|
||||||
break;
|
// return BUILD : build_extra(parser_node);
|
||||||
case tokens::Type::BOOL_LITERAL:
|
// case tokens::Type::EMPTY_LINES:
|
||||||
expr = build_bool_literal(parser_node);
|
// return BUILD : build_empty_lines(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;
|
|
||||||
default:
|
default:
|
||||||
utils::Assert(true,
|
break;
|
||||||
std::format("Unexpected expression node type {}",
|
|
||||||
static_cast<int>(type))); // TODO: magic_enum
|
|
||||||
// FIXME: change to fatal error ?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::Assert(expr.has_value(), "Expression should have value");
|
utils::Assert(true, std::format("Unexpected expression node type {}",
|
||||||
|
static_cast<int>(type))); // TODO: magic_enum
|
||||||
return state<Exprs>().add_expr(
|
// FIXME: change to fatal error ?
|
||||||
{build_node(parser_node), expr.value(), is_scoped});
|
throw std::exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- flow control
|
// --- flow control
|
||||||
|
|
||||||
// (':=' | '=:') expression (('??' | 'if') expression)? (_do_ expression)?
|
// (':=' | '=:') expression (('??' | 'if') expression)? (_do_ expression)?
|
||||||
nodes::Match::Case
|
Node BuilderTask<nodes::Match::Case>::operator()(const ParserNode &parser_node,
|
||||||
BuilderTask<nodes::Match::Case>::operator()(const ParserNode &parser_node,
|
const Args &) {
|
||||||
const Args &) {
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
|
|
||||||
std::string case_type = parser_node.nth_child(0).get_value();
|
std::string case_type = parser_node.nth_child(0).get_value();
|
||||||
|
|
||||||
std::optional<ParserNode> condition_node;
|
std::optional<ParserNode> condition_node;
|
||||||
|
|
@ -169,49 +144,59 @@ BuilderTask<nodes::Match::Case>::operator()(const ParserNode &parser_node,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodes::Match::Case(
|
return Build(
|
||||||
build_node(parser_node),
|
nodes::Match::Case{
|
||||||
case_type == ":=" ? nodes::Match::Case::PATTERN_VALUE
|
.kind = case_type == ":=" ? nodes::Match::Case::PATTERN_VALUE
|
||||||
: nodes::Match::Case::VALUE_PATTERN,
|
: nodes::Match::Case::VALUE_PATTERN,
|
||||||
Run<nodes::Expr>(parser_node.nth_named_child(0)),
|
.value = Run<Node>(parser_node.nth_named_child(0)),
|
||||||
condition_node.has_value() ? Run<nodes::Expr>(condition_node.value())
|
.condition = condition_node.has_value()
|
||||||
: std::optional<nodes::Expr>(),
|
? Run<Node>(condition_node.value())
|
||||||
expression_node.has_value() ? Run<nodes::Expr>(expression_node.value())
|
: std::optional<storage::Id>(),
|
||||||
: std::optional<nodes::Expr>());
|
.expr = expression_node.has_value()
|
||||||
|
? Run<Node>(expression_node.value())
|
||||||
|
: std::optional<storage::Id>(),
|
||||||
|
},
|
||||||
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
// expression case+
|
// expression case+
|
||||||
nodes::Match
|
Node BuilderTask<nodes::Match>::operator()(const ParserNode &parser_node,
|
||||||
BuilderTask<nodes::Match>::operator()(const ParserNode &parser_node,
|
const Args &) {
|
||||||
const Args &) {
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
std::vector<nodes::Match::Case> cases;
|
|
||||||
|
std::vector<storage::Id /*nodes::Match::Case*/> cases; // TODO
|
||||||
|
|
||||||
auto current_node = parser_node.nth_named_child(1);
|
auto current_node = parser_node.nth_named_child(1);
|
||||||
while (!current_node.is_null()) {
|
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();
|
current_node = current_node.next_named_sibling();
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodes::Match(build_node(parser_node),
|
return Build(
|
||||||
Run<nodes::Expr>(parser_node.nth_named_child(0)),
|
nodes::Match{
|
||||||
std::move(cases));
|
.value = Run<Node>(parser_node.nth_named_child(0)),
|
||||||
|
.cases = std::move(cases),
|
||||||
|
},
|
||||||
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ('??' | 'if') expression _do_ expression (('!!' | 'elif') expression _do_
|
// ('??' | 'if') expression _do_ expression (('!!' | 'elif') expression _do_
|
||||||
// expression)* (('!!=>', 'else') expression)?
|
// expression)* (('!!=>', 'else') expression)?
|
||||||
nodes::Condition
|
Node BuilderTask<nodes::Condition>::operator()(const ParserNode &parser_node,
|
||||||
BuilderTask<nodes::Condition>::operator()(const ParserNode &parser_node,
|
const Args &) {
|
||||||
const Args &) {
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
|
|
||||||
size_t named_child_count = parser_node.named_child_count();
|
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 current_node = parser_node.nth_named_child(0);
|
||||||
auto next_node = current_node.next_named_sibling();
|
auto next_node = current_node.next_named_sibling();
|
||||||
|
|
||||||
while (!current_node.is_null() && !next_node.is_null()) {
|
while (!current_node.is_null() && !next_node.is_null()) {
|
||||||
cases.push_back(
|
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();
|
current_node = next_node.next_named_sibling();
|
||||||
if (current_node.is_null()) {
|
if (current_node.is_null()) {
|
||||||
break;
|
break;
|
||||||
|
|
@ -219,97 +204,102 @@ BuilderTask<nodes::Condition>::operator()(const ParserNode &parser_node,
|
||||||
next_node = current_node.next_named_sibling();
|
next_node = current_node.next_named_sibling();
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodes::Condition(
|
return Build(
|
||||||
build_node(parser_node), std::move(cases),
|
nodes::Condition{
|
||||||
named_child_count % 2 == 1
|
.cases = std::move(cases),
|
||||||
? Run<nodes::Expr>(parser_node.nth_named_child(named_child_count - 1))
|
.else_case = named_child_count % 2 == 1
|
||||||
: std::optional<nodes::Expr>());
|
? Run<Node>(parser_node.nth_named_child(
|
||||||
|
named_child_count - 1))
|
||||||
|
: std::optional<Node>(),
|
||||||
|
},
|
||||||
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ('@' | 'for') (expression | expression ':' expression)? _do_ expression
|
// ('@' | 'for') (expression | expression ':' expression)? _do_ expression
|
||||||
nodes::Loop BuilderTask<nodes::Loop>::operator()(const ParserNode &parser_node,
|
Node BuilderTask<nodes::Loop>::operator()(const ParserNode &parser_node,
|
||||||
const Args &) {
|
const Args &) {
|
||||||
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
|
|
||||||
size_t named_child_count = parser_node.named_child_count();
|
size_t named_child_count = parser_node.named_child_count();
|
||||||
|
|
||||||
if (named_child_count == 1) { // body
|
if (named_child_count == 1) { // body
|
||||||
return nodes::Loop(build_node(parser_node),
|
return Build(nodes::Loop(Run<Node>(parser_node.nth_named_child(0))),
|
||||||
Run<nodes::Expr>(parser_node.nth_named_child(0)));
|
parser_node.get_pos());
|
||||||
} else if (named_child_count == 2) { // condition,
|
} else if (named_child_count == 2) { // condition,
|
||||||
// body
|
// body
|
||||||
return nodes::Loop(build_node(parser_node),
|
return Build(nodes::Loop(Run<Node>(parser_node.nth_named_child(0)),
|
||||||
Run<nodes::Expr>(parser_node.nth_named_child(0)),
|
Run<Node>(parser_node.nth_named_child(1))),
|
||||||
Run<nodes::Expr>(parser_node.nth_named_child(1)));
|
parser_node.get_pos());
|
||||||
} else if (named_child_count == 3) { // variable,
|
} else if (named_child_count == 3) { // variable,
|
||||||
// interval,
|
// interval,
|
||||||
// body
|
// body
|
||||||
return nodes::Loop(build_node(parser_node),
|
return Build(nodes::Loop(Run<Node>(parser_node.nth_named_child(0)),
|
||||||
Run<nodes::Expr>(parser_node.nth_named_child(0)),
|
Run<Node>(parser_node.nth_named_child(1)),
|
||||||
Run<nodes::Expr>(parser_node.nth_named_child(1)),
|
Run<Node>(parser_node.nth_named_child(2))),
|
||||||
Run<nodes::Expr>(parser_node.nth_named_child(2)));
|
parser_node.get_pos());
|
||||||
} else {
|
} else {
|
||||||
error_handling::handle_parsing_error("Unex"
|
logc.Fatal<Log::kProc>({{"Unexpected named expression amount in loop"}},
|
||||||
"prec"
|
parser_node.get_pos());
|
||||||
"ted "
|
|
||||||
"name"
|
|
||||||
"d "
|
|
||||||
"expr"
|
|
||||||
"essi"
|
|
||||||
"on "
|
|
||||||
"amou"
|
|
||||||
"nt "
|
|
||||||
"in "
|
|
||||||
"loo"
|
|
||||||
"p",
|
|
||||||
parser_node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error_handling::handle_general_error("Unreac"
|
error_handling::handle_general_error("Unreachable");
|
||||||
"habl"
|
|
||||||
"e");
|
|
||||||
exit(1); // unreachable
|
exit(1); // unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- operators
|
// --- operators
|
||||||
|
|
||||||
// expression ',' expression
|
// expression ',' expression
|
||||||
nodes::NameExpression
|
Node BuilderTask<nodes::NameExpression, utils::CommaTag>::operator()(
|
||||||
BuilderTask<nodes::NameExpression, utils::CommaTag>::operator()(
|
|
||||||
const ParserNode &parser_node, const Args &) {
|
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,
|
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,
|
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(
|
return Build(
|
||||||
build_node(parser_node),
|
nodes::NameExpression{
|
||||||
nodes::Identifier(
|
.name =
|
||||||
build_node(parser_node), // can't find more precise location
|
nodes::Identifier{
|
||||||
nodes::Identifier::SIMPLE_NAME, ","),
|
// can't find more precise location
|
||||||
std::move(args), std::nullopt, false, true);
|
.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
|
// expression operator expression
|
||||||
nodes::NameExpression
|
Node BuilderTask<nodes::NameExpression, utils::OperatorTag>::operator()(
|
||||||
BuilderTask<nodes::NameExpression, utils::OperatorTag>::operator()(
|
|
||||||
const ParserNode &parser_node, const Args &) {
|
const ParserNode &parser_node, const Args &) {
|
||||||
auto name_node = parser_node.child_by_field_name("na"
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
"m"
|
|
||||||
"e");
|
|
||||||
|
|
||||||
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,
|
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,
|
args.emplace_back(std::nullopt, Run<Node>(name_node.next_named_sibling()));
|
||||||
Run<nodes::Expr>(name_node.next_named_sibling()));
|
|
||||||
|
|
||||||
return nodes::NameExpression(build_node(parser_node),
|
return Build(
|
||||||
build_operator(name_node), std::move(args),
|
nodes::NameExpression{
|
||||||
std::nullopt, false, true);
|
.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
|
// --- continers
|
||||||
|
|
@ -319,64 +309,84 @@ BuilderTask<nodes::NameExpression, utils::OperatorTag>::operator()(
|
||||||
// --- modifiers
|
// --- modifiers
|
||||||
|
|
||||||
// ('return' | 'bring') expression
|
// ('return' | 'bring') expression
|
||||||
nodes::Return
|
Node BuilderTask<nodes::Return>::operator()(const ParserNode &parser_node,
|
||||||
BuilderTask<nodes::Return>::operator()(const ParserNode &parser_node,
|
const Args &) {
|
||||||
const Args &) {
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
|
|
||||||
std::string modifier = parser_node.nth_child(0).get_value();
|
std::string modifier = parser_node.nth_child(0).get_value();
|
||||||
|
|
||||||
return nodes::Return(build_node(parser_node),
|
return Build(
|
||||||
modifier == "re"
|
nodes::Return{
|
||||||
"tu"
|
.kind = modifier == "return" ? nodes::Return::RETURN
|
||||||
"rn"
|
: nodes::Return::BRING,
|
||||||
? nodes::Return::RETURN
|
.expr = Run<Node>(parser_node.nth_named_child(0)),
|
||||||
: nodes::Return::BRING,
|
},
|
||||||
Run<nodes::Expr>(parser_node.nth_named_child(0)));
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
// _var_let_ (simple_name_identifier | placeholder)
|
// _var_let_ (simple_name_identifier | placeholder)
|
||||||
nodes::NameDefinition
|
Node BuilderTask<nodes::NameDefinition>::operator()(
|
||||||
BuilderTask<nodes::NameDefinition>::operator()(const ParserNode &parser_node,
|
const ParserNode &parser_node, const Args &) {
|
||||||
const Args &) {
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
|
|
||||||
std::string modifier = parser_node.nth_child(0).get_value();
|
std::string modifier = parser_node.nth_child(0).get_value();
|
||||||
|
|
||||||
auto name_node = parser_node.nth_named_child(0);
|
auto name_node = parser_node.nth_named_child(0);
|
||||||
|
|
||||||
return nodes::NameDefinition(build_node(parser_node),
|
return Build(
|
||||||
(modifier == "%" || modifier == "let")
|
nodes::NameDefinition{
|
||||||
? nodes::NameDefinition::LET
|
.kind = (modifier == "%" || modifier == "let")
|
||||||
: nodes::NameDefinition::VAR,
|
? nodes::NameDefinition::LET
|
||||||
build_identifier(name_node));
|
: nodes::NameDefinition::VAR,
|
||||||
|
.name =
|
||||||
|
Run<nodes::Identifier, utils::None, nodes::Identifier>(name_node),
|
||||||
|
},
|
||||||
|
parser_node.get_pos());
|
||||||
} // IN PROGRESS
|
} // IN PROGRESS
|
||||||
|
|
||||||
// expression '[' expression ']'
|
// expression '[' expression ']'
|
||||||
nodes::Access BuilderTask<nodes::Access, utils::ArrayAccessTag>::operator()(
|
Node BuilderTask<nodes::Access, utils::ArrayAccessTag>::operator()(
|
||||||
const ParserNode &parser_node, const Args &) {
|
const ParserNode &parser_node, const Args &) {
|
||||||
return nodes::Access(build_node(parser_node), nodes::Access::ARRAY,
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
Run<nodes::Expr>(parser_node.nth_named_child(0)),
|
|
||||||
Run<nodes::Expr>(parser_node.nth_named_child(1)));
|
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
|
// expression '.' number_literal
|
||||||
nodes::Access BuilderTask<nodes::Access, utils::TupleAccessTag>::operator()(
|
Node BuilderTask<nodes::Access, utils::TupleAccessTag>::operator()(
|
||||||
const ParserNode &parser_node, const Args &) {
|
const ParserNode &parser_node, const Args &) {
|
||||||
return nodes::Access(
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
build_node(parser_node), nodes::Access::TUPLE,
|
|
||||||
Run<nodes::Expr>(parser_node.nth_named_child(0)),
|
auto const node = Build(
|
||||||
state<Exprs>().add_expr(
|
nodes::Access{
|
||||||
{build_node(parser_node.nth_named_child(1)),
|
.kind = nodes::Access::TUPLE,
|
||||||
build_index_literal(parser_node.nth_named_child(1)), false}));
|
.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'
|
// 'break' | 'continue'
|
||||||
nodes::LoopControl
|
Node BuilderTask<nodes::LoopControl>::operator()(const ParserNode &parser_node,
|
||||||
BuilderTask<nodes::LoopControl>::operator()(const ParserNode &parser_node,
|
const Args &) {
|
||||||
const Args &) {
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
return nodes::LoopControl(build_node(parser_node),
|
|
||||||
parser_node.get_value() == "br"
|
return Build(
|
||||||
"ea"
|
nodes::LoopControl{
|
||||||
"k"
|
.kind = parser_node.get_value() == "break"
|
||||||
? nodes::LoopControl::BREAK
|
? nodes::LoopControl::BREAK
|
||||||
: nodes::LoopControl::CONTINUE);
|
: nodes::LoopControl::CONTINUE,
|
||||||
|
},
|
||||||
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
// // ModifierExpression -> .hpp
|
// // ModifierExpression -> .hpp
|
||||||
|
|
@ -391,10 +401,12 @@ void build_args_until_end(ParserNode first_parse_node, Executor &executor,
|
||||||
while (!current_node.is_null()) {
|
while (!current_node.is_null()) {
|
||||||
if (tokens::string_to_type(current_node.get_type()) ==
|
if (tokens::string_to_type(current_node.get_type()) ==
|
||||||
tokens::Type::ANNOTATION_IDENTIFIER) {
|
tokens::Type::ANNOTATION_IDENTIFIER) {
|
||||||
last_annotation = build_annotation(current_node);
|
last_annotation =
|
||||||
|
BuilderTask<nodes::Annotation>{executor}(current_node, {})
|
||||||
|
.value; // TODO
|
||||||
} else {
|
} else {
|
||||||
args.emplace_back(std::move(last_annotation),
|
args.emplace_back(std::move(last_annotation),
|
||||||
BuilderTask<nodes::Expr>{executor}(current_node, {}));
|
BuilderTask<Node>{executor}(current_node, {}));
|
||||||
last_annotation = std::nullopt;
|
last_annotation = std::nullopt;
|
||||||
}
|
}
|
||||||
current_node = current_node.next_named_sibling();
|
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
|
// (type '.' simple_name | expression '.' simple_name | name | '(' operator
|
||||||
// ')') (annotation? expression)*
|
// ')') (annotation? expression)*
|
||||||
nodes::NameExpression
|
Node BuilderTask<nodes::NameExpression, utils::FuncCallTag>::operator()(
|
||||||
BuilderTask<nodes::NameExpression, utils::FuncCallTag>::operator()(
|
|
||||||
const ParserNode &parser_node, const Args &) {
|
const ParserNode &parser_node, const Args &) {
|
||||||
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
|
|
||||||
std::vector<nodes::AnnotatedArgument> args;
|
std::vector<nodes::AnnotatedArgument> args;
|
||||||
|
|
||||||
std::optional<nodes::TypeData> prefix;
|
std::optional<nodes::TypeData> prefix;
|
||||||
|
|
||||||
bool is_point_call = false;
|
bool is_point_call = false;
|
||||||
|
|
||||||
auto name_node = parser_node.child_by_field_name("na"
|
auto name_node = parser_node.child_by_field_name("name");
|
||||||
"m"
|
|
||||||
"e");
|
|
||||||
|
|
||||||
std::optional<ParserNode> prefix_node;
|
std::optional<ParserNode> prefix_node;
|
||||||
|
|
||||||
|
|
@ -433,23 +444,30 @@ BuilderTask<nodes::NameExpression, utils::FuncCallTag>::operator()(
|
||||||
prefix_node = current_node;
|
prefix_node = current_node;
|
||||||
} else {
|
} else {
|
||||||
is_point_call = true;
|
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);
|
build_args_until_end(name_node.next_named_sibling(), executor, args);
|
||||||
|
|
||||||
return nodes::NameExpression(
|
return Build(
|
||||||
build_node(parser_node), build_identifier(name_node), std::move(args),
|
nodes::NameExpression{
|
||||||
prefix_node.has_value() ? build_type(prefix_node.value(), state<Types>())
|
.name = RunOther<nodes::Identifier>(name_node),
|
||||||
: nodes::MaybeType(),
|
.args = std::move(args),
|
||||||
is_point_call, false);
|
.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)*
|
// type (annotation? expression)*
|
||||||
nodes::Constructor
|
Node BuilderTask<nodes::Constructor>::operator()(const ParserNode &parser_node,
|
||||||
BuilderTask<nodes::Constructor>::operator()(const ParserNode &parser_node,
|
const Args &) {
|
||||||
const Args &) {
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
|
|
||||||
std::vector<nodes::AnnotatedArgument> args;
|
std::vector<nodes::AnnotatedArgument> args;
|
||||||
|
|
||||||
build_args_until_end(parser_node
|
build_args_until_end(parser_node
|
||||||
|
|
@ -459,31 +477,39 @@ BuilderTask<nodes::Constructor>::operator()(const ParserNode &parser_node,
|
||||||
.next_named_sibling(),
|
.next_named_sibling(),
|
||||||
executor, args);
|
executor, args);
|
||||||
|
|
||||||
return nodes::Constructor(
|
return Build(
|
||||||
build_node(parser_node),
|
nodes::Constructor{
|
||||||
build_type(parser_node.child_by_field_name("type"), state<Types>()),
|
.type = build_type(parser_node.child_by_field_name("type"),
|
||||||
std::move(args));
|
state<Types>()),
|
||||||
|
.args = std::move(args),
|
||||||
|
},
|
||||||
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
// '\\' argument_name* _do_ expression
|
// '\\' argument_name* _do_ expression
|
||||||
nodes::Lambda
|
Node BuilderTask<nodes::Lambda>::operator()(const ParserNode &parser_node,
|
||||||
BuilderTask<nodes::Lambda>::operator()(const ParserNode &parser_node,
|
const Args &) {
|
||||||
const Args &) {
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
|
|
||||||
std::vector<nodes::Identifier> args;
|
std::vector<nodes::Identifier> args;
|
||||||
|
|
||||||
auto current_node =
|
auto current_node =
|
||||||
parser_node.nth_child(1); // next to '\\', not null ('=>' should present)
|
parser_node.nth_child(1); // next to '\\', not null ('=>' should present)
|
||||||
|
|
||||||
while (current_node.is_named()) { // until _do_
|
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();
|
current_node = current_node.next_sibling();
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip '=>'
|
// skip '=>'
|
||||||
current_node = current_node.next_named_sibling();
|
current_node = current_node.next_named_sibling();
|
||||||
|
|
||||||
return nodes::Lambda(build_node(parser_node), std::move(args),
|
return Build(
|
||||||
Run<nodes::Expr>(current_node));
|
nodes::Lambda{
|
||||||
|
.args = std::move(args),
|
||||||
|
.expr = Run<Node>(current_node),
|
||||||
|
},
|
||||||
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace builders
|
} // namespace builders
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
#include "basic_nodes.hpp"
|
#include "basic_nodes.hpp"
|
||||||
#include "doc_builders.hpp"
|
#include "doc_builders.hpp"
|
||||||
#include "doc_nodes.hpp"
|
#include "doc_nodes.hpp"
|
||||||
#include "error_handling.hpp"
|
|
||||||
#include "expression_builders.hpp"
|
#include "expression_builders.hpp"
|
||||||
#include "statement_nodes.hpp"
|
#include "statement_nodes.hpp"
|
||||||
#include "tokens.hpp"
|
#include "tokens.hpp"
|
||||||
|
|
@ -22,6 +21,8 @@ namespace builders {
|
||||||
nodes::Statements
|
nodes::Statements
|
||||||
BuilderTask<nodes::Statements>::operator()(const ParserNode &parser_node,
|
BuilderTask<nodes::Statements>::operator()(const ParserNode &parser_node,
|
||||||
const Args &) {
|
const Args &) {
|
||||||
|
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||||
|
|
||||||
std::vector<nodes::Statement> statements;
|
std::vector<nodes::Statement> statements;
|
||||||
|
|
||||||
std::optional<nodes::Identifier> last_defined_type_name;
|
std::optional<nodes::Identifier> last_defined_type_name;
|
||||||
|
|
@ -39,6 +40,8 @@ BuilderTask<nodes::Statements>::operator()(const ParserNode &parser_node,
|
||||||
nodes::Statement
|
nodes::Statement
|
||||||
BuilderTask<nodes::Statement>::operator()(const ParserNode &parser_node,
|
BuilderTask<nodes::Statement>::operator()(const ParserNode &parser_node,
|
||||||
const Args &) {
|
const Args &) {
|
||||||
|
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||||
|
|
||||||
tokens::Type type = tokens::string_to_type(parser_node.get_type());
|
tokens::Type type = tokens::string_to_type(parser_node.get_type());
|
||||||
|
|
||||||
std::optional<std::string> statement_name;
|
std::optional<std::string> statement_name;
|
||||||
|
|
@ -46,45 +49,33 @@ BuilderTask<nodes::Statement>::operator()(const ParserNode &parser_node,
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case tokens::Type::IMPORT:
|
case tokens::Type::IMPORT:
|
||||||
statement = nodes::Statement(build_node(parser_node),
|
statement = nodes::Statement{Run<nodes::Import>(parser_node)};
|
||||||
Run<nodes::Import>(parser_node));
|
statement_name =
|
||||||
statement_name = *statement.value()
|
statement.value().get<nodes::Import>().value()->module_name.value;
|
||||||
.get<nodes::Import>()
|
|
||||||
.value()
|
|
||||||
->get_module_name()
|
|
||||||
->get();
|
|
||||||
break;
|
break;
|
||||||
case tokens::Type::TYPE_DEFINITION:
|
case tokens::Type::TYPE_DEFINITION:
|
||||||
statement = nodes::Statement(build_node(parser_node),
|
statement = nodes::Statement{Run<nodes::TypeDefinition>(parser_node)};
|
||||||
Run<nodes::TypeDefinition>(parser_node));
|
|
||||||
state<State>().last_defined_type_name =
|
state<State>().last_defined_type_name =
|
||||||
*statement.value().get<nodes::TypeDefinition>().value()->get_name();
|
statement.value().get<nodes::TypeDefinition>().value()->name;
|
||||||
statement_name = *statement.value()
|
statement_name =
|
||||||
.get<nodes::TypeDefinition>()
|
statement.value().get<nodes::TypeDefinition>().value()->name.value;
|
||||||
.value()
|
|
||||||
->get_name()
|
|
||||||
->get();
|
|
||||||
break;
|
break;
|
||||||
case tokens::Type::FUNCTION_DEFINITION:
|
case tokens::Type::FUNCTION_DEFINITION:
|
||||||
statement = nodes::Statement(build_node(parser_node),
|
statement = nodes::Statement{Run<nodes::FunctionDefinition>(parser_node)};
|
||||||
Run<nodes::FunctionDefinition>(parser_node));
|
statement_name = statement.value()
|
||||||
statement_name = *statement.value()
|
.get<nodes::FunctionDefinition>()
|
||||||
.get<nodes::FunctionDefinition>()
|
.value()
|
||||||
.value()
|
->full_name.value;
|
||||||
->get_full_name()
|
|
||||||
->get();
|
|
||||||
break;
|
break;
|
||||||
case tokens::Type::EXTRA:
|
case tokens::Type::EXTRA:
|
||||||
statement =
|
statement = nodes::Statement{Run<nodes::Extra>(parser_node)};
|
||||||
nodes::Statement(build_node(parser_node), build_extra(parser_node));
|
|
||||||
break;
|
break;
|
||||||
case tokens::Type::EMPTY_LINES:
|
case tokens::Type::EMPTY_LINES:
|
||||||
statement = nodes::Statement(build_node(parser_node),
|
statement = nodes::Statement{Run<nodes::EmptyLines>(parser_node)};
|
||||||
build_empty_lines(parser_node));
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error_handling::handle_parsing_error("Unexprected statement node type",
|
logc.Fatal<Log::kProc>({{"Unexprected statement node type"}},
|
||||||
parser_node);
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!statement.has_value()) {
|
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))
|
.insert_combine(statement_name.value(), std::move(statement_copy))
|
||||||
.second != nodes::CombineResult::OK) {
|
.second != nodes::CombineResult::OK) {
|
||||||
// TODO: more detailed errors
|
// TODO: more detailed errors
|
||||||
error_handling::handle_parsing_error(
|
logc.Fatal<Log::kProc>({{"Can't combine statements with same name"}},
|
||||||
"Can't combine statements with same name", parser_node);
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,6 +100,7 @@ BuilderTask<nodes::Statement>::operator()(const ParserNode &parser_node,
|
||||||
nodes::Import
|
nodes::Import
|
||||||
BuilderTask<nodes::Import>::operator()(const ParserNode &parser_node,
|
BuilderTask<nodes::Import>::operator()(const ParserNode &parser_node,
|
||||||
const Args &) {
|
const Args &) {
|
||||||
|
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||||
|
|
||||||
auto name_node = parser_node.child_by_field_name("name");
|
auto name_node = parser_node.child_by_field_name("name");
|
||||||
auto module_node = parser_node.child_by_field_name("module");
|
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();
|
auto current_node = module_node.next_named_sibling();
|
||||||
while (!current_node.is_null()) {
|
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();
|
current_node = current_node.next_named_sibling();
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodes::Import(build_node(parser_node), build_identifier(name_node),
|
return nodes::Import(Run<nodes::Identifier>(name_node),
|
||||||
build_identifier(module_node), std::move(symbols));
|
Run<nodes::Identifier>(module_node), std::move(symbols));
|
||||||
}
|
}
|
||||||
|
|
||||||
// '?' expression
|
// '?' expression
|
||||||
nodes::Constraint
|
nodes::Constraint
|
||||||
BuilderTask<nodes::Constraint>::operator()(const ParserNode &parser_node,
|
BuilderTask<nodes::Constraint>::operator()(const ParserNode &parser_node,
|
||||||
const Args &) {
|
const Args &) {
|
||||||
return nodes::Constraint(build_node(parser_node),
|
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||||
Run<nodes::Expr>(parser_node.nth_named_child(0)));
|
|
||||||
|
return nodes::Constraint{.expr = Run<Node>(parser_node.nth_named_child(0))};
|
||||||
}
|
}
|
||||||
|
|
||||||
parser::ParseTree::Node collect_symbol_doc_nodes(
|
parser::ParseTree::Node collect_symbol_doc_nodes(
|
||||||
|
|
@ -170,6 +163,8 @@ parser::ParseTree::Node collect_symbol_doc_nodes(
|
||||||
nodes::TypeDefinition
|
nodes::TypeDefinition
|
||||||
BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
|
BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
|
||||||
const Args &) {
|
const Args &) {
|
||||||
|
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||||
|
|
||||||
std::optional<parser::ParseTree::Node> description_node;
|
std::optional<parser::ParseTree::Node> description_node;
|
||||||
std::vector<parser::ParseTree::Node> annotation_nodes;
|
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() &&
|
bool is_on_heap = !name_node.previous_sibling().is_null() &&
|
||||||
name_node.previous_sibling().get_value() == "<>";
|
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()) {
|
if (is_typeclass && !annotation_nodes.empty()) {
|
||||||
error_handling::handle_parsing_error(
|
logc.Fatal<Log::kProc>(
|
||||||
"Typeclass definition can't have annotation documentation",
|
{{"Typeclass definition can't have annotation documentation"}},
|
||||||
parser_node);
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -202,10 +197,10 @@ BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
|
||||||
while (!current_node.is_null()) {
|
while (!current_node.is_null()) {
|
||||||
switch (tokens::string_to_type(current_node.get_type())) {
|
switch (tokens::string_to_type(current_node.get_type())) {
|
||||||
case tokens::Type::TYPECLASS_IDENTIFIER:
|
case tokens::Type::TYPECLASS_IDENTIFIER:
|
||||||
typeclasses.push_back(build_identifier(current_node));
|
typeclasses.push_back(Run<nodes::Identifier>(current_node));
|
||||||
break;
|
break;
|
||||||
case tokens::Type::ARGUMENT_TYPE_IDENTIFIER:
|
case tokens::Type::ARGUMENT_TYPE_IDENTIFIER:
|
||||||
args.push_back(build_identifier(current_node));
|
args.push_back(Run<nodes::Identifier>(current_node));
|
||||||
break;
|
break;
|
||||||
case tokens::Type::VARIANT_TYPE:
|
case tokens::Type::VARIANT_TYPE:
|
||||||
case tokens::Type::TUPLE_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::MODIFIED_TYPE:
|
||||||
case tokens::Type::SIMPLE_TYPE:
|
case tokens::Type::SIMPLE_TYPE:
|
||||||
if (type_node.has_value()) {
|
if (type_node.has_value()) {
|
||||||
error_handling::handle_parsing_error(
|
logc.Fatal<Log::kProc>({{"More then one type node in type definition"}},
|
||||||
"More then one type node in type definition", parser_node);
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
type_node = current_node;
|
type_node = current_node;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error_handling::handle_parsing_error(
|
logc.Fatal<Log::kProc>({{"Unexprected node type in type definition"}},
|
||||||
"Unexprected node type in type definition", parser_node);
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
current_node = current_node.next_named_sibling();
|
current_node = current_node.next_named_sibling();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!type_node.has_value() && !annotation_nodes.empty()) {
|
if (!type_node.has_value() && !annotation_nodes.empty()) {
|
||||||
error_handling::handle_parsing_error(
|
logc.Fatal<Log::kProc>(
|
||||||
"Type declaration can't contain annotation documentation", parser_node);
|
{{"Type declaration can't contain annotation documentation"}},
|
||||||
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_typeclass) {
|
if (is_typeclass) {
|
||||||
if (!args.empty()) {
|
if (!args.empty()) {
|
||||||
error_handling::handle_parsing_error("Typeclass can't have arguments",
|
logc.Fatal<Log::kProc>({{"Typeclass can't have arguments"}},
|
||||||
parser_node);
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type_node.has_value()) {
|
if (type_node.has_value()) {
|
||||||
error_handling::handle_parsing_error(
|
logc.Fatal<Log::kProc>(
|
||||||
"Typeclass can't be type (contain constructors / fields)",
|
{{"Typeclass can't be type (contain constructors / fields)"}},
|
||||||
type_node.value());
|
type_node.value().get_pos());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -255,11 +251,15 @@ BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
|
||||||
annotations, annotations.begin()));
|
annotations, annotations.begin()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodes::TypeDefinition(
|
return nodes::TypeDefinition{
|
||||||
build_node(parser_node),
|
.docs =
|
||||||
build_symbol_docs(description_node, annotation_nodes, annotations),
|
build_symbol_docs(description_node, annotation_nodes, annotations),
|
||||||
is_on_heap, std::move(name), std::move(typeclasses), std::move(args),
|
.is_on_heap = is_on_heap,
|
||||||
type);
|
.name = std::move(name),
|
||||||
|
.typeclasses = std::move(typeclasses),
|
||||||
|
.args = std::move(args),
|
||||||
|
.type = type,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// definition_info? annotation_info* (constraint ';')* '.'? (simple_name
|
// definition_info? annotation_info* (constraint ';')* '.'? (simple_name
|
||||||
|
|
@ -268,6 +268,8 @@ BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
|
||||||
// (((block | array) | '=' expression ';') | ';')
|
// (((block | array) | '=' expression ';') | ';')
|
||||||
nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
|
nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
|
||||||
const ParserNode &parser_node, const Args &) {
|
const ParserNode &parser_node, const Args &) {
|
||||||
|
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||||
|
|
||||||
// const std::optional<nodes::Identifier> &last_defined_type_name, // TODO
|
// const std::optional<nodes::Identifier> &last_defined_type_name, // TODO
|
||||||
|
|
||||||
std::optional<parser::ParseTree::Node> description_node;
|
std::optional<parser::ParseTree::Node> description_node;
|
||||||
|
|
@ -296,8 +298,8 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
|
||||||
is_method = true;
|
is_method = true;
|
||||||
|
|
||||||
if (!state<State>().last_defined_type_name.has_value()) {
|
if (!state<State>().last_defined_type_name.has_value()) {
|
||||||
error_handling::handle_parsing_error(
|
logc.Fatal<Log::kProc>({{"Can't define method without associated type"}},
|
||||||
"Can't define method without associated type", parser_node);
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
name_prefix = state<State>().last_defined_type_name.value();
|
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();
|
current_node = name_node.next_sibling();
|
||||||
if (!current_node.is_null() && !current_node.is_named()) {
|
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
|
// only optional, result allowed
|
||||||
if (!nodes::utils::is_suffix_modifier(return_modifier)) {
|
if (!nodes::utils::is_suffix_modifier(return_modifier)) {
|
||||||
|
|
@ -333,7 +335,7 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
|
||||||
// update last before modifier
|
// update last before modifier
|
||||||
auto maybe_reference_node = current_node.previous_sibling();
|
auto maybe_reference_node = current_node.previous_sibling();
|
||||||
if (!maybe_reference_node.is_null() && !maybe_reference_node.is_named()) {
|
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
|
// only out, in, ref allowed
|
||||||
if (nodes::utils::is_suffix_modifier(last_before_modifier)) {
|
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())) {
|
switch (tokens::string_to_type(current_node.get_type())) {
|
||||||
case tokens::Type::ANNOTATION_IDENTIFIER:
|
case tokens::Type::ANNOTATION_IDENTIFIER:
|
||||||
last_annotation = build_annotation(current_node);
|
last_annotation = Run<nodes::Annotation>(current_node).value; // TODO
|
||||||
break;
|
break;
|
||||||
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
|
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
|
||||||
// update last after modifier
|
// update last after modifier
|
||||||
maybe_reference_node = current_node.next_sibling();
|
maybe_reference_node = current_node.next_sibling();
|
||||||
if (!maybe_reference_node.is_null() && !maybe_reference_node.is_named()) {
|
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
|
// only optional, result allowed
|
||||||
if (!nodes::utils::is_suffix_modifier(last_after_modifier)) {
|
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(
|
args.push_back(nodes::FunctionDefinition::Argument(
|
||||||
last_annotation, build_identifier(current_node), last_before_modifier,
|
last_annotation, Run<nodes::Identifier>(current_node),
|
||||||
last_after_modifier));
|
last_before_modifier, last_after_modifier));
|
||||||
|
|
||||||
last_annotation = std::nullopt;
|
last_annotation = std::nullopt;
|
||||||
break;
|
break;
|
||||||
|
|
@ -381,12 +383,12 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
|
||||||
if (!args[current_type_id].add_type(
|
if (!args[current_type_id].add_type(
|
||||||
last_annotation, build_type(current_node, state<Types>()),
|
last_annotation, build_type(current_node, state<Types>()),
|
||||||
last_before_modifier)) {
|
last_before_modifier)) {
|
||||||
error_handling::handle_parsing_error(
|
logc.Fatal<Log::kProc>(
|
||||||
"It is impossible to use argument modifiers (annotations, "
|
{{"It is impossible to use argument modifiers (annotations, "
|
||||||
"references, "
|
"references, "
|
||||||
"optional markers, result markers) when types explicitely "
|
"optional markers, result markers) when types explicitely "
|
||||||
"defined. Use type annotations instead.",
|
"defined. Use type annotations instead."}},
|
||||||
current_node);
|
current_node.get_pos());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -396,9 +398,9 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (expression_node.has_value()) {
|
if (expression_node.has_value()) {
|
||||||
error_handling::handle_parsing_error(
|
logc.Fatal<Log::kProc>(
|
||||||
"More then one expression found in function definition",
|
{{"More then one expression found in function definition"}},
|
||||||
parser_node);
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
expression_node = current_node;
|
expression_node = current_node;
|
||||||
break;
|
break;
|
||||||
|
|
@ -407,15 +409,16 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_type_id > 0 && current_type_id < args.size()) {
|
if (current_type_id > 0 && current_type_id < args.size()) {
|
||||||
error_handling::handle_parsing_error(
|
logc.Fatal<Log::kProc>(
|
||||||
"Less types then arguments in function definition", parser_node);
|
{{"Less types then arguments in function definition"}},
|
||||||
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_type_id == 0 && !expression_node.has_value()) {
|
if (current_type_id == 0 && !expression_node.has_value()) {
|
||||||
error_handling::handle_parsing_error(
|
logc.Fatal<Log::kProc>(
|
||||||
"Can't declare function without types (types or function body should "
|
{{"Can't declare function without types (types or function body should "
|
||||||
"be added)",
|
"be added)"}},
|
||||||
parser_node);
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
// automatic annotations
|
// automatic annotations
|
||||||
|
|
@ -424,13 +427,13 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
|
||||||
|
|
||||||
if (are_annotations_same_to_names) {
|
if (are_annotations_same_to_names) {
|
||||||
for (size_t i = 0; i < args.size(); ++i) {
|
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(
|
if (!args[i].add_annotation(
|
||||||
new_annotation.substr(1, new_annotation.size() - 1))) {
|
new_annotation.substr(1, new_annotation.size() - 1))) {
|
||||||
error_handling::handle_parsing_error(
|
logc.Fatal<Log::kProc>({{"no annotations provided ( => all annotations "
|
||||||
"no annotations provided ( => all annotations same to names), but "
|
"same to names), but "
|
||||||
"can't add name annotation",
|
"can't add name annotation"}},
|
||||||
current_node);
|
current_node.get_pos());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -439,21 +442,20 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
|
||||||
for (auto &arg : args) {
|
for (auto &arg : args) {
|
||||||
if (arg.get_annotation().has_value()) {
|
if (arg.get_annotation().has_value()) {
|
||||||
if (!annotations_set.insert(*arg.get_annotation().value()).second) {
|
if (!annotations_set.insert(*arg.get_annotation().value()).second) {
|
||||||
error_handling::handle_parsing_error(
|
logc.Fatal<Log::kProc>(
|
||||||
"Two or more same annotations found in function definition",
|
{{"Two or more same annotations found in function definition"}},
|
||||||
parser_node);
|
parser_node.get_pos());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodes::FunctionDefinition(
|
return nodes::FunctionDefinition(
|
||||||
build_node(parser_node),
|
|
||||||
build_symbol_docs(description_node, annotation_nodes, annotations_set),
|
build_symbol_docs(description_node, annotation_nodes, annotations_set),
|
||||||
std::move(constraints), return_modifier, is_method, name_prefix,
|
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,
|
are_annotations_same_to_names,
|
||||||
expression_node.has_value() ? Run<nodes::Expr>(expression_node.value())
|
expression_node.has_value() ? Run<Node>(expression_node.value())
|
||||||
: std::optional<nodes::Expr>());
|
: std::optional<Node>());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace builders
|
} // namespace builders
|
||||||
|
|
|
||||||
|
|
@ -151,37 +151,37 @@ inline bool can_cast_modifier(Modifier from, Modifier to) {
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|
||||||
class Node {
|
// class Node {
|
||||||
public:
|
// public:
|
||||||
Node() : undefined_(true) {}
|
// Node() : undefined_(true) {}
|
||||||
|
|
||||||
Node(std::pair<size_t, size_t> start_position,
|
// Node(std::pair<size_t, size_t> start_position,
|
||||||
std::pair<size_t, size_t> end_position)
|
// std::pair<size_t, size_t> end_position)
|
||||||
: undefined_(false), start_position_(start_position),
|
// : undefined_(false), start_position_(start_position),
|
||||||
end_position_(end_position) {}
|
// end_position_(end_position) {}
|
||||||
|
|
||||||
std::pair<size_t, size_t> get_start_position() const {
|
// std::pair<size_t, size_t> get_start_position() const {
|
||||||
if (undefined_) {
|
// if (undefined_) {
|
||||||
error_handling::handle_general_error(
|
// error_handling::handle_general_error(
|
||||||
"Get start position from undefined node");
|
// "Get start position from undefined node");
|
||||||
}
|
// }
|
||||||
return start_position_;
|
// return start_position_;
|
||||||
}
|
// }
|
||||||
|
|
||||||
std::pair<size_t, size_t> get_end_position() const {
|
// std::pair<size_t, size_t> get_end_position() const {
|
||||||
if (undefined_) {
|
// if (undefined_) {
|
||||||
error_handling::handle_general_error(
|
// error_handling::handle_general_error(
|
||||||
"Get end position from undefined node");
|
// "Get end position from undefined node");
|
||||||
}
|
// }
|
||||||
return end_position_;
|
// return end_position_;
|
||||||
}
|
// }
|
||||||
|
|
||||||
protected:
|
// protected:
|
||||||
bool undefined_ = false;
|
// bool undefined_ = false;
|
||||||
|
|
||||||
std::pair<size_t, size_t> start_position_ = {0, 0};
|
// 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> end_position_ = {0, 0};
|
||||||
};
|
// };
|
||||||
|
|
||||||
struct unit {};
|
struct unit {};
|
||||||
struct null {};
|
struct null {};
|
||||||
|
|
@ -194,162 +194,121 @@ struct unicode {
|
||||||
std::string ch;
|
std::string ch;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Literal : public Node {
|
struct Literal {
|
||||||
public:
|
public:
|
||||||
using Type =
|
using Type =
|
||||||
std::variant<float, double, int32_t, int64_t, size_t, std::string,
|
std::variant<float, double, int32_t, int64_t, size_t, std::string,
|
||||||
unicode_string, char, unicode, bool, unit, null>;
|
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() {
|
template <typename T> std::optional<T *> get() {
|
||||||
if (std::holds_alternative<T>(value_)) {
|
if (std::holds_alternative<T>(value)) {
|
||||||
return &std::get<T>(value_);
|
return &std::get<T>(value);
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> std::optional<const T *> get() const {
|
template <typename T> std::optional<const T *> get() const {
|
||||||
if (std::holds_alternative<T>(value_)) {
|
if (std::holds_alternative<T>(value)) {
|
||||||
return &std::get<T>(value_);
|
return &std::get<T>(value);
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type &get_any() { return value_; }
|
//
|
||||||
|
|
||||||
const Type &get_any() const { return value_; }
|
Type value;
|
||||||
|
|
||||||
private:
|
|
||||||
Type value_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Identifier : public Node {
|
// TODO: merge with identifier ??
|
||||||
public:
|
struct Annotation {
|
||||||
static constexpr char NAME_DELIMITER = '.';
|
auto operator<=>(const Annotation &other) const = default;
|
||||||
|
|
||||||
enum IdentifierType {
|
std::string value;
|
||||||
SIMPLE_NAME,
|
};
|
||||||
SIMPLE_TYPE,
|
|
||||||
TYPECLASS,
|
struct Identifier {
|
||||||
ARGUMENT_NAME,
|
public:
|
||||||
ARGUMENT_TYPE,
|
static constexpr char kNameDelimiter = '.';
|
||||||
|
|
||||||
|
enum Kind {
|
||||||
|
kSimpleName,
|
||||||
|
kSimpleType,
|
||||||
|
kTypeclass,
|
||||||
|
kArgName,
|
||||||
|
kArgType,
|
||||||
// ANNOTATION, used as std::string
|
// ANNOTATION, used as std::string
|
||||||
OPERATOR,
|
kOperator,
|
||||||
PLACEHOLDER,
|
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)
|
auto operator<=>(const Identifier &other) const = default;
|
||||||
: Node(node), type_(type), value_(value) {}
|
|
||||||
|
|
||||||
IdentifierType get_type() const { return type_; }
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
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) {
|
// void append_before(
|
||||||
value_ = name + NAME_DELIMITER + value_;
|
// 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(
|
// void append_after(const std::string &name) {
|
||||||
const Identifier &identifier,
|
// value_ += NAME_DELIMITER + name;
|
||||||
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) {
|
// void append_after(
|
||||||
value_ += NAME_DELIMITER + name;
|
// 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(
|
// std::vector<Identifier> get_fragments() const {
|
||||||
const Identifier &identifier,
|
// std::vector<Identifier> fragments;
|
||||||
std::source_location location = std::source_location::current()) {
|
// for (auto &&fragment_name :
|
||||||
error_handling::expect(identifier.type_ == type_,
|
// std::ranges::views::split(value_, NAME_DELIMITER)) {
|
||||||
"different Identifier types on append_after",
|
// fragments.emplace_back(
|
||||||
location);
|
// *this, type_,
|
||||||
value_ += NAME_DELIMITER + *identifier.get();
|
// std::string(fragment_name.begin(), fragment_name.end()));
|
||||||
}
|
// }
|
||||||
|
// return fragments;
|
||||||
|
// }
|
||||||
|
|
||||||
std::vector<Identifier> get_fragments() const {
|
// std::pair<Identifier, Identifier> split_first() {
|
||||||
std::vector<Identifier> fragments;
|
// const auto pos = value_.find(NAME_DELIMITER);
|
||||||
for (auto &&fragment_name :
|
// if (pos == std::string::npos) {
|
||||||
std::ranges::views::split(value_, NAME_DELIMITER)) {
|
// return {Identifier(*this, type_, ""), *this};
|
||||||
fragments.emplace_back(
|
// }
|
||||||
*this, type_,
|
// return {
|
||||||
std::string(fragment_name.begin(), fragment_name.end()));
|
// Identifier(*this, type_, value_.substr(0, pos)),
|
||||||
}
|
// Identifier(*this, type_, value_.substr(pos + 1))}; // '.' is leaved
|
||||||
return fragments;
|
// out
|
||||||
}
|
// }
|
||||||
|
|
||||||
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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Extra : public Node {
|
struct Extra {
|
||||||
public:
|
std::string content;
|
||||||
Extra(Node node, std::string &&content)
|
|
||||||
: Node(node), content_(std::move(content)) {}
|
|
||||||
|
|
||||||
Extra(Node node, const std::string &content)
|
|
||||||
: Node(node), content_(content) {}
|
|
||||||
|
|
||||||
std::string *content() { return &content_; }
|
|
||||||
|
|
||||||
const std::string *content() const { return &content_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string content_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class EmptyLines : public Node {
|
struct EmptyLines {
|
||||||
public:
|
size_t count;
|
||||||
EmptyLines(Node node, size_t line_count)
|
|
||||||
: Node(node), line_count_(line_count) {}
|
|
||||||
|
|
||||||
size_t line_count() const { return line_count_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
size_t line_count_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace nodes
|
} // namespace nodes
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "basic_nodes.hpp"
|
#include "basic_nodes.hpp"
|
||||||
|
#include "storage.hpp"
|
||||||
#include "type_nodes.hpp"
|
#include "type_nodes.hpp"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
@ -9,504 +10,190 @@
|
||||||
|
|
||||||
namespace nodes {
|
namespace nodes {
|
||||||
|
|
||||||
class TypedNode : public Node {
|
using NodeId = storage::Id;
|
||||||
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_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ExprData;
|
class ExprData;
|
||||||
class ExprStorage;
|
|
||||||
|
|
||||||
class Expr {
|
// TODO: add to all nodes
|
||||||
friend ExprStorage;
|
struct GeneralInfo {
|
||||||
|
bool is_scoped;
|
||||||
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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace utils {
|
// namespace utils {
|
||||||
|
|
||||||
inline std::optional<nodes::ExprData *>
|
// inline std::optional<nodes::ExprData *>
|
||||||
proxy_to_expr_optional(std::optional<nodes::Expr> &proxy) {
|
// proxy_to_expr_optional(std::optional<nodes::Expr> &proxy) {
|
||||||
if (proxy.has_value()) {
|
// if (proxy.has_value()) {
|
||||||
return proxy.value().get();
|
// return proxy.value().get();
|
||||||
}
|
// }
|
||||||
return std::nullopt;
|
// return std::nullopt;
|
||||||
}
|
// }
|
||||||
|
|
||||||
inline std::optional<const nodes::ExprData *>
|
// inline std::optional<const nodes::ExprData *>
|
||||||
proxy_to_expr_optional(const std::optional<nodes::Expr> &proxy) {
|
// proxy_to_expr_optional(const std::optional<nodes::Expr> &proxy) {
|
||||||
if (proxy.has_value()) {
|
// if (proxy.has_value()) {
|
||||||
return proxy.value().get();
|
// return proxy.value().get();
|
||||||
}
|
// }
|
||||||
return std::nullopt;
|
// return std::nullopt;
|
||||||
}
|
// }
|
||||||
|
|
||||||
} // namespace utils
|
// } // namespace utils
|
||||||
|
|
||||||
// --- flow control
|
// --- flow control
|
||||||
|
|
||||||
class Match : public TypedNode {
|
struct Match {
|
||||||
public:
|
struct Case {
|
||||||
class Case : public TypedNode {
|
enum Kind {
|
||||||
public:
|
|
||||||
enum CaseType {
|
|
||||||
PATTERN_VALUE,
|
PATTERN_VALUE,
|
||||||
VALUE_PATTERN,
|
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_; }
|
Kind kind;
|
||||||
|
NodeId value;
|
||||||
ExprData *get_value() { return value_.get(); }
|
std::optional<NodeId> condition;
|
||||||
|
std::optional<NodeId> expr;
|
||||||
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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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)
|
NodeId value;
|
||||||
: TypedNode(node), value_(value), cases_(cases) {}
|
std::vector<NodeId /*Case*/> 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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Condition : public Node {
|
struct Condition {
|
||||||
public:
|
std::vector<std::pair<NodeId, NodeId>> cases;
|
||||||
Condition(Node node, std::vector<std::pair<Expr, Expr>> &&cases,
|
std::optional<NodeId> else_case;
|
||||||
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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Loop : public TypedNode {
|
// TODO: prittier constructors
|
||||||
|
struct Loop {
|
||||||
public:
|
public:
|
||||||
enum LoopType {
|
enum Kind {
|
||||||
LOOP,
|
LOOP,
|
||||||
WHILE,
|
WHILE,
|
||||||
FOR,
|
FOR,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
// LOOP
|
// LOOP
|
||||||
Loop(Node node, Expr expression)
|
Loop(NodeId expr) : kind(LOOP), expr(expr) {}
|
||||||
: TypedNode(node), loop_type_(LOOP), expression_(expression) {}
|
|
||||||
|
|
||||||
// WHILE
|
// WHILE
|
||||||
Loop(Node node, Expr condition, Expr expression)
|
Loop(NodeId condition, NodeId expr)
|
||||||
: TypedNode(node), loop_type_(WHILE), expression_(expression),
|
: kind(WHILE), expr(expr), condition(condition) {}
|
||||||
condition_(condition) {}
|
|
||||||
|
|
||||||
// FOR
|
// FOR
|
||||||
Loop(Node node, Expr variable, Expr interval, Expr expression)
|
Loop(NodeId variable, NodeId interval, NodeId expr)
|
||||||
: TypedNode(node), loop_type_(FOR), expression_(expression),
|
: kind(FOR), expr(expr), variable(variable), interval(interval) {}
|
||||||
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<NodeId> condition;
|
||||||
|
std::optional<NodeId> variable;
|
||||||
std::optional<ExprData *> get_condition() {
|
std::optional<NodeId> interval;
|
||||||
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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- containers
|
// --- containers
|
||||||
|
|
||||||
class Container : public TypedNode {
|
struct Container {
|
||||||
public:
|
enum Kind {
|
||||||
enum ContainerType {
|
|
||||||
BLOCK,
|
BLOCK,
|
||||||
ARRAY,
|
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)
|
Kind kind;
|
||||||
: TypedNode(node), container_type_(type), expressions_(expressions) {}
|
std::vector<NodeId> exprs;
|
||||||
|
|
||||||
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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- modifiers
|
// --- modifiers
|
||||||
|
|
||||||
class Return : public Node {
|
struct Return {
|
||||||
public:
|
enum Kind {
|
||||||
enum ReturnType {
|
|
||||||
RETURN,
|
RETURN,
|
||||||
BRING,
|
BRING,
|
||||||
};
|
};
|
||||||
|
|
||||||
Return(Node node, ReturnType type, Expr expression)
|
//
|
||||||
: Node(node), return_type_(type), expression_(expression) {}
|
|
||||||
|
|
||||||
ReturnType get_type() const { return return_type_; }
|
Kind kind;
|
||||||
|
NodeId expr;
|
||||||
ExprData *get_expression() { return expression_.get(); }
|
|
||||||
|
|
||||||
const ExprData *get_expression() const { return expression_.get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
ReturnType return_type_;
|
|
||||||
|
|
||||||
Expr expression_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NameDefinition : public TypedNode {
|
struct NameDefinition {
|
||||||
public:
|
enum Kind {
|
||||||
enum Modifier {
|
|
||||||
LET, // %
|
LET, // %
|
||||||
VAR, // $
|
VAR, // $
|
||||||
};
|
};
|
||||||
|
|
||||||
NameDefinition(Node node, Modifier modifier, Identifier &&name)
|
//
|
||||||
: TypedNode(node), modifier_(modifier), name_(std::move(name)) {}
|
|
||||||
|
|
||||||
NameDefinition(Node node, Modifier modifier, const Identifier &name)
|
Kind kind;
|
||||||
: TypedNode(node), modifier_(modifier), name_(name) {}
|
Identifier name;
|
||||||
|
|
||||||
Modifier get_modifier() const { return modifier_; }
|
|
||||||
|
|
||||||
Identifier *get_name() { return &name_; }
|
|
||||||
|
|
||||||
const Identifier *get_name() const { return &name_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Modifier modifier_;
|
|
||||||
|
|
||||||
Identifier name_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Access : public TypedNode {
|
struct Access {
|
||||||
public:
|
enum Kind {
|
||||||
enum AccessType {
|
|
||||||
ARRAY,
|
ARRAY,
|
||||||
TUPLE, // only number literal index allowed
|
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(); }
|
NodeId value;
|
||||||
|
NodeId index;
|
||||||
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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class LoopControl : public TypedNode {
|
struct LoopControl {
|
||||||
public:
|
enum Kind {
|
||||||
enum LoopControlType {
|
|
||||||
BREAK,
|
BREAK,
|
||||||
CONTINUE,
|
CONTINUE,
|
||||||
};
|
};
|
||||||
|
|
||||||
LoopControl(Node node, LoopControlType type)
|
//
|
||||||
: TypedNode(node), loop_control_type_(type) {}
|
|
||||||
|
|
||||||
LoopControlType get_type() const { return loop_control_type_; }
|
Kind kind;
|
||||||
|
|
||||||
private:
|
|
||||||
LoopControlType loop_control_type_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ModifierExpression : public TypedNode {
|
struct ModifierExpression {
|
||||||
public:
|
Modifier modifier;
|
||||||
ModifierExpression(Node node, Modifier modifier, Expr expression)
|
NodeId expr;
|
||||||
: 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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- other
|
// --- other
|
||||||
|
|
||||||
using AnnotatedArgument = std::pair<std::optional<std::string>, Expr>;
|
using AnnotatedArgument = std::pair<std::optional<std::string>, NodeId>;
|
||||||
|
|
||||||
class NameExpression : public TypedNode {
|
struct NameExpression {
|
||||||
public:
|
Identifier name;
|
||||||
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_;
|
|
||||||
// universal function call syntax
|
// universal function call syntax
|
||||||
std::vector<AnnotatedArgument> args_;
|
std::vector<AnnotatedArgument> args = {};
|
||||||
std::optional<Type> prefix_;
|
std::optional<Type> prefix = {};
|
||||||
// for static methods
|
// for static methods
|
||||||
bool is_point_call_ = false; // x.f ... or f x ...
|
bool is_point_call = false; // x.f ... or f x ...
|
||||||
bool is_operator_call_ = false; // ... operator ...
|
bool is_operator_call = false; // ... operator ...
|
||||||
};
|
};
|
||||||
|
|
||||||
class Constructor : public TypedNode {
|
struct Constructor {
|
||||||
public:
|
Type type;
|
||||||
Constructor(Node node, Type type, std::vector<AnnotatedArgument> &&args)
|
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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Lambda : public TypedNode {
|
struct Lambda {
|
||||||
public:
|
std::vector<Identifier> args;
|
||||||
Lambda(Node node, std::vector<Identifier> &&args, Expr expression)
|
NodeId expr;
|
||||||
: 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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExprData : public Node {
|
class ExprData {
|
||||||
public:
|
public:
|
||||||
using Type = std::variant<
|
using Type = std::variant<
|
||||||
// --- flow control
|
// --- flow control
|
||||||
|
|
@ -542,9 +229,8 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
ExprData(Node node, T &&expression, bool is_scoped)
|
ExprData(T &&expression, bool is_scoped)
|
||||||
: Node(node), expression_(std::forward<T>(expression)),
|
: expression_(std::forward<T>(expression)), is_scoped_(is_scoped) {}
|
||||||
is_scoped_(is_scoped) {}
|
|
||||||
|
|
||||||
template <typename T> std::optional<T *> get() {
|
template <typename T> std::optional<T *> get() {
|
||||||
if (std::holds_alternative<T>(expression_)) {
|
if (std::holds_alternative<T>(expression_)) {
|
||||||
|
|
@ -572,22 +258,22 @@ private:
|
||||||
bool is_scoped_ = false;
|
bool is_scoped_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExprStorage {
|
// class ExprStorage {
|
||||||
friend Expr;
|
// friend Expr;
|
||||||
|
|
||||||
public:
|
// public:
|
||||||
Expr add_expr(ExprData expression) {
|
// Expr add_expr(ExprData expression) {
|
||||||
storage_.push_back(std::move(expression));
|
// storage_.push_back(std::move(expression));
|
||||||
return Expr(*this, storage_.size() - 1);
|
// return Expr(*this, storage_.size() - 1);
|
||||||
}
|
// }
|
||||||
|
|
||||||
private:
|
// private:
|
||||||
ExprData *get_expr(size_t id) { return &storage_.at(id); }
|
// 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:
|
// private:
|
||||||
std::vector<ExprData> storage_;
|
// std::vector<ExprData> storage_;
|
||||||
};
|
// };
|
||||||
|
|
||||||
} // namespace nodes
|
} // namespace nodes
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,38 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "expression_nodes.hpp"
|
||||||
#include "storage.hpp"
|
#include "storage.hpp"
|
||||||
|
|
||||||
namespace nodes {
|
namespace nodes {
|
||||||
|
|
||||||
// FIXME
|
template <typename... Mixins> class Node_;
|
||||||
struct NodeData {
|
|
||||||
std::variant<int, bool> value;
|
struct NodeData {
|
||||||
}; // TODO: union with nodes
|
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> {
|
class NodeStorage : public core::Storage<NodeData> {
|
||||||
using Id = storage::Id;
|
using Id = storage::Id;
|
||||||
|
|
||||||
|
|
@ -36,7 +59,7 @@ protected:
|
||||||
core::DependentStorage<T> &data_;
|
core::DependentStorage<T> &data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: replace all nodes
|
// FIXME: rename
|
||||||
// Mixins should be NodePart<...> or their children
|
// Mixins should be NodePart<...> or their children
|
||||||
template <typename... Mixins> class Node_ : public Mixins... {
|
template <typename... Mixins> class Node_ : public Mixins... {
|
||||||
using Id = storage::Id;
|
using Id = storage::Id;
|
||||||
|
|
@ -45,9 +68,13 @@ public:
|
||||||
Node_(Id id, NodeStorage &data, Mixins &&...mixins)
|
Node_(Id id, NodeStorage &data, Mixins &&...mixins)
|
||||||
: Mixins(std::move(mixins))..., id_(id), data_(data) {}
|
: 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); }
|
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_]; }
|
const NodeData &operator*() const { return data_[id_]; }
|
||||||
|
|
|
||||||
|
|
@ -27,54 +27,17 @@ enum class CombineResult {
|
||||||
};
|
};
|
||||||
|
|
||||||
// IN PROGRESS: add another constructors ??
|
// IN PROGRESS: add another constructors ??
|
||||||
class Import : public Node {
|
struct Import {
|
||||||
public:
|
Identifier import_name;
|
||||||
Import(Node node, const Identifier &import_name,
|
Identifier module_name;
|
||||||
const Identifier &module_name, std::vector<Identifier> &&symbols = {})
|
std::vector<Identifier> symbols;
|
||||||
: Node(node), import_name_(import_name), module_name_(module_name),
|
|
||||||
symbols_(std::move(symbols)) {}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
Identifier *get_import_name() { return &import_name_; }
|
|
||||||
|
|
||||||
const Identifier *get_import_name() const { return &import_name_; }
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
Identifier *get_module_name() { return &module_name_; }
|
|
||||||
|
|
||||||
const Identifier *get_module_name() const { return &module_name_; }
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
size_t symbols_size() const { return symbols_.size(); }
|
|
||||||
|
|
||||||
Identifier *get_symbol(size_t id) { return &symbols_.at(id); }
|
|
||||||
|
|
||||||
const Identifier *get_symbol(size_t id) const { return &symbols_.at(id); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Identifier import_name_;
|
|
||||||
Identifier module_name_;
|
|
||||||
std::vector<Identifier> symbols_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Constraint : public Node {
|
struct Constraint {
|
||||||
public:
|
NodeId expr;
|
||||||
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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FunctionDefinition : public Node {
|
struct FunctionDefinition {
|
||||||
public:
|
|
||||||
class Argument {
|
class Argument {
|
||||||
public:
|
public:
|
||||||
Argument(const std::optional<std::string> &annotation, Identifier &&name,
|
Argument(const std::optional<std::string> &annotation, Identifier &&name,
|
||||||
|
|
@ -242,151 +205,43 @@ public:
|
||||||
Modifier::NONE; // optional, result, none // sync with type
|
Modifier::NONE; // optional, result, none // sync with type
|
||||||
};
|
};
|
||||||
|
|
||||||
FunctionDefinition(Node node, SymbolDocs &&docs,
|
FunctionDefinition(SymbolDocs &&docs, std::vector<Constraint> &&constraints,
|
||||||
std::vector<Constraint> &&constraints,
|
|
||||||
Modifier return_modifier, bool is_method,
|
Modifier return_modifier, bool is_method,
|
||||||
const std::optional<Identifier> &name_prefix,
|
const std::optional<Identifier> &name_prefix,
|
||||||
const Identifier &name, std::vector<Argument> &&args,
|
const Identifier &name, std::vector<Argument> &&args,
|
||||||
bool are_annotations_same_to_names,
|
bool are_annotations_same_to_names,
|
||||||
std::optional<Expr> expression)
|
std::optional<NodeId> expr)
|
||||||
: Node(node), docs_(std::move(docs)),
|
: docs(std::move(docs)), constraints(std::move(constraints)),
|
||||||
constraints_(std::move(constraints)), return_modifier_(return_modifier),
|
return_modifier(return_modifier), is_method(is_method), name(name),
|
||||||
is_method_(is_method), name_(name), full_name_(name),
|
full_name(name), args(std::move(args)),
|
||||||
args_(std::move(args)),
|
are_annotations_same_to_names(are_annotations_same_to_names),
|
||||||
are_annotations_same_to_names_(are_annotations_same_to_names),
|
expr(expr) {
|
||||||
expression_(expression) {
|
|
||||||
if (name_prefix.has_value()) {
|
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;
|
bool is_same_to(const FunctionDefinition &other) const;
|
||||||
|
|
||||||
CombineResult combine(FunctionDefinition &&other);
|
CombineResult combine(FunctionDefinition &&other);
|
||||||
|
|
||||||
private:
|
//
|
||||||
SymbolDocs docs_;
|
|
||||||
std::vector<Constraint> constraints_;
|
SymbolDocs docs;
|
||||||
Modifier return_modifier_;
|
std::vector<Constraint> constraints;
|
||||||
bool is_method_;
|
Modifier return_modifier;
|
||||||
Identifier name_;
|
bool is_method;
|
||||||
Identifier full_name_;
|
Identifier name;
|
||||||
std::vector<Argument> args_;
|
Identifier full_name;
|
||||||
bool are_annotations_same_to_names_; // needed for easier prinitng process
|
std::vector<Argument> args;
|
||||||
std::optional<Expr> expression_;
|
bool are_annotations_same_to_names; // needed for easier prinitng process
|
||||||
|
std::optional<NodeId> expr;
|
||||||
}; // refactor ??
|
}; // refactor ??
|
||||||
|
|
||||||
class TypeDefinition : public Node {
|
struct TypeDefinition {
|
||||||
public:
|
bool is_typeclass() { return name.kind == Identifier::kTypeclass; }
|
||||||
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; }
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
@ -394,53 +249,44 @@ public:
|
||||||
|
|
||||||
CombineResult combine(TypeDefinition &&other);
|
CombineResult combine(TypeDefinition &&other);
|
||||||
|
|
||||||
private:
|
//
|
||||||
SymbolDocs docs_;
|
|
||||||
bool is_on_heap_;
|
SymbolDocs docs;
|
||||||
Identifier name_;
|
bool is_on_heap;
|
||||||
std::vector<Identifier> typeclasses_;
|
Identifier name;
|
||||||
std::vector<Identifier> args_;
|
std::vector<Identifier> typeclasses;
|
||||||
std::optional<Type> type_;
|
std::vector<Identifier> args;
|
||||||
|
std::optional<Type> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Statement : public Node {
|
struct Statement {
|
||||||
public:
|
public:
|
||||||
using Type = std::variant<Import, TypeDefinition, FunctionDefinition, Extra,
|
using Type = std::variant<Import, TypeDefinition, FunctionDefinition, Extra,
|
||||||
EmptyLines>;
|
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() {
|
template <typename T> std::optional<T *> get() {
|
||||||
if (std::holds_alternative<T>(expr_)) {
|
if (std::holds_alternative<T>(expr)) {
|
||||||
return &std::get<T>(expr_);
|
return &std::get<T>(expr);
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> std::optional<const T *> get() const {
|
template <typename T> std::optional<const T *> get() const {
|
||||||
if (std::holds_alternative<T>(expr_)) {
|
if (std::holds_alternative<T>(expr)) {
|
||||||
return &std::get<T>(expr_);
|
return &std::get<T>(expr);
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type &get_any() { return expr_; }
|
|
||||||
|
|
||||||
const Type &get_any() const { return expr_; }
|
|
||||||
|
|
||||||
bool is_same_to(const Statement &other) const;
|
bool is_same_to(const Statement &other) const;
|
||||||
|
|
||||||
CombineResult combine(Statement &&other);
|
CombineResult combine(Statement &&other);
|
||||||
|
|
||||||
private:
|
//
|
||||||
Type expr_;
|
|
||||||
|
Type expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace nodes
|
} // 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 {
|
bool operator<(const TypeData &other) const {
|
||||||
if (name_ != other.name_) {
|
if (name_ != other.name_) {
|
||||||
return *name_.get() < *other.name_.get();
|
return name_.value < other.name_.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modifier_ != other.modifier_) {
|
if (modifier_ != other.modifier_) {
|
||||||
|
|
@ -220,7 +220,7 @@ public:
|
||||||
|
|
||||||
// is parameters count check necessary ??
|
// is parameters count check necessary ??
|
||||||
builtin::Type to_builtin() const {
|
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 =
|
auto builtin_type_parameters_count =
|
||||||
builtin::types::get_parameters_count(builtin_type);
|
builtin::types::get_parameters_count(builtin_type);
|
||||||
|
|
@ -249,12 +249,12 @@ class TypeStorage {
|
||||||
public:
|
public:
|
||||||
Type primitive(builtin::Type type);
|
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,
|
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);
|
nodes::Type add_modification_of(Type type, Modifier modifier);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,3 @@
|
||||||
#include "expression_nodes.hpp"
|
#include "expression_nodes.hpp"
|
||||||
|
|
||||||
namespace nodes {
|
namespace nodes {}; // namespace nodes
|
||||||
|
|
||||||
ExprData *Expr::get() { return expression_storage_->get_expr(id_); }
|
|
||||||
|
|
||||||
const ExprData *Expr::get() const { return expression_storage_->get_expr(id_); }
|
|
||||||
|
|
||||||
}; // namespace nodes
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "statement_nodes.hpp"
|
#include "statement_nodes.hpp"
|
||||||
|
|
||||||
|
// #include "error_handling.hpp"
|
||||||
#include "error_handling.hpp"
|
#include "error_handling.hpp"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
@ -7,7 +8,7 @@
|
||||||
namespace nodes {
|
namespace nodes {
|
||||||
|
|
||||||
bool FunctionDefinition::is_same_to(const FunctionDefinition &other) const {
|
bool FunctionDefinition::is_same_to(const FunctionDefinition &other) const {
|
||||||
if (name_ != other.name_) {
|
if (name != other.name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -21,96 +22,95 @@ bool FunctionDefinition::is_same_to(const FunctionDefinition &other) const {
|
||||||
// name 'arg1 'arg2 -> 'arg3 = ... // function definition (without types)
|
// name 'arg1 'arg2 -> 'arg3 = ... // function definition (without types)
|
||||||
CombineResult FunctionDefinition::combine(FunctionDefinition &&other) {
|
CombineResult FunctionDefinition::combine(FunctionDefinition &&other) {
|
||||||
// names should be the same
|
// names should be the same
|
||||||
if (name_ != other.name_) {
|
if (name != other.name) {
|
||||||
return CombineResult::DIFFERENT_NAME_ERROR;
|
return CombineResult::DIFFERENT_NAME_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// modifiers should be the same
|
// modifiers should be the same
|
||||||
if (return_modifier_ != other.return_modifier_) {
|
if (return_modifier != other.return_modifier) {
|
||||||
return CombineResult::DIFFERNENT_MODIFIER_ERROR;
|
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 ??
|
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;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only one definition should have constraints
|
// 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;
|
return CombineResult::MORE_THEN_ONE_CONSTRAINTS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only one definition should have expression (body)
|
// 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;
|
return CombineResult::MORE_THEN_ONE_DEFINITION_BODY_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only one definition should have documentation
|
// only one definition should have documentation
|
||||||
if (docs_.get_description().has_value() &&
|
if (docs.get_description().has_value() &&
|
||||||
other.docs_.get_description().has_value()) {
|
other.docs.get_description().has_value()) {
|
||||||
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
|
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
|
||||||
}
|
}
|
||||||
if (docs_.annotations_info_size() > 0 &&
|
if (docs.annotations_info_size() > 0 &&
|
||||||
other.docs_.annotations_info_size() > 0) {
|
other.docs.annotations_info_size() > 0) {
|
||||||
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
|
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check, that function definitions have same named args
|
// check, that function definitions have same named args
|
||||||
for (size_t i = 0; i < std::max(args_.size(), other.args_.size()); ++i) {
|
for (size_t i = 0; i < std::max(args.size(), other.args.size()); ++i) {
|
||||||
if (i < args_.size() && i < other.args_.size()) {
|
if (i < args.size() && i < other.args.size()) {
|
||||||
|
|
||||||
// annotations should be the same
|
// annotations should be the same
|
||||||
if ((!args_[i].get_annotation().has_value() &&
|
if ((!args[i].get_annotation().has_value() &&
|
||||||
!other.args_[i].get_annotation().has_value()) ||
|
!other.args[i].get_annotation().has_value()) ||
|
||||||
(args_[i].get_annotation().has_value() &&
|
(args[i].get_annotation().has_value() &&
|
||||||
other.args_[i].get_annotation().has_value() &&
|
other.args[i].get_annotation().has_value() &&
|
||||||
*args_[i].get_annotation().value() !=
|
*args[i].get_annotation().value() !=
|
||||||
*other.args_[i].get_annotation().value())) {
|
*other.args[i].get_annotation().value())) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// argument names should be the same
|
// argument names should be the same
|
||||||
if ((!args_[i].get_name().has_value() &&
|
if ((!args[i].get_name().has_value() &&
|
||||||
!other.args_[i].get_name().has_value()) ||
|
!other.args[i].get_name().has_value()) ||
|
||||||
(args_[i].get_name().has_value() &&
|
(args[i].get_name().has_value() &&
|
||||||
other.args_[i].get_name().has_value() &&
|
other.args[i].get_name().has_value() &&
|
||||||
args_[i].get_name().value() != other.args_[i].get_name().value())) {
|
args[i].get_name().value() != other.args[i].get_name().value())) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// types should be the same (if present in both definitions)
|
// types should be the same (if present in both definitions)
|
||||||
if (args_[i].get_type().has_value() &&
|
if (args[i].get_type().has_value() &&
|
||||||
other.args_[i].get_type().has_value() &&
|
other.args[i].get_type().has_value() &&
|
||||||
*args_[i].get_type().value() != *other.args_[i].get_type().value()) {
|
*args[i].get_type().value() != *other.args[i].get_type().value()) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// argument modifiers should be the same
|
// argument modifiers should be the same
|
||||||
if (args_[i].get_before_modifier() !=
|
if (args[i].get_before_modifier() !=
|
||||||
other.args_[i].get_before_modifier() ||
|
other.args[i].get_before_modifier() ||
|
||||||
args_[i].get_after_modifier() !=
|
args[i].get_after_modifier() != other.args[i].get_after_modifier()) {
|
||||||
other.args_[i].get_after_modifier()) {
|
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
} else if (i < args_.size()) {
|
} else if (i < args.size()) {
|
||||||
// annotations should be the same
|
// annotations should be the same
|
||||||
if (args_[i].get_annotation().has_value()) {
|
if (args[i].get_annotation().has_value()) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// names should be the same
|
// names should be the same
|
||||||
if (args_[i].get_name().has_value()) {
|
if (args[i].get_name().has_value()) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
} else { // i < other_function_definition.size()
|
} else { // i < other_function_definition.size()
|
||||||
// annotations should be the same
|
// 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;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// names should be the same
|
// 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;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -118,28 +118,28 @@ CombineResult FunctionDefinition::combine(FunctionDefinition &&other) {
|
||||||
|
|
||||||
// combine docs
|
// combine docs
|
||||||
// all docs should be in one definition
|
// all docs should be in one definition
|
||||||
if (other.docs_.get_description().has_value() ||
|
if (other.docs.get_description().has_value() ||
|
||||||
other.docs_.annotations_info_size() > 0) {
|
other.docs.annotations_info_size() > 0) {
|
||||||
if (docs_.annotations_info_size() > 0 ||
|
if (docs.annotations_info_size() > 0 ||
|
||||||
docs_.get_description().has_value()) {
|
docs.get_description().has_value()) {
|
||||||
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
|
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
docs_ = std::move(other.docs_);
|
docs = std::move(other.docs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!other.constraints_.empty()) {
|
if (!other.constraints.empty()) {
|
||||||
constraints_ = std::move(other.constraints_);
|
constraints = std::move(other.constraints);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other.expression_.has_value()) {
|
if (other.expr.has_value()) {
|
||||||
expression_ = other.expression_;
|
expr = other.expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < other.args_.size(); ++i) {
|
for (size_t i = 0; i < other.args.size(); ++i) {
|
||||||
if (i < args_.size()) {
|
if (i < args.size()) {
|
||||||
if (other.args_[i].get_type().has_value()) {
|
if (other.args[i].get_type().has_value()) {
|
||||||
if (args_[i].update_type_from(other.args_[i])) {
|
if (args[i].update_type_from(other.args[i])) {
|
||||||
error_handling::handle_internal_error(
|
error_handling::handle_internal_error(
|
||||||
"Function arguments are not properly checked before merging "
|
"Function arguments are not properly checked before merging "
|
||||||
"during combination",
|
"during combination",
|
||||||
|
|
@ -147,7 +147,7 @@ CombineResult FunctionDefinition::combine(FunctionDefinition &&other) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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 {
|
bool TypeDefinition::is_same_to(const TypeDefinition &other) const {
|
||||||
if (name_ != other.name_) {
|
if (name != other.name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -167,83 +167,83 @@ bool TypeDefinition::is_same_to(const TypeDefinition &other) const {
|
||||||
// Type[...] 'A 'B 'C = ... // define type
|
// Type[...] 'A 'B 'C = ... // define type
|
||||||
CombineResult TypeDefinition::combine(TypeDefinition &&other) {
|
CombineResult TypeDefinition::combine(TypeDefinition &&other) {
|
||||||
// name should be same
|
// name should be same
|
||||||
if (name_ != other.name_) {
|
if (name != other.name) {
|
||||||
return CombineResult::DIFFERENT_NAME_ERROR;
|
return CombineResult::DIFFERENT_NAME_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// modifier should be the same
|
// 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;
|
return CombineResult::DIFFERNENT_MODIFIER_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// typeclasses should be the same
|
// typeclasses should be the same
|
||||||
if (typeclasses_.size() != other.typeclasses_.size()) {
|
if (typeclasses.size() != other.typeclasses.size()) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < typeclasses_.size(); ++i) {
|
for (size_t i = 0; i < typeclasses.size(); ++i) {
|
||||||
if (typeclasses_[i] != other.typeclasses_[i]) {
|
if (typeclasses[i] != other.typeclasses[i]) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// args should be the same
|
// args should be the same
|
||||||
if (args_.size() != other.args_.size()) {
|
if (args.size() != other.args.size()) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < args_.size(); ++i) {
|
for (size_t i = 0; i < args.size(); ++i) {
|
||||||
if (args_[i] != other.args_[i]) {
|
if (args[i] != other.args[i]) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// only one definition should have documentation
|
// only one definition should have documentation
|
||||||
if (docs_.get_description().has_value() &&
|
if (docs.get_description().has_value() &&
|
||||||
other.docs_.get_description().has_value()) {
|
other.docs.get_description().has_value()) {
|
||||||
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
|
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
|
||||||
}
|
}
|
||||||
if (docs_.annotations_info_size() > 0 &&
|
if (docs.annotations_info_size() > 0 &&
|
||||||
other.docs_.annotations_info_size() > 0) {
|
other.docs.annotations_info_size() > 0) {
|
||||||
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
|
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only one type should define type / body
|
// 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;
|
return CombineResult::MORE_THEN_ONE_DEFINITION_BODY_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// combine docs
|
// combine docs
|
||||||
// all docs should be in one definition
|
// all docs should be in one definition
|
||||||
if (other.docs_.get_description().has_value() ||
|
if (other.docs.get_description().has_value() ||
|
||||||
other.docs_.annotations_info_size() > 0) {
|
other.docs.annotations_info_size() > 0) {
|
||||||
if (docs_.annotations_info_size() > 0 ||
|
if (docs.annotations_info_size() > 0 ||
|
||||||
docs_.get_description().has_value()) {
|
docs.get_description().has_value()) {
|
||||||
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
|
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
docs_ = std::move(other.docs_);
|
docs = std::move(other.docs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other.type_.has_value()) {
|
if (other.type.has_value()) {
|
||||||
type_ = std::move(other.type_);
|
type = std::move(other.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CombineResult::OK;
|
return CombineResult::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Statement::is_same_to(const Statement &other) const {
|
bool Statement::is_same_to(const Statement &other) const {
|
||||||
if (expr_.index() != other.expr_.index()) {
|
if (expr.index() != other.expr.index()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (expr_.index()) {
|
switch (expr.index()) {
|
||||||
case 0: // Import
|
case 0: // Import
|
||||||
return false;
|
return false;
|
||||||
case 1: // TypeDefinition
|
case 1: // TypeDefinition
|
||||||
return std::get<TypeDefinition>(expr_).is_same_to(
|
return std::get<TypeDefinition>(expr).is_same_to(
|
||||||
std::move(std::get<TypeDefinition>(other.expr_)));
|
std::move(std::get<TypeDefinition>(other.expr)));
|
||||||
case 2: // FunctionDefinition
|
case 2: // FunctionDefinition
|
||||||
return std::get<FunctionDefinition>(expr_).is_same_to(
|
return std::get<FunctionDefinition>(expr).is_same_to(
|
||||||
std::move(std::get<FunctionDefinition>(other.expr_)));
|
std::move(std::get<FunctionDefinition>(other.expr)));
|
||||||
case 3: // Extra
|
case 3: // Extra
|
||||||
return false;
|
return false;
|
||||||
case 4: // EmptyLines
|
case 4: // EmptyLines
|
||||||
|
|
@ -259,19 +259,19 @@ bool Statement::is_same_to(const Statement &other) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
CombineResult Statement::combine(Statement &&other) {
|
CombineResult Statement::combine(Statement &&other) {
|
||||||
if (expr_.index() != other.expr_.index()) {
|
if (expr.index() != other.expr.index()) {
|
||||||
return CombineResult::DIFFERENT_STATEMENT_TYPES;
|
return CombineResult::DIFFERENT_STATEMENT_TYPES;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (expr_.index()) {
|
switch (expr.index()) {
|
||||||
case 0: // Import
|
case 0: // Import
|
||||||
return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR;
|
return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR;
|
||||||
case 1: // TypeDefinition
|
case 1: // TypeDefinition
|
||||||
return std::get<TypeDefinition>(expr_).combine(
|
return std::get<TypeDefinition>(expr).combine(
|
||||||
std::move(std::get<TypeDefinition>(other.expr_)));
|
std::move(std::get<TypeDefinition>(other.expr)));
|
||||||
case 2: // FunctionDefinition
|
case 2: // FunctionDefinition
|
||||||
return std::get<FunctionDefinition>(expr_).combine(
|
return std::get<FunctionDefinition>(expr).combine(
|
||||||
std::move(std::get<FunctionDefinition>(other.expr_)));
|
std::move(std::get<FunctionDefinition>(other.expr)));
|
||||||
case 3: // Extra
|
case 3: // Extra
|
||||||
return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR;
|
return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR;
|
||||||
case 4: // EmptyLines
|
case 4: // EmptyLines
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#include "type_nodes.hpp"
|
#include "type_nodes.hpp"
|
||||||
|
|
||||||
|
// TODO: replace error system
|
||||||
|
|
||||||
namespace nodes {
|
namespace nodes {
|
||||||
|
|
||||||
TypeData *Type::get() { return type_storage_->get_type(id_); }
|
TypeData *Type::get() { return type_storage_->get_type(id_); }
|
||||||
|
|
@ -18,12 +20,14 @@ Type TypeStorage::primitive(builtin::Type type) {
|
||||||
return Type(*this, iter->second);
|
return Type(*this, iter->second);
|
||||||
} else {
|
} else {
|
||||||
primitive_type_ids_[type] = storage_.size();
|
primitive_type_ids_[type] = storage_.size();
|
||||||
return add_type(TypeData(Identifier(Node(), Identifier::SIMPLE_TYPE,
|
return add_type(TypeData(Identifier{
|
||||||
builtin::types::to_string(type))));
|
.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) {
|
if (type.type_storage_ != this) {
|
||||||
error_handling::handle_general_error(
|
error_handling::handle_general_error(
|
||||||
"TypeStorage: Can't add array of type from another type "
|
"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;
|
std::vector<nodes::Type> parameters;
|
||||||
parameters.push_back(type);
|
parameters.push_back(type);
|
||||||
|
|
||||||
return add_type(TypeData(Identifier(node, Identifier::SIMPLE_TYPE,
|
return add_type(TypeData(
|
||||||
builtin::types::ARRAY_IDENTIFIER),
|
Identifier{
|
||||||
std::move(parameters)));
|
.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) {
|
if (type.type_storage_ != this) {
|
||||||
error_handling::handle_general_error(
|
error_handling::handle_general_error(
|
||||||
"TypeStorage: Can't add error of type from another type "
|
"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;
|
std::vector<nodes::Type> parameters;
|
||||||
parameters.push_back(type);
|
parameters.push_back(type);
|
||||||
|
|
||||||
return add_type(TypeData(Identifier(node, Identifier::SIMPLE_TYPE,
|
return add_type(TypeData(
|
||||||
builtin::types::ERROR_IDENTIFIER),
|
Identifier{
|
||||||
std::move(parameters)));
|
.kind = Identifier::kSimpleType,
|
||||||
|
.value = builtin::types::ERROR_IDENTIFIER,
|
||||||
|
},
|
||||||
|
std::move(parameters)));
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes::Type TypeStorage::add_container_of(std::vector<Type> &¶meters,
|
nodes::Type TypeStorage::add_container_of(std::vector<Type> &¶meters,
|
||||||
builtin::Type container, Node node) {
|
builtin::Type container) {
|
||||||
for (auto ¶meter : parameters) {
|
for (auto ¶meter : parameters) {
|
||||||
if (parameter.type_storage_ != this) {
|
if (parameter.type_storage_ != this) {
|
||||||
error_handling::handle_general_error(
|
error_handling::handle_general_error(
|
||||||
|
|
@ -64,10 +74,12 @@ nodes::Type TypeStorage::add_container_of(std::vector<Type> &¶meters,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return add_type(
|
return add_type(nodes::TypeData(
|
||||||
nodes::TypeData(nodes::Identifier(node, nodes::Identifier::SIMPLE_TYPE,
|
nodes::Identifier{
|
||||||
builtin::types::to_string(container)),
|
.kind = nodes::Identifier::kSimpleType,
|
||||||
std::move(parameters)));
|
.value = builtin::types::to_string(container),
|
||||||
|
},
|
||||||
|
std::move(parameters)));
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes::Type TypeStorage::add_modification_of(Type type, Modifier modifier) {
|
nodes::Type TypeStorage::add_modification_of(Type type, Modifier modifier) {
|
||||||
|
|
@ -95,7 +107,7 @@ bool TypeStorage::resolve_all_generic_types() {
|
||||||
|
|
||||||
for (auto &type : storage_) {
|
for (auto &type : storage_) {
|
||||||
if (type.is_generic()) {
|
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
|
// because of undefined order some types can became resolved earlir
|
||||||
// wirking correctly because each generic type has <= 1 successor, no
|
// wirking correctly because each generic type has <= 1 successor, no
|
||||||
|
|
@ -280,9 +292,10 @@ bool TypeStorage::resolve(
|
||||||
//
|
//
|
||||||
|
|
||||||
Identifier TypeStorage::generate_generic_type_identifier() {
|
Identifier TypeStorage::generate_generic_type_identifier() {
|
||||||
Identifier identifier =
|
Identifier identifier = Identifier{
|
||||||
Identifier(Node(), Identifier::GENERIC_TYPE,
|
.kind = Identifier::kGenericType,
|
||||||
"G_" + std::to_string(last_generic_type_id_));
|
.value = "G_" + std::to_string(last_generic_type_id_),
|
||||||
|
};
|
||||||
++last_generic_type_id_;
|
++last_generic_type_id_;
|
||||||
return identifier;
|
return identifier;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ void print(const nodes::ExprData &expression, printers::Printer &printer) {
|
||||||
|
|
||||||
void print(const nodes::Match::Case &expression, Printer &printer) {
|
void print(const nodes::Match::Case &expression, Printer &printer) {
|
||||||
|
|
||||||
switch (expression.case_type()) {
|
switch (expression.kind()) {
|
||||||
case nodes::Match::Case::PATTERN_VALUE:
|
case nodes::Match::Case::PATTERN_VALUE:
|
||||||
printer.print(":=");
|
printer.print(":=");
|
||||||
break;
|
break;
|
||||||
|
|
@ -316,7 +316,7 @@ void print(const nodes::NameExpression &expression,
|
||||||
|
|
||||||
bool operator_called_as_function =
|
bool operator_called_as_function =
|
||||||
(!expression.is_operator_call() &&
|
(!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) {
|
if (operator_called_as_function) {
|
||||||
printer.print("( ");
|
printer.print("( ");
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,15 @@ class State {
|
||||||
public:
|
public:
|
||||||
struct VariableInfo {
|
struct VariableInfo {
|
||||||
nodes::Type type;
|
nodes::Type type;
|
||||||
nodes::NameDefinition::Modifier modifier;
|
nodes::NameDefinition::Kind modifier;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
State(Log &log) : log_(log) {}
|
State(Log &log) : log_(log) {}
|
||||||
|
|
||||||
bool insert_variable(const std::string &name, nodes::Type type,
|
bool insert_variable(const std::string &name, nodes::Type type,
|
||||||
nodes::NameDefinition::Modifier modifier) {
|
nodes::NameDefinition::Kind modifier) {
|
||||||
Log::Context logc(log_, utils::Log::Area::kTypeCheck);
|
Log::Context logc(log_, Log::Area::kTypeCheck);
|
||||||
|
|
||||||
if (contexts_.empty()) {
|
if (contexts_.empty()) {
|
||||||
logc.Fatal<Log::kSys>(
|
logc.Fatal<Log::kSys>(
|
||||||
|
|
@ -50,7 +50,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bring_type(nodes::Type type) {
|
bool bring_type(nodes::Type type) {
|
||||||
Log::Context logc(log_, utils::Log::Area::kTypeCheck);
|
Log::Context logc(log_, Log::Area::kTypeCheck);
|
||||||
|
|
||||||
if (contexts_.empty()) {
|
if (contexts_.empty()) {
|
||||||
logc.Fatal<Log::kSys>(
|
logc.Fatal<Log::kSys>(
|
||||||
|
|
@ -66,7 +66,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool return_type(nodes::Type type) {
|
bool return_type(nodes::Type type) {
|
||||||
Log::Context logc(log_, utils::Log::Area::kTypeCheck);
|
Log::Context logc(log_, Log::Area::kTypeCheck);
|
||||||
|
|
||||||
if (contexts_.empty()) {
|
if (contexts_.empty()) {
|
||||||
logc.Fatal<Log::kSys>(
|
logc.Fatal<Log::kSys>(
|
||||||
|
|
@ -83,7 +83,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void enter_context(const nodes::Node &node) {
|
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);
|
contexts_.emplace_back(node);
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +92,7 @@ private:
|
||||||
// returns brought type, return type is merged with next context or with
|
// returns brought type, return type is merged with next context or with
|
||||||
// brought type in last context
|
// brought type in last context
|
||||||
nodes::MaybeType exit_context() {
|
nodes::MaybeType exit_context() {
|
||||||
Log::Context logc(log_, utils::Log::Area::kTypeCheck);
|
Log::Context logc(log_, Log::Area::kTypeCheck);
|
||||||
|
|
||||||
if (contexts_.empty()) {
|
if (contexts_.empty()) {
|
||||||
logc.Fatal<Log::kSys>(
|
logc.Fatal<Log::kSys>(
|
||||||
|
|
|
||||||
|
|
@ -849,7 +849,7 @@ Result CheckTask<nodes::Lambda>::operator()(const nodes::Lambda &expr,
|
||||||
if (!state<State>().insert_variable(
|
if (!state<State>().insert_variable(
|
||||||
*expr.get_argument(i)->get(),
|
*expr.get_argument(i)->get(),
|
||||||
expected_type.get()->get_parameter_proxy(i),
|
expected_type.get()->get_parameter_proxy(i),
|
||||||
nodes::NameDefinition::Modifier::LET)) {
|
nodes::NameDefinition::Kind::LET)) {
|
||||||
// TODO: which modifier ??
|
// TODO: which modifier ??
|
||||||
type_check_error("Variable is already defined in this context", expr,
|
type_check_error("Variable is already defined in this context", expr,
|
||||||
executor);
|
executor);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ nodes::Type check_same_to_pass_type_in_args(nodes::Type type, const Args &args,
|
||||||
Executor &executor,
|
Executor &executor,
|
||||||
const std::string &message,
|
const std::string &message,
|
||||||
bool handle_errors) {
|
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()) {
|
if (not args.get_passed().has_value()) {
|
||||||
return type;
|
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,
|
bool check_no_pass_type_in_args(const Args &args, const nodes::Node &node,
|
||||||
Executor &executor, const std::string &message,
|
Executor &executor, const std::string &message,
|
||||||
bool handle_errors) {
|
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()) {
|
if (args.get_passed().has_value()) {
|
||||||
type_check_error(message, node, executor, handle_errors);
|
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,
|
Result type_same_to_expected(nodes::Type type, const Args &args,
|
||||||
const nodes::Node & /*node*/, Executor &executor,
|
const nodes::Node & /*node*/, Executor &executor,
|
||||||
const std::string &message, bool handle_errors) {
|
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();
|
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*/,
|
Result type_check_from_args(nodes::Type /*type*/, const Args & /*args*/,
|
||||||
const nodes::Node & /*node*/, Executor &executor,
|
const nodes::Node & /*node*/, Executor &executor,
|
||||||
bool /*handle_errors*/) {
|
bool /*handle_errors*/) {
|
||||||
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
|
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||||
|
|
||||||
/* TODO FIXME */
|
/* TODO FIXME */
|
||||||
logc.Fatal<Log::kSys>({{"Not implemented yet"}});
|
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,
|
Executor &executor, const std::string &message_not_found,
|
||||||
const std::string &message_different_statement,
|
const std::string &message_different_statement,
|
||||||
bool handle_errors) {
|
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);
|
const auto maybe_any_statement = executor.state<names::NameTree>().find(name);
|
||||||
if (not maybe_any_statement.has_value()) {
|
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 *>
|
std::optional<const nodes::TypeDefinition *>
|
||||||
find_type_definition(const std::string &name, const nodes::Node &node,
|
find_type_definition(const std::string &name, const nodes::Node &node,
|
||||||
Executor &executor, bool handle_errors) {
|
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>(
|
return find_statement<nodes::TypeDefinition>(
|
||||||
name, node, executor, "No type definition found in name tree",
|
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 *>
|
std::optional<const nodes::FunctionDefinition *>
|
||||||
find_name_definition(const std::string &name, const nodes::Node &node,
|
find_name_definition(const std::string &name, const nodes::Node &node,
|
||||||
Executor &executor, bool handle_errors) {
|
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>(
|
return find_statement<nodes::FunctionDefinition>(
|
||||||
name, node, executor, "No name definition found in name tree",
|
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,
|
const nodes::Node &node,
|
||||||
Executor &executor,
|
Executor &executor,
|
||||||
bool handle_errors) {
|
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(
|
const auto maybe_type_definition = find_type_definition(
|
||||||
*type.get()->get_name()->get(), node, executor, handle_errors);
|
*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,
|
const nodes::Node &node,
|
||||||
Executor &executor,
|
Executor &executor,
|
||||||
bool handle_errors) {
|
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()) {
|
switch (type.get()->to_builtin()) {
|
||||||
case builtin::Type::TUPLE: { // access field
|
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
|
// FIXME: replace with direct log calls
|
||||||
void type_check_error(const std::string &message, const nodes::Node &,
|
void type_check_error(const std::string &message, const nodes::Node &,
|
||||||
Executor &executor, bool handle_error) {
|
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) {
|
if (!handle_error) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "log.hpp"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
#include "tree_sitter/api.h"
|
#include "tree_sitter/api.h"
|
||||||
|
|
@ -18,56 +19,46 @@ public:
|
||||||
: node_(node), source_(source) {}
|
: node_(node), source_(source) {}
|
||||||
|
|
||||||
std::string get_type() const {
|
std::string get_type() const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (get_type)");
|
||||||
"Null parsing node method called (get_type)");
|
|
||||||
}
|
|
||||||
return ts_node_type(node_);
|
return ts_node_type(node_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<size_t, size_t> get_start_point() const {
|
utils::Pos::Point get_start_point() const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (get_start_point)");
|
||||||
"Null parsing node method called (get_start_point)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TSPoint point = ts_node_start_point(node_);
|
TSPoint point = ts_node_start_point(node_);
|
||||||
return {point.row, point.column};
|
return {point.row, point.column};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<size_t, size_t> get_end_point() const {
|
utils::Pos::Point get_end_point() const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (get_end_point)");
|
||||||
"Null parsing node method called (get_end_point)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TSPoint point = ts_node_end_point(node_);
|
TSPoint point = ts_node_end_point(node_);
|
||||||
return {point.row, point.column};
|
return {point.row, point.column};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils::Pos get_pos() const { return {get_start_point(), get_end_point()}; }
|
||||||
|
|
||||||
std::string get_as_sexpression() const {
|
std::string get_as_sexpression() const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (get_as_sexpression)");
|
||||||
"Null parsing node method called (get_as_sexpression)");
|
|
||||||
}
|
|
||||||
return ts_node_string(node_);
|
return ts_node_string(node_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_value() const { // from source
|
std::string get_value() const { // from source
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (get_value)");
|
||||||
"Null parsing node method called (get_value)");
|
|
||||||
}
|
|
||||||
size_t start = ts_node_start_byte(node_);
|
size_t start = ts_node_start_byte(node_);
|
||||||
size_t end = ts_node_end_byte(node_);
|
size_t end = ts_node_end_byte(node_);
|
||||||
return source_->substr(start, end - start);
|
return source_->substr(start, end - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t get_value_length() const { // from source
|
size_t get_value_length() const { // from source
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (get_value_length)");
|
||||||
"Null parsing node method called (get_value_length)");
|
|
||||||
}
|
|
||||||
size_t start = ts_node_start_byte(node_);
|
size_t start = ts_node_start_byte(node_);
|
||||||
size_t end = ts_node_end_byte(node_);
|
size_t end = ts_node_end_byte(node_);
|
||||||
return end - start;
|
return end - start;
|
||||||
|
|
@ -76,106 +67,80 @@ public:
|
||||||
bool is_null() const { return ts_node_is_null(node_); }
|
bool is_null() const { return ts_node_is_null(node_); }
|
||||||
|
|
||||||
bool is_named() const {
|
bool is_named() const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (is_named)");
|
||||||
"Null parsing node method called (is_named)");
|
|
||||||
}
|
|
||||||
return ts_node_is_named(node_);
|
return ts_node_is_named(node_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_missing() const {
|
bool is_missing() const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (is_missing)");
|
||||||
"Null parsing node method called (is_missing)");
|
|
||||||
}
|
|
||||||
return ts_node_is_missing(node_);
|
return ts_node_is_missing(node_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_extra() const { // comments, etc.
|
bool is_extra() const { // comments, etc.
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (is_extra)");
|
||||||
"Null parsing node method called (is_extra)");
|
|
||||||
}
|
|
||||||
return ts_node_is_extra(node_);
|
return ts_node_is_extra(node_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_error() const {
|
bool has_error() const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (has_error)");
|
||||||
"Null parsing node method called (has_error)");
|
|
||||||
}
|
|
||||||
return ts_node_has_error(node_);
|
return ts_node_has_error(node_);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node nth_child(size_t n) const {
|
Node nth_child(size_t n) const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (nth_child)");
|
||||||
"Null parsing node method called (nth_child)");
|
|
||||||
}
|
|
||||||
return Node(ts_node_child(node_, n), source_);
|
return Node(ts_node_child(node_, n), source_);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t child_count() const {
|
size_t child_count() const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (child_count)");
|
||||||
"Null parsing node method called (child_count)");
|
|
||||||
}
|
|
||||||
return ts_node_child_count(node_);
|
return ts_node_child_count(node_);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node nth_named_child(size_t n) const {
|
Node nth_named_child(size_t n) const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (nth_named_child)");
|
||||||
"Null parsing node method called (nth_named_child)");
|
|
||||||
}
|
|
||||||
return Node(ts_node_named_child(node_, n), source_);
|
return Node(ts_node_named_child(node_, n), source_);
|
||||||
}
|
}
|
||||||
size_t named_child_count() const {
|
size_t named_child_count() const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (named_child_count)");
|
||||||
"Null parsing node method called (named_child_count)");
|
|
||||||
}
|
|
||||||
return ts_node_named_child_count(node_);
|
return ts_node_named_child_count(node_);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node child_by_field_name(const std::string &name) const {
|
Node child_by_field_name(const std::string &name) const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (child_by_field_name)");
|
||||||
"Null parsing node method called (child_by_field_name)");
|
|
||||||
}
|
|
||||||
return Node(ts_node_child_by_field_name(node_, name.c_str(), name.size()),
|
return Node(ts_node_child_by_field_name(node_, name.c_str(), name.size()),
|
||||||
source_);
|
source_);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node previous_sibling() const {
|
Node previous_sibling() const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (previous_sibling)");
|
||||||
"Null parsing node method called (previous_sibling)");
|
|
||||||
}
|
|
||||||
return Node(ts_node_prev_sibling(node_), source_);
|
return Node(ts_node_prev_sibling(node_), source_);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node previous_named_sibling() const {
|
Node previous_named_sibling() const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (previous_named_sibling)");
|
||||||
"Null parsing node method called (previous_named_sibling)");
|
|
||||||
}
|
|
||||||
return Node(ts_node_prev_named_sibling(node_), source_);
|
return Node(ts_node_prev_named_sibling(node_), source_);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node next_sibling() const {
|
Node next_sibling() const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (next_sibling)");
|
||||||
"Null parsing node method called (next_sibling)");
|
|
||||||
}
|
|
||||||
return Node(ts_node_next_sibling(node_), source_);
|
return Node(ts_node_next_sibling(node_), source_);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node next_named_sibling() const {
|
Node next_named_sibling() const {
|
||||||
if (is_null()) {
|
utils::Assert(not is_null(),
|
||||||
error_handling::handle_general_error(
|
"Null parsing node method called (next_named_sibling)");
|
||||||
"Null parsing node method called (next_named_sibling)");
|
|
||||||
}
|
|
||||||
return Node(ts_node_next_named_sibling(node_), source_);
|
return Node(ts_node_next_named_sibling(node_), source_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,18 @@ namespace utils {
|
||||||
#else // GCC, Clang
|
#else // GCC, Clang
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
#endif
|
#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
|
} // namespace utils
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue