From d31979166e88faa0257c111afdd7b7ee77742d3a Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Mon, 8 May 2023 20:34:36 +0300 Subject: [PATCH] bool literals, fixes --- include/build_visitor.hpp | 1 + include/error_handling.hpp | 8 ++--- include/execute_visitor.hpp | 17 +++++++++-- include/find_symbols_visitor.hpp | 1 + include/global_info.hpp | 3 +- include/interpreter_tree.hpp | 10 +++++- include/link_symbols_visitor.hpp | 5 +-- include/parse_token_types.hpp | 1 + include/print_visitor.hpp | 1 + include/type_check_visitor.hpp | 1 + include/typed_print_visitor.hpp | 1 + include/types.hpp | 31 +++++++++++++++++++ include/visitor.hpp | 1 + lang-parser | 2 +- src/build_visitor.cpp | 10 ++++++ src/execute_visitor.cpp | 9 ++---- src/find_symbols_visitor.cpp | 2 +- src/global_info.cpp | 28 +++++++++++++++-- src/link_symbols_visitor.cpp | 18 +++++++++-- src/print_visitor.cpp | 4 +++ src/type_check_visitor.cpp | 52 ++++++++++++++++++++------------ src/typed_print_visitor.cpp | 10 ++++++ src/visitor.cpp | 5 +++ tests/test_code.lang | 4 --- 24 files changed, 179 insertions(+), 46 deletions(-) diff --git a/include/build_visitor.hpp b/include/build_visitor.hpp index 72e4942..a3965c8 100644 --- a/include/build_visitor.hpp +++ b/include/build_visitor.hpp @@ -139,6 +139,7 @@ private: void Visit(StringLiteral* node) override; void Visit(CharLiteral* node) override; void Visit(UnitLiteral* node) override; + void Visit(BoolLiteral* node) override; void Visit(Literal& node) override; // variant private: diff --git a/include/error_handling.hpp b/include/error_handling.hpp index c52af2a..868e320 100644 --- a/include/error_handling.hpp +++ b/include/error_handling.hpp @@ -10,13 +10,13 @@ inline void PrintPosition(std::ostream& out, std::pair start_position, std::pair end_position) { out << '[' - << start_position.first + << start_position.first + 1 << ", " - << start_position.second + << start_position.second + 1 << "] - [" - << end_position.first + << end_position.first + 1 << ", " - << end_position.second + << end_position.second + 1 << ']'; } diff --git a/include/execute_visitor.hpp b/include/execute_visitor.hpp index ab87e43..1a454a5 100644 --- a/include/execute_visitor.hpp +++ b/include/execute_visitor.hpp @@ -5,8 +5,10 @@ // for clangd #include "contexts.hpp" #include "global_info.hpp" +#include "interpreter_tree.hpp" #include "type_info_contexts.hpp" #include "visitor.hpp" +#include "error_handling.hpp" namespace interpreter { @@ -14,11 +16,20 @@ class ExecuteVisitor : public Visitor { public: explicit ExecuteVisitor(info::GlobalInfo& global_info, info::TypeInfoContextManager& type_info_context_manager, - info::ContextManager& context_manager) + info::ContextManager& context_manager, + interpreter::tokens::PartitionStatement* execution_root) : namespace_visitor_(global_info.CreateVisitor()), type_info_context_manager_(type_info_context_manager), context_manager_(context_manager) {} + void VisitSourceFile(SourceFile* source_file) override { + error_handling::HandleInternalError("VisitSourceFile unavailible", "ExecuteVisitor.VisitSourceFile"); + }; + + void ExecutePartition(interpreter::tokens::PartitionStatement* partition) { + Visit(partition); + } + private: // Sources ----------------- @@ -39,8 +50,7 @@ private: void Visit(TypeDefinitionStatement* node) override; void Visit(AbstractTypeDefinitionStatement* node) override; void Visit(TypeclassDefinitionStatement* node) override; - void Visit(ExecutableStatement* node) override; - void Visit(TestStatement* node) override; + void Visit(PartitionStatement* node) override; // Definition parts @@ -125,6 +135,7 @@ private: void Visit(StringLiteral* node) override; void Visit(CharLiteral* node) override; void Visit(UnitLiteral* node) override; + void Visit(BoolLiteral* node) override; private: info::GlobalInfo::NamespaceVisitor namespace_visitor_; diff --git a/include/find_symbols_visitor.hpp b/include/find_symbols_visitor.hpp index 84ba085..276dc9a 100644 --- a/include/find_symbols_visitor.hpp +++ b/include/find_symbols_visitor.hpp @@ -119,6 +119,7 @@ private: // // void Visit(StringLiteral* node) override; // // void Visit(CharLiteral* node) override; // // void Visit(UnitLiteral* node) override; + // // void Visit(BoolLiteral* node) override; private: info::GlobalInfo::NamespaceVisitor namespace_visitor_; diff --git a/include/global_info.hpp b/include/global_info.hpp index ae74502..8c8971a 100644 --- a/include/global_info.hpp +++ b/include/global_info.hpp @@ -36,7 +36,8 @@ public: void AddImport(definition::Import&& import_info, const std::optional& name = std::nullopt); void AddEnterNamespace(const std::string& name, - std::optional modifier = std::nullopt); + std::optional modifier, + const interpreter::tokens::BaseNode& base_node); void EnterNamespace(const std::string& name); diff --git a/include/interpreter_tree.hpp b/include/interpreter_tree.hpp index 0dac07a..8753808 100644 --- a/include/interpreter_tree.hpp +++ b/include/interpreter_tree.hpp @@ -108,13 +108,15 @@ struct NumberLiteral; struct StringLiteral; struct CharLiteral; struct UnitLiteral; +struct BoolLiteral; using Literal = std::variant< std::unique_ptr, std::unique_ptr, std::unique_ptr, std::unique_ptr, - std::unique_ptr>; + std::unique_ptr, + std::unique_ptr>; // struct NameExpression; @@ -703,4 +705,10 @@ struct UnitLiteral { BaseNode base; }; +struct BoolLiteral { + BaseNode base; + + bool value; +}; + } // namespace interpereter::tokens diff --git a/include/link_symbols_visitor.hpp b/include/link_symbols_visitor.hpp index e7923de..557b4cf 100644 --- a/include/link_symbols_visitor.hpp +++ b/include/link_symbols_visitor.hpp @@ -110,13 +110,14 @@ private: // Identifiers, constants, etc. ----------------- // // void Visit(ExtendedName* node) override; - // // + // // void Visit(std::string* node) override; // std::string - // // + // // void Visit(FloatNumberLiteral* node) override; // // void Visit(NumberLiteral* node) override; // // void Visit(StringLiteral* node) override; // // void Visit(CharLiteral* node) override; + // // void Visit(BoolLiteral* node) override; private: info::GlobalInfo::NamespaceVisitor namespace_visitor_; diff --git a/include/parse_token_types.hpp b/include/parse_token_types.hpp index 8acbb22..86506da 100644 --- a/include/parse_token_types.hpp +++ b/include/parse_token_types.hpp @@ -127,6 +127,7 @@ const std::string NumberLiteral = "number_literal"; const std::string StringLiteral = "string_literal"; const std::string CharLiteral = "char_literal"; const std::string UnitLiteral = "unit_literal"; +const std::string BoolLiteral = "bool_literal"; const std::string Literal = "literal"; diff --git a/include/print_visitor.hpp b/include/print_visitor.hpp index c49e83c..8a56545 100644 --- a/include/print_visitor.hpp +++ b/include/print_visitor.hpp @@ -118,6 +118,7 @@ private: void Visit(StringLiteral* node) override; void Visit(CharLiteral* node) override; void Visit(UnitLiteral* node) override; + void Visit(BoolLiteral* node) override; private: std::ostream& out_; diff --git a/include/type_check_visitor.hpp b/include/type_check_visitor.hpp index 54d9f33..4297043 100644 --- a/include/type_check_visitor.hpp +++ b/include/type_check_visitor.hpp @@ -122,6 +122,7 @@ private: void Visit(StringLiteral* node) override; void Visit(CharLiteral* node) override; void Visit(UnitLiteral* node) override; + void Visit(BoolLiteral* node) override; // diff --git a/include/typed_print_visitor.hpp b/include/typed_print_visitor.hpp index dfb8411..b957c96 100644 --- a/include/typed_print_visitor.hpp +++ b/include/typed_print_visitor.hpp @@ -119,6 +119,7 @@ private: void Visit(StringLiteral* node) override; void Visit(CharLiteral* node) override; void Visit(UnitLiteral* node) override; + void Visit(BoolLiteral* node) override; private: std::ostream& out_; diff --git a/include/types.hpp b/include/types.hpp index b27c35f..681d8fe 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -78,6 +78,37 @@ enum class InternalType { Unit = 5, }; +inline std::optional ToInternalType(const std::string& type) { + if (type.empty()) { + return std::nullopt; + } + + switch (type[0]) { + case 'F': + if (type == "Float") { return InternalType::Float; } + break; + case 'I': + if (type == "Int") { return InternalType::Int; } + break; + case 'S': + if (type == "String") { return InternalType::String; } + break; + case 'C': + if (type == "Char") { return InternalType::Char; } + break; + case 'B': + if (type == "Bool") { return InternalType::Bool; } + break; + case 'U': + if (type == "Unit") { return InternalType::Unit; } + break; + default: + break; + } + + return std::nullopt; +} + class TupleType { public: TupleType() = default; diff --git a/include/visitor.hpp b/include/visitor.hpp index 89e93fe..da68bad 100644 --- a/include/visitor.hpp +++ b/include/visitor.hpp @@ -136,6 +136,7 @@ protected: virtual void Visit(StringLiteral* node); virtual void Visit(CharLiteral* node); virtual void Visit(UnitLiteral* node); + virtual void Visit(BoolLiteral* node); virtual void Visit(Literal& node); // variant }; diff --git a/lang-parser b/lang-parser index 0d034ea..82f3a4e 160000 --- a/lang-parser +++ b/lang-parser @@ -1 +1 @@ -Subproject commit 0d034ea18377d25429fe04e768458df2cc00586a +Subproject commit 82f3a4edebad870fbf7d28bfd06bcc67731d5837 diff --git a/src/build_visitor.cpp b/src/build_visitor.cpp index 58436be..f567fd9 100644 --- a/src/build_visitor.cpp +++ b/src/build_visitor.cpp @@ -1531,6 +1531,13 @@ void BuildVisitor::Visit(UnitLiteral* node) { SetPosition(node->base, current_node_); } +void BuildVisitor::Visit(BoolLiteral* node) { + SetPosition(node->base, current_node_); + + std::string literal = current_node_.GetValue(); + node->value = (literal == "true"); // always "false" in other way +} + void BuildVisitor::Visit(Literal& node) { auto parse_node = current_node_; @@ -1553,6 +1560,9 @@ void BuildVisitor::Visit(Literal& node) { } else if (current_node_type == parser::tokens::UnitLiteral) { node = std::make_unique(); Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::BoolLiteral) { + node = std::make_unique(); + Visit(std::get>(node).get()); } else { // error } diff --git a/src/execute_visitor.cpp b/src/execute_visitor.cpp index 218fdc1..286ed7e 100644 --- a/src/execute_visitor.cpp +++ b/src/execute_visitor.cpp @@ -73,12 +73,7 @@ void ExecuteVisitor::Visit(TypeclassDefinitionStatement* node) { } } -void ExecuteVisitor::Visit(ExecutableStatement* node) { - Visit(&node->name); - Visitor::Visit(node->value); -} - -void ExecuteVisitor::Visit(TestStatement* node) { +void ExecuteVisitor::Visit(PartitionStatement* node) { Visit(&node->name); Visitor::Visit(node->value); } @@ -391,5 +386,7 @@ void ExecuteVisitor::Visit(CharLiteral* node) {} void ExecuteVisitor::Visit(UnitLiteral* node) {} +void ExecuteVisitor::Visit(BoolLiteral* node) {} + } // namespace interpreter diff --git a/src/find_symbols_visitor.cpp b/src/find_symbols_visitor.cpp index 8287e9f..c4b4129 100644 --- a/src/find_symbols_visitor.cpp +++ b/src/find_symbols_visitor.cpp @@ -8,7 +8,7 @@ namespace interpreter { // Namespaces, partitions ----------------- void FindSymbolsVisitor::Visit(Namespace* node) { - namespace_visitor_.AddEnterNamespace(node->type, node->modifier); + namespace_visitor_.AddEnterNamespace(node->type, node->modifier, node->base); Visitor::Visit(&node->scope); namespace_visitor_.ExitNamespace(); } diff --git a/src/global_info.cpp b/src/global_info.cpp index b6c11cd..de4b937 100644 --- a/src/global_info.cpp +++ b/src/global_info.cpp @@ -1,7 +1,10 @@ +#include + // for clangd #include "../include/global_info.hpp" +#include "../include/types.hpp" #include "../include/error_handling.hpp" -#include + namespace info { @@ -15,7 +18,12 @@ void GlobalInfo::NamespaceVisitor::AddImport(definition::Import&& import_info, } void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name, - std::optional modifier) { + std::optional modifier, + const interpreter::tokens::BaseNode& base_node) { + if (type::ToInternalType(name).has_value()) { + error_handling::HandleTypecheckError("Can't define basic type namespace", base_node); + } + definition::Namespace* namespace_info = nullptr; if (modifier.has_value()) { if (modifier.value() == utils::IsConstModifier::Const) { @@ -122,6 +130,10 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDefinition(const std::str utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, definition::Type&& type_info, const interpreter::tokens::BaseNode& base_node) { + if (type::ToInternalType(type).has_value()) { + error_handling::HandleTypecheckError("Can't redefine basic type", base_node); + } + size_t id = 0; auto type_id_iter = namespace_stack_.back()->types.find(type); @@ -181,6 +193,10 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, utils::IdType GlobalInfo::NamespaceVisitor::AddAbstractType(const std::string& abstract_type, definition::AbstractType&& abstract_type_info, const interpreter::tokens::BaseNode& base_node) { + if (type::ToInternalType(abstract_type).has_value()) { + 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; @@ -197,6 +213,10 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddAbstractType(const std::string& a utils::IdType GlobalInfo::NamespaceVisitor::AddTypeclass(const std::string& typeclass, definition::Typeclass&& typeclass_info, const interpreter::tokens::BaseNode& base_node) { + if (type::ToInternalType(typeclass).has_value()) { + 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; @@ -211,6 +231,10 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddTypeclass(const std::string& type utils::IdType GlobalInfo::NamespaceVisitor::AddConstructor(const std::string& constructor, definition::Constructor&& constructor_info, const interpreter::tokens::BaseNode& base_node) { + if (type::ToInternalType(constructor).has_value()) { + error_handling::HandleTypecheckError("Can't redefine basic type as constructor", base_node); + } + auto constructor_id_iter = namespace_stack_.back()->constructors.find(constructor); if (constructor_id_iter == namespace_stack_.back()->constructors.end()) { diff --git a/src/link_symbols_visitor.cpp b/src/link_symbols_visitor.cpp index 9b96eec..3c8b006 100644 --- a/src/link_symbols_visitor.cpp +++ b/src/link_symbols_visitor.cpp @@ -1,7 +1,9 @@ +#include + // for clangd #include "../include/link_symbols_visitor.hpp" #include "../include/error_handling.hpp" -#include +#include "../include/types.hpp" namespace interpreter { @@ -50,8 +52,20 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) { // TODO: check node->type_id_ = namespace_visitor_.FindType(path, node->type.type); node->constructor_id_ = namespace_visitor_.FindConstructor(path, node->type.type); + // internal type + if (info::type::ToInternalType(node->type.type).has_value()) { + if (!node->path.empty()) { + error_handling::HandleTypecheckError("Internal type is not in namespace", node->base); + } + + if (!node->type.parameters.empty()) { + error_handling::HandleTypecheckError("Can't parametrize internal type", node->base); + } + return; + } + + // abstract / basic / TODO: local abstract type if (path.size() == 0 && namespace_visitor_.FindAbstractType(node->type.type).has_value()) { // TODO - // abstract / basic / TODO: local abstract type return; } diff --git a/src/print_visitor.cpp b/src/print_visitor.cpp index b09329e..825964e 100644 --- a/src/print_visitor.cpp +++ b/src/print_visitor.cpp @@ -742,4 +742,8 @@ void PrintVisitor::Visit(UnitLiteral* node) { out_ << "[Unit ()] "; } +void PrintVisitor::Visit(BoolLiteral* node) { + out_ << "[Bool " << (node->value ? "true" : "false") << "] "; +} + } // namespace interpreter diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 67718ad..a10e86e 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -765,7 +765,6 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { } if (node->prefix.has_value()) { - if (std::holds_alternative>(node->prefix.value())) { Visitor::Visit(*std::get>(node->prefix.value())); @@ -857,8 +856,8 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { // - if (function_declaration.argument_types.size() + 1 != node->arguments.size()) { - error_handling::HandleTypecheckError("Mismatched argument count in function call expression", node->base); + if (function_declaration.argument_types.size() != node->arguments.size() + 1) { + error_handling::HandleTypecheckError("Mismatched argument count in function call expression", node->base); } for (size_t i = 0; i < node->arguments.size(); ++i) { Visitor::Visit(*function_declaration.argument_types[i]); @@ -1015,7 +1014,7 @@ void TypeCheckVisitor::Visit(ArrayExpression* node) { } } - if (node->elements.size() == 0) { + if (node->elements.empty()) { error_handling::HandleInternalError("Element size is 0", "TypeCheckVisitor.ArrayExpression"); } @@ -1032,7 +1031,7 @@ void TypeCheckVisitor::Visit(PartitionName* node) {} // Handled in partition ( e void TypeCheckVisitor::Visit(NameExpression* node) { // TODO: move, etc. - if (node->names.size() == 0) { + if (node->names.empty()) { error_handling::HandleInternalError("Name expression with zero names", "TypeCheckVisitor.NameExpression"); } @@ -1136,7 +1135,7 @@ void TypeCheckVisitor::Visit(VariantName* node) { } for (size_t i = 0; i < node->names.size(); ++i) { - if (maybe_type_value.value()->GetConstructors()[i].GetFields().size() == 0) { + if (maybe_type_value.value()->GetConstructors()[i].GetFields().empty()) { current_type_ = context_manager_.AddType( info::type::OptionalType(context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp), context_manager_.GetTypeManager()), utils::IsConstModifierToValueType(is_const_definition_.value())); // TODO ?? @@ -1254,27 +1253,36 @@ void TypeCheckVisitor::Visit(VariantType* node) { node->base.type_ = current_type_; } +// TODO: better function design // TODO handle local abstract types, abstract types, aliases, etc. void TypeCheckVisitor::Visit(TypeExpression* node) { std::unordered_map context; CollectTypeExpressionContext(*node, context); - std::optional maybe_local_abstract_type = context_manager_.GetLocalAbstractType(node->type.type); - if (node->path.size() == 0 && maybe_local_abstract_type.has_value()) { - current_type_ = maybe_local_abstract_type.value(); - } else if (node->type.type_id_.has_value()) { // TODO: chack that names are different (always true ??) + auto maybe_internal_type = info::type::ToInternalType(node->type.type); - std::optional maybe_type_info = - namespace_visitor_.GetGlobalInfo()->GetTypeInfo(node->type.type_id_.value()); + if (maybe_internal_type.has_value()) { + // checks made in link_symbols_visitor - if (!maybe_type_info.has_value()) { // TODO: add alias, abstract, ... types - error_handling::HandleInternalError("No AnyType found", "TypeCheckVisitor.TypeExpression"); - } - - Visitor::Visit(*maybe_type_info.value()->value); - current_type_ = TypeInContext(current_type_, context); + current_type_ = context_manager_.AddType(maybe_internal_type.value(), utils::ValueType::Tmp); } else { - error_handling::HandleTypecheckError("Type not found", node->base); + std::optional maybe_local_abstract_type = context_manager_.GetLocalAbstractType(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: chack that names are different (always true ??) + + std::optional maybe_type_info = + namespace_visitor_.GetGlobalInfo()->GetTypeInfo(node->type.type_id_.value()); + + if (!maybe_type_info.has_value()) { // TODO: add alias, abstract, ... types + error_handling::HandleInternalError("No AnyType found", "TypeCheckVisitor.TypeExpression"); + } + + Visitor::Visit(*maybe_type_info.value()->value); + current_type_ = TypeInContext(current_type_, context); + } else { + error_handling::HandleTypecheckError("Type not found", node->base); + } } if (node->array_size.has_value()) { @@ -1342,6 +1350,12 @@ void TypeCheckVisitor::Visit(UnitLiteral* node) { node->base.type_ = current_type_; } +void TypeCheckVisitor::Visit(BoolLiteral* node) { + current_type_ = context_manager_.AddType(info::type::InternalType::Bool, utils::ValueType::Tmp); + + node->base.type_ = current_type_; +} + // void TypeCheckVisitor::CollectTypeContext(const ParametrizedType& type, diff --git a/src/typed_print_visitor.cpp b/src/typed_print_visitor.cpp index 76fbf36..5e21ad9 100644 --- a/src/typed_print_visitor.cpp +++ b/src/typed_print_visitor.cpp @@ -1065,4 +1065,14 @@ void TypedPrintVisitor::Visit(UnitLiteral* node) { out_ << ") ()] "; } +void TypedPrintVisitor::Visit(BoolLiteral* node) { + out_ << "[bool : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyType(node->base.type_.value())->GetTypeName(); + } + + out_ << ") " << (node->value ? "true" : "false") << "] "; +} + } // namespace interpreter diff --git a/src/visitor.cpp b/src/visitor.cpp index 37770e3..e39d3e3 100644 --- a/src/visitor.cpp +++ b/src/visitor.cpp @@ -285,6 +285,9 @@ void Visitor::Visit(Literal& node) { case 4: Visit(std::get>(node).get()); break; + case 5: + Visit(std::get>(node).get()); + break; default: // error break; @@ -674,5 +677,7 @@ void Visitor::Visit(CharLiteral* node) {} void Visitor::Visit(UnitLiteral* node) {} +void Visitor::Visit(BoolLiteral* node) {} + } // namespace interpreter diff --git a/tests/test_code.lang b/tests/test_code.lang index 2f258d2..139305f 100644 --- a/tests/test_code.lang +++ b/tests/test_code.lang @@ -1,7 +1,3 @@ -basic String -basic Int -basic Unit - decl print : String -> Unit decl func : String -> Int