some fixes, going to fix function_call_expression typeclass argument types search bug

This commit is contained in:
ProgramSnail 2023-05-22 01:25:12 +03:00
parent f2192b5331
commit 0290b5604a
9 changed files with 307 additions and 111 deletions

View file

@ -19,6 +19,7 @@ include_directories(include
add_executable(lang_interpreter src/main.cpp
src/types.cpp
src/values.cpp
src/utils.cpp
src/global_info.cpp
src/typeclass_graph.cpp
src/visitor.cpp

View file

@ -172,7 +172,14 @@ private:
}
}
//
void AddGraphIdLocalTypes(utils::IdType graph_id, utils::IdType type) {
std::unordered_set<utils::IdType> requirement_graph_ids = typeclass_graph_.GetDependenciesSet(graph_id);
requirement_graph_ids.insert(graph_id);
for (auto& requirement_graph_id : requirement_graph_ids) {
context_manager_.DefineLocalType(typeclass_graph_.GetVertex(requirement_graph_id).name, type);
}
}
private:
info::GlobalInfo::NamespaceVisitor namespace_visitor_;

View file

@ -50,14 +50,12 @@ public:
}
bool HasTypeclass(utils::IdType graph_id) {
error_handling::DebugPrint(name_);
error_handling::DebugPrint(requirement_graph_ids_.size());
for (auto& requirement_graph_id : requirement_graph_ids_) {
error_handling::DebugPrint(requirement_graph_id);
}
return requirement_graph_ids_.count(graph_id) != 0;
}
std::string ToString() {
return "Abstract";
}
private:
utils::AbstractTypeModifier modifier_;
std::string name_;
@ -93,6 +91,9 @@ public:
return class_modifier_;
}
std::string ToString() {
return "Defined";
}
private:
utils::IdType type_id_; // in defined types
utils::IdType type_; // in types manager, created using context types (if specific type)
@ -140,6 +141,32 @@ inline std::optional<InternalType> ToInternalType(const std::string& type) {
return std::nullopt;
}
inline std::string ToString(InternalType type) {
std::string result;
switch (type) {
case InternalType::Float:
result = "Float";
break;
case InternalType::Int:
result = "Int";
break;
case InternalType::String:
result = "String";
break;
case InternalType::Char:
result = "Char";
break;
case InternalType::Bool:
result = "Bool";
break;
case InternalType::Unit:
result = "Unit";
break;
}
return result;
}
class TupleType {
public:
TupleType() = default;
@ -160,6 +187,7 @@ public:
return fields_;
}
std::string ToString();
private:
std::optional<std::string> name_;
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields_;
@ -190,6 +218,7 @@ public:
current_constructor_ = constructor;
}
std::string ToString();
private:
std::optional<std::string> name_;
std::vector<TupleType> constructors_;
@ -211,6 +240,7 @@ public:
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
std::string ToString();
private:
utils::IdType type_;
TypeManager* type_manager_ = nullptr;
@ -232,6 +262,7 @@ public:
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
std::string ToString();
private:
std::vector<utils::ReferenceModifier> references_;
utils::IdType type_;
@ -256,6 +287,7 @@ public:
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
std::string ToString();
private:
std::vector<utils::IdType> argument_types_;
utils::IdType return_type_;
@ -282,6 +314,7 @@ public:
return elements_type_;
}
std::string ToString();
private:
size_t size_; // = 0 for dynamic
utils::IdType elements_type_;
@ -316,6 +349,8 @@ public:
OptionalType>& GetType() {
return type_;
}
std::string ToString();
private:
std::variant<AbstractType,
DefinedType,

View file

@ -31,62 +31,11 @@ enum class PartitionModifier { Exec = 0, Test = 1 };
enum class ValueType { Const = 0, Var = 1, Tmp = 2 };
inline ValueType IsConstModifierToValueType(IsConstModifier modifier) {
switch (modifier) {
case IsConstModifier::Const:
return ValueType::Const;
case IsConstModifier::Var:
return ValueType::Var;
}
ValueType IsConstModifierToValueType(IsConstModifier modifier);
exit(1); // unreachable
}
ValueType ClassInternalsModifierToValueType(ClassInternalsModifier modifier);
inline ValueType ClassInternalsModifierToValueType(ClassInternalsModifier modifier) {
switch (modifier) {
case ClassInternalsModifier::Const:
return ValueType::Const;
case ClassInternalsModifier::Var:
return ValueType::Var;
case ClassInternalsModifier::Static:
throw std::bad_cast(); // ??
}
exit(1); // unreachable
}
inline bool IsBuiltinFunction(const std::string& name) { // optimize ??
std::unordered_set<std::string> builtin_functions;
builtin_functions.insert("=");
builtin_functions.insert("<-");
builtin_functions.insert("==");
builtin_functions.insert("!=");
builtin_functions.insert("<");
builtin_functions.insert(">");
builtin_functions.insert("<=");
builtin_functions.insert(">=");
builtin_functions.insert("+=");
builtin_functions.insert("-=");
builtin_functions.insert("*=");
builtin_functions.insert("div");
builtin_functions.insert("mod");
builtin_functions.insert("/=");
// builtin_functions.insert("+");
// builtin_functions.insert("-");
// builtin_functions.insert("*");
// builtin_functions.insert("/");
builtin_functions.insert("&&");
builtin_functions.insert("||");
builtin_functions.insert("size");
builtin_functions.insert("random");
builtin_functions.insert("print");
builtin_functions.insert("scan");
builtin_functions.insert("zero");
builtin_functions.insert("one");
return builtin_functions.count(name) != 0;
}
bool IsBuiltinFunction(const std::string& name);
template<typename T>
class Storage {
@ -265,34 +214,12 @@ private:
std::vector<size_t> ranks_;
};
// move to .cpp ??
inline void BackVisitDfs(size_t id,
void BackVisitDfs(size_t id,
std::vector<size_t>& verticles,
std::vector<size_t>& marks,
const std::vector<std::vector<size_t>>& edges,
size_t mark) {
if (marks[id] != 0) {
return;
}
size_t mark);
marks[id] = mark;
verticles.push_back(id);
for (size_t i = 0; i < edges[id].size(); ++i) {
BackVisitDfs(id, verticles, marks, edges, mark);
}
}
// 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);
for (size_t i = 0; i < marks.size(); ++i) {
BackVisitDfs(i, sorted_verticles, marks, edges_, 1);
}
return sorted_verticles;
}
std::vector<size_t> BackTopSort(const std::vector<std::vector<size_t>>& edges_);
} // namespace utils

View file

@ -52,11 +52,9 @@ void TypeCheckVisitor::Visit(Namespace* node) {
context_manager_.EnterContext();
}
// including namespace typeclass
// define typeclasses local types as namespace typeclass
for (auto& requirement_graph_id : requirement_graph_ids) {
context_manager_.DefineLocalType(typeclass_graph_.GetVertex(requirement_graph_id).name, abstract_type);
}
abstract_type = context_manager_.ToModifiedValue(abstract_type, utils::ValueType::Tmp); // ??
AddGraphIdLocalTypes(graph_id, 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());
@ -80,12 +78,7 @@ void TypeCheckVisitor::Visit(Namespace* node) {
context_manager_.EnterContext();
}
// better decision ??
// define typeclasses local types as namespace type
auto typeclass_graph_ids = typeclass_graph_.GetDependenciesVector(type_info->type.node->graph_id_);
for (auto& typeclass_graph_id : typeclass_graph_ids) {
context_manager_.DefineLocalType(typeclass_graph_.GetVertex(typeclass_graph_id).name, type);
}
AddGraphIdLocalTypes(type_info->type.node->graph_id_, type);
if (type_namespaces_.count(node->link_type_id_.value()) != 0) {
error_handling::HandleTypecheckError("Namespaces of one type are one in another", node->base);
@ -269,6 +262,8 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
returned_type_ = current_type_;
}
if (!context_manager_.EqualValues(returned_type, returned_type_.value())) {
error_handling::DebugPrint(context_manager_.GetAnyValue(returned_type)->ToString());
error_handling::DebugPrint(context_manager_.GetAnyValue(returned_type_.value())->ToString());
error_handling::HandleTypecheckError("Wrong function return type", node->base);
}
returned_type_ = std::nullopt;
@ -319,7 +314,7 @@ void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) {
current_type_ = context_manager_.AddValue(info::type::AbstractType(node->modifier, node->type->type, requirements),
utils::ValueType::Tmp);
if (!context_manager_.DefineLocalType(node->type->type, current_type_)) {
error_handling::HandleTypecheckError("Can't define basic / astract type: abstract type redefinition", node->base);
error_handling::HandleTypecheckError("Can't define basic / abstract type: abstract type redefinition", node->base);
}
current_type_ = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp);
@ -731,6 +726,8 @@ void TypeCheckVisitor::Visit(AccessExpression* node) {
// TODO: more builtin functions, better handling (??)
void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
context_manager_.EnterContext();
std::optional<FunctionDeclaration*> maybe_function_declaration;
std::unordered_map<std::string, utils::IdType> context;
@ -749,7 +746,8 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
if (node->prefix.has_value()) {
if (std::holds_alternative<std::unique_ptr<SubExpressionToken>>(node->prefix.value())) {
Visitor::Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node->prefix.value()));
maybe_function_declaration = FindExpressionMethodAndUpdate(node, current_type_);
utils::IdType expression_type = current_type_;
maybe_function_declaration = FindExpressionMethodAndUpdate(node, expression_type);
} else if (std::holds_alternative<std::unique_ptr<TypeExpression>>(node->prefix.value())) {
maybe_function_declaration = FindTypeFunctionAndUpdate(
node,
@ -843,6 +841,8 @@ void TypeCheckVisitor::Visit(TupleExpression* node) {
info::type::TupleType(std::nullopt, fields, context_manager_.GetValueManager()),
utils::ValueType::Tmp);
context_manager_.ExitContext();
node->base.type_ = current_type_;
}
@ -988,7 +988,10 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) {
current_type_ = TypeInContext(current_type_, context);
current_type_ = context_manager_.AddValue(
info::type::DefinedType(type_id, current_type_, type_info.modifier, context_manager_.GetValueManager()),
info::type::DefinedType(type_id,
current_type_,
type_info.modifier,
context_manager_.GetValueManager()),
utils::ValueType::Tmp);
node->base.type_ = current_type_;
@ -1279,7 +1282,7 @@ void TypeCheckVisitor::Visit(TypeExpression* node) {
auto maybe_internal_type = info::type::ToInternalType(node->type.type);
if (maybe_internal_type.has_value()) {
if (maybe_internal_type.has_value()) { // TODO: ???
// checks made in link_symbols_visitor
current_type_ =
context_manager_.AddValue<info::type::InternalType>(
@ -1471,6 +1474,18 @@ std::optional<FunctionDeclaration*>
utils::IdType expression_type) {
std::optional<FunctionDeclaration*> maybe_function_declaration;
auto maybe_internal_type_info = context_manager_.GetValue<info::type::InternalType>(expression_type);
if (maybe_internal_type_info.has_value()) {
auto maybe_abstract_type_id = context_manager_.FindLocalType(info::type::ToString(*maybe_internal_type_info.value()));
if (maybe_abstract_type_id.has_value()) {
expression_type = maybe_abstract_type_id.value();
} else {
error_handling::HandleInternalError("InternalType local abstract type not found",
"TypeCheckVisitor.FindExpressionMethodAndUpdate",
&node->base);
}
}
auto maybe_abstract_type_info = context_manager_.GetValue<info::type::AbstractType>(expression_type);
if (maybe_abstract_type_info.has_value()) {
@ -1478,8 +1493,7 @@ std::optional<FunctionDeclaration*>
maybe_abstract_type_info.value(),
true);
} else {
auto maybe_defined_type_info =
context_manager_.GetValue<info::type::DefinedType>(expression_type);
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", node->base);
}
@ -1488,7 +1502,7 @@ std::optional<FunctionDeclaration*>
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(type_id);
if (!maybe_type_info.has_value()) {
error_handling::HandleInternalError("Functions / Methods implemented only for AnyType",
"TypeCheckVisitor.FunctionCallExpresssion",
"TypeCheckVisitor.FindExpressionMethodAndUpdate",
&node->base);
}
info::definition::AnyType* type_info = maybe_type_info.value();
@ -1645,6 +1659,7 @@ std::optional<FunctionDeclaration*>
}
node->graph_id_ = maybe_typeclass_graph_id;
node->abstract_type_name_ = abstract_type_info->GetName();
maybe_function_declaration = maybe_typeclass_function_info.value()->declaration;
@ -1671,6 +1686,7 @@ std::optional<FunctionDeclaration*>
}
node->graph_id_ = defined_type->type.node->graph_id_;
// type defined -> abstract type name not needed
maybe_function_declaration = maybe_type_function_info.value()->declaration;

View file

@ -128,7 +128,7 @@ void TypeclassGraph::CalculateGraph() {
}
std::vector<size_t> sorted_verticles = utils::BackTopSort(edges);
std::reverse(sorted_verticles.begin(), sorted_verticles.end());
// std::reverse(sorted_verticles.begin(), sorted_verticles.end());
for (auto& id : sorted_verticles) {
for (auto& dependency : verticles_[id].dependencies) {
@ -146,7 +146,7 @@ void TypeclassGraph::CalculateGraph() {
}
}
}
for (auto& inherited_dependency : verticles_[method_to_vertex_[dependency]].dependencies) {
for (auto& inherited_dependency : verticles_[name_to_typeclass_[dependency]].dependencies) {
verticles_[id].dependencies.insert(inherited_dependency);
}
}

View file

@ -124,6 +124,21 @@ std::optional<utils::IdType> TupleType::GetFieldType(const std::string& name,
return std::nullopt;
}
std::string TupleType::ToString() {
std::string result;
result += "(";
for (auto& field : fields_) {
result += "& ";
result += type_manager_->GetAnyValue(field.second)->ToString();
}
result += ")";
return result;
}
//
std::optional<utils::IdType> VariantType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
@ -174,6 +189,21 @@ std::optional<utils::IdType> VariantType::GetFieldType(const std::string& name,
return std::nullopt;
}
std::string VariantType::ToString() {
std::string result;
result += "(";
for (auto& constructor : constructors_) {
result += "& ";
result += constructor.ToString();
}
result += ")";
return result;
}
//
std::optional<utils::IdType> OptionalType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
@ -203,6 +233,10 @@ std::optional<utils::IdType> OptionalType::GetFieldType(const std::string&,
return std::nullopt;
}
std::string OptionalType::ToString() {
return "Optional " + type_manager_->GetAnyValue(type_)->ToString();
}
//
std::optional<utils::IdType> ReferenceToType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
@ -232,6 +266,29 @@ std::optional<utils::IdType> ReferenceToType::GetFieldType(const std::string& na
return type_manager_->GetAnyValue(type_)->GetFieldType(name, type_namespaces);
}
std::string ReferenceToType::ToString() {
std::string result;
for (auto& reference : references_) {
switch (reference) {
case utils::ReferenceModifier::Dereference:
result += '~';
break;
case utils::ReferenceModifier::Reference:
result += '^';
break;
case utils::ReferenceModifier::UniqueReference:
result += '@';
break;
}
}
result += type_manager_->GetAnyValue(type_)->ToString();
return result;
}
//
std::optional<utils::IdType> FunctionType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
@ -284,6 +341,26 @@ std::optional<utils::IdType> FunctionType::GetFieldType(const std::string&,
return std::nullopt;
}
std::string FunctionType::ToString() {
std::string result;
result += "(";
bool is_first_argument = true;
for (auto& argument_type : argument_types_) {
if (is_first_argument) {
is_first_argument = false;
} else {
result += " -> ";
}
result += type_manager_->GetAnyValue(argument_type)->ToString();
}
result += " -> " + type_manager_->GetAnyValue(return_type_)->ToString() + ")";
return result;
}
//
std::optional<utils::IdType> ArrayType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
@ -314,6 +391,10 @@ std::optional<utils::IdType> ArrayType::GetFieldType(const std::string&,
return std::nullopt;
}
std::string ArrayType::ToString() {
return "Array (" + std::to_string(size_) + ") " + type_manager_->GetAnyValue(elements_type_)->ToString();
}
//
std::optional<utils::IdType> Type::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
@ -477,5 +558,35 @@ std::string Type::GetTypeName() const {
return ""; // ??
}
std::string Type::ToString() {
size_t index = type_.index();
switch (index) {
case 0:
return std::get<AbstractType>(type_).ToString();
case 1:
return std::get<DefinedType>(type_).ToString();
case 2:
return ::info::type::ToString(std::get<InternalType>(type_));
case 3:
return std::get<TupleType>(type_).ToString();
case 4:
return std::get<VariantType>(type_).ToString();
case 5:
return std::get<ReferenceToType>(type_).ToString();
case 6:
return std::get<FunctionType>(type_).ToString();
case 7:
return std::get<ArrayType>(type_).ToString();
case 8:
return std::get<OptionalType>(type_).ToString();
default:
// error
break;
}
return "";
}
} // namespace info::type

99
src/utils.cpp Normal file
View file

@ -0,0 +1,99 @@
// for clangd
#include "../include/utils.hpp"
#include"../include/error_handling.hpp"
namespace utils {
using std::size_t;
using IdType = size_t;
ValueType IsConstModifierToValueType(IsConstModifier modifier) {
switch (modifier) {
case IsConstModifier::Const:
return ValueType::Const;
case IsConstModifier::Var:
return ValueType::Var;
}
exit(1); // unreachable
}
ValueType ClassInternalsModifierToValueType(ClassInternalsModifier modifier) {
switch (modifier) {
case ClassInternalsModifier::Const:
return ValueType::Const;
case ClassInternalsModifier::Var:
return ValueType::Var;
case ClassInternalsModifier::Static:
throw std::bad_cast(); // ??
}
exit(1); // unreachable
}
bool IsBuiltinFunction(const std::string& name) { // optimize ??
std::unordered_set<std::string> builtin_functions;
builtin_functions.insert("=");
builtin_functions.insert("<-");
builtin_functions.insert("==");
// builtin_functions.insert("!=");
builtin_functions.insert("<");
// builtin_functions.insert(">");
// builtin_functions.insert("<=");
// builtin_functions.insert(">=");
builtin_functions.insert("+=");
builtin_functions.insert("-=");
builtin_functions.insert("*=");
builtin_functions.insert("div");
builtin_functions.insert("mod");
builtin_functions.insert("/=");
// builtin_functions.insert("+");
// builtin_functions.insert("-");
// builtin_functions.insert("*");
// builtin_functions.insert("/");
builtin_functions.insert("&&");
builtin_functions.insert("||");
builtin_functions.insert("size");
builtin_functions.insert("random");
builtin_functions.insert("print");
builtin_functions.insert("scan");
builtin_functions.insert("zero");
builtin_functions.insert("one");
return builtin_functions.count(name) != 0;
}
void BackVisitDfs(size_t id,
std::vector<size_t>& verticles,
std::vector<size_t>& marks,
const std::vector<std::vector<size_t>>& edges,
size_t mark) {
if (marks[id] != 0) {
return;
}
marks[id] = mark;
for (size_t i = 0; i < edges[id].size(); ++i) {
BackVisitDfs(edges[id][i], verticles, marks, edges, mark);
}
verticles.push_back(id);
}
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);
for (size_t i = 0; i < edges_.size(); ++i) {
if (marks[i] == 0) {
BackVisitDfs(i, sorted_verticles, marks, edges_, 1);
}
}
return sorted_verticles;
}
} // namespace utils

View file

@ -77,8 +77,8 @@ namespace var Mult {
}
typeclass (IDiv : #Mult) =
& var div : IDiv -> Unit
& var mod : IDiv -> Unit
& var div : IDiv -> IDiv
& var mod : IDiv -> IDiv
namespace var IDiv {
def mod : x = self -. x * self.div: x
@ -190,7 +190,7 @@ def ( -- ) : begin end = {
var current = begin
return (while current < end do {
; current += 1
return current - 1
bring current - 1
})
}