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) {
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(); }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,147 +1,79 @@
#pragma once
#include "basic_nodes.hpp"
#include <iostream>
#include "printers_utils.hpp"
namespace printers {
class Printer {
public:
Printer(std::ostream &output, size_t tab_width, size_t width_limit,
bool print_words_instead_of_symbols)
: output_(output), tab_width_(tab_width), width_limit_(width_limit),
print_words_instead_of_symbols_(print_words_instead_of_symbols),
current_position_(0), indentation_level_(0) {}
// void print(const nodes::Modifier &modifier, Printer &printer,
// bool const_is_none = false);
template <>
struct PrintTask<nodes::Modifier> : public PrintTaskBase<nodes::Modifier> {
using PrintTaskBase<nodes::Modifier>::PrintTaskBase;
void print_converted(const std::string &value) {
for (auto &ch : value) {
output_ << to_printable_symbol(ch);
current_position_ += to_printable_symbol(ch).size();
}
}
// value shouldn't contain '\n', '\t', etc.
void print(const std::string &value) {
output_ << value;
current_position_ += value.size();
}
void column_down() {
size_t current_position = current_position_;
end_line();
print_spaces(current_position);
}
void new_indent_line() {
end_line();
print_spaces(indentation_level_);
}
void new_line(size_t indentation) {
end_line();
print_spaces(indentation);
}
void to_indentation_level() {
if (indentation_level_ > current_position_) {
print_spaces(indentation_level_ - current_position_);
}
}
void indent() { indentation_level_ += tab_width_; }
void deindent() { indentation_level_ -= tab_width_; }
void tab() { print_spaces(tab_width_); }
void space() { print_spaces(1); }
size_t current_position() const { return current_position_; }
size_t width_limit() const { return width_limit_; }
size_t width_left() const {
return std::max(static_cast<int64_t>(width_limit_) -
static_cast<int64_t>(current_position_),
static_cast<int64_t>(0));
}
bool print_words_instead_of_symbols() const {
return print_words_instead_of_symbols_;
}
size_t get_current_position() const { return current_position_; }
size_t get_indentation_level() const { return indentation_level_; }
void set_indentation_level(size_t indentation_level) {
indentation_level_ = indentation_level;
}
private:
void end_line() {
output_ << "\n";
current_position_ = 0;
}
void print_spaces(size_t n) { print(std::string(n, ' ')); }
static std::string to_printable_symbol(char ch) {
switch (ch) {
case '\a':
return "\\a";
case '\b':
return "\\b";
case '\e':
return "\\e";
case '\f':
return "\\f";
case '\n':
return "\\n";
case '\r':
return "\\r";
case '\t':
return "\\t";
case '\v':
return "\\v";
case '\'':
return "\\\'";
case '\"':
return "\\\"";
// case ' ':
// return "\\s";
default:
return std::string(1, ch);
}
}
private:
std::ostream &output_;
size_t tab_width_ = 0;
size_t width_limit_ = 0;
bool print_words_instead_of_symbols_ = false;
size_t current_position_ = 0;
size_t indentation_level_ = 0;
Result operator()(const nodes::Modifier &modifier, const Args &args) override;
};
void print(const nodes::Modifier &modifier, Printer &printer,
bool const_is_none = false);
// void print(const nodes::Literal &literal, Printer &printer);
template <>
struct PrintTask<nodes::Literal> : public PrintTaskBase<nodes::Literal> {
using PrintTaskBase<nodes::Literal>::PrintTaskBase;
void print(const nodes::Literal &literal, Printer &printer);
Result operator()(const nodes::Literal &literal, const Args &args) override;
};
void print(const nodes::Identifier &identifier, Printer &printer);
// void print(const nodes::Identifier &identifier, Printer &printer);
template <>
struct PrintTask<nodes::Identifier> : public PrintTaskBase<nodes::Identifier> {
using PrintTaskBase<nodes::Identifier>::PrintTaskBase;
void print_annotation(const std::string &annotation, Printer &printer);
Result operator()(const nodes::Identifier &identifier,
const Args &args) override;
};
void print(const nodes::Extra &extra, Printer &printer);
// void print_annotation(const nodes::Annotation &annotation, Printer &printer);
template <>
struct PrintTask<nodes::Annotation> : public PrintTaskBase<nodes::Annotation> {
using PrintTaskBase<nodes::Annotation>::PrintTaskBase;
void print(const nodes::EmptyLines &empty_lines, Printer &printer);
Result operator()(const nodes::Annotation &annotation,
const Args &args) override;
};
// void print(const nodes::Extra &extra, Printer &printer);
template <>
struct PrintTask<nodes::Extra> : public PrintTaskBase<nodes::Extra> {
using PrintTaskBase<nodes::Extra>::PrintTaskBase;
Result operator()(const nodes::Extra &extra, const Args &args) override;
};
// void print(const nodes::EmptyLines &empty_lines, Printer &printer);
template <>
struct PrintTask<nodes::EmptyLines> : public PrintTaskBase<nodes::EmptyLines> {
using PrintTaskBase<nodes::EmptyLines>::PrintTaskBase;
Result operator()(const nodes::EmptyLines &empty_lines,
const Args &args) override;
};
// template <typename T>
// inline void print(const std::vector<T> &nodes, Printer &printer) {
// for (const auto &node : nodes) {
// print(node, printer);
// }
// }
template <typename T>
inline void print(const std::vector<T> &nodes, Printer &printer) {
for (const auto &node : nodes) {
print(node, printer);
struct PrintTask<std::vector<T>> : public PrintTaskBase<std::vector<T>> {
using PrintTaskBase<std::vector<T>>::PrintTaskBase;
Result operator()(const std::vector<T> &exprs, const Args &args) override {
for (const auto &expr : exprs) {
PrintTaskBase<std::vector<T>>::Run(expr, args);
}
}
return {};
}
};
} // namespace printers

View file

@ -5,6 +5,11 @@
namespace printers {
void print(const nodes::SymbolDocs &docs, Printer &printer);
template <>
struct PrintTask<nodes::SymbolDocs> : public PrintTaskBase<nodes::SymbolDocs> {
using PrintTaskBase<nodes::SymbolDocs>::PrintTaskBase;
Result operator()(const nodes::SymbolDocs &docs, const Args &args) override;
};
} // namespace printers

View file

@ -1,44 +1,129 @@
#pragma once
#include "basic_printers.hpp"
#include "expression_nodes.hpp"
#include "printers_utils.hpp"
namespace printers {
void print(const nodes::ExprData &expression, printers::Printer &printer);
template <>
struct PrintTask<nodes::NodeId> : public PrintTaskBase<nodes::NodeId> {
using PrintTaskBase<nodes::NodeId>::PrintTaskBase;
Result operator()(const nodes::NodeId &expr, const Args &args) override;
};
template <>
struct PrintTask<nodes::NodeData> : public PrintTaskBase<nodes::NodeData> {
using PrintTaskBase<nodes::NodeData>::PrintTaskBase;
Result operator()(const nodes::NodeData &expr, const Args &args) override;
};
// --- flow control
void print(const nodes::Match::Case &expression, Printer &printer);
template <>
struct PrintTask<nodes::Match::Case>
: public PrintTaskBase<nodes::Match::Case> {
using PrintTaskBase<nodes::Match::Case>::PrintTaskBase;
void print(const nodes::Match &expression, printers::Printer &printer);
Result operator()(const nodes::Match::Case &expr, const Args &args) override;
};
void print(const nodes::Condition &expression, printers::Printer &printer);
template <>
struct PrintTask<nodes::Match> : public PrintTaskBase<nodes::Match> {
using PrintTaskBase<nodes::Match>::PrintTaskBase;
void print(const nodes::Loop &expression, printers::Printer &printer);
Result operator()(const nodes::Match &expr, const Args &args) override;
};
template <>
struct PrintTask<nodes::Condition> : public PrintTaskBase<nodes::Condition> {
using PrintTaskBase<nodes::Condition>::PrintTaskBase;
Result operator()(const nodes::Condition &expr, const Args &args) override;
};
template <> struct PrintTask<nodes::Loop> : public PrintTaskBase<nodes::Loop> {
using PrintTaskBase<nodes::Loop>::PrintTaskBase;
Result operator()(const nodes::Loop &expr, const Args &args) override;
};
// --- containers
void print(const nodes::Container &expression, printers::Printer &printer);
template <>
struct PrintTask<nodes::Container> : public PrintTaskBase<nodes::Container> {
using PrintTaskBase<nodes::Container>::PrintTaskBase;
Result operator()(const nodes::Container &expr, const Args &args) override;
};
// --- modifiers
void print(const nodes::Return &expression, printers::Printer &printer);
template <>
struct PrintTask<nodes::Return> : public PrintTaskBase<nodes::Return> {
using PrintTaskBase<nodes::Return>::PrintTaskBase;
void print(const nodes::NameDefinition &expression, printers::Printer &printer);
Result operator()(const nodes::Return &expr, const Args &args) override;
};
void print(const nodes::Access &expression, printers::Printer &printer);
template <>
struct PrintTask<nodes::NameDefinition>
: public PrintTaskBase<nodes::NameDefinition> {
using PrintTaskBase<nodes::NameDefinition>::PrintTaskBase;
void print(const nodes::LoopControl &expression, printers::Printer &printer);
Result operator()(const nodes::NameDefinition &expr,
const Args &args) override;
};
void print(const nodes::ModifierExpression &expression,
printers::Printer &printer);
template <>
struct PrintTask<nodes::Access> : public PrintTaskBase<nodes::Access> {
using PrintTaskBase<nodes::Access>::PrintTaskBase;
Result operator()(const nodes::Access &expr, const Args &args) override;
};
template <>
struct PrintTask<nodes::LoopControl>
: public PrintTaskBase<nodes::LoopControl> {
using PrintTaskBase<nodes::LoopControl>::PrintTaskBase;
Result operator()(const nodes::LoopControl &expr, const Args &args) override;
};
template <>
struct PrintTask<nodes::ModifierExpression>
: public PrintTaskBase<nodes::ModifierExpression> {
using PrintTaskBase<nodes::ModifierExpression>::PrintTaskBase;
Result operator()(const nodes::ModifierExpression &expr,
const Args &args) override;
};
// --- other
void print(const nodes::NameExpression &expression, printers::Printer &printer);
template <>
struct PrintTask<nodes::NameExpression>
: public PrintTaskBase<nodes::NameExpression> {
using PrintTaskBase<nodes::NameExpression>::PrintTaskBase;
void print(const nodes::Constructor &expression, printers::Printer &printer);
Result operator()(const nodes::NameExpression &expr,
const Args &args) override;
};
void print(const nodes::Lambda &expression, printers::Printer &printer);
template <>
struct PrintTask<nodes::Constructor>
: public PrintTaskBase<nodes::Constructor> {
using PrintTaskBase<nodes::Constructor>::PrintTaskBase;
Result operator()(const nodes::Constructor &expr, const Args &args) override;
};
template <>
struct PrintTask<nodes::Lambda> : public PrintTaskBase<nodes::Lambda> {
using PrintTaskBase<nodes::Lambda>::PrintTaskBase;
Result operator()(const nodes::Lambda &expr, const Args &args) override;
};
} // namespace printers

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
#include "basic_printers.hpp"
#include "printers_utils.hpp"
#include "statement_nodes.hpp"
#include <vector>
namespace printers {
// void print_source_file(const std::vector<nodes::Statement> &statements,
// Printer &printer);
void print(const nodes::Statement &statements, Printer &printer);
template <>
struct PrintTask<nodes::Statement> : public PrintTaskBase<nodes::Statement> {
using PrintTaskBase<nodes::Statement>::PrintTaskBase;
void print(const nodes::Import &statement, Printer &printer);
Result operator()(const nodes::Statement &statement,
const Args &args) override;
};
void print(const nodes::Constraint &statement, Printer &printer);
template <>
struct PrintTask<nodes::Import> : public PrintTaskBase<nodes::Import> {
using PrintTaskBase<nodes::Import>::PrintTaskBase;
void print(const nodes::TypeDefinition &statement, Printer &printer);
Result operator()(const nodes::Import &statement, const Args &args) override;
};
void print(const nodes::FunctionDefinition &statement, Printer &printer);
template <>
struct PrintTask<nodes::Constraint> : public PrintTaskBase<nodes::Constraint> {
using PrintTaskBase<nodes::Constraint>::PrintTaskBase;
Result operator()(const nodes::Constraint &statement,
const Args &args) override;
};
template <>
struct PrintTask<nodes::TypeDefinition>
: public PrintTaskBase<nodes::TypeDefinition> {
using PrintTaskBase<nodes::TypeDefinition>::PrintTaskBase;
Result operator()(const nodes::TypeDefinition &statement,
const Args &args) override;
};
template <>
struct PrintTask<nodes::FunctionDefinition>
: public PrintTaskBase<nodes::FunctionDefinition> {
using PrintTaskBase<nodes::FunctionDefinition>::PrintTaskBase;
Result operator()(const nodes::FunctionDefinition &statement,
const Args &args) override;
};
} // namespace printers

View file

@ -5,7 +5,18 @@
namespace printers {
void print(const nodes::TypeData &type, printers::Printer &printer);
template <> struct PrintTask<nodes::Type> : public PrintTaskBase<nodes::Type> {
using PrintTaskBase<nodes::Type>::PrintTaskBase;
Result operator()(const nodes::Type &type, const Args &args) override;
};
template <>
struct PrintTask<nodes::TypeData> : public PrintTaskBase<nodes::TypeData> {
using PrintTaskBase<nodes::TypeData>::PrintTaskBase;
Result operator()(const nodes::TypeData &type, const Args &args) override;
};
// void print_tuple_type(const nodes::TupleType &type, printers::Printer
// &printer);

View file

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

View file

@ -6,29 +6,31 @@ namespace printers {
// TODO
void print(const nodes::SymbolDocs &docs, Printer &printer) {
Result PrintTask<nodes::SymbolDocs>::operator()(const nodes::SymbolDocs &docs,
const Args &) {
auto description = docs.get_description();
if (description.has_value()) {
printer.print(": ");
Print(": ");
for (auto &ch : *description.value()) {
if (ch == '\n') {
printer.new_indent_line();
printer.print(": ");
NewIndentLine();
Print(": ");
} else {
printer.print(std::string(1, ch));
Print(std::string(1, ch));
}
}
printer.new_indent_line();
NewIndentLine();
}
for (size_t i = 0; i < docs.annotations_info_size(); ++i) {
print_annotation(*docs.get_annotation(i), printer);
printer.space();
printer.print(*docs.get_annotation_info(i));
printer.new_indent_line();
Run(nodes::Annotation{*docs.get_annotation(i)});
Space();
Print(*docs.get_annotation_info(i));
NewIndentLine();
}
return {};
} // IN PROGRESS
} // namespace printers

View file

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

View file

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

View file

@ -5,29 +5,36 @@
namespace printers {
Result PrintTask<nodes::Type>::operator()(const nodes::Type &type,
const Args &args) {
return Run(*type.get(), args);
}
// TODO: better printing format for builtin types
void print(const nodes::TypeData &type, printers::Printer &printer) {
Result PrintTask<nodes::TypeData>::operator()(const nodes::TypeData &type,
const Args &) {
if (type.has_annotation()) {
print_annotation(*type.get_annotation().value(), printer);
printer.space();
Run(nodes::Annotation{.value = *type.get_annotation().value()});
Space();
}
if (type.get_modifier() != nodes::Modifier::CONST) {
print(type.get_modifier(), printer);
Run(type.get_modifier());
}
print(*type.get_name(), printer);
Run(*type.get_name());
if (type.parameters_size() > 0) {
printer.print("[");
Print("[");
for (size_t i = 0; i < type.parameters_size(); ++i) {
print(*type.get_parameter(i), printer);
Run(*type.get_parameter(i));
if (i + 1 < type.parameters_size()) {
printer.space();
Space();
}
}
printer.print("]");
Print("]");
}
return {};
}
// void print_tuple_type(const nodes::TupleType &type,

View file

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

View file

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

View file

@ -7,7 +7,7 @@ namespace type_check {
// pass type -> compare types, return bool
// no pass type -> return type
nodes::Type check_same_to_pass_type_in_args(nodes::Type type, const Args &args,
const nodes::Node & /*node*/,
const utils::Pos &,
Executor &executor,
const std::string &message,
bool handle_errors) {
@ -24,13 +24,13 @@ nodes::Type check_same_to_pass_type_in_args(nodes::Type type, const Args &args,
return executor.state<Types>().primitive(builtin::Type::BOOL);
}
bool check_no_pass_type_in_args(const Args &args, const nodes::Node &node,
bool check_no_pass_type_in_args(const Args &args, const utils::Pos &pos,
Executor &executor, const std::string &message,
bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
if (args.get_passed().has_value()) {
type_check_error(message, node, executor, handle_errors);
type_check_error(message, pos, executor, handle_errors);
return false;
}
@ -38,7 +38,7 @@ bool check_no_pass_type_in_args(const Args &args, const nodes::Node &node,
}
Result type_same_to_expected(nodes::Type type, const Args &args,
const nodes::Node & /*node*/, Executor &executor,
const utils::Pos &, Executor &executor,
const std::string &message, bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
@ -61,7 +61,7 @@ Result type_same_to_expected(nodes::Type type, const Args &args,
}
Result type_check_from_args(nodes::Type /*type*/, const Args & /*args*/,
const nodes::Node & /*node*/, Executor &executor,
const utils::Pos &, Executor &executor,
bool /*handle_errors*/) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
@ -72,8 +72,8 @@ Result type_check_from_args(nodes::Type /*type*/, const Args & /*args*/,
template <typename T>
std::optional<const T *>
find_statement(const std::string &name, const nodes::Node & /*node*/,
Executor &executor, const std::string &message_not_found,
find_statement(const std::string &name, const utils::Pos &, Executor &executor,
const std::string &message_not_found,
const std::string &message_different_statement,
bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
@ -98,43 +98,43 @@ find_statement(const std::string &name, const nodes::Node & /*node*/,
}
std::optional<const nodes::TypeDefinition *>
find_type_definition(const std::string &name, const nodes::Node &node,
find_type_definition(const std::string &name, const utils::Pos &pos,
Executor &executor, bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return find_statement<nodes::TypeDefinition>(
name, node, executor, "No type definition found in name tree",
name, pos, executor, "No type definition found in name tree",
"Node in name tree is not type definition", handle_errors);
}
std::optional<const nodes::FunctionDefinition *>
find_name_definition(const std::string &name, const nodes::Node &node,
find_name_definition(const std::string &name, const utils::Pos &pos,
Executor &executor, bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
return find_statement<nodes::FunctionDefinition>(
name, node, executor, "No name definition found in name tree",
name, pos, executor, "No name definition found in name tree",
"Node in name tree is not name definition", handle_errors);
}
std::optional<nodes::Type> unfold_user_defined_type(nodes::Type type,
const nodes::Node &node,
const utils::Pos &pos,
Executor &executor,
bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
const auto maybe_type_definition = find_type_definition(
*type.get()->get_name()->get(), node, executor, handle_errors);
type.get()->get_name()->value, pos, executor, handle_errors);
if (!maybe_type_definition.has_value()) {
return std::nullopt;
}
if (maybe_type_definition.value()->get_type().has_value()) {
if (maybe_type_definition.value()->type.has_value()) {
if (handle_errors) {
logc.Error<Log::kProc>({{std::format(
"Only type declaration found for type {} (type is not defined)",
*type.get()->get_name()->get())}} /* TODO: node*/);
type.get()->get_name()->value)}} /* TODO: node*/);
}
return std::nullopt;
}
@ -143,12 +143,12 @@ std::optional<nodes::Type> unfold_user_defined_type(nodes::Type type,
logc.Require<Log::kProc>(type.get()->parameters_size() == 0,
{{"Unfold of generic type is not supported (yet)"}});
//
return maybe_type_definition.value()->get_type().value();
return maybe_type_definition.value()->type.value();
}
std::optional<nodes::Type> get_field_type_by_name(nodes::Type type,
const std::string &field,
const nodes::Node &node,
const utils::Pos &pos,
Executor &executor,
bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
@ -170,12 +170,12 @@ std::optional<nodes::Type> get_field_type_by_name(nodes::Type type,
// remove recursion ??
const auto maybe_internal_type =
unfold_user_defined_type(type, node, executor, handle_errors);
unfold_user_defined_type(type, pos, executor, handle_errors);
if (!maybe_internal_type.has_value()) {
return std::nullopt;
}
return get_field_type_by_name(maybe_internal_type.value(), field, node,
return get_field_type_by_name(maybe_internal_type.value(), field, pos,
executor, handle_errors);
}
default: // variant, function, optional, result, error (TODO: add message
@ -192,7 +192,7 @@ std::optional<nodes::Type> get_field_type_by_name(nodes::Type type,
}
// FIXME: replace with direct log calls
void type_check_error(const std::string &message, const nodes::Node &,
void type_check_error(const std::string &message, const utils::Pos &,
Executor &executor, bool handle_error) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);

View file

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

View file

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

View file

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

View file

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

View file

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