From 9aaac90ef6d171761d622304042f0b7341b98927 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Mon, 22 May 2023 16:03:50 +0300 Subject: [PATCH] fixes, builtin function fixes, deep copy, string access --- CMakeLists.txt | 2 +- include/execute_visitor.hpp | 4 +- include/interpreter_tree.hpp | 2 + include/type_check_visitor.hpp | 4 +- include/types.hpp | 36 ++--- include/values.hpp | 60 ++++++-- src/execute_visitor.cpp | 259 +++++++++++++++++++++++++++------ src/type_check_visitor.cpp | 58 ++++---- src/typeclass_graph.cpp | 6 +- src/types.cpp | 13 +- src/utils.cpp | 13 +- src/values.cpp | 98 ++++++++++++- tests/test_code.lang | 47 +++--- 13 files changed, 450 insertions(+), 152 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ff28e9..60f3366 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD 17) # find_package(Catch2 2 REQUIRED) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") include_directories(include tree-sitter/lib/src diff --git a/include/execute_visitor.hpp b/include/execute_visitor.hpp index 5443290..ee5bb01 100644 --- a/include/execute_visitor.hpp +++ b/include/execute_visitor.hpp @@ -164,8 +164,8 @@ private: bool HandleBuiltinFunctionCall(FunctionCallExpression* node); - bool HandleBuiltinTypeclassFunctionCall(FunctionCallExpression* node); - + bool HandleBuiltinTypeFunctionCall(FunctionCallExpression* node, + info::type::InternalType type); private: info::GlobalInfo& global_info_; info::TypeclassGraph& typeclass_graph_; diff --git a/include/interpreter_tree.hpp b/include/interpreter_tree.hpp index 01b61b2..62918d8 100644 --- a/include/interpreter_tree.hpp +++ b/include/interpreter_tree.hpp @@ -506,6 +506,8 @@ struct AccessExpression { std::unique_ptr name; SubExpressionToken id; + + bool is_string_access_ = false; }; // Other Expressions ----------------- diff --git a/include/type_check_visitor.hpp b/include/type_check_visitor.hpp index 44fa31c..f77f197 100644 --- a/include/type_check_visitor.hpp +++ b/include/type_check_visitor.hpp @@ -198,8 +198,8 @@ private: utils::IdType abstract_type = context_manager_.AddValue( info::type::AbstractType(utils::AbstractTypeModifier::Abstract, - typeclass_graph_.GetVertex(graph_id).name, - requirement_graph_ids), + graph_id, + typeclass_graph_), utils::ValueType::Tmp); for (auto& requirement_graph_id : requirement_graph_ids) { diff --git a/include/types.hpp b/include/types.hpp index 20773e2..d5397ee 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -9,6 +9,7 @@ // for clangd #include "error_handling.hpp" +#include "typeclass_graph.hpp" #include "utils.hpp" namespace info::type { @@ -19,23 +20,12 @@ class TypeManager; class AbstractType { // latter will be found in context public: - AbstractType() = default; AbstractType(utils::AbstractTypeModifier modifier, - const std::string& name, - const std::vector& requirement_graph_ids) + utils::IdType graph_id, + info::TypeclassGraph& typeclass_graph) : modifier_(modifier), - name_(name) { - for (auto& requirement_graph_id : requirement_graph_ids) { - requirement_graph_ids_.insert(requirement_graph_id); - } - } - - AbstractType(utils::AbstractTypeModifier modifier, - const std::string& name, - const std::unordered_set& requirement_graph_ids) - : modifier_(modifier), - name_(name), - requirement_graph_ids_(requirement_graph_ids) {} + graph_id_(graph_id), + typeclass_graph_(typeclass_graph) {} std::optional InContext(const std::unordered_map& context); bool Same(const AbstractType& type) const; @@ -45,21 +35,21 @@ public: std::optional GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const; - const std::string& GetName() { - return name_; + utils::IdType GetGraphId() { + return graph_id_; } - bool HasTypeclass(utils::IdType graph_id) { - return requirement_graph_ids_.count(graph_id) != 0; + bool HasTypeclass(utils::IdType graph_id) { // TODO: cache dependencies set + return graph_id == graph_id_ || typeclass_graph_.GetDependenciesSet(graph_id_).count(graph_id) != 0; } std::string ToString() { - return "Abstract " + name_; + return "Abstract " + std::to_string(graph_id_); } private: utils::AbstractTypeModifier modifier_; - std::string name_; - std::unordered_set requirement_graph_ids_; // TODO: all typeclasses from tree + utils::IdType graph_id_; + info::TypeclassGraph& typeclass_graph_; }; class DefinedType { @@ -324,8 +314,6 @@ private: class Type { public: - Type() = default; - template explicit Type(const T& type) : type_(type) {} diff --git a/include/values.hpp b/include/values.hpp index e7ef2d2..6665f81 100644 --- a/include/values.hpp +++ b/include/values.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -32,16 +33,19 @@ public: bool Same(const InternalValue& value) const; std::optional GetFieldValue(const std::string& name) const; + + utils::IdType DeepCopy(ValueManager* value_manager); + public: std::variant value; }; -struct TupleValue { +struct TupleValue { /// TODO: no need to store strings (only store associated type) ?? public: TupleValue() = default; @@ -51,6 +55,9 @@ public: bool Same(const TupleValue& other_value) const; std::optional GetFieldValue(const std::string& name) const; + + utils::IdType DeepCopy(ValueManager* value_manager); // TODO + public: std::vector, utils::IdType>> fields; @@ -65,12 +72,14 @@ public: VariantValue(TupleValue&& value, size_t current_constructor) : value(std::move(value)), current_constructor(current_constructor) {} + bool Same(const VariantValue& other_value) const; + std::optional GetFieldValue(const std::string& name) const; + + utils::IdType DeepCopy(ValueManager* value_manager); + public: TupleValue value; size_t current_constructor; - - bool Same(const VariantValue& other_value) const; - std::optional GetFieldValue(const std::string& name) const; }; struct ReferenceToValue { @@ -82,13 +91,15 @@ public: ValueManager* value_manager) : references(references), value(value), value_manager_(value_manager) {} + bool Same(const ReferenceToValue& other_value) const; + std::optional GetFieldValue(const std::string& name) const; + + utils::IdType DeepCopy(ValueManager* value_manager); + public: std::vector references; utils::IdType value; - bool Same(const ReferenceToValue& other_value) const; - std::optional GetFieldValue(const std::string& name) const; - private: ValueManager* value_manager_ = nullptr; }; @@ -101,13 +112,15 @@ public: FunctionValue(const T& function, ValueManager* value_manager) : function(function), value_manager_(value_manager) {} + bool Same(const FunctionValue& other_value) const; + std::optional GetFieldValue(const std::string& name) const; + + utils::IdType DeepCopy(ValueManager* value_manager); + public: std::variant function; - bool Same(const FunctionValue& other_value) const; - std::optional GetFieldValue(const std::string& name) const; - private: ValueManager* value_manager_ = nullptr; }; @@ -122,13 +135,15 @@ public: ValueManager* value_manager) : elements(std::move(elements)), is_constant_size(is_constant_size), value_manager_(value_manager) {} + bool Same(const ArrayValue& other_value) const; + std::optional GetFieldValue(const std::string& name) const; + + utils::IdType DeepCopy(ValueManager* value_manager); + public: std::vector elements; bool is_constant_size = false; - bool Same(const ArrayValue& other_value) const; - std::optional GetFieldValue(const std::string& name) const; - private: ValueManager* value_manager_ = nullptr; }; @@ -143,6 +158,8 @@ public: bool Same(const OptionalValue& other_value) const; std::optional GetFieldValue(const std::string& name) const; + utils::IdType DeepCopy(ValueManager* value_manager); + public: std::optional value; @@ -160,6 +177,8 @@ public: bool Same(const Value& other_value) const; std::optional GetFieldValue(const std::string& name) const; + utils::IdType DeepCopy(ValueManager* value_manager); + public: std::variant - utils::IdType AddValue(const T& value, utils::ValueType value_type) { + utils::IdType ExplicitAddValue(const T& value, utils::ValueType value_type) { values_.push_back(std::pair {Value(value), value_type}); return values_.size() - 1; } - utils::IdType AddAnyValue(Value&& value, utils::ValueType value_type) { + utils::IdType ExplicitAddAnyValue(Value&& value, utils::ValueType value_type) { values_.push_back(std::pair {std::move(value), value_type}); return values_.size() - 1; } + template + utils::IdType AddValue(const T& value, utils::ValueType value_type) { + return ExplicitAddValue(std::move(value), value_type); + } + + utils::IdType AddAnyValue(Value&& value, utils::ValueType value_type) { + return ExplicitAddAnyValue(std::move(value), value_type); + } + template std::optional GetValue(utils::IdType value_id) { if (!std::holds_alternative(values_.at(value_id).first.value)) { diff --git a/src/execute_visitor.cpp b/src/execute_visitor.cpp index 9798afe..7c64b8f 100644 --- a/src/execute_visitor.cpp +++ b/src/execute_visitor.cpp @@ -392,20 +392,37 @@ void ExecuteVisitor::Visit(ReferenceExpression* node) { value_type); } +// TODO: extend to other types +// TODO: string should be array void ExecuteVisitor::Visit(AccessExpression* node) { - // TODO: extend to other types Visit(node->name.get()); - info::value::ArrayValue* array_value = ExtractValue(current_value_, node->base); - utils::ValueType value_type = context_manager_.GetValueType(current_value_); + utils::IdType array_value = current_value_; + utils::ValueType value_type = context_manager_.GetValueType(array_value); Visitor::Visit(node->id); - long long index = *ExtractInternalValue(current_value_, node->base); // TODO: size_t + int64_t index = *ExtractInternalValue(current_value_, node->base); // TODO: size_t - if (index < 0 || index >= (long long)array_value->elements.size()) { - error_handling::HandleRuntimeError("Access index out of range", node->base); + if (index < 0) { + error_handling::HandleRuntimeError("Access index is negative", node->base); } - current_value_ = context_manager_.ToModifiedValue(array_value->elements[index], value_type); // needed ?? + if (node->is_string_access_) { + std::string* string_value_info = ExtractInternalValue(current_value_, node->base); + + if (index >= (int64_t)string_value_info->size()) { + error_handling::HandleRuntimeError("Access index is out of range (string)", node->base); + } + + current_value_ = context_manager_.ToModifiedValue((*string_value_info)[index], value_type); + } else { + info::value::ArrayValue* array_value_info = ExtractValue(current_value_, node->base); + + if (index >= (int64_t)array_value_info->elements.size()) { + error_handling::HandleRuntimeError("Access index is out of range (array)", node->base); + } + + current_value_ = context_manager_.ToModifiedValue(array_value_info->elements[index], value_type); + } } // Other Expressions @@ -462,6 +479,7 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) { if (!maybe_function_definition_info.has_value()) { if (HandleBuiltinFunctionCall(node)) { + context_manager_.ExitContext(); return; } @@ -485,6 +503,16 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) { if (!maybe_function_definition.has_value()) { if (typeclass_graph_.GetVertex(node->graph_id_.value()).modifier == info::TypeclassGraph::Modifier::Type) { + auto maybe_internal_type = info::type::ToInternalType(typeclass_graph_.GetVertex(node->graph_id_.value()).name); + + if (maybe_internal_type.has_value()) { + if (HandleBuiltinTypeFunctionCall(node, maybe_internal_type.value())) { + context_manager_.ExitContext(); + return; // TODO: always return from end of function + } + error_handling::HandleRuntimeError("Type function definition not found (builtin type)", node->base); + } + error_handling::HandleRuntimeError("Type function definition not found (by graph_id_)", node->base); } @@ -515,10 +543,6 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) { } if (!maybe_function_definition.has_value()) { - if (HandleBuiltinTypeclassFunctionCall(node)) { - return; - } - error_handling::HandleRuntimeError("Function definition not found (by graph_id_)", node->base); } @@ -723,25 +747,9 @@ void ExecuteVisitor::Visit(TupleName* node) { // TODO: check error_handling::HandleRuntimeError("Mismatched field count in tuple variable definition", node->base); } - if (!is_const_definition_.has_value()) { - error_handling::HandleInternalError("No value in is_const_definition_", - "TypeCheckVisitor.TupleName", - &node->base); - } - - utils::ValueType value_type = context_manager_.GetValueType(value); - if (value_type == utils::ValueType::Const - && is_const_definition_.value() == utils::IsConstModifier::Var) { - error_handling::HandleRuntimeError("TupleName: value type expression not match variable definition modifier", node->base); - } - for (size_t i = 0; i < node->names.size(); ++i) { current_value_ = maybe_tuple_value.value()->fields[i].second; - if (value_type == utils::ValueType::Tmp) { // TODO: ?? - current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Tmp); - } - Visitor::Visit(node->names[i]); } @@ -798,11 +806,13 @@ void ExecuteVisitor::Visit(AnnotatedName* node) { // TODO: check &node->base); } - utils::ValueType value_type = context_manager_.GetValueType(current_value_); - if (value_type == utils::ValueType::Const - && is_const_definition_.value() == utils::IsConstModifier::Var) { - error_handling::HandleRuntimeError("AnnotatedName: value type expression not match variable definition modifier", node->base); - } + // utils::ValueType value_type = context_manager_.GetValueType(current_value_); + + // TODO: only on move + // if (value_type == utils::ValueType::Const + // && is_const_definition_.value() == utils::IsConstModifier::Var) { + // error_handling::HandleRuntimeError("AnnotatedName: value type expression not match variable definition modifier", node->base); + // } current_value_ = context_manager_.ToModifiedValue(value, utils::IsConstModifierToValueType(is_const_definition_.value())); if (!context_manager_.DefineVariable(node->name, current_value_)) { @@ -963,30 +973,191 @@ void ExecuteVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) { bool ExecuteVisitor::HandleBuiltinFunctionCall(FunctionCallExpression* node) { if (node->name == "print") { - if (node->arguments.size() < 1) { - error_handling::HandleInternalError("Builtin function \"print\" has 0 arguments", - "ExecuteVisitor.HandleBuiltinFunctionCall", - &node->base); - } - Visitor::Visit(node->arguments[0]); info::builtin::Print(*ExtractInternalValue(current_value_, node->base)); current_value_ = context_manager_.AddValue(info::value::InternalValue(info::value::Unit()), utils::ValueType::Tmp); - return true; } else if (node->name == "scan") { current_value_ = context_manager_.AddValue(info::value::InternalValue(info::builtin::Read()), utils::ValueType::Tmp); - return true; + } else if (node->name == "random") { // TODO + current_value_ = context_manager_.AddValue(info::value::InternalValue(rand()), + utils::ValueType::Tmp); + } else { + return false; + } + + return true; +} + +bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node, + info::type::InternalType type) { + const std::string& name = node->name; + + if (utils::IsBuiltinFunction(name)) { + std::vector arguments; + arguments.reserve(node->arguments.size()); + + if (std::holds_alternative>(node->prefix.value())) { + Visitor::Visit(*std::get>(node->prefix.value())); + arguments.push_back(ExtractValue(current_value_, node->base)); + } + + for (auto& argument : node->arguments) { + Visitor::Visit(argument); + arguments.push_back(ExtractValue(current_value_, node->base)); + } + + error_handling::DebugPrint(info::type::ToString(type)); + + switch (type) { + case info::type::InternalType::Float: + if (name == "show") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(std::to_string(*arguments[0]->GetValue().value())), + utils::ValueType::Tmp); + } else if (name == "<") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() < *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "==") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() == *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "zero") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(0.0), + utils::ValueType::Tmp); + } else if (name == "one") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(1.0), + utils::ValueType::Tmp); + } else if (name == "+=") { + // TODO + error_handling::HandleInternalError("+= not implemented yet (float)", + "ExecuteVisitor.HandleBuiltinTypeFunctionCall", + &node->base); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else { + return false; + } + break; + case info::type::InternalType::Int: + if (name == "show") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(std::to_string(*arguments[0]->GetValue().value())), + utils::ValueType::Tmp); + } else if (name == "<") { + error_handling::DebugPrint("_");/* + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() < *arguments[1]->GetValue().value()), + utils::ValueType::Tmp);*/ + error_handling::DebugPrint("aaaaaaaa"); + } else if (name == "==") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() == *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "div") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() / *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "mod") { // TODO: best implementation of mod (read % specification) + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() % *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "zero") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(0), + utils::ValueType::Tmp); + } else if (name == "one") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(1), + utils::ValueType::Tmp); + } else if (name == "+=") { + // TODO + error_handling::HandleInternalError("+= not implemented yet (int)", + "ExecuteVisitor.HandleBuiltinTypeFunctionCall", + &node->base); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else { + return false; + } + break; + case info::type::InternalType::String: // TODO: string is array ?? + if (name == "show") { // do not copy ?? + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "<") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() < *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "==") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() == *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "size") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(static_cast(arguments[0]->GetValue().value()->size())), + utils::ValueType::Tmp); + } else if (name == "at") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue((*arguments[0]->GetValue().value())[*arguments[1]->GetValue().value()]), + utils::ValueType::Tmp); + } else { + return false; + } + break; + case info::type::InternalType::Char: + if (name == "show") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(std::string{*arguments[0]->GetValue().value()}), + utils::ValueType::Tmp); + } else if (name == "<") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() < *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "==") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() == *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else { + return false; + } + break; + case info::type::InternalType::Bool: + if (name == "show") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() ? "true" : "false"), + utils::ValueType::Tmp); + } else { + return false; + } + break; + case info::type::InternalType::Unit: + if (name == "show") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue("()"), + utils::ValueType::Tmp); + } else { + return false; + } + break; + default: + // error + break; + } + + return false; } return false; } -bool ExecuteVisitor::HandleBuiltinTypeclassFunctionCall(FunctionCallExpression*) { - return false; -} - } // namespace interpreter diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 14d4330..f06d920 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -142,11 +142,10 @@ void TypeCheckVisitor::Visit(FunctionDeclaration* node) { context_manager_.EnterContext(); for (auto& parameter : node->parameters) { // declaration correctness check // TODO: needed?? - auto requirements = typeclass_graph_.GetDependenciesSet(parameter->graph_id_); current_type_ = context_manager_.AddValue( info::type::AbstractType(utils::AbstractTypeModifier::Abstract, - parameter->type, - requirements), + parameter->graph_id_, + typeclass_graph_), utils::ValueType::Tmp); context_manager_.DefineLocalType(parameter->type, current_type_); } @@ -223,11 +222,10 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { } for (auto& parameter : declaration->parameters) { - auto requirements = typeclass_graph_.GetDependenciesSet(parameter->graph_id_); current_type_ = context_manager_.AddValue(info::type::AbstractType(utils::AbstractTypeModifier::Abstract, - parameter->type, - requirements), - utils::ValueType::Tmp); + parameter->graph_id_, + typeclass_graph_), + utils::ValueType::Tmp); if (!context_manager_.DefineLocalType(parameter->type, current_type_)) { error_handling::HandleTypecheckError("Can't define function parameter type: abstract type redefinition", node->base); } @@ -313,8 +311,10 @@ void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) { auto requirements = typeclass_graph_.GetDependenciesSet(node->type->graph_id_); - current_type_ = context_manager_.AddValue(info::type::AbstractType(node->modifier, node->type->type, requirements), - utils::ValueType::Tmp); + current_type_ = context_manager_.AddValue(info::type::AbstractType(node->modifier, + node->type->graph_id_, + typeclass_graph_), + utils::ValueType::Tmp); if (maybe_internal_type.has_value()) { internal_to_abstract_type_[maybe_internal_type.value()] = current_type_; @@ -710,6 +710,8 @@ void TypeCheckVisitor::Visit(ReferenceExpression* node) { context_manager_.GetValueType(current_type_)); // ?? } +// TODO: redifinitions for other types and tuples (with const index) ?? +// TODO: string should be array void TypeCheckVisitor::Visit(AccessExpression* node) { Visitor::Visit(node->id); if (!context_manager_.EqualValues(internal_to_abstract_type_.at(info::type::InternalType::Int), current_type_)) { @@ -718,15 +720,21 @@ void TypeCheckVisitor::Visit(AccessExpression* node) { Visitor::Visit(node->name.get()); - std::optional maybe_type_value = context_manager_.GetValue(current_type_); + auto maybe_type_value = context_manager_.GetValue(current_type_); - if (!maybe_type_value.has_value()) { - error_handling::HandleTypecheckError("Access type is not array", node->base); - // TODO: redifinitions for other types and tuples (with const index) ?? + if (maybe_type_value.has_value()) { + current_type_ = maybe_type_value.value()->GetElementsType(); + } else { + auto maybe_internal_type_value = context_manager_.GetValue(current_type_); + + if (!maybe_internal_type_value.has_value() || *maybe_internal_type_value.value() != info::type::InternalType::String) { + error_handling::HandleTypecheckError("Access type is not array", node->base); + } + + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Char); + node->is_string_access_ = true; } - current_type_ = maybe_type_value.value()->GetElementsType(); - node->base.type_ = current_type_; } @@ -1643,22 +1651,16 @@ std::optional bool is_method) { std::optional maybe_function_declaration; - auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name); - if (!maybe_typeclass_graph_id.has_value()) { + utils::IdType graph_id = abstract_type_info->GetGraphId(); + + if (!typeclass_graph_.IsFunctionInVertex(node->name, graph_id)) { return std::nullopt; } - 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())) { - error_handling::HandleTypecheckError("Function typeclass not pesent in type typeclasses list (abstract type)", node->base); - } + auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name, graph_id); if (!maybe_typeclass_function_info.has_value()) { - error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (abstract type)", - "TypeCheckVisitor.FindAbstractTypeTypeclassFunctionAndUpdate", - &node->base); + error_handling::HandleTypecheckError("Function not present in typeclass (abstract type)", node->base); } // TODO: check that const functions not called on var expressions ?? @@ -1666,10 +1668,10 @@ std::optional error_handling::HandleTypecheckError("Typeclass function has wrong modifier (abstract type)", node->base); } - node->graph_id_ = maybe_typeclass_graph_id; + node->graph_id_ = graph_id; AddGraphIdLocalAbstractTypes(node->graph_id_.value()); // check - node->abstract_type_name_ = abstract_type_info->GetName(); + node->abstract_type_name_ = typeclass_graph_.GetVertex(node->graph_id_.value()).name; maybe_function_declaration = maybe_typeclass_function_info.value()->declaration; return maybe_function_declaration; diff --git a/src/typeclass_graph.cpp b/src/typeclass_graph.cpp index 3dd8e93..8cef103 100644 --- a/src/typeclass_graph.cpp +++ b/src/typeclass_graph.cpp @@ -73,7 +73,11 @@ std::optional TypeclassGraph::FindFunctionTypeclass(const std::st std::optional TypeclassGraph::GetFunctionInfo(const std::string& name, std::optional vertex_id) { if (vertex_id.has_value()) { - return &verticles_[vertex_id.value()].functions[name]; + auto function_info_iter = verticles_[vertex_id.value()].functions.find(name); + return function_info_iter != + verticles_[vertex_id.value()].functions.end() + ? std::optional(&function_info_iter->second) + : std::nullopt; } auto maybe_function_typeclass_id = FindFunctionTypeclass(name); diff --git a/src/types.cpp b/src/types.cpp index 9fa788f..0c35d92 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -5,7 +5,7 @@ namespace info::type { std::optional AbstractType::InContext(const std::unordered_map& context) { - auto type_iter = context.find(name_); + auto type_iter = context.find(typeclass_graph_.GetVertex(graph_id_).name); if (type_iter != context.end()) { return type_iter->second; @@ -14,12 +14,15 @@ std::optional AbstractType::InContext(const std::unordered_map"); - // 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"); + builtin_functions.insert("show"); + // builtin_functions.insert("read"); // TODO + // builtin_functions.insert("debug_show"); // TODO return builtin_functions.count(name) != 0; } diff --git a/src/values.cpp b/src/values.cpp index 00dd48d..2e90e04 100644 --- a/src/values.cpp +++ b/src/values.cpp @@ -1,5 +1,8 @@ +#include + // for clangd #include "../include/values.hpp" +#include "../include/error_handling.hpp" namespace info::value { @@ -12,7 +15,7 @@ bool InternalValue::Same(const InternalValue& other_value) const { case 0: return std::get(value) == std::get(other_value.value); case 1: - return std::get(value) == std::get(other_value.value); + return std::get(value) == std::get(other_value.value); case 2: return std::get(value) == std::get(other_value.value); case 3: @@ -34,6 +37,10 @@ std::optional InternalValue::GetFieldValue(const std::string&) co return std::nullopt; } +utils::IdType InternalValue::DeepCopy(ValueManager* value_manager) { + return value_manager->ExplicitAddValue(InternalValue(value), utils::ValueType::Tmp); +} + // bool TupleValue::Same(const TupleValue& other_value) const { @@ -58,6 +65,18 @@ std::optional TupleValue::GetFieldValue(const std::string& name) return std::nullopt; } +utils::IdType TupleValue::DeepCopy(ValueManager* value_manager) { + std::vector, utils::IdType>> fields_copy(fields.size()); + + for (size_t i = 0; i < fields.size(); ++i) { + fields_copy[i] = {fields[i].first, value_manager_->GetAnyValue(fields[i].second)->DeepCopy(value_manager)}; + } + + return value_manager->ExplicitAddValue( + TupleValue(std::move(fields_copy), value_manager), + utils::ValueType::Tmp); +} + // bool VariantValue::Same(const VariantValue& other_value) const { @@ -73,6 +92,20 @@ std::optional VariantValue::GetFieldValue(const std::string& name return value.GetFieldValue(name); } +utils::IdType VariantValue::DeepCopy(ValueManager* value_manager) { + auto maybe_tuple_deep_copy = value_manager->GetValue(value.DeepCopy(value_manager)); + + if (!maybe_tuple_deep_copy) { + error_handling::HandleInternalError("Deep copied TupleType in not TupleType", + "VariantValue.DeepCopy", + std::nullopt); + } + + return value_manager->ExplicitAddValue( + VariantValue(TupleValue(*maybe_tuple_deep_copy.value()), current_constructor), + utils::ValueType::Tmp); +} + // bool ReferenceToValue::Same(const ReferenceToValue& other_value) const { @@ -91,6 +124,13 @@ std::optional ReferenceToValue::GetFieldValue(const std::string& return value_manager_->GetAnyValue(value)->GetFieldValue(name); } +utils::IdType ReferenceToValue::DeepCopy(ValueManager* value_manager) { + return value_manager->ExplicitAddValue( + ReferenceToValue(references, value_manager_->GetAnyValue(value)->DeepCopy(value_manager), value_manager), + utils::ValueType::Tmp); +} + + // bool FunctionValue::Same(const FunctionValue& other_value) const { @@ -116,6 +156,12 @@ std::optional FunctionValue::GetFieldValue(const std::string&) co return std::nullopt; } +utils::IdType FunctionValue::DeepCopy(ValueManager* value_manager) { + return value_manager->ExplicitAddValue( + FunctionValue(function, value_manager), + utils::ValueType::Tmp); +} + // bool ArrayValue::Same(const ArrayValue& other_value) const { @@ -135,6 +181,18 @@ std::optional ArrayValue::GetFieldValue(const std::string&) const return std::nullopt; } +utils::IdType ArrayValue::DeepCopy(ValueManager* value_manager) { + std::vector elements_copy(elements.size()); + + for (size_t i = 0; i < elements.size(); ++i) { + elements_copy[i] = value_manager_->GetAnyValue(elements[i])->DeepCopy(value_manager); + } + + return value_manager->ExplicitAddValue( + ArrayValue(std::move(elements_copy), is_constant_size, value_manager), + utils::ValueType::Tmp); +} + // bool OptionalValue::Same(const OptionalValue& other_value) const { @@ -152,6 +210,18 @@ std::optional OptionalValue::GetFieldValue(const std::string&) co return std::nullopt; } +utils::IdType OptionalValue::DeepCopy(ValueManager* value_manager) { + if (!value.has_value()) { + return value_manager->ExplicitAddValue( + OptionalValue(std::nullopt, value_manager), + utils::ValueType::Tmp); + } + + return value_manager->ExplicitAddValue( + OptionalValue(value_manager_->GetAnyValue(value.value())->DeepCopy(value_manager), value_manager), + utils::ValueType::Tmp); +} + // bool Value::Same(const Value& other_value) const { @@ -209,4 +279,30 @@ std::optional Value::GetFieldValue(const std::string& name) const return std::nullopt; } +utils::IdType Value::DeepCopy(ValueManager* value_manager) { + size_t index = value.index(); + + switch (index) { + case 0: + return std::get(value).DeepCopy(value_manager); + case 1: + return std::get(value).DeepCopy(value_manager); + case 2: + return std::get(value).DeepCopy(value_manager); + case 3: + return std::get(value).DeepCopy(value_manager); + case 4: + return std::get(value).DeepCopy(value_manager); + case 5: + return std::get(value).DeepCopy(value_manager); + case 6: + return std::get(value).DeepCopy(value_manager); + default: + // error + break; + } + + exit(1); // better error handling ?? +} + }; // namespace info::value diff --git a/tests/test_code.lang b/tests/test_code.lang index 559ecd8..54904c0 100644 --- a/tests/test_code.lang +++ b/tests/test_code.lang @@ -1,9 +1,9 @@ -basic (Float : #Ord #Div) -basic (Int : #Ord #IDiv) -basic (String : #Ord) -basic (Char : #Ord #Enum) -basic (Bool : #Ord) -basic Unit +basic (Float : #Ord #Div #Show) +basic (Int : #Ord #IDiv #Show) +basic (String : #Ord #Show #CharContainer) +basic (Char : #Ord #Show) +basic (Bool : #Ord #Show) +basic (Unit : #Show) // @@ -35,6 +35,12 @@ def ( || ) : x y = // +typeclass CharContainer = + & var size : -> Int + & var at : Int -> Char + +// + typeclass Move = & var ( <- ) : Move -> Unit // TODO @@ -142,11 +148,11 @@ namespace var Ord { typeclass Show = & var show : -> String -typeclass Read = - & var read : String -> Read +// typeclass Read = // TODO +// & var read : String -> Read -typeclass DebugShow = - & debug_show : -> String +// typeclass DebugShow = // TODO +// & debug_show : -> String // @@ -171,6 +177,12 @@ typeclass Enum = // +decl print : String -> Unit +decl scan : -> String +decl random : -> Int // TODO + +// + // // bad // typeclass Functor 'A = // & fmap 'B ('F : (#Functor 'B)) : ('A -> 'B) -> Functor -> 'F @@ -189,22 +201,21 @@ decl ( -- ) : Int -> Int -> Int_0 def ( -- ) : begin end = { var current = begin return (while current < end do { - ; current += 1 - bring current - 1 + //; current += 1 + //bring current - 1 + bring 1 }) } -decl print : String -> Unit -decl scan : -> String - -decl func : String -> Int -def func : s = { +decl func : String -> Int -> Int +def func : s i = { ; print: s + ; print: (i.show:) return 5 } exec main { - for i in 0--9 do func: "abacaba" + for i in 0--9 do func: "abacaba" i ; print: ({ if true then bring scan: else { ; print: "aaa" } bring "nothing"