mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-06 06:58:45 +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/types.cpp
|
||||||
src/values.cpp
|
src/values.cpp
|
||||||
src/global_info.cpp
|
src/global_info.cpp
|
||||||
include/definitions.hpp
|
src/typeclass_graph.cpp
|
||||||
src/visitor.cpp
|
src/visitor.cpp
|
||||||
src/build_visitor.cpp
|
src/build_visitor.cpp
|
||||||
src/print_visitor.cpp
|
src/print_visitor.cpp
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ private:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (variables_.count(name) > 0) {
|
if (variables_.count(name) != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
variables_[name] = value_id;
|
variables_[name] = value_id;
|
||||||
|
|
@ -140,7 +140,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DefineLocalType(const std::string& name, utils::IdType type_id) {
|
bool DefineLocalType(const std::string& name, utils::IdType type_id) {
|
||||||
if (local_types_.count(name) > 0) {
|
if (local_types_.count(name) != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
local_types_[name] = type_id;
|
local_types_[name] = type_id;
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ struct AnyType {
|
||||||
interpreter::tokens::AnyType* value;
|
interpreter::tokens::AnyType* value;
|
||||||
utils::ClassModifier modifier;
|
utils::ClassModifier modifier;
|
||||||
|
|
||||||
utils::IdType parent_namespace;
|
utils::IdType parent_namespace = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Type {
|
struct Type {
|
||||||
|
|
@ -57,8 +57,8 @@ struct Type {
|
||||||
|
|
||||||
struct Constructor {
|
struct Constructor {
|
||||||
std::string name;
|
std::string name;
|
||||||
size_t order;
|
std::optional<size_t> order; // no order for tuple types
|
||||||
utils::IdType type_id;
|
utils::IdType type_id = 0;
|
||||||
std::optional<interpreter::tokens::TupleType*> constructor_tuple_node;
|
std::optional<interpreter::tokens::TupleType*> constructor_tuple_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -83,9 +83,9 @@ struct Typeclass {
|
||||||
std::vector<Parameter> parameters;
|
std::vector<Parameter> parameters;
|
||||||
interpreter::tokens::TypeclassDefinitionStatement* node;
|
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 {
|
struct Import {
|
||||||
|
|
@ -101,7 +101,7 @@ struct Namespace {
|
||||||
std::unordered_map<std::string, utils::IdType> var_namespaces;
|
std::unordered_map<std::string, utils::IdType> var_namespaces;
|
||||||
std::unordered_map<std::string, utils::IdType> const_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;
|
utils::ClassInternalsModifier modifier = utils::ClassInternalsModifier::Static;
|
||||||
std::string type_name;
|
std::string type_name;
|
||||||
|
|
|
||||||
|
|
@ -32,146 +32,32 @@ public:
|
||||||
interpreter::tokens::TypeclassDefinitionStatement* definition,
|
interpreter::tokens::TypeclassDefinitionStatement* definition,
|
||||||
const std::vector<std::string>& dependencies, // TODO: parameters
|
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, std::pair<utils::ClassInternalsModifier, interpreter::tokens::FunctionDeclaration*>>>& function_declarations,
|
||||||
const std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>>& function_definitions) {
|
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;
|
std::optional<utils::IdType> FindFunctionTypeclass(const std::string& name);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsFunctionInTypeclass(const std::string& name, utils::IdType typeclass_id) {
|
bool IsFunctionInTypeclass(const std::string& name, utils::IdType typeclass_id) {
|
||||||
return typeclasses_[typeclass_id].functions.count(name) != 0;
|
return typeclasses_[typeclass_id].functions.count(name) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<FunctionInfo*> GetFunctionInfo(const std::string& name,
|
std::optional<FunctionInfo*> GetFunctionInfo(const std::string& name,
|
||||||
std::optional<utils::IdType> typeclass_id) {
|
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 ??
|
const TypeclassVertex& GetTypeclass(utils::IdType typeclass_id) { // check, if calculated ??
|
||||||
return typeclasses_.at(typeclass_id);
|
return typeclasses_.at(typeclass_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cache ??
|
// cache ??
|
||||||
std::vector<utils::IdType> GetTypeclassDependencies(utils::IdType id) {
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cache ??
|
// cache ??
|
||||||
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo*>> GetTypeclassFunctions(utils::IdType id) {
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsCalculated() {
|
bool IsCalculated() {
|
||||||
return is_calculated_;
|
return is_calculated_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CalculateGraph() {
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, utils::IdType> method_to_typeclass_;
|
std::unordered_map<std::string, utils::IdType> method_to_typeclass_;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
// for clangd
|
// for clangd
|
||||||
|
#include "error_handling.hpp"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
namespace info::type {
|
namespace info::type {
|
||||||
|
|
@ -24,8 +25,8 @@ public:
|
||||||
const std::vector<utils::IdType>& requirement_graph_ids)
|
const std::vector<utils::IdType>& requirement_graph_ids)
|
||||||
: modifier_(modifier),
|
: modifier_(modifier),
|
||||||
name_(name) {
|
name_(name) {
|
||||||
for (auto& typeclass : requirement_graph_ids) {
|
for (auto& requirement_graph_id : requirement_graph_ids) {
|
||||||
requirement_graph_ids_.insert(typeclass);
|
requirement_graph_ids_.insert(requirement_graph_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,8 @@ private:
|
||||||
std::vector<size_t> ranks_;
|
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>& verticles,
|
||||||
std::vector<size_t>& marks,
|
std::vector<size_t>& marks,
|
||||||
const std::vector<std::vector<size_t>>& edges,
|
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> sorted_verticles;
|
||||||
std::vector<size_t> marks(edges_.size(), 0);
|
std::vector<size_t> marks(edges_.size(), 0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1292,32 +1292,32 @@ void BuildVisitor::Visit(TupleType* node) {
|
||||||
|
|
||||||
auto parse_node = current_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();
|
node->type = current_node_.GetValue();
|
||||||
|
|
||||||
++current_node_n;
|
++current_child;
|
||||||
current_node_ = parse_node.NthNamedChild(current_node_n);
|
current_node_ = parse_node.NthNamedChild(current_child);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (current_node_n < parse_node.NamedChildCount()) {
|
while (current_child < parse_node.NamedChildCount()) {
|
||||||
node->entities.emplace_back();
|
node->entities.emplace_back();
|
||||||
|
|
||||||
if (current_node_.GetType() == parser::tokens::NameIdentifier) {
|
if (current_node_.GetType() == parser::tokens::NameIdentifier) {
|
||||||
node->entities.back().first = current_node_.GetValue();
|
node->entities.back().first = current_node_.GetValue();
|
||||||
|
|
||||||
++current_node_n;
|
++current_child;
|
||||||
current_node_ = parse_node.NthNamedChild(current_node_n);
|
current_node_ = parse_node.NthNamedChild(current_child);
|
||||||
}
|
}
|
||||||
|
|
||||||
node->entities.back().second = std::make_unique<ExtendedScopedAnyType>();
|
node->entities.back().second = std::make_unique<ExtendedScopedAnyType>();
|
||||||
Visit(node->entities.back().second.get());
|
Visit(node->entities.back().second.get());
|
||||||
|
|
||||||
++current_node_n;
|
++current_child;
|
||||||
current_node_ = parse_node.NthNamedChild(current_node_n);
|
current_node_ = parse_node.NthNamedChild(current_child);
|
||||||
}
|
}
|
||||||
|
|
||||||
current_node_ = parse_node;
|
current_node_ = parse_node;
|
||||||
|
|
@ -1328,33 +1328,31 @@ void BuildVisitor::Visit(VariantType* node) {
|
||||||
|
|
||||||
auto parse_node = current_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) {
|
if (parse_node.NthChild(0).GetValue() != "|") {
|
||||||
node->type = current_node_.GetValue();
|
node->type = parse_node.NthNamedChild(0).GetValue();
|
||||||
|
|
||||||
++current_node_n;
|
++excluded_child_count;
|
||||||
current_node_ = parse_node.NthNamedChild(current_node_n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
std::string current_node_type = current_node_.GetType();
|
||||||
|
|
||||||
node->constructors.emplace_back();
|
|
||||||
|
|
||||||
if (current_node_type == parser::tokens::Constructor) {
|
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) {
|
} else if (current_node_type == parser::tokens::TupleType) {
|
||||||
node->constructors.back() = std::make_unique<TupleType>();
|
node->constructors[i] = std::make_unique<TupleType>();
|
||||||
Visit(std::get<std::unique_ptr<TupleType>>(node->constructors.back()).get());
|
Visit(std::get<std::unique_ptr<TupleType>>(node->constructors[i]).get());
|
||||||
} else {
|
} else {
|
||||||
// error
|
// error
|
||||||
}
|
}
|
||||||
|
|
||||||
++current_node_n;
|
|
||||||
current_node_ = parse_node.NthNamedChild(current_node_n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
current_node_ = parse_node;
|
current_node_ = parse_node;
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ void ExecuteVisitor::Visit(PartitionStatement* node) {
|
||||||
void ExecuteVisitor::Visit(TypeConstructorPatternParameter* node) {} // handled in TypeConstructorPattern
|
void ExecuteVisitor::Visit(TypeConstructorPatternParameter* node) {} // handled in TypeConstructorPattern
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
// TODO: tuples
|
||||||
// TODO: non-variant constructor patterns
|
// TODO: non-variant constructor patterns
|
||||||
void ExecuteVisitor::Visit(TypeConstructorPattern* node) {
|
void ExecuteVisitor::Visit(TypeConstructorPattern* node) {
|
||||||
if (!node->constructor->constructor_id_.has_value()) { // checked in typeckeck visitor ??
|
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
|
void ExecuteVisitor::Visit(TypeConstructorParameter* node) {} // handled in TypeConstructor
|
||||||
|
|
||||||
|
// TODO: variants, etc.
|
||||||
void ExecuteVisitor::Visit(TypeConstructor* node) {
|
void ExecuteVisitor::Visit(TypeConstructor* node) {
|
||||||
// TODO: support for non-tuples
|
// TODO: support for non-tuples
|
||||||
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields;
|
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>(
|
current_value_ = context_manager_.AddValue<info::value::TupleValue>(
|
||||||
info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()),
|
info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()),
|
||||||
utils::ValueType::Tmp);
|
utils::ValueType::Tmp);
|
||||||
|
|
||||||
|
// if (constructor_info.order.has_value()) {
|
||||||
|
// // TODO: construct variant value
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|
|
||||||
|
|
@ -167,9 +167,11 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type,
|
||||||
|
|
||||||
definition::Type& moved_type_info = global_info_.types_.back();
|
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);
|
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)) {
|
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);
|
interpreter::tokens::VariantType& variant_type_info = *std::get<std::unique_ptr<interpreter::tokens::VariantType>>(*any_type_info.value);
|
||||||
|
|
@ -195,14 +197,26 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type,
|
||||||
constructor_name = type;
|
constructor_name = type;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// error
|
error_handling::HandleInternalError("Unexprected VariantType constructor node type",
|
||||||
|
"GlobalInfo.NamespaceVisitor.AddType");
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor_info.name = constructor_name;
|
constructor_info.name = constructor_name;
|
||||||
|
|
||||||
AddConstructor(constructor_name, std::move(constructor_info), base_node);
|
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;
|
return id;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <bits/types/error_t.h>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
// for clangd
|
// for clangd
|
||||||
|
|
@ -26,6 +27,7 @@ void LinkSymbolsVisitor::Visit(Namespace* node) {
|
||||||
if (maybe_type.has_value()) {
|
if (maybe_type.has_value()) {
|
||||||
node->link_type_id_ = maybe_type.value();
|
node->link_type_id_ = maybe_type.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maybe_typeclass.has_value()) {
|
if (maybe_typeclass.has_value()) {
|
||||||
node->link_typeclass_id_ = maybe_typeclass.value();
|
node->link_typeclass_id_ = maybe_typeclass.value();
|
||||||
if (!namespace_visitor_.IsInGlobalNamespace()) {
|
if (!namespace_visitor_.IsInGlobalNamespace()) {
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,12 @@ void TypeCheckVisitor::Visit(Namespace* node) {
|
||||||
if (node->link_typeclass_id_.has_value()) {
|
if (node->link_typeclass_id_.has_value()) {
|
||||||
utils::IdType graph_id = global_info_.GetTypeclassInfo(node->link_typeclass_id_.value()).graph_id_;
|
utils::IdType graph_id = global_info_.GetTypeclassInfo(node->link_typeclass_id_.value()).graph_id_;
|
||||||
|
|
||||||
std::vector<utils::IdType> requirements = typeclass_graph_.GetTypeclassDependencies(graph_id);
|
std::vector<utils::IdType> requirement_graph_ids = typeclass_graph_.GetTypeclassDependencies(graph_id);
|
||||||
requirements.push_back(graph_id);
|
requirement_graph_ids.push_back(graph_id);
|
||||||
utils::IdType abstract_type = context_manager_.AddValue(
|
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));
|
ClassInternalsModifierToValueType(node->modifier));
|
||||||
|
|
||||||
if (node->modifier != utils::ClassInternalsModifier::Static) {
|
if (node->modifier != utils::ClassInternalsModifier::Static) {
|
||||||
|
|
@ -48,29 +50,42 @@ void TypeCheckVisitor::Visit(Namespace* node) {
|
||||||
} else {
|
} else {
|
||||||
context_manager_.EnterContext();
|
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()) {
|
} else if (node->link_type_id_.has_value()) {
|
||||||
if (node->modifier != utils::ClassInternalsModifier::Static) {
|
|
||||||
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(node->link_type_id_.value());
|
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(node->link_type_id_.value());
|
||||||
|
|
||||||
if (!maybe_type_info.has_value()) {
|
if (!maybe_type_info.has_value()) {
|
||||||
error_handling::HandleTypecheckError("Namespace type is not AnyType", node->base);
|
error_handling::HandleTypecheckError("Namespace type is not AnyType", node->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
Visitor::Visit(*maybe_type_info.value()->value); // handle error?
|
info::definition::AnyType* type_info = maybe_type_info.value();
|
||||||
|
|
||||||
context_manager_.EnterVariableContext(
|
Visitor::Visit(*type_info->value);
|
||||||
utils::ClassInternalVarName,
|
utils::IdType type = context_manager_.AddValue(
|
||||||
context_manager_.AddValue(
|
|
||||||
info::type::DefinedType(node->link_type_id_.value(),
|
info::type::DefinedType(node->link_type_id_.value(),
|
||||||
current_type_,
|
current_type_,
|
||||||
maybe_type_info.value()->modifier,
|
type_info->modifier,
|
||||||
context_manager_.GetValueManager()),
|
context_manager_.GetValueManager()),
|
||||||
ClassInternalsModifierToValueType(node->modifier)));
|
ClassInternalsModifierToValueType(node->modifier));
|
||||||
|
|
||||||
|
if (node->modifier != utils::ClassInternalsModifier::Static) {
|
||||||
|
context_manager_.EnterVariableContext(utils::ClassInternalVarName, type);
|
||||||
} else {
|
} else {
|
||||||
context_manager_.EnterContext();
|
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) {
|
if (type_namespaces_.count(node->link_type_id_.value()) != 0) {
|
||||||
error_handling::HandleTypecheckError("Namespaces of one type are one in another", node->base);
|
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
|
void TypeCheckVisitor::Visit(TypeConstructorPatternParameter* node) {} // Handled in TypeConstructorPattern
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
// TODO: check for tuples
|
||||||
void TypeCheckVisitor::Visit(TypeConstructorPattern* node) { // TODO: match named constructor
|
void TypeCheckVisitor::Visit(TypeConstructorPattern* node) { // TODO: match named constructor
|
||||||
if (!node->constructor->constructor_id_.has_value()) {
|
if (!node->constructor->constructor_id_.has_value()) {
|
||||||
error_handling::HandleTypecheckError("Type constructor pattern constructor name not found", node->base);
|
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
|
void TypeCheckVisitor::Visit(TypeConstructorParameter* node) {} // Handeled in TypeConstructor visit
|
||||||
|
|
||||||
|
// TODO: check for tuples
|
||||||
void TypeCheckVisitor::Visit(TypeConstructor* node) {
|
void TypeCheckVisitor::Visit(TypeConstructor* node) {
|
||||||
if (!node->constructor->constructor_id_.has_value()) {
|
if (!node->constructor->constructor_id_.has_value()) {
|
||||||
error_handling::HandleTypecheckError("Type constructor name not found", node->base);
|
error_handling::HandleTypecheckError("Type constructor name not found", node->base);
|
||||||
|
|
@ -884,9 +901,14 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) {
|
||||||
std::optional<info::type::VariantType*> maybe_variant_type =
|
std::optional<info::type::VariantType*> maybe_variant_type =
|
||||||
context_manager_.GetValue<info::type::VariantType>(current_type_);
|
context_manager_.GetValue<info::type::VariantType>(current_type_);
|
||||||
|
|
||||||
if (maybe_type_info.has_value()) {
|
if (maybe_variant_type.has_value()) {
|
||||||
maybe_variant_type.value()->SetCurrentConstructor(constructor_info.order);
|
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);
|
current_type_ = TypeInContext(current_type_, context);
|
||||||
|
|
||||||
|
|
@ -1405,7 +1427,7 @@ std::optional<FunctionDeclaration*>
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: internal types ??
|
// TODO: internal types ??
|
||||||
// TODO: abstract types, typeclasses
|
// TODO: handle abstract defined types ??
|
||||||
std::optional<FunctionDeclaration*>
|
std::optional<FunctionDeclaration*>
|
||||||
TypeCheckVisitor::FindTypeFunctionAndUpdate(FunctionCallExpression* node,
|
TypeCheckVisitor::FindTypeFunctionAndUpdate(FunctionCallExpression* node,
|
||||||
TypeExpression* type_node,
|
TypeExpression* type_node,
|
||||||
|
|
@ -1540,25 +1562,29 @@ std::optional<FunctionDeclaration*>
|
||||||
|
|
||||||
auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name);
|
auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name);
|
||||||
if (!maybe_typeclass_graph_id.has_value()) {
|
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,
|
auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name,
|
||||||
maybe_typeclass_graph_id.value());
|
maybe_typeclass_graph_id.value());
|
||||||
|
|
||||||
if (abstract_type_info->HasTypeclass(maybe_typeclass_graph_id.value())) {
|
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()) {
|
if (!maybe_typeclass_function_info.has_value()) {
|
||||||
error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (abstract type)",
|
error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (abstract type)",
|
||||||
"TypeCheckVisitor.FindAbstractTypeTypeclassFunctionAndUpdate");
|
"TypeCheckVisitor.FindAbstractTypeTypeclassFunctionAndUpdate");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((maybe_typeclass_function_info.value()->modifier == utils::ClassInternalsModifier::Static) != is_method) {
|
// TODO: check that const functions not called on var expressions
|
||||||
return std::nullopt;
|
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;
|
node->typeclass_graph_id_ = maybe_typeclass_graph_id;
|
||||||
maybe_function_declaration = maybe_typeclass_function_info.value()->declaration;
|
maybe_function_declaration = maybe_typeclass_function_info.value()->declaration;
|
||||||
}
|
|
||||||
|
|
||||||
return maybe_function_declaration;
|
return maybe_function_declaration;
|
||||||
}
|
}
|
||||||
|
|
@ -1571,11 +1597,17 @@ std::optional<FunctionDeclaration*>
|
||||||
std::optional<FunctionDeclaration*> maybe_function_declaration;
|
std::optional<FunctionDeclaration*> maybe_function_declaration;
|
||||||
|
|
||||||
auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name);
|
auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name);
|
||||||
if (maybe_typeclass_graph_id.has_value()) {
|
if (!maybe_typeclass_graph_id.has_value()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
auto typeclasses = global_info_.GetAnnotatedTypeTypeclassesSet(defined_type->type.node);
|
auto typeclasses = global_info_.GetAnnotatedTypeTypeclassesSet(defined_type->type.node);
|
||||||
auto function_typeclass_iter = typeclasses.find(maybe_typeclass_graph_id.value());
|
auto function_typeclass_iter = typeclasses.find(maybe_typeclass_graph_id.value());
|
||||||
|
|
||||||
if (function_typeclass_iter != typeclasses.end()) {
|
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,
|
auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name,
|
||||||
maybe_typeclass_graph_id.value());
|
maybe_typeclass_graph_id.value());
|
||||||
if (!maybe_typeclass_function_info.has_value()) {
|
if (!maybe_typeclass_function_info.has_value()) {
|
||||||
|
|
@ -1589,8 +1621,6 @@ std::optional<FunctionDeclaration*>
|
||||||
|
|
||||||
node->typeclass_graph_id_ = maybe_typeclass_graph_id;
|
node->typeclass_graph_id_ = maybe_typeclass_graph_id;
|
||||||
maybe_function_declaration = maybe_typeclass_function_info.value()->declaration;
|
maybe_function_declaration = maybe_typeclass_function_info.value()->declaration;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return maybe_function_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