#include #include // for clangd #include "../include/build_visitor.hpp" #include "../include/parse_token_types.hpp" #include "../include/error_handling.hpp" namespace interpreter { void SetPosition(BaseNode& base_node, parser::ParseTree::Node& parse_node) { base_node.start_position = parse_node.GetStartPoint(); base_node.end_position = parse_node.GetEndPoint(); } // Sources ----------------- void BuildVisitor::Visit(SourceFile* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t statement_count = parse_node.NamedChildCount(); node->statements.resize(statement_count); for (size_t i = 0; i < statement_count; ++i) { current_node_ = parse_node.NthNamedChild(i); Visit(node->statements[i]); } current_node_ = parse_node; } // Namespaces, partitions ----------------- void BuildVisitor::Visit(NamespaceSources* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t statement_count = parse_node.NamedChildCount(); node->statements.resize(statement_count); for (size_t i = 0; i < statement_count; ++i) { current_node_ = parse_node.NthNamedChild(i); Visit(node->statements[i]); } current_node_ = parse_node; } void BuildVisitor::Visit(Namespace* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; std::string modifier = parse_node.NthChild(1).GetValue(); if (modifier == "let") { node->modifier = utils::ClassInternalsModifier::Const; } else if (modifier == "var") { node->modifier = utils::ClassInternalsModifier::Var; } else { node->modifier = utils::ClassInternalsModifier::Static; } current_node_ = parse_node.ChildByFieldName("type"); node->type = current_node_.GetValue(); node->is_type_namespace = (current_node_.PreviousSibling().GetValue() == "\\"); current_node_ = parse_node.ChildByFieldName("scope"); Visit(&node->scope); current_node_ = parse_node; } // Definitions ----------------- void BuildVisitor::Visit(ImportStatement* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t excluded_child_count = 0; if (parse_node.NthChild(0).GetValue() == "use") { node->name = parse_node.ChildByFieldName("name").GetValue(); ++excluded_child_count; } StringLiteral module_name; current_node_ = parse_node.ChildByFieldName("module_name"); Visit(&module_name); node->module_name = module_name.value; ++excluded_child_count; size_t child_count = parse_node.NamedChildCount(); if (child_count > excluded_child_count) { node->symbols.resize(child_count - excluded_child_count); for (size_t i = 0; i < child_count - excluded_child_count; ++i) { node->symbols[i] = parse_node.NthNamedChild(i + excluded_child_count).GetValue(); } } current_node_ = parse_node; } void BuildVisitor::Visit(AliasDefinitionStatement* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; std::string modifier = parse_node.NthChild(0).GetValue(); if (modifier == "alias") { node->modifier = utils::AliasModifier::Alias; } else if (modifier == "type") { node->modifier = utils::AliasModifier::Type; } else if (modifier == "let") { node->modifier = utils::AliasModifier::Let; } node->type = parse_node.ChildByFieldName("type").GetValue(); size_t child_count = parse_node.NamedChildCount(); if (child_count > 2) { node->parameters.resize(child_count - 2); for (size_t i = 0; i + 2 < child_count; ++i) { node->parameters[i] = parse_node.NthNamedChild(i + 1).GetValue(); } } current_node_ = parse_node.ChildByFieldName("value"); node->value = std::make_unique(); Visit(node->value.get()); current_node_ = parse_node; } void BuildVisitor::Visit(VariableDefinitionStatement* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; std::string modifier = parse_node.NthChild(0).GetValue(); if (modifier == "let") { node->modifier = utils::IsConstModifier::Const; } else if (modifier == "var") { node->modifier = utils::IsConstModifier::Var; } else { // error } current_node_ = parse_node.ChildByFieldName("name"); Visit(node->name); current_node_ = parse_node.ChildByFieldName("value"); Visit(node->value); std::string assignment_modifier = parse_node.NthChild(2).GetValue(); if (assignment_modifier == "=") { node->assignment_modifier = utils::AssignmentModifier::Assign; } else if (assignment_modifier == "<-") { node->assignment_modifier = utils::AssignmentModifier::Move; } else { // error } size_t child_count = parse_node.NamedChildCount(); if (child_count > 2) { // name, value [, in_expression] current_node_ = parse_node.ChildByFieldName("in_expression"); node->in_expression.emplace(); Visit(node->in_expression.value()); } current_node_ = parse_node; } void BuildVisitor::Visit(FunctionDeclaration* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; // ['decl'] ['interface'] name if (parse_node.NthChild(0).GetValue() == "decl") { node->is_in_interface = (parse_node.NthChild(1).GetValue() == "interface"); } else { node->is_in_interface = false; } node->name = parse_node.ChildByFieldName("name").GetValue(); size_t child_count = parse_node.NamedChildCount(); if (child_count > 2) { node->parameters.resize(child_count - 2); for (size_t i = 0; i + 2 < child_count; ++i) { current_node_ = parse_node.NthNamedChild(i + 1); node->parameters[i] = std::make_unique(); Visit(node->parameters.back().get()); } } current_node_ = parse_node.ChildByFieldName("type"); node->type = std::make_unique(); Visit(node->type.get()); current_node_ = parse_node; } void BuildVisitor::Visit(FunctionDefinitionStatement* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; current_node_ = parse_node.ChildByFieldName("definition"); node->definition = std::make_unique(); Visit(node->definition.get()); current_node_ = parse_node.ChildByFieldName("value"); Visit(node->value); current_node_ = parse_node; } void BuildVisitor::Visit(TypeDefinitionStatement* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; std::string modifier = parse_node.NthChild(0).GetValue(); if (modifier == "class") { node->modifier = utils::ClassModifier::Class; } else if (modifier == "struct") { node->modifier = utils::ClassModifier::Struct; } node->is_in_interface = (parse_node.NthChild(1).GetValue() == "interface"); current_node_ = parse_node.ChildByFieldName("definition"); node->definition = std::make_unique(); Visit(node->definition.get()); current_node_ = parse_node.ChildByFieldName("value"); Visit(node->value); current_node_ = parse_node; } void BuildVisitor::Visit(AbstractTypeDefinitionStatement* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; std::string modifier = parse_node.NthChild(0).GetValue(); if (modifier == "basic") { node->modifier = utils::AbstractTypeModifier::Basic; } else if (modifier == "abstract") { node->modifier = utils::AbstractTypeModifier::Abstract; } current_node_ = parse_node.ChildByFieldName("type"); node->type = std::make_unique(); Visit(node->type.get()); current_node_ = parse_node; } void BuildVisitor::Visit(TypeclassDefinitionStatement* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; current_node_ = parse_node.ChildByFieldName("definition"); node->definition = std::make_unique(); Visit(node->definition.get()); size_t child_count = parse_node.NamedChildCount(); if (child_count > 1) { node->requirements.reserve(child_count - 1); for (size_t i = 0; i + 1 < child_count; ++i) { current_node_ = parse_node.NthNamedChild(i + 1); std::string modifier_name = current_node_.PreviousSibling().GetValue(); utils::ClassInternalsModifier modifier; if (modifier_name == "let") { modifier = utils::ClassInternalsModifier::Const; } else if (modifier_name == "var") { modifier = utils::ClassInternalsModifier::Var; } else { modifier = utils::ClassInternalsModifier::Static; } node->requirements.push_back({modifier, std::make_unique()}); Visit(node->requirements.back().second.get()); } } current_node_ = parse_node; } void BuildVisitor::Visit(PartitionStatement* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; std::string partition_modifier = parse_node.NthChild(0).GetValue(); if (partition_modifier == "exec") { node->modifier = utils::PartitionModifier::Exec; } else if (partition_modifier == "test") { node->modifier = utils::PartitionModifier::Test; } else if (partition_modifier == "example") { node->modifier = utils::PartitionModifier::Example; } else { // error } current_node_ = parse_node.ChildByFieldName("name"); Visit(&node->name); current_node_ = parse_node.ChildByFieldName("value"); Visit(node->value); current_node_ = parse_node; } // void BuildVisitor::Visit(NamespaceStatement& node) { auto parse_node = current_node_; current_node_ = parse_node.NthNamedChild(0); std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::AliasDefinitionStatement) { // optimize ?? node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::FunctionDeclaration) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::FunctionDefinitionStatement) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::TypeDefinitionStatement) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::PartitionStatement) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::Namespace) { node = std::make_unique(); Visit(std::get>(node).get()); } else { // error } current_node_ = parse_node; } void BuildVisitor::Visit(SourceStatement& node) { auto parse_node = current_node_; current_node_ = parse_node.NthNamedChild(0); std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::ImportStatement) { // optimize ?? node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::AbstractTypeDefinitionStatement) { // optimize ?? node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::TypeclassDefinitionStatement) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::NamespaceStatement) { node = std::make_unique(); Visit(*std::get>(node)); } else { // error } current_node_ = parse_node; } // Definition parts void BuildVisitor::Visit(FunctionDefinition* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; node->name = parse_node.ChildByFieldName("name").GetValue(); size_t child_count = parse_node.NamedChildCount(); if (child_count > 1) { node->arguments.resize(child_count - 1); for (size_t i = 0; i + 1 < child_count; ++i) { node->arguments[i] = parse_node.NthNamedChild(i + 1).GetValue(); } } current_node_ = parse_node; } void BuildVisitor::Visit(TypeDefinition* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; current_node_ = parse_node.ChildByFieldName("type"); node->type = std::make_unique(); Visit(node->type.get()); size_t child_count = parse_node.NamedChildCount(); if (child_count > 1) { for (size_t i = 0; i + 1 < child_count; ++i) { current_node_ = parse_node.NthNamedChild(i + 1); node->parameters.push_back(std::make_unique()); Visit(node->parameters.back().get()); } } current_node_ = parse_node; } void BuildVisitor::Visit(AnyAnnotatedType* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; node->type = parse_node.ChildByFieldName("type").GetValue(); size_t child_count = parse_node.NamedChildCount(); if (child_count > 1) { node->typeclasses.resize(child_count - 1); for (size_t i = 0; i + 1 < child_count; ++i) { current_node_ = parse_node.NthNamedChild(i + 1); node->typeclasses[i] = std::make_unique(); Visit(node->typeclasses[i].get()); } } current_node_ = parse_node; } // Flow control ----------------- void BuildVisitor::Visit(TypeConstructorPatternParameter* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t child_count = parse_node.NamedChildCount(); if (child_count > 1) { node->name.value() = parse_node.ChildByFieldName("name").GetValue(); } current_node_ = parse_node.ChildByFieldName("value"), Visit(node->value); current_node_ = parse_node; } void BuildVisitor::Visit(TypeConstructorPattern* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; current_node_ = parse_node.ChildByFieldName("constructor"); node->constructor = std::make_unique(); Visit(node->constructor.get()); size_t child_count = parse_node.NamedChildCount(); if (child_count > 1) { node->parameters.resize(child_count - 1); for (size_t i = 0; i + 1 < child_count; ++i) { current_node_ = parse_node.NthNamedChild(i + 1); Visit(&node->parameters[i]); } } current_node_ = parse_node; } void BuildVisitor::Visit(Pattern& node) { // <-> ScopedPattern auto parse_node = current_node_; current_node_ = parse_node.NthNamedChild(0); std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::NameIdentifier) { // optimize ?? node = std::make_unique(current_node_.GetValue()); // Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::Literal) { node = std::make_unique(); Visit(*std::get>(node)); } else if (current_node_type == parser::tokens::TypeConstructorPattern) { node = std::make_unique(); Visit(std::get>(node).get()); } else { // error } current_node_ = parse_node; } void BuildVisitor::Visit(MatchCase* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; current_node_ = parse_node.ChildByFieldName("value"); Visit(node->value); size_t child_count = parse_node.NamedChildCount(); if (child_count > 1) { std::string prefix = parse_node.NthChild(2).GetValue(); if (child_count > 2 || prefix == "?") { current_node_ = parse_node.ChildByFieldName("condition"); node->condition.emplace(); Visit(node->condition.value()); } if (child_count > 2 || prefix == "->") { current_node_ = parse_node.ChildByFieldName("statement"); node->statement.emplace(); Visit(node->statement.value()); } } current_node_ = parse_node; } void BuildVisitor::Visit(Match* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; node->is_consuming_value = (parse_node.NthChild(1).GetValue() == "<-"); current_node_ = parse_node.ChildByFieldName("value"); Visit(node->value); size_t child_count = parse_node.NamedChildCount(); // if (child_count > 1) { // always true (repeat1) node->matches.resize(child_count - 1); for (size_t i = 0; i + 1 < child_count; ++i) { current_node_ = parse_node.NthNamedChild(i + 1); Visit(&node->matches[i]); } // } current_node_ = parse_node; } void BuildVisitor::Visit(Condition* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t child_count = parse_node.NamedChildCount(); node->conditions.resize(child_count / 2); node->statements.resize((child_count + 1) / 2); for (size_t i = 0; i < child_count; ++i) { current_node_ = parse_node.NthNamedChild(i); if (i % 2 == 0 && i / 2 < node->conditions.size()) { Visit(node->conditions[i / 2]); } else { Visit(node->statements[i / 2]); } } current_node_ = parse_node; } void BuildVisitor::Visit(DoWhileLoop* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; current_node_ = parse_node.ChildByFieldName("statement"); Visit(node->statement); current_node_ = parse_node.ChildByFieldName("condition"); Visit(node->condition); current_node_ = parse_node; } void BuildVisitor::Visit(WhileLoop* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; current_node_ = parse_node.ChildByFieldName("condition"); Visit(node->condition); current_node_ = parse_node.ChildByFieldName("statement"); Visit(node->statement); current_node_ = parse_node; } void BuildVisitor::Visit(ForLoop* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; if (parse_node.ChildCount() < 7) { // no "var" node node->variable_modifier = utils::IsConstModifier::Const; } else { node->variable_modifier = utils::IsConstModifier::Var; } current_node_ = parse_node.ChildByFieldName("variable"); Visit(node->variable); current_node_ = parse_node.ChildByFieldName("interval"); Visit(node->interval); current_node_ = parse_node.ChildByFieldName("statement"); Visit(node->statement); current_node_ = parse_node; } void BuildVisitor::Visit(LoopLoop* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; current_node_ = parse_node.ChildByFieldName("statement"); Visit(node->statement); current_node_ = parse_node; } void BuildVisitor::Visit(FlowControl& node) { auto parse_node = current_node_; current_node_ = parse_node.NthNamedChild(0); std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::Match) { // optimize ?? node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::Condition) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::DoWhileLoop) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::WhileLoop) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::ForLoop) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::LoopLoop) { node = std::make_unique(); Visit(std::get>(node).get()); } else { // error } current_node_ = parse_node; } // Statements, expressions, blocks, etc. ----------------- void BuildVisitor::Visit(BlockStatement& node) { auto parse_node = current_node_; current_node_ = parse_node.NthNamedChild(0); std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::Expression) { // optimize ?? node = std::make_unique(); Visit(*std::get>(node)); } else if (current_node_type == parser::tokens::VariableDefinitionStatement) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::FlowControl) { node = std::make_unique(); Visit(*std::get>(node)); } else if (current_node_type == parser::tokens::PrefixedExpression) { node = std::make_unique(); Visit(*std::get>(node)); } else { // error } current_node_ = parse_node; } void BuildVisitor::Visit(Block* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t statement_count = parse_node.NamedChildCount(); node->statements.resize(statement_count); for (size_t i = 0; i < statement_count; ++i) { current_node_ = parse_node.NthNamedChild(i); Visit(node->statements[i]); } current_node_ = parse_node; } void BuildVisitor::Visit(SubExpressionToken& node) { auto parse_node = current_node_; current_node_ = parse_node.NthNamedChild(0); std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::NameExpression) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::ScopedStatement) { node = std::make_unique(); Visit(std::get>(node).get()); } if (current_node_type == parser::tokens::AccessExpression) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::Literal) { node = std::make_unique(); Visit(*std::get>(node)); } else if (current_node_type == parser::tokens::ReferenceExpression) { node = std::make_unique(); Visit(std::get>(node).get()); } else { // error } current_node_ = parse_node; } void BuildVisitor::Visit(SubExpression& node) { auto parse_node = current_node_; current_node_ = parse_node.NthNamedChild(0); std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::FunctionCallExpression) { // optimize ?? node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::BinaryOperatorExpression) { node = std::make_unique(); VisitBinaryOperatorExpression(std::get>(node).get()); } else if (current_node_type == parser::tokens::SubExpressionToken) { node = std::make_unique(); Visit(*std::get>(node)); } else { // error } current_node_ = parse_node; } void BuildVisitor::Visit(PrefixedExpression& node) { auto parse_node = current_node_; current_node_ = parse_node.NthNamedChild(0); std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::ReturnExpression) { // optimize ?? node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::LoopControlExpression) { node = std::make_unique(); Visit(*std::get>(node)); } else if (current_node_type == parser::tokens::Block) { node = std::make_unique(); Visit(std::get>(node).get()); } else { // error } current_node_ = parse_node; } void BuildVisitor::Visit(Expression& node) { auto parse_node = current_node_; current_node_ = parse_node.NthNamedChild(0); std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::LambdaFunction) { // optimize ?? node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::TypeConstructor) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::PrefixedExpression) { node = std::make_unique(); Visit(*std::get>(node)); } else if (current_node_type == parser::tokens::SubExpression) { node = std::make_unique(); Visit(*std::get>(node)); } else if (current_node_type == parser::tokens::AndExpression) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::OrExpression) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::ArrayExpression) { node = std::make_unique(); Visit(std::get>(node).get()); } else { // error } current_node_ = parse_node; } void BuildVisitor::Visit(SuperExpression& node) { auto parse_node = current_node_; current_node_ = parse_node.NthNamedChild(0); std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::FlowControl) { // optimize ?? node = std::make_unique(); Visit(*std::get>(node)); } else if (current_node_type == parser::tokens::TupleExpression) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::VariantExpression) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::Expression) { node = std::make_unique(); Visit(*std::get>(node)); } else { // error } current_node_ = parse_node; } void BuildVisitor::Visit(ScopedStatement* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; current_node_ = parse_node.ChildByFieldName("statement"); Visit(node->statement); current_node_ = parse_node; } // Operators void BuildVisitor::VisitBinaryOperatorExpression(FunctionCallExpression* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; node->is_binary_operator_expression = true; node->arguments.resize(2); current_node_ = parse_node.ChildByFieldName("left_expression"); Visit(node->arguments[0].second); node->name = parse_node.ChildByFieldName("operator_name").GetValue(); { // remove operator precedence markers size_t operator_size = 0; for (; operator_size < node->name.size() && node->name[operator_size] != '.'; ++operator_size) {} node->precedence = utils::MaxOperatorPrecedence - (node->name.size() - operator_size); node->name = node->name.substr(0, operator_size); } current_node_ = parse_node.ChildByFieldName("right_expression"); Visit(node->arguments[1].second); // ?? for (size_t i = 0; i < node->arguments.size(); ++i) { if (std::holds_alternative>(node->arguments[i].second)) { FunctionCallExpression* argument_node = std::get>(node->arguments[i].second).get(); if (argument_node->is_binary_operator_expression && argument_node->precedence.has_value() && argument_node->precedence.value() == node->precedence.value() && node->name != argument_node->name) { // same operators can be chained error_handling::HandleParsingError("Operators can't be chained (left argument)", node->base.start_position, node->base.end_position); } } } current_node_ = parse_node; } void BuildVisitor::Visit(ReferenceExpression* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t child_count = parse_node.ChildCount(); if (child_count > 1) { std::string reference_name = parse_node.NthChild(0).GetValue(); if (reference_name == "^") { node->reference = utils::ReferenceModifier::Reference; } else if (reference_name == "~") { node->reference = utils::ReferenceModifier::Dereference; } else if (reference_name == "@") { node->reference = utils::ReferenceModifier::UniqueReference; // TODO: rename to move ?? } else { // error } } current_node_ = parse_node.ChildByFieldName("expression"); Visit(node->expression); current_node_ = parse_node; } void BuildVisitor::Visit(AccessExpression* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; current_node_ = parse_node.ChildByFieldName("name"); node->name = std::make_unique(); Visit(node->name.get()); current_node_ = parse_node.ChildByFieldName("id"); Visit(node->id); current_node_ = parse_node; } // Other expressions void BuildVisitor::Visit(FunctionCallExpression* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t excluded_child_count = 0; current_node_ = parse_node.NthNamedChild(0); std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::SubExpressionToken) { node->prefix = std::make_unique(); Visit(*std::get>(node->prefix.value())); ++excluded_child_count; } else if (current_node_type == parser::tokens::WrappedTypeExpression) { node->prefix = std::make_unique(); Visit(std::get>(node->prefix.value()).get()); ++excluded_child_count; } else { // no prefix } node->name = parse_node.ChildByFieldName("name").GetValue(); ++excluded_child_count; size_t child_count = parse_node.NamedChildCount(); if (child_count > excluded_child_count) { bool parameters_ended = false; bool last_child_is_annotation = false; for (size_t i = 0; i + excluded_child_count < child_count; ++i) { current_node_ = parse_node.NthNamedChild(i + excluded_child_count); if (current_node_.GetType() != parser::tokens::TypeExpression) { parameters_ended = true; } if (!parameters_ended) { node->parameters.push_back(std::make_unique()); Visit(node->parameters.back().get()); } else { if (!current_node_.PreviousSibling().IsNull() && current_node_.PreviousSibling().GetValue() == "::") { // annotation node->arguments.push_back({current_node_.GetValue(), SubExpression()}); last_child_is_annotation = true; } else if (last_child_is_annotation) { // argument after annotation node->arguments.back().second = std::make_unique(); Visit(*std::get>(node->arguments.back().second)); last_child_is_annotation = false; } else { // argument without annotation node->arguments.push_back({std::nullopt, std::make_unique()}); Visit(*std::get>(node->arguments.back().second)); last_child_is_annotation = false; } } } if (last_child_is_annotation) { error_handling::HandleInternalError("Last child is annotation", "BuildVisitor.FunctionCallExpression", &node->base); } } current_node_ = parse_node; } void BuildVisitor::Visit(TupleExpression* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t expressions_count = parse_node.NamedChildCount(); node->expressions.resize(expressions_count); for (size_t i = 0; i < expressions_count; ++i) { current_node_ = parse_node.NthNamedChild(i); Visit(node->expressions[i]); } current_node_ = parse_node; } void BuildVisitor::Visit(VariantExpression* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t expressions_count = parse_node.NamedChildCount(); node->expressions.resize(expressions_count); for (size_t i = 0; i < expressions_count; ++i) { current_node_ = parse_node.NthNamedChild(i); Visit(node->expressions[i]); } current_node_ = parse_node; } void BuildVisitor::Visit(ReturnExpression* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; node->is_from_definition = (parse_node.NthChild(0).GetValue() == "return"); // "return" to return from definition and "bring" to return from block current_node_ = parse_node.ChildByFieldName("expression"); Visit(node->expression); current_node_ = parse_node; } void BuildVisitor::Visit(TypeConstructorParameter* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t child_count = parse_node.NamedChildCount(); if (child_count > 1) { current_node_ = parse_node.ChildByFieldName("name"); node->name = current_node_.GetValue(); std::string assignment_modifier = current_node_.NextSibling().GetValue(); if (assignment_modifier == "=") { node->asignment_modifier = utils::AssignmentModifier::Assign; } else if (assignment_modifier == "<-") { node->asignment_modifier = utils::AssignmentModifier::Move; } } current_node_ = parse_node.ChildByFieldName("value"); Visit(node->value); current_node_ = parse_node; } void BuildVisitor::Visit(TypeConstructor* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; node->is_allocated_on_heap = (parse_node.NthChild(1).GetValue() == "@"); current_node_ = parse_node.ChildByFieldName("constructor"); node->constructor = std::make_unique(); Visit(node->constructor.get()); size_t child_count = parse_node.NamedChildCount(); if (child_count > 1) { node->parameters.resize(child_count - 1); for (size_t i = 0; i + 1 < child_count; ++i) { current_node_ = parse_node.NthNamedChild(i + 1); Visit(&node->parameters[i]); } } current_node_ = parse_node; } void BuildVisitor::Visit(LambdaFunction* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t child_count = parse_node.NamedChildCount(); if (child_count > 1) { bool parameters_ended = false; for (size_t i = 0; i + 1 < child_count; ++i) { current_node_ = parse_node.NthNamedChild(i); if (current_node_.GetType() != parser::tokens::AnnotatedAbstractType) { parameters_ended = true; } if (!parameters_ended) { node->parameters.push_back(std::make_unique()); Visit(node->parameters.back().get()); } else { node->arguments.emplace_back(); node->arguments.back() = current_node_.GetValue(); } } } current_node_ = parse_node.ChildByFieldName("expression"); Visit(node->expression); current_node_ = parse_node; } void BuildVisitor::Visit(AndExpression* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t expressions_count = parse_node.NamedChildCount(); node->expressions.resize(expressions_count); for (size_t i = 0; i < expressions_count; ++i) { current_node_ = parse_node.NthNamedChild(i); Visit(node->expressions[i]); } current_node_ = parse_node; } void BuildVisitor::Visit(OrExpression* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t expressions_count = parse_node.NamedChildCount(); node->expressions.resize(expressions_count); for (size_t i = 0; i < expressions_count; ++i) { current_node_ = parse_node.NthNamedChild(i); Visit(node->expressions[i]); } current_node_ = parse_node; } void BuildVisitor::Visit(ArrayExpression* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t elements_count = parse_node.NamedChildCount(); node->elements.resize(elements_count); for (size_t i = 0; i < elements_count; ++i) { current_node_ = parse_node.NthNamedChild(i); Visit(node->elements[i]); } current_node_ = parse_node; } void BuildVisitor::Visit(LoopControlExpression& node) { std::string value = current_node_.NthChild(0).GetValue(); if (value == "break") { node = LoopControlExpression::Break; } else if (value == "continue") { node = LoopControlExpression::Continue; } else { // error } } // Name void BuildVisitor::Visit(PartitionName* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t child_count = parse_node.NamedChildCount(); if (child_count > 1) { node->path.resize(child_count - 1); for (size_t i = 0; i + 1 < child_count; ++i) { node->path[i] = parse_node.NthNamedChild(i).GetValue(); } } node->path.push_back(parse_node.ChildByFieldName("name").GetValue()); current_node_ = parse_node; } void BuildVisitor::Visit(NameExpression* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t child_count = parse_node.NamedChildCount(); node->names.resize(child_count); for (size_t i = 0; i < child_count; ++i) { node->names[i] = parse_node.NthNamedChild(i).GetValue(); } current_node_ = parse_node; } void BuildVisitor::Visit(OptionalName* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; current_node_ = parse_node.ChildByFieldName("name"); Visit(node->name); current_node_ = parse_node; } void BuildVisitor::Visit(TupleName* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t names_count = parse_node.NamedChildCount(); node->names.resize(names_count); for (size_t i = 0; i < names_count; ++i) { current_node_ = parse_node.NthNamedChild(i); node->names[i] = std::make_unique(); Visit(node->names[i]); } current_node_ = parse_node; } void BuildVisitor::Visit(VariantName* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t names_count = parse_node.NamedChildCount(); node->names.resize(names_count); for (size_t i = 0; i < names_count; ++i) { current_node_ = parse_node.NthNamedChild(i); node->names[i] =std::make_unique(); Visit(node->names[i]); } current_node_ = parse_node; } void BuildVisitor::Visit(Name* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; node->name = parse_node.ChildByFieldName("name").GetValue(); current_node_ = parse_node; } void BuildVisitor::Visit(AnyName& node) { auto parse_node = current_node_; current_node_ = parse_node.NthNamedChild(0); std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::Name) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::OptionalName) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::TupleName) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::VariantName) { node = std::make_unique(); Visit(std::get>(node).get()); } else { // error } current_node_ = parse_node; } // Type, typeclass, etc. ----------------- // Type void BuildVisitor::Visit(FunctionType* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t types_count = parse_node.NamedChildCount(); node->types.reserve(types_count); bool last_child_is_annotation = false; for (size_t i = 0; i < types_count; ++i) { current_node_ = parse_node.NthNamedChild(i); if (!current_node_.PreviousSibling().IsNull() && current_node_.PreviousSibling().GetValue() == "::") { // annotation node->types.push_back({current_node_.GetValue(), nullptr}); last_child_is_annotation = true; } else if (last_child_is_annotation) { // argument after annotation node->types.back().second = std::make_unique(); Visit(node->types.back().second.get()); last_child_is_annotation = false; } else { // argument without annotation node->types.push_back({std::nullopt, std::make_unique()}); Visit(node->types.back().second.get()); last_child_is_annotation = false; } } if (last_child_is_annotation) { error_handling::HandleInternalError("Last child is annotation", "BuildVisitor.FunctionType", &node->base); } current_node_ = parse_node; } void BuildVisitor::Visit(TupleType* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t current_child = 0; current_node_ = parse_node.NthNamedChild(current_child); if (parse_node.NthChild(0).GetValue() != "&") { node->type = current_node_.GetValue(); ++current_child; current_node_ = parse_node.NthNamedChild(current_child); } while (current_child < parse_node.NamedChildCount()) { node->entities.emplace_back(); if (current_node_.GetType() == parser::tokens::NameIdentifier) { node->entities.back().first = current_node_.GetValue(); ++current_child; current_node_ = parse_node.NthNamedChild(current_child); } node->entities.back().second = std::make_unique(); Visit(node->entities.back().second.get()); ++current_child; current_node_ = parse_node.NthNamedChild(current_child); } current_node_ = parse_node; } void BuildVisitor::Visit(VariantType* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t excluded_child_count = 0; size_t child_count = parse_node.NamedChildCount(); if (parse_node.NthChild(0).GetValue() != "|") { node->type = parse_node.NthNamedChild(0).GetValue(); ++excluded_child_count; } if (child_count > excluded_child_count) { node->constructors.reserve(child_count - excluded_child_count); for (size_t i = 0; i < child_count - excluded_child_count; ++i) { current_node_ = parse_node.NthNamedChild(i + excluded_child_count); std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::Constructor) { std::string constructor_name = current_node_.GetValue(); constructor_name = constructor_name.substr(1, constructor_name.size() - 1); node->constructors.push_back({constructor_name, std::nullopt}); } else if (current_node_type == parser::tokens::TupleType) { if (!node->constructors.empty() && !node->constructors.back().second.has_value()) { node->constructors.back().second = std::make_unique(); Visit(node->constructors.back().second.value().get()); } else { node->constructors.push_back({std::nullopt, std::make_unique()}); Visit(node->constructors.back().second.value().get()); } } else { // error } } } current_node_ = parse_node; } void BuildVisitor::Visit(TypeExpression* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t excluded_child_count = 0; size_t child_count = parse_node.NamedChildCount(); current_node_ = parse_node.ChildByFieldName("type"); Visit(&node->type); ++excluded_child_count; auto suffix_node1 = current_node_.NextSibling(); // TODO: better structure // TODO: check if (!suffix_node1.IsNull()) { auto suffix_node2 = suffix_node1.NextSibling(); if (!suffix_node2.IsNull()) { auto suffix_node3 = suffix_node2.NextSibling(); if (!suffix_node3.IsNull()) { current_node_ = suffix_node2; NumberLiteral literal; Visit(&literal); node->array_size = literal.value; ++excluded_child_count; node->is_optional = true; } else { if (suffix_node1.GetValue() == "`" && suffix_node2.GetValue() == "?") { node->array_size = 0; node->is_optional = true; } else if (suffix_node1.GetValue() == "`") { current_node_ = suffix_node2; NumberLiteral literal; Visit(&literal); node->array_size = literal.value; ++excluded_child_count; } else { error_handling::HandleInternalError("Undefined suffix (2 elements)", "BuildVisitor.TypeExpression", std::nullopt); } } } else { if (suffix_node1.GetValue() == "`") { node->array_size = 0; } else if (suffix_node1.GetValue() == "?") { node->is_optional = true; } else { error_handling::HandleInternalError("Undefined suffix (1 element)", "BuildVisitor.TypeExpression", std::nullopt); } } } if (child_count > excluded_child_count) { node->path.resize(child_count - excluded_child_count); for (size_t i = 0; i + excluded_child_count < child_count; ++i) { current_node_ = parse_node.NthNamedChild(i); Visit(&node->path[i]); } } current_node_ = parse_node; } void BuildVisitor::Visit(AnyType& node) { auto parse_node = current_node_; current_node_ = parse_node.NthNamedChild(0); std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::WrappedTypeExpression) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::TupleType) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::VariantType) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::FunctionType) { node = std::make_unique(); Visit(std::get>(node).get()); } else { // error } current_node_ = parse_node; } void BuildVisitor::Visit(ExtendedScopedAnyType* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; size_t child_count = parse_node.ChildCount(); if (child_count > 1) { node->references.resize(child_count - 1); for (size_t i = 0; i + 1 < child_count; ++i) { std::string reference = parse_node.NthChild(i).GetValue(); if (reference == "^") { node->references[i] = utils::ReferenceModifier::Reference; } else if (reference == "@") { node->references[i] = utils::ReferenceModifier::UniqueReference; } } } current_node_ = parse_node.ChildByFieldName("type"); Visit(node->type); current_node_ = parse_node; } // Typeclass void BuildVisitor::Visit(ParametrizedTypeclass* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; std::string prefixed_typeclass = parse_node.ChildByFieldName("typeclass").GetValue(); // prefix # removed node->typeclass = prefixed_typeclass.substr(1, prefixed_typeclass.size() - 1); size_t child_count = parse_node.NamedChildCount(); if (child_count > 1) { node->parameters.resize(child_count - 1); for (size_t i = 0; i + 1 < child_count; ++i) { current_node_ = parse_node.NthNamedChild(i + 1); node->parameters[i] = std::make_unique(); Visit(node->parameters[i].get()); } } current_node_ = parse_node; } // Typeclass & Type ----------------- void BuildVisitor::Visit(ParametrizedType* node) { SetPosition(node->base, current_node_); auto parse_node = current_node_; node->type = parse_node.ChildByFieldName("type").GetValue(); size_t child_count = parse_node.NamedChildCount(); if (child_count > 1) { node->parameters.resize(child_count - 1); for (size_t i = 0; i + 1 < child_count; ++i) { current_node_ = parse_node.NthNamedChild(i + 1); node->parameters[i] = std::make_unique(); Visit(node->parameters[i].get()); } } current_node_ = parse_node; } // Identifiers, constants, etc. ----------------- // void BuildVisitor::Visit(AnyIdentifier* node) { // std::string // *node = current_node_.GetValue(); // } void BuildVisitor::Visit(FloatNumberLiteral* node) { SetPosition(node->base, current_node_); node->value = std::stod(current_node_.GetValue()); } void BuildVisitor::Visit(NumberLiteral* node) { SetPosition(node->base, current_node_); node->value = std::stoll(current_node_.GetValue()); } void BuildVisitor::Visit(StringLiteral* node) { // TODO: other special symbols, etc. SetPosition(node->base, current_node_); std::string literal = current_node_.GetValue(); literal = literal.substr(1, literal.size() - 2); node->value.reserve(literal.size()); bool is_escape_symbol = false; for (size_t i = 0; i < literal.size(); ++i) { if (literal[i] == '\\' && !is_escape_symbol) { is_escape_symbol = true; } else { if (is_escape_symbol) { auto maybe_escape_symbol = utils::ToEscapeSymbol(literal[i]); if (maybe_escape_symbol.has_value()) { node->value += maybe_escape_symbol.value(); } else { node->value += literal[i]; } } else { node->value += literal[i]; } } } } void BuildVisitor::Visit(CharLiteral* node) { SetPosition(node->base, current_node_); std::string literal = current_node_.GetValue(); literal = literal.substr(2, literal.size() - 2); // TODO: other special symbols, etc. if (literal[0] == '\\') { auto maybe_escape_symbol = utils::ToEscapeSymbol(literal.back()); if (maybe_escape_symbol.has_value()) { node->value = maybe_escape_symbol.value(); } else { node->value = literal.back(); } } else { node->value = literal.back(); } } void BuildVisitor::Visit(UnitLiteral* node) { SetPosition(node->base, current_node_); } void BuildVisitor::Visit(BoolLiteral* node) { SetPosition(node->base, current_node_); std::string literal = current_node_.GetValue(); node->value = (literal == "true"); // always "false" in other way } void BuildVisitor::Visit(Literal& node) { auto parse_node = current_node_; current_node_ = parse_node.NthNamedChild(0); std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::FloatNumberLiteral) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::NumberLiteral) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::StringLiteral) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::CharLiteral) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::UnitLiteral) { node = std::make_unique(); Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::BoolLiteral) { node = std::make_unique(); Visit(std::get>(node).get()); } else { // error } current_node_ = parse_node; } } // namespace interpreter