mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-05 22:48:42 +00:00
binary operator expression repalced with function call expression
This commit is contained in:
parent
5192ffe5f3
commit
94805c8662
15 changed files with 165 additions and 269 deletions
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -80,7 +80,6 @@ private:
|
|||
|
||||
// Operators
|
||||
|
||||
void Visit(BinaryOperatorExpression* node) override;
|
||||
void Visit(ReferenceExpression* node) override;
|
||||
void Visit(AccessExpression* node) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ private:
|
|||
|
||||
// Operators
|
||||
|
||||
// // void Visit(BinaryOperatorExpression* node) override;
|
||||
// // void Visit(ReferenceExpression* node) override;
|
||||
// // void Visit(AccessExpression* node) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@ private:
|
|||
|
||||
// Operators
|
||||
|
||||
// // void Visit(BinaryOperatorExpression* node) override;
|
||||
// // void Visit(ReferenceExpression* node) override;
|
||||
// // void Visit(AccessExpression* node) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ private:
|
|||
|
||||
// Operators
|
||||
|
||||
void Visit(BinaryOperatorExpression* node) override;
|
||||
void Visit(ReferenceExpression* node) override;
|
||||
void Visit(AccessExpression* node) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ private:
|
|||
|
||||
// Operators
|
||||
|
||||
void Visit(BinaryOperatorExpression* node) override;
|
||||
void Visit(ReferenceExpression* node) override;
|
||||
void Visit(AccessExpression* node) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,6 @@ protected:
|
|||
|
||||
// Operators
|
||||
|
||||
virtual void Visit(BinaryOperatorExpression* node);
|
||||
virtual void Visit(ReferenceExpression* node);
|
||||
virtual void Visit(AccessExpression* node);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
// ??
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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())) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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())) {
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue