mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-05 22:48:42 +00:00
fixes, build_visitor TupleType and VariantType fix
This commit is contained in:
parent
692f7ea3ec
commit
b723fd6a65
12 changed files with 321 additions and 241 deletions
|
|
@ -20,7 +20,7 @@ add_executable(lang_interpreter src/main.cpp
|
|||
src/types.cpp
|
||||
src/values.cpp
|
||||
src/global_info.cpp
|
||||
include/definitions.hpp
|
||||
src/typeclass_graph.cpp
|
||||
src/visitor.cpp
|
||||
src/build_visitor.cpp
|
||||
src/print_visitor.cpp
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ private:
|
|||
return true;
|
||||
}
|
||||
|
||||
if (variables_.count(name) > 0) {
|
||||
if (variables_.count(name) != 0) {
|
||||
return false;
|
||||
}
|
||||
variables_[name] = value_id;
|
||||
|
|
@ -140,7 +140,7 @@ private:
|
|||
}
|
||||
|
||||
bool DefineLocalType(const std::string& name, utils::IdType type_id) {
|
||||
if (local_types_.count(name) > 0) {
|
||||
if (local_types_.count(name) != 0) {
|
||||
return false;
|
||||
}
|
||||
local_types_[name] = type_id;
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ struct AnyType {
|
|||
interpreter::tokens::AnyType* value;
|
||||
utils::ClassModifier modifier;
|
||||
|
||||
utils::IdType parent_namespace;
|
||||
utils::IdType parent_namespace = 0;
|
||||
};
|
||||
|
||||
struct Type {
|
||||
|
|
@ -57,8 +57,8 @@ struct Type {
|
|||
|
||||
struct Constructor {
|
||||
std::string name;
|
||||
size_t order;
|
||||
utils::IdType type_id;
|
||||
std::optional<size_t> order; // no order for tuple types
|
||||
utils::IdType type_id = 0;
|
||||
std::optional<interpreter::tokens::TupleType*> constructor_tuple_node;
|
||||
};
|
||||
|
||||
|
|
@ -83,9 +83,9 @@ struct Typeclass {
|
|||
std::vector<Parameter> parameters;
|
||||
interpreter::tokens::TypeclassDefinitionStatement* node;
|
||||
|
||||
utils::IdType parent_namespace;
|
||||
utils::IdType parent_namespace = 0;
|
||||
|
||||
utils::IdType graph_id_; // TODO: make safe??
|
||||
utils::IdType graph_id_ = 0; // TODO: make safe??
|
||||
};
|
||||
|
||||
struct Import {
|
||||
|
|
@ -101,7 +101,7 @@ struct Namespace {
|
|||
std::unordered_map<std::string, utils::IdType> var_namespaces;
|
||||
std::unordered_map<std::string, utils::IdType> const_namespaces;
|
||||
|
||||
utils::IdType parent_namespace;
|
||||
utils::IdType parent_namespace = 0;
|
||||
|
||||
utils::ClassInternalsModifier modifier = utils::ClassInternalsModifier::Static;
|
||||
std::string type_name;
|
||||
|
|
|
|||
|
|
@ -32,146 +32,32 @@ public:
|
|||
interpreter::tokens::TypeclassDefinitionStatement* definition,
|
||||
const std::vector<std::string>& dependencies, // TODO: parameters
|
||||
const std::vector<std::pair<std::string, std::pair<utils::ClassInternalsModifier, interpreter::tokens::FunctionDeclaration*>>>& function_declarations,
|
||||
const std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>>& function_definitions) {
|
||||
for (auto& method : function_declarations) {
|
||||
if (method_to_typeclass_.count(method.first) != 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
const std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>>& function_definitions);
|
||||
|
||||
is_calculated_ = false;
|
||||
|
||||
typeclasses_.emplace_back();
|
||||
TypeclassVertex& typeclass = typeclasses_.back();
|
||||
typeclass.name = name;
|
||||
typeclass.definition = definition;
|
||||
|
||||
for (auto& dependency : dependencies) {
|
||||
typeclass.dependencies.insert(dependency);
|
||||
}
|
||||
|
||||
for (auto& method : function_declarations) {
|
||||
FunctionInfo function_info;
|
||||
function_info.modifier = method.second.first;
|
||||
function_info.declaration = method.second.second;
|
||||
|
||||
typeclass.functions[method.first] = function_info;
|
||||
|
||||
method_to_typeclass_[method.first] = typeclasses_.size();
|
||||
}
|
||||
name_to_typeclass_[name] = typeclasses_.size() - 1;
|
||||
|
||||
for (auto& method : function_definitions) {
|
||||
typeclass.functions[method.first].definition = method.second;
|
||||
}
|
||||
|
||||
return typeclasses_.size() - 1;
|
||||
}
|
||||
|
||||
std::optional<utils::IdType> FindFunctionTypeclass(const std::string& name) {
|
||||
auto function_iter = method_to_typeclass_.find(name);
|
||||
if (function_iter == method_to_typeclass_.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return function_iter->second;
|
||||
}
|
||||
std::optional<utils::IdType> FindFunctionTypeclass(const std::string& name);
|
||||
|
||||
bool IsFunctionInTypeclass(const std::string& name, utils::IdType typeclass_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];
|
||||
}
|
||||
std::optional<utils::IdType> typeclass_id);
|
||||
|
||||
const TypeclassVertex& GetTypeclass(utils::IdType typeclass_id) { // check, if calculated ??
|
||||
return typeclasses_.at(typeclass_id);
|
||||
}
|
||||
|
||||
// cache ??
|
||||
std::vector<utils::IdType> GetTypeclassDependencies(utils::IdType id) {
|
||||
std::vector<utils::IdType> dependencies;
|
||||
|
||||
dependencies.reserve(typeclasses_.at(id).dependencies.size());
|
||||
for (auto& dependency : typeclasses_[id].dependencies) {
|
||||
dependencies.push_back(name_to_typeclass_[dependency]);
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
std::vector<utils::IdType> GetTypeclassDependencies(utils::IdType id);
|
||||
|
||||
// cache ??
|
||||
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});
|
||||
}
|
||||
|
||||
return functions;
|
||||
}
|
||||
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo*>> GetTypeclassFunctions(utils::IdType id);
|
||||
|
||||
bool IsCalculated() {
|
||||
return is_calculated_;
|
||||
}
|
||||
|
||||
bool CalculateGraph() {
|
||||
if (is_calculated_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::vector<size_t>> edges(typeclasses_.size());
|
||||
|
||||
for (size_t i = 0; i < typeclasses_.size(); ++i) {
|
||||
edges[i].reserve(typeclasses_[i].dependencies.size());
|
||||
for (auto& dependency :typeclasses_[i].dependencies) {
|
||||
auto dependency_iter = name_to_typeclass_.find(dependency);
|
||||
|
||||
if (dependency_iter == name_to_typeclass_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
edges[i].push_back(dependency_iter->second);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<size_t> sorted_verticles = utils::BackTopSort(edges);
|
||||
std::reverse(sorted_verticles.begin(), sorted_verticles.end());
|
||||
|
||||
for (auto& id : sorted_verticles) {
|
||||
for (auto& dependency : typeclasses_[id].dependencies) {
|
||||
for (auto& method : typeclasses_[name_to_typeclass_[dependency]].functions) {
|
||||
auto function_iter = typeclasses_[id].functions.find(method.first);
|
||||
if (function_iter == typeclasses_[id].functions.end()) {
|
||||
typeclasses_[id].functions[method.first] = method.second;
|
||||
} else {
|
||||
if (!function_iter->second.definition.has_value()) {
|
||||
function_iter->second.definition = method.second.definition;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto& inherited_dependency : typeclasses_[name_to_typeclass_[dependency]].dependencies) {
|
||||
typeclasses_[id].dependencies.insert(inherited_dependency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is_calculated_ = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool CalculateGraph();
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, utils::IdType> method_to_typeclass_;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <unordered_map>
|
||||
|
||||
// for clangd
|
||||
#include "error_handling.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace info::type {
|
||||
|
|
@ -24,8 +25,8 @@ public:
|
|||
const std::vector<utils::IdType>& requirement_graph_ids)
|
||||
: modifier_(modifier),
|
||||
name_(name) {
|
||||
for (auto& typeclass : requirement_graph_ids) {
|
||||
requirement_graph_ids_.insert(typeclass);
|
||||
for (auto& requirement_graph_id : requirement_graph_ids) {
|
||||
requirement_graph_ids_.insert(requirement_graph_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -228,7 +228,8 @@ private:
|
|||
std::vector<size_t> ranks_;
|
||||
};
|
||||
|
||||
static void BackVisitDfs(size_t id,
|
||||
// move to .cpp ??
|
||||
inline void BackVisitDfs(size_t id,
|
||||
std::vector<size_t>& verticles,
|
||||
std::vector<size_t>& marks,
|
||||
const std::vector<std::vector<size_t>>& edges,
|
||||
|
|
@ -245,7 +246,8 @@ static void BackVisitDfs(size_t id,
|
|||
}
|
||||
}
|
||||
|
||||
static std::vector<size_t> BackTopSort(const std::vector<std::vector<size_t>>& edges_) {
|
||||
// move to .cpp ??
|
||||
inline std::vector<size_t> BackTopSort(const std::vector<std::vector<size_t>>& edges_) {
|
||||
std::vector<size_t> sorted_verticles;
|
||||
std::vector<size_t> marks(edges_.size(), 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -1292,32 +1292,32 @@ void BuildVisitor::Visit(TupleType* node) {
|
|||
|
||||
auto parse_node = current_node_;
|
||||
|
||||
size_t current_node_n = 0;
|
||||
size_t current_child = 0;
|
||||
|
||||
current_node_ = parse_node.NthNamedChild(current_node_n);
|
||||
current_node_ = parse_node.NthNamedChild(current_child);
|
||||
|
||||
if (current_node_.GetType() == parser::tokens::Constructor) {
|
||||
if (parse_node.NthChild(0).GetValue() != "&") {
|
||||
node->type = current_node_.GetValue();
|
||||
|
||||
++current_node_n;
|
||||
current_node_ = parse_node.NthNamedChild(current_node_n);
|
||||
++current_child;
|
||||
current_node_ = parse_node.NthNamedChild(current_child);
|
||||
}
|
||||
|
||||
while (current_node_n < parse_node.NamedChildCount()) {
|
||||
while (current_child < parse_node.NamedChildCount()) {
|
||||
node->entities.emplace_back();
|
||||
|
||||
if (current_node_.GetType() == parser::tokens::NameIdentifier) {
|
||||
node->entities.back().first = current_node_.GetValue();
|
||||
|
||||
++current_node_n;
|
||||
current_node_ = parse_node.NthNamedChild(current_node_n);
|
||||
++current_child;
|
||||
current_node_ = parse_node.NthNamedChild(current_child);
|
||||
}
|
||||
|
||||
node->entities.back().second = std::make_unique<ExtendedScopedAnyType>();
|
||||
Visit(node->entities.back().second.get());
|
||||
|
||||
++current_node_n;
|
||||
current_node_ = parse_node.NthNamedChild(current_node_n);
|
||||
++current_child;
|
||||
current_node_ = parse_node.NthNamedChild(current_child);
|
||||
}
|
||||
|
||||
current_node_ = parse_node;
|
||||
|
|
@ -1328,33 +1328,31 @@ void BuildVisitor::Visit(VariantType* node) {
|
|||
|
||||
auto parse_node = current_node_;
|
||||
|
||||
size_t current_node_n = 0;
|
||||
size_t excluded_child_count = 0;
|
||||
|
||||
current_node_ = parse_node.NthNamedChild(current_node_n);
|
||||
size_t child_count = parse_node.NamedChildCount();
|
||||
|
||||
if (current_node_.GetType() == parser::tokens::Constructor) {
|
||||
node->type = current_node_.GetValue();
|
||||
if (parse_node.NthChild(0).GetValue() != "|") {
|
||||
node->type = parse_node.NthNamedChild(0).GetValue();
|
||||
|
||||
++current_node_n;
|
||||
current_node_ = parse_node.NthNamedChild(current_node_n);
|
||||
++excluded_child_count;
|
||||
}
|
||||
|
||||
while (current_node_n < parse_node.NamedChildCount()) {
|
||||
|
||||
node->constructors.resize(child_count - excluded_child_count);
|
||||
for (size_t i = 0; i < node->constructors.size(); ++i) {
|
||||
current_node_ = parse_node.NthNamedChild(i + excluded_child_count);
|
||||
|
||||
std::string current_node_type = current_node_.GetType();
|
||||
|
||||
node->constructors.emplace_back();
|
||||
|
||||
if (current_node_type == parser::tokens::Constructor) {
|
||||
node->constructors.back() = current_node_.GetValue();
|
||||
node->constructors[i] = current_node_.GetValue();
|
||||
} else if (current_node_type == parser::tokens::TupleType) {
|
||||
node->constructors.back() = std::make_unique<TupleType>();
|
||||
Visit(std::get<std::unique_ptr<TupleType>>(node->constructors.back()).get());
|
||||
node->constructors[i] = std::make_unique<TupleType>();
|
||||
Visit(std::get<std::unique_ptr<TupleType>>(node->constructors[i]).get());
|
||||
} else {
|
||||
// error
|
||||
}
|
||||
|
||||
++current_node_n;
|
||||
current_node_ = parse_node.NthNamedChild(current_node_n);
|
||||
}
|
||||
|
||||
current_node_ = parse_node;
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ void ExecuteVisitor::Visit(PartitionStatement* node) {
|
|||
void ExecuteVisitor::Visit(TypeConstructorPatternParameter* node) {} // handled in TypeConstructorPattern
|
||||
|
||||
// TODO
|
||||
// TODO: tuples
|
||||
// TODO: non-variant constructor patterns
|
||||
void ExecuteVisitor::Visit(TypeConstructorPattern* node) {
|
||||
if (!node->constructor->constructor_id_.has_value()) { // checked in typeckeck visitor ??
|
||||
|
|
@ -475,7 +476,7 @@ void ExecuteVisitor::Visit(ReturnExpression* node) {
|
|||
|
||||
void ExecuteVisitor::Visit(TypeConstructorParameter* node) {} // handled in TypeConstructor
|
||||
|
||||
|
||||
// TODO: variants, etc.
|
||||
void ExecuteVisitor::Visit(TypeConstructor* node) {
|
||||
// TODO: support for non-tuples
|
||||
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields;
|
||||
|
|
@ -493,6 +494,10 @@ void ExecuteVisitor::Visit(TypeConstructor* node) {
|
|||
current_value_ = context_manager_.AddValue<info::value::TupleValue>(
|
||||
info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()),
|
||||
utils::ValueType::Tmp);
|
||||
|
||||
// if (constructor_info.order.has_value()) {
|
||||
// // TODO: construct variant value
|
||||
// }
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
|
|
|||
|
|
@ -167,42 +167,56 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type,
|
|||
|
||||
definition::Type& moved_type_info = global_info_.types_.back();
|
||||
|
||||
// TODO: constructors for tuple types, function types (??), array types (??), ...
|
||||
if (!std::holds_alternative<definition::AnyType>(moved_type_info.type)) {
|
||||
error_handling::HandleInternalError("Not AnyType constructor search is not implemented yet",
|
||||
"GlobalInfo.NamespaceVisitor.AddType");
|
||||
}
|
||||
|
||||
if (std::holds_alternative<definition::AnyType>(moved_type_info.type)) {
|
||||
definition::AnyType& any_type_info = std::get<definition::AnyType>(moved_type_info.type);
|
||||
if (std::holds_alternative<std::unique_ptr<interpreter::tokens::VariantType>>(*any_type_info.value)) {
|
||||
interpreter::tokens::VariantType& variant_type_info = *std::get<std::unique_ptr<interpreter::tokens::VariantType>>(*any_type_info.value);
|
||||
for (size_t i = 0; i < variant_type_info.constructors.size(); ++i) {
|
||||
std::string constructor_name;
|
||||
definition::Constructor constructor_info;
|
||||
definition::AnyType& any_type_info = std::get<definition::AnyType>(moved_type_info.type);
|
||||
if (std::holds_alternative<std::unique_ptr<interpreter::tokens::VariantType>>(*any_type_info.value)) {
|
||||
interpreter::tokens::VariantType& variant_type_info = *std::get<std::unique_ptr<interpreter::tokens::VariantType>>(*any_type_info.value);
|
||||
for (size_t i = 0; i < variant_type_info.constructors.size(); ++i) {
|
||||
std::string constructor_name;
|
||||
definition::Constructor constructor_info;
|
||||
|
||||
constructor_info.type_id = id;
|
||||
constructor_info.order = i;
|
||||
constructor_info.type_id = id;
|
||||
constructor_info.order = i;
|
||||
|
||||
if (std::holds_alternative<interpreter::tokens::Constructor>(variant_type_info.constructors[i])) {
|
||||
constructor_name = std::get<interpreter::tokens::Constructor>(variant_type_info.constructors[i]);
|
||||
} else if (std::holds_alternative<
|
||||
std::unique_ptr<interpreter::tokens::TupleType>>(variant_type_info.constructors[i])) {
|
||||
constructor_info.constructor_tuple_node =
|
||||
std::get<std::unique_ptr<interpreter::tokens::TupleType>>(variant_type_info.constructors[i]).get();
|
||||
if (std::holds_alternative<interpreter::tokens::Constructor>(variant_type_info.constructors[i])) {
|
||||
constructor_name = std::get<interpreter::tokens::Constructor>(variant_type_info.constructors[i]);
|
||||
} else if (std::holds_alternative<
|
||||
std::unique_ptr<interpreter::tokens::TupleType>>(variant_type_info.constructors[i])) {
|
||||
constructor_info.constructor_tuple_node =
|
||||
std::get<std::unique_ptr<interpreter::tokens::TupleType>>(variant_type_info.constructors[i]).get();
|
||||
|
||||
auto maybe_constructor_name = constructor_info.constructor_tuple_node.value()->type;
|
||||
auto maybe_constructor_name = constructor_info.constructor_tuple_node.value()->type;
|
||||
|
||||
if (maybe_constructor_name.has_value()) {
|
||||
constructor_name = maybe_constructor_name.value();
|
||||
} else {
|
||||
constructor_name = type;
|
||||
}
|
||||
if (maybe_constructor_name.has_value()) {
|
||||
constructor_name = maybe_constructor_name.value();
|
||||
} else {
|
||||
// error
|
||||
constructor_name = type;
|
||||
}
|
||||
|
||||
constructor_info.name = constructor_name;
|
||||
|
||||
AddConstructor(constructor_name, std::move(constructor_info), base_node);
|
||||
} else {
|
||||
error_handling::HandleInternalError("Unexprected VariantType constructor node type",
|
||||
"GlobalInfo.NamespaceVisitor.AddType");
|
||||
}
|
||||
|
||||
constructor_info.name = constructor_name;
|
||||
|
||||
AddConstructor(constructor_name, std::move(constructor_info), base_node);
|
||||
}
|
||||
} else if (std::holds_alternative<std::unique_ptr<interpreter::tokens::TupleType>>(*any_type_info.value)) {
|
||||
definition::Constructor constructor_info;
|
||||
constructor_info.type_id = id;
|
||||
// constructor_info.order = std::nullopt;
|
||||
constructor_info.name = type;
|
||||
constructor_info.constructor_tuple_node = std::get<std::unique_ptr<interpreter::tokens::TupleType>>(*any_type_info.value).get();
|
||||
|
||||
AddConstructor(type, std::move(constructor_info), base_node);
|
||||
} else {
|
||||
// TODO: constructors for function types (??), array types (??), ...
|
||||
error_handling::HandleInternalError("Not VariantType constructor search is not implemented yet",
|
||||
"GlobalInfo.NamespaceVisitor.AddType");
|
||||
}
|
||||
|
||||
return id;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include <bits/types/error_t.h>
|
||||
#include <optional>
|
||||
|
||||
// for clangd
|
||||
|
|
@ -26,6 +27,7 @@ void LinkSymbolsVisitor::Visit(Namespace* node) {
|
|||
if (maybe_type.has_value()) {
|
||||
node->link_type_id_ = maybe_type.value();
|
||||
}
|
||||
|
||||
if (maybe_typeclass.has_value()) {
|
||||
node->link_typeclass_id_ = maybe_typeclass.value();
|
||||
if (!namespace_visitor_.IsInGlobalNamespace()) {
|
||||
|
|
|
|||
|
|
@ -36,10 +36,12 @@ void TypeCheckVisitor::Visit(Namespace* node) {
|
|||
if (node->link_typeclass_id_.has_value()) {
|
||||
utils::IdType graph_id = global_info_.GetTypeclassInfo(node->link_typeclass_id_.value()).graph_id_;
|
||||
|
||||
std::vector<utils::IdType> requirements = typeclass_graph_.GetTypeclassDependencies(graph_id);
|
||||
requirements.push_back(graph_id);
|
||||
std::vector<utils::IdType> requirement_graph_ids = typeclass_graph_.GetTypeclassDependencies(graph_id);
|
||||
requirement_graph_ids.push_back(graph_id);
|
||||
utils::IdType abstract_type = context_manager_.AddValue(
|
||||
info::type::AbstractType(utils::AbstractTypeModifier::Abstract, node->type, requirements),
|
||||
info::type::AbstractType(utils::AbstractTypeModifier::Abstract,
|
||||
node->type,
|
||||
requirement_graph_ids),
|
||||
ClassInternalsModifierToValueType(node->modifier));
|
||||
|
||||
if (node->modifier != utils::ClassInternalsModifier::Static) {
|
||||
|
|
@ -48,29 +50,42 @@ void TypeCheckVisitor::Visit(Namespace* node) {
|
|||
} else {
|
||||
context_manager_.EnterContext();
|
||||
}
|
||||
context_manager_.DefineLocalType(node->type, abstract_type);
|
||||
|
||||
// including namespace typeclass
|
||||
// define typeclasses local types as namespace typeclass
|
||||
for (auto& requirement_graph_id : requirement_graph_ids) {
|
||||
context_manager_.DefineLocalType(typeclass_graph_.GetTypeclass(requirement_graph_id).name, abstract_type);
|
||||
}
|
||||
} else if (node->link_type_id_.has_value()) {
|
||||
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(node->link_type_id_.value());
|
||||
|
||||
if (!maybe_type_info.has_value()) {
|
||||
error_handling::HandleTypecheckError("Namespace type is not AnyType", node->base);
|
||||
}
|
||||
|
||||
info::definition::AnyType* type_info = maybe_type_info.value();
|
||||
|
||||
Visitor::Visit(*type_info->value);
|
||||
utils::IdType type = context_manager_.AddValue(
|
||||
info::type::DefinedType(node->link_type_id_.value(),
|
||||
current_type_,
|
||||
type_info->modifier,
|
||||
context_manager_.GetValueManager()),
|
||||
ClassInternalsModifierToValueType(node->modifier));
|
||||
|
||||
if (node->modifier != utils::ClassInternalsModifier::Static) {
|
||||
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(node->link_type_id_.value());
|
||||
|
||||
if (!maybe_type_info.has_value()) {
|
||||
error_handling::HandleTypecheckError("Namespace type is not AnyType", node->base);
|
||||
}
|
||||
|
||||
Visitor::Visit(*maybe_type_info.value()->value); // handle error?
|
||||
|
||||
context_manager_.EnterVariableContext(
|
||||
utils::ClassInternalVarName,
|
||||
context_manager_.AddValue(
|
||||
info::type::DefinedType(node->link_type_id_.value(),
|
||||
current_type_,
|
||||
maybe_type_info.value()->modifier,
|
||||
context_manager_.GetValueManager()),
|
||||
ClassInternalsModifierToValueType(node->modifier)));
|
||||
context_manager_.EnterVariableContext(utils::ClassInternalVarName, type);
|
||||
} else {
|
||||
context_manager_.EnterContext();
|
||||
}
|
||||
|
||||
// better decision ??
|
||||
// define typeclasses local types as namespace type
|
||||
auto typeclass_graph_ids = global_info_.GetAnnotatedTypeTypeclassesVector(type_info->type.node);
|
||||
for (auto& typeclass_graph_id : typeclass_graph_ids) {
|
||||
context_manager_.DefineLocalType(typeclass_graph_.GetTypeclass(typeclass_graph_id).name, type);
|
||||
}
|
||||
|
||||
if (type_namespaces_.count(node->link_type_id_.value()) != 0) {
|
||||
error_handling::HandleTypecheckError("Namespaces of one type are one in another", node->base);
|
||||
}
|
||||
|
|
@ -344,6 +359,7 @@ void TypeCheckVisitor::Visit(AnyAnnotatedType* node) {
|
|||
void TypeCheckVisitor::Visit(TypeConstructorPatternParameter* node) {} // Handled in TypeConstructorPattern
|
||||
|
||||
// TODO
|
||||
// TODO: check for tuples
|
||||
void TypeCheckVisitor::Visit(TypeConstructorPattern* node) { // TODO: match named constructor
|
||||
if (!node->constructor->constructor_id_.has_value()) {
|
||||
error_handling::HandleTypecheckError("Type constructor pattern constructor name not found", node->base);
|
||||
|
|
@ -815,6 +831,7 @@ void TypeCheckVisitor::Visit(ReturnExpression* node) {
|
|||
|
||||
void TypeCheckVisitor::Visit(TypeConstructorParameter* node) {} // Handeled in TypeConstructor visit
|
||||
|
||||
// TODO: check for tuples
|
||||
void TypeCheckVisitor::Visit(TypeConstructor* node) {
|
||||
if (!node->constructor->constructor_id_.has_value()) {
|
||||
error_handling::HandleTypecheckError("Type constructor name not found", node->base);
|
||||
|
|
@ -884,10 +901,15 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) {
|
|||
std::optional<info::type::VariantType*> maybe_variant_type =
|
||||
context_manager_.GetValue<info::type::VariantType>(current_type_);
|
||||
|
||||
if (maybe_type_info.has_value()) {
|
||||
maybe_variant_type.value()->SetCurrentConstructor(constructor_info.order);
|
||||
if (maybe_variant_type.has_value()) {
|
||||
if (!constructor_info.order.has_value()) {
|
||||
error_handling::HandleInternalError("No order found in constructor of VariantType", "TypeCheckVisitor.TypeConstructor");
|
||||
}
|
||||
maybe_variant_type.value()->SetCurrentConstructor(constructor_info.order.value());
|
||||
}
|
||||
|
||||
// if it is tuple, order not required
|
||||
|
||||
current_type_ = TypeInContext(current_type_, context);
|
||||
|
||||
node->base.type_ = current_type_;
|
||||
|
|
@ -1405,7 +1427,7 @@ std::optional<FunctionDeclaration*>
|
|||
}
|
||||
|
||||
// TODO: internal types ??
|
||||
// TODO: abstract types, typeclasses
|
||||
// TODO: handle abstract defined types ??
|
||||
std::optional<FunctionDeclaration*>
|
||||
TypeCheckVisitor::FindTypeFunctionAndUpdate(FunctionCallExpression* node,
|
||||
TypeExpression* type_node,
|
||||
|
|
@ -1540,26 +1562,30 @@ std::optional<FunctionDeclaration*>
|
|||
|
||||
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);
|
||||
return std::nullopt;
|
||||
// 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;
|
||||
if (!abstract_type_info->HasTypeclass(maybe_typeclass_graph_id.value())) {
|
||||
error_handling::HandleTypecheckError("Function typeclass not pesent in type typeclasses list (abstract type)", node->base);
|
||||
}
|
||||
|
||||
if (!maybe_typeclass_function_info.has_value()) {
|
||||
error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (abstract type)",
|
||||
"TypeCheckVisitor.FindAbstractTypeTypeclassFunctionAndUpdate");
|
||||
}
|
||||
|
||||
// TODO: check that const functions not called on var expressions
|
||||
if ((maybe_typeclass_function_info.value()->modifier != utils::ClassInternalsModifier::Static) != is_method) {
|
||||
error_handling::HandleTypecheckError("Typeclass function has wrong modifier (abstract type)", node->base);
|
||||
}
|
||||
|
||||
node->typeclass_graph_id_ = maybe_typeclass_graph_id;
|
||||
maybe_function_declaration = maybe_typeclass_function_info.value()->declaration;
|
||||
|
||||
return maybe_function_declaration;
|
||||
}
|
||||
|
||||
|
|
@ -1571,27 +1597,31 @@ std::optional<FunctionDeclaration*>
|
|||
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;
|
||||
}
|
||||
if (!maybe_typeclass_graph_id.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
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()) {
|
||||
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;
|
||||
|
||||
return maybe_function_declaration;
|
||||
}
|
||||
|
||||
|
|
|
|||
142
src/typeclass_graph.cpp
Normal file
142
src/typeclass_graph.cpp
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
// for clangd
|
||||
#include "../include/typeclass_graph.hpp"
|
||||
|
||||
namespace info {
|
||||
|
||||
std::optional<utils::IdType> TypeclassGraph::AddTypeclass(
|
||||
const std::string& name,
|
||||
interpreter::tokens::TypeclassDefinitionStatement* definition,
|
||||
const std::vector<std::string>& dependencies, // TODO: parameters
|
||||
const std::vector<std::pair<std::string, std::pair<utils::ClassInternalsModifier, interpreter::tokens::FunctionDeclaration*>>>& function_declarations,
|
||||
const std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>>& function_definitions) {
|
||||
for (auto& method : function_declarations) {
|
||||
if (method_to_typeclass_.count(method.first) != 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
is_calculated_ = false;
|
||||
|
||||
utils::IdType id = typeclasses_.size();
|
||||
|
||||
typeclasses_.emplace_back();
|
||||
TypeclassVertex& typeclass = typeclasses_.back();
|
||||
typeclass.name = name;
|
||||
typeclass.definition = definition;
|
||||
|
||||
for (auto& dependency : dependencies) {
|
||||
typeclass.dependencies.insert(dependency);
|
||||
}
|
||||
|
||||
for (auto& method : function_declarations) {
|
||||
FunctionInfo function_info;
|
||||
function_info.modifier = method.second.first;
|
||||
function_info.declaration = method.second.second;
|
||||
|
||||
typeclass.functions[method.first] = function_info;
|
||||
|
||||
method_to_typeclass_[method.first] = id;
|
||||
}
|
||||
name_to_typeclass_[name] = id;
|
||||
|
||||
for (auto& method : function_definitions) {
|
||||
typeclass.functions[method.first].definition = method.second;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
std::optional<utils::IdType> TypeclassGraph::FindFunctionTypeclass(const std::string& name) {
|
||||
auto function_iter = method_to_typeclass_.find(name);
|
||||
if (function_iter == method_to_typeclass_.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return function_iter->second;
|
||||
}
|
||||
|
||||
std::optional<TypeclassGraph::FunctionInfo*> TypeclassGraph::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];
|
||||
}
|
||||
|
||||
// cache ??
|
||||
std::vector<utils::IdType> TypeclassGraph::GetTypeclassDependencies(utils::IdType id) {
|
||||
std::vector<utils::IdType> dependencies;
|
||||
|
||||
dependencies.reserve(typeclasses_.at(id).dependencies.size());
|
||||
for (auto& dependency : typeclasses_[id].dependencies) {
|
||||
dependencies.push_back(name_to_typeclass_[dependency]);
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
// cache ??
|
||||
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo*>> TypeclassGraph::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});
|
||||
}
|
||||
|
||||
return functions;
|
||||
}
|
||||
|
||||
bool TypeclassGraph::CalculateGraph() {
|
||||
if (is_calculated_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::vector<size_t>> edges(typeclasses_.size());
|
||||
|
||||
for (size_t i = 0; i < typeclasses_.size(); ++i) {
|
||||
edges[i].reserve(typeclasses_[i].dependencies.size());
|
||||
for (auto& dependency :typeclasses_[i].dependencies) {
|
||||
auto dependency_iter = name_to_typeclass_.find(dependency);
|
||||
|
||||
if (dependency_iter == name_to_typeclass_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
edges[i].push_back(dependency_iter->second);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<size_t> sorted_verticles = utils::BackTopSort(edges);
|
||||
std::reverse(sorted_verticles.begin(), sorted_verticles.end());
|
||||
|
||||
for (auto& id : sorted_verticles) {
|
||||
for (auto& dependency : typeclasses_[id].dependencies) {
|
||||
for (auto& method : typeclasses_[name_to_typeclass_[dependency]].functions) {
|
||||
auto function_iter = typeclasses_[id].functions.find(method.first);
|
||||
if (function_iter == typeclasses_[id].functions.end()) {
|
||||
typeclasses_[id].functions[method.first] = method.second;
|
||||
} else {
|
||||
if (!function_iter->second.definition.has_value()) {
|
||||
function_iter->second.definition = method.second.definition;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto& inherited_dependency : typeclasses_[name_to_typeclass_[dependency]].dependencies) {
|
||||
typeclasses_[id].dependencies.insert(inherited_dependency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is_calculated_ = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace info
|
||||
Loading…
Add table
Add a link
Reference in a new issue