mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-05 22:48:43 +00:00
Most fixes done, build working (without typecheck fixes, is_scoped proper propogation and executor views)
This commit is contained in:
parent
d02c3a637b
commit
5891066414
33 changed files with 1391 additions and 960 deletions
|
|
@ -51,7 +51,13 @@ public:
|
|||
|
||||
void Print(std::ostream &out) {
|
||||
printers::Printer printer(out, 2, 80, true);
|
||||
printers::print(statements_, printer);
|
||||
|
||||
// TODO: FIXME: share executor
|
||||
printers::Executor executor(
|
||||
utils::BuildPrintLog(std::cout),
|
||||
printers::Exprs{executor_.state<printers::Exprs>()},
|
||||
std::move(printer));
|
||||
printers::PrintTask<nodes::Statements>{executor}(statements_, {});
|
||||
}
|
||||
|
||||
size_t statements_size() const { return statements_.size(); }
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ template <typename N, typename Tag = utils::None> struct BuilderTask {
|
|||
template <typename N> struct BuilderTaskUtils : public Task<N> {
|
||||
using Task<N>::Task;
|
||||
|
||||
Node Ext(storage::Id id) const {
|
||||
Node Ext(storage::Id id) {
|
||||
return Node(id, this->template state<Exprs>(),
|
||||
this->template state<Positions>());
|
||||
}
|
||||
|
|
@ -58,7 +58,15 @@ template <typename N> struct BuilderTaskUtils : public Task<N> {
|
|||
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);
|
||||
return Ext(id);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -85,11 +93,15 @@ struct ExprBuilderTaskBase : public BuilderTaskUtils<Node> {
|
|||
BuilderTask<OtherN, OtherTag> task(this->executor);
|
||||
return task(node, args);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename N>
|
||||
struct TypeBuilderTaskBase : public BuilderTaskUtils<nodes::Type> {
|
||||
using BuilderTaskUtils<nodes::Type>::BuilderTaskUtils;
|
||||
|
||||
// TODO: rename
|
||||
template <typename OtherN, typename OtherTag = utils::None,
|
||||
typename Ret = OtherN>
|
||||
Ret RunOther(const parser::ParseTree::Node &node, const Args &args = {}) {
|
||||
typename Ret = nodes::Type>
|
||||
Ret Run(const parser::ParseTree::Node &node, const Args &args = {}) {
|
||||
BuilderTask<OtherN, OtherTag> task(this->executor);
|
||||
return task(node, args);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "builders_utils.hpp"
|
||||
#include "doc_nodes.hpp"
|
||||
#include "tree_sitter_wrapper.hpp"
|
||||
|
||||
|
|
@ -8,9 +9,10 @@
|
|||
|
||||
namespace builders {
|
||||
|
||||
nodes::SymbolDocs build_symbol_docs(
|
||||
std::optional<parser::ParseTree::Node> description_parser_node,
|
||||
const std::vector<parser::ParseTree::Node> &annotation_parser_nodes = {},
|
||||
const std::unordered_set<std::string> &annotations = {});
|
||||
nodes::SymbolDocs
|
||||
build_symbol_docs(std::optional<ParserNode> description_parser_node,
|
||||
const std::vector<ParserNode> &annotation_parser_nodes,
|
||||
const std::unordered_set<std::string> &annotations,
|
||||
Executor &executor);
|
||||
|
||||
} // namespace builders
|
||||
|
|
|
|||
|
|
@ -23,6 +23,13 @@ namespace builders {
|
|||
|
||||
// --- flow control
|
||||
|
||||
template <>
|
||||
struct BuilderTask<nodes::NodeId> : public ExprBuilderTaskBase<nodes::NodeId> {
|
||||
using ExprBuilderTaskBase<nodes::NodeId>::ExprBuilderTaskBase;
|
||||
|
||||
Node operator()(const ParserNode &parser_node, const Args &args) override;
|
||||
};
|
||||
|
||||
template <> struct BuilderTask<Node> : public ExprBuilderTaskBase<Node> {
|
||||
using ExprBuilderTaskBase<Node>::ExprBuilderTaskBase;
|
||||
|
||||
|
|
@ -90,6 +97,8 @@ struct BuilderTask<nodes::Container, T>
|
|||
// or
|
||||
// '[[' expression+ ']]'
|
||||
Node operator()(const ParserNode &parser_node, const Args &) override {
|
||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||
|
||||
const auto kind = std::is_same_v<T, utils::BlockTag>
|
||||
? nodes::Container::BLOCK
|
||||
: nodes::Container::ARRAY;
|
||||
|
|
@ -103,10 +112,12 @@ struct BuilderTask<nodes::Container, T>
|
|||
current_node = current_node.next_named_sibling();
|
||||
}
|
||||
|
||||
return state<Exprs>().Insert(nodes::Container{
|
||||
return Build(
|
||||
nodes::Container{
|
||||
.kind = kind,
|
||||
.exprs = std::move(exprs),
|
||||
});
|
||||
},
|
||||
parser_node.get_pos());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -162,13 +173,18 @@ struct BuilderTask<nodes::ModifierExpression, T>
|
|||
// or
|
||||
// expression ('?' | '!')
|
||||
Node operator()(const ParserNode &parser_node, const Args &) override {
|
||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||
|
||||
const size_t modifier_pos =
|
||||
std::is_same_v<T, utils::RefTag> ? 0 : parser_node.child_count() - 1;
|
||||
|
||||
return state<Exprs>().Insert(nodes::ModifierExpression{
|
||||
.modifier = Run<nodes::Modifier>(parser_node.nth_child(modifier_pos)),
|
||||
return Build(
|
||||
nodes::ModifierExpression{
|
||||
.modifier = RunOther<nodes::Modifier, utils::None, nodes::Modifier>(
|
||||
parser_node.nth_child(modifier_pos)),
|
||||
.expr = Run<Node>(parser_node.nth_named_child(0)),
|
||||
});
|
||||
},
|
||||
parser_node.get_pos());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,26 +1,69 @@
|
|||
#pragma once
|
||||
|
||||
#include "builders_utils.hpp"
|
||||
#include "tokens.hpp"
|
||||
#include "tree_sitter_wrapper.hpp"
|
||||
#include "type_nodes.hpp"
|
||||
|
||||
namespace utils {
|
||||
|
||||
template <tokens::Type> struct TypeTag {};
|
||||
|
||||
} // namespace utils
|
||||
|
||||
namespace builders {
|
||||
|
||||
nodes::Type build_type(parser::ParseTree::Node parse_node,
|
||||
nodes::TypeStorage &type_storage);
|
||||
template <>
|
||||
struct BuilderTask<nodes::Type> : public TypeBuilderTaskBase<nodes::Type> {
|
||||
using TypeBuilderTaskBase<nodes::Type>::TypeBuilderTaskBase;
|
||||
|
||||
nodes::Type build_variant_type(parser::ParseTree::Node parse_node,
|
||||
nodes::TypeStorage &type_storage);
|
||||
nodes::Type operator()(const ParserNode &parser_node,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
nodes::Type build_tuple_type(parser::ParseTree::Node parse_node,
|
||||
nodes::TypeStorage &type_storage);
|
||||
template <>
|
||||
struct BuilderTask<nodes::Type, utils::TypeTag<tokens::Type::VARIANT_TYPE>>
|
||||
: public TypeBuilderTaskBase<nodes::Type> {
|
||||
using TypeBuilderTaskBase<nodes::Type>::TypeBuilderTaskBase;
|
||||
|
||||
nodes::Type build_reference_type(parser::ParseTree::Node parse_node,
|
||||
nodes::TypeStorage &type_storage);
|
||||
nodes::Type operator()(const ParserNode &parser_node,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
nodes::Type build_modified_type(parser::ParseTree::Node parse_node,
|
||||
nodes::TypeStorage &type_storage);
|
||||
template <>
|
||||
struct BuilderTask<nodes::Type, utils::TypeTag<tokens::Type::TUPLE_TYPE>>
|
||||
: public TypeBuilderTaskBase<nodes::Type> {
|
||||
using TypeBuilderTaskBase<nodes::Type>::TypeBuilderTaskBase;
|
||||
|
||||
nodes::Type build_simple_type(parser::ParseTree::Node parse_node,
|
||||
nodes::TypeStorage &type_storage);
|
||||
nodes::Type operator()(const ParserNode &parser_node,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct BuilderTask<nodes::Type, utils::TypeTag<tokens::Type::REFERENCE_TYPE>>
|
||||
: public TypeBuilderTaskBase<nodes::Type> {
|
||||
using TypeBuilderTaskBase<nodes::Type>::TypeBuilderTaskBase;
|
||||
|
||||
nodes::Type operator()(const ParserNode &parser_node,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct BuilderTask<nodes::Type, utils::TypeTag<tokens::Type::MODIFIED_TYPE>>
|
||||
: public TypeBuilderTaskBase<nodes::Type> {
|
||||
using TypeBuilderTaskBase<nodes::Type>::TypeBuilderTaskBase;
|
||||
|
||||
nodes::Type operator()(const ParserNode &parser_node,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct BuilderTask<nodes::Type, utils::TypeTag<tokens::Type::SIMPLE_TYPE>>
|
||||
: public TypeBuilderTaskBase<nodes::Type> {
|
||||
using TypeBuilderTaskBase<nodes::Type>::TypeBuilderTaskBase;
|
||||
|
||||
nodes::Type operator()(const ParserNode &parser_node,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
} // namespace builders
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
#include "doc_builders.hpp"
|
||||
#include "basic_builders.hpp"
|
||||
#include "doc_nodes.hpp"
|
||||
#include "error_handling.hpp"
|
||||
#include "log.hpp"
|
||||
|
||||
namespace builders {
|
||||
|
||||
// TODO: check, that all annotations are exist in function definition
|
||||
nodes::SymbolDocs build_symbol_docs(
|
||||
std::optional<parser::ParseTree::Node> description_parser_node,
|
||||
const std::vector<parser::ParseTree::Node> &annotation_parser_nodes,
|
||||
const std::unordered_set<std::string> &annotations) {
|
||||
nodes::SymbolDocs
|
||||
build_symbol_docs(std::optional<ParserNode> description_parser_node,
|
||||
const std::vector<ParserNode> &annotation_parser_nodes,
|
||||
const std::unordered_set<std::string> &annotations,
|
||||
Executor &executor) {
|
||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||
|
||||
std::optional<std::string> description;
|
||||
|
||||
|
|
@ -35,15 +37,16 @@ nodes::SymbolDocs build_symbol_docs(
|
|||
: nodes::SymbolDocs();
|
||||
|
||||
for (auto &annotation_parser_node : annotation_parser_nodes) {
|
||||
std::string annotation =
|
||||
build_annotation(annotation_parser_node.nth_named_child(0));
|
||||
std::string annotation = BuilderTask<nodes::Annotation>{executor}(
|
||||
annotation_parser_node.nth_named_child(0), {})
|
||||
.value;
|
||||
|
||||
if (annotations.count(annotation) == 0) {
|
||||
error_handling::handle_parsing_error(
|
||||
"Annotation \"" + annotation +
|
||||
"\" doesn't present in corresponding symbol",
|
||||
annotation_parser_node);
|
||||
}
|
||||
logc.Expect<Log::kProc>(
|
||||
annotations.count(annotation) == 0,
|
||||
{{std::format(
|
||||
"Annotation \"{}\" doesn't present in corresponding symbol",
|
||||
annotation)}},
|
||||
annotation_parser_node.get_pos());
|
||||
|
||||
docs.add_annotation_info(
|
||||
annotation, annotation_parser_node.nth_named_child(1).get_value());
|
||||
|
|
|
|||
|
|
@ -12,15 +12,29 @@
|
|||
|
||||
namespace builders {
|
||||
|
||||
Node BuilderTask<nodes::NodeId>::operator()(const ParserNode &parser_node,
|
||||
const Args &args) {
|
||||
return Run<Node>(parser_node, args);
|
||||
}
|
||||
|
||||
// NOTE: use args in some way ??
|
||||
Node BuilderTask<Node>::operator()(const ParserNode &parser_node,
|
||||
const Args &) {
|
||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||
|
||||
logc.Default<Log::kSys>(
|
||||
{{std::format("type is [{}]", parser_node.get_type())}},
|
||||
parser_node.get_pos());
|
||||
|
||||
logc.Default<Log::kSys>(
|
||||
{{std::format("current sexpr is [{}]", parser_node.get_as_sexpression()),
|
||||
Log::Fragment::Color::kImportant}},
|
||||
parser_node.get_pos());
|
||||
|
||||
tokens::Type type = tokens::string_to_type(parser_node.get_type());
|
||||
|
||||
auto maybe_parenthesis = parser_node.previous_sibling();
|
||||
|
||||
// FIXME TODO
|
||||
bool is_scoped =
|
||||
(!maybe_parenthesis.is_null() && !maybe_parenthesis.is_named() &&
|
||||
maybe_parenthesis.get_value() == "(");
|
||||
|
|
@ -66,8 +80,12 @@ Node BuilderTask<Node>::operator()(const ParserNode &parser_node,
|
|||
case tokens::Type::NAME_EXPRESSION:
|
||||
return Run<nodes::NameExpression, utils::FuncCallTag>(parser_node,
|
||||
{is_scoped});
|
||||
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
|
||||
case tokens::Type::SIMPLE_NAME_IDENTIFIER:
|
||||
case tokens::Type::SIMPLE_TYPE_IDENTIFIER:
|
||||
case tokens::Type::TYPECLASS_IDENTIFIER:
|
||||
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
|
||||
case tokens::Type::ARGUMENT_TYPE_IDENTIFIER:
|
||||
case tokens::Type::OPERATOR:
|
||||
case tokens::Type::PLACEHOLDER:
|
||||
return Build(
|
||||
nodes::NameExpression{
|
||||
|
|
@ -79,43 +97,56 @@ Node BuilderTask<Node>::operator()(const ParserNode &parser_node,
|
|||
case tokens::Type::LAMBDA:
|
||||
return Run<nodes::Lambda>(parser_node);
|
||||
// --- literals
|
||||
// TODO: FIXME:
|
||||
// case tokens::Type::FLOAT_LITERAL:
|
||||
// return BUILD : build_float_literal(parser_node);
|
||||
// case tokens::Type::DOUBLE_LITERAL:
|
||||
// return BUILD : build_double_literal(parser_node);
|
||||
// case tokens::Type::INT_LITERAL:
|
||||
// return BUILD : build_int_literal(parser_node);
|
||||
// case tokens::Type::LONG_LITERAL:
|
||||
// return BUILD : build_long_literal(parser_node);
|
||||
// case tokens::Type::INDEX_LITERAL:
|
||||
// return BUILD : build_index_literal(parser_node);
|
||||
// case tokens::Type::STRING_LITERAL:
|
||||
// return BUILD : build_string_literal(parser_node);
|
||||
// case tokens::Type::UNICODE_STRING_LITERAL:
|
||||
// return BUILD : build_unicode_string_literal(parser_node);
|
||||
// case tokens::Type::CHAR_LITERAL:
|
||||
// return BUILD : build_char_literal(parser_node);
|
||||
// case tokens::Type::UNICODE_LITERAL:
|
||||
// return BUILD : build_unicode_literal(parser_node);
|
||||
// case tokens::Type::BOOL_LITERAL:
|
||||
// return BUILD : build_bool_literal(parser_node);
|
||||
// case tokens::Type::UNIT_LITERAL:
|
||||
// return BUILD : build_unit_literal(parser_node);
|
||||
// case tokens::Type::NULL_LITERAL:
|
||||
// return BUILD : build_null_literal(parser_node);
|
||||
// case tokens::Type::EXTRA:
|
||||
// return BUILD : build_extra(parser_node);
|
||||
// case tokens::Type::EMPTY_LINES:
|
||||
// return BUILD : build_empty_lines(parser_node);
|
||||
case tokens::Type::FLOAT_LITERAL:
|
||||
return Build(RunOther<nodes::Literal, float>(parser_node),
|
||||
parser_node.get_pos());
|
||||
case tokens::Type::DOUBLE_LITERAL:
|
||||
return Build(RunOther<nodes::Literal, double>(parser_node),
|
||||
parser_node.get_pos());
|
||||
case tokens::Type::INT_LITERAL:
|
||||
return Build(RunOther<nodes::Literal, int32_t>(parser_node),
|
||||
parser_node.get_pos());
|
||||
case tokens::Type::LONG_LITERAL:
|
||||
return Build(RunOther<nodes::Literal, int64_t>(parser_node),
|
||||
parser_node.get_pos());
|
||||
case tokens::Type::INDEX_LITERAL:
|
||||
return Build(RunOther<nodes::Literal, size_t>(parser_node),
|
||||
parser_node.get_pos());
|
||||
case tokens::Type::STRING_LITERAL:
|
||||
return Build(RunOther<nodes::Literal, std::string>(parser_node),
|
||||
parser_node.get_pos());
|
||||
case tokens::Type::UNICODE_STRING_LITERAL:
|
||||
return Build(RunOther<nodes::Literal, nodes::unicode_string>(parser_node),
|
||||
parser_node.get_pos());
|
||||
case tokens::Type::CHAR_LITERAL:
|
||||
return Build(RunOther<nodes::Literal, char>(parser_node),
|
||||
parser_node.get_pos());
|
||||
case tokens::Type::UNICODE_LITERAL:
|
||||
return Build(RunOther<nodes::Literal, nodes::unicode>(parser_node),
|
||||
parser_node.get_pos());
|
||||
case tokens::Type::BOOL_LITERAL:
|
||||
return Build(RunOther<nodes::Literal, bool>(parser_node),
|
||||
parser_node.get_pos());
|
||||
case tokens::Type::UNIT_LITERAL:
|
||||
return Build(RunOther<nodes::Literal, nodes::unit>(parser_node),
|
||||
parser_node.get_pos());
|
||||
case tokens::Type::NULL_LITERAL:
|
||||
return Build(RunOther<nodes::Literal, nodes::null>(parser_node),
|
||||
parser_node.get_pos());
|
||||
case tokens::Type::EXTRA:
|
||||
return Build(RunOther<nodes::Extra, utils::None>(parser_node),
|
||||
parser_node.get_pos());
|
||||
case tokens::Type::EMPTY_LINES:
|
||||
return Build(RunOther<nodes::EmptyLines, utils::None>(parser_node),
|
||||
parser_node.get_pos());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
utils::Assert(true, std::format("Unexpected expression node type {}",
|
||||
static_cast<int>(type))); // TODO: magic_enum
|
||||
utils::Assert(false, std::format("Unexpected expression node type [{}]\n",
|
||||
parser_node.get_type())); // TODO: magic_enum
|
||||
// FIXME: change to fatal error ?
|
||||
throw std::exception();
|
||||
utils::unreachable();
|
||||
}
|
||||
|
||||
// --- flow control
|
||||
|
|
@ -124,8 +155,9 @@ Node BuilderTask<Node>::operator()(const ParserNode &parser_node,
|
|||
Node BuilderTask<nodes::Match::Case>::operator()(const ParserNode &parser_node,
|
||||
const Args &) {
|
||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||
std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
|
||||
|
||||
std::string case_type = parser_node.nth_child(0).get_value();
|
||||
std::string case_kind = parser_node.nth_child(0).get_value();
|
||||
|
||||
std::optional<ParserNode> condition_node;
|
||||
std::optional<ParserNode> expression_node;
|
||||
|
|
@ -146,15 +178,15 @@ Node BuilderTask<nodes::Match::Case>::operator()(const ParserNode &parser_node,
|
|||
|
||||
return Build(
|
||||
nodes::Match::Case{
|
||||
.kind = case_type == ":=" ? nodes::Match::Case::PATTERN_VALUE
|
||||
.kind = case_kind == ":=" ? nodes::Match::Case::PATTERN_VALUE
|
||||
: nodes::Match::Case::VALUE_PATTERN,
|
||||
.value = Run<Node>(parser_node.nth_named_child(0)),
|
||||
.condition = condition_node.has_value()
|
||||
? Run<Node>(condition_node.value())
|
||||
: std::optional<storage::Id>(),
|
||||
: std::optional<nodes::NodeId>(),
|
||||
.expr = expression_node.has_value()
|
||||
? Run<Node>(expression_node.value())
|
||||
: std::optional<storage::Id>(),
|
||||
: std::optional<nodes::NodeId>(),
|
||||
},
|
||||
parser_node.get_pos());
|
||||
}
|
||||
|
|
@ -164,7 +196,8 @@ Node BuilderTask<nodes::Match>::operator()(const ParserNode &parser_node,
|
|||
const Args &) {
|
||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||
|
||||
std::vector<storage::Id /*nodes::Match::Case*/> cases; // TODO
|
||||
std::cout << "????????????????";
|
||||
std::vector<nodes::NodeId /*nodes::Match::Case*/> cases; // TODO
|
||||
|
||||
auto current_node = parser_node.nth_named_child(1);
|
||||
while (!current_node.is_null()) {
|
||||
|
|
@ -175,7 +208,8 @@ Node BuilderTask<nodes::Match>::operator()(const ParserNode &parser_node,
|
|||
|
||||
return Build(
|
||||
nodes::Match{
|
||||
.value = Run<Node>(parser_node.nth_named_child(0)),
|
||||
.value = Run<nodes::Match::Case>(parser_node.nth_named_child(
|
||||
0)), // TODO: is_scoped info (always false ??)
|
||||
.cases = std::move(cases),
|
||||
},
|
||||
parser_node.get_pos());
|
||||
|
|
@ -189,14 +223,14 @@ Node BuilderTask<nodes::Condition>::operator()(const ParserNode &parser_node,
|
|||
|
||||
size_t named_child_count = parser_node.named_child_count();
|
||||
|
||||
std::vector<std::pair<storage::Id, storage::Id>> cases;
|
||||
std::vector<std::pair<nodes::NodeId, nodes::NodeId>> cases;
|
||||
|
||||
auto current_node = parser_node.nth_named_child(0);
|
||||
auto next_node = current_node.next_named_sibling();
|
||||
|
||||
while (!current_node.is_null() && !next_node.is_null()) {
|
||||
cases.push_back(
|
||||
{Run<storage::Id>(current_node), Run<storage::Id>(next_node)});
|
||||
{Run<nodes::NodeId>(current_node), Run<nodes::NodeId>(next_node)});
|
||||
current_node = next_node.next_named_sibling();
|
||||
if (current_node.is_null()) {
|
||||
break;
|
||||
|
|
@ -253,13 +287,13 @@ Node BuilderTask<nodes::NameExpression, utils::CommaTag>::operator()(
|
|||
const ParserNode &parser_node, const Args &) {
|
||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||
|
||||
std::vector<std::pair<std::optional<std::string>, storage::Id>> args;
|
||||
std::vector<std::pair<std::optional<std::string>, nodes::NodeId>> args;
|
||||
|
||||
args.emplace_back(std::nullopt,
|
||||
Run<storage::Id>(parser_node.nth_named_child(0)));
|
||||
Run<nodes::NodeId>(parser_node.nth_named_child(0)));
|
||||
|
||||
args.emplace_back(std::nullopt,
|
||||
Run<storage::Id>(parser_node.nth_named_child(1)));
|
||||
Run<nodes::NodeId>(parser_node.nth_named_child(1)));
|
||||
|
||||
return Build(
|
||||
nodes::NameExpression{
|
||||
|
|
@ -284,7 +318,7 @@ Node BuilderTask<nodes::NameExpression, utils::OperatorTag>::operator()(
|
|||
|
||||
auto name_node = parser_node.child_by_field_name("name");
|
||||
|
||||
std::vector<std::pair<std::optional<std::string>, storage::Id>> args;
|
||||
std::vector<std::pair<std::optional<std::string>, nodes::NodeId>> args;
|
||||
|
||||
args.emplace_back(std::nullopt,
|
||||
Run<Node>(name_node.previous_named_sibling()));
|
||||
|
|
@ -455,7 +489,8 @@ Node BuilderTask<nodes::NameExpression, utils::FuncCallTag>::operator()(
|
|||
.name = RunOther<nodes::Identifier>(name_node),
|
||||
.args = std::move(args),
|
||||
.prefix = prefix_node.has_value()
|
||||
? build_type(prefix_node.value(), state<Types>())
|
||||
? RunOther<nodes::Type, utils::None, nodes::Type>(
|
||||
prefix_node.value())
|
||||
: nodes::MaybeType(),
|
||||
.is_point_call = is_point_call,
|
||||
.is_operator_call = false,
|
||||
|
|
@ -479,8 +514,8 @@ Node BuilderTask<nodes::Constructor>::operator()(const ParserNode &parser_node,
|
|||
|
||||
return Build(
|
||||
nodes::Constructor{
|
||||
.type = build_type(parser_node.child_by_field_name("type"),
|
||||
state<Types>()),
|
||||
.type = RunOther<nodes::Type, utils::None, nodes::Type>(
|
||||
parser_node.child_by_field_name("type")),
|
||||
.args = std::move(args),
|
||||
},
|
||||
parser_node.get_pos());
|
||||
|
|
|
|||
|
|
@ -239,8 +239,9 @@ BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
|
|||
}
|
||||
}
|
||||
|
||||
nodes::MaybeType type = type_node.has_value()
|
||||
? build_type(type_node.value(), state<Types>())
|
||||
nodes::MaybeType type =
|
||||
type_node.has_value()
|
||||
? RunOther<nodes::Type, utils::None, nodes::Type>(type_node.value())
|
||||
: nodes::MaybeType();
|
||||
|
||||
std::unordered_set<std::string> annotations;
|
||||
|
|
@ -252,8 +253,8 @@ BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
|
|||
}
|
||||
|
||||
return nodes::TypeDefinition{
|
||||
.docs =
|
||||
build_symbol_docs(description_node, annotation_nodes, annotations),
|
||||
.docs = build_symbol_docs(description_node, annotation_nodes, annotations,
|
||||
executor),
|
||||
.is_on_heap = is_on_heap,
|
||||
.name = std::move(name),
|
||||
.typeclasses = std::move(typeclasses),
|
||||
|
|
@ -377,11 +378,13 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
|
|||
case tokens::Type::SIMPLE_TYPE:
|
||||
if (current_type_id >= args.size()) {
|
||||
args.push_back(nodes::FunctionDefinition::Argument(
|
||||
last_annotation, build_type(current_node, state<Types>()),
|
||||
last_annotation,
|
||||
RunOther<nodes::Type, utils::None, nodes::Type>(current_node),
|
||||
last_before_modifier));
|
||||
} else {
|
||||
if (!args[current_type_id].add_type(
|
||||
last_annotation, build_type(current_node, state<Types>()),
|
||||
last_annotation,
|
||||
RunOther<nodes::Type, utils::None, nodes::Type>(current_node),
|
||||
last_before_modifier)) {
|
||||
logc.Fatal<Log::kProc>(
|
||||
{{"It is impossible to use argument modifiers (annotations, "
|
||||
|
|
@ -427,7 +430,7 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
|
|||
|
||||
if (are_annotations_same_to_names) {
|
||||
for (size_t i = 0; i < args.size(); ++i) {
|
||||
std::string new_annotation = args[i].get_name().value()->value;
|
||||
std::string new_annotation = args[i].name.value().value;
|
||||
if (!args[i].add_annotation(
|
||||
new_annotation.substr(1, new_annotation.size() - 1))) {
|
||||
logc.Fatal<Log::kProc>({{"no annotations provided ( => all annotations "
|
||||
|
|
@ -440,8 +443,8 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
|
|||
|
||||
std::unordered_set<std::string> annotations_set;
|
||||
for (auto &arg : args) {
|
||||
if (arg.get_annotation().has_value()) {
|
||||
if (!annotations_set.insert(*arg.get_annotation().value()).second) {
|
||||
if (arg.annotation.has_value()) {
|
||||
if (!annotations_set.insert(arg.annotation.value()).second) {
|
||||
logc.Fatal<Log::kProc>(
|
||||
{{"Two or more same annotations found in function definition"}},
|
||||
parser_node.get_pos());
|
||||
|
|
@ -450,7 +453,8 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
|
|||
}
|
||||
|
||||
return nodes::FunctionDefinition(
|
||||
build_symbol_docs(description_node, annotation_nodes, annotations_set),
|
||||
build_symbol_docs(description_node, annotation_nodes, annotations_set,
|
||||
executor),
|
||||
std::move(constraints), return_modifier, is_method, name_prefix,
|
||||
Run<nodes::Identifier>(name_node), std::move(args),
|
||||
are_annotations_same_to_names,
|
||||
|
|
|
|||
|
|
@ -2,14 +2,19 @@
|
|||
#include "basic_builders.hpp"
|
||||
#include "basic_nodes.hpp"
|
||||
#include "builtin_types.hpp"
|
||||
#include "error_handling.hpp"
|
||||
// #include "error_handling.hpp"
|
||||
#include "tokens.hpp"
|
||||
#include "type_nodes.hpp"
|
||||
|
||||
namespace builders {
|
||||
|
||||
nodes::Type build_type(parser::ParseTree::Node parser_node,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
using Tp = tokens::Type;
|
||||
using utils::TypeTag;
|
||||
|
||||
nodes::Type BuilderTask<nodes::Type>::operator()(const ParserNode &parser_node,
|
||||
const Args &) {
|
||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||
|
||||
tokens::Type type = tokens::string_to_type(parser_node.get_type());
|
||||
|
||||
// TODO: for better formatted printing
|
||||
|
|
@ -19,26 +24,29 @@ nodes::Type build_type(parser::ParseTree::Node parser_node,
|
|||
// maybe_parenthesis.get_value() == "(");
|
||||
|
||||
switch (type) {
|
||||
case tokens::Type::VARIANT_TYPE:
|
||||
return build_variant_type(parser_node, type_storage);
|
||||
case tokens::Type::TUPLE_TYPE:
|
||||
return build_tuple_type(parser_node, type_storage);
|
||||
case tokens::Type::REFERENCE_TYPE:
|
||||
return build_reference_type(parser_node, type_storage);
|
||||
case tokens::Type::MODIFIED_TYPE:
|
||||
return build_modified_type(parser_node, type_storage);
|
||||
case tokens::Type::SIMPLE_TYPE:
|
||||
return build_simple_type(parser_node, type_storage);
|
||||
case Tp::VARIANT_TYPE:
|
||||
return Run<nodes::Type, TypeTag<Tp::VARIANT_TYPE>>(parser_node);
|
||||
case Tp::TUPLE_TYPE:
|
||||
return Run<nodes::Type, TypeTag<Tp::TUPLE_TYPE>>(parser_node);
|
||||
case Tp::REFERENCE_TYPE:
|
||||
return Run<nodes::Type, TypeTag<Tp::REFERENCE_TYPE>>(parser_node);
|
||||
case Tp::MODIFIED_TYPE:
|
||||
return Run<nodes::Type, TypeTag<Tp::MODIFIED_TYPE>>(parser_node);
|
||||
case Tp::SIMPLE_TYPE:
|
||||
return Run<nodes::Type, TypeTag<Tp::SIMPLE_TYPE>>(parser_node);
|
||||
default:
|
||||
error_handling::handle_parsing_error("Unexprected type node type",
|
||||
parser_node);
|
||||
logc.Fatal<Log::kSys>({{"Unexprected type node type"}},
|
||||
parser_node.get_pos());
|
||||
}
|
||||
error_handling::handle_general_error("Unreachable");
|
||||
exit(1); // unreachable
|
||||
|
||||
utils::unreachable();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::vector<nodes::Type> collect_parameters(parser::ParseTree::Node first_node,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
Executor &executor) {
|
||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||
|
||||
std::vector<nodes::Type> parameters;
|
||||
|
||||
std::optional<std::string> current_annotation;
|
||||
|
|
@ -47,9 +55,11 @@ std::vector<nodes::Type> collect_parameters(parser::ParseTree::Node first_node,
|
|||
while (!current_node.is_null()) {
|
||||
if (tokens::string_to_type(current_node.get_type()) ==
|
||||
tokens::Type::ANNOTATION_IDENTIFIER) {
|
||||
current_annotation = build_annotation(current_node);
|
||||
current_annotation =
|
||||
BuilderTask<nodes::Annotation>{executor}(current_node, {}).value;
|
||||
} else {
|
||||
parameters.push_back(build_type(current_node, type_storage));
|
||||
parameters.push_back(
|
||||
BuilderTask<nodes::Type>{executor}(current_node, {}));
|
||||
if (current_annotation.has_value()) {
|
||||
parameters.back().get()->set_annotation(current_annotation.value());
|
||||
}
|
||||
|
|
@ -61,45 +71,55 @@ std::vector<nodes::Type> collect_parameters(parser::ParseTree::Node first_node,
|
|||
}
|
||||
|
||||
nodes::Type build_container_type(parser::ParseTree::Node parser_node,
|
||||
nodes::TypeStorage &type_storage,
|
||||
builtin::Type container) {
|
||||
std::vector<nodes::Type> parameters =
|
||||
collect_parameters(parser_node.nth_named_child(0), type_storage);
|
||||
Executor &executor, builtin::Type container) {
|
||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||
|
||||
return type_storage.add_container_of(std::move(parameters), container,
|
||||
build_node(parser_node));
|
||||
std::vector<nodes::Type> parameters =
|
||||
collect_parameters(parser_node.nth_named_child(0), executor);
|
||||
|
||||
return executor.state<Types>().add_container_of(std::move(parameters),
|
||||
container);
|
||||
}
|
||||
|
||||
// '|'? annotation? type ('|' annotation? type)+
|
||||
nodes::Type build_variant_type(parser::ParseTree::Node parser_node,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
return build_container_type(parser_node, type_storage,
|
||||
builtin::Type::VARIANT);
|
||||
nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::VARIANT_TYPE>>::operator()(
|
||||
const ParserNode &parser_node, const Args &) {
|
||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||
|
||||
return build_container_type(parser_node, executor, builtin::Type::VARIANT);
|
||||
}
|
||||
|
||||
// '&'? annotation? type ('&' annotation? type)+
|
||||
nodes::Type build_tuple_type(parser::ParseTree::Node parser_node,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
return build_container_type(parser_node, type_storage, builtin::Type::TUPLE);
|
||||
nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::TUPLE_TYPE>>::operator()(
|
||||
const ParserNode &parser_node, const Args &) {
|
||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||
|
||||
return build_container_type(parser_node, executor, builtin::Type::TUPLE);
|
||||
}
|
||||
|
||||
// _reference_ type
|
||||
nodes::Type build_reference_type(parser::ParseTree::Node parser_node,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
nodes::Type type = build_type(parser_node.nth_named_child(0), type_storage);
|
||||
type.get()->set_modifier(build_modifier(parser_node.nth_child(0)));
|
||||
nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::REFERENCE_TYPE>>::operator()(
|
||||
const ParserNode &parser_node, const Args &) {
|
||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||
|
||||
nodes::Type type = Run<nodes::Type>(parser_node.nth_named_child(0));
|
||||
type.get()->set_modifier(
|
||||
RunOther<nodes::Modifier, utils::None, nodes::Modifier>(
|
||||
parser_node.nth_child(0)));
|
||||
return type;
|
||||
}
|
||||
|
||||
// type ('?' | '!')
|
||||
nodes::Type build_modified_type(parser::ParseTree::Node parser_node,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::MODIFIED_TYPE>>::operator()(
|
||||
const ParserNode &parser_node, const Args &) {
|
||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||
|
||||
std::vector<nodes::Type> parameters;
|
||||
parameters.push_back(
|
||||
build_type(parser_node.nth_named_child(0), type_storage));
|
||||
parameters.push_back(Run<nodes::Type>(parser_node.nth_named_child(0)));
|
||||
|
||||
nodes::Modifier modifier =
|
||||
build_modifier(parser_node.nth_child(parser_node.child_count() - 1));
|
||||
RunOther<nodes::Modifier, utils::None, nodes::Modifier>(
|
||||
parser_node.nth_child(parser_node.child_count() - 1));
|
||||
|
||||
std::string identifier;
|
||||
|
||||
|
|
@ -111,27 +131,30 @@ nodes::Type build_modified_type(parser::ParseTree::Node parser_node,
|
|||
identifier = builtin::types::RESULT_IDENTIFIER;
|
||||
break;
|
||||
default:
|
||||
error_handling::handle_parsing_error(
|
||||
"Unexpected modifier type in modified type", parser_node);
|
||||
logc.Fatal<Log::kSys>({{"Unexpected modifier type in modified type"}},
|
||||
parser_node.get_pos());
|
||||
break;
|
||||
}
|
||||
|
||||
return type_storage.add_type(nodes::TypeData(
|
||||
nodes::Identifier(build_node(parser_node), nodes::Identifier::SIMPLE_TYPE,
|
||||
identifier),
|
||||
return executor.state<Types>().add_type(
|
||||
nodes::TypeData(nodes::Identifier{.kind = nodes::Identifier::kSimpleType,
|
||||
.value = identifier},
|
||||
std::move(parameters)));
|
||||
}
|
||||
|
||||
// type_identifier ('[' (annotation? type)+ ']')?
|
||||
nodes::Type build_simple_type(parser::ParseTree::Node parser_node,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::SIMPLE_TYPE>>::operator()(
|
||||
const ParserNode &parser_node, const Args &) {
|
||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||
|
||||
auto name_node = parser_node.child_by_field_name("name");
|
||||
|
||||
std::vector<nodes::Type> parameters =
|
||||
collect_parameters(name_node.next_named_sibling(), type_storage);
|
||||
collect_parameters(name_node.next_named_sibling(), executor);
|
||||
|
||||
return type_storage.add_type(
|
||||
nodes::TypeData(build_identifier(name_node), std::move(parameters)));
|
||||
return executor.state<Types>().add_type(nodes::TypeData(
|
||||
RunOther<nodes::Identifier, utils::None, nodes::Identifier>(name_node),
|
||||
std::move(parameters)));
|
||||
}
|
||||
|
||||
} // namespace builders
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "log.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
#include <format>
|
||||
#include <optional>
|
||||
#include <ranges>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace nodes {
|
||||
|
||||
|
|
@ -252,55 +253,55 @@ public:
|
|||
Kind kind;
|
||||
std::string value;
|
||||
|
||||
// TODO
|
||||
// TODO: rewrite identifier modification
|
||||
|
||||
// void append_before(const std::string &name) {
|
||||
// value_ = name + NAME_DELIMITER + value_;
|
||||
// }
|
||||
void append_before(std::string_view other) {
|
||||
value = std::format("{}{}{}", other, kNameDelimiter, value);
|
||||
}
|
||||
|
||||
// void append_before(
|
||||
// const Identifier &identifier,
|
||||
// std::source_location location = std::source_location::current()) {
|
||||
// error_handling::expect(identifier.type_ == type_,
|
||||
// "different Identifier types on append_before",
|
||||
// location);
|
||||
// value_ = *identifier.get() + NAME_DELIMITER + value_;
|
||||
// }
|
||||
void append_before(
|
||||
const Identifier &other,
|
||||
std::source_location source_location = std::source_location::current()) {
|
||||
::utils::Assert(other.kind == kind,
|
||||
"different Identifier types on append_before",
|
||||
source_location);
|
||||
value = std::format("{}{}{}", other.value, kNameDelimiter, value);
|
||||
}
|
||||
|
||||
// void append_after(const std::string &name) {
|
||||
// value_ += NAME_DELIMITER + name;
|
||||
// }
|
||||
void append_after(std::string_view other) {
|
||||
value += std::format("{}{}", kNameDelimiter, other);
|
||||
}
|
||||
|
||||
// void append_after(
|
||||
// const Identifier &identifier,
|
||||
// std::source_location location = std::source_location::current()) {
|
||||
// error_handling::expect(identifier.type_ == type_,
|
||||
// "different Identifier types on append_after",
|
||||
// location);
|
||||
// value_ += NAME_DELIMITER + *identifier.get();
|
||||
// }
|
||||
void append_after(
|
||||
const Identifier &other,
|
||||
std::source_location source_location = std::source_location::current()) {
|
||||
::utils::Assert(other.kind == kind,
|
||||
"different Identifier types on append_after",
|
||||
source_location);
|
||||
value += std::format("{}{}", kNameDelimiter, other.value);
|
||||
}
|
||||
|
||||
// std::vector<Identifier> get_fragments() const {
|
||||
// std::vector<Identifier> fragments;
|
||||
// for (auto &&fragment_name :
|
||||
// std::ranges::views::split(value_, NAME_DELIMITER)) {
|
||||
// fragments.emplace_back(
|
||||
// *this, type_,
|
||||
// std::string(fragment_name.begin(), fragment_name.end()));
|
||||
// }
|
||||
// return fragments;
|
||||
// }
|
||||
std::vector<Identifier> get_fragments() const {
|
||||
std::vector<Identifier> fragments;
|
||||
for (auto &&fragment_name :
|
||||
std::ranges::views::split(value, kNameDelimiter)) {
|
||||
fragments.push_back({
|
||||
.kind = kind,
|
||||
.value = std::string(fragment_name.begin(), fragment_name.end()),
|
||||
});
|
||||
}
|
||||
return fragments;
|
||||
}
|
||||
|
||||
// std::pair<Identifier, Identifier> split_first() {
|
||||
// const auto pos = value_.find(NAME_DELIMITER);
|
||||
// if (pos == std::string::npos) {
|
||||
// return {Identifier(*this, type_, ""), *this};
|
||||
// }
|
||||
// return {
|
||||
// Identifier(*this, type_, value_.substr(0, pos)),
|
||||
// Identifier(*this, type_, value_.substr(pos + 1))}; // '.' is leaved
|
||||
// out
|
||||
// }
|
||||
std::pair<Identifier, Identifier> split_first() {
|
||||
const auto pos = value.find(kNameDelimiter);
|
||||
if (pos == std::string::npos) {
|
||||
return {Identifier{.kind = kind, .value = {}}, *this};
|
||||
}
|
||||
return {Identifier{.kind = kind, .value = value.substr(0, pos)},
|
||||
Identifier{.kind = kind,
|
||||
.value = value.substr(pos + 1)}}; // '.' is leaved
|
||||
}
|
||||
};
|
||||
|
||||
struct Extra {
|
||||
|
|
|
|||
|
|
@ -197,7 +197,8 @@ class ExprData {
|
|||
public:
|
||||
using Type = std::variant<
|
||||
// --- flow control
|
||||
Match, Condition, Loop,
|
||||
// TODO: separate Case from Match
|
||||
Match, Match::Case, Condition, Loop,
|
||||
|
||||
// --- operators
|
||||
// CommaExpression is OperatorExpression for operator ','
|
||||
|
|
|
|||
|
|
@ -7,9 +7,12 @@ namespace nodes {
|
|||
|
||||
template <typename... Mixins> class Node_;
|
||||
|
||||
// TODO FIXME: always require is_scoped parameter
|
||||
struct NodeData {
|
||||
public:
|
||||
template <typename T> NodeData(T value) : value(std::move(value)) {}
|
||||
template <typename T>
|
||||
NodeData(T value, bool is_scoped = false)
|
||||
: value(std::move(value)), is_scoped(is_scoped) {}
|
||||
|
||||
template <typename T> std::optional<T *> get() {
|
||||
if (std::holds_alternative<T>(value)) {
|
||||
|
|
@ -31,6 +34,7 @@ public:
|
|||
|
||||
public:
|
||||
nodes::ExprData::Type value;
|
||||
bool is_scoped;
|
||||
};
|
||||
|
||||
class NodeStorage : public core::Storage<NodeData> {
|
||||
|
|
@ -79,8 +83,14 @@ public:
|
|||
//
|
||||
|
||||
template <typename T> T &part() { return NodePart<T>::data_[id_]; }
|
||||
template <typename T> const T &part() const {
|
||||
return NodePart<T>::data_[id_];
|
||||
}
|
||||
|
||||
template <typename T> T &get() { return std::get<T>(data_[id_].value); }
|
||||
template <typename T> const T &get() const {
|
||||
return std::get<T>(data_[id_].value);
|
||||
}
|
||||
|
||||
Id id() const { return id_; }
|
||||
|
||||
|
|
|
|||
|
|
@ -38,170 +38,109 @@ struct Constraint {
|
|||
};
|
||||
|
||||
struct FunctionDefinition {
|
||||
class Argument {
|
||||
struct Argument {
|
||||
public:
|
||||
Argument(const std::optional<std::string> &annotation, Identifier &&name,
|
||||
Modifier before_modifier = Modifier::NONE,
|
||||
Modifier after_modifier = Modifier::NONE)
|
||||
: annotation_(annotation), name_(std::move(name)),
|
||||
before_modifier_(before_modifier), after_modifier_(after_modifier) {}
|
||||
: annotation(annotation), name(std::move(name)),
|
||||
before_modifier(before_modifier), after_modifier(after_modifier) {}
|
||||
|
||||
Argument(const std::optional<std::string> &annotation,
|
||||
const Identifier &name, Modifier before_modifier = Modifier::NONE,
|
||||
Modifier after_modifier = Modifier::NONE)
|
||||
: annotation_(annotation), name_(name),
|
||||
before_modifier_(before_modifier), after_modifier_(after_modifier) {}
|
||||
: annotation(annotation), name(name), before_modifier(before_modifier),
|
||||
after_modifier(after_modifier) {}
|
||||
|
||||
Argument(const std::optional<std::string> &annotation, Type type,
|
||||
Modifier before_modifier = Modifier::NONE)
|
||||
: annotation_(annotation), type_(type),
|
||||
before_modifier_(before_modifier),
|
||||
after_modifier_(
|
||||
: annotation(annotation), type(type), before_modifier(before_modifier),
|
||||
after_modifier(
|
||||
builtin::types::get_modifier(type.get()->to_builtin())) {}
|
||||
|
||||
//
|
||||
|
||||
// add type with same annotation and same before_modifier
|
||||
bool update_type_from(const Argument &other) {
|
||||
if (type_.has_value() || !other.type_.has_value()) {
|
||||
if (type.has_value() || !other.type.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (annotation_.has_value() &&
|
||||
(!other.annotation_.has_value() ||
|
||||
annotation_.value() != other.annotation_.value())) {
|
||||
if (annotation.has_value() &&
|
||||
(!other.annotation.has_value() ||
|
||||
annotation.value() != other.annotation.value())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (before_modifier_ != other.before_modifier_) {
|
||||
if (before_modifier != other.before_modifier) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (after_modifier_ != other.after_modifier_) {
|
||||
if (after_modifier != other.after_modifier) {
|
||||
return false;
|
||||
}
|
||||
|
||||
annotation_ = other.annotation_;
|
||||
type_ = other.type_;
|
||||
before_modifier_ = other.before_modifier_;
|
||||
after_modifier_ = other.after_modifier_;
|
||||
annotation = other.annotation;
|
||||
type = other.type;
|
||||
before_modifier = other.before_modifier;
|
||||
after_modifier = other.after_modifier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// check, that argument modifiers are none or same to different from type
|
||||
// modifiers
|
||||
bool add_type(const std::optional<std::string> &annotation, Type type,
|
||||
nodes::Modifier before_modifier = Modifier::NONE) {
|
||||
if (type_.has_value()) {
|
||||
bool add_type(const std::optional<std::string> &new_annotation,
|
||||
Type new_type,
|
||||
nodes::Modifier new_before_modifier = Modifier::NONE) {
|
||||
if (type.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (annotation_.has_value() &&
|
||||
(!annotation.has_value() ||
|
||||
annotation_.value() != annotation.value())) {
|
||||
if (annotation.has_value() &&
|
||||
(!new_annotation.has_value() ||
|
||||
annotation.value() != new_annotation.value())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (before_modifier_ != Modifier::NONE &&
|
||||
before_modifier_ != before_modifier) {
|
||||
if (before_modifier != Modifier::NONE &&
|
||||
before_modifier != new_before_modifier) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto type_after_modifier =
|
||||
builtin::types::get_modifier(type.get()->to_builtin());
|
||||
builtin::types::get_modifier(new_type.get()->to_builtin());
|
||||
|
||||
if (after_modifier_ != Modifier::NONE &&
|
||||
after_modifier_ != type_after_modifier) {
|
||||
if (after_modifier != Modifier::NONE &&
|
||||
after_modifier != type_after_modifier) {
|
||||
return false;
|
||||
}
|
||||
|
||||
annotation_ = annotation;
|
||||
type_ = type;
|
||||
before_modifier_ = before_modifier;
|
||||
after_modifier_ = type_after_modifier;
|
||||
annotation = new_annotation;
|
||||
type = new_type;
|
||||
before_modifier = new_before_modifier;
|
||||
after_modifier = type_after_modifier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool add_annotation(const std::string &annotation) {
|
||||
if (annotation_.has_value()) {
|
||||
bool add_annotation(const std::string &new_annotation) {
|
||||
if (annotation.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
annotation_ = annotation;
|
||||
annotation = new_annotation;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
std::optional<std::string *> get_annotation() {
|
||||
if (annotation_.has_value()) {
|
||||
return &annotation_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const std::string *> get_annotation() const {
|
||||
if (annotation_.has_value()) {
|
||||
return &annotation_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
std::optional<Identifier *> get_name() {
|
||||
if (name_.has_value()) {
|
||||
return &name_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const Identifier *> get_name() const {
|
||||
if (name_.has_value()) {
|
||||
return &name_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
std::optional<TypeData *> get_type() {
|
||||
if (type_.has_value()) {
|
||||
return type_.value().get();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const TypeData *> get_type() const {
|
||||
if (type_.has_value()) {
|
||||
return type_.value().get();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<Type> get_type_proxy() const {
|
||||
if (type_.has_value()) {
|
||||
return type_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Modifier get_before_modifier() const { return before_modifier_; }
|
||||
|
||||
Modifier get_after_modifier() const { return after_modifier_; }
|
||||
|
||||
private:
|
||||
std::optional<std::string> annotation_;
|
||||
std::optional<Identifier> name_; // no name for output args
|
||||
std::optional<Type> type_; // no type if it is deduced
|
||||
Modifier before_modifier_ =
|
||||
public:
|
||||
std::optional<std::string> annotation;
|
||||
std::optional<Identifier> name; // no name for output args
|
||||
std::optional<Type> type; // no type if it is deduced
|
||||
Modifier before_modifier =
|
||||
Modifier::NONE; // in, out, ref, none // sync with type
|
||||
Modifier after_modifier_ =
|
||||
Modifier after_modifier =
|
||||
Modifier::NONE; // optional, result, none // sync with type
|
||||
};
|
||||
|
||||
|
|
@ -267,15 +206,15 @@ public:
|
|||
//
|
||||
|
||||
template <typename T> std::optional<T *> get() {
|
||||
if (std::holds_alternative<T>(expr)) {
|
||||
return &std::get<T>(expr);
|
||||
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>(expr)) {
|
||||
return &std::get<T>(expr);
|
||||
if (std::holds_alternative<T>(value)) {
|
||||
return &std::get<T>(value);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
|
@ -286,7 +225,7 @@ public:
|
|||
|
||||
//
|
||||
|
||||
Type expr;
|
||||
Type value;
|
||||
};
|
||||
|
||||
} // namespace nodes
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "statement_nodes.hpp"
|
||||
|
||||
// #include "error_handling.hpp"
|
||||
#include "error_handling.hpp"
|
||||
#include "utils.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
|
|
@ -62,55 +60,50 @@ CombineResult FunctionDefinition::combine(FunctionDefinition &&other) {
|
|||
if (i < args.size() && i < other.args.size()) {
|
||||
|
||||
// annotations should be the same
|
||||
if ((!args[i].get_annotation().has_value() &&
|
||||
!other.args[i].get_annotation().has_value()) ||
|
||||
(args[i].get_annotation().has_value() &&
|
||||
other.args[i].get_annotation().has_value() &&
|
||||
*args[i].get_annotation().value() !=
|
||||
*other.args[i].get_annotation().value())) {
|
||||
if ((!args[i].annotation.has_value() &&
|
||||
!other.args[i].annotation.has_value()) ||
|
||||
(args[i].annotation.has_value() &&
|
||||
other.args[i].annotation.has_value() &&
|
||||
args[i].annotation.value() != other.args[i].annotation.value())) {
|
||||
return CombineResult::ARGUMENTS_ERROR;
|
||||
}
|
||||
|
||||
// argument names should be the same
|
||||
if ((!args[i].get_name().has_value() &&
|
||||
!other.args[i].get_name().has_value()) ||
|
||||
(args[i].get_name().has_value() &&
|
||||
other.args[i].get_name().has_value() &&
|
||||
args[i].get_name().value() != other.args[i].get_name().value())) {
|
||||
if ((!args[i].name.has_value() && !other.args[i].name.has_value()) ||
|
||||
(args[i].name.has_value() && other.args[i].name.has_value() &&
|
||||
args[i].name.value() != other.args[i].name.value())) {
|
||||
return CombineResult::ARGUMENTS_ERROR;
|
||||
}
|
||||
|
||||
// types should be the same (if present in both definitions)
|
||||
if (args[i].get_type().has_value() &&
|
||||
other.args[i].get_type().has_value() &&
|
||||
*args[i].get_type().value() != *other.args[i].get_type().value()) {
|
||||
if (args[i].type.has_value() && other.args[i].type.has_value() &&
|
||||
args[i].type.value() != other.args[i].type.value()) {
|
||||
return CombineResult::ARGUMENTS_ERROR;
|
||||
}
|
||||
|
||||
// argument modifiers should be the same
|
||||
if (args[i].get_before_modifier() !=
|
||||
other.args[i].get_before_modifier() ||
|
||||
args[i].get_after_modifier() != other.args[i].get_after_modifier()) {
|
||||
if (args[i].before_modifier != other.args[i].before_modifier ||
|
||||
args[i].after_modifier != other.args[i].after_modifier) {
|
||||
return CombineResult::ARGUMENTS_ERROR;
|
||||
}
|
||||
} else if (i < args.size()) {
|
||||
// annotations should be the same
|
||||
if (args[i].get_annotation().has_value()) {
|
||||
if (args[i].annotation.has_value()) {
|
||||
return CombineResult::ARGUMENTS_ERROR;
|
||||
}
|
||||
|
||||
// names should be the same
|
||||
if (args[i].get_name().has_value()) {
|
||||
if (args[i].name.has_value()) {
|
||||
return CombineResult::ARGUMENTS_ERROR;
|
||||
}
|
||||
} else { // i < other_function_definition.size()
|
||||
// annotations should be the same
|
||||
if (other.args[i].get_annotation().has_value()) {
|
||||
if (other.args[i].annotation.has_value()) {
|
||||
return CombineResult::ARGUMENTS_ERROR;
|
||||
}
|
||||
|
||||
// names should be the same
|
||||
if (other.args[i].get_name().has_value()) {
|
||||
if (other.args[i].name.has_value()) {
|
||||
return CombineResult::ARGUMENTS_ERROR;
|
||||
}
|
||||
}
|
||||
|
|
@ -138,13 +131,11 @@ CombineResult FunctionDefinition::combine(FunctionDefinition &&other) {
|
|||
|
||||
for (size_t i = 0; i < other.args.size(); ++i) {
|
||||
if (i < args.size()) {
|
||||
if (other.args[i].get_type().has_value()) {
|
||||
if (args[i].update_type_from(other.args[i])) {
|
||||
error_handling::handle_internal_error(
|
||||
if (other.args[i].type.has_value()) {
|
||||
::utils::Assert(
|
||||
not args[i].update_type_from(other.args[i]),
|
||||
"Function arguments are not properly checked before merging "
|
||||
"during combination",
|
||||
*this);
|
||||
}
|
||||
"during combination"); // TODO: proper log error
|
||||
}
|
||||
} else {
|
||||
args.push_back(std::move(other.args[i]));
|
||||
|
|
@ -231,19 +222,19 @@ CombineResult TypeDefinition::combine(TypeDefinition &&other) {
|
|||
}
|
||||
|
||||
bool Statement::is_same_to(const Statement &other) const {
|
||||
if (expr.index() != other.expr.index()) {
|
||||
if (value.index() != other.value.index()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (expr.index()) {
|
||||
switch (value.index()) {
|
||||
case 0: // Import
|
||||
return false;
|
||||
case 1: // TypeDefinition
|
||||
return std::get<TypeDefinition>(expr).is_same_to(
|
||||
std::move(std::get<TypeDefinition>(other.expr)));
|
||||
return std::get<TypeDefinition>(value).is_same_to(
|
||||
std::move(std::get<TypeDefinition>(other.value)));
|
||||
case 2: // FunctionDefinition
|
||||
return std::get<FunctionDefinition>(expr).is_same_to(
|
||||
std::move(std::get<FunctionDefinition>(other.expr)));
|
||||
return std::get<FunctionDefinition>(value).is_same_to(
|
||||
std::move(std::get<FunctionDefinition>(other.value)));
|
||||
case 3: // Extra
|
||||
return false;
|
||||
case 4: // EmptyLines
|
||||
|
|
@ -259,30 +250,31 @@ bool Statement::is_same_to(const Statement &other) const {
|
|||
}
|
||||
|
||||
CombineResult Statement::combine(Statement &&other) {
|
||||
if (expr.index() != other.expr.index()) {
|
||||
if (value.index() != other.value.index()) {
|
||||
return CombineResult::DIFFERENT_STATEMENT_TYPES;
|
||||
}
|
||||
|
||||
switch (expr.index()) {
|
||||
switch (value.index()) {
|
||||
case 0: // Import
|
||||
return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR;
|
||||
case 1: // TypeDefinition
|
||||
return std::get<TypeDefinition>(expr).combine(
|
||||
std::move(std::get<TypeDefinition>(other.expr)));
|
||||
return std::get<TypeDefinition>(value).combine(
|
||||
std::move(std::get<TypeDefinition>(other.value)));
|
||||
case 2: // FunctionDefinition
|
||||
return std::get<FunctionDefinition>(expr).combine(
|
||||
std::move(std::get<FunctionDefinition>(other.expr)));
|
||||
return std::get<FunctionDefinition>(value).combine(
|
||||
std::move(std::get<FunctionDefinition>(other.value)));
|
||||
case 3: // Extra
|
||||
return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR;
|
||||
case 4: // EmptyLines
|
||||
return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR;
|
||||
default:
|
||||
error_handling::handle_general_error(
|
||||
"Unexpected statement type in combine");
|
||||
::utils::Assert(
|
||||
false,
|
||||
"Unexpected statement type in combine"); // TODO: log context
|
||||
break;
|
||||
}
|
||||
|
||||
error_handling::handle_general_error("Unreachable");
|
||||
::utils::Assert(false, "Unreachable"); // TODO: log context
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,147 +1,79 @@
|
|||
#pragma once
|
||||
|
||||
#include "basic_nodes.hpp"
|
||||
#include <iostream>
|
||||
#include "printers_utils.hpp"
|
||||
|
||||
namespace printers {
|
||||
|
||||
class Printer {
|
||||
public:
|
||||
Printer(std::ostream &output, size_t tab_width, size_t width_limit,
|
||||
bool print_words_instead_of_symbols)
|
||||
: output_(output), tab_width_(tab_width), width_limit_(width_limit),
|
||||
print_words_instead_of_symbols_(print_words_instead_of_symbols),
|
||||
current_position_(0), indentation_level_(0) {}
|
||||
// void print(const nodes::Modifier &modifier, Printer &printer,
|
||||
// bool const_is_none = false);
|
||||
template <>
|
||||
struct PrintTask<nodes::Modifier> : public PrintTaskBase<nodes::Modifier> {
|
||||
using PrintTaskBase<nodes::Modifier>::PrintTaskBase;
|
||||
|
||||
void print_converted(const std::string &value) {
|
||||
for (auto &ch : value) {
|
||||
output_ << to_printable_symbol(ch);
|
||||
current_position_ += to_printable_symbol(ch).size();
|
||||
}
|
||||
}
|
||||
|
||||
// value shouldn't contain '\n', '\t', etc.
|
||||
void print(const std::string &value) {
|
||||
output_ << value;
|
||||
current_position_ += value.size();
|
||||
}
|
||||
|
||||
void column_down() {
|
||||
size_t current_position = current_position_;
|
||||
end_line();
|
||||
print_spaces(current_position);
|
||||
}
|
||||
|
||||
void new_indent_line() {
|
||||
end_line();
|
||||
print_spaces(indentation_level_);
|
||||
}
|
||||
|
||||
void new_line(size_t indentation) {
|
||||
end_line();
|
||||
print_spaces(indentation);
|
||||
}
|
||||
|
||||
void to_indentation_level() {
|
||||
if (indentation_level_ > current_position_) {
|
||||
print_spaces(indentation_level_ - current_position_);
|
||||
}
|
||||
}
|
||||
|
||||
void indent() { indentation_level_ += tab_width_; }
|
||||
|
||||
void deindent() { indentation_level_ -= tab_width_; }
|
||||
|
||||
void tab() { print_spaces(tab_width_); }
|
||||
|
||||
void space() { print_spaces(1); }
|
||||
|
||||
size_t current_position() const { return current_position_; }
|
||||
|
||||
size_t width_limit() const { return width_limit_; }
|
||||
|
||||
size_t width_left() const {
|
||||
return std::max(static_cast<int64_t>(width_limit_) -
|
||||
static_cast<int64_t>(current_position_),
|
||||
static_cast<int64_t>(0));
|
||||
}
|
||||
|
||||
bool print_words_instead_of_symbols() const {
|
||||
return print_words_instead_of_symbols_;
|
||||
}
|
||||
|
||||
size_t get_current_position() const { return current_position_; }
|
||||
|
||||
size_t get_indentation_level() const { return indentation_level_; }
|
||||
|
||||
void set_indentation_level(size_t indentation_level) {
|
||||
indentation_level_ = indentation_level;
|
||||
}
|
||||
|
||||
private:
|
||||
void end_line() {
|
||||
output_ << "\n";
|
||||
current_position_ = 0;
|
||||
}
|
||||
void print_spaces(size_t n) { print(std::string(n, ' ')); }
|
||||
|
||||
static std::string to_printable_symbol(char ch) {
|
||||
switch (ch) {
|
||||
case '\a':
|
||||
return "\\a";
|
||||
case '\b':
|
||||
return "\\b";
|
||||
case '\e':
|
||||
return "\\e";
|
||||
case '\f':
|
||||
return "\\f";
|
||||
case '\n':
|
||||
return "\\n";
|
||||
case '\r':
|
||||
return "\\r";
|
||||
case '\t':
|
||||
return "\\t";
|
||||
case '\v':
|
||||
return "\\v";
|
||||
case '\'':
|
||||
return "\\\'";
|
||||
case '\"':
|
||||
return "\\\"";
|
||||
// case ' ':
|
||||
// return "\\s";
|
||||
default:
|
||||
return std::string(1, ch);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream &output_;
|
||||
size_t tab_width_ = 0;
|
||||
size_t width_limit_ = 0;
|
||||
bool print_words_instead_of_symbols_ = false;
|
||||
|
||||
size_t current_position_ = 0;
|
||||
size_t indentation_level_ = 0;
|
||||
Result operator()(const nodes::Modifier &modifier, const Args &args) override;
|
||||
};
|
||||
|
||||
void print(const nodes::Modifier &modifier, Printer &printer,
|
||||
bool const_is_none = false);
|
||||
// void print(const nodes::Literal &literal, Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::Literal> : public PrintTaskBase<nodes::Literal> {
|
||||
using PrintTaskBase<nodes::Literal>::PrintTaskBase;
|
||||
|
||||
void print(const nodes::Literal &literal, Printer &printer);
|
||||
Result operator()(const nodes::Literal &literal, const Args &args) override;
|
||||
};
|
||||
|
||||
void print(const nodes::Identifier &identifier, Printer &printer);
|
||||
// void print(const nodes::Identifier &identifier, Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::Identifier> : public PrintTaskBase<nodes::Identifier> {
|
||||
using PrintTaskBase<nodes::Identifier>::PrintTaskBase;
|
||||
|
||||
void print_annotation(const std::string &annotation, Printer &printer);
|
||||
Result operator()(const nodes::Identifier &identifier,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
void print(const nodes::Extra &extra, Printer &printer);
|
||||
// void print_annotation(const nodes::Annotation &annotation, Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::Annotation> : public PrintTaskBase<nodes::Annotation> {
|
||||
using PrintTaskBase<nodes::Annotation>::PrintTaskBase;
|
||||
|
||||
void print(const nodes::EmptyLines &empty_lines, Printer &printer);
|
||||
Result operator()(const nodes::Annotation &annotation,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
// void print(const nodes::Extra &extra, Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::Extra> : public PrintTaskBase<nodes::Extra> {
|
||||
using PrintTaskBase<nodes::Extra>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::Extra &extra, const Args &args) override;
|
||||
};
|
||||
|
||||
// void print(const nodes::EmptyLines &empty_lines, Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::EmptyLines> : public PrintTaskBase<nodes::EmptyLines> {
|
||||
using PrintTaskBase<nodes::EmptyLines>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::EmptyLines &empty_lines,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
// template <typename T>
|
||||
// inline void print(const std::vector<T> &nodes, Printer &printer) {
|
||||
// for (const auto &node : nodes) {
|
||||
// print(node, printer);
|
||||
// }
|
||||
// }
|
||||
template <typename T>
|
||||
inline void print(const std::vector<T> &nodes, Printer &printer) {
|
||||
for (const auto &node : nodes) {
|
||||
print(node, printer);
|
||||
struct PrintTask<std::vector<T>> : public PrintTaskBase<std::vector<T>> {
|
||||
using PrintTaskBase<std::vector<T>>::PrintTaskBase;
|
||||
|
||||
Result operator()(const std::vector<T> &exprs, const Args &args) override {
|
||||
for (const auto &expr : exprs) {
|
||||
PrintTaskBase<std::vector<T>>::Run(expr, args);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace printers
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
namespace printers {
|
||||
|
||||
void print(const nodes::SymbolDocs &docs, Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::SymbolDocs> : public PrintTaskBase<nodes::SymbolDocs> {
|
||||
using PrintTaskBase<nodes::SymbolDocs>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::SymbolDocs &docs, const Args &args) override;
|
||||
};
|
||||
|
||||
} // namespace printers
|
||||
|
|
|
|||
|
|
@ -1,44 +1,129 @@
|
|||
#pragma once
|
||||
|
||||
#include "basic_printers.hpp"
|
||||
#include "expression_nodes.hpp"
|
||||
#include "printers_utils.hpp"
|
||||
|
||||
namespace printers {
|
||||
|
||||
void print(const nodes::ExprData &expression, printers::Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::NodeId> : public PrintTaskBase<nodes::NodeId> {
|
||||
using PrintTaskBase<nodes::NodeId>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::NodeId &expr, const Args &args) override;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrintTask<nodes::NodeData> : public PrintTaskBase<nodes::NodeData> {
|
||||
using PrintTaskBase<nodes::NodeData>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::NodeData &expr, const Args &args) override;
|
||||
};
|
||||
|
||||
// --- flow control
|
||||
|
||||
void print(const nodes::Match::Case &expression, Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::Match::Case>
|
||||
: public PrintTaskBase<nodes::Match::Case> {
|
||||
using PrintTaskBase<nodes::Match::Case>::PrintTaskBase;
|
||||
|
||||
void print(const nodes::Match &expression, printers::Printer &printer);
|
||||
Result operator()(const nodes::Match::Case &expr, const Args &args) override;
|
||||
};
|
||||
|
||||
void print(const nodes::Condition &expression, printers::Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::Match> : public PrintTaskBase<nodes::Match> {
|
||||
using PrintTaskBase<nodes::Match>::PrintTaskBase;
|
||||
|
||||
void print(const nodes::Loop &expression, printers::Printer &printer);
|
||||
Result operator()(const nodes::Match &expr, const Args &args) override;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrintTask<nodes::Condition> : public PrintTaskBase<nodes::Condition> {
|
||||
using PrintTaskBase<nodes::Condition>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::Condition &expr, const Args &args) override;
|
||||
};
|
||||
|
||||
template <> struct PrintTask<nodes::Loop> : public PrintTaskBase<nodes::Loop> {
|
||||
using PrintTaskBase<nodes::Loop>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::Loop &expr, const Args &args) override;
|
||||
};
|
||||
|
||||
// --- containers
|
||||
|
||||
void print(const nodes::Container &expression, printers::Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::Container> : public PrintTaskBase<nodes::Container> {
|
||||
using PrintTaskBase<nodes::Container>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::Container &expr, const Args &args) override;
|
||||
};
|
||||
|
||||
// --- modifiers
|
||||
|
||||
void print(const nodes::Return &expression, printers::Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::Return> : public PrintTaskBase<nodes::Return> {
|
||||
using PrintTaskBase<nodes::Return>::PrintTaskBase;
|
||||
|
||||
void print(const nodes::NameDefinition &expression, printers::Printer &printer);
|
||||
Result operator()(const nodes::Return &expr, const Args &args) override;
|
||||
};
|
||||
|
||||
void print(const nodes::Access &expression, printers::Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::NameDefinition>
|
||||
: public PrintTaskBase<nodes::NameDefinition> {
|
||||
using PrintTaskBase<nodes::NameDefinition>::PrintTaskBase;
|
||||
|
||||
void print(const nodes::LoopControl &expression, printers::Printer &printer);
|
||||
Result operator()(const nodes::NameDefinition &expr,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
void print(const nodes::ModifierExpression &expression,
|
||||
printers::Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::Access> : public PrintTaskBase<nodes::Access> {
|
||||
using PrintTaskBase<nodes::Access>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::Access &expr, const Args &args) override;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrintTask<nodes::LoopControl>
|
||||
: public PrintTaskBase<nodes::LoopControl> {
|
||||
using PrintTaskBase<nodes::LoopControl>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::LoopControl &expr, const Args &args) override;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrintTask<nodes::ModifierExpression>
|
||||
: public PrintTaskBase<nodes::ModifierExpression> {
|
||||
using PrintTaskBase<nodes::ModifierExpression>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::ModifierExpression &expr,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
// --- other
|
||||
|
||||
void print(const nodes::NameExpression &expression, printers::Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::NameExpression>
|
||||
: public PrintTaskBase<nodes::NameExpression> {
|
||||
using PrintTaskBase<nodes::NameExpression>::PrintTaskBase;
|
||||
|
||||
void print(const nodes::Constructor &expression, printers::Printer &printer);
|
||||
Result operator()(const nodes::NameExpression &expr,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
void print(const nodes::Lambda &expression, printers::Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::Constructor>
|
||||
: public PrintTaskBase<nodes::Constructor> {
|
||||
using PrintTaskBase<nodes::Constructor>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::Constructor &expr, const Args &args) override;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrintTask<nodes::Lambda> : public PrintTaskBase<nodes::Lambda> {
|
||||
using PrintTaskBase<nodes::Lambda>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::Lambda &expr, const Args &args) override;
|
||||
};
|
||||
|
||||
} // namespace printers
|
||||
|
|
|
|||
212
lang/printers/include/printers_utils.hpp
Normal file
212
lang/printers/include/printers_utils.hpp
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
#pragma once
|
||||
|
||||
#include "executor.hpp"
|
||||
#include "nodes_storage.hpp"
|
||||
namespace printers {
|
||||
|
||||
class Printer {
|
||||
public:
|
||||
Printer(std::ostream &output, size_t tab_width, size_t width_limit,
|
||||
bool print_words_instead_of_symbols)
|
||||
: output_(output), tab_width_(tab_width), width_limit_(width_limit),
|
||||
print_words_instead_of_symbols_(print_words_instead_of_symbols),
|
||||
current_position_(0), indentation_level_(0) {}
|
||||
|
||||
void PrintConverted(std::string_view value) {
|
||||
for (auto &ch : value) {
|
||||
output_ << ToPrintableSymbol(ch);
|
||||
current_position_ += ToPrintableSymbol(ch).size();
|
||||
}
|
||||
}
|
||||
|
||||
// value shouldn't contain '\n', '\t', etc.
|
||||
void Print(std::string_view value) {
|
||||
output_ << value;
|
||||
current_position_ += value.size();
|
||||
}
|
||||
|
||||
void ColumnDown() {
|
||||
size_t current_position = current_position_;
|
||||
EndLine();
|
||||
PrintSpaces(current_position);
|
||||
}
|
||||
|
||||
void NewIndentLine() {
|
||||
EndLine();
|
||||
PrintSpaces(indentation_level_);
|
||||
}
|
||||
|
||||
void NewLine(size_t indentation) {
|
||||
EndLine();
|
||||
PrintSpaces(indentation);
|
||||
}
|
||||
|
||||
void ToIndentationLevel() {
|
||||
if (indentation_level_ > current_position_) {
|
||||
PrintSpaces(indentation_level_ - current_position_);
|
||||
}
|
||||
}
|
||||
|
||||
void Indent() { indentation_level_ += tab_width_; }
|
||||
|
||||
void Deindent() { indentation_level_ -= tab_width_; }
|
||||
|
||||
void Tab() { PrintSpaces(tab_width_); }
|
||||
|
||||
void Space() { PrintSpaces(1); }
|
||||
|
||||
void SetIndentationLevel(size_t indentation) {
|
||||
indentation_level_ = indentation;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
bool words_instead_of_symbols() const {
|
||||
return print_words_instead_of_symbols_;
|
||||
}
|
||||
|
||||
size_t current_position() const { return current_position_; }
|
||||
|
||||
size_t width_limit() const { return width_limit_; }
|
||||
|
||||
size_t width_left() const {
|
||||
return std::max(static_cast<int64_t>(width_limit_) -
|
||||
static_cast<int64_t>(current_position_),
|
||||
static_cast<int64_t>(0));
|
||||
}
|
||||
|
||||
size_t indentation_level() const { return indentation_level_; }
|
||||
|
||||
private:
|
||||
void EndLine() {
|
||||
output_ << "\n";
|
||||
current_position_ = 0;
|
||||
}
|
||||
void PrintSpaces(size_t n) { Print(std::string(n, ' ')); }
|
||||
|
||||
static std::string ToPrintableSymbol(char ch) {
|
||||
switch (ch) {
|
||||
case '\a':
|
||||
return "\\a";
|
||||
case '\b':
|
||||
return "\\b";
|
||||
case '\e':
|
||||
return "\\e";
|
||||
case '\f':
|
||||
return "\\f";
|
||||
case '\n':
|
||||
return "\\n";
|
||||
case '\r':
|
||||
return "\\r";
|
||||
case '\t':
|
||||
return "\\t";
|
||||
case '\v':
|
||||
return "\\v";
|
||||
case '\'':
|
||||
return "\\\'";
|
||||
case '\"':
|
||||
return "\\\"";
|
||||
// case ' ':
|
||||
// return "\\s";
|
||||
default:
|
||||
return std::string(1, ch);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream &output_;
|
||||
size_t tab_width_ = 0;
|
||||
size_t width_limit_ = 0;
|
||||
bool print_words_instead_of_symbols_ = false;
|
||||
|
||||
size_t current_position_ = 0;
|
||||
size_t indentation_level_ = 0;
|
||||
};
|
||||
|
||||
using Exprs = nodes::NodeStorage; // nodes::ExprStorage;
|
||||
|
||||
using Executor = utils::Executor<Exprs, Printer>;
|
||||
|
||||
using Node = nodes::Node_<>;
|
||||
|
||||
struct Args {
|
||||
// TODO FIXME
|
||||
bool const_is_none = false;
|
||||
};
|
||||
|
||||
using Result = utils::None;
|
||||
|
||||
template <typename N> using Task = utils::Task<Executor, Result, Args, N>;
|
||||
|
||||
template <typename N> struct PrintTask {
|
||||
static_assert(false);
|
||||
};
|
||||
|
||||
template <typename N> struct PrintTaskBase : public Task<N> {
|
||||
using Task<N>::Task;
|
||||
|
||||
Node Ext(storage::Id id) { return Node(id, this->template state<Exprs>()); }
|
||||
|
||||
template <typename OtherN>
|
||||
Result Run(const OtherN &node, const Args &args = {}) {
|
||||
PrintTask<OtherN> task(this->executor);
|
||||
return task(node, args);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void PrintConverted(const std::string_view value) {
|
||||
Task<N>::template state<Printer>().PrintConverted(value);
|
||||
}
|
||||
|
||||
// value shouldn't contain '\n', '\t', etc.
|
||||
void Print(std::string_view value) {
|
||||
Task<N>::template state<Printer>().Print(value);
|
||||
}
|
||||
|
||||
void ColumnDown() { Task<N>::template state<Printer>().ColumnDown(); }
|
||||
|
||||
void NewIndentLine() { Task<N>::template state<Printer>().NewIndentLine(); }
|
||||
|
||||
void NewLine(size_t indentation) {
|
||||
Task<N>::template state<Printer>().NewLine(indentation);
|
||||
}
|
||||
|
||||
void ToIndentationLevel() {
|
||||
Task<N>::template state<Printer>().ToIndentationLevel();
|
||||
}
|
||||
|
||||
void Indent() { Task<N>::template state<Printer>().Indent(); }
|
||||
|
||||
void Deindent() { Task<N>::template state<Printer>().Deindent(); }
|
||||
|
||||
void Tab() { Task<N>::template state<Printer>().Tab(); }
|
||||
|
||||
void Space() { Task<N>::template state<Printer>().Space(); }
|
||||
|
||||
void SetIndentationLevel(size_t indentation) {
|
||||
Task<N>::template state<Printer>().SetIndentationLevel(indentation);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
bool words_instead_of_symbols() const {
|
||||
return Task<N>::template state<Printer>().words_instead_of_symbols();
|
||||
}
|
||||
|
||||
size_t current_position() const {
|
||||
return Task<N>::template state<Printer>().current_position();
|
||||
}
|
||||
|
||||
size_t width_limit() const {
|
||||
return Task<N>::template state<Printer>().width_limit();
|
||||
}
|
||||
|
||||
size_t width_left() const { Task<N>::template state<Printer>().width_left(); }
|
||||
|
||||
size_t indentation_level() const {
|
||||
return Task<N>::template state<Printer>().indentation_level();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace printers
|
||||
|
|
@ -1,23 +1,52 @@
|
|||
#pragma once
|
||||
|
||||
#include "basic_printers.hpp"
|
||||
#include "printers_utils.hpp"
|
||||
#include "statement_nodes.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace printers {
|
||||
|
||||
// void print_source_file(const std::vector<nodes::Statement> &statements,
|
||||
// Printer &printer);
|
||||
|
||||
void print(const nodes::Statement &statements, Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::Statement> : public PrintTaskBase<nodes::Statement> {
|
||||
using PrintTaskBase<nodes::Statement>::PrintTaskBase;
|
||||
|
||||
void print(const nodes::Import &statement, Printer &printer);
|
||||
Result operator()(const nodes::Statement &statement,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
void print(const nodes::Constraint &statement, Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::Import> : public PrintTaskBase<nodes::Import> {
|
||||
using PrintTaskBase<nodes::Import>::PrintTaskBase;
|
||||
|
||||
void print(const nodes::TypeDefinition &statement, Printer &printer);
|
||||
Result operator()(const nodes::Import &statement, const Args &args) override;
|
||||
};
|
||||
|
||||
void print(const nodes::FunctionDefinition &statement, Printer &printer);
|
||||
template <>
|
||||
struct PrintTask<nodes::Constraint> : public PrintTaskBase<nodes::Constraint> {
|
||||
using PrintTaskBase<nodes::Constraint>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::Constraint &statement,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrintTask<nodes::TypeDefinition>
|
||||
: public PrintTaskBase<nodes::TypeDefinition> {
|
||||
using PrintTaskBase<nodes::TypeDefinition>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::TypeDefinition &statement,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrintTask<nodes::FunctionDefinition>
|
||||
: public PrintTaskBase<nodes::FunctionDefinition> {
|
||||
using PrintTaskBase<nodes::FunctionDefinition>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::FunctionDefinition &statement,
|
||||
const Args &args) override;
|
||||
};
|
||||
|
||||
} // namespace printers
|
||||
|
|
|
|||
|
|
@ -5,7 +5,18 @@
|
|||
|
||||
namespace printers {
|
||||
|
||||
void print(const nodes::TypeData &type, printers::Printer &printer);
|
||||
template <> struct PrintTask<nodes::Type> : public PrintTaskBase<nodes::Type> {
|
||||
using PrintTaskBase<nodes::Type>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::Type &type, const Args &args) override;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrintTask<nodes::TypeData> : public PrintTaskBase<nodes::TypeData> {
|
||||
using PrintTaskBase<nodes::TypeData>::PrintTaskBase;
|
||||
|
||||
Result operator()(const nodes::TypeData &type, const Args &args) override;
|
||||
};
|
||||
|
||||
// void print_tuple_type(const nodes::TupleType &type, printers::Printer
|
||||
// &printer);
|
||||
|
|
|
|||
|
|
@ -7,157 +7,161 @@
|
|||
|
||||
namespace printers {
|
||||
|
||||
void print(const nodes::Modifier &modifier, Printer &printer,
|
||||
bool const_is_none) {
|
||||
Result PrintTask<nodes::Modifier>::operator()(const nodes::Modifier &modifier,
|
||||
const Args &args) {
|
||||
switch (modifier) {
|
||||
case nodes::Modifier::IN:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "in " : "<- ");
|
||||
Print(words_instead_of_symbols() ? "in " : "<- ");
|
||||
break;
|
||||
case nodes::Modifier::REF:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "ref " : "<> ");
|
||||
Print(words_instead_of_symbols() ? "ref " : "<> ");
|
||||
break;
|
||||
case nodes::Modifier::CONST:
|
||||
if (!const_is_none) {
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "ref " : "<> ");
|
||||
if (!args.const_is_none) {
|
||||
Print(words_instead_of_symbols() ? "ref " : "<> ");
|
||||
}
|
||||
break;
|
||||
case nodes::Modifier::OUT:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "out " : "-> ");
|
||||
Print(words_instead_of_symbols() ? "out " : "-> ");
|
||||
break;
|
||||
// ---
|
||||
case nodes::Modifier::IN_OR_REF:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "in|ref "
|
||||
: "<-|<> ");
|
||||
Print(words_instead_of_symbols() ? "in|ref " : "<-|<> ");
|
||||
break;
|
||||
case nodes::Modifier::IN_OR_CONST:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "in|const "
|
||||
: "<-|-- ");
|
||||
Print(words_instead_of_symbols() ? "in|const " : "<-|-- ");
|
||||
break;
|
||||
case nodes::Modifier::REF_OR_OUT:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "ref|out "
|
||||
: "<>|-> ");
|
||||
Print(words_instead_of_symbols() ? "ref|out " : "<>|-> ");
|
||||
break;
|
||||
case nodes::Modifier::CONST_OR_OUT:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "const|out "
|
||||
: "--|-> ");
|
||||
Print(words_instead_of_symbols() ? "const|out " : "--|-> ");
|
||||
break;
|
||||
case nodes::Modifier::REF_OR_CONST:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "ref|const "
|
||||
: "<>|-- ");
|
||||
Print(words_instead_of_symbols() ? "ref|const " : "<>|-- ");
|
||||
break;
|
||||
case nodes::Modifier::IN_OR_OUT:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "in|out "
|
||||
: "<-|-> ");
|
||||
Print(words_instead_of_symbols() ? "in|out " : "<-|-> ");
|
||||
break;
|
||||
// ---
|
||||
case nodes::Modifier::IN_OR_REF_OR_OUT:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "in|ref|out "
|
||||
: "<-|<>|-> ");
|
||||
Print(words_instead_of_symbols() ? "in|ref|out " : "<-|<>|-> ");
|
||||
break;
|
||||
case nodes::Modifier::IN_OR_CONST_OR_OUT:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "in|const|out "
|
||||
: "<-|--|-> ");
|
||||
Print(words_instead_of_symbols() ? "in|const|out " : "<-|--|-> ");
|
||||
break;
|
||||
case nodes::Modifier::IN_OR_REF_OR_CONST:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "in|ref|const "
|
||||
: "<-|<>|-- ");
|
||||
Print(words_instead_of_symbols() ? "in|ref|const " : "<-|<>|-- ");
|
||||
break;
|
||||
case nodes::Modifier::REF_OR_CONST_OR_OUT:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "ref|const|out "
|
||||
: "<>|--|-> ");
|
||||
Print(words_instead_of_symbols() ? "ref|const|out " : "<>|--|-> ");
|
||||
break;
|
||||
// ---
|
||||
case nodes::Modifier::IN_OR_REF_OR_CONST_OR_OUT:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "in|ref|const|out "
|
||||
: "<-|<>|--|-> ");
|
||||
Print(words_instead_of_symbols() ? "in|ref|const|out " : "<-|<>|--|-> ");
|
||||
break;
|
||||
//
|
||||
case nodes::Modifier::OPTIONAL:
|
||||
printer.print("?");
|
||||
Print("?");
|
||||
break;
|
||||
case nodes::Modifier::RESULT:
|
||||
printer.print("!");
|
||||
Print("!");
|
||||
break;
|
||||
case nodes::Modifier::NONE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void print(const nodes::Literal &literal, Printer &printer) {
|
||||
switch (literal.get_any().index()) {
|
||||
Result PrintTask<nodes::Literal>::operator()(const nodes::Literal &literal,
|
||||
const Args &) {
|
||||
switch (literal.value.index()) {
|
||||
case 0: // float
|
||||
printer.print(std::to_string(*literal.get<float>().value()));
|
||||
return;
|
||||
Print(std::to_string(*literal.get<float>().value()));
|
||||
return {};
|
||||
case 1: // double
|
||||
printer.print(std::to_string(*literal.get<double>().value()));
|
||||
return;
|
||||
Print(std::to_string(*literal.get<double>().value()));
|
||||
break;
|
||||
case 2: // int32_t
|
||||
printer.print(std::to_string(*literal.get<int32_t>().value()));
|
||||
return;
|
||||
Print(std::to_string(*literal.get<int32_t>().value()));
|
||||
break;
|
||||
case 3: // int64_t
|
||||
printer.print(std::to_string(*literal.get<int64_t>().value()));
|
||||
return;
|
||||
Print(std::to_string(*literal.get<int64_t>().value()));
|
||||
break;
|
||||
case 4: // size_t
|
||||
printer.print(std::to_string(*literal.get<size_t>().value()));
|
||||
return;
|
||||
Print(std::to_string(*literal.get<size_t>().value()));
|
||||
break;
|
||||
case 5: // std::string
|
||||
printer.print("\"");
|
||||
printer.print_converted(
|
||||
*literal.get<std::string>()
|
||||
Print("\"");
|
||||
PrintConverted(*literal.get<std::string>()
|
||||
.value()); // special symbols are converted inside
|
||||
printer.print("\"");
|
||||
return;
|
||||
Print("\"");
|
||||
break;
|
||||
case 6: // unicode_string
|
||||
printer.print("\"");
|
||||
printer.print_converted(literal.get<nodes::unicode_string>()
|
||||
Print("\"");
|
||||
PrintConverted(literal.get<nodes::unicode_string>()
|
||||
.value()
|
||||
->str); // special symbols are converted inside
|
||||
printer.print("\"u");
|
||||
return;
|
||||
Print("\"u");
|
||||
break;
|
||||
case 7: // char
|
||||
printer.print("\'\'");
|
||||
printer.print_converted(std::string(1, *literal.get<char>().value()));
|
||||
printer.print("\'\'");
|
||||
return;
|
||||
Print("\'\'");
|
||||
PrintConverted(std::string(1, *literal.get<char>().value()));
|
||||
Print("\'\'");
|
||||
break;
|
||||
case 8: // unicode
|
||||
printer.print("\'\'");
|
||||
printer.print_converted(literal.get<nodes::unicode>().value()->ch);
|
||||
printer.print("\'\'u");
|
||||
return;
|
||||
Print("\'\'");
|
||||
PrintConverted(literal.get<nodes::unicode>().value()->ch);
|
||||
Print("\'\'u");
|
||||
break;
|
||||
case 9: // bool
|
||||
printer.print(*literal.get<bool>().value() ? "true" : "false");
|
||||
return;
|
||||
Print(*literal.get<bool>().value() ? "true" : "false");
|
||||
break;
|
||||
case 10: // unit
|
||||
printer.print("()");
|
||||
return;
|
||||
Print("()");
|
||||
break;
|
||||
case 11: // null
|
||||
printer.print("null");
|
||||
return;
|
||||
}
|
||||
|
||||
Print("null");
|
||||
break;
|
||||
default:
|
||||
error_handling::handle_general_error("Unreachable");
|
||||
exit(1); // unreachable
|
||||
}
|
||||
|
||||
void print(const nodes::Identifier &identifier, Printer &printer) {
|
||||
printer.print(*identifier.get());
|
||||
}
|
||||
|
||||
void print_annotation(const std::string &annotation, Printer &printer) {
|
||||
printer.print("@");
|
||||
printer.print(annotation);
|
||||
}
|
||||
|
||||
void print(const nodes::Extra &extra, Printer &printer) {
|
||||
printer.print(*extra.content());
|
||||
}
|
||||
|
||||
void print(const nodes::EmptyLines &empty_lines, Printer &printer) {
|
||||
for (size_t i = 0; i < empty_lines.line_count(); ++i) {
|
||||
printer.new_indent_line();
|
||||
break;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Result
|
||||
PrintTask<nodes::Identifier>::operator()(const nodes::Identifier &identifier,
|
||||
const Args &) {
|
||||
Print(identifier.value);
|
||||
return {};
|
||||
}
|
||||
|
||||
Result
|
||||
PrintTask<nodes::Annotation>::operator()(const nodes::Annotation &annotation,
|
||||
const Args &) {
|
||||
Print("@");
|
||||
Print(annotation.value);
|
||||
return {};
|
||||
}
|
||||
|
||||
Result PrintTask<nodes::Extra>::operator()(const nodes::Extra &extra,
|
||||
const Args &) {
|
||||
Print(extra.content);
|
||||
return {};
|
||||
}
|
||||
|
||||
Result
|
||||
PrintTask<nodes::EmptyLines>::operator()(const nodes::EmptyLines &empty_lines,
|
||||
const Args &) {
|
||||
for (size_t i = 0; i < empty_lines.count; ++i) {
|
||||
NewIndentLine();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace printers
|
||||
|
|
|
|||
|
|
@ -6,29 +6,31 @@ namespace printers {
|
|||
|
||||
// TODO
|
||||
|
||||
void print(const nodes::SymbolDocs &docs, Printer &printer) {
|
||||
Result PrintTask<nodes::SymbolDocs>::operator()(const nodes::SymbolDocs &docs,
|
||||
const Args &) {
|
||||
auto description = docs.get_description();
|
||||
|
||||
if (description.has_value()) {
|
||||
printer.print(": ");
|
||||
Print(": ");
|
||||
for (auto &ch : *description.value()) {
|
||||
if (ch == '\n') {
|
||||
printer.new_indent_line();
|
||||
printer.print(": ");
|
||||
NewIndentLine();
|
||||
Print(": ");
|
||||
} else {
|
||||
printer.print(std::string(1, ch));
|
||||
Print(std::string(1, ch));
|
||||
}
|
||||
}
|
||||
printer.new_indent_line();
|
||||
NewIndentLine();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < docs.annotations_info_size(); ++i) {
|
||||
print_annotation(*docs.get_annotation(i), printer);
|
||||
printer.space();
|
||||
printer.print(*docs.get_annotation_info(i));
|
||||
printer.new_indent_line();
|
||||
Run(nodes::Annotation{*docs.get_annotation(i)});
|
||||
Space();
|
||||
Print(*docs.get_annotation_info(i));
|
||||
NewIndentLine();
|
||||
}
|
||||
|
||||
return {};
|
||||
} // IN PROGRESS
|
||||
|
||||
} // namespace printers
|
||||
|
|
|
|||
|
|
@ -5,375 +5,417 @@
|
|||
#include "type_printers.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
// TODO Run, get for Ids
|
||||
|
||||
namespace printers {
|
||||
namespace utils {
|
||||
|
||||
bool is_block_expression(const nodes::ExprData &expression) {
|
||||
return expression.get<nodes::Container>().has_value() &&
|
||||
expression.get<nodes::Container>().value()->get_type() ==
|
||||
nodes::Container::BLOCK;
|
||||
bool is_block_expression(const Node &expr) {
|
||||
return expr.Holds<nodes::Container>() &&
|
||||
expr.get<nodes::Container>().kind == nodes::Container::BLOCK;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
||||
void print(const nodes::ExprData &expression, printers::Printer &printer) {
|
||||
if (expression.is_scoped()) {
|
||||
printer.print("(");
|
||||
Result PrintTask<nodes::NodeId>::operator()(const nodes::NodeId &expr,
|
||||
const Args &args) {
|
||||
Run(*Ext(expr), args);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Result PrintTask<nodes::NodeData>::operator()(const nodes::NodeData &expr,
|
||||
const Args &args) {
|
||||
if (expr.is_scoped) {
|
||||
Print("(");
|
||||
}
|
||||
|
||||
std::visit([&printer](const auto &arg) -> void { print(arg, printer); },
|
||||
expression.get_any());
|
||||
std::visit([this, &args](const auto &expr) -> void { Run(expr, args); },
|
||||
expr.value);
|
||||
|
||||
if (expression.is_scoped()) {
|
||||
printer.print(")");
|
||||
if (expr.is_scoped) {
|
||||
Print(")");
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// --- flow control
|
||||
|
||||
void print(const nodes::Match::Case &expression, Printer &printer) {
|
||||
Result PrintTask<nodes::Match::Case>::operator()(const nodes::Match::Case &expr,
|
||||
const Args &) {
|
||||
|
||||
switch (expression.kind()) {
|
||||
switch (expr.kind) {
|
||||
case nodes::Match::Case::PATTERN_VALUE:
|
||||
printer.print(":=");
|
||||
Print(":=");
|
||||
break;
|
||||
case nodes::Match::Case::VALUE_PATTERN:
|
||||
printer.print("=:");
|
||||
Print("=:");
|
||||
break;
|
||||
}
|
||||
|
||||
printer.space();
|
||||
Space();
|
||||
|
||||
print(*expression.get_value(), printer);
|
||||
Run(expr.value);
|
||||
|
||||
if (expression.get_condition().has_value()) {
|
||||
printer.print(printer.print_words_instead_of_symbols() ? " if " : " ?? ");
|
||||
print(*expression.get_condition().value(), printer);
|
||||
if (expr.condition.has_value()) {
|
||||
Print(words_instead_of_symbols() ? " if " : " ?? ");
|
||||
Run(expr.condition.value());
|
||||
}
|
||||
|
||||
if (expression.get_expression().has_value()) {
|
||||
printer.print(printer.print_words_instead_of_symbols() ? " do " : " => ");
|
||||
print(*expression.get_expression().value(), printer);
|
||||
if (expr.expr.has_value()) {
|
||||
Print(words_instead_of_symbols() ? " do " : " => ");
|
||||
Run(expr.expr.value());
|
||||
}
|
||||
|
||||
return {};
|
||||
} // IN PROGRESS
|
||||
|
||||
void print(const nodes::Match &expression, printers::Printer &printer) {
|
||||
print(*expression.get_value(), printer);
|
||||
Result PrintTask<nodes::Match>::operator()(const nodes::Match &expr,
|
||||
const Args &) {
|
||||
Run(expr.value, {});
|
||||
|
||||
printer.space();
|
||||
Space();
|
||||
|
||||
size_t previous_indentation_level = printer.get_indentation_level();
|
||||
size_t previous_indentation_level = indentation_level();
|
||||
|
||||
printer.set_indentation_level(printer.current_position());
|
||||
SetIndentationLevel(current_position());
|
||||
|
||||
for (size_t i = 0; i < expression.cases_size(); ++i) {
|
||||
print(*expression.get_case(i), printer);
|
||||
for (size_t i = 0; i < expr.cases.size(); ++i) {
|
||||
Run(expr.cases.at(i));
|
||||
|
||||
if (i + 1 < expression.cases_size()) {
|
||||
printer.new_indent_line();
|
||||
if (i + 1 < expr.cases.size()) {
|
||||
NewIndentLine();
|
||||
}
|
||||
}
|
||||
|
||||
printer.set_indentation_level(previous_indentation_level);
|
||||
SetIndentationLevel(previous_indentation_level);
|
||||
|
||||
return {};
|
||||
} // IN PROGRESS
|
||||
|
||||
void print(const nodes::Condition &expression, printers::Printer &printer) {
|
||||
Result PrintTask<nodes::Condition>::operator()(const nodes::Condition &expr,
|
||||
const Args &) {
|
||||
|
||||
for (size_t i = 0; i < expression.cases_size(); ++i) {
|
||||
for (size_t i = 0; i < expr.cases.size(); ++i) {
|
||||
if (i > 0) {
|
||||
if (utils::is_block_expression(*expression.get_case(i - 1).second)) {
|
||||
printer.space();
|
||||
if (utils::is_block_expression(
|
||||
Ext(expr.cases.at(i - 1).second))) { // TODO
|
||||
Space();
|
||||
} else {
|
||||
printer.new_indent_line();
|
||||
NewIndentLine();
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "if " : "?? ");
|
||||
Print(words_instead_of_symbols() ? "if " : "?? ");
|
||||
} else {
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "elif " : "!! ");
|
||||
Print(words_instead_of_symbols() ? "elif " : "!! ");
|
||||
}
|
||||
|
||||
print(*expression.get_case(i).first, printer);
|
||||
Run(expr.cases.at(i).first);
|
||||
|
||||
printer.print(printer.print_words_instead_of_symbols() ? " do " : " => ");
|
||||
Print(words_instead_of_symbols() ? " do " : " => ");
|
||||
|
||||
print(*expression.get_case(i).second, printer);
|
||||
Run(expr.cases.at(i).second);
|
||||
}
|
||||
|
||||
if (expression.cases_size() == 0) {
|
||||
if (expr.cases.size() == 0) {
|
||||
error_handling::handle_general_error(
|
||||
"Condition with zero cases"); // TODO ??
|
||||
}
|
||||
|
||||
if (expression.get_else_case().has_value()) {
|
||||
if (expr.else_case.has_value()) {
|
||||
if (utils::is_block_expression(
|
||||
*expression.get_case(expression.cases_size() - 1).second)) {
|
||||
printer.space();
|
||||
Ext(expr.cases.at(expr.cases.size() - 1).second))) {
|
||||
Space();
|
||||
} else {
|
||||
printer.new_indent_line();
|
||||
NewIndentLine();
|
||||
}
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "else " : "!!=> ");
|
||||
print(*expression.get_else_case().value(), printer);
|
||||
Print(words_instead_of_symbols() ? "else " : "!!=> ");
|
||||
Run(expr.else_case.value());
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void print(const nodes::Loop &expression, printers::Printer &printer) {
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "for" : "@");
|
||||
Result PrintTask<nodes::Loop>::operator()(const nodes::Loop &expr,
|
||||
const Args &) {
|
||||
Print(words_instead_of_symbols() ? "for" : "@");
|
||||
|
||||
switch (expression.get_type()) {
|
||||
switch (expr.kind) {
|
||||
case nodes::Loop::LOOP:
|
||||
printer.space();
|
||||
Space();
|
||||
break;
|
||||
case nodes::Loop::WHILE:
|
||||
printer.space();
|
||||
print(*expression.get_condition().value(), printer);
|
||||
printer.space();
|
||||
Space();
|
||||
Run(expr.condition.value());
|
||||
Space();
|
||||
break;
|
||||
case nodes::Loop::FOR:
|
||||
printer.space();
|
||||
print(*expression.get_variable().value(), printer);
|
||||
printer.print(" : ");
|
||||
print(*expression.get_interval().value(), printer);
|
||||
printer.space();
|
||||
Space();
|
||||
Run(expr.variable.value());
|
||||
Print(" : ");
|
||||
Run(expr.interval.value());
|
||||
Space();
|
||||
break;
|
||||
}
|
||||
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "do " : "=> ");
|
||||
Print(words_instead_of_symbols() ? "do " : "=> ");
|
||||
|
||||
print(*expression.get_expression(), printer);
|
||||
Run(expr.expr);
|
||||
|
||||
return {};
|
||||
} // IN PROGRESS
|
||||
|
||||
// --- containers
|
||||
|
||||
void print(const nodes::Container &expression, printers::Printer &printer) {
|
||||
bool is_array = expression.get_type() == nodes::Container::ARRAY;
|
||||
Result PrintTask<nodes::Container>::operator()(const nodes::Container &expr,
|
||||
const Args &) {
|
||||
bool is_array = expr.kind == nodes::Container::ARRAY;
|
||||
|
||||
if (is_array) {
|
||||
printer.print("[[");
|
||||
Print("[[");
|
||||
} else {
|
||||
printer.print("{");
|
||||
printer.indent();
|
||||
Print("{");
|
||||
Indent();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < expression.expressions_size(); ++i) {
|
||||
bool is_empty_lines =
|
||||
expression.get_expression(i)->get<nodes::EmptyLines>().has_value();
|
||||
|
||||
bool is_extra =
|
||||
expression.get_expression(i)->get<nodes::Extra>().has_value();
|
||||
for (size_t i = 0; i < expr.exprs.size(); ++i) {
|
||||
bool is_empty_lines = Ext(expr.exprs.at(i)).Holds<nodes::EmptyLines>();
|
||||
bool is_extra = Ext(expr.exprs.at(i)).Holds<nodes::Extra>();
|
||||
|
||||
if (!is_array && !is_empty_lines) {
|
||||
printer.new_indent_line();
|
||||
NewIndentLine();
|
||||
}
|
||||
print(*expression.get_expression(i), printer);
|
||||
Run(expr.exprs.at(i));
|
||||
if (is_array) {
|
||||
if (i + 1 < expression.expressions_size()) {
|
||||
printer.space();
|
||||
if (i + 1 < expr.exprs.size()) {
|
||||
Space();
|
||||
}
|
||||
} else {
|
||||
if (!is_empty_lines && !is_extra) {
|
||||
printer.print(";");
|
||||
Print(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array) {
|
||||
printer.print("]]");
|
||||
Print("]]");
|
||||
} else {
|
||||
printer.deindent();
|
||||
printer.new_indent_line();
|
||||
printer.print("}");
|
||||
Deindent();
|
||||
NewIndentLine();
|
||||
Print("}");
|
||||
}
|
||||
|
||||
return {};
|
||||
} // IN PROGRESS
|
||||
|
||||
// --- modifiers
|
||||
|
||||
void print(const nodes::Return &expression, printers::Printer &printer) {
|
||||
Result PrintTask<nodes::Return>::operator()(const nodes::Return &expr,
|
||||
const Args &) {
|
||||
|
||||
switch (expression.get_type()) {
|
||||
switch (expr.kind) {
|
||||
case nodes::Return::RETURN:
|
||||
printer.print("return ");
|
||||
Print("return ");
|
||||
break;
|
||||
case nodes::Return::BRING:
|
||||
printer.print("bring ");
|
||||
Print("bring ");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
print(*expression.get_expression(), printer);
|
||||
Run(expr.expr);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void print(const nodes::NameDefinition &expression,
|
||||
printers::Printer &printer) {
|
||||
Result
|
||||
PrintTask<nodes::NameDefinition>::operator()(const nodes::NameDefinition &expr,
|
||||
const Args &) {
|
||||
|
||||
if (printer.print_words_instead_of_symbols()) {
|
||||
switch (expression.get_modifier()) {
|
||||
if (words_instead_of_symbols()) {
|
||||
switch (expr.kind) {
|
||||
case nodes::NameDefinition::LET:
|
||||
printer.print("let ");
|
||||
Print("let ");
|
||||
break;
|
||||
case nodes::NameDefinition::VAR:
|
||||
printer.print("var ");
|
||||
Print("var ");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (expression.get_modifier()) {
|
||||
switch (expr.kind) {
|
||||
case nodes::NameDefinition::LET:
|
||||
printer.print("%");
|
||||
Print("%");
|
||||
break;
|
||||
case nodes::NameDefinition::VAR:
|
||||
printer.print("$");
|
||||
Print("$");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
print(*expression.get_name(), printer);
|
||||
Run(expr.name);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void print(const nodes::Access &expression, printers::Printer &printer) {
|
||||
print(*expression.get_value(), printer);
|
||||
Result PrintTask<nodes::Access>::operator()(const nodes::Access &expr,
|
||||
const Args &) {
|
||||
Run(expr.value);
|
||||
|
||||
switch (expression.get_type()) {
|
||||
switch (expr.kind) {
|
||||
case nodes::Access::ARRAY:
|
||||
printer.print("[");
|
||||
Print("[");
|
||||
break;
|
||||
case nodes::Access::TUPLE:
|
||||
printer.print(".");
|
||||
Print(".");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
print(*expression.get_index(), printer);
|
||||
Run(expr.index);
|
||||
|
||||
switch (expression.get_type()) {
|
||||
switch (expr.kind) {
|
||||
case nodes::Access::ARRAY:
|
||||
printer.print("]");
|
||||
Print("]");
|
||||
break;
|
||||
case nodes::Access::TUPLE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void print(const nodes::LoopControl &expression, printers::Printer &printer) {
|
||||
switch (expression.get_type()) {
|
||||
Result PrintTask<nodes::LoopControl>::operator()(const nodes::LoopControl &expr,
|
||||
const Args &) {
|
||||
switch (expr.kind) {
|
||||
case nodes::LoopControl::BREAK:
|
||||
printer.print("break");
|
||||
Print("break");
|
||||
break;
|
||||
case nodes::LoopControl::CONTINUE:
|
||||
printer.print("continue");
|
||||
Print("continue");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void print(const nodes::ModifierExpression &expression,
|
||||
printers::Printer &printer) {
|
||||
if (expression.get_modifier() != nodes::Modifier::OPTIONAL &&
|
||||
expression.get_modifier() != nodes::Modifier::RESULT) {
|
||||
print(expression.get_modifier(), printer);
|
||||
Result PrintTask<nodes::ModifierExpression>::operator()(
|
||||
const nodes::ModifierExpression &expr, const Args &) {
|
||||
if (expr.modifier != nodes::Modifier::OPTIONAL &&
|
||||
expr.modifier != nodes::Modifier::RESULT) {
|
||||
Run(expr.modifier);
|
||||
}
|
||||
|
||||
print(*expression.get_expression(), printer);
|
||||
Run(expr.expr);
|
||||
|
||||
if (expression.get_modifier() == nodes::Modifier::OPTIONAL ||
|
||||
expression.get_modifier() == nodes::Modifier::RESULT) {
|
||||
print(expression.get_modifier(), printer);
|
||||
if (expr.modifier == nodes::Modifier::OPTIONAL ||
|
||||
expr.modifier == nodes::Modifier::RESULT) {
|
||||
Run(expr.modifier);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// --- other
|
||||
|
||||
void print(const nodes::NameExpression &expression,
|
||||
printers::Printer &printer) {
|
||||
bool is_comma_operator = (*expression.get_name()->get() == ",");
|
||||
bool is_range_operator = (*expression.get_name()->get() == "..");
|
||||
Result
|
||||
PrintTask<nodes::NameExpression>::operator()(const nodes::NameExpression &expr,
|
||||
const Args &) {
|
||||
bool is_comma_operator = (expr.name.value == ",");
|
||||
bool is_range_operator = (expr.name.value == "..");
|
||||
|
||||
if (expression.is_operator_call() || expression.is_point_call()) {
|
||||
print(*expression.get_argument_value(0), printer);
|
||||
if (expression.is_point_call()) {
|
||||
printer.print(".");
|
||||
if (expr.is_operator_call || expr.is_point_call) {
|
||||
Run(expr.args.at(0).second);
|
||||
if (expr.is_point_call) {
|
||||
Print(".");
|
||||
|
||||
// not comma operator and not range operator
|
||||
} else if (!is_comma_operator && !is_range_operator) {
|
||||
printer.space();
|
||||
Space();
|
||||
}
|
||||
} else if (expression.get_prefix().has_value()) {
|
||||
print(*expression.get_prefix().value(), printer);
|
||||
printer.print(".");
|
||||
} else if (expr.prefix.has_value()) {
|
||||
Run(expr.prefix.value());
|
||||
Print(".");
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
bool operator_called_as_function =
|
||||
(!expression.is_operator_call() &&
|
||||
expression.get_name()->get_type() == nodes::Identifier::kOperator);
|
||||
(!expr.is_operator_call &&
|
||||
expr.name.kind == nodes::Identifier::kOperator);
|
||||
|
||||
if (operator_called_as_function) {
|
||||
printer.print("( ");
|
||||
Print("( ");
|
||||
}
|
||||
|
||||
print(*expression.get_name(), printer);
|
||||
Run(expr.name);
|
||||
|
||||
if (operator_called_as_function) {
|
||||
printer.print(" )");
|
||||
Print(" )");
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
for (size_t i =
|
||||
expression.is_operator_call() || expression.is_point_call() ? 1 : 0;
|
||||
i < expression.args_size(); ++i) {
|
||||
if (!expression.is_operator_call() || !is_range_operator || i > 1) {
|
||||
printer.space();
|
||||
for (size_t i = expr.is_operator_call || expr.is_point_call ? 1 : 0;
|
||||
i < expr.args.size(); ++i) {
|
||||
if (!expr.is_operator_call || !is_range_operator || i > 1) {
|
||||
Space();
|
||||
}
|
||||
|
||||
if (expression.get_argument_annotation(i).has_value()) {
|
||||
print_annotation(*expression.get_argument_annotation(i).value(), printer);
|
||||
printer.space();
|
||||
if (expr.args.at(i).first.has_value()) {
|
||||
Run(nodes::Annotation{expr.args.at(i).first.value()});
|
||||
Space();
|
||||
}
|
||||
print(*expression.get_argument_value(i), printer);
|
||||
Run(expr.args.at(i).second);
|
||||
}
|
||||
|
||||
return {};
|
||||
} // IN PROGRESS
|
||||
|
||||
void print(const nodes::Constructor &expression, printers::Printer &printer) {
|
||||
print(*expression.get_type(), printer);
|
||||
Result PrintTask<nodes::Constructor>::operator()(const nodes::Constructor &expr,
|
||||
const Args &) {
|
||||
Run(expr.type);
|
||||
|
||||
for (size_t i = 0; i < expression.args_size(); ++i) {
|
||||
printer.space();
|
||||
for (size_t i = 0; i < expr.args.size(); ++i) {
|
||||
Space();
|
||||
|
||||
if (expression.get_argument_annotation(i).has_value()) {
|
||||
print_annotation(*expression.get_argument_annotation(i).value(), printer);
|
||||
printer.space();
|
||||
if (expr.args.at(i).first.has_value()) {
|
||||
Run(nodes::Annotation{expr.args.at(i).first.value()});
|
||||
Space();
|
||||
}
|
||||
|
||||
print(*expression.get_argument_value(i), printer);
|
||||
Run(expr.args.at(i).second);
|
||||
}
|
||||
|
||||
return {};
|
||||
} // IN PROGRESS
|
||||
|
||||
void print(const nodes::Lambda &expression, printers::Printer &printer) {
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "lambda " : "\\ ");
|
||||
Result PrintTask<nodes::Lambda>::operator()(const nodes::Lambda &expr,
|
||||
const Args &) {
|
||||
Print(words_instead_of_symbols() ? "lambda " : "\\ ");
|
||||
|
||||
for (size_t i = 0; i < expression.args_size(); ++i) {
|
||||
print(*expression.get_argument(i), printer);
|
||||
printer.space();
|
||||
for (size_t i = 0; i < expr.args.size(); ++i) {
|
||||
Run(expr.args.at(i));
|
||||
Space();
|
||||
}
|
||||
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "do " : "=> ");
|
||||
Print(words_instead_of_symbols() ? "do " : "=> ");
|
||||
|
||||
print(*expression.get_expression(), printer);
|
||||
Run(expr.expr);
|
||||
|
||||
return {};
|
||||
} // IN PROGRESS
|
||||
|
||||
} // namespace printers
|
||||
|
|
|
|||
|
|
@ -17,177 +17,189 @@ namespace printers {
|
|||
// }
|
||||
// }
|
||||
|
||||
void print(const nodes::Statement &statement, Printer &printer) {
|
||||
std::visit([&printer](const auto &arg) -> void { print(arg, printer); },
|
||||
statement.get_any());
|
||||
Result
|
||||
PrintTask<nodes::Statement>::operator()(const nodes::Statement &statement,
|
||||
const Args &) {
|
||||
std::visit([this](const auto &arg) -> void { Run(arg); }, statement.value);
|
||||
|
||||
if (not statement.get<nodes::EmptyLines>().has_value()) {
|
||||
printer.new_indent_line();
|
||||
NewIndentLine();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void print(const nodes::Import &statement, Printer &printer) {
|
||||
printer.print(":: ");
|
||||
Result PrintTask<nodes::Import>::operator()(const nodes::Import &statement,
|
||||
const Args &) {
|
||||
Print(":: ");
|
||||
|
||||
print(*statement.get_import_name(), printer);
|
||||
Run(statement.import_name);
|
||||
|
||||
if (*statement.get_import_name()->get() !=
|
||||
*statement.get_module_name()->get()) {
|
||||
printer.print(" = ");
|
||||
print(*statement.get_module_name(), printer);
|
||||
if (statement.import_name.value != statement.module_name.value) {
|
||||
Print(" = ");
|
||||
Run(statement.module_name);
|
||||
}
|
||||
|
||||
if (statement.symbols_size() > 0) {
|
||||
printer.print(" :");
|
||||
for (size_t i = 0; i < statement.symbols_size(); ++i) {
|
||||
printer.space();
|
||||
if (not statement.symbols.empty()) {
|
||||
Print(" :");
|
||||
for (const auto &symbol : statement.symbols) {
|
||||
Space();
|
||||
|
||||
bool identifier_is_operator =
|
||||
(statement.get_symbol(i)->get_type() == nodes::Identifier::OPERATOR);
|
||||
(symbol.kind == nodes::Identifier::kOperator);
|
||||
|
||||
if (identifier_is_operator) {
|
||||
printer.print("( ");
|
||||
Print("( ");
|
||||
}
|
||||
|
||||
print(*statement.get_symbol(i), printer);
|
||||
Run(symbol);
|
||||
|
||||
if (identifier_is_operator) {
|
||||
printer.print(" )");
|
||||
Print(" )");
|
||||
}
|
||||
}
|
||||
}
|
||||
printer.print(";");
|
||||
Print(";");
|
||||
|
||||
return {};
|
||||
} // IN PROGRESS
|
||||
|
||||
void print(const nodes::Constraint &statement, Printer &printer) {
|
||||
printer.print("? ");
|
||||
print(*statement.get_expression(), printer);
|
||||
printer.print(";");
|
||||
Result
|
||||
PrintTask<nodes::Constraint>::operator()(const nodes::Constraint &statement,
|
||||
const Args &) {
|
||||
Print("? ");
|
||||
Run(statement.expr);
|
||||
Print(";");
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void print(const nodes::TypeDefinition &statement, Printer &printer) {
|
||||
print(*statement.get_docs(), printer);
|
||||
Result PrintTask<nodes::TypeDefinition>::operator()(
|
||||
const nodes::TypeDefinition &statement, const Args &) {
|
||||
Run(statement.docs);
|
||||
|
||||
if (statement.is_on_heap()) {
|
||||
printer.print("<> ");
|
||||
if (statement.is_on_heap) {
|
||||
Print("<> ");
|
||||
}
|
||||
|
||||
print(*statement.get_name(), printer);
|
||||
Run(statement.name);
|
||||
|
||||
for (size_t i = 0; i < statement.args_size(); ++i) {
|
||||
printer.space();
|
||||
print(*statement.get_argument(i), printer);
|
||||
for (const auto &arg : statement.args) {
|
||||
Space();
|
||||
Run(arg);
|
||||
}
|
||||
|
||||
if (statement.get_type().has_value()) {
|
||||
printer.print(" = ");
|
||||
if (statement.type.has_value()) {
|
||||
Print(" = ");
|
||||
|
||||
size_t previous_indentation_level = printer.get_indentation_level();
|
||||
size_t previous_indentation_level = indentation_level();
|
||||
|
||||
printer.set_indentation_level(printer.get_current_position() - 2);
|
||||
SetIndentationLevel(current_position() - 2);
|
||||
|
||||
print(*statement.get_type().value().get(), printer);
|
||||
Run(statement.type.value());
|
||||
|
||||
printer.set_indentation_level(previous_indentation_level);
|
||||
SetIndentationLevel(previous_indentation_level);
|
||||
}
|
||||
printer.print(";");
|
||||
Print(";");
|
||||
|
||||
return {};
|
||||
} // IN PROGRESS
|
||||
|
||||
// TODO: do not print prefix type for names
|
||||
void print(const nodes::FunctionDefinition &statement, Printer &printer) {
|
||||
print(*statement.get_docs(), printer);
|
||||
Result PrintTask<nodes::FunctionDefinition>::operator()(
|
||||
const nodes::FunctionDefinition &statement, const Args &) {
|
||||
Run(statement.docs);
|
||||
|
||||
for (size_t i = 0; i < statement.constraints_size(); ++i) {
|
||||
print(*statement.get_constraint(i), printer);
|
||||
printer.new_indent_line();
|
||||
for (const auto &constraint : statement.constraints) {
|
||||
Run(constraint);
|
||||
NewIndentLine();
|
||||
}
|
||||
|
||||
if (statement.is_method()) {
|
||||
printer.print(".");
|
||||
if (statement.is_method) {
|
||||
Print(".");
|
||||
}
|
||||
|
||||
bool identifier_is_operator =
|
||||
(statement.get_name()->get_type() == nodes::Identifier::OPERATOR);
|
||||
(statement.name.kind == nodes::Identifier::kOperator);
|
||||
|
||||
if (identifier_is_operator) {
|
||||
printer.print("( ");
|
||||
Print("( ");
|
||||
}
|
||||
|
||||
print(*statement.get_name(), printer);
|
||||
Run(statement.name);
|
||||
|
||||
if (identifier_is_operator) {
|
||||
printer.print(" )");
|
||||
Print(" )");
|
||||
}
|
||||
|
||||
print(statement.get_return_modifier(), printer); // ! or ?
|
||||
Run(statement.return_modifier); // ! or ?
|
||||
|
||||
for (size_t i = 0; i < statement.args_size(); ++i) {
|
||||
if (!statement.get_argument(i)->get_name().has_value()) {
|
||||
for (const auto &arg : statement.args) {
|
||||
if (not arg.name.has_value()) {
|
||||
break;
|
||||
}
|
||||
|
||||
printer.space();
|
||||
Space();
|
||||
|
||||
// all args are typed or are untyped in the same time
|
||||
if (!statement.get_argument(i)->get_type().has_value()) {
|
||||
if (not arg.type.has_value()) {
|
||||
|
||||
// print annotation
|
||||
if (!statement.are_annotations_same_to_names() &&
|
||||
statement.get_argument(i)->get_annotation().has_value()) {
|
||||
print_annotation(*statement.get_argument(i)->get_annotation().value(),
|
||||
printer);
|
||||
printer.space();
|
||||
if (not statement.are_annotations_same_to_names &&
|
||||
arg.annotation.has_value()) {
|
||||
Run(nodes::Annotation{arg.annotation.value()});
|
||||
Space();
|
||||
}
|
||||
|
||||
print(statement.get_argument(i)->get_before_modifier(), printer, true);
|
||||
Run(arg.before_modifier, {.const_is_none = true}); // TODO: check
|
||||
}
|
||||
|
||||
print(*statement.get_argument(i)->get_name().value(), printer);
|
||||
Run(arg.name.value());
|
||||
|
||||
// all args are typed or are untyped in the same time
|
||||
if (!statement.get_argument(i)->get_type().has_value()) {
|
||||
print(statement.get_argument(i)->get_after_modifier(), printer);
|
||||
if (not arg.type.has_value()) {
|
||||
Run(arg.after_modifier);
|
||||
}
|
||||
}
|
||||
|
||||
// all args are typed or are untyped in the same time
|
||||
if (statement.args_size() > 0 &&
|
||||
statement.get_argument(0)->get_type().has_value()) {
|
||||
if (not statement.args.empty() && statement.args.at(0).type.has_value()) {
|
||||
|
||||
printer.print(" :");
|
||||
Print(" :");
|
||||
|
||||
for (size_t i = 0; i < statement.args_size(); ++i) {
|
||||
printer.space();
|
||||
if (statement.get_argument(i)->get_annotation().has_value()) {
|
||||
print_annotation(*statement.get_argument(i)->get_annotation().value(),
|
||||
printer);
|
||||
printer.space();
|
||||
for (const auto &arg : statement.args) {
|
||||
Space();
|
||||
if (arg.annotation.has_value()) {
|
||||
Run(nodes::Annotation{arg.annotation.value()});
|
||||
Space();
|
||||
}
|
||||
|
||||
print(statement.get_argument(i)->get_before_modifier(), printer, true);
|
||||
Run(arg.before_modifier, {.const_is_none = true}); // TODO: check
|
||||
|
||||
print(*statement.get_argument(i)->get_type().value(), printer);
|
||||
Run(arg.type.value());
|
||||
}
|
||||
}
|
||||
|
||||
if (statement.get_expression().has_value()) {
|
||||
if (statement.expr.has_value()) {
|
||||
bool expression_is_container =
|
||||
statement.get_expression().value()->get<nodes::Container>().has_value();
|
||||
Ext(statement.expr.value()).Holds<nodes::Container>();
|
||||
|
||||
printer.print(expression_is_container ? " " : " = ");
|
||||
Print(expression_is_container ? " " : " = ");
|
||||
|
||||
size_t previous_indentation_level = printer.get_indentation_level();
|
||||
size_t previous_indentation_level = indentation_level();
|
||||
if (!expression_is_container) {
|
||||
printer.set_indentation_level(printer.current_position());
|
||||
SetIndentationLevel(current_position());
|
||||
}
|
||||
print(*statement.get_expression().value(), printer);
|
||||
Run(statement.expr.value());
|
||||
if (!expression_is_container) {
|
||||
printer.set_indentation_level(previous_indentation_level);
|
||||
printer.print(";");
|
||||
SetIndentationLevel(previous_indentation_level);
|
||||
Print(";");
|
||||
}
|
||||
} else {
|
||||
printer.print(";");
|
||||
Print(";");
|
||||
}
|
||||
|
||||
return {};
|
||||
} // IN PROGRESS
|
||||
|
||||
} // namespace printers
|
||||
|
|
|
|||
|
|
@ -5,29 +5,36 @@
|
|||
|
||||
namespace printers {
|
||||
|
||||
Result PrintTask<nodes::Type>::operator()(const nodes::Type &type,
|
||||
const Args &args) {
|
||||
return Run(*type.get(), args);
|
||||
}
|
||||
// TODO: better printing format for builtin types
|
||||
void print(const nodes::TypeData &type, printers::Printer &printer) {
|
||||
Result PrintTask<nodes::TypeData>::operator()(const nodes::TypeData &type,
|
||||
const Args &) {
|
||||
if (type.has_annotation()) {
|
||||
print_annotation(*type.get_annotation().value(), printer);
|
||||
printer.space();
|
||||
Run(nodes::Annotation{.value = *type.get_annotation().value()});
|
||||
Space();
|
||||
}
|
||||
|
||||
if (type.get_modifier() != nodes::Modifier::CONST) {
|
||||
print(type.get_modifier(), printer);
|
||||
Run(type.get_modifier());
|
||||
}
|
||||
|
||||
print(*type.get_name(), printer);
|
||||
Run(*type.get_name());
|
||||
|
||||
if (type.parameters_size() > 0) {
|
||||
printer.print("[");
|
||||
Print("[");
|
||||
for (size_t i = 0; i < type.parameters_size(); ++i) {
|
||||
print(*type.get_parameter(i), printer);
|
||||
Run(*type.get_parameter(i));
|
||||
if (i + 1 < type.parameters_size()) {
|
||||
printer.space();
|
||||
Space();
|
||||
}
|
||||
}
|
||||
printer.print("]");
|
||||
Print("]");
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// void print_tuple_type(const nodes::TupleType &type,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "expression_nodes.hpp"
|
||||
#include "log.hpp"
|
||||
#include "name_tree.hpp"
|
||||
#include "nodes_storage.hpp"
|
||||
#include "type_nodes.hpp"
|
||||
|
||||
#include <optional>
|
||||
|
|
@ -82,10 +83,10 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
void enter_context(const nodes::Node &node) {
|
||||
void enter_context(const utils::Pos &pos) {
|
||||
Log::Context logc(log_, Log::Area::kTypeCheck);
|
||||
|
||||
contexts_.emplace_back(node);
|
||||
contexts_.emplace_back(pos);
|
||||
}
|
||||
|
||||
// TODO: argument for property is returned type should be merged
|
||||
|
|
@ -134,7 +135,7 @@ private:
|
|||
public:
|
||||
class Context {
|
||||
public:
|
||||
Context(const nodes::Node &node) : node_(node) {}
|
||||
Context(const utils::Pos &pos) : pos_(pos) {}
|
||||
|
||||
// void log_typecheck_error(
|
||||
// const std::string &message = "Context typecheck error") {
|
||||
|
|
@ -148,7 +149,7 @@ public:
|
|||
std::unordered_map<std::string, VariableInfo> variables;
|
||||
|
||||
private:
|
||||
const nodes::Node &node_; // TODO: use as position
|
||||
const utils::Pos &pos_; // TODO: use as position
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
@ -159,7 +160,7 @@ private:
|
|||
|
||||
//
|
||||
|
||||
using Exprs = nodes::ExprStorage;
|
||||
using Exprs = nodes::NodeStorage;
|
||||
using Types = nodes::TypeStorage;
|
||||
using Names = names::NameTree;
|
||||
|
||||
|
|
@ -230,10 +231,10 @@ private:
|
|||
|
||||
class ContextHolder {
|
||||
public:
|
||||
ContextHolder(State &state, const nodes::Node &node,
|
||||
ContextHolder(State &state, const utils::Pos &pos,
|
||||
nodes::MaybeType *context_exit_type)
|
||||
: state_(state), context_exit_type_(context_exit_type) {
|
||||
state.enter_context(node);
|
||||
state.enter_context(pos);
|
||||
}
|
||||
|
||||
ContextHolder(const ContextHolder &) = delete;
|
||||
|
|
@ -299,46 +300,46 @@ using MaybeResult = std::optional<Result>;
|
|||
//
|
||||
|
||||
nodes::Type check_same_to_pass_type_in_args(
|
||||
nodes::Type type, const Args &args, const nodes::Node &node,
|
||||
nodes::Type type, const Args &args, const utils::Pos &pos,
|
||||
Executor &executor,
|
||||
const std::string &message = "Different type with passed one",
|
||||
bool handle_errors = true);
|
||||
|
||||
// bool check_no_pass_type_in_args(
|
||||
// const Args &args, const nodes::Node &node,
|
||||
// const Args &args, const utils::Pos &pos,
|
||||
// SourcesManager &sources_manager,
|
||||
// const std::string &message = "Type can't be passed to this node");
|
||||
|
||||
Result type_same_to_expected(
|
||||
nodes::Type type, const Args &argumensr, const nodes::Node &node,
|
||||
nodes::Type type, const Args &args, const utils::Pos &pos,
|
||||
Executor &executor,
|
||||
const std::string &message = "Different type with expected one",
|
||||
bool handle_errors = true);
|
||||
|
||||
Result type_check_from_args(nodes::Type type, const Args &args,
|
||||
const nodes::Node &node, Executor &executor,
|
||||
const utils::Pos &pos, Executor &executor,
|
||||
bool handle_errors = true);
|
||||
|
||||
std::optional<const nodes::TypeDefinition *>
|
||||
find_type_definition(const std::string &name, const nodes::Node &node,
|
||||
find_type_definition(const std::string &name, const utils::Pos &pos,
|
||||
Executor &executor, bool handle_errors = true);
|
||||
|
||||
std::optional<const nodes::FunctionDefinition *>
|
||||
find_name_definition(const std::string &name, const nodes::Node &node,
|
||||
find_name_definition(const std::string &name, const utils::Pos &pos,
|
||||
Executor &executor, bool handle_errors = true);
|
||||
|
||||
nodes::MaybeType unfold_user_defined_type(nodes::Type type,
|
||||
const nodes::Node &node,
|
||||
const utils::Pos &pos,
|
||||
Executor &executor,
|
||||
bool handle_errors = true);
|
||||
|
||||
nodes::MaybeType get_field_type_by_name(nodes::Type type,
|
||||
const std::string &field,
|
||||
const nodes::Node &node,
|
||||
const utils::Pos &pos,
|
||||
Executor &executor,
|
||||
bool handle_errors = true);
|
||||
|
||||
void type_check_error(const std::string &message, const nodes::Node &node,
|
||||
void type_check_error(const std::string &message, const utils::Pos &pos,
|
||||
Executor &executor, bool handle_error = true);
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ namespace type_check {
|
|||
|
||||
nodes::Type get_literal_type(const nodes::Literal &literal,
|
||||
Executor &executor) {
|
||||
switch (literal.get_any().index()) {
|
||||
switch (literal.value.index()) {
|
||||
case 0: // float
|
||||
return executor.state<Types>().primitive(builtin::Type::FLOAT);
|
||||
case 1: // double
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace type_check {
|
|||
// pass type -> compare types, return bool
|
||||
// no pass type -> return type
|
||||
nodes::Type check_same_to_pass_type_in_args(nodes::Type type, const Args &args,
|
||||
const nodes::Node & /*node*/,
|
||||
const utils::Pos &,
|
||||
Executor &executor,
|
||||
const std::string &message,
|
||||
bool handle_errors) {
|
||||
|
|
@ -24,13 +24,13 @@ nodes::Type check_same_to_pass_type_in_args(nodes::Type type, const Args &args,
|
|||
return executor.state<Types>().primitive(builtin::Type::BOOL);
|
||||
}
|
||||
|
||||
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 utils::Pos &pos,
|
||||
Executor &executor, const std::string &message,
|
||||
bool handle_errors) {
|
||||
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||
|
||||
if (args.get_passed().has_value()) {
|
||||
type_check_error(message, node, executor, handle_errors);
|
||||
type_check_error(message, pos, executor, handle_errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ bool check_no_pass_type_in_args(const Args &args, const nodes::Node &node,
|
|||
}
|
||||
|
||||
Result type_same_to_expected(nodes::Type type, const Args &args,
|
||||
const nodes::Node & /*node*/, Executor &executor,
|
||||
const utils::Pos &, Executor &executor,
|
||||
const std::string &message, bool handle_errors) {
|
||||
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ Result type_same_to_expected(nodes::Type type, const Args &args,
|
|||
}
|
||||
|
||||
Result type_check_from_args(nodes::Type /*type*/, const Args & /*args*/,
|
||||
const nodes::Node & /*node*/, Executor &executor,
|
||||
const utils::Pos &, Executor &executor,
|
||||
bool /*handle_errors*/) {
|
||||
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||
|
||||
|
|
@ -72,8 +72,8 @@ Result type_check_from_args(nodes::Type /*type*/, const Args & /*args*/,
|
|||
|
||||
template <typename T>
|
||||
std::optional<const T *>
|
||||
find_statement(const std::string &name, const nodes::Node & /*node*/,
|
||||
Executor &executor, const std::string &message_not_found,
|
||||
find_statement(const std::string &name, const utils::Pos &, Executor &executor,
|
||||
const std::string &message_not_found,
|
||||
const std::string &message_different_statement,
|
||||
bool handle_errors) {
|
||||
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||
|
|
@ -98,43 +98,43 @@ find_statement(const std::string &name, const nodes::Node & /*node*/,
|
|||
}
|
||||
|
||||
std::optional<const nodes::TypeDefinition *>
|
||||
find_type_definition(const std::string &name, const nodes::Node &node,
|
||||
find_type_definition(const std::string &name, const utils::Pos &pos,
|
||||
Executor &executor, bool handle_errors) {
|
||||
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||
|
||||
return find_statement<nodes::TypeDefinition>(
|
||||
name, node, executor, "No type definition found in name tree",
|
||||
name, pos, executor, "No type definition found in name tree",
|
||||
"Node in name tree is not type definition", handle_errors);
|
||||
}
|
||||
|
||||
std::optional<const nodes::FunctionDefinition *>
|
||||
find_name_definition(const std::string &name, const nodes::Node &node,
|
||||
find_name_definition(const std::string &name, const utils::Pos &pos,
|
||||
Executor &executor, bool handle_errors) {
|
||||
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||
|
||||
return find_statement<nodes::FunctionDefinition>(
|
||||
name, node, executor, "No name definition found in name tree",
|
||||
name, pos, executor, "No name definition found in name tree",
|
||||
"Node in name tree is not name definition", handle_errors);
|
||||
}
|
||||
|
||||
std::optional<nodes::Type> unfold_user_defined_type(nodes::Type type,
|
||||
const nodes::Node &node,
|
||||
const utils::Pos &pos,
|
||||
Executor &executor,
|
||||
bool handle_errors) {
|
||||
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||
|
||||
const auto maybe_type_definition = find_type_definition(
|
||||
*type.get()->get_name()->get(), node, executor, handle_errors);
|
||||
type.get()->get_name()->value, pos, executor, handle_errors);
|
||||
|
||||
if (!maybe_type_definition.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (maybe_type_definition.value()->get_type().has_value()) {
|
||||
if (maybe_type_definition.value()->type.has_value()) {
|
||||
if (handle_errors) {
|
||||
logc.Error<Log::kProc>({{std::format(
|
||||
"Only type declaration found for type {} (type is not defined)",
|
||||
*type.get()->get_name()->get())}} /* TODO: node*/);
|
||||
type.get()->get_name()->value)}} /* TODO: node*/);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
|
@ -143,12 +143,12 @@ std::optional<nodes::Type> unfold_user_defined_type(nodes::Type type,
|
|||
logc.Require<Log::kProc>(type.get()->parameters_size() == 0,
|
||||
{{"Unfold of generic type is not supported (yet)"}});
|
||||
//
|
||||
return maybe_type_definition.value()->get_type().value();
|
||||
return maybe_type_definition.value()->type.value();
|
||||
}
|
||||
|
||||
std::optional<nodes::Type> get_field_type_by_name(nodes::Type type,
|
||||
const std::string &field,
|
||||
const nodes::Node &node,
|
||||
const utils::Pos &pos,
|
||||
Executor &executor,
|
||||
bool handle_errors) {
|
||||
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||
|
|
@ -170,12 +170,12 @@ std::optional<nodes::Type> get_field_type_by_name(nodes::Type type,
|
|||
|
||||
// remove recursion ??
|
||||
const auto maybe_internal_type =
|
||||
unfold_user_defined_type(type, node, executor, handle_errors);
|
||||
unfold_user_defined_type(type, pos, executor, handle_errors);
|
||||
if (!maybe_internal_type.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return get_field_type_by_name(maybe_internal_type.value(), field, node,
|
||||
return get_field_type_by_name(maybe_internal_type.value(), field, pos,
|
||||
executor, handle_errors);
|
||||
}
|
||||
default: // variant, function, optional, result, error (TODO: add message
|
||||
|
|
@ -192,7 +192,7 @@ std::optional<nodes::Type> get_field_type_by_name(nodes::Type type,
|
|||
}
|
||||
|
||||
// FIXME: replace with direct log calls
|
||||
void type_check_error(const std::string &message, const nodes::Node &,
|
||||
void type_check_error(const std::string &message, const utils::Pos &,
|
||||
Executor &executor, bool handle_error) {
|
||||
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ includes("../nodes/xmake.lua")
|
|||
|
||||
set_languages("c++20")
|
||||
|
||||
target("lang.type_check")
|
||||
set_kind("static")
|
||||
add_includedirs("include", {public = true})
|
||||
add_files("src/**.cpp")
|
||||
add_deps("lang.utils", "lang.nodes")
|
||||
set_warnings("allextra") -- , "error")
|
||||
set_rundir("$(projectdir)")
|
||||
-- target("lang.type_check")
|
||||
-- set_kind("static")
|
||||
-- add_includedirs("include", {public = true})
|
||||
-- add_files("src/**.cpp")
|
||||
-- add_deps("lang.utils", "lang.nodes")
|
||||
-- set_warnings("allextra") -- , "error")
|
||||
-- set_rundir("$(projectdir)")
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
// FIXME: DEPRECATED, TO DELETE
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "basic_nodes.hpp"
|
||||
|
|
@ -8,69 +10,69 @@
|
|||
|
||||
namespace error_handling {
|
||||
|
||||
inline void handle_internal_error(
|
||||
std::string_view message, const nodes::Node &node,
|
||||
const std::source_location &location = std::source_location::current()) {
|
||||
std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at ";
|
||||
print_position(std::cerr, node.get_start_position(), node.get_end_position());
|
||||
std::cerr << ".\n";
|
||||
print_source_location(std::cerr, location);
|
||||
exit(1);
|
||||
}
|
||||
// inline void handle_internal_error(
|
||||
// std::string_view message, const nodes::Node &node,
|
||||
// const std::source_location &location = std::source_location::current()) {
|
||||
// std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at ";
|
||||
// print_position(std::cerr, node.get_start_position(),
|
||||
// node.get_end_position()); std::cerr << ".\n";
|
||||
// print_source_location(std::cerr, location);
|
||||
// exit(1);
|
||||
// }
|
||||
|
||||
inline void handle_internal_error(
|
||||
std::string_view message, parser::ParseTree::Node node,
|
||||
const std::source_location &location = std::source_location::current()) {
|
||||
std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at ";
|
||||
print_position(std::cerr, node.get_start_point(), node.get_end_point());
|
||||
std::cerr << ".\n";
|
||||
print_source_location(std::cerr, location);
|
||||
exit(1);
|
||||
}
|
||||
// inline void handle_internal_error(
|
||||
// std::string_view message, parser::ParseTree::Node node,
|
||||
// const std::source_location &location = std::source_location::current()) {
|
||||
// std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at ";
|
||||
// print_position(std::cerr, node.get_start_point(), node.get_end_point());
|
||||
// std::cerr << ".\n";
|
||||
// print_source_location(std::cerr, location);
|
||||
// exit(1);
|
||||
// }
|
||||
|
||||
inline void handle_parsing_error(
|
||||
std::string_view message, parser::ParseTree::Node parse_node,
|
||||
const std::source_location &location = std::source_location::current()) {
|
||||
std::cerr << "\x1b[1;31mParsing Error:\x1b[0m " << message << " at ";
|
||||
print_position(std::cerr, parse_node.get_start_point(),
|
||||
parse_node.get_end_point());
|
||||
std::cerr << ".\n";
|
||||
print_source_location(std::cerr, location);
|
||||
exit(1);
|
||||
}
|
||||
// inline void handle_parsing_error(
|
||||
// std::string_view message, parser::ParseTree::Node parse_node,
|
||||
// const std::source_location &location = std::source_location::current()) {
|
||||
// std::cerr << "\x1b[1;31mParsing Error:\x1b[0m " << message << " at ";
|
||||
// print_position(std::cerr, parse_node.get_start_point(),
|
||||
// parse_node.get_end_point());
|
||||
// std::cerr << ".\n";
|
||||
// print_source_location(std::cerr, location);
|
||||
// exit(1);
|
||||
// }
|
||||
|
||||
inline void handle_typecheck_error(
|
||||
std::string_view message, nodes::Node node,
|
||||
const std::source_location &location = std::source_location::current()) {
|
||||
std::cerr << "\x1b[1;31mTypecheck Error:\x1b[0m " << message << " at ";
|
||||
print_position(std::cerr, node.get_start_position(), node.get_end_position());
|
||||
std::cerr << ".\n";
|
||||
print_source_location(std::cerr, location);
|
||||
exit(1);
|
||||
}
|
||||
// inline void handle_typecheck_error(
|
||||
// std::string_view message, nodes::Node node,
|
||||
// const std::source_location &location = std::source_location::current()) {
|
||||
// std::cerr << "\x1b[1;31mTypecheck Error:\x1b[0m " << message << " at ";
|
||||
// print_position(std::cerr, node.get_start_position(),
|
||||
// node.get_end_position()); std::cerr << ".\n";
|
||||
// print_source_location(std::cerr, location);
|
||||
// exit(1);
|
||||
// }
|
||||
|
||||
inline void handle_runtime_error(
|
||||
std::string_view message, nodes::Node node,
|
||||
const std::source_location &location = std::source_location::current()) {
|
||||
std::cerr << "\x1b[1;31mRuntime Error:\x1b[0m " << message << " at ";
|
||||
print_position(std::cerr, node.get_start_position(), node.get_end_position());
|
||||
std::cerr << ".\n";
|
||||
print_source_location(std::cerr, location);
|
||||
exit(1);
|
||||
}
|
||||
// inline void handle_runtime_error(
|
||||
// std::string_view message, nodes::Node node,
|
||||
// const std::source_location &location = std::source_location::current()) {
|
||||
// std::cerr << "\x1b[1;31mRuntime Error:\x1b[0m " << message << " at ";
|
||||
// print_position(std::cerr, node.get_start_position(),
|
||||
// node.get_end_position()); std::cerr << ".\n";
|
||||
// print_source_location(std::cerr, location);
|
||||
// exit(1);
|
||||
// }
|
||||
|
||||
inline void handle_names_error(
|
||||
std::string_view message, nodes::Node node,
|
||||
const std::source_location &location = std::source_location::current()) {
|
||||
std::cerr << "\x1b[1;31mNames Error:\x1b[0m " << message << " at ";
|
||||
print_position(std::cerr, node.get_start_position(), node.get_end_position());
|
||||
std::cerr << ".\n";
|
||||
print_source_location(std::cerr, location);
|
||||
exit(1);
|
||||
}
|
||||
// inline void handle_names_error(
|
||||
// std::string_view message, nodes::Node node,
|
||||
// const std::source_location &location = std::source_location::current()) {
|
||||
// std::cerr << "\x1b[1;31mNames Error:\x1b[0m " << message << " at ";
|
||||
// print_position(std::cerr, node.get_start_position(),
|
||||
// node.get_end_position()); std::cerr << ".\n";
|
||||
// print_source_location(std::cerr, location);
|
||||
// exit(1);
|
||||
// }
|
||||
|
||||
template <typename T> inline void debug_print(const T &value) {
|
||||
std::cerr << "\x1b[1;33mDebug:\x1b[0m " << value << '\n';
|
||||
}
|
||||
// template <typename T> inline void debug_print(const T &value) {
|
||||
// std::cerr << "\x1b[1;33mDebug:\x1b[0m " << value << '\n';
|
||||
// }
|
||||
|
||||
} // namespace error_handling
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ public:
|
|||
|
||||
enum class Area {
|
||||
kDefault,
|
||||
kBuild,
|
||||
kParse,
|
||||
kTypeCheck,
|
||||
kIntepret,
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ template <typename T> class DependentStorage : public Storage<T> {
|
|||
using Id = storage::Id;
|
||||
|
||||
public:
|
||||
void ForceInsert(Id id, T &&elem) {
|
||||
utils::Assert(Storage<T>::data_.insert(id, elem).second,
|
||||
void ForceInsert(Id id, T elem) {
|
||||
utils::Assert(Storage<T>::data_.insert({id, std::move(elem)}).second,
|
||||
std::format("insert failed, id={}", *id));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,8 +33,7 @@ func {
|
|||
: example of function with optional arguments (without type annotation)
|
||||
: real type is 'A? 'A? -> 'A?
|
||||
sum 'a? 'b? =
|
||||
'a & 'b =: %a? & %b? => a + b
|
||||
=: _ => null;
|
||||
'a & 'b =: %a => a;
|
||||
|
||||
|
||||
: example that shows that default annotations are argument names (without ')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue