diff --git a/include/builtin_functions.hpp b/include/builtin_functions.hpp new file mode 100644 index 0000000..5fba95c --- /dev/null +++ b/include/builtin_functions.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +// for clangd + +namespace info::builtin { + +template +inline void Print(const T& value) { // only for strings ?? + std::cout << "\x1b[1;32mOutput:\x1b[0m " << value << '\n'; +} + +template +inline T Read() { + T value; + std::cout << "\x1b[1;32mInput:\x1b[0m "; + std::cin >> value; + return value; +} + +} // namespace info diff --git a/include/builtin_methods.hpp b/include/builtin_methods.hpp deleted file mode 100644 index 0d0cfa7..0000000 --- a/include/builtin_methods.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include - -// for clangd -#include "types.hpp" -#include "utils.hpp" - -// TODO - -namespace info { - -struct BuiltinFunction { -public: - BuiltinFunction(const std::vector& argument_types, utils::IdType return_type) - : argument_types(argument_types), return_type(return_type) {} - - static std::optional FindMethod(const std::string& name, info::type::TypeManager& type_manager) { - return std::nullopt; - } - - static std::optional FindStaticMethod(const std::string& name, info::type::TypeManager& type_manager) { - return std::nullopt; - } - -public: - std::vector argument_types; - utils::IdType return_type; -}; - -} // namespace info diff --git a/include/contexts.hpp b/include/contexts.hpp index 3993ea0..ae3825f 100644 --- a/include/contexts.hpp +++ b/include/contexts.hpp @@ -7,6 +7,7 @@ #include // for clangd +#include "error_handling.hpp" #include "utils.hpp" namespace info { @@ -15,7 +16,7 @@ template class ContextManager { public: ContextManager() { - contexts_.emplace_back(); + contexts_.emplace_back(true); // no difference ?? } template @@ -57,67 +58,103 @@ public: return &value_manager_; } - void EnterContext() { - contexts_.emplace_back(); + void EnterContext(bool is_hiding_previous = false) { + contexts_.emplace_back(is_hiding_previous); } void ExitContext() { if (contexts_.empty()) { - // error + error_handling::HandleInternalError("contexts_ is empty", + "ContextManager.ExitContext", + std::nullopt); } contexts_.pop_back(); } - void ExitFromAllContexts() { - contexts_.clear(); - contexts_.emplace_back(); + void ChangeHidingOfCurrentContextTo(bool is_hiding_previous) { + contexts_.back().ChangeHidingTo(is_hiding_previous); } bool DefineVariable(const std::string& name, utils::IdType value_id) { - // check in previous contexts ?? return contexts_.back().DefineVariable(name, value_id); } bool DefineLocalType(const std::string& name, utils::IdType type_id) { - if (GetLocalType(name).has_value()) { - return false; - } return contexts_.back().DefineLocalType(name, type_id); } + bool AssignVariable(const std::string& name, utils::IdType value_id) { + for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { + if (contexts_[i].AssignVariable(name, value_id)) { + return true; + } + + if (contexts_[i].IsHidingPrevious()) { + break; + } + } + return false; + } + + bool AssignLocalType(const std::string& name, utils::IdType type_id) { + for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { + if (contexts_[i].AssignLocalType(name, type_id)) { + return true; + } + + if (contexts_[i].IsHidingPrevious()) { + break; + } + } + return false; + } + bool RemoveVariable(const std::string& name) { for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { if (contexts_[i].RemoveVariable(name)) { return true; } + + if (contexts_[i].IsHidingPrevious()) { + break; + } } return false; } - void EnterVariableContext(const std::string& name, utils::IdType value_id) { - // for variable namespaces, for loops - contexts_.emplace_back(); + void EnterVariableContext(const std::string& name, + utils::IdType value_id, + bool is_hiding_previous = false) { + EnterContext(is_hiding_previous); DefineVariable(name, value_id); } - std::optional GetVariableInfo(const std::string& name) { + std::optional FindVariable(const std::string& name) { for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { - auto maybe_type = contexts_[i].GetVariableInfo(name); - if (maybe_type.has_value()) { - return maybe_type.value(); + auto maybe_variable = contexts_[i].FindVariable(name); + if (maybe_variable.has_value()) { + return maybe_variable.value(); + } + + if (contexts_[i].IsHidingPrevious()) { + break; } } return std::nullopt; } - std::optional GetLocalType(const std::string& name) { + std::optional FindLocalType(const std::string& name) { for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { - auto maybe_type = contexts_[i].GetLocalType(name); + auto maybe_type = contexts_[i].FindLocalType(name); if (maybe_type.has_value()) { return maybe_type.value(); } + + if (contexts_[i].IsHidingPrevious()) { + break; + } } return std::nullopt; } @@ -125,10 +162,10 @@ public: private: class Context { public: - Context() = default; + explicit Context(bool is_hiding_previous) : is_hiding_previous_(is_hiding_previous) {} bool DefineVariable(const std::string& name, utils::IdType value_id) { - if (name == "_") { // placeholder // TODO: ?? + if (name == "_") { // placeholder return true; } @@ -147,11 +184,33 @@ private: return true; } + bool AssignVariable(const std::string& name, utils::IdType value_id) { + if (name == "_") { // placeholder + return true; + } + + auto variable_iter = variables_.find(name); + if (variable_iter == variables_.end()) { + return false; + } + variable_iter->second = value_id; + return true; + } + + bool AssignLocalType(const std::string& name, utils::IdType type_id) { + auto local_type_iter = local_types_.find(name); + if (local_type_iter == local_types_.end()) { + return false; + } + local_type_iter->second = type_id; + return true; + } + bool RemoveVariable(const std::string& name) { return variables_.erase(name); } - std::optional GetVariableInfo(const std::string& name) { + std::optional FindVariable(const std::string& name) { auto variable_iter = variables_.find(name); if (variable_iter == variables_.end()) { @@ -161,7 +220,7 @@ private: return variable_iter->second; } - std::optional GetLocalType(const std::string& name) { + std::optional FindLocalType(const std::string& name) { auto local_abstract_type_iter = local_types_.find(name); if (local_abstract_type_iter == local_types_.end()) { @@ -171,9 +230,19 @@ private: return local_abstract_type_iter->second; } + bool IsHidingPrevious() { + return is_hiding_previous_; + } + + void ChangeHidingTo(bool is_hiding_previous) { + is_hiding_previous_ = is_hiding_previous; + } + private: std::unordered_map variables_; std::unordered_map local_types_; + + bool is_hiding_previous_ = false; }; std::vector contexts_; diff --git a/include/error_handling.hpp b/include/error_handling.hpp index 690cb72..619e51c 100644 --- a/include/error_handling.hpp +++ b/include/error_handling.hpp @@ -34,8 +34,15 @@ inline void HandleGeneralError(const std::string& message) { exit(1); } -inline void HandleInternalError(const std::string& message, const std::string& place) { - std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at " << place << ".\n"; +inline void HandleInternalError(const std::string& message, + const std::string& place, + std::optional node) { + std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at " << place; + if (node.has_value()) { + std::cerr << ", at "; + PrintPosition(std::cerr, node.value()->start_position, node.value()->end_position); + } + std::cerr << ".\n"; exit(1); } diff --git a/include/execute_visitor.hpp b/include/execute_visitor.hpp index 3e31aec..53dd7db 100644 --- a/include/execute_visitor.hpp +++ b/include/execute_visitor.hpp @@ -24,8 +24,10 @@ public: type_context_manager_(type_context_manager), context_manager_(context_manager) {} - void VisitSourceFile(SourceFile*) override { - error_handling::HandleInternalError("VisitSourceFile unavailible", "ExecuteVisitor.VisitSourceFile"); + void VisitSourceFile(SourceFile* node) override { + error_handling::HandleInternalError("VisitSourceFile unavailible", + "ExecuteVisitor.VisitSourceFile", + &node->base); }; void ExecutePartition(interpreter::tokens::PartitionStatement* partition) { @@ -157,6 +159,13 @@ private: } return maybe_internal_value_info.value(); } + + // + + bool HandleBuiltinFunctionCall(FunctionCallExpression* node); + + bool HandleBuiltinTypeclassFunctionCall(FunctionCallExpression* node); + private: info::GlobalInfo& global_info_; info::TypeclassGraph& typeclass_graph_; diff --git a/include/interpreter_tree.hpp b/include/interpreter_tree.hpp index 0c68668..2635490 100644 --- a/include/interpreter_tree.hpp +++ b/include/interpreter_tree.hpp @@ -523,6 +523,9 @@ struct FunctionCallExpression { // only one from two is present std::optional function_id_; std::optional graph_id_; // for type or typeclass + + std::optional abstract_type_name_; // for typeclasses + bool is_method_of_first_argument_ = false; }; diff --git a/include/type_check_visitor.hpp b/include/type_check_visitor.hpp index 213f105..c5bd669 100644 --- a/include/type_check_visitor.hpp +++ b/include/type_check_visitor.hpp @@ -162,6 +162,13 @@ private: FunctionCallExpression* node, info::definition::AnyType* defined_type, bool is_method); + + // + + bool HandleBuiltinFunctionCall(FunctionCallExpression* node); + + bool HandleBuiltinTypeclassFunctionCall(FunctionCallExpression* node); + private: info::GlobalInfo::NamespaceVisitor namespace_visitor_; info::GlobalInfo& global_info_; diff --git a/include/types.hpp b/include/types.hpp index 14d63ee..f6c99f6 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -44,6 +44,10 @@ public: std::optional GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const; + const std::string& GetName() { + return name_; + } + bool HasTypeclass(utils::IdType graph_id) { return requirement_graph_ids_.count(graph_id) != 0; } diff --git a/src/build_visitor.cpp b/src/build_visitor.cpp index 49c0cd6..239ba67 100644 --- a/src/build_visitor.cpp +++ b/src/build_visitor.cpp @@ -62,7 +62,9 @@ void BuildVisitor::Visit(Namespace* node) { } else if (modifier == "var") { node->modifier = utils::ClassInternalsModifier::Var; } else { - error_handling::HandleInternalError("Can't parse namespace modifier", "BuildVisitor.Namespace"); + error_handling::HandleInternalError("Can't parse namespace modifier", + "BuildVisitor.Namespace", + &node->base); } } else { node->modifier = utils::ClassInternalsModifier::Static; diff --git a/src/execute_visitor.cpp b/src/execute_visitor.cpp index 8b8363f..5498c20 100644 --- a/src/execute_visitor.cpp +++ b/src/execute_visitor.cpp @@ -1,9 +1,11 @@ -// for clangd -#include "../include/execute_visitor.hpp" -#include #include #include +// for clangd +#include "../include/execute_visitor.hpp" +#include "../include/builtin_functions.hpp" + + // TODO namespace interpreter { @@ -46,7 +48,9 @@ void ExecuteVisitor::Visit(FunctionDeclaration*) {} // no value void ExecuteVisitor::Visit(FunctionDefinitionStatement* node) { // visited on function call // Visit(node->definition.get()); + context_manager_.EnterContext(); Visitor::Visit(node->value); + context_manager_.ExitContext(); } void ExecuteVisitor::Visit(TypeDefinitionStatement*) {} // no value @@ -244,8 +248,12 @@ void ExecuteVisitor::Visit(ForLoop* node) { info::value::ArrayValue* interval = ExtractValue(current_value_, node->base); for (auto& value : interval->elements) { + context_manager_.EnterContext(); // TODO + current_value_ = value; - Visitor::Visit(node->variable); + is_const_definition_ = node->variable_modifier; + Visitor::Visit(node->variable); // TODO: assign variable, instead of making new + is_const_definition_ = std::nullopt; Visitor::Visit(node->statement); if (active_loop_control_expression_.has_value()) { @@ -258,6 +266,8 @@ void ExecuteVisitor::Visit(ForLoop* node) { } result.push_back(current_value_); + + context_manager_.ExitContext(); // TODO } current_value_ = context_manager_.AddValue( @@ -302,10 +312,11 @@ void ExecuteVisitor::Visit(Block* node) { Visitor::Visit(statement); if (returned_value_.has_value()) { current_value_ = returned_value_.value(); - returned_value_ = std::nullopt; // ?? + returned_value_ = std::nullopt; // TODO: ?? ("return" exits only from one block) return; } } + context_manager_.ExitContext(); current_value_ = context_manager_.AddValue( @@ -326,36 +337,6 @@ void ExecuteVisitor::Visit(LoopControlExpression& node) { // Operators -// TODO: function call expression used instead -///////////////////////////////////////////////// -// void ExecuteVisitor::Visit(BinaryOperatorExpression* node) { -// context_manager_.EnterContext(); -// -// auto maybe_function_definition = global_info_.GetFunctionInfo(node->function_id_).definition; -// -// if (maybe_function_definition.has_value()) { -// Visitor::Visit(node->left_expression); -// // TODO: custom argument value types, references, etc. -// current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); -// context_manager_.DefineVariable( -// node->is_method_ ? utils::ClassInternalVarName : maybe_function_definition.value().argument_names[0], -// current_value_); -// -// Visitor::Visit(node->left_expression); -// // TODO: custom argument value types, references, etc. -// current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); -// context_manager_.DefineVariable(maybe_function_definition.value().argument_names[node->is_method_ ? 0 : 1], current_value_); -// -// Visit(maybe_function_definition.value().node); -// } else { -// // TODO: builtin operators, etc. (imports?) -// error_handling::HandleRuntimeError("Binary operator definition not found", node->base); -// } -// -// context_manager_.ExitContext(); -// } -///////////////////////////////////////////////// - void ExecuteVisitor::Visit(ReferenceExpression* node) { // TODO: check, that there is no references to "Tmp"?? Visit(node->expression.get()); @@ -385,18 +366,18 @@ void ExecuteVisitor::Visit(AccessExpression* node) { // Other Expressions -// TODO -// TODO: typeclass functions -// TODO: builtin functions -// TODO: binary operator expression +// TODO: refactor, separate to several functions +// TODO: more builtin functions, better handling (??) void ExecuteVisitor::Visit(FunctionCallExpression* node) { context_manager_.EnterContext(); if (node->prefix.has_value()) { if (std::holds_alternative>(node->prefix.value())) { Visitor::Visit(*std::get>(node->prefix.value())); - // modify value on const methods, etc. ?? - context_manager_.DefineVariable(utils::ClassInternalVarName, current_value_); + + if (!context_manager_.DefineVariable(utils::ClassInternalVarName, current_value_)) { + error_handling::HandleRuntimeError("Variable redefinition (mathod caller var)", node->base); + } } else if (std::holds_alternative>(node->prefix.value())) { TypeExpression& prefix = *std::get>(node->prefix.value()); @@ -407,46 +388,135 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) { CollectTypeContext(prefix.type); } else { - // error + error_handling::HandleInternalError("Unexpected prefix type", + "ExecuteVisitor.FunctionCallExpression", + &node->base); } } else { if (node->is_method_of_first_argument_) { Visitor::Visit(node->arguments[0]); - context_manager_.DefineVariable(utils::ClassInternalVarName, current_value_); + if (!context_manager_.DefineVariable(utils::ClassInternalVarName, current_value_)) { + error_handling::HandleRuntimeError("Variable redefinition (mathod caller var)", node->base); + } } - // TODO } - if (!node->function_id_.has_value()) { - // TODO: typeclass function - error_handling::HandleInternalError("Typeclass functions not implemented yet", - "ExecuteVisitor.FunctionCallExpression"); - } + FunctionDeclaration* function_declaration = nullptr; + FunctionDefinitionStatement* function_definition = nullptr; - auto function_declaration = global_info_.GetFunctionInfo(node->function_id_.value()).declaration.value(); // checked in type_check_visitor + if (node->function_id_.has_value()) { + auto maybe_function_declaration_info = global_info_.GetFunctionInfo(node->function_id_.value()).declaration; + + if (!maybe_function_declaration_info.has_value()) { + error_handling::HandleRuntimeError("Function declaration not found (for namespace function)", node->base); + // always namespace function ?? + } + + function_declaration = maybe_function_declaration_info.value().node; + + auto maybe_function_definition_info = global_info_.GetFunctionInfo(node->function_id_.value()).definition; + + if (!maybe_function_definition_info.has_value()) { + if (HandleBuiltinFunctionCall(node)) { + return; + } + + error_handling::HandleRuntimeError("Function definition not found (by graph_id_)", node->base); + } + + function_definition = maybe_function_definition_info.value().node; + + } else if (node->graph_id_.has_value()) { + std::optional maybe_function_definition; + + auto maybe_function_graph_info = typeclass_graph_.GetFunctionInfo(node->name, + node->graph_id_.value()); + + if (!maybe_function_graph_info.has_value()) { + error_handling::HandleRuntimeError("Function info not found (by graph_id_)", node->base); + } + + function_declaration = maybe_function_graph_info.value()->declaration; + maybe_function_definition = maybe_function_graph_info.value()->definition; + + if (!maybe_function_definition.has_value()) { + if (typeclass_graph_.GetVertex(node->graph_id_.value()).modifier == info::TypeclassGraph::Modifier::Type) { + 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", + "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()) { + error_handling::HandleRuntimeError("Function's abstract type replacement defined type is not AnyType", node->base); + } + + maybe_function_graph_info = typeclass_graph_.GetFunctionInfo(node->name, maybe_type_info.value()->type.node->graph_id_); + + if (!maybe_function_graph_info.has_value()) { + error_handling::HandleRuntimeError("Function info not found (by abstract type graph_id_)", node->base); + } + + maybe_function_definition = maybe_function_graph_info.value()->definition; + } + + if (!maybe_function_definition.has_value()) { + if (HandleBuiltinTypeclassFunctionCall(node)) { + return; + } + + error_handling::HandleRuntimeError("Function definition not found (by graph_id_)", node->base); + } + + function_definition = maybe_function_definition.value(); + } for (size_t i = 0; i < node->parameters.size(); ++i) { - // TODO: local abstract types, absract types, etc. + utils::IdType type_id = 0; - context_manager_.DefineLocalType(function_declaration.parameters[i].type, node->parameters[i]->type_id_.value()); // TODO: check - } + if (node->parameters[i]->type_id_.has_value()) { + type_id = node->parameters[i]->type_id_.value(); + } else { + auto maybe_parameter_type_id = context_manager_.FindLocalType(node->parameters[i]->type.type); - auto maybe_function_definition = global_info_.GetFunctionInfo(node->function_id_.value()).definition; + if (!maybe_parameter_type_id.has_value()) { + error_handling::HandleInternalError("Parameter type not found", + "ExecuteVisitor.FunctionCallExpression", + &node->base); + } - if (maybe_function_definition.has_value()) { - for (size_t i = (node->is_method_of_first_argument_ ? 1 : 0); i < node->arguments.size(); ++i) { - Visitor::Visit(node->arguments[i]); - // TODO: custom argument value types, references, etc. - current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); - context_manager_.DefineVariable(maybe_function_definition.value().argument_names[i], current_value_); + type_id = maybe_parameter_type_id.value(); } - Visit(maybe_function_definition.value().node); - } else { - error_handling::HandleRuntimeError("Function definition not found", node->base); - // TODO: functions, defined in typeclasses ?? + if (!context_manager_.DefineLocalType(function_declaration->parameters[i]->type, + type_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) { + Visitor::Visit(node->arguments[i]); + + current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); + if (!context_manager_.DefineVariable(function_definition->definition->arguments[i], + current_value_)) { + error_handling::HandleRuntimeError("Variable redefinition (function argument)", node->base); + } + } + + context_manager_.ChangeHidingOfCurrentContextTo(true); + Visit(function_definition); + context_manager_.ExitContext(); } @@ -534,9 +604,10 @@ void ExecuteVisitor::Visit(TypeConstructor* node) { } // TODO -void ExecuteVisitor::Visit(LambdaFunction*) { +void ExecuteVisitor::Visit(LambdaFunction* node) { error_handling::HandleInternalError("Lambda function are not implemented yet", - "ExecuteVisitor.LambdaFunction"); + "ExecuteVisitor.LambdaFunction", + &node->base); } void ExecuteVisitor::Visit(ArrayExpression* node) { @@ -557,11 +628,13 @@ void ExecuteVisitor::Visit(ArrayExpression* node) { void ExecuteVisitor::Visit(NameExpression* node) { // TODO: check if (node->names.empty()) { - error_handling::HandleInternalError("Names array is empty", "ExecuteVisitor.NameExpression"); + error_handling::HandleInternalError("Names array is empty", + "ExecuteVisitor.NameExpression", + &node->base); } std::optional maybe_variable_value = - context_manager_.GetVariableInfo(node->names[0]); + context_manager_.FindVariable(node->names[0]); if (!maybe_variable_value.has_value()) { error_handling::HandleRuntimeError("Variable not found", node->base); @@ -599,7 +672,9 @@ void ExecuteVisitor::Visit(TupleName* node) { // TODO: check } if (!is_const_definition_.has_value()) { - error_handling::HandleInternalError("No value in is_const_definition_", "TypeCheckVisitor.TupleName"); + error_handling::HandleInternalError("No value in is_const_definition_", + "TypeCheckVisitor.TupleName", + &node->base); } utils::ValueType value_type = context_manager_.GetValueType(value); @@ -667,7 +742,8 @@ void ExecuteVisitor::Visit(AnnotatedName* node) { // TODO: check if (!is_const_definition_.has_value()) { error_handling::HandleInternalError("No value in is_const_definition_", - "TypeCheckVisitor.AnnotatedName"); + "TypeCheckVisitor.AnnotatedName", + &node->base); } utils::ValueType value_type = context_manager_.GetValueType(current_value_); @@ -749,16 +825,26 @@ bool ExecuteVisitor::HandleCondition(Expression& node, const BaseNode& base_node return *ExtractInternalValue(current_value_, base_node); } -// TODO: handle abstract types, handle local abstract types, etc. +// TODO: handle abstract types, handle local abstract types, etc. // partially done (check needed) void ExecuteVisitor::CollectTypeContext(const ParametrizedType& type) { + utils::IdType type_id = 0; + if (!type.type_id_.has_value()) { - return; + 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 + } else { + type_id = type.type_id_.has_value(); } - auto maybe_type_info = global_info_.GetTypeInfo(type.type_id_.value()); + auto maybe_type_info = global_info_.GetTypeInfo(type_id); if (!maybe_type_info.has_value()) { - error_handling::HandleInternalError("CollectTypeContext unimplemented anything except AnyType", "ExecuteVisitor.CollectTYpeContext"); + error_handling::HandleInternalError("CollectTypeContext implemented only for AnyType", + "ExecuteVisitor.CollectTYpeContext", + std::nullopt); } info::definition::AnyType& type_info = *maybe_type_info.value(); // check, that has value ?? @@ -771,7 +857,6 @@ void ExecuteVisitor::CollectTypeContext(const ParametrizedType& type) { } } -// TODO void ExecuteVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) { utils::IdType value = current_value_; @@ -798,5 +883,34 @@ 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 == "read") { + current_value_ = context_manager_.AddValue(info::value::InternalValue(info::builtin::Read()), + utils::ValueType::Tmp); + return true; + } + + return false; +} + +bool ExecuteVisitor::HandleBuiltinTypeclassFunctionCall(FunctionCallExpression*) { + return false; +} + } // namespace interpreter diff --git a/src/find_symbols_visitor.cpp b/src/find_symbols_visitor.cpp index 654590d..80d56c2 100644 --- a/src/find_symbols_visitor.cpp +++ b/src/find_symbols_visitor.cpp @@ -195,7 +195,8 @@ void FindSymbolsVisitor::Visit(AnyAnnotatedType* node) { if (!maybe_typeclass_graph_id.has_value()) { error_handling::HandleInternalError("Can't add annotated type to typeclass graph", - "FindSymbolsVisitor.AnyAnnotatedType"); + "FindSymbolsVisitor.AnyAnnotatedType", + &node->base); } node->graph_id_ = maybe_typeclass_graph_id.value(); diff --git a/src/global_info.cpp b/src/global_info.cpp index bd35db5..1206937 100644 --- a/src/global_info.cpp +++ b/src/global_info.cpp @@ -69,13 +69,15 @@ void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& name, } error_handling::HandleInternalError("Can't find namespace " + name, - "GlobalInfo.NamespaceVisitor.EnterNamespace"); + "GlobalInfo.NamespaceVisitor.EnterNamespace", + std::nullopt); } void GlobalInfo::NamespaceVisitor::ExitNamespace() { if (namespace_stack_.size() <= 1) { error_handling::HandleInternalError("Can't exit from global namespace", - "GlobalInfo.NamespaceVisitor.ExitNamespace"); + "GlobalInfo.NamespaceVisitor.ExitNamespace", + std::nullopt); return; } @@ -169,7 +171,8 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, if (!std::holds_alternative(moved_type_info.type)) { error_handling::HandleInternalError("Not AnyType constructor search is not implemented yet", - "GlobalInfo.NamespaceVisitor.AddType"); + "GlobalInfo.NamespaceVisitor.AddType", + &base_node); } definition::AnyType& any_type_info = std::get(moved_type_info.type); @@ -198,7 +201,8 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, } } else { error_handling::HandleInternalError("Unexprected VariantType constructor node type", - "GlobalInfo.NamespaceVisitor.AddType"); + "GlobalInfo.NamespaceVisitor.AddType", + &base_node); } constructor_info.name = constructor_name; @@ -216,7 +220,8 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, } else { // TODO: constructors for function types (??), array types (??), ... error_handling::HandleInternalError("Not VariantType constructor search is not implemented yet", - "GlobalInfo.NamespaceVisitor.AddType"); + "GlobalInfo.NamespaceVisitor.AddType", + &base_node); } return id; @@ -466,7 +471,8 @@ std::optional GlobalInfo::GetTypeNamespace(utils::IdType if (!maybe_type_info.has_value()) { error_handling::HandleInternalError("Only AnyType is supported now", - "GlobalInfo.GetTypeNamespace"); + "GlobalInfo.GetTypeNamespace", + std::nullopt); } std::string& name = maybe_type_info.value()->type.type; @@ -511,7 +517,8 @@ std::optional GlobalInfo::AddTypeclassToGraph(utils::IdType typec std::string dependency = dependency_node->typeclass; if (dependency_node->parameters.size() > 0) { error_handling::HandleInternalError("Paramtrized typeclass requirements are not implemented yet", - "GlobalInfo.AddTypeclassToGraph"); + "GlobalInfo.AddTypeclassToGraph", + std::nullopt); } dependencies.push_back(dependency); } @@ -557,7 +564,8 @@ std::optional GlobalInfo::AddAnnotatedTypeToGraph(interpreter::to std::string dependency = dependency_node->typeclass; if (dependency_node->parameters.size() > 0) { error_handling::HandleInternalError("Paramtrized typeclass requirements are not implemented yet", - "GlobalInfo.AddAnnotatedTypeToGraph"); + "GlobalInfo.AddAnnotatedTypeToGraph", + &node->base); } dependencies.push_back(dependency); } diff --git a/src/link_symbols_visitor.cpp b/src/link_symbols_visitor.cpp index 720a797..37454fc 100644 --- a/src/link_symbols_visitor.cpp +++ b/src/link_symbols_visitor.cpp @@ -172,7 +172,8 @@ void LinkSymbolsVisitor::AddTypeFunctionsToTypeclassGraph(utils::IdType type_id, auto maybe_type_graph_info = typeclass_graph_.GetTypeVertex(graph_id); if (!maybe_type_graph_info.has_value()) { error_handling::HandleInternalError("Type in typeclass graph is not marked as type", - "LinkSymbolsVisitor.AddTypeFunctionsToTypeclassGraph"); + "LinkSymbolsVisitor.AddTypeFunctionsToTypeclassGraph", + &base_node); } auto type_graph_info = maybe_type_graph_info.value(); @@ -207,7 +208,8 @@ void LinkSymbolsVisitor::AddTypeFunctionsToTypeclassGraph(utils::IdType type_id, } error_handling::HandleInternalError("This code should be unreachable", - "LinkSymbolsVisitor.AddTypeFunctionsToTypeclassGraph"); + "LinkSymbolsVisitor.AddTypeFunctionsToTypeclassGraph", + &base_node); } } } diff --git a/src/main.cpp b/src/main.cpp index f8eea47..9d73e0c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,16 +48,16 @@ int main(int argc, char** argv) { // TODO, only test version info::ContextManager context_manager; interpreter::BuildVisitor build_visitor(parse_tree); - interpreter::PrintVisitor print_visitor(std::cout); + // interpreter::PrintVisitor print_visitor(std::cout); interpreter::FindSymbolsVisitor find_symbols_visitor(global_info); interpreter::LinkSymbolsVisitor link_symbols_visitor(global_info); interpreter::TypeCheckVisitor type_check_visitor(global_info, type_context_manager); - interpreter::TypedPrintVisitor typed_print_visitor(std::cout, type_context_manager); + // interpreter::TypedPrintVisitor typed_print_visitor(std::cout, type_context_manager); build_visitor.VisitSourceFile(source_file.get()); - std::cout << "\n---------------------------------- Untyped -------------------------------------\n\n"; - print_visitor.VisitSourceFile(source_file.get()); + // std::cout << "\n---------------------------------- Untyped -------------------------------------\n\n"; + // print_visitor.VisitSourceFile(source_file.get()); find_symbols_visitor.VisitSourceFile(source_file.get()); link_symbols_visitor.VisitSourceFile(source_file.get()); @@ -73,11 +73,11 @@ int main(int argc, char** argv) { // TODO, only test version global_info.GetPartitionInfo(maybe_main_partition_id.value()); interpreter::ExecuteVisitor execute_visitor(global_info, - type_context_manager, - context_manager); + type_context_manager, + context_manager); execute_visitor.ExecutePartition(main_partition.node); - std::cout << "\n---------------------------------- Typed -------------------------------------\n\n"; - typed_print_visitor.VisitSourceFile(source_file.get()); + // std::cout << "\n---------------------------------- Typed -------------------------------------\n\n"; + // typed_print_visitor.VisitSourceFile(source_file.get()); } diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 98100db..6a7f90d 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -112,9 +112,10 @@ void TypeCheckVisitor::Visit(Namespace* node) { void TypeCheckVisitor::Visit(ImportStatement*) {} // TODO -void TypeCheckVisitor::Visit(AliasDefinitionStatement*) { +void TypeCheckVisitor::Visit(AliasDefinitionStatement* node) { error_handling::HandleInternalError("Unimplemented", - "TypeCheckVisitor.AliasDefinitionStatement"); + "TypeCheckVisitor.AliasDefinitionStatement", + &node->base); } void TypeCheckVisitor::Visit(VariableDefinitionStatement* node) { @@ -194,7 +195,8 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { if (maybe_curent_type.has_value() && maybe_current_typeclass.has_value()) { error_handling::HandleInternalError("Current namespace is belong to type and typeclass in same time", - "TypeCheckVisitor.FunctionDefinitionStatement"); + "TypeCheckVisitor.FunctionDefinitionStatement", + &node->base); } if (!maybe_curent_type.has_value() && !maybe_current_typeclass.has_value()) { @@ -219,7 +221,8 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { auto maybe_function_info = typeclass_graph_.GetFunctionInfo(function_name, std::nullopt); if (!maybe_function_info.has_value()) { error_handling::HandleInternalError("FunctionInfo not found", - "TypeCheckVisitor.FunctionDefinitionStatement"); + "TypeCheckVisitor.FunctionDefinitionStatement", + &node->base); } declaration = maybe_function_info.value()->declaration; // TODO: save declaration to global info ?? @@ -367,7 +370,8 @@ void TypeCheckVisitor::Visit(TypeConstructorPattern* node) { // TODO: match name if (!node->constructor->type_id_.has_value()) { error_handling::HandleInternalError("Type constructor pattern without type", - "TypeCheckVisitor.TypeConstructorPattern"); + "TypeCheckVisitor.TypeConstructorPattern", + &node->base); } utils::IdType constructor_id = node->constructor->constructor_id_.value(); @@ -384,7 +388,8 @@ void TypeCheckVisitor::Visit(TypeConstructorPattern* node) { // TODO: match name if (!maybe_type_info.has_value()) { error_handling::HandleInternalError("Implemented only for AnyType", - "TypeCheckVisitor.TypeConstructorPattern"); + "TypeCheckVisitor.TypeConstructorPattern", + &node->base); } info::definition::AnyType& type_info = *maybe_type_info.value(); @@ -712,17 +717,20 @@ void TypeCheckVisitor::Visit(AccessExpression* node) { // Other Expressions -// TODO: builtin functions / methods -// TODO: find & check definitions +// TODO: more builtin functions, better handling (??) void TypeCheckVisitor::Visit(FunctionCallExpression* node) { std::optional maybe_function_declaration; std::unordered_map context; - // guaranteed, that name.size() > 0 + if (node->name.empty()) { + error_handling::HandleInternalError("Empty name", + "TypeCheckVisitor.FunctionCallExpression", + &node->base); + } + if (node->name[0] == '_') { - error_handling::HandleInternalError("Builtin functions/methods weren't implemented yet", - "TypeCheckVisitor.FunctionCallExpresssion"); + error_handling::HandleTypecheckError("Only builtin functions can start with _. This function not found", node->base); } // try to find function declaration @@ -737,7 +745,8 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { context); } else { error_handling::HandleInternalError("Unexpected prefix type", - "TypeCheckVisitor.FunctionCallExpression"); + "TypeCheckVisitor.FunctionCallExpression", + &node->base); } } else { maybe_function_declaration = FindFunctionAndUpdate(node); @@ -760,7 +769,8 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { if (context.count(parameter_name) != 0) { error_handling::HandleInternalError("Local abstract types with same name in one context", - "TypeCheckVisitor.FunctionCallExpresssion"); + "TypeCheckVisitor.FunctionCallExpresssion", + &node->base); } context[parameter_name] = current_type_; } @@ -779,7 +789,11 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { if (node->function_id_.has_value()) { if (!global_info_.GetFunctionInfo(node->function_id_.value()).definition.has_value()) { - error_handling::HandleTypecheckError("No function definition found (non-type function)", node->base); + if (HandleBuiltinFunctionCall(node)) { + return; // current_type_ - from HandleBuiltinFunctionCall + } + + error_handling::HandleTypecheckError("No function definition found (namespace function)", node->base); } } else if (node->graph_id_.has_value()) { if (typeclass_graph_.GetVertex(node->graph_id_.value()).modifier != info::TypeclassGraph::Modifier::Typeclass) { @@ -787,16 +801,22 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { if (!maybe_graph_function_info.has_value()) { error_handling::HandleInternalError("FunctionInfo by graph_id_ not found", - "TypeCheckVisitor.FunctionCallExpression"); + "TypeCheckVisitor.FunctionCallExpression", + &node->base); } if (!maybe_graph_function_info.value()->definition.has_value()) { + if (HandleBuiltinTypeclassFunctionCall(node)) { + return; // current_type_ - from HandleBuiltinTypeclassFunctionCall + } + error_handling::HandleTypecheckError("No function definition found (type function)", node->base); } } } else { error_handling::HandleInternalError("No function_id_ and graph_id_ found", - "TypeCheckVisitor.FunctionCallExpression"); + "TypeCheckVisitor.FunctionCallExpression", + &node->base); } Visitor::Visit(function_declaration->type->types.back()); @@ -846,6 +866,8 @@ void TypeCheckVisitor::Visit(ReturnExpression* node) { Visitor::Visit(node->expression); returned_type_ = current_type_; + current_type_ = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp); + node->base.type_ = current_type_; } @@ -858,7 +880,9 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { } if (!node->constructor->type_id_.has_value()) { - error_handling::HandleInternalError("Type constructor without type", "TypeCheckVisitor.TypeConstructor"); + error_handling::HandleInternalError("Type constructor without type", + "TypeCheckVisitor.TypeConstructor", + &node->base); } utils::IdType constructor_id = node->constructor->constructor_id_.value(); @@ -876,7 +900,8 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { if (!maybe_type_info.has_value()) { // TODO error_handling::HandleInternalError("Implemented only for AnyType", - "TypeCheckVisitor.TypeConstructor"); + "TypeCheckVisitor.TypeConstructor", + &node->base); } info::definition::AnyType& type_info = *maybe_type_info.value(); @@ -925,7 +950,9 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { if (maybe_variant_type.has_value()) { if (!constructor_info.order.has_value()) { - error_handling::HandleInternalError("No order found in constructor of VariantType", "TypeCheckVisitor.TypeConstructor"); + error_handling::HandleInternalError("No order found in constructor of VariantType", + "TypeCheckVisitor.TypeConstructor", + &node->base); } maybe_variant_type.value()->SetCurrentConstructor(constructor_info.order.value()); } @@ -944,7 +971,8 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { // TODO void TypeCheckVisitor::Visit(LambdaFunction* node) { error_handling::HandleInternalError("Unimplemented (unsolved type deduction problems)", - "TypeCheckVisitor.LambdaFunction"); + "TypeCheckVisitor.LambdaFunction", + &node->base); node->base.type_ = current_type_; } @@ -964,7 +992,9 @@ void TypeCheckVisitor::Visit(ArrayExpression* node) { } if (node->elements.empty()) { - error_handling::HandleInternalError("Element size is 0", "TypeCheckVisitor.ArrayExpression"); + error_handling::HandleInternalError("Element size is 0", + "TypeCheckVisitor.ArrayExpression", + &node->base); } current_type_ = context_manager_.AddValue( @@ -981,10 +1011,12 @@ void TypeCheckVisitor::Visit(PartitionName*) {} // Handled in partition ( execut void TypeCheckVisitor::Visit(NameExpression* node) { // TODO: move, etc. if (node->names.empty()) { - error_handling::HandleInternalError("Name expression with zero names", "TypeCheckVisitor.NameExpression"); + error_handling::HandleInternalError("Name expression with zero names", + "TypeCheckVisitor.NameExpression", + &node->base); } - auto maybe_variable_type = context_manager_.GetVariableInfo(node->names[0]); + auto maybe_variable_type = context_manager_.FindVariable(node->names[0]); if (!maybe_variable_type.has_value()) { error_handling::HandleTypecheckError("Variable not found", node->base); @@ -1019,18 +1051,20 @@ void TypeCheckVisitor::Visit(TupleName* node) { type = maybe_defined_type_value.value()->GetType(); } - std::optional maybe_type_value = context_manager_.GetValue(type); - - if (maybe_type_value.has_value()) { + auto maybe_type_value = context_manager_.GetValue(type); + if (!maybe_type_value.has_value()) { error_handling::HandleTypecheckError("Mismatched types in tuple variable definition", node->base); } + info::type::TupleType* type_value = maybe_type_value.value(); - if (maybe_type_value.value()->GetFields().size() != node->names.size()) { + if (type_value->GetFields().size() != node->names.size()) { error_handling::HandleTypecheckError("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"); + error_handling::HandleInternalError("No value in is_const_definition_", + "TypeCheckVisitor.TupleName", + &node->base); } utils::ValueType value_type = context_manager_.GetValueType(type); @@ -1040,7 +1074,7 @@ void TypeCheckVisitor::Visit(TupleName* node) { } for (size_t i = 0; i < node->names.size(); ++i) { - current_type_ = maybe_type_value.value()->GetFields()[i].second; + current_type_ = type_value->GetFields()[i].second; if (value_type == utils::ValueType::Tmp) { // TODO: ?? current_type_ = context_manager_.ToModifiedValue(current_type_, utils::ValueType::Tmp); @@ -1062,18 +1096,20 @@ void TypeCheckVisitor::Visit(VariantName* node) { type = maybe_defined_type_value.value()->GetType(); } - std::optional maybe_type_value = context_manager_.GetValue(type); - + auto maybe_type_value = context_manager_.GetValue(type); if (!maybe_type_value.has_value()) { error_handling::HandleTypecheckError("Mismatched types in variant variable definition", node->base); } + info::type::VariantType* type_value = maybe_type_value.value(); - if (maybe_type_value.value()->GetConstructors().size() != node->names.size()) { + if (type_value->GetConstructors().size() != node->names.size()) { error_handling::HandleTypecheckError("Mismatched variant count in variant variable definition", node->base); } if (!is_const_definition_.has_value()) { - error_handling::HandleInternalError("No value in is_const_definition_", "TypeCheckVisitor.VariantName"); + error_handling::HandleInternalError("No value in is_const_definition_", + "TypeCheckVisitor.VariantName", + &node->base); } utils::ValueType value_type = context_manager_.GetValueType(type); @@ -1083,14 +1119,14 @@ void TypeCheckVisitor::Visit(VariantName* node) { } for (size_t i = 0; i < node->names.size(); ++i) { - if (maybe_type_value.value()->GetConstructors()[i].GetFields().empty()) { + if (type_value->GetConstructors()[i].GetFields().empty()) { current_type_ = context_manager_.AddValue( info::type::OptionalType( context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp), context_manager_.GetValueManager()), utils::IsConstModifierToValueType(is_const_definition_.value())); // TODO ?? } else { - info::type::TupleType constructor_type_value = maybe_type_value.value()->GetConstructors()[i]; + info::type::TupleType constructor_type_value = type_value->GetConstructors()[i]; utils::IdType constructor_type = context_manager_.AddValue(std::move(constructor_type_value), @@ -1113,7 +1149,8 @@ void TypeCheckVisitor::Visit(AnnotatedName* node) { if (!is_const_definition_.has_value()) { error_handling::HandleInternalError("No value in is_const_definition_", - "TypeCheckVisitor.AnnotatedName"); + "TypeCheckVisitor.AnnotatedName", + &node->base); } utils::ValueType value_type = context_manager_.GetValueType(type); @@ -1190,7 +1227,9 @@ void TypeCheckVisitor::Visit(VariantType* node) { Visit(std::get>(constructor).get()); std::optional maybe_constructor = context_manager_.GetValue(current_type_); if (!maybe_constructor.has_value()) { - error_handling::HandleInternalError("Entity of VariantType is not TupleType", "TypeCheckVisitor.VariantType"); + error_handling::HandleInternalError("Entity of VariantType is not TupleType", + "TypeCheckVisitor.VariantType", + &node->base); } constructors.push_back(*maybe_constructor.value()); } else { @@ -1222,7 +1261,7 @@ void TypeCheckVisitor::Visit(TypeExpression* node) { utils::ValueType::Tmp); } else { std::optional maybe_local_abstract_type = - context_manager_.GetLocalType(node->type.type); + context_manager_.FindLocalType(node->type.type); if (node->path.empty() && maybe_local_abstract_type.has_value()) { current_type_ = maybe_local_abstract_type.value(); } else if (node->type.type_id_.has_value()) { // TODO: check that names are different (always true ??) @@ -1230,7 +1269,9 @@ void TypeCheckVisitor::Visit(TypeExpression* node) { global_info_.GetTypeInfo(node->type.type_id_.value()); if (!maybe_type_info.has_value()) { - error_handling::HandleInternalError("No AnyType found (alias types, ... not implemented)", "TypeCheckVisitor.TypeExpression"); + error_handling::HandleInternalError("No AnyType found (alias types, ... not implemented)", + "TypeCheckVisitor.TypeExpression", + &node->base); } Visitor::Visit(*maybe_type_info.value()->value); @@ -1270,11 +1311,13 @@ void TypeCheckVisitor::Visit(ExtendedScopedAnyType* node) { void TypeCheckVisitor::Visit(ParametrizedTypeclass* node) { if (node->parameters.size()) { error_handling::HandleInternalError("Typeclasses with parameters are not implemented", - "TypeCheckVisitor.ParametrizedTypeclass"); + "TypeCheckVisitor.ParametrizedTypeclass", + &node->base); } error_handling::HandleInternalError("ParametizedTypeclass shouldn't be visited (?)", - "TypeCheckVisitor.ParametrizedTypeclass"); + "TypeCheckVisitor.ParametrizedTypeclass", + &node->base); } // Typeclass & Type ----------------- @@ -1331,7 +1374,9 @@ void TypeCheckVisitor::CollectTypeContext(const ParametrizedType& type, global_info_.GetTypeInfo(type.type_id_.value()); if (!maybe_type_info.has_value()) { - error_handling::HandleInternalError("Wrong type id", "TypeCheckVisitor.CollectTypeContext"); + error_handling::HandleInternalError("Wrong type id", + "TypeCheckVisitor.CollectTypeContext", + std::nullopt); } info::definition::AnyType& type_info = *maybe_type_info.value(); @@ -1344,7 +1389,9 @@ void TypeCheckVisitor::CollectTypeContext(const ParametrizedType& type, Visit(type.parameters[i].get()); if (context.count(type_info.parameters[i].type) != 0) { - error_handling::HandleInternalError("Same parameter type names", "TypeCheckVisitor.CollectTypeContext"); + error_handling::HandleInternalError("Same parameter type names", + "TypeCheckVisitor.CollectTypeContext", + std::nullopt); } context[type_info.parameters[i].type] = current_type_; @@ -1415,7 +1462,8 @@ std::optional auto maybe_type_info = global_info_.GetTypeInfo(type_id); if (!maybe_type_info.has_value()) { error_handling::HandleInternalError("Functions / Methods implemented only for AnyType", - "TypeCheckVisitor.FunctionCallExpresssion"); + "TypeCheckVisitor.FunctionCallExpresssion", + &node->base); } info::definition::AnyType* type_info = maybe_type_info.value(); @@ -1438,7 +1486,7 @@ std::optional error_handling::HandleTypecheckError("Can't call function from array type namespace", node->base); } - std::optional maybe_local_abstract_type = context_manager_.GetLocalType(type_node->type.type); + std::optional maybe_local_abstract_type = context_manager_.FindLocalType(type_node->type.type); if (maybe_local_abstract_type.has_value()) { auto maybe_abstract_type_info = @@ -1446,7 +1494,8 @@ std::optional if (!maybe_abstract_type_info.has_value()) { error_handling::HandleInternalError("Local abstract type contains not abstract type", - "TypeCheckVisitor.FindTypeFunctionAndUpdate"); + "TypeCheckVisitor.FindTypeFunctionAndUpdate", + &node->base); } maybe_function_declaration = FindAbstractTypeTypeclassFunctionAndUpdate(node, @@ -1467,7 +1516,8 @@ std::optional auto maybe_type_info = global_info_.GetTypeInfo(type_node->type_id_.value()); if (!maybe_type_info.has_value()) { error_handling::HandleInternalError("typeclass functions / methods implemented only for AnyType", - "TypeCheckVisitor.FindTypeFunctionAndUpdate"); + "TypeCheckVisitor.FindTypeFunctionAndUpdate", + &node->base); } maybe_function_declaration = FindDefinedTypeFunctionAndUpdate(node, @@ -1478,8 +1528,14 @@ std::optional if (maybe_function_id.has_value()) { node->function_id_ = maybe_function_id.value(); + + auto maybe_function_declaration_info = + global_info_.GetFunctionInfo(maybe_function_id.value()).declaration; + maybe_function_declaration = - global_info_.GetFunctionInfo(maybe_function_id.value()).declaration.value().node; + (maybe_function_declaration_info.has_value() + ? maybe_function_declaration_info.value().node + : std::optional()); } } } @@ -1496,19 +1552,21 @@ std::optional TypeCheckVisitor::FindFunctionAndUpdate(Func auto maybe_type_info = global_info_.GetTypeInfo(path_types[i].value()); if (!maybe_type_info.has_value()) { error_handling::HandleInternalError("typeclass functions / methods implemented only for AnyType", - "TypeCheckVisitor.FindTypeFunctionAndUpdate"); + "TypeCheckVisitor.FindTypeFunctionAndUpdate", + &node->base); } maybe_function_declaration = FindDefinedTypeFunctionAndUpdate(node, - maybe_type_info.value(), - false); - } else { + maybe_type_info.value(), + false); + } else if (global_info_.GetNamespaceInfo(path_namespaces[i]).modifier == utils::ClassInternalsModifier::Static) { auto function_iter = global_info_.GetNamespaceInfo(path_namespaces[i]).functions.find(node->name); if (function_iter != global_info_.GetNamespaceInfo(path_namespaces[i]).functions.end()) { auto& maybe_declaration_info = global_info_.GetFunctionInfo(function_iter->second).declaration; if (maybe_declaration_info.has_value()) { + node->function_id_ = function_iter->second; maybe_function_declaration = maybe_declaration_info.value().node; } } @@ -1540,7 +1598,6 @@ std::optional auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name); if (!maybe_typeclass_graph_id.has_value()) { return std::nullopt; - // error_handling::HandleTypecheckError("Typeclass function not found", node->base); } auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name, @@ -1552,15 +1609,17 @@ std::optional if (!maybe_typeclass_function_info.has_value()) { error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (abstract type)", - "TypeCheckVisitor.FindAbstractTypeTypeclassFunctionAndUpdate"); + "TypeCheckVisitor.FindAbstractTypeTypeclassFunctionAndUpdate", + &node->base); } - // TODO: check that const functions not called on var expressions + // TODO: check that const functions not called on var expressions ?? if ((maybe_typeclass_function_info.value()->modifier != utils::ClassInternalsModifier::Static) != is_method) { error_handling::HandleTypecheckError("Typeclass function has wrong modifier (abstract type)", node->base); } node->graph_id_ = maybe_typeclass_graph_id; + node->abstract_type_name_ = abstract_type_info->GetName(); maybe_function_declaration = maybe_typeclass_function_info.value()->declaration; return maybe_function_declaration; @@ -1580,10 +1639,53 @@ std::optional // error_handling::HandleTypecheckError("Function is not declared in type", node->base); } + // TODO: check that const functions not called on var expressions ?? + if ((maybe_type_function_info.value()->modifier != utils::ClassInternalsModifier::Static) != is_method) { + error_handling::HandleTypecheckError("Typeclass function has wrong modifier (abstract type)", node->base); + } + 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; return maybe_function_declaration; } +// + +bool TypeCheckVisitor::HandleBuiltinFunctionCall(FunctionCallExpression* node) { + if (node->name == "print") { + if (node->prefix.has_value() + || !node->parameters.empty() + || node->arguments.size() != 1) { + error_handling::HandleTypecheckError("Wrong builtin function \"print\" usage", node->base); + } + + Visitor::Visit(node->arguments[0]); + if (!context_manager_.EqualValues( + current_type_, + context_manager_.AddValue(info::type::InternalType::String, utils::ValueType::Tmp))) { + error_handling::HandleTypecheckError("Wrong builtin function \"print\" argument (should be string)", node->base); + } + + current_type_ = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp); + return true; + } else if (node->name == "read") { + if (node->prefix.has_value() + || !node->parameters.empty() + || node->arguments.size() != 0) { + error_handling::HandleTypecheckError("Wrong builtin function \"read\" usage", node->base); + } + + current_type_ = context_manager_.AddValue(info::type::InternalType::String, utils::ValueType::Tmp); + return true; + } + + return false; +} + +bool TypeCheckVisitor::HandleBuiltinTypeclassFunctionCall(FunctionCallExpression*) { + return false; +} + } // namespace interpreter diff --git a/tests/test_code.lang b/tests/test_code.lang index d7e702f..6d743b1 100644 --- a/tests/test_code.lang +++ b/tests/test_code.lang @@ -76,11 +76,11 @@ namespace var Ord { // -typeclass Show = - & var show : -> String - -typeclass Read = - & var read : String -> Read +// typeclass Print = +// & var print : -> String +// +// typeclass Read = +// & var read : String -> Read typeclass Debug = & debug : -> String @@ -132,6 +132,7 @@ decl ( -- ) : Int -> Int -> Int_0 // } decl print : String -> Unit +decl read : -> String decl func : String -> Int def func : s = { @@ -140,5 +141,6 @@ def func : s = { } exec main { - for i in 0--10 do func: "abacaba" + for i in (,0 ,1 ,2 ,3) do func: "abacaba" + ; print: ({ return read: }) }