fixes, function definition search in typecheck

This commit is contained in:
ProgramSnail 2023-05-19 17:09:14 +03:00
parent 0b53b2f218
commit afecbd64f5
6 changed files with 123 additions and 129 deletions

View file

@ -205,15 +205,21 @@ public:
return current_path_;
}
const std::vector<utils::IdType>& GetCurrentPathNamespaces() {
return namespace_stack_;
}
// use only after LinkSymbolsVisitor
std::vector<utils::IdType> GetCurrentPathTypes() {
std::vector<utils::IdType> types;
std::vector<std::optional<utils::IdType>> GetCurrentPathTypes() {
std::vector<std::optional<utils::IdType>> types;
types.reserve(namespace_stack_.size());
for (auto& namespace_id : namespace_stack_) {
definition::Namespace& namespace_info = global_info_.GetNamespaceInfo(namespace_id);
if (namespace_info.any_node.has_value() && namespace_info.any_node.value()->link_type_id_.has_value()) {
types.push_back(namespace_info.any_node.value()->link_type_id_.value());
} else {
types.push_back(std::nullopt);
}
}

View file

@ -522,7 +522,7 @@ struct FunctionCallExpression {
// only one from two is present
std::optional<utils::IdType> function_id_;
std::optional<utils::IdType> typeclass_graph_id_;
std::optional<utils::IdType> graph_id_; // for type or typeclass
bool is_method_of_first_argument_ = false;
};

View file

@ -130,7 +130,8 @@ private:
void AddTypeFunctionsToTypeclassGraph(utils::IdType type_id,
utils::IdType graph_id,
utils::ClassInternalsModifier namespace_modifier);
utils::ClassInternalsModifier namespace_modifier,
const BaseNode& base_node);
private:
info::GlobalInfo::NamespaceVisitor namespace_visitor_;

View file

@ -158,7 +158,7 @@ private:
bool is_method);
std::optional<FunctionDeclaration*>
FindDefinedTypeTypeclassFunctionAndUpdate(
FindDefinedTypeFunctionAndUpdate(
FunctionCallExpression* node,
info::definition::AnyType* defined_type,
bool is_method);

View file

@ -55,15 +55,18 @@ void LinkSymbolsVisitor::Visit(TypeDefinitionStatement* node) {
AddTypeFunctionsToTypeclassGraph(node->type_id_,
graph_id,
utils::ClassInternalsModifier::Static);
utils::ClassInternalsModifier::Static,
node->base);
AddTypeFunctionsToTypeclassGraph(node->type_id_,
graph_id,
utils::ClassInternalsModifier::Const);
utils::ClassInternalsModifier::Const,
node->base);
AddTypeFunctionsToTypeclassGraph(node->type_id_,
graph_id,
utils::ClassInternalsModifier::Var);
utils::ClassInternalsModifier::Var,
node->base);
}
void LinkSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) {
@ -164,7 +167,8 @@ void LinkSymbolsVisitor::Visit(ParametrizedTypeclass* node) {
void LinkSymbolsVisitor::AddTypeFunctionsToTypeclassGraph(utils::IdType type_id,
utils::IdType graph_id,
utils::ClassInternalsModifier namespace_modifier) {
utils::ClassInternalsModifier namespace_modifier,
const BaseNode& base_node) {
auto maybe_type_graph_info = typeclass_graph_.GetTypeVertex(graph_id);
if (!maybe_type_graph_info.has_value()) {
error_handling::HandleInternalError("Type in typeclass graph is not marked as type",
@ -198,10 +202,12 @@ void LinkSymbolsVisitor::AddTypeFunctionsToTypeclassGraph(utils::IdType type_id,
type_graph_info->functions[function.first] = function_graph_info;
} else {
if (function_info.definition.has_value()) {
function_graph_iter->second.is_defined_in_owner = true;
function_graph_iter->second.definition = function_info.definition.value().node;
if (namespace_modifier != function_graph_iter->second.modifier) {
error_handling::HandleTypecheckError("Type function \"" + function.first + "\" has definitions / declarations with different modifiers (static / const /var)", base_node);
}
error_handling::HandleInternalError("This code should be unreachable",
"LinkSymbolsVisitor.AddTypeFunctionsToTypeclassGraph");
}
}
}

View file

@ -713,6 +713,7 @@ void TypeCheckVisitor::Visit(AccessExpression* node) {
// Other Expressions
// TODO: builtin functions / methods
// TODO: find & check definitions
void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
std::optional<FunctionDeclaration*> maybe_function_declaration;
@ -776,7 +777,27 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
context_manager_.AddValueRequirement(current_type_, argument_type);
}
// node->function_id_ = maybe_function_id.value(); // IMPORTANT // TODO: do in functions
if (node->function_id_.has_value()) {
if (!global_info_.GetFunctionInfo(node->function_id_.value()).definition.has_value()) {
error_handling::HandleTypecheckError("No function definition found (non-type function)", node->base);
}
} else if (node->graph_id_.has_value()) {
if (typeclass_graph_.GetVertex(node->graph_id_.value()).modifier != info::TypeclassGraph::Modifier::Typeclass) {
auto maybe_graph_function_info = typeclass_graph_.GetFunctionInfo(node->name, node->graph_id_.value());
if (!maybe_graph_function_info.has_value()) {
error_handling::HandleInternalError("FunctionInfo by graph_id_ not found",
"TypeCheckVisitor.FunctionCallExpression");
}
if (!maybe_graph_function_info.value()->definition.has_value()) {
error_handling::HandleTypecheckError("No function definition found (type function)", node->base);
}
}
} else {
error_handling::HandleInternalError("No function_id_ and graph_id_ found",
"TypeCheckVisitor.FunctionCallExpression");
}
Visitor::Visit(function_declaration->type->types.back());
current_type_ = TypeInContext(current_type_, context);
@ -1372,7 +1393,6 @@ void TypeCheckVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) {
}
// TODO: internal types ??
// TODO: find & check definitions
std::optional<FunctionDeclaration*>
TypeCheckVisitor::FindExpressionMethodAndUpdate(FunctionCallExpression* node,
utils::IdType expression_type) {
@ -1399,35 +1419,9 @@ std::optional<FunctionDeclaration*>
}
info::definition::AnyType* type_info = maybe_type_info.value();
std::optional<utils::IdType> maybe_const_function_id = global_info_.GetNamespaceInfo(global_info_.GetNamespaceInfo(type_info->parent_namespace).const_namespaces.at(type_info->type.type)).functions[node->name];
utils::ValueType expression_value_type = context_manager_.GetValueType(expression_type);
std::optional<utils::IdType> maybe_function_id;
if (expression_value_type == utils::ValueType::Var || expression_value_type == utils::ValueType::Tmp) {
// TODO: choose expression value types
maybe_function_id = global_info_.GetNamespaceInfo(global_info_.GetNamespaceInfo(type_info->parent_namespace).var_namespaces.at(type_info->type.type)).functions[node->name];
}
if (maybe_const_function_id.has_value() && maybe_function_id.has_value()) { // TODO: handle on link_types stage
error_handling::HandleTypecheckError("Redefinition of method: const & var", node->base);
}
if (!maybe_function_id.has_value()) {
maybe_function_id = maybe_const_function_id;
}
if (maybe_function_id.has_value()) {
node->function_id_ = maybe_function_id.value();
maybe_function_declaration =
global_info_.GetFunctionInfo(maybe_function_id.value()).declaration.value().node;
}
if (!maybe_function_declaration.has_value()) {
maybe_function_declaration = FindDefinedTypeTypeclassFunctionAndUpdate(node,
type_info,
true);
}
maybe_function_declaration = FindDefinedTypeFunctionAndUpdate(node,
type_info,
true);
}
return maybe_function_declaration;
}
@ -1467,26 +1461,26 @@ std::optional<FunctionDeclaration*>
}
path.push_back(type_node->type.type);
std::optional<utils::IdType> maybe_function_id = namespace_visitor_.FindFunctionId(path, node->name);
CollectTypeExpressionContext(*type_node, context);
if (maybe_function_id.has_value()) {
node->function_id_ = maybe_function_id.value();
maybe_function_declaration =
global_info_.GetFunctionInfo(maybe_function_id.value()).declaration.value().node;
}
if (!maybe_function_declaration.has_value() && type_node->type_id_.has_value()) {
if (type_node->type_id_.has_value()) {
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(type_node->type_id_.value());
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);
maybe_function_declaration = FindDefinedTypeFunctionAndUpdate(node,
maybe_type_info.value(),
false);
} else {
std::optional<utils::IdType> maybe_function_id = namespace_visitor_.FindFunctionId(path, node->name);
if (maybe_function_id.has_value()) {
node->function_id_ = maybe_function_id.value();
maybe_function_declaration =
global_info_.GetFunctionInfo(maybe_function_id.value()).declaration.value().node;
}
}
}
return maybe_function_declaration;
@ -1494,36 +1488,63 @@ std::optional<FunctionDeclaration*>
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();
const std::vector<utils::IdType>& path_namespaces = namespace_visitor_.GetCurrentPathNamespaces();
auto path_types = namespace_visitor_.GetCurrentPathTypes();
for (ssize_t i = (ssize_t)path_types.size() - 1; i >= 0; --i) { // optimize ??
if (path_types[i].has_value()) {
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(path_types[i].value());
if (!maybe_type_info.has_value()) {
error_handling::HandleInternalError("typeclass functions / methods implemented only for AnyType",
"TypeCheckVisitor.FindTypeFunctionAndUpdate");
}
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 !!!
maybe_function_declaration =
FindDefinedTypeFunctionAndUpdate(node,
maybe_type_info.value(),
false);
} else {
auto function_iter = global_info_.GetNamespaceInfo(path_namespaces[i]).functions.find(node->name);
if (function_iter != global_info_.GetNamespaceInfo(path_namespaces[i]).functions.end()) {
auto& maybe_declaration_info = global_info_.GetFunctionInfo(function_iter->second).declaration;
if (maybe_declaration_info.has_value()) {
maybe_function_declaration = maybe_declaration_info.value().node;
}
}
}
namespace_visitor_.EnterNamespace(namespace_name, namespace_modifier);
} else {
maybe_function_id = namespace_visitor_.FindFunctionId(std::nullopt, node->name);
if (maybe_function_declaration.has_value()) {
break;
}
}
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;
}
// ------------------ replaced ------------------
// 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);
// }
//
// 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;
// }
// 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_);
@ -1532,30 +1553,6 @@ std::optional<FunctionDeclaration*> TypeCheckVisitor::FindFunctionAndUpdate(Func
}
}
// 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;
}
@ -1589,44 +1586,28 @@ std::optional<FunctionDeclaration*>
error_handling::HandleTypecheckError("Typeclass function has wrong modifier (abstract type)", node->base);
}
node->typeclass_graph_id_ = maybe_typeclass_graph_id;
node->graph_id_ = maybe_typeclass_graph_id;
maybe_function_declaration = maybe_typeclass_function_info.value()->declaration;
return maybe_function_declaration;
}
std::optional<FunctionDeclaration*>
TypeCheckVisitor::FindDefinedTypeTypeclassFunctionAndUpdate(
FunctionCallExpression* node,
info::definition::AnyType* defined_type,
bool is_method) {
TypeCheckVisitor::FindDefinedTypeFunctionAndUpdate(
FunctionCallExpression* node,
info::definition::AnyType* defined_type,
bool is_method) {
std::optional<FunctionDeclaration*> maybe_function_declaration;
auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name);
if (!maybe_typeclass_graph_id.has_value()) {
auto maybe_type_function_info = typeclass_graph_.GetFunctionInfo(node->name, defined_type->type.node->graph_id_);
if (!maybe_type_function_info.has_value()) {
return std::nullopt;
// error_handling::HandleTypecheckError("Function is not declared in type", node->base);
}
auto typeclasses = typeclass_graph_.GetDependenciesSet(defined_type->type.node->graph_id_);
auto function_typeclass_iter = typeclasses.find(maybe_typeclass_graph_id.value());
if (function_typeclass_iter == typeclasses.end()) {
error_handling::HandleTypecheckError("Function typeclass not pesent in type typeclasses list (defined type)", node->base);
}
auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name,
maybe_typeclass_graph_id.value());
if (!maybe_typeclass_function_info.has_value()) {
error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (definied type)",
"TypeCheckVisitor.FindDefinedTypeTypeclassFunctionAndUpdate");
}
if ((maybe_typeclass_function_info.value()->modifier == utils::ClassInternalsModifier::Static) != is_method) {
return std::nullopt;
}
node->typeclass_graph_id_ = maybe_typeclass_graph_id;
maybe_function_declaration = maybe_typeclass_function_info.value()->declaration;
node->graph_id_ = defined_type->type.node->graph_id_;
maybe_function_declaration = maybe_type_function_info.value()->declaration;
return maybe_function_declaration;
}