mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-05 22:48:42 +00:00
type_check_visitor fixes, function_call_expression for typeclasses
This commit is contained in:
parent
8e74b3082e
commit
584bdfa54d
6 changed files with 192 additions and 73 deletions
|
|
@ -205,6 +205,21 @@ public:
|
|||
return current_path_;
|
||||
}
|
||||
|
||||
// use only after LinkSymbolsVisitor
|
||||
std::vector<utils::IdType> GetCurrentPathTypes() {
|
||||
std::vector<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());
|
||||
}
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
utils::IdType GetCurrentNamespaceId() {
|
||||
return namespace_stack_.back();
|
||||
}
|
||||
|
|
@ -341,10 +356,10 @@ public:
|
|||
std::vector<utils::IdType>
|
||||
GetAnnotatedTypeTypeclassesVector(interpreter::tokens::AnnotatedType* node);
|
||||
|
||||
std::unordered_map<std::string, utils::ClassInternalsModifier>
|
||||
std::unordered_map<std::string, TypeclassGraph::FunctionInfo*>
|
||||
GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node);
|
||||
|
||||
std::vector<std::pair<std::string, utils::ClassInternalsModifier>>
|
||||
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo*>>
|
||||
GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node);
|
||||
|
||||
std::unordered_map<std::string, utils::IdType>* ChooseNamespaces(
|
||||
|
|
|
|||
|
|
@ -143,14 +143,24 @@ private:
|
|||
|
||||
std::optional<FunctionDeclaration*>
|
||||
FindSubExpressionMethodAndUpdate(FunctionCallExpression* node,
|
||||
SubExpressionToken* expression_node,
|
||||
const BaseNode& base_node);
|
||||
SubExpressionToken* expression_node);
|
||||
|
||||
std::optional<FunctionDeclaration*>
|
||||
FindTypeFunctionAndUpdate(FunctionCallExpression* node,
|
||||
TypeExpression* type_node,
|
||||
std::unordered_map<std::string, utils::IdType>& context);
|
||||
|
||||
std::optional<FunctionDeclaration*>
|
||||
FindAbstractTypeTypeclassFunctionAndUpdate(
|
||||
FunctionCallExpression* node,
|
||||
info::type::AbstractType* abstract_type,
|
||||
bool is_method);
|
||||
|
||||
std::optional<FunctionDeclaration*>
|
||||
FindDefinedTypeTypeclassFunctionAndUpdate(
|
||||
FunctionCallExpression* node,
|
||||
info::definition::AnyType* defined_type,
|
||||
bool is_method);
|
||||
private:
|
||||
info::GlobalInfo::NamespaceVisitor namespace_visitor_;
|
||||
info::GlobalInfo& global_info_;
|
||||
|
|
|
|||
|
|
@ -112,12 +112,12 @@ public:
|
|||
}
|
||||
|
||||
// cache ??
|
||||
std::vector<std::pair<std::string, utils::ClassInternalsModifier>> GetTypeclassFunctions(utils::IdType id) {
|
||||
std::vector<std::pair<std::string, utils::ClassInternalsModifier>> functions;
|
||||
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo*>> GetTypeclassFunctions(utils::IdType id) {
|
||||
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo*>> functions;
|
||||
|
||||
functions.reserve(typeclasses_.at(id).functions.size());
|
||||
for (auto& function : typeclasses_[id].functions) {
|
||||
functions.push_back({function.first, function.second.modifier});
|
||||
functions.push_back({function.first, &function.second});
|
||||
}
|
||||
|
||||
return functions;
|
||||
|
|
|
|||
|
|
@ -476,10 +476,10 @@ std::vector<utils::IdType>
|
|||
return typeclasses_vector;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, utils::ClassInternalsModifier>
|
||||
std::unordered_map<std::string, TypeclassGraph::FunctionInfo*>
|
||||
GlobalInfo::GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node) {
|
||||
|
||||
std::unordered_map<std::string, utils::ClassInternalsModifier> functions;
|
||||
std::unordered_map<std::string, TypeclassGraph::FunctionInfo*> functions;
|
||||
|
||||
for (auto& typeclass : node->typeclasses) {
|
||||
utils::IdType graph_id = typeclasses_[typeclass->typeclass_id_].graph_id_;
|
||||
|
|
@ -492,12 +492,12 @@ std::unordered_map<std::string, utils::ClassInternalsModifier>
|
|||
return functions;
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, utils::ClassInternalsModifier>>
|
||||
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo*>>
|
||||
GlobalInfo::GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node) {
|
||||
|
||||
std::unordered_map<std::string, utils::ClassInternalsModifier> functions_set = GetAnnotatedTypeFunctionsMap(node);
|
||||
std::unordered_map<std::string, TypeclassGraph::FunctionInfo*> functions_set = GetAnnotatedTypeFunctionsMap(node);
|
||||
|
||||
std::vector<std::pair<std::string, utils::ClassInternalsModifier>> functions_vector;
|
||||
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo*>> functions_vector;
|
||||
functions_vector.reserve(functions_vector.size());
|
||||
for (auto& typeclass : functions_set) {
|
||||
functions_vector.push_back(typeclass);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,12 @@ void LinkSymbolsVisitor::Visit(Namespace* node) {
|
|||
}
|
||||
if (maybe_typeclass.has_value()) {
|
||||
node->link_typeclass_id_ = maybe_typeclass.value();
|
||||
if (!namespace_visitor_.IsInGlobalNamespace()) {
|
||||
// other type of error??
|
||||
error_handling::HandleParsingError("Can't use typeclass namespace in other namespace",
|
||||
node->base.start_position,
|
||||
node->base.end_position);
|
||||
}
|
||||
}
|
||||
|
||||
namespace_visitor_.EnterNamespace(node->type, node->modifier);
|
||||
|
|
|
|||
|
|
@ -254,14 +254,19 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
|
|||
void TypeCheckVisitor::Visit(TypeDefinitionStatement* node) {
|
||||
is_in_statement_ = true;
|
||||
|
||||
std::unordered_map<std::string, utils::ClassInternalsModifier> required_functions =
|
||||
// TODO: defined functions can be not redifined
|
||||
std::unordered_map<std::string, info::TypeclassGraph::FunctionInfo*> required_functions =
|
||||
global_info_.GetAnnotatedTypeFunctionsMap(node->definition->type.get());
|
||||
|
||||
std::string& type_name = node->definition->type->type;
|
||||
|
||||
for (auto& function : required_functions) { // TODO: optimize
|
||||
if (function.second->definition.has_value()) { // TODO: check
|
||||
continue;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, utils::IdType>* current_namespaces =
|
||||
global_info_.ChooseNamespaces(function.second, namespace_visitor_.GetCurrentNamespace());
|
||||
global_info_.ChooseNamespaces(function.second->modifier, namespace_visitor_.GetCurrentNamespace());
|
||||
|
||||
auto& type_functions = global_info_.GetNamespaceInfo((*current_namespaces)[type_name]).functions;
|
||||
|
||||
|
|
@ -790,7 +795,6 @@ void TypeCheckVisitor::Visit(AccessExpression* node) {
|
|||
// Other Expressions
|
||||
|
||||
// TODO: builtin functions / methods
|
||||
// TODO: abstract types (check typeclass requirements)
|
||||
void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
|
||||
std::optional<FunctionDeclaration*> maybe_function_declaration;
|
||||
|
||||
|
|
@ -807,8 +811,7 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
|
|||
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(),
|
||||
node->base);
|
||||
std::get<std::unique_ptr<SubExpressionToken>>(node->prefix.value()).get());
|
||||
} else if (std::holds_alternative<std::unique_ptr<TypeExpression>>(node->prefix.value())) {
|
||||
maybe_function_declaration = FindTypeFunctionAndUpdate(
|
||||
node,
|
||||
|
|
@ -819,8 +822,6 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
|
|||
"TypeCheckVisitor.FunctionCallExpression");
|
||||
}
|
||||
} else {
|
||||
// TODO: static functions from parent namespaces' typeclasses
|
||||
|
||||
std::optional<utils::IdType> maybe_function_id;
|
||||
|
||||
if (namespace_visitor_.GetCurrentNamespace()->modifier != utils::ClassInternalsModifier::Static) {
|
||||
|
|
@ -844,17 +845,40 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
|
|||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// function declaration check
|
||||
if (!maybe_function_declaration.has_value()) {
|
||||
error_handling::HandleTypecheckError("No function declaration found for function in function call expression", node->base);
|
||||
error_handling::HandleTypecheckError("No function declaration found for function in call expression", node->base);
|
||||
}
|
||||
FunctionDeclaration* function_declaration = maybe_function_declaration.value();
|
||||
|
||||
|
|
@ -1472,39 +1496,23 @@ void TypeCheckVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) {
|
|||
// TODO: internal types ??
|
||||
std::optional<FunctionDeclaration*>
|
||||
TypeCheckVisitor::FindSubExpressionMethodAndUpdate(FunctionCallExpression* node,
|
||||
SubExpressionToken* expression_node,
|
||||
const BaseNode& base_node) {
|
||||
std::optional<utils::IdType> maybe_function_id;
|
||||
SubExpressionToken* expression_node) {
|
||||
std::optional<FunctionDeclaration*> maybe_function_declaration;
|
||||
|
||||
Visitor::Visit(*expression_node);
|
||||
utils::IdType expression_type = current_type_;
|
||||
|
||||
auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name);
|
||||
auto maybe_abstract_type_info = context_manager_.GetValue<info::type::AbstractType>(expression_type);
|
||||
|
||||
if (maybe_abstract_type_info.has_value()) {
|
||||
if (!maybe_typeclass_graph_id.has_value()) {
|
||||
error_handling::HandleTypecheckError("Typeclass function not found", base_node);
|
||||
}
|
||||
|
||||
info::type::AbstractType* abstract_type_info = maybe_abstract_type_info.value();
|
||||
|
||||
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 (abstract type)",
|
||||
"TypeCheckVisitor.FindSubExpressionMethodAndUpdate");
|
||||
}
|
||||
if (abstract_type_info->HasTypeclass(maybe_typeclass_graph_id.value())) {
|
||||
node->typeclass_graph_id_ = maybe_typeclass_graph_id;
|
||||
maybe_function_declaration = maybe_typeclass_function_info.value()->declaration;
|
||||
}
|
||||
maybe_function_declaration = FindAbstractTypeTypeclassFunctionAndUpdate(node,
|
||||
maybe_abstract_type_info.value(),
|
||||
true);
|
||||
} else {
|
||||
auto maybe_defined_type_info =
|
||||
context_manager_.GetValue<info::type::DefinedType>(expression_type);
|
||||
if (!maybe_defined_type_info.has_value()) {
|
||||
error_handling::HandleTypecheckError("There is no non-builtin methods for not defined type", base_node);
|
||||
error_handling::HandleTypecheckError("There is no non-builtin methods for not defined type", node->base);
|
||||
}
|
||||
|
||||
utils::IdType type_id = maybe_defined_type_info.value()->GetTypeId();
|
||||
|
|
@ -1519,13 +1527,14 @@ std::optional<FunctionDeclaration*>
|
|||
|
||||
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", base_node);
|
||||
error_handling::HandleTypecheckError("Redefinition of method: const & var", node->base);
|
||||
}
|
||||
|
||||
if (!maybe_function_id.has_value()) {
|
||||
|
|
@ -1538,19 +1547,10 @@ std::optional<FunctionDeclaration*>
|
|||
global_info_.GetFunctionInfo(maybe_function_id.value()).declaration.value().node;
|
||||
}
|
||||
|
||||
if (!maybe_function_declaration.has_value() && maybe_typeclass_graph_id.has_value()) {
|
||||
auto typeclasses = global_info_.GetAnnotatedTypeTypeclassesSet(type_info->type.node);
|
||||
auto function_typeclass_iter = typeclasses.find(maybe_typeclass_graph_id.value());
|
||||
|
||||
if (function_typeclass_iter != typeclasses.end()) {
|
||||
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.FindSubExpressionMethodAndUpdate");
|
||||
}
|
||||
maybe_function_declaration = maybe_typeclass_function_info.value()->declaration;
|
||||
}
|
||||
if (!maybe_function_declaration.has_value()) {
|
||||
maybe_function_declaration = FindDefinedTypeTypeclassFunctionAndUpdate(node,
|
||||
type_info,
|
||||
true);
|
||||
}
|
||||
}
|
||||
return maybe_function_declaration;
|
||||
|
|
@ -1562,16 +1562,27 @@ std::optional<FunctionDeclaration*>
|
|||
TypeCheckVisitor::FindTypeFunctionAndUpdate(FunctionCallExpression* node,
|
||||
TypeExpression* type_node,
|
||||
std::unordered_map<std::string, utils::IdType>& context) {
|
||||
std::optional<utils::IdType> maybe_function_id;
|
||||
std::optional<FunctionDeclaration*> maybe_function_declaration;
|
||||
|
||||
if (type_node->array_size.has_value()) {
|
||||
error_handling::HandleTypecheckError("Can't call function from array type namespace", node->base);
|
||||
}
|
||||
|
||||
// std::optional<utils::IdType> maybe_local_abstract_type =
|
||||
// context_manager_.GetLocalType(type_node->type.type);
|
||||
std::optional<utils::IdType> maybe_local_abstract_type = context_manager_.GetLocalType(type_node->type.type);
|
||||
|
||||
if (maybe_local_abstract_type.has_value()) {
|
||||
auto maybe_abstract_type_info =
|
||||
context_manager_.GetValue<info::type::AbstractType>(maybe_local_abstract_type.value());
|
||||
|
||||
if (!maybe_abstract_type_info.has_value()) {
|
||||
error_handling::HandleInternalError("Local abstract type contains not abstract type",
|
||||
"TypeCheckVisitor.FindTypeFunctionAndUpdate");
|
||||
}
|
||||
|
||||
maybe_function_declaration = FindAbstractTypeTypeclassFunctionAndUpdate(node,
|
||||
maybe_abstract_type_info.value(),
|
||||
false);
|
||||
} else {
|
||||
std::vector<std::string> path;
|
||||
path.reserve(type_node->path.size() + 1);
|
||||
|
||||
|
|
@ -1580,7 +1591,7 @@ std::optional<FunctionDeclaration*>
|
|||
}
|
||||
path.push_back(type_node->type.type);
|
||||
|
||||
maybe_function_id = namespace_visitor_.FindFunctionId(path, node->name);
|
||||
std::optional<utils::IdType> maybe_function_id = namespace_visitor_.FindFunctionId(path, node->name);
|
||||
|
||||
CollectTypeExpressionContext(*type_node, context);
|
||||
|
||||
|
|
@ -1589,6 +1600,83 @@ std::optional<FunctionDeclaration*>
|
|||
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()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
return maybe_function_declaration;
|
||||
}
|
||||
|
||||
std::optional<FunctionDeclaration*>
|
||||
TypeCheckVisitor::FindAbstractTypeTypeclassFunctionAndUpdate(
|
||||
FunctionCallExpression* node,
|
||||
info::type::AbstractType* abstract_type_info,
|
||||
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()) {
|
||||
error_handling::HandleTypecheckError("Typeclass function not found", node->base);
|
||||
}
|
||||
|
||||
auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name,
|
||||
maybe_typeclass_graph_id.value());
|
||||
|
||||
if (abstract_type_info->HasTypeclass(maybe_typeclass_graph_id.value())) {
|
||||
if (!maybe_typeclass_function_info.has_value()) {
|
||||
error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (abstract type)",
|
||||
"TypeCheckVisitor.FindAbstractTypeTypeclassFunctionAndUpdate");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return maybe_function_declaration;
|
||||
}
|
||||
|
||||
std::optional<FunctionDeclaration*>
|
||||
TypeCheckVisitor::FindDefinedTypeTypeclassFunctionAndUpdate(
|
||||
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 typeclasses = global_info_.GetAnnotatedTypeTypeclassesSet(defined_type->type.node);
|
||||
auto function_typeclass_iter = typeclasses.find(maybe_typeclass_graph_id.value());
|
||||
|
||||
if (function_typeclass_iter != typeclasses.end()) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return maybe_function_declaration;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue