diff --git a/include/execute_visitor.hpp b/include/execute_visitor.hpp index ee5bb01..0d1da6e 100644 --- a/include/execute_visitor.hpp +++ b/include/execute_visitor.hpp @@ -160,6 +160,16 @@ private: return maybe_internal_value_info.value(); } + utils::IdType GraphIdByTypeId(utils::IdType type_id) { + auto maybe_any_type = global_info_.GetTypeInfo(type_id); + if (!maybe_any_type.has_value()) { + error_handling::HandleInternalError("Only AnyType implemented", + "ExecuteVisitor.ExtractInternalValue", + std::nullopt); + } + return maybe_any_type.value()->node->definition->type->graph_id_; + } + // bool HandleBuiltinFunctionCall(FunctionCallExpression* node); @@ -170,7 +180,9 @@ private: info::GlobalInfo& global_info_; info::TypeclassGraph& typeclass_graph_; info::ContextManager& type_context_manager_; + info::ContextManager& context_manager_; + // local types store types graph ids utils::IdType current_value_; std::optional active_loop_control_expression_; diff --git a/include/typeclass_graph.hpp b/include/typeclass_graph.hpp index 40b4806..ce5dc34 100644 --- a/include/typeclass_graph.hpp +++ b/include/typeclass_graph.hpp @@ -32,6 +32,7 @@ public: std::unordered_map functions; std::unordered_set dependencies; // TODO: parameters interpreter::tokens::BaseNode* base_node; // for error handling + std::optional type_id; // for defined types Modifier modifier; }; diff --git a/src/.execute_visitor.cpp.kate-swp b/src/.execute_visitor.cpp.kate-swp new file mode 100644 index 0000000..52b49f2 Binary files /dev/null and b/src/.execute_visitor.cpp.kate-swp differ diff --git a/src/execute_visitor.cpp b/src/execute_visitor.cpp index 53df44f..1af1165 100644 --- a/src/execute_visitor.cpp +++ b/src/execute_visitor.cpp @@ -490,10 +490,27 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) { function_definition = maybe_function_definition_info.value().node; } else if (node->graph_id_.has_value()) { + error_handling::DebugPrint(typeclass_graph_.GetVertex(node->graph_id_.value()).name); + + utils::IdType defined_type_graph_id; // try to find defined or basic type + if (typeclass_graph_.GetVertex(node->graph_id_.value()).type_id.has_value() + || (node->abstract_type_name_.has_value() + && info::type::ToInternalType(node->abstract_type_name_.value()).has_value())) { + defined_type_graph_id = node->graph_id_.value(); + } + else { + auto maybe_defined_type_graph_id = context_manager_.FindLocalType(node->abstract_type_name_.value()); + if (!maybe_defined_type_graph_id.has_value()) { + error_handling::HandleRuntimeError("Function's defined / basic abstract type not found (by abstract_type_name_ and in typeclass graph)", node->base); + } + defined_type_graph_id = maybe_defined_type_graph_id.value(); + } + + std::optional maybe_function_definition; auto maybe_function_graph_info = typeclass_graph_.GetFunctionInfo(node->name, - node->graph_id_.value()); + node->defined_type_graph_id.value()); if (!maybe_function_graph_info.has_value()) { error_handling::HandleRuntimeError("Function info not found (by graph_id_)", node->base); @@ -517,17 +534,20 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) { error_handling::HandleRuntimeError("Type function definition not found (by graph_id_)", node->base); } - if (!node->abstract_type_name_.has_value()) { - error_handling::HandleInternalError("Typeclass function's abstract_type_name_ has no value", + // if (!node->abstract_type_name_.has_value()) { + // error_handling::HandleInternalError("Typeclass function's abstract_type_name_ has no value", + // "ExecuteVisitor.FunctionCallExpression", + // &node->base); + // } + + auto maybe_type_id = typeclass_graph_.GetVertex(defined_type_graph_id).type_id; + + if (!maybe_type_id.has_value()) { + error_handling::HandleInternalError("Function's abstract type type_id not found", "ExecuteVisitor.FunctionCallExpression", &node->base); } - auto maybe_type_id = context_manager_.FindLocalType(node->abstract_type_name_.value()); - if (!maybe_type_id.has_value()) { - error_handling::HandleRuntimeError("Function's abstract type not found (by abstract_type_name_)", node->base); - } - auto maybe_type_info = global_info_.GetTypeInfo(maybe_type_id.value()); if (!maybe_type_info.has_value()) { @@ -548,36 +568,48 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) { } function_definition = maybe_function_definition.value(); + + auto dependency_graph_ids = typeclass_graph_.GetDependenciesSet(node->graph_id_.value()); + dependency_graph_ids.insert(node->graph_id_.value()); // TODO: ?? + for (auto& dependency_graph_id : dependency_graph_ids) { + context_manager_.DefineLocalType(typeclass_graph_.GetVertex(dependency_graph_id).name, defined_type_graph_id); + } } + // handle choosen type typclasses + + // handle parameters for (size_t i = 0; i < node->parameters.size(); ++i) { - utils::IdType type_id = 0; + utils::IdType graph_id = 0; if (node->parameters[i]->type_id_.has_value()) { - type_id = node->parameters[i]->type_id_.value(); + graph_id = GraphIdByTypeId(node->parameters[i]->type_id_.value()); } else { - auto maybe_parameter_type_id = context_manager_.FindLocalType(node->parameters[i]->type.type); + auto maybe_parameter_graph_id = context_manager_.FindLocalType(node->parameters[i]->type.type); - if (!maybe_parameter_type_id.has_value()) { + if (!maybe_parameter_graph_id.has_value()) { error_handling::HandleInternalError("Parameter type not found", "ExecuteVisitor.FunctionCallExpression", &node->base); } - type_id = maybe_parameter_type_id.value(); + graph_id = maybe_parameter_graph_id.value(); } - if (!context_manager_.DefineLocalType(function_declaration->parameters[i]->type, type_id)) { + if (!context_manager_.DefineLocalType(function_declaration->parameters[i]->type, graph_id)) { error_handling::HandleRuntimeError("Type redefinition (function argument)", node->base); } } - for (size_t i = (node->is_method_of_first_argument_ ? 1 : 0); i < node->arguments.size(); ++i) { + size_t index_shift = (node->is_method_of_first_argument_ ? 1 : 0); + + // handle arguments + for (size_t i = index_shift; i < node->arguments.size(); ++i) { Visitor::Visit(node->arguments[i]); // function arguments can't be changed inside function current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); - if (!context_manager_.DefineVariable(function_definition->definition->arguments[i], + if (!context_manager_.DefineVariable(function_definition->definition->arguments[i - index_shift], current_value_)) { error_handling::HandleRuntimeError("Variable redefinition (function argument)", node->base); } @@ -915,11 +947,8 @@ void ExecuteVisitor::CollectTypeContext(const ParametrizedType& type) { utils::IdType type_id = 0; if (!type.type_id_.has_value()) { - auto maybe_local_type_id = context_manager_.FindLocalType(type.type); - if (!maybe_local_type_id.has_value()) { - return; - } - type_id = maybe_local_type_id.value(); // TODO: check + // abstract types have no parameters + return; } else { type_id = type.type_id_.has_value(); } @@ -937,7 +966,7 @@ void ExecuteVisitor::CollectTypeContext(const ParametrizedType& type) { for (size_t i = 0; i < type.parameters.size(); ++i) { if (type.parameters[i]->type_id_.has_value()) { context_manager_.DefineLocalType(type_info.parameters[i].type, - type.parameters[i]->type_id_.value()); + GraphIdByTypeId(type.parameters[i]->type_id_.value())); } } } @@ -995,13 +1024,11 @@ bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node, info::type::InternalType type) { const std::string& name = node->name; - error_handling::DebugPrint(name); - if (utils::IsBuiltinFunction(name)) { std::vector arguments; arguments.reserve(node->arguments.size()); - if (std::holds_alternative>(node->prefix.value())) { + if (node->prefix.has_value() && std::holds_alternative>(node->prefix.value())) { Visitor::Visit(*std::get>(node->prefix.value())); arguments.push_back(ExtractValue(current_value_, node->base)); } @@ -1011,9 +1038,6 @@ bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node, arguments.push_back(ExtractValue(current_value_, node->base)); } - error_handling::DebugPrint(info::type::ToString(type)); - std::cout << std::endl; - switch (type) { case info::type::InternalType::Float: if (name == "show") { @@ -1036,6 +1060,11 @@ bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node, current_value_ = context_manager_.AddValue( info::value::InternalValue(1.0), utils::ValueType::Tmp); + } else if (name == "=") { + *arguments[0]->GetValue().value() = *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); } else if (name == "+=") { *arguments[0]->GetValue().value() += *arguments[1]->GetValue().value(); current_value_ = context_manager_.AddValue( @@ -1077,7 +1106,7 @@ bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node, current_value_ = context_manager_.AddValue( info::value::InternalValue(*arguments[0]->GetValue().value() / *arguments[1]->GetValue().value()), utils::ValueType::Tmp); - } else if (name == "mod") { // TODO: better implementation of mod (read % specification) + } else if (name == "mod") { // TODO: better implementation of mod (read "%" specification) current_value_ = context_manager_.AddValue( info::value::InternalValue(*arguments[0]->GetValue().value() % *arguments[1]->GetValue().value()), utils::ValueType::Tmp); @@ -1089,18 +1118,23 @@ bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node, current_value_ = context_manager_.AddValue( info::value::InternalValue(1), utils::ValueType::Tmp); + } else if (name == "=") { + *arguments[0]->GetValue().value() = *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); } else if (name == "+=") { *arguments[0]->GetValue().value() += *arguments[1]->GetValue().value(); current_value_ = context_manager_.AddValue( info::value::InternalValue(info::value::Unit()), utils::ValueType::Tmp); } else if (name == "-=") { - *arguments[0]->GetValue().value() += *arguments[1]->GetValue().value(); + *arguments[0]->GetValue().value() -= *arguments[1]->GetValue().value(); current_value_ = context_manager_.AddValue( info::value::InternalValue(info::value::Unit()), utils::ValueType::Tmp); } else if (name == "*=") { - *arguments[0]->GetValue().value() += *arguments[1]->GetValue().value(); + *arguments[0]->GetValue().value() *= *arguments[1]->GetValue().value(); current_value_ = context_manager_.AddValue( info::value::InternalValue(info::value::Unit()), utils::ValueType::Tmp); @@ -1108,7 +1142,7 @@ bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node, return false; } break; - case info::type::InternalType::String: // TODO: string is array ?? + case info::type::InternalType::String: if (name == "show") { // do not copy ?? current_value_ = context_manager_.AddValue( info::value::InternalValue(*arguments[0]->GetValue().value()), @@ -1129,6 +1163,11 @@ bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node, current_value_ = context_manager_.AddValue( info::value::InternalValue((*arguments[0]->GetValue().value())[*arguments[1]->GetValue().value()]), utils::ValueType::Tmp); + } else if (name == "=") { + *arguments[0]->GetValue().value() = *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); } else { return false; } @@ -1146,6 +1185,11 @@ bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node, current_value_ = context_manager_.AddValue( info::value::InternalValue(*arguments[0]->GetValue().value() == *arguments[1]->GetValue().value()), utils::ValueType::Tmp); + } else if (name == "=") { + *arguments[0]->GetValue().value() = *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); } else { return false; } @@ -1155,6 +1199,11 @@ bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node, current_value_ = context_manager_.AddValue( info::value::InternalValue(*arguments[0]->GetValue().value() ? "true" : "false"), utils::ValueType::Tmp); + } else if (name == "=") { + *arguments[0]->GetValue().value() = *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); } else { return false; } @@ -1164,16 +1213,22 @@ bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node, current_value_ = context_manager_.AddValue( info::value::InternalValue("()"), utils::ValueType::Tmp); + } else if (name == "=") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); } else { return false; } break; default: - // error + error_handling::HandleInternalError("Unknown basic type", + "ExecuteVisitor.HandleBuiltinTypeFunctionCall", + &node->base); break; } - return false; + return true; } return false; diff --git a/src/find_symbols_visitor.cpp b/src/find_symbols_visitor.cpp index 0db9387..ba5417c 100644 --- a/src/find_symbols_visitor.cpp +++ b/src/find_symbols_visitor.cpp @@ -121,6 +121,16 @@ void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) { node->type_id_ = namespace_visitor_.AddType(type, std::move(info), node->base); + auto maybe_graph_type_vertex = namespace_visitor_.GetTypeclassGraph()->GetTypeVertex(node->definition->type->graph_id_); + + if (!maybe_graph_type_vertex.has_value()) { + error_handling::HandleInternalError("Type vertex in TypeclassGraph is not type vertex", + "FindSymbolsVisitor.FunctionDefinitionStatement", + &node->base); + } + + maybe_graph_type_vertex.value()->type_id = node->type_id_; + // definition visited earlier Visitor::Visit(node->value); // to visit all tree } diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 896cee6..74087e7 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -797,16 +797,21 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { context[parameter_name] = current_type_; } + size_t index_shift = (node->is_method_of_first_argument_ ? 1 : 0); + // check arguments - if (function_declaration->type->types.size() != node->arguments.size() + (node->is_method_of_first_argument_ ? 0 : 1)) { + if (function_declaration->type->types.size() != node->arguments.size() + 1 - index_shift) { error_handling::HandleTypecheckError("Mismatched argument count in function call expression", node->base); } - for (size_t i = (node->is_method_of_first_argument_ ? 1 : 0); i < node->arguments.size(); ++i) { - Visitor::Visit(function_declaration->type->types[i]); + + for (size_t i = index_shift; i < node->arguments.size(); ++i) { + Visitor::Visit(function_declaration->type->types[i - index_shift]); utils::IdType argument_type = TypeInContext(current_type_, context); Visitor::Visit(node->arguments[i]); - context_manager_.AddValueRequirement(current_type_, argument_type); + if (!context_manager_.AddValueRequirement(current_type_, argument_type)) { + error_handling::HandleTypecheckError("Wrong argument type (argument " + std::to_string(i - index_shift + 1) + ")", node->base); + } } if (!utils::IsBuiltinFunction(node->name)) { diff --git a/src/types.cpp b/src/types.cpp index 0c35d92..9bf19af 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -18,15 +18,7 @@ bool AbstractType::Same(const AbstractType& type) const { } bool AbstractType::operator<(const AbstractType& type) const { // TODO: cache DependenciesSet - auto requirement_graph_ids = typeclass_graph_.GetDependenciesSet(graph_id_); - auto other_requirement_graph_ids = type.typeclass_graph_.GetDependenciesSet(type.graph_id_); - - for (auto& graph_id : requirement_graph_ids) { - if (other_requirement_graph_ids.count(graph_id) == 0) { - return false; - } - } - return true; + return typeclass_graph_.GetDependenciesSet(graph_id_).count(type.graph_id_) != 0 || graph_id_ == type.graph_id_; } bool AbstractType::operator>(const AbstractType& type) const { diff --git a/tests/test_code.lang b/tests/test_code.lang index 54904c0..04a8ecf 100644 --- a/tests/test_code.lang +++ b/tests/test_code.lang @@ -1,9 +1,9 @@ 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) +basic (String : #Ord #Show #CharContainer #Copy) +basic (Char : #Ord #Show #Copy) +basic (Bool : #Ord #Show #Copy) +basic (Unit : #Show #Copy) // @@ -197,13 +197,16 @@ decl random : -> Int // TODO // +decl ret_one : -> Int +def ret_one = 1 + decl ( -- ) : Int -> Int -> Int_0 def ( -- ) : begin end = { var current = begin return (while current < end do { - //; current += 1 + ; current += 1 + bring current //bring current - 1 - bring 1 }) } @@ -215,7 +218,7 @@ def func : s i = { } exec main { - for i in 0--9 do func: "abacaba" i + for i in 0--9 do func: "abacaba" (i - 1) ; print: ({ if true then bring scan: else { ; print: "aaa" } bring "nothing"