Most fixes done, build working (without typecheck fixes, is_scoped proper propogation and executor views)

This commit is contained in:
ProgramSnail 2024-09-01 14:19:56 +03:00
parent d02c3a637b
commit 5891066414
33 changed files with 1391 additions and 960 deletions

View file

@ -51,7 +51,13 @@ public:
void Print(std::ostream &out) { void Print(std::ostream &out) {
printers::Printer printer(out, 2, 80, true); 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(); } size_t statements_size() const { return statements_.size(); }

View file

@ -40,7 +40,7 @@ template <typename N, typename Tag = utils::None> struct BuilderTask {
template <typename N> struct BuilderTaskUtils : public Task<N> { template <typename N> struct BuilderTaskUtils : public Task<N> {
using Task<N>::Task; using Task<N>::Task;
Node Ext(storage::Id id) const { Node Ext(storage::Id id) {
return Node(id, this->template state<Exprs>(), return Node(id, this->template state<Exprs>(),
this->template state<Positions>()); 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) { template <typename T> Node Build(T value, utils::Pos pos) {
auto id = this->template state<Exprs>().Insert(std::move(value)); auto id = this->template state<Exprs>().Insert(std::move(value));
this->template state<Positions>().ForceInsert(id, pos); 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); BuilderTask<OtherN, OtherTag> task(this->executor);
return task(node, args); 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, template <typename OtherN, typename OtherTag = utils::None,
typename Ret = OtherN> typename Ret = nodes::Type>
Ret RunOther(const parser::ParseTree::Node &node, const Args &args = {}) { Ret Run(const parser::ParseTree::Node &node, const Args &args = {}) {
BuilderTask<OtherN, OtherTag> task(this->executor); BuilderTask<OtherN, OtherTag> task(this->executor);
return task(node, args); return task(node, args);
} }

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "builders_utils.hpp"
#include "doc_nodes.hpp" #include "doc_nodes.hpp"
#include "tree_sitter_wrapper.hpp" #include "tree_sitter_wrapper.hpp"
@ -8,9 +9,10 @@
namespace builders { namespace builders {
nodes::SymbolDocs build_symbol_docs( nodes::SymbolDocs
std::optional<parser::ParseTree::Node> description_parser_node, build_symbol_docs(std::optional<ParserNode> description_parser_node,
const std::vector<parser::ParseTree::Node> &annotation_parser_nodes = {}, const std::vector<ParserNode> &annotation_parser_nodes,
const std::unordered_set<std::string> &annotations = {}); const std::unordered_set<std::string> &annotations,
Executor &executor);
} // namespace builders } // namespace builders

View file

@ -23,6 +23,13 @@ namespace builders {
// --- flow control // --- 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> { template <> struct BuilderTask<Node> : public ExprBuilderTaskBase<Node> {
using ExprBuilderTaskBase<Node>::ExprBuilderTaskBase; using ExprBuilderTaskBase<Node>::ExprBuilderTaskBase;
@ -90,6 +97,8 @@ struct BuilderTask<nodes::Container, T>
// or // or
// '[[' expression+ ']]' // '[[' expression+ ']]'
Node operator()(const ParserNode &parser_node, const Args &) override { 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> const auto kind = std::is_same_v<T, utils::BlockTag>
? nodes::Container::BLOCK ? nodes::Container::BLOCK
: nodes::Container::ARRAY; : nodes::Container::ARRAY;
@ -103,10 +112,12 @@ struct BuilderTask<nodes::Container, T>
current_node = current_node.next_named_sibling(); current_node = current_node.next_named_sibling();
} }
return state<Exprs>().Insert(nodes::Container{ return Build(
.kind = kind, nodes::Container{
.exprs = std::move(exprs), .kind = kind,
}); .exprs = std::move(exprs),
},
parser_node.get_pos());
} }
}; };
@ -162,13 +173,18 @@ struct BuilderTask<nodes::ModifierExpression, T>
// or // or
// expression ('?' | '!') // expression ('?' | '!')
Node operator()(const ParserNode &parser_node, const Args &) override { Node operator()(const ParserNode &parser_node, const Args &) override {
Log::Context logc(executor.log(), Log::Area::kParse);
const size_t modifier_pos = const size_t modifier_pos =
std::is_same_v<T, utils::RefTag> ? 0 : parser_node.child_count() - 1; std::is_same_v<T, utils::RefTag> ? 0 : parser_node.child_count() - 1;
return state<Exprs>().Insert(nodes::ModifierExpression{ return Build(
.modifier = Run<nodes::Modifier>(parser_node.nth_child(modifier_pos)), nodes::ModifierExpression{
.expr = Run<Node>(parser_node.nth_named_child(0)), .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());
} }
}; };

View file

@ -1,26 +1,69 @@
#pragma once #pragma once
#include "builders_utils.hpp"
#include "tokens.hpp"
#include "tree_sitter_wrapper.hpp" #include "tree_sitter_wrapper.hpp"
#include "type_nodes.hpp" #include "type_nodes.hpp"
namespace utils {
template <tokens::Type> struct TypeTag {};
} // namespace utils
namespace builders { namespace builders {
nodes::Type build_type(parser::ParseTree::Node parse_node, template <>
nodes::TypeStorage &type_storage); struct BuilderTask<nodes::Type> : public TypeBuilderTaskBase<nodes::Type> {
using TypeBuilderTaskBase<nodes::Type>::TypeBuilderTaskBase;
nodes::Type build_variant_type(parser::ParseTree::Node parse_node, nodes::Type operator()(const ParserNode &parser_node,
nodes::TypeStorage &type_storage); const Args &args) override;
};
nodes::Type build_tuple_type(parser::ParseTree::Node parse_node, template <>
nodes::TypeStorage &type_storage); 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::Type operator()(const ParserNode &parser_node,
nodes::TypeStorage &type_storage); const Args &args) override;
};
nodes::Type build_modified_type(parser::ParseTree::Node parse_node, template <>
nodes::TypeStorage &type_storage); 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::Type operator()(const ParserNode &parser_node,
nodes::TypeStorage &type_storage); 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 } // namespace builders

View file

@ -1,15 +1,17 @@
#include "doc_builders.hpp" #include "doc_builders.hpp"
#include "basic_builders.hpp" #include "basic_builders.hpp"
#include "doc_nodes.hpp" #include "doc_nodes.hpp"
#include "error_handling.hpp" #include "log.hpp"
namespace builders { namespace builders {
// TODO: check, that all annotations are exist in function definition // TODO: check, that all annotations are exist in function definition
nodes::SymbolDocs build_symbol_docs( nodes::SymbolDocs
std::optional<parser::ParseTree::Node> description_parser_node, build_symbol_docs(std::optional<ParserNode> description_parser_node,
const std::vector<parser::ParseTree::Node> &annotation_parser_nodes, const std::vector<ParserNode> &annotation_parser_nodes,
const std::unordered_set<std::string> &annotations) { const std::unordered_set<std::string> &annotations,
Executor &executor) {
Log::Context logc(executor.log(), Log::Area::kParse);
std::optional<std::string> description; std::optional<std::string> description;
@ -35,15 +37,16 @@ nodes::SymbolDocs build_symbol_docs(
: nodes::SymbolDocs(); : nodes::SymbolDocs();
for (auto &annotation_parser_node : annotation_parser_nodes) { for (auto &annotation_parser_node : annotation_parser_nodes) {
std::string annotation = std::string annotation = BuilderTask<nodes::Annotation>{executor}(
build_annotation(annotation_parser_node.nth_named_child(0)); annotation_parser_node.nth_named_child(0), {})
.value;
if (annotations.count(annotation) == 0) { logc.Expect<Log::kProc>(
error_handling::handle_parsing_error( annotations.count(annotation) == 0,
"Annotation \"" + annotation + {{std::format(
"\" doesn't present in corresponding symbol", "Annotation \"{}\" doesn't present in corresponding symbol",
annotation_parser_node); annotation)}},
} annotation_parser_node.get_pos());
docs.add_annotation_info( docs.add_annotation_info(
annotation, annotation_parser_node.nth_named_child(1).get_value()); annotation, annotation_parser_node.nth_named_child(1).get_value());

View file

@ -12,15 +12,29 @@
namespace builders { 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, Node BuilderTask<Node>::operator()(const ParserNode &parser_node,
const Args &) { const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse); 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()); tokens::Type type = tokens::string_to_type(parser_node.get_type());
auto maybe_parenthesis = parser_node.previous_sibling(); auto maybe_parenthesis = parser_node.previous_sibling();
// FIXME TODO
bool is_scoped = bool is_scoped =
(!maybe_parenthesis.is_null() && !maybe_parenthesis.is_named() && (!maybe_parenthesis.is_null() && !maybe_parenthesis.is_named() &&
maybe_parenthesis.get_value() == "("); maybe_parenthesis.get_value() == "(");
@ -66,8 +80,12 @@ Node BuilderTask<Node>::operator()(const ParserNode &parser_node,
case tokens::Type::NAME_EXPRESSION: case tokens::Type::NAME_EXPRESSION:
return Run<nodes::NameExpression, utils::FuncCallTag>(parser_node, return Run<nodes::NameExpression, utils::FuncCallTag>(parser_node,
{is_scoped}); {is_scoped});
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
case tokens::Type::SIMPLE_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: case tokens::Type::PLACEHOLDER:
return Build( return Build(
nodes::NameExpression{ nodes::NameExpression{
@ -79,43 +97,56 @@ Node BuilderTask<Node>::operator()(const ParserNode &parser_node,
case tokens::Type::LAMBDA: case tokens::Type::LAMBDA:
return Run<nodes::Lambda>(parser_node); return Run<nodes::Lambda>(parser_node);
// --- literals // --- literals
// TODO: FIXME: case tokens::Type::FLOAT_LITERAL:
// case tokens::Type::FLOAT_LITERAL: return Build(RunOther<nodes::Literal, float>(parser_node),
// return BUILD : build_float_literal(parser_node); parser_node.get_pos());
// case tokens::Type::DOUBLE_LITERAL: case tokens::Type::DOUBLE_LITERAL:
// return BUILD : build_double_literal(parser_node); return Build(RunOther<nodes::Literal, double>(parser_node),
// case tokens::Type::INT_LITERAL: parser_node.get_pos());
// return BUILD : build_int_literal(parser_node); case tokens::Type::INT_LITERAL:
// case tokens::Type::LONG_LITERAL: return Build(RunOther<nodes::Literal, int32_t>(parser_node),
// return BUILD : build_long_literal(parser_node); parser_node.get_pos());
// case tokens::Type::INDEX_LITERAL: case tokens::Type::LONG_LITERAL:
// return BUILD : build_index_literal(parser_node); return Build(RunOther<nodes::Literal, int64_t>(parser_node),
// case tokens::Type::STRING_LITERAL: parser_node.get_pos());
// return BUILD : build_string_literal(parser_node); case tokens::Type::INDEX_LITERAL:
// case tokens::Type::UNICODE_STRING_LITERAL: return Build(RunOther<nodes::Literal, size_t>(parser_node),
// return BUILD : build_unicode_string_literal(parser_node); parser_node.get_pos());
// case tokens::Type::CHAR_LITERAL: case tokens::Type::STRING_LITERAL:
// return BUILD : build_char_literal(parser_node); return Build(RunOther<nodes::Literal, std::string>(parser_node),
// case tokens::Type::UNICODE_LITERAL: parser_node.get_pos());
// return BUILD : build_unicode_literal(parser_node); case tokens::Type::UNICODE_STRING_LITERAL:
// case tokens::Type::BOOL_LITERAL: return Build(RunOther<nodes::Literal, nodes::unicode_string>(parser_node),
// return BUILD : build_bool_literal(parser_node); parser_node.get_pos());
// case tokens::Type::UNIT_LITERAL: case tokens::Type::CHAR_LITERAL:
// return BUILD : build_unit_literal(parser_node); return Build(RunOther<nodes::Literal, char>(parser_node),
// case tokens::Type::NULL_LITERAL: parser_node.get_pos());
// return BUILD : build_null_literal(parser_node); case tokens::Type::UNICODE_LITERAL:
// case tokens::Type::EXTRA: return Build(RunOther<nodes::Literal, nodes::unicode>(parser_node),
// return BUILD : build_extra(parser_node); parser_node.get_pos());
// case tokens::Type::EMPTY_LINES: case tokens::Type::BOOL_LITERAL:
// return BUILD : build_empty_lines(parser_node); 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: default:
break; break;
} }
utils::Assert(true, std::format("Unexpected expression node type {}", utils::Assert(false, std::format("Unexpected expression node type [{}]\n",
static_cast<int>(type))); // TODO: magic_enum parser_node.get_type())); // TODO: magic_enum
// FIXME: change to fatal error ? // FIXME: change to fatal error ?
throw std::exception(); utils::unreachable();
} }
// --- flow control // --- flow control
@ -124,8 +155,9 @@ Node BuilderTask<Node>::operator()(const ParserNode &parser_node,
Node BuilderTask<nodes::Match::Case>::operator()(const ParserNode &parser_node, Node BuilderTask<nodes::Match::Case>::operator()(const ParserNode &parser_node,
const Args &) { const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse); 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> condition_node;
std::optional<ParserNode> expression_node; std::optional<ParserNode> expression_node;
@ -146,15 +178,15 @@ Node BuilderTask<nodes::Match::Case>::operator()(const ParserNode &parser_node,
return Build( return Build(
nodes::Match::Case{ nodes::Match::Case{
.kind = case_type == ":=" ? nodes::Match::Case::PATTERN_VALUE .kind = case_kind == ":=" ? nodes::Match::Case::PATTERN_VALUE
: nodes::Match::Case::VALUE_PATTERN, : nodes::Match::Case::VALUE_PATTERN,
.value = Run<Node>(parser_node.nth_named_child(0)), .value = Run<Node>(parser_node.nth_named_child(0)),
.condition = condition_node.has_value() .condition = condition_node.has_value()
? Run<Node>(condition_node.value()) ? Run<Node>(condition_node.value())
: std::optional<storage::Id>(), : std::optional<nodes::NodeId>(),
.expr = expression_node.has_value() .expr = expression_node.has_value()
? Run<Node>(expression_node.value()) ? Run<Node>(expression_node.value())
: std::optional<storage::Id>(), : std::optional<nodes::NodeId>(),
}, },
parser_node.get_pos()); parser_node.get_pos());
} }
@ -164,7 +196,8 @@ Node BuilderTask<nodes::Match>::operator()(const ParserNode &parser_node,
const Args &) { const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse); 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); auto current_node = parser_node.nth_named_child(1);
while (!current_node.is_null()) { while (!current_node.is_null()) {
@ -175,7 +208,8 @@ Node BuilderTask<nodes::Match>::operator()(const ParserNode &parser_node,
return Build( return Build(
nodes::Match{ 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), .cases = std::move(cases),
}, },
parser_node.get_pos()); 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(); 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 current_node = parser_node.nth_named_child(0);
auto next_node = current_node.next_named_sibling(); auto next_node = current_node.next_named_sibling();
while (!current_node.is_null() && !next_node.is_null()) { while (!current_node.is_null() && !next_node.is_null()) {
cases.push_back( cases.push_back(
{Run<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(); current_node = next_node.next_named_sibling();
if (current_node.is_null()) { if (current_node.is_null()) {
break; break;
@ -253,13 +287,13 @@ Node BuilderTask<nodes::NameExpression, utils::CommaTag>::operator()(
const ParserNode &parser_node, const Args &) { const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse); 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, 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, 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( return Build(
nodes::NameExpression{ nodes::NameExpression{
@ -284,7 +318,7 @@ Node BuilderTask<nodes::NameExpression, utils::OperatorTag>::operator()(
auto name_node = parser_node.child_by_field_name("name"); 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, args.emplace_back(std::nullopt,
Run<Node>(name_node.previous_named_sibling())); Run<Node>(name_node.previous_named_sibling()));
@ -455,7 +489,8 @@ Node BuilderTask<nodes::NameExpression, utils::FuncCallTag>::operator()(
.name = RunOther<nodes::Identifier>(name_node), .name = RunOther<nodes::Identifier>(name_node),
.args = std::move(args), .args = std::move(args),
.prefix = prefix_node.has_value() .prefix = prefix_node.has_value()
? build_type(prefix_node.value(), state<Types>()) ? RunOther<nodes::Type, utils::None, nodes::Type>(
prefix_node.value())
: nodes::MaybeType(), : nodes::MaybeType(),
.is_point_call = is_point_call, .is_point_call = is_point_call,
.is_operator_call = false, .is_operator_call = false,
@ -479,8 +514,8 @@ Node BuilderTask<nodes::Constructor>::operator()(const ParserNode &parser_node,
return Build( return Build(
nodes::Constructor{ nodes::Constructor{
.type = build_type(parser_node.child_by_field_name("type"), .type = RunOther<nodes::Type, utils::None, nodes::Type>(
state<Types>()), parser_node.child_by_field_name("type")),
.args = std::move(args), .args = std::move(args),
}, },
parser_node.get_pos()); parser_node.get_pos());

View file

@ -239,9 +239,10 @@ BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
} }
} }
nodes::MaybeType type = type_node.has_value() nodes::MaybeType type =
? build_type(type_node.value(), state<Types>()) type_node.has_value()
: nodes::MaybeType(); ? RunOther<nodes::Type, utils::None, nodes::Type>(type_node.value())
: nodes::MaybeType();
std::unordered_set<std::string> annotations; std::unordered_set<std::string> annotations;
@ -252,8 +253,8 @@ BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
} }
return nodes::TypeDefinition{ return nodes::TypeDefinition{
.docs = .docs = build_symbol_docs(description_node, annotation_nodes, annotations,
build_symbol_docs(description_node, annotation_nodes, annotations), executor),
.is_on_heap = is_on_heap, .is_on_heap = is_on_heap,
.name = std::move(name), .name = std::move(name),
.typeclasses = std::move(typeclasses), .typeclasses = std::move(typeclasses),
@ -377,11 +378,13 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
case tokens::Type::SIMPLE_TYPE: case tokens::Type::SIMPLE_TYPE:
if (current_type_id >= args.size()) { if (current_type_id >= args.size()) {
args.push_back(nodes::FunctionDefinition::Argument( 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)); last_before_modifier));
} else { } else {
if (!args[current_type_id].add_type( 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)) { last_before_modifier)) {
logc.Fatal<Log::kProc>( logc.Fatal<Log::kProc>(
{{"It is impossible to use argument modifiers (annotations, " {{"It is impossible to use argument modifiers (annotations, "
@ -427,7 +430,7 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
if (are_annotations_same_to_names) { if (are_annotations_same_to_names) {
for (size_t i = 0; i < args.size(); ++i) { for (size_t i = 0; i < args.size(); ++i) {
std::string new_annotation = args[i].get_name().value()->value; std::string new_annotation = args[i].name.value().value;
if (!args[i].add_annotation( if (!args[i].add_annotation(
new_annotation.substr(1, new_annotation.size() - 1))) { new_annotation.substr(1, new_annotation.size() - 1))) {
logc.Fatal<Log::kProc>({{"no annotations provided ( => all annotations " 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; std::unordered_set<std::string> annotations_set;
for (auto &arg : args) { for (auto &arg : args) {
if (arg.get_annotation().has_value()) { if (arg.annotation.has_value()) {
if (!annotations_set.insert(*arg.get_annotation().value()).second) { if (!annotations_set.insert(arg.annotation.value()).second) {
logc.Fatal<Log::kProc>( logc.Fatal<Log::kProc>(
{{"Two or more same annotations found in function definition"}}, {{"Two or more same annotations found in function definition"}},
parser_node.get_pos()); parser_node.get_pos());
@ -450,7 +453,8 @@ nodes::FunctionDefinition BuilderTask<nodes::FunctionDefinition>::operator()(
} }
return nodes::FunctionDefinition( 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, std::move(constraints), return_modifier, is_method, name_prefix,
Run<nodes::Identifier>(name_node), std::move(args), Run<nodes::Identifier>(name_node), std::move(args),
are_annotations_same_to_names, are_annotations_same_to_names,

View file

@ -2,14 +2,19 @@
#include "basic_builders.hpp" #include "basic_builders.hpp"
#include "basic_nodes.hpp" #include "basic_nodes.hpp"
#include "builtin_types.hpp" #include "builtin_types.hpp"
#include "error_handling.hpp" // #include "error_handling.hpp"
#include "tokens.hpp" #include "tokens.hpp"
#include "type_nodes.hpp" #include "type_nodes.hpp"
namespace builders { namespace builders {
nodes::Type build_type(parser::ParseTree::Node parser_node, using Tp = tokens::Type;
nodes::TypeStorage &type_storage) { 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()); tokens::Type type = tokens::string_to_type(parser_node.get_type());
// TODO: for better formatted printing // TODO: for better formatted printing
@ -19,26 +24,29 @@ nodes::Type build_type(parser::ParseTree::Node parser_node,
// maybe_parenthesis.get_value() == "("); // maybe_parenthesis.get_value() == "(");
switch (type) { switch (type) {
case tokens::Type::VARIANT_TYPE: case Tp::VARIANT_TYPE:
return build_variant_type(parser_node, type_storage); return Run<nodes::Type, TypeTag<Tp::VARIANT_TYPE>>(parser_node);
case tokens::Type::TUPLE_TYPE: case Tp::TUPLE_TYPE:
return build_tuple_type(parser_node, type_storage); return Run<nodes::Type, TypeTag<Tp::TUPLE_TYPE>>(parser_node);
case tokens::Type::REFERENCE_TYPE: case Tp::REFERENCE_TYPE:
return build_reference_type(parser_node, type_storage); return Run<nodes::Type, TypeTag<Tp::REFERENCE_TYPE>>(parser_node);
case tokens::Type::MODIFIED_TYPE: case Tp::MODIFIED_TYPE:
return build_modified_type(parser_node, type_storage); return Run<nodes::Type, TypeTag<Tp::MODIFIED_TYPE>>(parser_node);
case tokens::Type::SIMPLE_TYPE: case Tp::SIMPLE_TYPE:
return build_simple_type(parser_node, type_storage); return Run<nodes::Type, TypeTag<Tp::SIMPLE_TYPE>>(parser_node);
default: default:
error_handling::handle_parsing_error("Unexprected type node type", logc.Fatal<Log::kSys>({{"Unexprected type node type"}},
parser_node); 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, 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::vector<nodes::Type> parameters;
std::optional<std::string> current_annotation; 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()) { while (!current_node.is_null()) {
if (tokens::string_to_type(current_node.get_type()) == if (tokens::string_to_type(current_node.get_type()) ==
tokens::Type::ANNOTATION_IDENTIFIER) { tokens::Type::ANNOTATION_IDENTIFIER) {
current_annotation = build_annotation(current_node); current_annotation =
BuilderTask<nodes::Annotation>{executor}(current_node, {}).value;
} else { } else {
parameters.push_back(build_type(current_node, type_storage)); parameters.push_back(
BuilderTask<nodes::Type>{executor}(current_node, {}));
if (current_annotation.has_value()) { if (current_annotation.has_value()) {
parameters.back().get()->set_annotation(current_annotation.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::Type build_container_type(parser::ParseTree::Node parser_node,
nodes::TypeStorage &type_storage, Executor &executor, builtin::Type container) {
builtin::Type container) { Log::Context logc(executor.log(), Log::Area::kParse);
std::vector<nodes::Type> parameters =
collect_parameters(parser_node.nth_named_child(0), type_storage);
return type_storage.add_container_of(std::move(parameters), container, std::vector<nodes::Type> parameters =
build_node(parser_node)); collect_parameters(parser_node.nth_named_child(0), executor);
return executor.state<Types>().add_container_of(std::move(parameters),
container);
} }
// '|'? annotation? type ('|' annotation? type)+ // '|'? annotation? type ('|' annotation? type)+
nodes::Type build_variant_type(parser::ParseTree::Node parser_node, nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::VARIANT_TYPE>>::operator()(
nodes::TypeStorage &type_storage) { const ParserNode &parser_node, const Args &) {
return build_container_type(parser_node, type_storage, Log::Context logc(executor.log(), Log::Area::kParse);
builtin::Type::VARIANT);
return build_container_type(parser_node, executor, builtin::Type::VARIANT);
} }
// '&'? annotation? type ('&' annotation? type)+ // '&'? annotation? type ('&' annotation? type)+
nodes::Type build_tuple_type(parser::ParseTree::Node parser_node, nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::TUPLE_TYPE>>::operator()(
nodes::TypeStorage &type_storage) { const ParserNode &parser_node, const Args &) {
return build_container_type(parser_node, type_storage, builtin::Type::TUPLE); Log::Context logc(executor.log(), Log::Area::kParse);
return build_container_type(parser_node, executor, builtin::Type::TUPLE);
} }
// _reference_ type // _reference_ type
nodes::Type build_reference_type(parser::ParseTree::Node parser_node, nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::REFERENCE_TYPE>>::operator()(
nodes::TypeStorage &type_storage) { const ParserNode &parser_node, const Args &) {
nodes::Type type = build_type(parser_node.nth_named_child(0), type_storage); Log::Context logc(executor.log(), Log::Area::kParse);
type.get()->set_modifier(build_modifier(parser_node.nth_child(0)));
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; return type;
} }
// type ('?' | '!') // type ('?' | '!')
nodes::Type build_modified_type(parser::ParseTree::Node parser_node, nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::MODIFIED_TYPE>>::operator()(
nodes::TypeStorage &type_storage) { const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse);
std::vector<nodes::Type> parameters; std::vector<nodes::Type> parameters;
parameters.push_back( parameters.push_back(Run<nodes::Type>(parser_node.nth_named_child(0)));
build_type(parser_node.nth_named_child(0), type_storage));
nodes::Modifier modifier = 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; std::string identifier;
@ -111,27 +131,30 @@ nodes::Type build_modified_type(parser::ParseTree::Node parser_node,
identifier = builtin::types::RESULT_IDENTIFIER; identifier = builtin::types::RESULT_IDENTIFIER;
break; break;
default: default:
error_handling::handle_parsing_error( logc.Fatal<Log::kSys>({{"Unexpected modifier type in modified type"}},
"Unexpected modifier type in modified type", parser_node); parser_node.get_pos());
break; break;
} }
return type_storage.add_type(nodes::TypeData( return executor.state<Types>().add_type(
nodes::Identifier(build_node(parser_node), nodes::Identifier::SIMPLE_TYPE, nodes::TypeData(nodes::Identifier{.kind = nodes::Identifier::kSimpleType,
identifier), .value = identifier},
std::move(parameters))); std::move(parameters)));
} }
// type_identifier ('[' (annotation? type)+ ']')? // type_identifier ('[' (annotation? type)+ ']')?
nodes::Type build_simple_type(parser::ParseTree::Node parser_node, nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::SIMPLE_TYPE>>::operator()(
nodes::TypeStorage &type_storage) { const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse);
auto name_node = parser_node.child_by_field_name("name"); auto name_node = parser_node.child_by_field_name("name");
std::vector<nodes::Type> parameters = 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( return executor.state<Types>().add_type(nodes::TypeData(
nodes::TypeData(build_identifier(name_node), std::move(parameters))); RunOther<nodes::Identifier, utils::None, nodes::Identifier>(name_node),
std::move(parameters)));
} }
} // namespace builders } // namespace builders

View file

@ -1,13 +1,14 @@
#pragma once #pragma once
#include "log.hpp"
#include "utils.hpp" #include "utils.hpp"
#include <format>
#include <optional> #include <optional>
#include <ranges> #include <ranges>
#include <string> #include <string>
#include <utility> #include <utility>
#include <variant> #include <variant>
#include <vector>
namespace nodes { namespace nodes {
@ -252,55 +253,55 @@ public:
Kind kind; Kind kind;
std::string value; std::string value;
// TODO // TODO: rewrite identifier modification
// void append_before(const std::string &name) { void append_before(std::string_view other) {
// value_ = name + NAME_DELIMITER + value_; value = std::format("{}{}{}", other, kNameDelimiter, value);
// } }
// void append_before( void append_before(
// const Identifier &identifier, const Identifier &other,
// std::source_location location = std::source_location::current()) { std::source_location source_location = std::source_location::current()) {
// error_handling::expect(identifier.type_ == type_, ::utils::Assert(other.kind == kind,
// "different Identifier types on append_before", "different Identifier types on append_before",
// location); source_location);
// value_ = *identifier.get() + NAME_DELIMITER + value_; value = std::format("{}{}{}", other.value, kNameDelimiter, value);
// } }
// void append_after(const std::string &name) { void append_after(std::string_view other) {
// value_ += NAME_DELIMITER + name; value += std::format("{}{}", kNameDelimiter, other);
// } }
// void append_after( void append_after(
// const Identifier &identifier, const Identifier &other,
// std::source_location location = std::source_location::current()) { std::source_location source_location = std::source_location::current()) {
// error_handling::expect(identifier.type_ == type_, ::utils::Assert(other.kind == kind,
// "different Identifier types on append_after", "different Identifier types on append_after",
// location); source_location);
// value_ += NAME_DELIMITER + *identifier.get(); value += std::format("{}{}", kNameDelimiter, other.value);
// } }
// std::vector<Identifier> get_fragments() const { std::vector<Identifier> get_fragments() const {
// std::vector<Identifier> fragments; std::vector<Identifier> fragments;
// for (auto &&fragment_name : for (auto &&fragment_name :
// std::ranges::views::split(value_, NAME_DELIMITER)) { std::ranges::views::split(value, kNameDelimiter)) {
// fragments.emplace_back( fragments.push_back({
// *this, type_, .kind = kind,
// std::string(fragment_name.begin(), fragment_name.end())); .value = std::string(fragment_name.begin(), fragment_name.end()),
// } });
// return fragments; }
// } return fragments;
}
// std::pair<Identifier, Identifier> split_first() { std::pair<Identifier, Identifier> split_first() {
// const auto pos = value_.find(NAME_DELIMITER); const auto pos = value.find(kNameDelimiter);
// if (pos == std::string::npos) { if (pos == std::string::npos) {
// return {Identifier(*this, type_, ""), *this}; return {Identifier{.kind = kind, .value = {}}, *this};
// } }
// return { return {Identifier{.kind = kind, .value = value.substr(0, pos)},
// Identifier(*this, type_, value_.substr(0, pos)), Identifier{.kind = kind,
// Identifier(*this, type_, value_.substr(pos + 1))}; // '.' is leaved .value = value.substr(pos + 1)}}; // '.' is leaved
// out }
// }
}; };
struct Extra { struct Extra {

View file

@ -197,7 +197,8 @@ class ExprData {
public: public:
using Type = std::variant< using Type = std::variant<
// --- flow control // --- flow control
Match, Condition, Loop, // TODO: separate Case from Match
Match, Match::Case, Condition, Loop,
// --- operators // --- operators
// CommaExpression is OperatorExpression for operator ',' // CommaExpression is OperatorExpression for operator ','

View file

@ -7,9 +7,12 @@ namespace nodes {
template <typename... Mixins> class Node_; template <typename... Mixins> class Node_;
// TODO FIXME: always require is_scoped parameter
struct NodeData { struct NodeData {
public: 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() { template <typename T> std::optional<T *> get() {
if (std::holds_alternative<T>(value)) { if (std::holds_alternative<T>(value)) {
@ -31,6 +34,7 @@ public:
public: public:
nodes::ExprData::Type value; nodes::ExprData::Type value;
bool is_scoped;
}; };
class NodeStorage : public core::Storage<NodeData> { class NodeStorage : public core::Storage<NodeData> {
@ -79,8 +83,14 @@ public:
// //
template <typename T> T &part() { return NodePart<T>::data_[id_]; } 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> 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_; } Id id() const { return id_; }

View file

@ -38,170 +38,109 @@ struct Constraint {
}; };
struct FunctionDefinition { struct FunctionDefinition {
class Argument { struct Argument {
public: public:
Argument(const std::optional<std::string> &annotation, Identifier &&name, Argument(const std::optional<std::string> &annotation, Identifier &&name,
Modifier before_modifier = Modifier::NONE, Modifier before_modifier = Modifier::NONE,
Modifier after_modifier = Modifier::NONE) Modifier after_modifier = Modifier::NONE)
: annotation_(annotation), name_(std::move(name)), : annotation(annotation), name(std::move(name)),
before_modifier_(before_modifier), after_modifier_(after_modifier) {} before_modifier(before_modifier), after_modifier(after_modifier) {}
Argument(const std::optional<std::string> &annotation, Argument(const std::optional<std::string> &annotation,
const Identifier &name, Modifier before_modifier = Modifier::NONE, const Identifier &name, Modifier before_modifier = Modifier::NONE,
Modifier after_modifier = Modifier::NONE) Modifier after_modifier = Modifier::NONE)
: annotation_(annotation), name_(name), : annotation(annotation), name(name), before_modifier(before_modifier),
before_modifier_(before_modifier), after_modifier_(after_modifier) {} after_modifier(after_modifier) {}
Argument(const std::optional<std::string> &annotation, Type type, Argument(const std::optional<std::string> &annotation, Type type,
Modifier before_modifier = Modifier::NONE) Modifier before_modifier = Modifier::NONE)
: annotation_(annotation), type_(type), : annotation(annotation), type(type), before_modifier(before_modifier),
before_modifier_(before_modifier), after_modifier(
after_modifier_(
builtin::types::get_modifier(type.get()->to_builtin())) {} builtin::types::get_modifier(type.get()->to_builtin())) {}
// //
// add type with same annotation and same before_modifier // add type with same annotation and same before_modifier
bool update_type_from(const Argument &other) { 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; return false;
} }
if (annotation_.has_value() && if (annotation.has_value() &&
(!other.annotation_.has_value() || (!other.annotation.has_value() ||
annotation_.value() != other.annotation_.value())) { annotation.value() != other.annotation.value())) {
return false; return false;
} }
if (before_modifier_ != other.before_modifier_) { if (before_modifier != other.before_modifier) {
return false; return false;
} }
if (after_modifier_ != other.after_modifier_) { if (after_modifier != other.after_modifier) {
return false; return false;
} }
annotation_ = other.annotation_; annotation = other.annotation;
type_ = other.type_; type = other.type;
before_modifier_ = other.before_modifier_; before_modifier = other.before_modifier;
after_modifier_ = other.after_modifier_; after_modifier = other.after_modifier;
return true; return true;
} }
// check, that argument modifiers are none or same to different from type // check, that argument modifiers are none or same to different from type
// modifiers // modifiers
bool add_type(const std::optional<std::string> &annotation, Type type, bool add_type(const std::optional<std::string> &new_annotation,
nodes::Modifier before_modifier = Modifier::NONE) { Type new_type,
if (type_.has_value()) { nodes::Modifier new_before_modifier = Modifier::NONE) {
if (type.has_value()) {
return false; return false;
} }
if (annotation_.has_value() && if (annotation.has_value() &&
(!annotation.has_value() || (!new_annotation.has_value() ||
annotation_.value() != annotation.value())) { annotation.value() != new_annotation.value())) {
return false; return false;
} }
if (before_modifier_ != Modifier::NONE && if (before_modifier != Modifier::NONE &&
before_modifier_ != before_modifier) { before_modifier != new_before_modifier) {
return false; return false;
} }
auto type_after_modifier = 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 && if (after_modifier != Modifier::NONE &&
after_modifier_ != type_after_modifier) { after_modifier != type_after_modifier) {
return false; return false;
} }
annotation_ = annotation; annotation = new_annotation;
type_ = type; type = new_type;
before_modifier_ = before_modifier; before_modifier = new_before_modifier;
after_modifier_ = type_after_modifier; after_modifier = type_after_modifier;
return true; return true;
} }
bool add_annotation(const std::string &annotation) { bool add_annotation(const std::string &new_annotation) {
if (annotation_.has_value()) { if (annotation.has_value()) {
return false; return false;
} }
annotation_ = annotation; annotation = new_annotation;
return true; return true;
} }
// public:
std::optional<std::string> annotation;
std::optional<std::string *> get_annotation() { std::optional<Identifier> name; // no name for output args
if (annotation_.has_value()) { std::optional<Type> type; // no type if it is deduced
return &annotation_.value(); Modifier before_modifier =
}
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_ =
Modifier::NONE; // in, out, ref, none // sync with type Modifier::NONE; // in, out, ref, none // sync with type
Modifier after_modifier_ = Modifier after_modifier =
Modifier::NONE; // optional, result, none // sync with type Modifier::NONE; // optional, result, none // sync with type
}; };
@ -267,15 +206,15 @@ public:
// //
template <typename T> std::optional<T *> get() { template <typename T> std::optional<T *> get() {
if (std::holds_alternative<T>(expr)) { if (std::holds_alternative<T>(value)) {
return &std::get<T>(expr); return &std::get<T>(value);
} }
return std::nullopt; return std::nullopt;
} }
template <typename T> std::optional<const T *> get() const { template <typename T> std::optional<const T *> get() const {
if (std::holds_alternative<T>(expr)) { if (std::holds_alternative<T>(value)) {
return &std::get<T>(expr); return &std::get<T>(value);
} }
return std::nullopt; return std::nullopt;
} }
@ -286,7 +225,7 @@ public:
// //
Type expr; Type value;
}; };
} // namespace nodes } // namespace nodes

View file

@ -1,7 +1,5 @@
#include "statement_nodes.hpp" #include "statement_nodes.hpp"
// #include "error_handling.hpp"
#include "error_handling.hpp"
#include "utils.hpp" #include "utils.hpp"
#include <algorithm> #include <algorithm>
@ -62,55 +60,50 @@ CombineResult FunctionDefinition::combine(FunctionDefinition &&other) {
if (i < args.size() && i < other.args.size()) { if (i < args.size() && i < other.args.size()) {
// annotations should be the same // annotations should be the same
if ((!args[i].get_annotation().has_value() && if ((!args[i].annotation.has_value() &&
!other.args[i].get_annotation().has_value()) || !other.args[i].annotation.has_value()) ||
(args[i].get_annotation().has_value() && (args[i].annotation.has_value() &&
other.args[i].get_annotation().has_value() && other.args[i].annotation.has_value() &&
*args[i].get_annotation().value() != args[i].annotation.value() != other.args[i].annotation.value())) {
*other.args[i].get_annotation().value())) {
return CombineResult::ARGUMENTS_ERROR; return CombineResult::ARGUMENTS_ERROR;
} }
// argument names should be the same // argument names should be the same
if ((!args[i].get_name().has_value() && if ((!args[i].name.has_value() && !other.args[i].name.has_value()) ||
!other.args[i].get_name().has_value()) || (args[i].name.has_value() && other.args[i].name.has_value() &&
(args[i].get_name().has_value() && args[i].name.value() != other.args[i].name.value())) {
other.args[i].get_name().has_value() &&
args[i].get_name().value() != other.args[i].get_name().value())) {
return CombineResult::ARGUMENTS_ERROR; return CombineResult::ARGUMENTS_ERROR;
} }
// types should be the same (if present in both definitions) // types should be the same (if present in both definitions)
if (args[i].get_type().has_value() && if (args[i].type.has_value() && other.args[i].type.has_value() &&
other.args[i].get_type().has_value() && args[i].type.value() != other.args[i].type.value()) {
*args[i].get_type().value() != *other.args[i].get_type().value()) {
return CombineResult::ARGUMENTS_ERROR; return CombineResult::ARGUMENTS_ERROR;
} }
// argument modifiers should be the same // argument modifiers should be the same
if (args[i].get_before_modifier() != if (args[i].before_modifier != other.args[i].before_modifier ||
other.args[i].get_before_modifier() || args[i].after_modifier != other.args[i].after_modifier) {
args[i].get_after_modifier() != other.args[i].get_after_modifier()) {
return CombineResult::ARGUMENTS_ERROR; return CombineResult::ARGUMENTS_ERROR;
} }
} else if (i < args.size()) { } else if (i < args.size()) {
// annotations should be the same // annotations should be the same
if (args[i].get_annotation().has_value()) { if (args[i].annotation.has_value()) {
return CombineResult::ARGUMENTS_ERROR; return CombineResult::ARGUMENTS_ERROR;
} }
// names should be the same // names should be the same
if (args[i].get_name().has_value()) { if (args[i].name.has_value()) {
return CombineResult::ARGUMENTS_ERROR; return CombineResult::ARGUMENTS_ERROR;
} }
} else { // i < other_function_definition.size() } else { // i < other_function_definition.size()
// annotations should be the same // annotations should be the same
if (other.args[i].get_annotation().has_value()) { if (other.args[i].annotation.has_value()) {
return CombineResult::ARGUMENTS_ERROR; return CombineResult::ARGUMENTS_ERROR;
} }
// names should be the same // names should be the same
if (other.args[i].get_name().has_value()) { if (other.args[i].name.has_value()) {
return CombineResult::ARGUMENTS_ERROR; return CombineResult::ARGUMENTS_ERROR;
} }
} }
@ -138,13 +131,11 @@ CombineResult FunctionDefinition::combine(FunctionDefinition &&other) {
for (size_t i = 0; i < other.args.size(); ++i) { for (size_t i = 0; i < other.args.size(); ++i) {
if (i < args.size()) { if (i < args.size()) {
if (other.args[i].get_type().has_value()) { if (other.args[i].type.has_value()) {
if (args[i].update_type_from(other.args[i])) { ::utils::Assert(
error_handling::handle_internal_error( not args[i].update_type_from(other.args[i]),
"Function arguments are not properly checked before merging " "Function arguments are not properly checked before merging "
"during combination", "during combination"); // TODO: proper log error
*this);
}
} }
} else { } else {
args.push_back(std::move(other.args[i])); 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 { bool Statement::is_same_to(const Statement &other) const {
if (expr.index() != other.expr.index()) { if (value.index() != other.value.index()) {
return false; return false;
} }
switch (expr.index()) { switch (value.index()) {
case 0: // Import case 0: // Import
return false; return false;
case 1: // TypeDefinition case 1: // TypeDefinition
return std::get<TypeDefinition>(expr).is_same_to( return std::get<TypeDefinition>(value).is_same_to(
std::move(std::get<TypeDefinition>(other.expr))); std::move(std::get<TypeDefinition>(other.value)));
case 2: // FunctionDefinition case 2: // FunctionDefinition
return std::get<FunctionDefinition>(expr).is_same_to( return std::get<FunctionDefinition>(value).is_same_to(
std::move(std::get<FunctionDefinition>(other.expr))); std::move(std::get<FunctionDefinition>(other.value)));
case 3: // Extra case 3: // Extra
return false; return false;
case 4: // EmptyLines case 4: // EmptyLines
@ -259,30 +250,31 @@ bool Statement::is_same_to(const Statement &other) const {
} }
CombineResult Statement::combine(Statement &&other) { CombineResult Statement::combine(Statement &&other) {
if (expr.index() != other.expr.index()) { if (value.index() != other.value.index()) {
return CombineResult::DIFFERENT_STATEMENT_TYPES; return CombineResult::DIFFERENT_STATEMENT_TYPES;
} }
switch (expr.index()) { switch (value.index()) {
case 0: // Import case 0: // Import
return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR; return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR;
case 1: // TypeDefinition case 1: // TypeDefinition
return std::get<TypeDefinition>(expr).combine( return std::get<TypeDefinition>(value).combine(
std::move(std::get<TypeDefinition>(other.expr))); std::move(std::get<TypeDefinition>(other.value)));
case 2: // FunctionDefinition case 2: // FunctionDefinition
return std::get<FunctionDefinition>(expr).combine( return std::get<FunctionDefinition>(value).combine(
std::move(std::get<FunctionDefinition>(other.expr))); std::move(std::get<FunctionDefinition>(other.value)));
case 3: // Extra case 3: // Extra
return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR; return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR;
case 4: // EmptyLines case 4: // EmptyLines
return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR; return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR;
default: default:
error_handling::handle_general_error( ::utils::Assert(
"Unexpected statement type in combine"); false,
"Unexpected statement type in combine"); // TODO: log context
break; break;
} }
error_handling::handle_general_error("Unreachable"); ::utils::Assert(false, "Unreachable"); // TODO: log context
exit(1); exit(1);
} }

View file

@ -1,147 +1,79 @@
#pragma once #pragma once
#include "basic_nodes.hpp" #include "basic_nodes.hpp"
#include <iostream> #include "printers_utils.hpp"
namespace printers { namespace printers {
class Printer { // void print(const nodes::Modifier &modifier, Printer &printer,
public: // bool const_is_none = false);
Printer(std::ostream &output, size_t tab_width, size_t width_limit, template <>
bool print_words_instead_of_symbols) struct PrintTask<nodes::Modifier> : public PrintTaskBase<nodes::Modifier> {
: output_(output), tab_width_(tab_width), width_limit_(width_limit), using PrintTaskBase<nodes::Modifier>::PrintTaskBase;
print_words_instead_of_symbols_(print_words_instead_of_symbols),
current_position_(0), indentation_level_(0) {}
void print_converted(const std::string &value) { Result operator()(const nodes::Modifier &modifier, const Args &args) override;
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;
}; };
void print(const nodes::Modifier &modifier, Printer &printer, // void print(const nodes::Literal &literal, Printer &printer);
bool const_is_none = false); 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> template <typename T>
inline void print(const std::vector<T> &nodes, Printer &printer) { struct PrintTask<std::vector<T>> : public PrintTaskBase<std::vector<T>> {
for (const auto &node : nodes) { using PrintTaskBase<std::vector<T>>::PrintTaskBase;
print(node, printer);
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 } // namespace printers

View file

@ -5,6 +5,11 @@
namespace printers { 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 } // namespace printers

View file

@ -1,44 +1,129 @@
#pragma once #pragma once
#include "basic_printers.hpp"
#include "expression_nodes.hpp" #include "expression_nodes.hpp"
#include "printers_utils.hpp"
namespace printers { 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 // --- 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 // --- 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 // --- 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, template <>
printers::Printer &printer); 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 // --- 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 } // namespace printers

View 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

View file

@ -1,23 +1,52 @@
#pragma once #pragma once
#include "basic_printers.hpp" #include "printers_utils.hpp"
#include "statement_nodes.hpp" #include "statement_nodes.hpp"
#include <vector>
namespace printers { namespace printers {
// void print_source_file(const std::vector<nodes::Statement> &statements, // void print_source_file(const std::vector<nodes::Statement> &statements,
// Printer &printer); // 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 } // namespace printers

View file

@ -5,7 +5,18 @@
namespace printers { 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 // void print_tuple_type(const nodes::TupleType &type, printers::Printer
// &printer); // &printer);

View file

@ -7,157 +7,161 @@
namespace printers { namespace printers {
void print(const nodes::Modifier &modifier, Printer &printer, Result PrintTask<nodes::Modifier>::operator()(const nodes::Modifier &modifier,
bool const_is_none) { const Args &args) {
switch (modifier) { switch (modifier) {
case nodes::Modifier::IN: case nodes::Modifier::IN:
printer.print(printer.print_words_instead_of_symbols() ? "in " : "<- "); Print(words_instead_of_symbols() ? "in " : "<- ");
break; break;
case nodes::Modifier::REF: case nodes::Modifier::REF:
printer.print(printer.print_words_instead_of_symbols() ? "ref " : "<> "); Print(words_instead_of_symbols() ? "ref " : "<> ");
break; break;
case nodes::Modifier::CONST: case nodes::Modifier::CONST:
if (!const_is_none) { if (!args.const_is_none) {
printer.print(printer.print_words_instead_of_symbols() ? "ref " : "<> "); Print(words_instead_of_symbols() ? "ref " : "<> ");
} }
break; break;
case nodes::Modifier::OUT: case nodes::Modifier::OUT:
printer.print(printer.print_words_instead_of_symbols() ? "out " : "-> "); Print(words_instead_of_symbols() ? "out " : "-> ");
break; break;
// --- // ---
case nodes::Modifier::IN_OR_REF: case nodes::Modifier::IN_OR_REF:
printer.print(printer.print_words_instead_of_symbols() ? "in|ref " Print(words_instead_of_symbols() ? "in|ref " : "<-|<> ");
: "<-|<> ");
break; break;
case nodes::Modifier::IN_OR_CONST: case nodes::Modifier::IN_OR_CONST:
printer.print(printer.print_words_instead_of_symbols() ? "in|const " Print(words_instead_of_symbols() ? "in|const " : "<-|-- ");
: "<-|-- ");
break; break;
case nodes::Modifier::REF_OR_OUT: case nodes::Modifier::REF_OR_OUT:
printer.print(printer.print_words_instead_of_symbols() ? "ref|out " Print(words_instead_of_symbols() ? "ref|out " : "<>|-> ");
: "<>|-> ");
break; break;
case nodes::Modifier::CONST_OR_OUT: case nodes::Modifier::CONST_OR_OUT:
printer.print(printer.print_words_instead_of_symbols() ? "const|out " Print(words_instead_of_symbols() ? "const|out " : "--|-> ");
: "--|-> ");
break; break;
case nodes::Modifier::REF_OR_CONST: case nodes::Modifier::REF_OR_CONST:
printer.print(printer.print_words_instead_of_symbols() ? "ref|const " Print(words_instead_of_symbols() ? "ref|const " : "<>|-- ");
: "<>|-- ");
break; break;
case nodes::Modifier::IN_OR_OUT: case nodes::Modifier::IN_OR_OUT:
printer.print(printer.print_words_instead_of_symbols() ? "in|out " Print(words_instead_of_symbols() ? "in|out " : "<-|-> ");
: "<-|-> ");
break; break;
// --- // ---
case nodes::Modifier::IN_OR_REF_OR_OUT: 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; break;
case nodes::Modifier::IN_OR_CONST_OR_OUT: 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; break;
case nodes::Modifier::IN_OR_REF_OR_CONST: 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; break;
case nodes::Modifier::REF_OR_CONST_OR_OUT: 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; break;
// --- // ---
case nodes::Modifier::IN_OR_REF_OR_CONST_OR_OUT: 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; break;
// //
case nodes::Modifier::OPTIONAL: case nodes::Modifier::OPTIONAL:
printer.print("?"); Print("?");
break; break;
case nodes::Modifier::RESULT: case nodes::Modifier::RESULT:
printer.print("!"); Print("!");
break; break;
case nodes::Modifier::NONE: case nodes::Modifier::NONE:
break; break;
default: default:
break; break;
} }
return {};
} }
void print(const nodes::Literal &literal, Printer &printer) { Result PrintTask<nodes::Literal>::operator()(const nodes::Literal &literal,
switch (literal.get_any().index()) { const Args &) {
switch (literal.value.index()) {
case 0: // float case 0: // float
printer.print(std::to_string(*literal.get<float>().value())); Print(std::to_string(*literal.get<float>().value()));
return; return {};
case 1: // double case 1: // double
printer.print(std::to_string(*literal.get<double>().value())); Print(std::to_string(*literal.get<double>().value()));
return; break;
case 2: // int32_t case 2: // int32_t
printer.print(std::to_string(*literal.get<int32_t>().value())); Print(std::to_string(*literal.get<int32_t>().value()));
return; break;
case 3: // int64_t case 3: // int64_t
printer.print(std::to_string(*literal.get<int64_t>().value())); Print(std::to_string(*literal.get<int64_t>().value()));
return; break;
case 4: // size_t case 4: // size_t
printer.print(std::to_string(*literal.get<size_t>().value())); Print(std::to_string(*literal.get<size_t>().value()));
return; break;
case 5: // std::string case 5: // std::string
printer.print("\""); Print("\"");
printer.print_converted( PrintConverted(*literal.get<std::string>()
*literal.get<std::string>() .value()); // special symbols are converted inside
.value()); // special symbols are converted inside Print("\"");
printer.print("\""); break;
return;
case 6: // unicode_string case 6: // unicode_string
printer.print("\""); Print("\"");
printer.print_converted(literal.get<nodes::unicode_string>() PrintConverted(literal.get<nodes::unicode_string>()
.value() .value()
->str); // special symbols are converted inside ->str); // special symbols are converted inside
printer.print("\"u"); Print("\"u");
return; break;
case 7: // char case 7: // char
printer.print("\'\'"); Print("\'\'");
printer.print_converted(std::string(1, *literal.get<char>().value())); PrintConverted(std::string(1, *literal.get<char>().value()));
printer.print("\'\'"); Print("\'\'");
return; break;
case 8: // unicode case 8: // unicode
printer.print("\'\'"); Print("\'\'");
printer.print_converted(literal.get<nodes::unicode>().value()->ch); PrintConverted(literal.get<nodes::unicode>().value()->ch);
printer.print("\'\'u"); Print("\'\'u");
return; break;
case 9: // bool case 9: // bool
printer.print(*literal.get<bool>().value() ? "true" : "false"); Print(*literal.get<bool>().value() ? "true" : "false");
return; break;
case 10: // unit case 10: // unit
printer.print("()"); Print("()");
return; break;
case 11: // null case 11: // null
printer.print("null"); Print("null");
return; break;
default:
error_handling::handle_general_error("Unreachable");
exit(1); // unreachable
break;
} }
error_handling::handle_general_error("Unreachable"); return {};
exit(1); // unreachable
} }
void print(const nodes::Identifier &identifier, Printer &printer) { Result
printer.print(*identifier.get()); PrintTask<nodes::Identifier>::operator()(const nodes::Identifier &identifier,
const Args &) {
Print(identifier.value);
return {};
} }
void print_annotation(const std::string &annotation, Printer &printer) { Result
printer.print("@"); PrintTask<nodes::Annotation>::operator()(const nodes::Annotation &annotation,
printer.print(annotation); const Args &) {
Print("@");
Print(annotation.value);
return {};
} }
void print(const nodes::Extra &extra, Printer &printer) { Result PrintTask<nodes::Extra>::operator()(const nodes::Extra &extra,
printer.print(*extra.content()); const Args &) {
Print(extra.content);
return {};
} }
void print(const nodes::EmptyLines &empty_lines, Printer &printer) { Result
for (size_t i = 0; i < empty_lines.line_count(); ++i) { PrintTask<nodes::EmptyLines>::operator()(const nodes::EmptyLines &empty_lines,
printer.new_indent_line(); const Args &) {
for (size_t i = 0; i < empty_lines.count; ++i) {
NewIndentLine();
} }
return {};
} }
} // namespace printers } // namespace printers

View file

@ -6,29 +6,31 @@ namespace printers {
// TODO // 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(); auto description = docs.get_description();
if (description.has_value()) { if (description.has_value()) {
printer.print(": "); Print(": ");
for (auto &ch : *description.value()) { for (auto &ch : *description.value()) {
if (ch == '\n') { if (ch == '\n') {
printer.new_indent_line(); NewIndentLine();
printer.print(": "); Print(": ");
} else { } 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) { for (size_t i = 0; i < docs.annotations_info_size(); ++i) {
print_annotation(*docs.get_annotation(i), printer); Run(nodes::Annotation{*docs.get_annotation(i)});
printer.space(); Space();
printer.print(*docs.get_annotation_info(i)); Print(*docs.get_annotation_info(i));
printer.new_indent_line(); NewIndentLine();
} }
return {};
} // IN PROGRESS } // IN PROGRESS
} // namespace printers } // namespace printers

View file

@ -5,375 +5,417 @@
#include "type_printers.hpp" #include "type_printers.hpp"
#include "utils.hpp" #include "utils.hpp"
// TODO Run, get for Ids
namespace printers { namespace printers {
namespace utils { namespace utils {
bool is_block_expression(const nodes::ExprData &expression) { bool is_block_expression(const Node &expr) {
return expression.get<nodes::Container>().has_value() && return expr.Holds<nodes::Container>() &&
expression.get<nodes::Container>().value()->get_type() == expr.get<nodes::Container>().kind == nodes::Container::BLOCK;
nodes::Container::BLOCK;
} }
} // namespace utils } // namespace utils
void print(const nodes::ExprData &expression, printers::Printer &printer) { Result PrintTask<nodes::NodeId>::operator()(const nodes::NodeId &expr,
if (expression.is_scoped()) { const Args &args) {
printer.print("("); 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); }, std::visit([this, &args](const auto &expr) -> void { Run(expr, args); },
expression.get_any()); expr.value);
if (expression.is_scoped()) { if (expr.is_scoped) {
printer.print(")"); Print(")");
} }
return {};
} }
// --- flow control // --- 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: case nodes::Match::Case::PATTERN_VALUE:
printer.print(":="); Print(":=");
break; break;
case nodes::Match::Case::VALUE_PATTERN: case nodes::Match::Case::VALUE_PATTERN:
printer.print("=:"); Print("=:");
break; break;
} }
printer.space(); Space();
print(*expression.get_value(), printer); Run(expr.value);
if (expression.get_condition().has_value()) { if (expr.condition.has_value()) {
printer.print(printer.print_words_instead_of_symbols() ? " if " : " ?? "); Print(words_instead_of_symbols() ? " if " : " ?? ");
print(*expression.get_condition().value(), printer); Run(expr.condition.value());
} }
if (expression.get_expression().has_value()) { if (expr.expr.has_value()) {
printer.print(printer.print_words_instead_of_symbols() ? " do " : " => "); Print(words_instead_of_symbols() ? " do " : " => ");
print(*expression.get_expression().value(), printer); Run(expr.expr.value());
} }
return {};
} // IN PROGRESS } // IN PROGRESS
void print(const nodes::Match &expression, printers::Printer &printer) { Result PrintTask<nodes::Match>::operator()(const nodes::Match &expr,
print(*expression.get_value(), printer); 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) { for (size_t i = 0; i < expr.cases.size(); ++i) {
print(*expression.get_case(i), printer); Run(expr.cases.at(i));
if (i + 1 < expression.cases_size()) { if (i + 1 < expr.cases.size()) {
printer.new_indent_line(); NewIndentLine();
} }
} }
printer.set_indentation_level(previous_indentation_level); SetIndentationLevel(previous_indentation_level);
return {};
} // IN PROGRESS } // 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 (i > 0) {
if (utils::is_block_expression(*expression.get_case(i - 1).second)) { if (utils::is_block_expression(
printer.space(); Ext(expr.cases.at(i - 1).second))) { // TODO
Space();
} else { } else {
printer.new_indent_line(); NewIndentLine();
} }
} }
if (i == 0) { if (i == 0) {
printer.print(printer.print_words_instead_of_symbols() ? "if " : "?? "); Print(words_instead_of_symbols() ? "if " : "?? ");
} else { } 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( error_handling::handle_general_error(
"Condition with zero cases"); // TODO ?? "Condition with zero cases"); // TODO ??
} }
if (expression.get_else_case().has_value()) { if (expr.else_case.has_value()) {
if (utils::is_block_expression( if (utils::is_block_expression(
*expression.get_case(expression.cases_size() - 1).second)) { Ext(expr.cases.at(expr.cases.size() - 1).second))) {
printer.space(); Space();
} else { } else {
printer.new_indent_line(); NewIndentLine();
} }
printer.print(printer.print_words_instead_of_symbols() ? "else " : "!!=> "); Print(words_instead_of_symbols() ? "else " : "!!=> ");
print(*expression.get_else_case().value(), printer); Run(expr.else_case.value());
} }
return {};
} }
void print(const nodes::Loop &expression, printers::Printer &printer) { Result PrintTask<nodes::Loop>::operator()(const nodes::Loop &expr,
printer.print(printer.print_words_instead_of_symbols() ? "for" : "@"); const Args &) {
Print(words_instead_of_symbols() ? "for" : "@");
switch (expression.get_type()) { switch (expr.kind) {
case nodes::Loop::LOOP: case nodes::Loop::LOOP:
printer.space(); Space();
break; break;
case nodes::Loop::WHILE: case nodes::Loop::WHILE:
printer.space(); Space();
print(*expression.get_condition().value(), printer); Run(expr.condition.value());
printer.space(); Space();
break; break;
case nodes::Loop::FOR: case nodes::Loop::FOR:
printer.space(); Space();
print(*expression.get_variable().value(), printer); Run(expr.variable.value());
printer.print(" : "); Print(" : ");
print(*expression.get_interval().value(), printer); Run(expr.interval.value());
printer.space(); Space();
break; 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 } // IN PROGRESS
// --- containers // --- containers
void print(const nodes::Container &expression, printers::Printer &printer) { Result PrintTask<nodes::Container>::operator()(const nodes::Container &expr,
bool is_array = expression.get_type() == nodes::Container::ARRAY; const Args &) {
bool is_array = expr.kind == nodes::Container::ARRAY;
if (is_array) { if (is_array) {
printer.print("[["); Print("[[");
} else { } else {
printer.print("{"); Print("{");
printer.indent(); Indent();
} }
for (size_t i = 0; i < expression.expressions_size(); ++i) { for (size_t i = 0; i < expr.exprs.size(); ++i) {
bool is_empty_lines = bool is_empty_lines = Ext(expr.exprs.at(i)).Holds<nodes::EmptyLines>();
expression.get_expression(i)->get<nodes::EmptyLines>().has_value(); bool is_extra = Ext(expr.exprs.at(i)).Holds<nodes::Extra>();
bool is_extra =
expression.get_expression(i)->get<nodes::Extra>().has_value();
if (!is_array && !is_empty_lines) { 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 (is_array) {
if (i + 1 < expression.expressions_size()) { if (i + 1 < expr.exprs.size()) {
printer.space(); Space();
} }
} else { } else {
if (!is_empty_lines && !is_extra) { if (!is_empty_lines && !is_extra) {
printer.print(";"); Print(";");
} }
} }
} }
if (is_array) { if (is_array) {
printer.print("]]"); Print("]]");
} else { } else {
printer.deindent(); Deindent();
printer.new_indent_line(); NewIndentLine();
printer.print("}"); Print("}");
} }
return {};
} // IN PROGRESS } // IN PROGRESS
// --- modifiers // --- 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: case nodes::Return::RETURN:
printer.print("return "); Print("return ");
break; break;
case nodes::Return::BRING: case nodes::Return::BRING:
printer.print("bring "); Print("bring ");
break; break;
default: default:
break; break;
} }
print(*expression.get_expression(), printer); Run(expr.expr);
return {};
} }
void print(const nodes::NameDefinition &expression, Result
printers::Printer &printer) { PrintTask<nodes::NameDefinition>::operator()(const nodes::NameDefinition &expr,
const Args &) {
if (printer.print_words_instead_of_symbols()) { if (words_instead_of_symbols()) {
switch (expression.get_modifier()) { switch (expr.kind) {
case nodes::NameDefinition::LET: case nodes::NameDefinition::LET:
printer.print("let "); Print("let ");
break; break;
case nodes::NameDefinition::VAR: case nodes::NameDefinition::VAR:
printer.print("var "); Print("var ");
break; break;
default: default:
break; break;
} }
} else { } else {
switch (expression.get_modifier()) { switch (expr.kind) {
case nodes::NameDefinition::LET: case nodes::NameDefinition::LET:
printer.print("%"); Print("%");
break; break;
case nodes::NameDefinition::VAR: case nodes::NameDefinition::VAR:
printer.print("$"); Print("$");
break; break;
default: default:
break; break;
} }
} }
print(*expression.get_name(), printer); Run(expr.name);
return {};
} }
void print(const nodes::Access &expression, printers::Printer &printer) { Result PrintTask<nodes::Access>::operator()(const nodes::Access &expr,
print(*expression.get_value(), printer); const Args &) {
Run(expr.value);
switch (expression.get_type()) { switch (expr.kind) {
case nodes::Access::ARRAY: case nodes::Access::ARRAY:
printer.print("["); Print("[");
break; break;
case nodes::Access::TUPLE: case nodes::Access::TUPLE:
printer.print("."); Print(".");
break; break;
default: default:
break; break;
} }
print(*expression.get_index(), printer); Run(expr.index);
switch (expression.get_type()) { switch (expr.kind) {
case nodes::Access::ARRAY: case nodes::Access::ARRAY:
printer.print("]"); Print("]");
break; break;
case nodes::Access::TUPLE: case nodes::Access::TUPLE:
break; break;
default: default:
break; break;
} }
return {};
} }
void print(const nodes::LoopControl &expression, printers::Printer &printer) { Result PrintTask<nodes::LoopControl>::operator()(const nodes::LoopControl &expr,
switch (expression.get_type()) { const Args &) {
switch (expr.kind) {
case nodes::LoopControl::BREAK: case nodes::LoopControl::BREAK:
printer.print("break"); Print("break");
break; break;
case nodes::LoopControl::CONTINUE: case nodes::LoopControl::CONTINUE:
printer.print("continue"); Print("continue");
break; break;
default: default:
break; break;
} }
return {};
} }
void print(const nodes::ModifierExpression &expression, Result PrintTask<nodes::ModifierExpression>::operator()(
printers::Printer &printer) { const nodes::ModifierExpression &expr, const Args &) {
if (expression.get_modifier() != nodes::Modifier::OPTIONAL && if (expr.modifier != nodes::Modifier::OPTIONAL &&
expression.get_modifier() != nodes::Modifier::RESULT) { expr.modifier != nodes::Modifier::RESULT) {
print(expression.get_modifier(), printer); Run(expr.modifier);
} }
print(*expression.get_expression(), printer); Run(expr.expr);
if (expression.get_modifier() == nodes::Modifier::OPTIONAL || if (expr.modifier == nodes::Modifier::OPTIONAL ||
expression.get_modifier() == nodes::Modifier::RESULT) { expr.modifier == nodes::Modifier::RESULT) {
print(expression.get_modifier(), printer); Run(expr.modifier);
} }
return {};
} }
// --- other // --- other
void print(const nodes::NameExpression &expression, Result
printers::Printer &printer) { PrintTask<nodes::NameExpression>::operator()(const nodes::NameExpression &expr,
bool is_comma_operator = (*expression.get_name()->get() == ","); const Args &) {
bool is_range_operator = (*expression.get_name()->get() == ".."); bool is_comma_operator = (expr.name.value == ",");
bool is_range_operator = (expr.name.value == "..");
if (expression.is_operator_call() || expression.is_point_call()) { if (expr.is_operator_call || expr.is_point_call) {
print(*expression.get_argument_value(0), printer); Run(expr.args.at(0).second);
if (expression.is_point_call()) { if (expr.is_point_call) {
printer.print("."); Print(".");
// not comma operator and not range operator // not comma operator and not range operator
} else if (!is_comma_operator && !is_range_operator) { } else if (!is_comma_operator && !is_range_operator) {
printer.space(); Space();
} }
} else if (expression.get_prefix().has_value()) { } else if (expr.prefix.has_value()) {
print(*expression.get_prefix().value(), printer); Run(expr.prefix.value());
printer.print("."); Print(".");
} }
// //
bool operator_called_as_function = bool operator_called_as_function =
(!expression.is_operator_call() && (!expr.is_operator_call &&
expression.get_name()->get_type() == nodes::Identifier::kOperator); expr.name.kind == nodes::Identifier::kOperator);
if (operator_called_as_function) { if (operator_called_as_function) {
printer.print("( "); Print("( ");
} }
print(*expression.get_name(), printer); Run(expr.name);
if (operator_called_as_function) { if (operator_called_as_function) {
printer.print(" )"); Print(" )");
} }
// //
for (size_t i = for (size_t i = expr.is_operator_call || expr.is_point_call ? 1 : 0;
expression.is_operator_call() || expression.is_point_call() ? 1 : 0; i < expr.args.size(); ++i) {
i < expression.args_size(); ++i) { if (!expr.is_operator_call || !is_range_operator || i > 1) {
if (!expression.is_operator_call() || !is_range_operator || i > 1) { Space();
printer.space();
} }
if (expression.get_argument_annotation(i).has_value()) { if (expr.args.at(i).first.has_value()) {
print_annotation(*expression.get_argument_annotation(i).value(), printer); Run(nodes::Annotation{expr.args.at(i).first.value()});
printer.space(); Space();
} }
print(*expression.get_argument_value(i), printer); Run(expr.args.at(i).second);
} }
return {};
} // IN PROGRESS } // IN PROGRESS
void print(const nodes::Constructor &expression, printers::Printer &printer) { Result PrintTask<nodes::Constructor>::operator()(const nodes::Constructor &expr,
print(*expression.get_type(), printer); const Args &) {
Run(expr.type);
for (size_t i = 0; i < expression.args_size(); ++i) { for (size_t i = 0; i < expr.args.size(); ++i) {
printer.space(); Space();
if (expression.get_argument_annotation(i).has_value()) { if (expr.args.at(i).first.has_value()) {
print_annotation(*expression.get_argument_annotation(i).value(), printer); Run(nodes::Annotation{expr.args.at(i).first.value()});
printer.space(); Space();
} }
print(*expression.get_argument_value(i), printer); Run(expr.args.at(i).second);
} }
return {};
} // IN PROGRESS } // IN PROGRESS
void print(const nodes::Lambda &expression, printers::Printer &printer) { Result PrintTask<nodes::Lambda>::operator()(const nodes::Lambda &expr,
printer.print(printer.print_words_instead_of_symbols() ? "lambda " : "\\ "); const Args &) {
Print(words_instead_of_symbols() ? "lambda " : "\\ ");
for (size_t i = 0; i < expression.args_size(); ++i) { for (size_t i = 0; i < expr.args.size(); ++i) {
print(*expression.get_argument(i), printer); Run(expr.args.at(i));
printer.space(); 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 } // IN PROGRESS
} // namespace printers } // namespace printers

View file

@ -17,177 +17,189 @@ namespace printers {
// } // }
// } // }
void print(const nodes::Statement &statement, Printer &printer) { Result
std::visit([&printer](const auto &arg) -> void { print(arg, printer); }, PrintTask<nodes::Statement>::operator()(const nodes::Statement &statement,
statement.get_any()); const Args &) {
std::visit([this](const auto &arg) -> void { Run(arg); }, statement.value);
if (not statement.get<nodes::EmptyLines>().has_value()) { if (not statement.get<nodes::EmptyLines>().has_value()) {
printer.new_indent_line(); NewIndentLine();
} }
return {};
} }
void print(const nodes::Import &statement, Printer &printer) { Result PrintTask<nodes::Import>::operator()(const nodes::Import &statement,
printer.print(":: "); const Args &) {
Print(":: ");
print(*statement.get_import_name(), printer); Run(statement.import_name);
if (*statement.get_import_name()->get() != if (statement.import_name.value != statement.module_name.value) {
*statement.get_module_name()->get()) { Print(" = ");
printer.print(" = "); Run(statement.module_name);
print(*statement.get_module_name(), printer);
} }
if (statement.symbols_size() > 0) { if (not statement.symbols.empty()) {
printer.print(" :"); Print(" :");
for (size_t i = 0; i < statement.symbols_size(); ++i) { for (const auto &symbol : statement.symbols) {
printer.space(); Space();
bool identifier_is_operator = bool identifier_is_operator =
(statement.get_symbol(i)->get_type() == nodes::Identifier::OPERATOR); (symbol.kind == nodes::Identifier::kOperator);
if (identifier_is_operator) { if (identifier_is_operator) {
printer.print("( "); Print("( ");
} }
print(*statement.get_symbol(i), printer); Run(symbol);
if (identifier_is_operator) { if (identifier_is_operator) {
printer.print(" )"); Print(" )");
} }
} }
} }
printer.print(";"); Print(";");
return {};
} // IN PROGRESS } // IN PROGRESS
void print(const nodes::Constraint &statement, Printer &printer) { Result
printer.print("? "); PrintTask<nodes::Constraint>::operator()(const nodes::Constraint &statement,
print(*statement.get_expression(), printer); const Args &) {
printer.print(";"); Print("? ");
Run(statement.expr);
Print(";");
return {};
} }
void print(const nodes::TypeDefinition &statement, Printer &printer) { Result PrintTask<nodes::TypeDefinition>::operator()(
print(*statement.get_docs(), printer); const nodes::TypeDefinition &statement, const Args &) {
Run(statement.docs);
if (statement.is_on_heap()) { if (statement.is_on_heap) {
printer.print("<> "); Print("<> ");
} }
print(*statement.get_name(), printer); Run(statement.name);
for (size_t i = 0; i < statement.args_size(); ++i) { for (const auto &arg : statement.args) {
printer.space(); Space();
print(*statement.get_argument(i), printer); Run(arg);
} }
if (statement.get_type().has_value()) { if (statement.type.has_value()) {
printer.print(" = "); 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 } // IN PROGRESS
// TODO: do not print prefix type for names // TODO: do not print prefix type for names
void print(const nodes::FunctionDefinition &statement, Printer &printer) { Result PrintTask<nodes::FunctionDefinition>::operator()(
print(*statement.get_docs(), printer); const nodes::FunctionDefinition &statement, const Args &) {
Run(statement.docs);
for (size_t i = 0; i < statement.constraints_size(); ++i) { for (const auto &constraint : statement.constraints) {
print(*statement.get_constraint(i), printer); Run(constraint);
printer.new_indent_line(); NewIndentLine();
} }
if (statement.is_method()) { if (statement.is_method) {
printer.print("."); Print(".");
} }
bool identifier_is_operator = bool identifier_is_operator =
(statement.get_name()->get_type() == nodes::Identifier::OPERATOR); (statement.name.kind == nodes::Identifier::kOperator);
if (identifier_is_operator) { if (identifier_is_operator) {
printer.print("( "); Print("( ");
} }
print(*statement.get_name(), printer); Run(statement.name);
if (identifier_is_operator) { 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) { for (const auto &arg : statement.args) {
if (!statement.get_argument(i)->get_name().has_value()) { if (not arg.name.has_value()) {
break; break;
} }
printer.space(); Space();
// all args are typed or are untyped in the same time // 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 // print annotation
if (!statement.are_annotations_same_to_names() && if (not statement.are_annotations_same_to_names &&
statement.get_argument(i)->get_annotation().has_value()) { arg.annotation.has_value()) {
print_annotation(*statement.get_argument(i)->get_annotation().value(), Run(nodes::Annotation{arg.annotation.value()});
printer); Space();
printer.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 // 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(statement.get_argument(i)->get_after_modifier(), printer); Run(arg.after_modifier);
} }
} }
// all args are typed or are untyped in the same time // all args are typed or are untyped in the same time
if (statement.args_size() > 0 && if (not statement.args.empty() && statement.args.at(0).type.has_value()) {
statement.get_argument(0)->get_type().has_value()) {
printer.print(" :"); Print(" :");
for (size_t i = 0; i < statement.args_size(); ++i) { for (const auto &arg : statement.args) {
printer.space(); Space();
if (statement.get_argument(i)->get_annotation().has_value()) { if (arg.annotation.has_value()) {
print_annotation(*statement.get_argument(i)->get_annotation().value(), Run(nodes::Annotation{arg.annotation.value()});
printer); Space();
printer.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 = 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) { 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) { if (!expression_is_container) {
printer.set_indentation_level(previous_indentation_level); SetIndentationLevel(previous_indentation_level);
printer.print(";"); Print(";");
} }
} else { } else {
printer.print(";"); Print(";");
} }
return {};
} // IN PROGRESS } // IN PROGRESS
} // namespace printers } // namespace printers

View file

@ -5,29 +5,36 @@
namespace printers { 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 // 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()) { if (type.has_annotation()) {
print_annotation(*type.get_annotation().value(), printer); Run(nodes::Annotation{.value = *type.get_annotation().value()});
printer.space(); Space();
} }
if (type.get_modifier() != nodes::Modifier::CONST) { 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) { if (type.parameters_size() > 0) {
printer.print("["); Print("[");
for (size_t i = 0; i < type.parameters_size(); ++i) { 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()) { if (i + 1 < type.parameters_size()) {
printer.space(); Space();
} }
} }
printer.print("]"); Print("]");
} }
return {};
} }
// void print_tuple_type(const nodes::TupleType &type, // void print_tuple_type(const nodes::TupleType &type,

View file

@ -4,6 +4,7 @@
#include "expression_nodes.hpp" #include "expression_nodes.hpp"
#include "log.hpp" #include "log.hpp"
#include "name_tree.hpp" #include "name_tree.hpp"
#include "nodes_storage.hpp"
#include "type_nodes.hpp" #include "type_nodes.hpp"
#include <optional> #include <optional>
@ -82,10 +83,10 @@ public:
} }
private: private:
void enter_context(const nodes::Node &node) { void enter_context(const utils::Pos &pos) {
Log::Context logc(log_, Log::Area::kTypeCheck); 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 // TODO: argument for property is returned type should be merged
@ -134,7 +135,7 @@ private:
public: public:
class Context { class Context {
public: public:
Context(const nodes::Node &node) : node_(node) {} Context(const utils::Pos &pos) : pos_(pos) {}
// void log_typecheck_error( // void log_typecheck_error(
// const std::string &message = "Context typecheck error") { // const std::string &message = "Context typecheck error") {
@ -148,7 +149,7 @@ public:
std::unordered_map<std::string, VariableInfo> variables; std::unordered_map<std::string, VariableInfo> variables;
private: private:
const nodes::Node &node_; // TODO: use as position const utils::Pos &pos_; // TODO: use as position
}; };
private: private:
@ -159,7 +160,7 @@ private:
// //
using Exprs = nodes::ExprStorage; using Exprs = nodes::NodeStorage;
using Types = nodes::TypeStorage; using Types = nodes::TypeStorage;
using Names = names::NameTree; using Names = names::NameTree;
@ -230,10 +231,10 @@ private:
class ContextHolder { class ContextHolder {
public: public:
ContextHolder(State &state, const nodes::Node &node, ContextHolder(State &state, const utils::Pos &pos,
nodes::MaybeType *context_exit_type) nodes::MaybeType *context_exit_type)
: state_(state), context_exit_type_(context_exit_type) { : state_(state), context_exit_type_(context_exit_type) {
state.enter_context(node); state.enter_context(pos);
} }
ContextHolder(const ContextHolder &) = delete; ContextHolder(const ContextHolder &) = delete;
@ -299,46 +300,46 @@ using MaybeResult = std::optional<Result>;
// //
nodes::Type check_same_to_pass_type_in_args( 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, Executor &executor,
const std::string &message = "Different type with passed one", const std::string &message = "Different type with passed one",
bool handle_errors = true); bool handle_errors = true);
// bool check_no_pass_type_in_args( // bool check_no_pass_type_in_args(
// const Args &args, const nodes::Node &node, // const Args &args, const utils::Pos &pos,
// SourcesManager &sources_manager, // SourcesManager &sources_manager,
// const std::string &message = "Type can't be passed to this node"); // const std::string &message = "Type can't be passed to this node");
Result type_same_to_expected( 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, Executor &executor,
const std::string &message = "Different type with expected one", const std::string &message = "Different type with expected one",
bool handle_errors = true); bool handle_errors = true);
Result type_check_from_args(nodes::Type type, const Args &args, Result type_check_from_args(nodes::Type type, const Args &args,
const nodes::Node &node, Executor &executor, const utils::Pos &pos, Executor &executor,
bool handle_errors = true); bool handle_errors = true);
std::optional<const nodes::TypeDefinition *> std::optional<const nodes::TypeDefinition *>
find_type_definition(const std::string &name, const nodes::Node &node, find_type_definition(const std::string &name, const utils::Pos &pos,
Executor &executor, bool handle_errors = true); Executor &executor, bool handle_errors = true);
std::optional<const nodes::FunctionDefinition *> std::optional<const nodes::FunctionDefinition *>
find_name_definition(const std::string &name, const nodes::Node &node, find_name_definition(const std::string &name, const utils::Pos &pos,
Executor &executor, bool handle_errors = true); Executor &executor, bool handle_errors = true);
nodes::MaybeType unfold_user_defined_type(nodes::Type type, nodes::MaybeType unfold_user_defined_type(nodes::Type type,
const nodes::Node &node, const utils::Pos &pos,
Executor &executor, Executor &executor,
bool handle_errors = true); bool handle_errors = true);
nodes::MaybeType get_field_type_by_name(nodes::Type type, nodes::MaybeType get_field_type_by_name(nodes::Type type,
const std::string &field, const std::string &field,
const nodes::Node &node, const utils::Pos &pos,
Executor &executor, Executor &executor,
bool handle_errors = true); 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); Executor &executor, bool handle_error = true);
// //

View file

@ -4,7 +4,7 @@ namespace type_check {
nodes::Type get_literal_type(const nodes::Literal &literal, nodes::Type get_literal_type(const nodes::Literal &literal,
Executor &executor) { Executor &executor) {
switch (literal.get_any().index()) { switch (literal.value.index()) {
case 0: // float case 0: // float
return executor.state<Types>().primitive(builtin::Type::FLOAT); return executor.state<Types>().primitive(builtin::Type::FLOAT);
case 1: // double case 1: // double

View file

@ -7,7 +7,7 @@ namespace type_check {
// pass type -> compare types, return bool // pass type -> compare types, return bool
// no pass type -> return type // no pass type -> return type
nodes::Type check_same_to_pass_type_in_args(nodes::Type type, const Args &args, nodes::Type check_same_to_pass_type_in_args(nodes::Type type, const Args &args,
const nodes::Node & /*node*/, const utils::Pos &,
Executor &executor, Executor &executor,
const std::string &message, const std::string &message,
bool handle_errors) { 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); 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, Executor &executor, const std::string &message,
bool handle_errors) { bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck); Log::Context logc(executor.log(), Log::Area::kTypeCheck);
if (args.get_passed().has_value()) { if (args.get_passed().has_value()) {
type_check_error(message, node, executor, handle_errors); type_check_error(message, pos, executor, handle_errors);
return false; 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, 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) { const std::string &message, bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck); 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*/, 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*/) { bool /*handle_errors*/) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck); 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> template <typename T>
std::optional<const T *> std::optional<const T *>
find_statement(const std::string &name, const nodes::Node & /*node*/, find_statement(const std::string &name, const utils::Pos &, Executor &executor,
Executor &executor, const std::string &message_not_found, const std::string &message_not_found,
const std::string &message_different_statement, const std::string &message_different_statement,
bool handle_errors) { bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck); 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 *> 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) { Executor &executor, bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck); Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return find_statement<nodes::TypeDefinition>( return find_statement<nodes::TypeDefinition>(
name, node, executor, "No type definition found in name tree", name, pos, executor, "No type definition found in name tree",
"Node in name tree is not type definition", handle_errors); "Node in name tree is not type definition", handle_errors);
} }
std::optional<const nodes::FunctionDefinition *> std::optional<const nodes::FunctionDefinition *>
find_name_definition(const std::string &name, const nodes::Node &node, find_name_definition(const std::string &name, const utils::Pos &pos,
Executor &executor, bool handle_errors) { Executor &executor, bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck); Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return find_statement<nodes::FunctionDefinition>( return find_statement<nodes::FunctionDefinition>(
name, node, executor, "No name definition found in name tree", name, pos, executor, "No name definition found in name tree",
"Node in name tree is not name definition", handle_errors); "Node in name tree is not name definition", handle_errors);
} }
std::optional<nodes::Type> unfold_user_defined_type(nodes::Type type, std::optional<nodes::Type> unfold_user_defined_type(nodes::Type type,
const nodes::Node &node, const utils::Pos &pos,
Executor &executor, Executor &executor,
bool handle_errors) { bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck); Log::Context logc(executor.log(), Log::Area::kTypeCheck);
const auto maybe_type_definition = find_type_definition( const auto maybe_type_definition = find_type_definition(
*type.get()->get_name()->get(), node, executor, handle_errors); type.get()->get_name()->value, pos, executor, handle_errors);
if (!maybe_type_definition.has_value()) { if (!maybe_type_definition.has_value()) {
return std::nullopt; return std::nullopt;
} }
if (maybe_type_definition.value()->get_type().has_value()) { if (maybe_type_definition.value()->type.has_value()) {
if (handle_errors) { if (handle_errors) {
logc.Error<Log::kProc>({{std::format( logc.Error<Log::kProc>({{std::format(
"Only type declaration found for type {} (type is not defined)", "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; 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, logc.Require<Log::kProc>(type.get()->parameters_size() == 0,
{{"Unfold of generic type is not supported (yet)"}}); {{"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, std::optional<nodes::Type> get_field_type_by_name(nodes::Type type,
const std::string &field, const std::string &field,
const nodes::Node &node, const utils::Pos &pos,
Executor &executor, Executor &executor,
bool handle_errors) { bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck); 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 ?? // remove recursion ??
const auto maybe_internal_type = 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()) { if (!maybe_internal_type.has_value()) {
return std::nullopt; 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); executor, handle_errors);
} }
default: // variant, function, optional, result, error (TODO: add message 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 // 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) { Executor &executor, bool handle_error) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck); Log::Context logc(executor.log(), Log::Area::kTypeCheck);

View file

@ -3,10 +3,10 @@ includes("../nodes/xmake.lua")
set_languages("c++20") set_languages("c++20")
target("lang.type_check") -- target("lang.type_check")
set_kind("static") -- set_kind("static")
add_includedirs("include", {public = true}) -- add_includedirs("include", {public = true})
add_files("src/**.cpp") -- add_files("src/**.cpp")
add_deps("lang.utils", "lang.nodes") -- add_deps("lang.utils", "lang.nodes")
set_warnings("allextra") -- , "error") -- set_warnings("allextra") -- , "error")
set_rundir("$(projectdir)") -- set_rundir("$(projectdir)")

View file

@ -1,3 +1,5 @@
// FIXME: DEPRECATED, TO DELETE
#pragma once #pragma once
#include "basic_nodes.hpp" #include "basic_nodes.hpp"
@ -8,69 +10,69 @@
namespace error_handling { namespace error_handling {
inline void handle_internal_error( // inline void handle_internal_error(
std::string_view message, const nodes::Node &node, // std::string_view message, const nodes::Node &node,
const std::source_location &location = std::source_location::current()) { // const std::source_location &location = std::source_location::current()) {
std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at "; // std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at ";
print_position(std::cerr, node.get_start_position(), node.get_end_position()); // print_position(std::cerr, node.get_start_position(),
std::cerr << ".\n"; // node.get_end_position()); std::cerr << ".\n";
print_source_location(std::cerr, location); // print_source_location(std::cerr, location);
exit(1); // exit(1);
} // }
inline void handle_internal_error( // inline void handle_internal_error(
std::string_view message, parser::ParseTree::Node node, // std::string_view message, parser::ParseTree::Node node,
const std::source_location &location = std::source_location::current()) { // const std::source_location &location = std::source_location::current()) {
std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at "; // std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at ";
print_position(std::cerr, node.get_start_point(), node.get_end_point()); // print_position(std::cerr, node.get_start_point(), node.get_end_point());
std::cerr << ".\n"; // std::cerr << ".\n";
print_source_location(std::cerr, location); // print_source_location(std::cerr, location);
exit(1); // exit(1);
} // }
inline void handle_parsing_error( // inline void handle_parsing_error(
std::string_view message, parser::ParseTree::Node parse_node, // std::string_view message, parser::ParseTree::Node parse_node,
const std::source_location &location = std::source_location::current()) { // const std::source_location &location = std::source_location::current()) {
std::cerr << "\x1b[1;31mParsing Error:\x1b[0m " << message << " at "; // std::cerr << "\x1b[1;31mParsing Error:\x1b[0m " << message << " at ";
print_position(std::cerr, parse_node.get_start_point(), // print_position(std::cerr, parse_node.get_start_point(),
parse_node.get_end_point()); // parse_node.get_end_point());
std::cerr << ".\n"; // std::cerr << ".\n";
print_source_location(std::cerr, location); // print_source_location(std::cerr, location);
exit(1); // exit(1);
} // }
inline void handle_typecheck_error( // inline void handle_typecheck_error(
std::string_view message, nodes::Node node, // std::string_view message, nodes::Node node,
const std::source_location &location = std::source_location::current()) { // const std::source_location &location = std::source_location::current()) {
std::cerr << "\x1b[1;31mTypecheck Error:\x1b[0m " << message << " at "; // std::cerr << "\x1b[1;31mTypecheck Error:\x1b[0m " << message << " at ";
print_position(std::cerr, node.get_start_position(), node.get_end_position()); // print_position(std::cerr, node.get_start_position(),
std::cerr << ".\n"; // node.get_end_position()); std::cerr << ".\n";
print_source_location(std::cerr, location); // print_source_location(std::cerr, location);
exit(1); // exit(1);
} // }
inline void handle_runtime_error( // inline void handle_runtime_error(
std::string_view message, nodes::Node node, // std::string_view message, nodes::Node node,
const std::source_location &location = std::source_location::current()) { // const std::source_location &location = std::source_location::current()) {
std::cerr << "\x1b[1;31mRuntime Error:\x1b[0m " << message << " at "; // std::cerr << "\x1b[1;31mRuntime Error:\x1b[0m " << message << " at ";
print_position(std::cerr, node.get_start_position(), node.get_end_position()); // print_position(std::cerr, node.get_start_position(),
std::cerr << ".\n"; // node.get_end_position()); std::cerr << ".\n";
print_source_location(std::cerr, location); // print_source_location(std::cerr, location);
exit(1); // exit(1);
} // }
inline void handle_names_error( // inline void handle_names_error(
std::string_view message, nodes::Node node, // std::string_view message, nodes::Node node,
const std::source_location &location = std::source_location::current()) { // const std::source_location &location = std::source_location::current()) {
std::cerr << "\x1b[1;31mNames Error:\x1b[0m " << message << " at "; // std::cerr << "\x1b[1;31mNames Error:\x1b[0m " << message << " at ";
print_position(std::cerr, node.get_start_position(), node.get_end_position()); // print_position(std::cerr, node.get_start_position(),
std::cerr << ".\n"; // node.get_end_position()); std::cerr << ".\n";
print_source_location(std::cerr, location); // print_source_location(std::cerr, location);
exit(1); // exit(1);
} // }
template <typename T> inline void debug_print(const T &value) { // template <typename T> inline void debug_print(const T &value) {
std::cerr << "\x1b[1;33mDebug:\x1b[0m " << value << '\n'; // std::cerr << "\x1b[1;33mDebug:\x1b[0m " << value << '\n';
} // }
} // namespace error_handling } // namespace error_handling

View file

@ -87,6 +87,7 @@ public:
enum class Area { enum class Area {
kDefault, kDefault,
kBuild,
kParse, kParse,
kTypeCheck, kTypeCheck,
kIntepret, kIntepret,

View file

@ -48,8 +48,8 @@ template <typename T> class DependentStorage : public Storage<T> {
using Id = storage::Id; using Id = storage::Id;
public: public:
void ForceInsert(Id id, T &&elem) { void ForceInsert(Id id, T elem) {
utils::Assert(Storage<T>::data_.insert(id, elem).second, utils::Assert(Storage<T>::data_.insert({id, std::move(elem)}).second,
std::format("insert failed, id={}", *id)); std::format("insert failed, id={}", *id));
} }

View file

@ -33,8 +33,7 @@ func {
: example of function with optional arguments (without type annotation) : example of function with optional arguments (without type annotation)
: real type is 'A? 'A? -> 'A? : real type is 'A? 'A? -> 'A?
sum 'a? 'b? = sum 'a? 'b? =
'a & 'b =: %a? & %b? => a + b 'a & 'b =: %a => a;
=: _ => null;
: example that shows that default annotations are argument names (without ') : example that shows that default annotations are argument names (without ')