mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-06 06:58:45 +00:00
function declaration & definition statements for typeclasses and inherited classes in typecheck_visitor
This commit is contained in:
parent
aab455ff1d
commit
090f638e45
3 changed files with 102 additions and 21 deletions
|
|
@ -340,7 +340,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// cache ??
|
// cache ??
|
||||||
std::vector<utils::IdType> GetAnnotatedTypeTypeclasses(interpreter::tokens::AnnotatedType* node) {
|
std::unordered_set<utils::IdType> GetAnnotatedTypeTypeclassesSet(interpreter::tokens::AnnotatedType* node) {
|
||||||
std::unordered_set<utils::IdType> typeclasses;
|
std::unordered_set<utils::IdType> typeclasses;
|
||||||
|
|
||||||
for (auto& typeclass : node->typeclasses) {
|
for (auto& typeclass : node->typeclasses) {
|
||||||
|
|
@ -353,13 +353,18 @@ public:
|
||||||
|
|
||||||
typeclasses.insert(graph_id);
|
typeclasses.insert(graph_id);
|
||||||
}
|
}
|
||||||
|
return typeclasses;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<utils::IdType> collected_typeclasses;
|
std::vector<utils::IdType> GetAnnotatedTypeTypeclassesVector(interpreter::tokens::AnnotatedType* node) {
|
||||||
collected_typeclasses.reserve(typeclasses.size());
|
std::unordered_set<utils::IdType> typeclasses_set = GetAnnotatedTypeTypeclassesSet(node);
|
||||||
for (auto& typeclass : typeclasses) {
|
|
||||||
collected_typeclasses.push_back(typeclass);
|
std::vector<utils::IdType> typeclasses_vector;
|
||||||
|
typeclasses_vector.reserve(typeclasses_vector.size());
|
||||||
|
for (auto& typeclass : typeclasses_set) {
|
||||||
|
typeclasses_vector.push_back(typeclass);
|
||||||
}
|
}
|
||||||
return collected_typeclasses;
|
return typeclasses_vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<utils::IdType> AddTypeclassToGraph(utils::IdType typeclass);
|
std::optional<utils::IdType> AddTypeclassToGraph(utils::IdType typeclass);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
@ -67,7 +68,7 @@ public:
|
||||||
return typeclasses_.size() - 1;
|
return typeclasses_.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<utils::IdType> FindMethodTypeclass(const std::string& name) {
|
std::optional<utils::IdType> FindFunctionTypeclass(const std::string& name) {
|
||||||
auto function_iter = method_to_typeclass_.find(name);
|
auto function_iter = method_to_typeclass_.find(name);
|
||||||
if (function_iter == method_to_typeclass_.end()) {
|
if (function_iter == method_to_typeclass_.end()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
@ -75,8 +76,27 @@ public:
|
||||||
return function_iter->second;
|
return function_iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TypeclassVertex& GetTypeclass(utils::IdType id) { // check, if calculated ??
|
bool IsFunctionInTypeclass(const std::string& name, utils::IdType typeclass_id) {
|
||||||
return typeclasses_.at(id);
|
return typeclasses_[typeclass_id].functions.count(name) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<FunctionInfo*> GetFunctionInfo(const std::string& name,
|
||||||
|
std::optional<utils::IdType> typeclass_id) {
|
||||||
|
if (typeclass_id.has_value()) {
|
||||||
|
return &typeclasses_[typeclass_id.value()].functions[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
auto maybe_function_typeclass_id = FindFunctionTypeclass(name);
|
||||||
|
|
||||||
|
if (!maybe_function_typeclass_id.has_value()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &typeclasses_[maybe_function_typeclass_id.value()].functions[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
const TypeclassVertex& GetTypeclass(utils::IdType typeclass_id) { // check, if calculated ??
|
||||||
|
return typeclasses_.at(typeclass_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cache ??
|
// cache ??
|
||||||
|
|
|
||||||
|
|
@ -127,11 +127,19 @@ void TypeCheckVisitor::Visit(FunctionDeclaration* node) {
|
||||||
bool was_in_statement = is_in_statement_;
|
bool was_in_statement = is_in_statement_;
|
||||||
is_in_statement_ = true;
|
is_in_statement_ = true;
|
||||||
|
|
||||||
|
if (!was_in_statement) {
|
||||||
|
if (namespace_visitor_.GetCurrentNamespaceTypeclassId().has_value()) {
|
||||||
|
error_handling::HandleTypecheckError("Can't declare functions in typeclass namespace", node->base);
|
||||||
|
}
|
||||||
|
if (typeclass_graph_.FindFunctionTypeclass(node->name).has_value()) {
|
||||||
|
error_handling::HandleTypecheckError("Can't redeclare functions, that are declared as typeclass functions", node->base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
context_manager_.EnterContext();
|
context_manager_.EnterContext();
|
||||||
for (auto& parameter : node->parameters) { // declaration correctness check // TODO: needed??
|
for (auto& parameter : node->parameters) { // declaration correctness check // TODO: needed??
|
||||||
std::vector<utils::IdType> requirements =
|
std::vector<utils::IdType> requirements =
|
||||||
global_info_.GetAnnotatedTypeTypeclasses(parameter.get());
|
global_info_.GetAnnotatedTypeTypeclassesVector(parameter.get());
|
||||||
current_type_ = context_manager_.AddValue(
|
current_type_ = context_manager_.AddValue(
|
||||||
info::type::AbstractType(utils::AbstractTypeModifier::Abstract,
|
info::type::AbstractType(utils::AbstractTypeModifier::Abstract,
|
||||||
parameter->type,
|
parameter->type,
|
||||||
|
|
@ -152,37 +160,84 @@ void TypeCheckVisitor::Visit(FunctionDeclaration* node) {
|
||||||
|
|
||||||
void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
|
void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
|
||||||
is_in_statement_ = true;
|
is_in_statement_ = true;
|
||||||
context_manager_.EnterContext();
|
|
||||||
|
std::string& function_name = node->definition->name;
|
||||||
|
|
||||||
info::definition::Function& function_info = global_info_.GetFunctionInfo(node->function_id_);
|
info::definition::Function& function_info = global_info_.GetFunctionInfo(node->function_id_);
|
||||||
|
|
||||||
if (!function_info.declaration.has_value()) {
|
interpreter::tokens::FunctionDeclaration* declaration = nullptr;
|
||||||
error_handling::HandleTypecheckError("Function defined, but not declared", node->base);
|
if (function_info.declaration.has_value()) {
|
||||||
|
declaration = function_info.declaration.value().node;
|
||||||
|
} else {
|
||||||
|
auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(function_name);
|
||||||
|
|
||||||
|
if (!maybe_typeclass_graph_id.has_value()) {
|
||||||
|
error_handling::HandleTypecheckError("Function defined, but not declared", node->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto maybe_curent_type = namespace_visitor_.GetCurrentNamespaceType<info::definition::AnyType>(); // TODO: aliases
|
||||||
|
auto maybe_current_typeclass = namespace_visitor_.GetCurrentNamespaceTypeclass();
|
||||||
|
|
||||||
|
if (maybe_curent_type.has_value() && maybe_current_typeclass.has_value()) {
|
||||||
|
error_handling::HandleInternalError("Current namespace is belong to type and typeclass in same time",
|
||||||
|
"TypeCheckVisitor.FunctionDefinitionStatement");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!maybe_curent_type.has_value() && !maybe_current_typeclass.has_value()) {
|
||||||
|
error_handling::HandleTypecheckError("Function defined, but declared in typeclass and not belong to type or typeclass namespace", node->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool method_found_in_typeclass = false;
|
||||||
|
if (maybe_curent_type.has_value()) { // optiomize??
|
||||||
|
auto typeclasses = global_info_.GetAnnotatedTypeTypeclassesSet(maybe_curent_type.value()->type.node);
|
||||||
|
|
||||||
|
method_found_in_typeclass = (typeclasses.count(maybe_typeclass_graph_id.value()) != 0);
|
||||||
|
|
||||||
|
} else if (maybe_current_typeclass.has_value()) {
|
||||||
|
method_found_in_typeclass =
|
||||||
|
typeclass_graph_.IsFunctionInTypeclass(function_name, maybe_current_typeclass.value()->graph_id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!method_found_in_typeclass) {
|
||||||
|
error_handling::HandleTypecheckError("Function defined, but declared in different typeclass", node->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto maybe_function_info = typeclass_graph_.GetFunctionInfo(function_name, std::nullopt);
|
||||||
|
if (!maybe_function_info.has_value()) {
|
||||||
|
error_handling::HandleInternalError("FunctionInfo not found",
|
||||||
|
"TypeCheckVisitor.FunctionDefinitionStatement");
|
||||||
|
}
|
||||||
|
|
||||||
|
declaration = maybe_function_info.value()->declaration; // TODO: save declaration to global info ??
|
||||||
}
|
}
|
||||||
|
|
||||||
info::definition::FunctionDeclaration& declaration = function_info.declaration.value();
|
context_manager_.EnterContext();
|
||||||
|
|
||||||
for (auto parameter : declaration.parameters) {
|
if (declaration->type->types.size() != node->definition->arguments.size() + 1) { // + return type
|
||||||
|
error_handling::HandleTypecheckError("Wrong argument count in function definition", node->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& parameter : declaration->parameters) {
|
||||||
std::vector<utils::IdType> requirements =
|
std::vector<utils::IdType> requirements =
|
||||||
global_info_.GetAnnotatedTypeTypeclasses(parameter.node);
|
global_info_.GetAnnotatedTypeTypeclassesVector(parameter.get());
|
||||||
current_type_ = context_manager_.AddValue(info::type::AbstractType(utils::AbstractTypeModifier::Abstract,
|
current_type_ = context_manager_.AddValue(info::type::AbstractType(utils::AbstractTypeModifier::Abstract,
|
||||||
parameter.type,
|
parameter->type,
|
||||||
requirements),
|
requirements),
|
||||||
utils::ValueType::Tmp);
|
utils::ValueType::Tmp);
|
||||||
if (!context_manager_.DefineLocalType(parameter.type, current_type_)) {
|
if (!context_manager_.DefineLocalType(parameter->type, current_type_)) {
|
||||||
error_handling::HandleTypecheckError("Can't define function parameter type: abstract type redefinition", node->base);
|
error_handling::HandleTypecheckError("Can't define function parameter type: abstract type redefinition", node->base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < node->definition->arguments.size(); ++i) {
|
for (size_t i = 0; i < node->definition->arguments.size(); ++i) {
|
||||||
Visitor::Visit(*declaration.argument_types[i]);
|
Visitor::Visit(declaration->type->types[i]);
|
||||||
current_type_ = context_manager_.ToModifiedValue(current_type_, utils::ValueType::Const); // TODO: var function arguments??
|
current_type_ = context_manager_.ToModifiedValue(current_type_, utils::ValueType::Const); // TODO: var function arguments??
|
||||||
if (!context_manager_.DefineVariable(node->definition->arguments[i], current_type_)) { // TODO: watch to reference
|
if (!context_manager_.DefineVariable(node->definition->arguments[i], current_type_)) { // TODO: watch to reference
|
||||||
error_handling::HandleTypecheckError("Can't define function argument variable: name redefinition", node->base);
|
error_handling::HandleTypecheckError("Can't define function argument variable: name redefinition", node->base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Visitor::Visit(*declaration.argument_types.back());
|
Visitor::Visit(declaration->type->types.back());
|
||||||
utils::IdType return_type = current_type_;
|
utils::IdType return_type = current_type_;
|
||||||
|
|
||||||
Visitor::Visit(node->value);
|
Visitor::Visit(node->value);
|
||||||
|
|
@ -191,6 +246,7 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
context_manager_.ExitContext();
|
context_manager_.ExitContext();
|
||||||
|
|
||||||
current_type_ = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp);
|
current_type_ = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp);
|
||||||
is_in_statement_ = false;
|
is_in_statement_ = false;
|
||||||
|
|
||||||
|
|
@ -209,7 +265,7 @@ void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) {
|
||||||
is_in_statement_ = true;
|
is_in_statement_ = true;
|
||||||
|
|
||||||
std::vector<utils::IdType> requirements =
|
std::vector<utils::IdType> requirements =
|
||||||
global_info_.GetAnnotatedTypeTypeclasses(node->type.get());
|
global_info_.GetAnnotatedTypeTypeclassesVector(node->type.get());
|
||||||
current_type_ = context_manager_.AddValue(info::type::AbstractType(node->modifier, node->type->type, requirements),
|
current_type_ = context_manager_.AddValue(info::type::AbstractType(node->modifier, node->type->type, requirements),
|
||||||
utils::ValueType::Tmp);
|
utils::ValueType::Tmp);
|
||||||
if (!context_manager_.DefineLocalType(node->type->type, current_type_)) {
|
if (!context_manager_.DefineLocalType(node->type->type, current_type_)) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue