binary operator expression repalced with function call expression

This commit is contained in:
ProgramSnail 2023-05-17 15:49:15 +03:00
parent 5192ffe5f3
commit 94805c8662
15 changed files with 165 additions and 269 deletions

View file

@ -78,7 +78,6 @@ private:
// Operators
void Visit(BinaryOperatorExpression* node) override;
void Visit(ReferenceExpression* node) override;
void Visit(AccessExpression* node) override;
@ -139,6 +138,11 @@ private:
void Visit(BoolLiteral* node) override;
void Visit(Literal& node) override; // variant
//
void VisitBinaryOperatorExpression(FunctionCallExpression* node);
private:
const parser::ParseTree& parse_tree_;
parser::ParseTree::Node current_node_;

View file

@ -80,7 +80,6 @@ private:
// Operators
void Visit(BinaryOperatorExpression* node) override;
void Visit(ReferenceExpression* node) override;
void Visit(AccessExpression* node) override;

View file

@ -63,7 +63,6 @@ private:
// Operators
// // void Visit(BinaryOperatorExpression* node) override;
// // void Visit(ReferenceExpression* node) override;
// // void Visit(AccessExpression* node) override;

View file

@ -129,12 +129,10 @@ using SubExpressionToken = std::variant<
std::unique_ptr<Literal>>;
//
struct FunctionCallExpression;
struct BinaryOperatorExpression;
struct ArrayExpression;
struct ReferenceExpression;
using SubExpression = std::variant<
using SubExpression = std::variant< // BiaryOperatorExpression is FunctionCallExpression
std::unique_ptr<FunctionCallExpression>,
std::unique_ptr<BinaryOperatorExpression>,
std::unique_ptr<SubExpressionToken>,
std::unique_ptr<ReferenceExpression>>;
//
@ -171,7 +169,6 @@ struct ScopedStatement;
// Operators
struct BinaryOperatorExpression;
struct ReferenceExpression;
// Other expressions
@ -482,17 +479,17 @@ struct ScopedStatement {
// Operators -----------------
struct BinaryOperatorExpression {
BaseNode base;
OperatorIdentifier operator_name;
SubExpression left_expression;
SubExpression right_expression;
size_t precedence = utils::MaxOperatorPrecedence;
utils::IdType function_id_;
bool is_method_ = false;
};
// struct BinaryOperatorExpression {
// BaseNode base;
//
// OperatorIdentifier operator_name;
// SubExpression left_expression;
// SubExpression right_expression;
// size_t precedence = utils::MaxOperatorPrecedence;
//
// utils::IdType function_id_;
// bool is_method_ = false;
// };
struct ReferenceExpression {
BaseNode base;
@ -517,11 +514,15 @@ struct FunctionCallExpression {
std::unique_ptr<TypeExpression>>> prefix;
NameOrOperatorIdentifier name;
std::vector<std::unique_ptr<TypeExpression>> parameters;
std::vector<SubExpressionToken> arguments;
std::vector<SubExpression> arguments;
std::optional<size_t> precedence; // for operators
bool is_binary_operator_expression = false; // for operators
// only one from two is present
std::optional<utils::IdType> function_id_;
std::optional<utils::IdType> typeclass_graph_id_;
bool is_method_of_first_argument_ = false;
};
struct TupleExpression {

View file

@ -69,7 +69,6 @@ private:
// Operators
// // void Visit(BinaryOperatorExpression* node) override;
// // void Visit(ReferenceExpression* node) override;
// // void Visit(AccessExpression* node) override;

View file

@ -61,7 +61,6 @@ private:
// Operators
void Visit(BinaryOperatorExpression* node) override;
void Visit(ReferenceExpression* node) override;
void Visit(AccessExpression* node) override;

View file

@ -71,7 +71,6 @@ private:
// Operators
void Visit(BinaryOperatorExpression* node) override;
void Visit(ReferenceExpression* node) override;
void Visit(AccessExpression* node) override;
@ -142,14 +141,16 @@ private:
std::optional<FunctionDeclaration*>
FindSubExpressionMethodAndUpdate(FunctionCallExpression* node,
SubExpressionToken* expression_node);
FindExpressionMethodAndUpdate(FunctionCallExpression* node,
utils::IdType expression_type);
std::optional<FunctionDeclaration*>
FindTypeFunctionAndUpdate(FunctionCallExpression* node,
TypeExpression* type_node,
std::unordered_map<std::string, utils::IdType>& context);
std::optional<FunctionDeclaration*> FindFunctionAndUpdate(FunctionCallExpression* node);
std::optional<FunctionDeclaration*>
FindAbstractTypeTypeclassFunctionAndUpdate(
FunctionCallExpression* node,

View file

@ -63,7 +63,6 @@ private:
// Operators
void Visit(BinaryOperatorExpression* node) override;
void Visit(ReferenceExpression* node) override;
void Visit(AccessExpression* node) override;

View file

@ -75,7 +75,6 @@ protected:
// Operators
virtual void Visit(BinaryOperatorExpression* node);
virtual void Visit(ReferenceExpression* node);
virtual void Visit(AccessExpression* node);

View file

@ -763,8 +763,8 @@ void BuildVisitor::Visit(SubExpression& node) {
node = std::make_unique<FunctionCallExpression>();
Visit(std::get<std::unique_ptr<FunctionCallExpression>>(node).get());
} else if (current_node_type == parser::tokens::BinaryOperatorExpression) {
node = std::make_unique<BinaryOperatorExpression>();
Visit(std::get<std::unique_ptr<BinaryOperatorExpression>>(node).get());
node = std::make_unique<FunctionCallExpression>();
VisitBinaryOperatorExpression(std::get<std::unique_ptr<FunctionCallExpression>>(node).get());
} else if (current_node_type == parser::tokens::SubExpressionToken) {
node = std::make_unique<SubExpressionToken>();
Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node));
@ -869,38 +869,39 @@ void BuildVisitor::Visit(ScopedStatement* node) {
// Operators
void BuildVisitor::Visit(BinaryOperatorExpression* node) {
void BuildVisitor::VisitBinaryOperatorExpression(FunctionCallExpression* node) {
SetPosition(node->base, current_node_);
auto parse_node = current_node_;
current_node_ = parse_node.ChildByFieldName("left_expression");
Visit(node->left_expression);
node->is_binary_operator_expression = true;
node->arguments.resize(2);
node->operator_name = parse_node.ChildByFieldName("operator_name").GetValue();
current_node_ = parse_node.ChildByFieldName("left_expression");
Visit(node->arguments[0]);
node->name = parse_node.ChildByFieldName("operator_name").GetValue();
{ // remove operator precedence markers
size_t operator_size = 0;
for (; operator_size < node->operator_name.size() && node->operator_name[operator_size] != '.'; ++operator_size) {}
node->precedence = utils::MaxOperatorPrecedence - (node->operator_name.size() - operator_size);
node->operator_name = node->operator_name.substr(0, operator_size);
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->right_expression);
Visit(node->arguments[1]);
// ??
if (std::holds_alternative<std::unique_ptr<BinaryOperatorExpression>>(node->left_expression)
&& std::get<std::unique_ptr<BinaryOperatorExpression>>(node->left_expression)->precedence >= node->precedence) {
error_handling::HandleParsingError("Operators can't be chained", node->base.start_position, node->base.end_position);
for (size_t i = 0; i < node->arguments.size(); ++i) {
if (std::holds_alternative<std::unique_ptr<FunctionCallExpression>>(node->arguments[i])) {
FunctionCallExpression* argument_node = std::get<std::unique_ptr<FunctionCallExpression>>(node->arguments[i]).get();
if (argument_node->is_binary_operator_expression
&& argument_node->precedence.has_value()
&& argument_node->precedence.value() >= node->precedence.value()) {
error_handling::HandleParsingError("Operators can't be chained (left argument)", node->base.start_position, node->base.end_position);
}
}
// ??
if (std::holds_alternative<std::unique_ptr<BinaryOperatorExpression>>(node->right_expression)
&& std::get<std::unique_ptr<BinaryOperatorExpression>>(node->right_expression)->precedence >= node->precedence) {
error_handling::HandleParsingError("Operators can't be chained", node->base.start_position, node->base.end_position);
}
current_node_ = parse_node;
@ -991,8 +992,8 @@ void BuildVisitor::Visit(FunctionCallExpression* node) {
node->parameters.push_back(std::make_unique<TypeExpression>());
Visit(node->parameters.back().get());
} else {
node->arguments.emplace_back();
Visit(node->arguments.back());
node->arguments.push_back(std::make_unique<SubExpressionToken>());
Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node->arguments.back()));
}
}
}

View file

@ -315,32 +315,35 @@ void ExecuteVisitor::Visit(LoopControlExpression& node) {
// Operators
void ExecuteVisitor::Visit(BinaryOperatorExpression* node) {
context_manager_.EnterContext();
auto maybe_function_definition = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_).definition;
if (maybe_function_definition.has_value()) {
Visitor::Visit(node->left_expression);
// TODO: custom argument value types, references, etc.
current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const);
context_manager_.DefineVariable(
node->is_method_ ? utils::ClassInternalVarName : maybe_function_definition.value().argument_names[0],
current_value_);
Visitor::Visit(node->left_expression);
// TODO: custom argument value types, references, etc.
current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const);
context_manager_.DefineVariable(maybe_function_definition.value().argument_names[node->is_method_ ? 0 : 1], current_value_);
Visit(maybe_function_definition.value().node);
} else {
// TODO: builtin operators, etc. (imports?)
error_handling::HandleRuntimeError("Binary operator definition not found", node->base);
}
context_manager_.ExitContext();
}
// TODO: function call expression used instead
/////////////////////////////////////////////////
// void ExecuteVisitor::Visit(BinaryOperatorExpression* node) {
// context_manager_.EnterContext();
//
// auto maybe_function_definition = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_).definition;
//
// if (maybe_function_definition.has_value()) {
// Visitor::Visit(node->left_expression);
// // TODO: custom argument value types, references, etc.
// current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const);
// context_manager_.DefineVariable(
// node->is_method_ ? utils::ClassInternalVarName : maybe_function_definition.value().argument_names[0],
// current_value_);
//
// Visitor::Visit(node->left_expression);
// // TODO: custom argument value types, references, etc.
// current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const);
// context_manager_.DefineVariable(maybe_function_definition.value().argument_names[node->is_method_ ? 0 : 1], current_value_);
//
// Visit(maybe_function_definition.value().node);
// } else {
// // TODO: builtin operators, etc. (imports?)
// error_handling::HandleRuntimeError("Binary operator definition not found", node->base);
// }
//
// context_manager_.ExitContext();
// }
/////////////////////////////////////////////////
void ExecuteVisitor::Visit(ReferenceExpression* node) {
// TODO: check, that there is no references to "Tmp"??
@ -371,6 +374,8 @@ void ExecuteVisitor::Visit(AccessExpression* node) {
// Other Expressions
// TODO: typeclass methods
// TODO: binary operator expression
void ExecuteVisitor::Visit(FunctionCallExpression* node) {
context_manager_.EnterContext();
if (node->prefix.has_value()) {

View file

@ -380,16 +380,6 @@ void PrintVisitor::Visit(LoopControlExpression& node) { // enum
// Operators
void PrintVisitor::Visit(BinaryOperatorExpression* node) {
out_ << "[BinaryOperator] (";
Visitor::Visit(node->left_expression);
out_ << ") [";
Visit(&node->operator_name);
out_ << "] (";
Visitor::Visit(node->right_expression);
out_ << ')';
}
void PrintVisitor::Visit(ReferenceExpression* node) {
out_ << "[ReferenceExpression ";
for (auto& reference : node->references) {
@ -423,6 +413,10 @@ void PrintVisitor::Visit(AccessExpression* node) {
void PrintVisitor::Visit(FunctionCallExpression* node) {
out_ << "[FunctionCall ";
if (node->is_binary_operator_expression) {
out_ << "(binary operation) ";
}
if (node->prefix.has_value()) {
out_ << '(';
if (std::holds_alternative<std::unique_ptr<SubExpressionToken>>(node->prefix.value())) {

View file

@ -665,102 +665,6 @@ void TypeCheckVisitor::Visit(LoopControlExpression& node) { // enum
// Operators
// TODO: better structure
void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) {
// TODO: Check, that type is not abstract ??
auto maybe_operator_id = namespace_visitor_.FindFunctionId(std::nullopt, node->operator_name);
info::definition::Function* operator_info = nullptr;
node->is_method_ = false;
if (maybe_operator_id.has_value()) {
operator_info = &global_info_.GetFunctionInfo(maybe_operator_id.value());
node->is_method_ = false;
} else {
Visitor::Visit(node->left_expression);
auto maybe_left_type = context_manager_.GetValue<info::type::DefinedType>(current_type_);
utils::ValueType left_value_type = context_manager_.GetValueType(current_type_);
if (!maybe_left_type.has_value()) {
error_handling::HandleTypecheckError("Operator not found (type is not DefinedType)", node->base);
}
auto maybe_left_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(maybe_left_type.value()->GetTypeId());
std::string left_type_name = maybe_left_type_info.value()->type.type;
auto maybe_const_operator_id = namespace_visitor_.FindMethodId(std::nullopt,
left_type_name,
node->operator_name,
utils::IsConstModifier::Const);
if (left_value_type != utils::ValueType::Const) {
maybe_operator_id = namespace_visitor_.FindMethodId(std::nullopt,
left_type_name,
node->operator_name,
utils::IsConstModifier::Var);
}
if (!maybe_operator_id.has_value() && !maybe_const_operator_id.has_value()) {
error_handling::HandleTypecheckError("Operator not found (method name not found)", node->base);
}
if (maybe_operator_id.has_value() && maybe_const_operator_id.has_value()) {
error_handling::HandleTypecheckError("Ambigious operator (const and var method)", node->base);
}
if (!maybe_operator_id.has_value()) {
maybe_operator_id = maybe_const_operator_id;
}
operator_info = &global_info_.GetFunctionInfo(maybe_operator_id.value());
node->is_method_ = true;
}
if (!operator_info->declaration.has_value()) {
error_handling::HandleTypecheckError("Operator declaration not found", node->base);
}
if (!operator_info->definition.has_value()) { // TODO: builtin, etc.
error_handling::HandleTypecheckError("Operator definition not found", node->base);
}
if (operator_info->argument_count != (node->is_method_ ? 2 : 3)) { // 2 + return type
error_handling::HandleTypecheckError("Operator wrong argument count", node->base);
}
if (operator_info->declaration->parameters.size() > 0) {
error_handling::HandleTypecheckError("Operator with parameters", node->base);
}
if (!node->is_method_) {
Visitor::Visit(*operator_info->declaration.value().argument_types[0]);
utils::IdType left_expression_type = current_type_;
Visitor::Visit(node->left_expression);
if (!context_manager_.AddValueRequirement(current_type_, left_expression_type)) {
error_handling::HandleTypecheckError("Operator left expression has wrong type", node->base);
}
}
Visitor::Visit(*operator_info->declaration.value().argument_types[node->is_method_ ? 0 : 1]);
utils::IdType right_expression_type = current_type_;
Visitor::Visit(node->right_expression);
if (!context_manager_.AddValueRequirement(current_type_, right_expression_type)) {
error_handling::HandleTypecheckError("Operator right expression has wrong type", node->base);
}
node->function_id_ = maybe_operator_id.value(); // IMPORTANT
Visitor::Visit(*operator_info->declaration.value().argument_types.back());
node->base.type_ = current_type_;
}
void TypeCheckVisitor::Visit(ReferenceExpression* node) {
Visit(node->expression.get());
@ -808,9 +712,8 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
// try to find function declaration
if (node->prefix.has_value()) {
if (std::holds_alternative<std::unique_ptr<SubExpressionToken>>(node->prefix.value())) {
maybe_function_declaration = FindSubExpressionMethodAndUpdate(
node,
std::get<std::unique_ptr<SubExpressionToken>>(node->prefix.value()).get());
Visitor::Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node->prefix.value()));
maybe_function_declaration = FindExpressionMethodAndUpdate(node, current_type_);
} else if (std::holds_alternative<std::unique_ptr<TypeExpression>>(node->prefix.value())) {
maybe_function_declaration = FindTypeFunctionAndUpdate(
node,
@ -821,58 +724,7 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
"TypeCheckVisitor.FunctionCallExpression");
}
} else {
std::optional<utils::IdType> maybe_function_id;
if (namespace_visitor_.GetCurrentNamespace()->modifier != utils::ClassInternalsModifier::Static) {
std::string namespace_name =
namespace_visitor_.GetCurrentNamespace()->type_name;
utils::ClassInternalsModifier namespace_modifier =
namespace_visitor_.GetCurrentNamespace()->modifier;
namespace_visitor_.ExitNamespace();
maybe_function_id = namespace_visitor_.FindFunctionId(std::nullopt, node->name);
if (!maybe_function_id.has_value()) {
// call functions from static namespace of current type
std::vector<std::string> current_type_path { namespace_visitor_.GetCurrentNamespace()->type_name };
maybe_function_id = namespace_visitor_.FindFunctionId(current_type_path, node->name); // TODO: check !!!
}
namespace_visitor_.EnterNamespace(namespace_name, namespace_modifier);
} else {
maybe_function_id = namespace_visitor_.FindFunctionId(std::nullopt, node->name);
}
if (maybe_function_id.has_value() && global_info_.GetFunctionInfo(maybe_function_id.value()).declaration.has_value()) {
node->function_id_ = maybe_function_id.value();
maybe_function_declaration =
global_info_.GetFunctionInfo(maybe_function_id.value()).declaration.value().node;
} else {
maybe_function_declaration = std::nullopt;
}
// try to find typeclass function in for parent namespaces (check definition ??)
if (!maybe_function_declaration.has_value()) {
// TODO: check
auto path_types = namespace_visitor_.GetCurrentPathTypes();
if (!path_types.empty()) {
for (ssize_t i = (ssize_t)path_types.size() - 1; i >= 0; --i) { // optimize
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(path_types[i]);
if (!maybe_type_info.has_value()) {
error_handling::HandleInternalError("typeclass functions / methods implemented only for AnyType",
"TypeCheckVisitor.FindTypeFunctionAndUpdate");
}
maybe_function_declaration =
FindDefinedTypeTypeclassFunctionAndUpdate(node,
maybe_type_info.value(),
false);
if (maybe_function_declaration.has_value()) {
break;
}
}
}
}
maybe_function_declaration = FindFunctionAndUpdate(node);
}
// function declaration check
@ -898,10 +750,10 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
}
// check arguments
if (function_declaration->type->types.size() != node->arguments.size() + 1) {
if (function_declaration->type->types.size() != node->arguments.size() + (node->is_method_of_first_argument_ ? 0 : 1)) {
error_handling::HandleTypecheckError("Mismatched argument count in function call expression", node->base);
}
for (size_t i = 0; i < node->arguments.size(); ++i) {
for (size_t i = (node->is_method_of_first_argument_ ? 1 : 0); i < node->arguments.size(); ++i) {
Visitor::Visit(function_declaration->type->types[i]);
utils::IdType argument_type = TypeInContext(current_type_, context);
@ -1494,13 +1346,10 @@ void TypeCheckVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) {
// TODO: internal types ??
std::optional<FunctionDeclaration*>
TypeCheckVisitor::FindSubExpressionMethodAndUpdate(FunctionCallExpression* node,
SubExpressionToken* expression_node) {
TypeCheckVisitor::FindExpressionMethodAndUpdate(FunctionCallExpression* node,
utils::IdType expression_type) {
std::optional<FunctionDeclaration*> maybe_function_declaration;
Visitor::Visit(*expression_node);
utils::IdType expression_type = current_type_;
auto maybe_abstract_type_info = context_manager_.GetValue<info::type::AbstractType>(expression_type);
if (maybe_abstract_type_info.has_value()) {
@ -1615,6 +1464,73 @@ std::optional<FunctionDeclaration*>
return maybe_function_declaration;
}
std::optional<FunctionDeclaration*> TypeCheckVisitor::FindFunctionAndUpdate(FunctionCallExpression* node) {
std::optional<FunctionDeclaration*> maybe_function_declaration;
std::optional<utils::IdType> maybe_function_id;
if (namespace_visitor_.GetCurrentNamespace()->modifier != utils::ClassInternalsModifier::Static) {
std::string namespace_name =
namespace_visitor_.GetCurrentNamespace()->type_name;
utils::ClassInternalsModifier namespace_modifier =
namespace_visitor_.GetCurrentNamespace()->modifier;
namespace_visitor_.ExitNamespace();
maybe_function_id = namespace_visitor_.FindFunctionId(std::nullopt, node->name);
if (!maybe_function_id.has_value()) {
// call functions from static namespace of current type
std::vector<std::string> current_type_path { namespace_visitor_.GetCurrentNamespace()->type_name };
maybe_function_id = namespace_visitor_.FindFunctionId(current_type_path, node->name); // TODO: check !!!
}
namespace_visitor_.EnterNamespace(namespace_name, namespace_modifier);
} else {
maybe_function_id = namespace_visitor_.FindFunctionId(std::nullopt, node->name);
}
if (maybe_function_id.has_value() && global_info_.GetFunctionInfo(maybe_function_id.value()).declaration.has_value()) {
node->function_id_ = maybe_function_id.value();
maybe_function_declaration =
global_info_.GetFunctionInfo(maybe_function_id.value()).declaration.value().node;
} else {
maybe_function_declaration = std::nullopt;
}
// call as method of first argument // TODO: earlier??
if (!maybe_function_declaration.has_value() && node->is_binary_operator_expression && node->arguments.size() > 0) {
Visitor::Visit(node->arguments[0]);
maybe_function_declaration = FindExpressionMethodAndUpdate(node, current_type_);
if (maybe_function_declaration.has_value()) {
node->is_method_of_first_argument_ = true;
}
}
// try to find typeclass function in for parent namespaces (check definition ??)
if (!maybe_function_declaration.has_value()) {
// TODO: check
auto path_types = namespace_visitor_.GetCurrentPathTypes();
if (!path_types.empty()) {
for (ssize_t i = (ssize_t)path_types.size() - 1; i >= 0; --i) { // optimize
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(path_types[i]);
if (!maybe_type_info.has_value()) {
error_handling::HandleInternalError("typeclass functions / methods implemented only for AnyType",
"TypeCheckVisitor.FindTypeFunctionAndUpdate");
}
maybe_function_declaration =
FindDefinedTypeTypeclassFunctionAndUpdate(node,
maybe_type_info.value(),
false);
if (maybe_function_declaration.has_value()) {
break;
}
}
}
}
return maybe_function_declaration;
}
std::optional<FunctionDeclaration*>
TypeCheckVisitor::FindAbstractTypeTypeclassFunctionAndUpdate(
FunctionCallExpression* node,

View file

@ -531,22 +531,6 @@ void TypedPrintVisitor::Visit(LoopControlExpression& node) { // enum
// Operators
void TypedPrintVisitor::Visit(BinaryOperatorExpression* node) {
out_ << "[BinaryOperator : ";
if (node->base.type_.has_value()) {
out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName();
}
out_ << "] (";
Visitor::Visit(node->left_expression);
out_ << ") [";
Visit(&node->operator_name);
out_ << "] (";
Visitor::Visit(node->right_expression);
out_ << ')';
}
void TypedPrintVisitor::Visit(ReferenceExpression* node) {
out_ << "[ReferenceExpression : (";
@ -597,6 +581,11 @@ void TypedPrintVisitor::Visit(FunctionCallExpression* node) {
}
out_ << ") ";
if (node->is_binary_operator_expression) {
out_ << "(binary operation) ";
}
if (node->prefix.has_value()) {
out_ << '(';
if (std::holds_alternative<std::unique_ptr<SubExpressionToken>>(node->prefix.value())) {

View file

@ -146,12 +146,9 @@ void Visitor::Visit(SubExpression& node) {
Visit(std::get<std::unique_ptr<FunctionCallExpression>>(node).get());
break;
case 1:
Visit(std::get<std::unique_ptr<BinaryOperatorExpression>>(node).get());
break;
case 2:
Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node));
break;
case 3:
case 2:
Visit(std::get<std::unique_ptr<ReferenceExpression>>(node).get());
break;
default:
@ -468,12 +465,6 @@ void Visitor::Visit(LoopControlExpression& node) {} // enum
// Operators
void Visitor::Visit(BinaryOperatorExpression* node) {
Visit(node->left_expression);
Visit(&node->operator_name);
Visit(node->right_expression);
}
void Visitor::Visit(ReferenceExpression* node) {
Visit(node->expression.get());
}