diff --git a/include/definitions.hpp b/include/definitions.hpp index 2f09f23..cfe6c68 100644 --- a/include/definitions.hpp +++ b/include/definitions.hpp @@ -79,8 +79,7 @@ struct Function { struct Typeclass { std::vector parameters; - std::vector function_requirements; - std::vector method_requirements; + interpreter::tokens::TypeclassDefinitionStatement* node; }; struct Import { diff --git a/include/error_handling.hpp b/include/error_handling.hpp index d99e443..7b53ab1 100644 --- a/include/error_handling.hpp +++ b/include/error_handling.hpp @@ -23,38 +23,36 @@ inline void PrintPosition(std::ostream& out, inline void HandleParsingError(const std::string& message, std::pair start_position, std::pair end_position) { - std::cout << "Parsing Error: " << message << " at "; + std::cout << "\x1b[1;31mParsing Error:\x1b[0m " << message << " at "; PrintPosition(std::cout, start_position, end_position); std::cout << ".\n"; exit(1); } inline void HandleGeneralError(const std::string& message) { - std::cout << "General Error: " << message << ".\n"; + std::cout << "\x1b[1;31mGeneral Error:\x1b[0m " << message << ".\n"; exit(1); } inline void HandleInternalError(const std::string& message, const std::string& place) { - std::cout << "Internal Error: " << message << " at " << place << ".\n"; + std::cout << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at " << place << ".\n"; exit(1); } inline void HandleTypecheckError(const std::string& message, - const interpreter::tokens::BaseNode& node) { // TODO: place in code - std::cout << "Typecheck Error: " << message << " at "; + const interpreter::tokens::BaseNode& node) { + std::cout << "\x1b[1;31mTypecheck Error:\x1b[0m " << message << " at "; PrintPosition(std::cout, node.start_position, node.end_position); std::cout << ".\n"; exit(1); } inline void HandleRuntimeError(const std::string& message, - const interpreter::tokens::BaseNode& node) { // TODO: place in code - std::cout << "Runtime Error: " << message << " at "; + const interpreter::tokens::BaseNode& node) { + std::cout << "\x1b[1;31mRuntime Error:\x1b[0m " << message << " at "; PrintPosition(std::cout, node.start_position, node.end_position); std::cout << ".\n"; exit(1); } -// ... - } // namespace error_handling diff --git a/include/execute_visitor.hpp b/include/execute_visitor.hpp index e9340dc..b3a3057 100644 --- a/include/execute_visitor.hpp +++ b/include/execute_visitor.hpp @@ -165,7 +165,7 @@ private: utils::IdType current_value_; std::optional active_loop_control_expression_; - std::optional return_value_; // TODO: work outside block ?? + std::optional returned_value_; // TODO: work outside block ?? std::optional is_const_definition_; bool case_matched_; }; diff --git a/include/find_symbols_visitor.hpp b/include/find_symbols_visitor.hpp index 625fb6b..a5eeb17 100644 --- a/include/find_symbols_visitor.hpp +++ b/include/find_symbols_visitor.hpp @@ -121,7 +121,6 @@ private: private: info::GlobalInfo::NamespaceVisitor namespace_visitor_; - bool is_in_statement_ = false; std::any current_info_; }; diff --git a/include/global_info.hpp b/include/global_info.hpp index d61cfdd..7b34aa0 100644 --- a/include/global_info.hpp +++ b/include/global_info.hpp @@ -51,10 +51,12 @@ public: void ToGlobalNamespace(); utils::IdType AddFunctionDeclaration(const std::string& name, - definition::FunctionDeclaration&& function_declaration_info); + definition::FunctionDeclaration&& function_declaration_info, + const interpreter::tokens::BaseNode& base_node); utils::IdType AddFunctionDefinition(const std::string& name, - definition::FunctionDefinition&& function_definition_info); + definition::FunctionDefinition&& function_definition_info, + const interpreter::tokens::BaseNode& base_node); utils::IdType AddType(const std::string& type, definition::Type&& type_info, @@ -124,6 +126,10 @@ public: std::optional FindNamespaceIn( utils::IdType current_namespace, const std::vector& path); + + std::unordered_map* + ChooseNamespaces(std::optional modifier, + utils::IdType namespace_id); private: GlobalInfo& global_info_; @@ -135,7 +141,6 @@ public: return NamespaceVisitor(*this); } - // remember about vector realloc definition::Function& GetFunctionInfo(utils::IdType id) { return functions_.at(id); } @@ -148,27 +153,22 @@ public: return &std::get(types_[id].type); } - // remember about vector realloc definition::Type& GetAnyTypeInfo(utils::IdType id) { return types_.at(id); } - // remember about vector realloc definition::Typeclass& GetTypeclassInfo(utils::IdType id) { return typeclasses_.at(id); } - // remember about vector realloc definition::Constructor& GetConstructorInfo(utils::IdType id) { return constructors_.at(id); } - // remember about vector realloc definition::Namespace& GetNamespaceInfo(utils::IdType id) { return namespaces_.at(id); } - // remember about vector realloc PartitionInfo& GetPartitionInfo(utils::IdType id) { return partitions_.at(id); } diff --git a/src/build_visitor.cpp b/src/build_visitor.cpp index 179dfd1..367726a 100644 --- a/src/build_visitor.cpp +++ b/src/build_visitor.cpp @@ -1,5 +1,3 @@ -#include - #include #include @@ -63,6 +61,8 @@ void BuildVisitor::Visit(Namespace* node) { node->modifier = utils::IsConstModifier::Const; } else if (modifier == "var") { node->modifier = utils::IsConstModifier::Var; + } else { + error_handling::HandleInternalError("Can't parse namespace modifier", "BuildVisitor.Namespace"); } } @@ -150,6 +150,8 @@ void BuildVisitor::Visit(VariableDefinitionStatement* node) { node->modifier = utils::IsConstModifier::Const; } else if (modifier == "var") { node->modifier = utils::IsConstModifier::Var; + } else { + // error } current_node_ = parse_node.ChildByFieldName("name"); @@ -163,6 +165,8 @@ void BuildVisitor::Visit(VariableDefinitionStatement* node) { node->assignment_modifier = utils::AssignmentModifier::Assign; } else if (assignment_modifier == "<-") { node->assignment_modifier = utils::AssignmentModifier::Move; + } else { + // error } current_node_ = parse_node; diff --git a/src/execute_visitor.cpp b/src/execute_visitor.cpp index 9b4aed5..afba6ce 100644 --- a/src/execute_visitor.cpp +++ b/src/execute_visitor.cpp @@ -131,14 +131,18 @@ void ExecuteVisitor::Visit(Match* node) { context_manager_.ExitContext(); } - if (statement_visited) { - current_value_ = context_manager_.AddValue( - info::value::OptionalValue(current_value_, context_manager_.GetValueManager()), - utils::ValueType::Tmp); - } else { - current_value_ = context_manager_.AddValue( - info::value::OptionalValue(std::nullopt, context_manager_.GetValueManager()), - utils::ValueType::Tmp); + // --- instead of optional return value or throw runtime error --- + // if (statement_visited) { + // current_value_ = context_manager_.AddValue( + // info::value::OptionalValue(current_value_, context_manager_.GetValueManager()), + // utils::ValueType::Tmp); + // } else { + // current_value_ = context_manager_.AddValue( + // info::value::OptionalValue(std::nullopt, context_manager_.GetValueManager()), + // utils::ValueType::Tmp); + // } + if (!statement_visited) { + error_handling::HandleRuntimeError("Value match option not found", node->base); } context_manager_.ExitContext(); @@ -283,10 +287,11 @@ void ExecuteVisitor::Visit(Block* node) { context_manager_.EnterContext(); for (auto& statement : node->statements) { - return_value_ = std::nullopt; + returned_value_ = std::nullopt; Visitor::Visit(statement); - if (return_value_.has_value()) { - current_value_ = return_value_.value(); + if (returned_value_.has_value()) { + current_value_ = returned_value_.value(); + returned_value_ = std::nullopt; // ?? return; } } @@ -457,7 +462,7 @@ void ExecuteVisitor::Visit(VariantExpression* node) { void ExecuteVisitor::Visit(ReturnExpression* node) { Visitor::Visit(node->expression); - return_value_ = current_value_; + returned_value_ = current_value_; } diff --git a/src/find_symbols_visitor.cpp b/src/find_symbols_visitor.cpp index 537b0b2..2273a82 100644 --- a/src/find_symbols_visitor.cpp +++ b/src/find_symbols_visitor.cpp @@ -1,3 +1,5 @@ +#include + // for clangd #include "../include/find_symbols_visitor.hpp" @@ -8,7 +10,7 @@ namespace interpreter { // Namespaces, partitions ----------------- void FindSymbolsVisitor::Visit(Namespace* node) { - namespace_visitor_.AddEnterNamespace(node->type, node->modifier, node->base); + namespace_visitor_.AddEnterNamespace(node->type, node->modifier, node->base); Visitor::Visit(&node->scope); @@ -19,27 +21,19 @@ void FindSymbolsVisitor::Visit(Namespace* node) { // TODO: add imported symbols to symbol table (global info) void FindSymbolsVisitor::Visit(ImportStatement* node) { - is_in_statement_ = true; - info::definition::Import info; info.module_name = node->module_name; info.symbols = node->symbols; namespace_visitor_.AddImport(std::move(info), node->name); - - is_in_statement_ = false; } void FindSymbolsVisitor::Visit(AliasDefinitionStatement* node) { - is_in_statement_ = true; - info::definition::Type info; info::definition::AliasType alias_info; alias_info.modifier = node->modifier; - // TODO: deduce parameter requirements - alias_info.parameters = node->parameters; alias_info.value.node = node->value.get(); alias_info.node = node; @@ -47,14 +41,9 @@ void FindSymbolsVisitor::Visit(AliasDefinitionStatement* node) { info.type = std::move(alias_info); node->type_id_ = namespace_visitor_.AddType(node->type, std::move(info), node->base); - - is_in_statement_ = false; } void FindSymbolsVisitor::Visit(FunctionDeclaration* node) { - bool was_in_statement = is_in_statement_; - is_in_statement_ = true; - info::definition::FunctionDeclaration info; info.parameters.resize(node->parameters.size()); @@ -71,17 +60,10 @@ void FindSymbolsVisitor::Visit(FunctionDeclaration* node) { info.node = node; - if (was_in_statement) { - current_info_ = std::move(info); - } else { - node->function_id_ = namespace_visitor_.AddFunctionDeclaration(node->name, std::move(info)); - is_in_statement_ = false; - } + node->function_id_ = namespace_visitor_.AddFunctionDeclaration(node->name, std::move(info), node->base); } void FindSymbolsVisitor::Visit(FunctionDefinitionStatement* node) { - is_in_statement_ = true; - info::definition::FunctionDefinition info; auto definition = node->definition.get(); @@ -93,14 +75,10 @@ void FindSymbolsVisitor::Visit(FunctionDefinitionStatement* node) { info.node = node; - node->function_id_ = namespace_visitor_.AddFunctionDefinition(definition->name, std::move(info)); - - is_in_statement_ = false; + node->function_id_ = namespace_visitor_.AddFunctionDefinition(definition->name, std::move(info), node->base); } void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) { - is_in_statement_ = true; - info::definition::Type info; auto definition = node->definition.get(); @@ -127,13 +105,9 @@ void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) { info.type = std::move(any_type_info); node->type_id_ = namespace_visitor_.AddType(type, std::move(info), node->base); - - is_in_statement_ = false; } void FindSymbolsVisitor::Visit(AbstractTypeDefinitionStatement* node) { - is_in_statement_ = true; - info::definition::AbstractType info; Visit(node->type.get()); @@ -145,17 +119,15 @@ void FindSymbolsVisitor::Visit(AbstractTypeDefinitionStatement* node) { std::string type = info.type.type; node->type_id_ = namespace_visitor_.AddAbstractType(type, std::move(info), node->base); - - is_in_statement_ = false; } void FindSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) { - is_in_statement_ = true; - info::definition::Typeclass info; auto definition = node->definition.get(); + std::string& type_name = definition->type.get()->type; + info.parameters.resize(definition->parameters.size()); for (size_t i = 0; i < definition->parameters.size(); ++i) { Visit(definition->parameters[i].get()); @@ -163,32 +135,25 @@ void FindSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) { current_info_.reset(); } - info.function_requirements.resize(node->function_requirements.size()); + namespace_visitor_.AddEnterNamespace(type_name, std::nullopt, node->base); for (size_t i = 0; i < node->function_requirements.size(); ++i) { Visit(node->function_requirements[i].get()); - info.function_requirements[i] = std::move(std::any_cast(current_info_)); - current_info_.reset(); } + namespace_visitor_.ExitNamespace(); - info.method_requirements.resize(node->method_requirements.size()); + namespace_visitor_.AddEnterNamespace(type_name, utils::IsConstModifier::Var, node->base); for (size_t i = 0; i < node->method_requirements.size(); ++i) { Visit(node->method_requirements[i].get()); - info.method_requirements[i] = std::move(std::any_cast(current_info_)); - current_info_.reset(); } + namespace_visitor_.ExitNamespace(); - node->typeclass_id_ = namespace_visitor_.AddTypeclass(definition->type.get()->type, std::move(info), node->base); + info.node = node; - is_in_statement_ = false; + node->typeclass_id_ = namespace_visitor_.AddTypeclass(type_name, std::move(info), node->base); } void FindSymbolsVisitor::Visit(PartitionStatement* node) { - is_in_statement_ = true; - node->executable_id_ = namespace_visitor_.AddPartition(node->name.path, node); - // TODO: typecheck error on same tests - - is_in_statement_ = false; } // Definition parts diff --git a/src/global_info.cpp b/src/global_info.cpp index 361c6e5..766dd30 100644 --- a/src/global_info.cpp +++ b/src/global_info.cpp @@ -24,20 +24,22 @@ void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name, error_handling::HandleTypecheckError("Can't define basic type namespace", base_node); } - size_t id = global_info_.namespaces_.size(); - global_info_.namespaces_.emplace_back(); - definition::Namespace* namespace_info = &global_info_.namespaces_.back(); + auto current_namespaces = ChooseNamespaces(modifier, namespace_stack_.back()); + + utils::IdType id = 0; + + auto namespace_iter = current_namespaces->find(name); + if (namespace_iter == current_namespaces->end()) { + id = global_info_.namespaces_.size(); + (*current_namespaces)[name] = id; + global_info_.namespaces_.emplace_back(); + } else { + id = namespace_iter->second; + } + definition::Namespace* namespace_info = &global_info_.namespaces_[id]; if (modifier.has_value()) { - if (modifier.value() == utils::IsConstModifier::Const) { - global_info_.namespaces_[namespace_stack_.back()].const_namespaces[name] = id; - } else { - global_info_.namespaces_[namespace_stack_.back()].var_namespaces[name] = id; - } - namespace_info->modifier = modifier; - } else { - global_info_.namespaces_[namespace_stack_.back()].namespaces[name] = id; } namespace_info->parent_namespace = namespace_stack_.back(); @@ -48,36 +50,15 @@ void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name, current_path_.push_back(name); } -// better code ?? void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& name, std::optional modifier) { - - if (!modifier.has_value()) { - for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) { - auto namespace_iter = global_info_.namespaces_[namespace_stack_[i]].namespaces.find(name); - if (namespace_iter != global_info_.namespaces_[namespace_stack_[i]].namespaces.end()) { - namespace_stack_.push_back(namespace_iter->second); - current_path_.push_back(name); - return; - } - } - } else if (modifier.has_value() && modifier.value() == utils::IsConstModifier::Const) { - for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) { - auto const_namespace_iter = global_info_.namespaces_[namespace_stack_[i]].const_namespaces.find(name); - if (const_namespace_iter != global_info_.namespaces_[namespace_stack_[i]].const_namespaces.end()) { - namespace_stack_.push_back(const_namespace_iter->second); - current_path_.push_back(name); - return; - } - } - } else { - for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) { - auto var_namespace_iter = global_info_.namespaces_[namespace_stack_[i]].var_namespaces.find(name); - if (var_namespace_iter != global_info_.namespaces_[namespace_stack_[i]].var_namespaces.end()) { - namespace_stack_.push_back(var_namespace_iter->second); - current_path_.push_back(name); - return; - } + for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) { + auto current_namespaces = ChooseNamespaces(modifier, i); + auto namespace_iter = current_namespaces->find(name); + if (namespace_iter != current_namespaces->end()) { + namespace_stack_.push_back(namespace_iter->second); + current_path_.push_back(name); + return; } } @@ -104,51 +85,56 @@ void GlobalInfo::NamespaceVisitor::ToGlobalNamespace() { } utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDeclaration( - const std::string& name, - definition::FunctionDeclaration&& function_declaration_info) { - - size_t id = 0; + const std::string& name, + definition::FunctionDeclaration&& function_declaration_info, + const interpreter::tokens::BaseNode& base_node) { + utils::IdType id = 0; auto function_id_iter = global_info_.namespaces_[namespace_stack_.back()].functions.find(name); - if (function_id_iter == global_info_.namespaces_[namespace_stack_.back()].functions.end()) { id = global_info_.functions_.size(); global_info_.namespaces_[namespace_stack_.back()].functions[name] = id; global_info_.functions_.emplace_back(); global_info_.functions_.back().argument_count = function_declaration_info.argument_types.size(); // add return type - global_info_.functions_.back().declaration = std::move(function_declaration_info); } else { id = function_id_iter->second; - if (global_info_.functions_.back().argument_count != function_declaration_info.argument_types.size()) { - error_handling::HandleInternalError("Not same argument count in function definition and declaration", - "GlobalInfo.NamespaceVisitor. AddFunctionDeclaration"); + if (global_info_.functions_[id].argument_count != function_declaration_info.argument_types.size()) { + error_handling::HandleTypecheckError("Function declaration: not same argument count in function definition and declaration", base_node); } - global_info_.functions_[id].declaration = std::move(function_declaration_info); } + if (global_info_.functions_[id].declaration.has_value()) { + error_handling::HandleTypecheckError("Second function declaration", base_node); + } + global_info_.functions_[id].declaration = std::move(function_declaration_info); + return id; } -utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDefinition(const std::string& name, - definition::FunctionDefinition&& function_definition_info) { - size_t id = 0; +utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDefinition( + const std::string& name, + definition::FunctionDefinition&& function_definition_info, + const interpreter::tokens::BaseNode& base_node) { + utils::IdType id = 0; auto function_id_iter = global_info_.namespaces_[namespace_stack_.back()].functions.find(name); - if (function_id_iter == global_info_.namespaces_[namespace_stack_.back()].functions.end()) { id = global_info_.functions_.size(); global_info_.namespaces_[namespace_stack_.back()].functions[name] = id; global_info_.functions_.emplace_back(); global_info_.functions_.back().argument_count = function_definition_info.argument_names.size() + 1; - global_info_.functions_.back().definition = std::move(function_definition_info); } else { id = function_id_iter->second; - if (global_info_.functions_.back().argument_count != function_definition_info.argument_names.size() + 1) { - error_handling::HandleInternalError("Not same argument count in function definition and declaration", "GlobalInfo"); + if (global_info_.functions_[id].argument_count != function_definition_info.argument_names.size() + 1) { + error_handling::HandleTypecheckError("Function definition: not same argument count in function definition and declaration", base_node); } - global_info_.functions_[id].definition = std::move(function_definition_info); } + if (global_info_.functions_[id].definition.has_value()) { + error_handling::HandleTypecheckError("Second function definition", base_node); + } + global_info_.functions_[id].definition = std::move(function_definition_info); + return id; } @@ -161,7 +147,7 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, error_handling::HandleTypecheckError("Can't redefine basic type", base_node); } - size_t id = 0; + utils::IdType id = 0; auto type_id_iter = global_info_.namespaces_[namespace_stack_.back()].types.find(type); @@ -224,17 +210,16 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddAbstractType(const std::string& a error_handling::HandleTypecheckError("Can't redefine basic type as abstract type", base_node); } - if (!FindAbstractType(abstract_type).has_value()) { - utils::IdType id = global_info_.abstract_types_.size(); - global_info_.name_to_abstract_type_[abstract_type] = id; - global_info_.abstract_types_.push_back(std::move(abstract_type_info)); - - return id; + if (FindAbstractType(abstract_type).has_value()) { + error_handling::HandleTypecheckError("More then one abstract type with the same name in namespace", + base_node); } - error_handling::HandleTypecheckError("More then one abstract type with the same name in namespace", - base_node); - return 0; + utils::IdType id = global_info_.abstract_types_.size(); + global_info_.name_to_abstract_type_[abstract_type] = id; + global_info_.abstract_types_.push_back(std::move(abstract_type_info)); + + return id; } utils::IdType GlobalInfo::NamespaceVisitor::AddTypeclass(const std::string& typeclass, @@ -244,17 +229,15 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddTypeclass(const std::string& type error_handling::HandleTypecheckError("Can't redefine basic type as typeclass", base_node); } - if (!FindTypeclass(typeclass).has_value()) { - size_t id = global_info_.typeclasses_.size(); - global_info_.name_to_typeclass_[typeclass] = id; - global_info_.typeclasses_.push_back(std::move(typeclass_info)); - - return id; + if (FindTypeclass(typeclass).has_value()) { + error_handling::HandleTypecheckError("More then one typeclass with the same name in namespace", base_node); } + utils::IdType id = global_info_.typeclasses_.size(); + global_info_.name_to_typeclass_[typeclass] = id; + global_info_.typeclasses_.push_back(std::move(typeclass_info)); - error_handling::HandleTypecheckError("More then one typeclass with the same name in namespace", base_node); - return 0; + return id; } utils::IdType GlobalInfo::NamespaceVisitor::AddConstructor(const std::string& constructor, @@ -266,16 +249,15 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddConstructor(const std::string& co auto constructor_id_iter = global_info_.namespaces_[namespace_stack_.back()].constructors.find(constructor); - if (constructor_id_iter == global_info_.namespaces_[namespace_stack_.back()].constructors.end()) { - size_t id = global_info_.constructors_.size(); - global_info_.namespaces_[namespace_stack_.back()].constructors[constructor] = id; - global_info_.constructors_.push_back(std::move(constructor_info)); - - return id; + if (constructor_id_iter != global_info_.namespaces_[namespace_stack_.back()].constructors.end()) { + error_handling::HandleTypecheckError("More then one constructor with the same name in namespace", base_node); } - error_handling::HandleTypecheckError("More then one constructor with the same name in namespace", base_node); - exit(1); + utils::IdType id = global_info_.constructors_.size(); + global_info_.namespaces_[namespace_stack_.back()].constructors[constructor] = id; + global_info_.constructors_.push_back(std::move(constructor_info)); + + return id; } utils::IdType GlobalInfo::NamespaceVisitor::AddPartition(const std::vector& path, @@ -417,8 +399,8 @@ template std::optional GlobalInfo::NamespaceVisitor::FindSomething( const std::optional>& path, std::function(utils::IdType)> search_func) { - for (ssize_t i = namespace_stack_.size() - 1; i >= 0; --i) { - utils::IdType current_namespace; + for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) { + utils::IdType current_namespace = 0; if (path.has_value()) { auto maybe_namespace = FindNamespaceIn(namespace_stack_[i], path.value()); @@ -456,4 +438,21 @@ std::optional GlobalInfo::NamespaceVisitor::FindNamespaceIn( return next_namespace; } +std::unordered_map* + GlobalInfo::NamespaceVisitor::ChooseNamespaces(std::optional modifier, + utils::IdType namespace_id) { + std::unordered_map* current_namespaces = nullptr; + if (modifier.has_value()) { + if (modifier.value() == utils::IsConstModifier::Const) { + current_namespaces = &global_info_.namespaces_[namespace_id].const_namespaces; + } else { + current_namespaces = &global_info_.namespaces_[namespace_id].var_namespaces; + } + } else { + current_namespaces = &global_info_.namespaces_[namespace_id].namespaces; + } + + return current_namespaces; +} + } // namespace info diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 32d63b9..40b61b5 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -33,18 +33,22 @@ void TypeCheckVisitor::Visit(NamespaceSources* node) { } void TypeCheckVisitor::Visit(Namespace* node) { // TODO: two var namespces for class: const and var - if (node->modifier.has_value()) { - if (node->link_typeclass_id_.has_value()) { // TODO: think about typeclass + if (node->link_typeclass_id_.has_value()) { // TODO: think about typeclass - std::vector requirements {node->link_typeclass_id_.value()}; - utils::IdType abstract_type = context_manager_.AddValue( - info::type::AbstractType(utils::AbstractTypeModifier::Abstract, node->type, requirements), - IsConstModifierToValueType(node->modifier.value())); + std::vector requirements {node->link_typeclass_id_.value()}; + utils::IdType abstract_type = context_manager_.AddValue( + info::type::AbstractType(utils::AbstractTypeModifier::Abstract, node->type, requirements), + IsConstModifierToValueType(node->modifier.value())); + if (node->modifier.has_value()) { context_manager_.EnterVariableContext(utils::ClassInternalVarName, abstract_type); - context_manager_.DefineLocalType(node->type, abstract_type); - } else if (node->link_type_id_.has_value()) { + } else { + context_manager_.EnterContext(); + } + context_manager_.DefineLocalType(node->type, abstract_type); + } else if (node->link_type_id_.has_value()) { + if (node->modifier.has_value()) { auto maybe_type_info = namespace_visitor_.GetGlobalInfo()->GetTypeInfo(node->link_type_id_.value()); if (!maybe_type_info.has_value()) { @@ -61,18 +65,12 @@ void TypeCheckVisitor::Visit(Namespace* node) { // TODO: two var namespces for c maybe_type_info.value()->modifier, context_manager_.GetValueManager()), IsConstModifierToValueType(node->modifier.value()))); - } - } else { - if (node->link_typeclass_id_.has_value()) { // TODO - error_handling::HandleTypecheckError("Typeclass can't have not variable namespace", node->base); + } else { + context_manager_.EnterContext(); } - context_manager_.EnterContext(); - } - - if (node->link_type_id_.has_value()) { if (type_namespaces_.count(node->link_type_id_.value()) != 0) { - error_handling::HandleTypecheckError("Namespaces of one type one in another", node->base); + error_handling::HandleTypecheckError("Namespaces of one type are one in another", node->base); } type_namespaces_.insert(node->link_type_id_.value()); } @@ -413,14 +411,16 @@ void TypeCheckVisitor::Visit(Match* node) { // TODO: move value to match } if (!is_type_found) { - type = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp); + error_handling::HandleTypecheckError("Can't find match expression type", node->base); + // type = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp); } current_type_ = type; - current_type_ = context_manager_.AddValue( - info::type::OptionalType(current_type_, context_manager_.GetValueManager()), - utils::ValueType::Tmp); + // --- instead of optional return value or throw runtime error --- + // current_type_ = context_manager_.AddValue( + // info::type::OptionalType(current_type_, context_manager_.GetValueManager()), + // utils::ValueType::Tmp); context_manager_.ExitContext(); diff --git a/tests/test_code.lang b/tests/test_code.lang index a442cd0..a8392db 100644 --- a/tests/test_code.lang +++ b/tests/test_code.lang @@ -39,7 +39,7 @@ typeclass Eq = & var ( == ) : Eq -> Bool & var ( != ) : Eq -> Bool -namespace const Eq { +namespace var Eq { def ( != ) : x = not: (self == x) } @@ -51,13 +51,17 @@ struct Order = | GT typeclass (Ord : #Eq) = - & var compare: Ord -> Order + & var compare : Ord -> Order & var ( < ) : Ord -> Bool & var ( >= ) : Ord -> Bool & var ( > ) : Ord -> Bool & var ( <= ) : Ord -> Bool - & var min : Ord -> Ord - & var max : Ord -> Ord + +decl min ('A : #Ord) : 'A -> 'A -> 'A +def min : x y = if x < y then x else y + +decl max ('A : #Ord) : 'A -> 'A -> 'A +def max : x y = if x < y then y else x namespace var Ord { def compare : x = @@ -68,8 +72,6 @@ namespace var Ord { def ( >= ) : x = not: (self < x) def ( > ) : x = x < self def ( <= ) : x = not: (x < self) - def min : x = if self < x then self else x - def max : x = if self < x then x else self } //