From 189306df260941d3b09c09276e800ef60c823bd2 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Mon, 3 Jul 2023 19:05:50 +0300 Subject: [PATCH] const -> let --- include/build_visitor.hpp | 2 + include/builtin_functions.hpp | 8 ++ include/execute_visitor.hpp | 2 + include/find_symbols_visitor.hpp | 2 + include/interpreter_tree.hpp | 28 ++++- include/link_symbols_visitor.hpp | 2 + include/parse_token_types.hpp | 2 + include/print_visitor.hpp | 2 + include/type_check_visitor.hpp | 2 + include/typed_print_visitor.hpp | 2 + include/utils.hpp | 2 +- include/visitor.hpp | 2 + lang-parser | 2 +- src/build_visitor.cpp | 105 ++++++++++++++--- src/execute_visitor.cpp | 47 +++++++- src/find_symbols_visitor.cpp | 3 +- src/print_visitor.cpp | 38 ++++++- src/type_check_visitor.cpp | 50 ++++++-- src/typed_print_visitor.cpp | 50 +++++++- src/utils.cpp | 3 + src/visitor.cpp | 34 +++++- tests/arrays.lang | 10 +- tests/flow_control.lang | 12 +- tests/functions.lang | 14 ++- tests/lambdas.lang | 10 +- tests/match.lang | 2 +- tests/memory.lang | 2 +- tests/namespaces.lang | 2 +- tests/partitions.lang | 10 +- tests/stdlib.lang | 189 ------------------------------- tests/test_code.lang | 49 ++++---- tests/tuples.lang | 2 +- tests/variants.lang | 1 + 33 files changed, 406 insertions(+), 285 deletions(-) delete mode 100644 tests/stdlib.lang diff --git a/include/build_visitor.hpp b/include/build_visitor.hpp index 65d71cc..dd9de94 100644 --- a/include/build_visitor.hpp +++ b/include/build_visitor.hpp @@ -91,6 +91,8 @@ private: void Visit(TypeConstructorParameter* node) override; void Visit(TypeConstructor* node) override; void Visit(LambdaFunction* node) override; + void Visit(AndExpression* node) override; + void Visit(OrExpression* node) override; void Visit(ArrayExpression* node) override; void Visit(LoopControlExpression& node) override; // enum diff --git a/include/builtin_functions.hpp b/include/builtin_functions.hpp index 25324de..8c4d868 100644 --- a/include/builtin_functions.hpp +++ b/include/builtin_functions.hpp @@ -22,4 +22,12 @@ inline T Read() { return value; } +template +inline void Error(const T& value) { // only for strings ?? + std::cout << "\x1b[1;33mError:\x1b[0m "; + std::cout << value; + std::cout << '\n'; + exit(1); +} + } // namespace info diff --git a/include/execute_visitor.hpp b/include/execute_visitor.hpp index dce215d..e6e00be 100644 --- a/include/execute_visitor.hpp +++ b/include/execute_visitor.hpp @@ -100,6 +100,8 @@ private: void Visit(TypeConstructorParameter* node) override; void Visit(TypeConstructor* node) override; void Visit(LambdaFunction* node) override; + void Visit(AndExpression* node) override; + void Visit(OrExpression* node) override; void Visit(ArrayExpression* node) override; void Visit(LoopControlExpression& node) override; // enum diff --git a/include/find_symbols_visitor.hpp b/include/find_symbols_visitor.hpp index 26fbdc1..a74bfef 100644 --- a/include/find_symbols_visitor.hpp +++ b/include/find_symbols_visitor.hpp @@ -76,6 +76,8 @@ private: // // void Visit(TypeConstructorParameter* node) override; // // void Visit(TypeConstructor* node) override; // // void Visit(LambdaFunction* node) override; + // // void Visit(AndExpression* node) override; + // // void Visit(OrExpression* node) override; // // void Visit(ArrayExpression* node) override; // // void Visit(LoopControlExpression& node) override; // enum diff --git a/include/interpreter_tree.hpp b/include/interpreter_tree.hpp index afdbbdf..fce6c24 100644 --- a/include/interpreter_tree.hpp +++ b/include/interpreter_tree.hpp @@ -131,7 +131,6 @@ using SubExpressionToken = std::variant< std::unique_ptr>; // struct FunctionCallExpression; -struct ArrayExpression; using SubExpression = std::variant< // BiaryOperatorExpression is FunctionCallExpression std::unique_ptr, std::unique_ptr>; @@ -149,11 +148,17 @@ using PrefixedExpression = std::variant< // struct LambdaFunction; struct TypeConstructor; +struct AndExpression; +struct OrExpression; +struct ArrayExpression; using Expression = std::variant< std::unique_ptr, std::unique_ptr, std::unique_ptr, - std::unique_ptr>; + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr>; // struct TupleExpression; struct VariantExpression; @@ -161,7 +166,6 @@ using SuperExpression = std::variant< std::unique_ptr, std::unique_ptr, std::unique_ptr, - std::unique_ptr, std::unique_ptr>; // @@ -181,6 +185,8 @@ struct ReturnExpression; struct TypeConstructorParameter; struct TypeConstructor; struct LambdaFunction; +struct AndExpression; +struct OrExpression; struct ArrayExpression; // Name @@ -525,7 +531,7 @@ struct FunctionCallExpression { std::unique_ptr>> prefix; NameOrOperatorIdentifier name; std::vector> parameters; - std::vector arguments; + std::vector, SubExpression>> arguments; std::optional precedence; // for operators bool is_binary_operator_expression = false; // for operators @@ -587,6 +593,18 @@ struct LambdaFunction { utils::IdType return_type_graph_id_ = 0; }; +struct AndExpression { + BaseNode base; + + std::vector expressions; +}; + +struct OrExpression { + BaseNode base; + + std::vector expressions; +}; + struct ArrayExpression { BaseNode base; @@ -632,7 +650,7 @@ struct Name { struct FunctionType { BaseNode base; - std::vector> types; + std::vector, std::unique_ptr>> types; }; struct TupleType { diff --git a/include/link_symbols_visitor.hpp b/include/link_symbols_visitor.hpp index 2670121..0de69d9 100644 --- a/include/link_symbols_visitor.hpp +++ b/include/link_symbols_visitor.hpp @@ -85,6 +85,8 @@ private: // // void Visit(TypeConstructorParameter* node) override; // // void Visit(TypeConstructor* node) override; // // void Visit(LambdaFunction* node) override; + // // void Visit(AndExpression* node) override; + // // void Visit(OrExpression* node) override; // // void Visit(ArrayExpression* node) override; // // void Visit(LoopControlExpression& node) override; // enum diff --git a/include/parse_token_types.hpp b/include/parse_token_types.hpp index 2c47100..d7503fb 100644 --- a/include/parse_token_types.hpp +++ b/include/parse_token_types.hpp @@ -77,6 +77,8 @@ const std::string ReturnExpression = "return_expression"; const std::string TypeConstructorParameter = "type_constructor_parameter"; const std::string TypeConstructor = "type_constructor"; const std::string LambdaFunction = "lambda_function"; +const std::string AndExpression = "and_expression"; +const std::string OrExpression = "or_expression"; const std::string ArrayExpression = "array_expression"; const std::string LoopControlExpression = "loop_control_expression"; diff --git a/include/print_visitor.hpp b/include/print_visitor.hpp index 7e1584b..f24b943 100644 --- a/include/print_visitor.hpp +++ b/include/print_visitor.hpp @@ -74,6 +74,8 @@ private: void Visit(TypeConstructorParameter* node) override; void Visit(TypeConstructor* node) override; void Visit(LambdaFunction* node) override; + void Visit(AndExpression* node) override; + void Visit(OrExpression* node) override; void Visit(ArrayExpression* node) override; void Visit(LoopControlExpression& node) override; // enum diff --git a/include/type_check_visitor.hpp b/include/type_check_visitor.hpp index 5f794b5..196ccdd 100644 --- a/include/type_check_visitor.hpp +++ b/include/type_check_visitor.hpp @@ -95,6 +95,8 @@ private: void Visit(TypeConstructorParameter* node) override; void Visit(TypeConstructor* node) override; void Visit(LambdaFunction* node) override; + void Visit(AndExpression* node) override; + void Visit(OrExpression* node) override; void Visit(ArrayExpression* node) override; void Visit(LoopControlExpression& node) override; // enum diff --git a/include/typed_print_visitor.hpp b/include/typed_print_visitor.hpp index c023b00..7700c73 100644 --- a/include/typed_print_visitor.hpp +++ b/include/typed_print_visitor.hpp @@ -76,6 +76,8 @@ private: void Visit(TypeConstructorParameter* node) override; void Visit(TypeConstructor* node) override; void Visit(LambdaFunction* node) override; + void Visit(AndExpression* node) override; + void Visit(OrExpression* node) override; void Visit(ArrayExpression* node) override; void Visit(LoopControlExpression& node) override; // enum diff --git a/include/utils.hpp b/include/utils.hpp index efca7ff..4e7541e 100644 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -27,7 +27,7 @@ enum class ClassModifier { Struct = 0, Class = 1 }; enum class AssignmentModifier { Assign = 0, Move = 1 }; enum class AliasModifier { Alias = 0, Type = 1, Let = 2 }; enum class AbstractTypeModifier { Basic = 0, Abstract = 1 }; -enum class PartitionModifier { Exec = 0, Test = 1 }; +enum class PartitionModifier { Exec = 0, Test = 1, Example = 2 }; enum class ValueType { Const = 0, Var = 1, Tmp = 2 }; diff --git a/include/visitor.hpp b/include/visitor.hpp index 2949020..c4262f0 100644 --- a/include/visitor.hpp +++ b/include/visitor.hpp @@ -88,6 +88,8 @@ protected: virtual void Visit(TypeConstructorParameter* node); virtual void Visit(TypeConstructor* node); virtual void Visit(LambdaFunction* node); + virtual void Visit(AndExpression* node); + virtual void Visit(OrExpression* node); virtual void Visit(ArrayExpression* node); virtual void Visit(LoopControlExpression& node); // enum diff --git a/lang-parser b/lang-parser index 25f8750..8e69e96 160000 --- a/lang-parser +++ b/lang-parser @@ -1 +1 @@ -Subproject commit 25f8750ab2a99222f61b4702419f8b4533ed8cf4 +Subproject commit 8e69e96520290fab76a98e620d58a4478e9d0861 diff --git a/src/build_visitor.cpp b/src/build_visitor.cpp index 0403977..124c118 100644 --- a/src/build_visitor.cpp +++ b/src/build_visitor.cpp @@ -315,6 +315,8 @@ void BuildVisitor::Visit(PartitionStatement* node) { node->modifier = utils::PartitionModifier::Exec; } else if (partition_modifier == "test") { node->modifier = utils::PartitionModifier::Test; + } else if (partition_modifier == "example") { + node->modifier = utils::PartitionModifier::Example; } else { // error } @@ -826,6 +828,15 @@ void BuildVisitor::Visit(Expression& node) { } else if (current_node_type == parser::tokens::SubExpression) { node = std::make_unique(); Visit(*std::get>(node)); + } else if (current_node_type == parser::tokens::AndExpression) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::OrExpression) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::ArrayExpression) { + node = std::make_unique(); + Visit(std::get>(node).get()); } else { // error } @@ -849,9 +860,6 @@ void BuildVisitor::Visit(SuperExpression& node) { } else if (current_node_type == parser::tokens::VariantExpression) { node = std::make_unique(); Visit(std::get>(node).get()); - } else if (current_node_type == parser::tokens::ArrayExpression) { - node = std::make_unique(); - Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::Expression) { node = std::make_unique(); Visit(*std::get>(node)); @@ -884,7 +892,7 @@ void BuildVisitor::VisitBinaryOperatorExpression(FunctionCallExpression* node) { node->arguments.resize(2); current_node_ = parse_node.ChildByFieldName("left_expression"); - Visit(node->arguments[0]); + Visit(node->arguments[0].second); node->name = parse_node.ChildByFieldName("operator_name").GetValue(); @@ -896,15 +904,16 @@ void BuildVisitor::VisitBinaryOperatorExpression(FunctionCallExpression* node) { } current_node_ = parse_node.ChildByFieldName("right_expression"); - Visit(node->arguments[1]); + Visit(node->arguments[1].second); // ?? for (size_t i = 0; i < node->arguments.size(); ++i) { - if (std::holds_alternative>(node->arguments[i])) { - FunctionCallExpression* argument_node = std::get>(node->arguments[i]).get(); + if (std::holds_alternative>(node->arguments[i].second)) { + FunctionCallExpression* argument_node = std::get>(node->arguments[i].second).get(); if (argument_node->is_binary_operator_expression && argument_node->precedence.has_value() - && argument_node->precedence.value() == node->precedence.value()) { + && argument_node->precedence.value() == node->precedence.value() + && node->name != argument_node->name) { // same operators can be chained error_handling::HandleParsingError("Operators can't be chained (left argument)", node->base.start_position, node->base.end_position); } } @@ -986,6 +995,7 @@ void BuildVisitor::Visit(FunctionCallExpression* node) { if (child_count > excluded_child_count) { bool parameters_ended = false; + bool last_child_is_annotation = false; for (size_t i = 0; i + excluded_child_count < child_count; ++i) { current_node_ = parse_node.NthNamedChild(i + excluded_child_count); @@ -998,10 +1008,26 @@ void BuildVisitor::Visit(FunctionCallExpression* node) { node->parameters.push_back(std::make_unique()); Visit(node->parameters.back().get()); } else { - node->arguments.push_back(std::make_unique()); - Visit(*std::get>(node->arguments.back())); + if (!current_node_.PreviousSibling().IsNull() && current_node_.PreviousSibling().GetValue() == "::") { // annotation + node->arguments.push_back({current_node_.GetValue(), SubExpression()}); + last_child_is_annotation = true; + } else if (last_child_is_annotation) { // argument after annotation + node->arguments.back().second = std::make_unique(); + Visit(*std::get>(node->arguments.back().second)); + last_child_is_annotation = false; + } else { // argument without annotation + node->arguments.push_back({std::nullopt, std::make_unique()}); + Visit(*std::get>(node->arguments.back().second)); + last_child_is_annotation = false; + } } } + + if (last_child_is_annotation) { + error_handling::HandleInternalError("Last child is annotation", + "BuildVisitor.FunctionCallExpression", + &node->base); + } } current_node_ = parse_node; @@ -1137,6 +1163,40 @@ void BuildVisitor::Visit(LambdaFunction* node) { current_node_ = parse_node; } +void BuildVisitor::Visit(AndExpression* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t expressions_count = parse_node.NamedChildCount(); + + node->expressions.resize(expressions_count); + + for (size_t i = 0; i < expressions_count; ++i) { + current_node_ = parse_node.NthNamedChild(i); + Visit(node->expressions[i]); + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(OrExpression* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t expressions_count = parse_node.NamedChildCount(); + + node->expressions.resize(expressions_count); + + for (size_t i = 0; i < expressions_count; ++i) { + current_node_ = parse_node.NthNamedChild(i); + Visit(node->expressions[i]); + } + + current_node_ = parse_node; +} + void BuildVisitor::Visit(ArrayExpression* node) { SetPosition(node->base, current_node_); @@ -1296,12 +1356,31 @@ void BuildVisitor::Visit(FunctionType* node) { size_t types_count = parse_node.NamedChildCount(); - node->types.resize(types_count); + node->types.reserve(types_count); + + bool last_child_is_annotation = false; for (size_t i = 0; i < types_count; ++i) { current_node_ = parse_node.NthNamedChild(i); - node->types[i] = std::make_unique(); - Visit(node->types[i].get()); + + if (!current_node_.PreviousSibling().IsNull() && current_node_.PreviousSibling().GetValue() == "::") { // annotation + node->types.push_back({current_node_.GetValue(), nullptr}); + last_child_is_annotation = true; + } else if (last_child_is_annotation) { // argument after annotation + node->types.back().second = std::make_unique(); + Visit(node->types.back().second.get()); + last_child_is_annotation = false; + } else { // argument without annotation + node->types.push_back({std::nullopt, std::make_unique()}); + Visit(node->types.back().second.get()); + last_child_is_annotation = false; + } + } + + if (last_child_is_annotation) { + error_handling::HandleInternalError("Last child is annotation", + "BuildVisitor.FunctionType", + &node->base); } current_node_ = parse_node; diff --git a/src/execute_visitor.cpp b/src/execute_visitor.cpp index 9a22c11..c3e002f 100644 --- a/src/execute_visitor.cpp +++ b/src/execute_visitor.cpp @@ -477,7 +477,7 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) { } } else { if (node->is_method_of_first_argument_) { - Visitor::Visit(node->arguments[0]); + Visitor::Visit(node->arguments[0].second); if (context_manager_.GetValueType(current_value_) == utils::ValueType::Tmp) { // temporary value can't be modified inside @@ -598,7 +598,7 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) { // handle arguments for (size_t i = index_shift; i < node->arguments.size(); ++i) { - Visitor::Visit(node->arguments[i]); + Visitor::Visit(node->arguments[i].second); // function arguments can't be changed inside function current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); @@ -711,6 +711,38 @@ void ExecuteVisitor::Visit(LambdaFunction* node) { &node->base); } +void ExecuteVisitor::Visit(AndExpression* node) { + bool result = true; + + for (auto& expression : node->expressions) { + Visitor::Visit(expression); + if (!*ExtractInternalValue(current_value_, node->base)) { + result = false; + break; + } + } + + current_value_ = context_manager_.AddValue( + info::value::InternalValue(result), + utils::ValueType::Tmp); +} + +void ExecuteVisitor::Visit(OrExpression* node) { + bool result = false; + + for (auto& expression : node->expressions) { + Visitor::Visit(expression); + if (*ExtractInternalValue(current_value_, node->base)) { + result = true; + break; + } + } + + current_value_ = context_manager_.AddValue( + info::value::InternalValue(result), + utils::ValueType::Tmp); +} + void ExecuteVisitor::Visit(ArrayExpression* node) { std::vector elements; @@ -1014,7 +1046,7 @@ void ExecuteVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) { bool ExecuteVisitor::HandleBuiltinFunctionCall(FunctionCallExpression* node) { if (node->name == "print") { - Visitor::Visit(node->arguments[0]); + Visitor::Visit(node->arguments[0].second); info::builtin::Print(*ExtractInternalValue(current_value_, node->base)); current_value_ = context_manager_.AddValue(info::value::InternalValue(info::value::Unit()), @@ -1025,6 +1057,13 @@ bool ExecuteVisitor::HandleBuiltinFunctionCall(FunctionCallExpression* node) { } else if (node->name == "random") { // TODO: different types, better random, seed, etc. current_value_ = context_manager_.AddValue(info::value::InternalValue(rand()), utils::ValueType::Tmp); + } else if (node->name == "error") { + Visitor::Visit(node->arguments[0].second); + info::builtin::Error(*ExtractInternalValue(current_value_, node->base)); + + error_handling::HandleInternalError("Error function finished", + "ExecuteVisitor.HandleBuiltinFunctionCall", + &node->base); } else { return false; } @@ -1046,7 +1085,7 @@ bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node, } for (auto& argument : node->arguments) { - Visitor::Visit(argument); + Visitor::Visit(argument.second); arguments.push_back(ExtractValue(current_value_, node->base)); } diff --git a/src/find_symbols_visitor.cpp b/src/find_symbols_visitor.cpp index 8529b81..cff4a65 100644 --- a/src/find_symbols_visitor.cpp +++ b/src/find_symbols_visitor.cpp @@ -65,7 +65,7 @@ void FindSymbolsVisitor::Visit(FunctionDeclaration* node) { info.argument_types.resize(node->type->types.size()); for (size_t i = 0; i < node->type->types.size(); ++i) { - info.argument_types[i] = node->type->types[i].get(); + info.argument_types[i] = node->type->types[i].second.get(); } info.node = node; @@ -179,6 +179,7 @@ void FindSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) { } void FindSymbolsVisitor::Visit(PartitionStatement* node) { + // TODO: difference between partitions ?? node->executable_id_ = namespace_visitor_.AddPartition(node->name.path, node, node->base); Visitor::Visit(node->value); // to visit all tree diff --git a/src/print_visitor.cpp b/src/print_visitor.cpp index 55345fc..726a4b4 100644 --- a/src/print_visitor.cpp +++ b/src/print_visitor.cpp @@ -193,6 +193,9 @@ void PrintVisitor::Visit(PartitionStatement* node) { case utils::PartitionModifier::Test: out_ << "test "; break; + case utils::PartitionModifier::Example: + out_ << "example "; + break; } Visit(&node->name); out_ << "] = ("; @@ -460,7 +463,13 @@ void PrintVisitor::Visit(FunctionCallExpression* node) { } is_first = false; - Visitor::Visit(argument); + if (argument.first.has_value()) { + out_ << "::"; + Visit(&argument.first.value()); + out_ << ' '; + } + + Visitor::Visit(argument.second); } out_ << ")"; } @@ -544,6 +553,24 @@ void PrintVisitor::Visit(LambdaFunction* node) { out_ << ")\n"; } +void PrintVisitor::Visit(AndExpression* node) { + out_ << "[AndExpression] ("; + for (auto& expression : node->expressions) { + out_ << "&&"; + Visitor::Visit(expression); + } + out_ << ")"; +} + +void PrintVisitor::Visit(OrExpression* node) { + out_ << "[OrExpression] ("; + for (auto& expression : node->expressions) { + out_ << "||"; + Visitor::Visit(expression); + } + out_ << ")"; +} + void PrintVisitor::Visit(ArrayExpression* node) { out_ << "[ArrayExpression] ( ,"; for (auto& element : node->elements) { @@ -619,7 +646,14 @@ void PrintVisitor::Visit(FunctionType* node) { out_ << " -> "; } is_first = false; - Visit(type.get()); + + if (type.first.has_value()) { + out_ << "::"; + Visit(&type.first.value()); + out_ << ' '; + } + + Visit(type.second.get()); } out_ << ')'; } diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index d9fae1b..e41d337 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -239,14 +239,14 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { } for (size_t i = 0; i < node->definition->arguments.size(); ++i) { - Visit(declaration->type->types[i].get()); + Visit(declaration->type->types[i].second.get()); current_type_ = context_manager_.ToModifiedValue(current_type_, utils::ValueType::Const); if (!context_manager_.DefineVariable(node->definition->arguments[i], current_type_)) { error_handling::HandleTypecheckError("Can't define function argument variable: name redefinition", node->base); } } - Visit(declaration->type->types.back().get()); + Visit(declaration->type->types.back().second.get()); utils::IdType returned_type = current_type_; returned_type_ = std::nullopt; @@ -828,10 +828,18 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { } for (size_t i = index_shift; i < node->arguments.size(); ++i) { - Visit(function_declaration->type->types[i - index_shift].get()); + Visit(function_declaration->type->types[i - index_shift].second.get()); utils::IdType argument_type = TypeInContext(current_type_, context); - Visitor::Visit(node->arguments[i]); + if (node->arguments[i].first.has_value()) { + if (!function_declaration->type->types[i - index_shift].first.has_value()) { + error_handling::HandleTypecheckError("Declared argument has no annotation (argument " + std::to_string(i - index_shift + 1) + ")", node->base); + } else if (node->arguments[i].first.value() != function_declaration->type->types[i - index_shift].first.value()) { + error_handling::HandleTypecheckError("Wrong argument annotation (argument " + std::to_string(i - index_shift + 1) + ")", node->base); + } + } + + Visitor::Visit(node->arguments[i].second); if (!context_manager_.AddValueRequirement(current_type_, argument_type)) { error_handling::HandleTypecheckError("Wrong argument type (argument " + std::to_string(i - index_shift + 1) + ")", node->base); } @@ -863,7 +871,7 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { } } - Visit(function_declaration->type->types.back().get()); + Visit(function_declaration->type->types.back().second.get()); current_type_ = TypeInContext(current_type_, context); context_manager_.ExitContext(); @@ -1052,6 +1060,32 @@ void TypeCheckVisitor::Visit(LambdaFunction* node) { node->base.type_ = current_type_; } +void TypeCheckVisitor::Visit(AndExpression* node) { + for (auto& expression : node->expressions) { + Visitor::Visit(expression); + if (!context_manager_.EqualValues(internal_to_abstract_type_.at(info::type::InternalType::Bool), current_type_)) { + error_handling::HandleTypecheckError("And expression element is not bool expression", node->base); + } + } + + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Bool); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(OrExpression* node) { + for (auto& expression : node->expressions) { + Visitor::Visit(expression); + if (!context_manager_.EqualValues(internal_to_abstract_type_.at(info::type::InternalType::Bool), current_type_)) { + error_handling::HandleTypecheckError("Or expression element is not bool expression", node->base); + } + } + + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Bool); + + node->base.type_ = current_type_; +} + void TypeCheckVisitor::Visit(ArrayExpression* node) { utils::IdType elements_type = 0; @@ -1282,7 +1316,7 @@ void TypeCheckVisitor::Visit(FunctionType* node) { std::vector argument_types(node->types.size()); for (auto& argument_type : node->types) { - Visit(argument_type.get()); + Visit(argument_type.second.get()); argument_types.push_back(current_type_); } @@ -1677,8 +1711,8 @@ std::optional TypeCheckVisitor::FindFunctionAndUpdate(Func } } - if (!maybe_function_declaration.has_value() && node->is_binary_operator_expression && node->arguments.size() > 0) { - Visitor::Visit(node->arguments[0]); + if (!maybe_function_declaration.has_value() && node->is_binary_operator_expression && node->arguments.size() > 0 && !node->arguments[0].first.has_value()) { // ... , no annotation + Visitor::Visit(node->arguments[0].second); maybe_function_declaration = FindExpressionMethodAndUpdate(node, current_type_); if (maybe_function_declaration.has_value()) { node->is_method_of_first_argument_ = true; diff --git a/src/typed_print_visitor.cpp b/src/typed_print_visitor.cpp index 9a7eae4..3f7d89b 100644 --- a/src/typed_print_visitor.cpp +++ b/src/typed_print_visitor.cpp @@ -260,6 +260,9 @@ void TypedPrintVisitor::Visit(PartitionStatement* node) { case utils::PartitionModifier::Test: out_ << "test "; break; + case utils::PartitionModifier::Example: + out_ << "example "; + break; } Visit(&node->name); out_ << "] = ("; @@ -631,7 +634,13 @@ void TypedPrintVisitor::Visit(FunctionCallExpression* node) { } is_first = false; - Visitor::Visit(argument); + if (argument.first.has_value()) { + out_ << "::"; + Visit(&argument.first.value()); + out_ << ' '; + } + + Visitor::Visit(argument.second); } out_ << ")"; } @@ -750,6 +759,36 @@ void TypedPrintVisitor::Visit(LambdaFunction* node) { out_ << ")\n"; } +void TypedPrintVisitor::Visit(AndExpression* node) { + out_ << "[AndExpression : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + for (auto& expression : node->expressions) { + out_ << "&&"; + Visitor::Visit(expression); + } + out_ << ")"; +} + +void TypedPrintVisitor::Visit(OrExpression* node) { + out_ << "[OrExpression : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + for (auto& expression : node->expressions) { + out_ << "||"; + Visitor::Visit(expression); + } + out_ << ")"; +} + void TypedPrintVisitor::Visit(ArrayExpression* node) { out_ << "[ArrayExpression : "; @@ -873,7 +912,14 @@ void TypedPrintVisitor::Visit(FunctionType* node) { out_ << " -> "; } is_first = false; - Visit(type.get()); + + if (type.first.has_value()) { + out_ << "::"; + Visit(&type.first.value()); + out_ << ' '; + } + + Visit(type.second.get()); } out_ << ')'; } diff --git a/src/utils.cpp b/src/utils.cpp index 5c9fad4..3254bf2 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -56,6 +56,8 @@ std::optional ToEscapeSymbol(char symbol) { return '\t'; case 'v': return '\v'; + case 's': + return ' '; default: return std::nullopt; } @@ -82,6 +84,7 @@ bool IsBuiltinFunction(const std::string& name) { // optimize ?? builtin_functions.insert("one"); builtin_functions.insert("show"); builtin_functions.insert("read"); + builtin_functions.insert("error"); // builtin_functions.insert("debug_show"); // TODO return builtin_functions.count(name) != 0; diff --git a/src/visitor.cpp b/src/visitor.cpp index 5b57145..5851ffa 100644 --- a/src/visitor.cpp +++ b/src/visitor.cpp @@ -188,6 +188,15 @@ void Visitor::Visit(Expression& node) { case 3: Visit(*std::get>(node)); break; + case 4: + Visit(std::get>(node).get()); + break; + case 5: + Visit(std::get>(node).get()); + break; + case 6: + Visit(std::get>(node).get()); + break; default: // error break; @@ -206,9 +215,6 @@ void Visitor::Visit(SuperExpression& node) { Visit(std::get>(node).get()); break; case 3: - Visit(std::get>(node).get()); - break; - case 4: Visit(*std::get>(node)); break; default: @@ -500,7 +506,10 @@ void Visitor::Visit(FunctionCallExpression* node) { } for (auto& argument : node->arguments) { - Visit(argument); + if (argument.first.has_value()) { + Visit(&argument.first.value()); + } + Visit(argument.second); } } @@ -544,6 +553,18 @@ void Visitor::Visit(LambdaFunction* node) { Visit(node->expression); } +void Visitor::Visit(AndExpression* node) { + for (auto& expression : node->expressions) { + Visit(expression); + } +} + +void Visitor::Visit(OrExpression* node) { + for (auto& expression : node->expressions) { + Visit(expression); + } +} + void Visitor::Visit(ArrayExpression* node) { for (auto& element : node->elements) { Visit(element); @@ -590,7 +611,10 @@ void Visitor::Visit(Name* node) { void Visitor::Visit(FunctionType* node) { for (auto& type : node->types) { - Visit(type.get()); + if (type.first.has_value()) { + Visit(&type.first.value()); + } + Visit(type.second.get()); } } diff --git a/tests/arrays.lang b/tests/arrays.lang index 12003af..d983513 100644 --- a/tests/arrays.lang +++ b/tests/arrays.lang @@ -1,18 +1,18 @@ decl test-arrays : -> \unit def test-arrays = { var arr1 = ,1 ,2 ,3 - const arr2 = \int..array: 32 + let arr2 = \int..array: 32 var arr3 = \string..array: 11 - const arr4 = ''a--''z - const n = 100 + let arr4 = ''a--''z + let n = 100 var arr5 <- \int..new-array: 10 var arr6 <- \string..new-array: 10 var arr6-reference = ^arr6 - const elem1 = arr1`0 + let elem1 = arr1`0 var elem2 = arr1`2 - const ref1 = ^arr1`1 + let ref1 = ^arr1`1 var ref2 = ^arr1`3 ; arr1`1 = 123 diff --git a/tests/flow_control.lang b/tests/flow_control.lang index 76e0993..192a001 100644 --- a/tests/flow_control.lang +++ b/tests/flow_control.lang @@ -1,14 +1,20 @@ decl flow-control-test : -> \unit def flow-control-test = { - if (a < b ||. a == b) && (b < c) then \io..print: x - elif x < 0 then { + if && ( || a < b + || a == b ) + && b < c + then \io..print: x + elif x < 0 + then { ; x += 1 ; \io..print: y } else { return {} } - while (a > 0) && not: (array..is-empty:) do { + while && a > 0 + && not: (array..is-empty:) + do { ; a -= 1 ; array..pop: } diff --git a/tests/functions.lang b/tests/functions.lang index e530d4d..7ddcead 100644 --- a/tests/functions.lang +++ b/tests/functions.lang @@ -30,15 +30,15 @@ def find-prefix-hashes : str = { alias \hash = \acc-hash[char] -decl find-substring : \string -> \string -> \array[index] +decl find-substring : ::str \string -> ::substr \string -> \array[index] def find-substring : str substr = { var result = \array[index]..empty: - const str-hashes = find-prefix-hashes:[hash] str - const substr-hash = \hash..of: substr + let str-hashes = find-prefix-hashes:[hash] str + let substr-hash = \hash..of: substr for i in 0--(str-hashes..size: - substr..size:) do { - const part-hash = hash..diff: str-hashes`(i + substr..size:) str-hashes`i + let part-hash = hash..diff: str-hashes`(i + substr..size:) str-hashes`i if part-hash == substr-hash then { ; result..push: i @@ -60,3 +60,9 @@ def mul : x y = x * y decl mul-10 : \int -> \int def mul-10 = mul: 10 + +exec main { + ; find-substring: + ::str "abacaba" + ::substr "bac" +} diff --git a/tests/lambdas.lang b/tests/lambdas.lang index f5f01d0..db20e31 100644 --- a/tests/lambdas.lang +++ b/tests/lambdas.lang @@ -1,12 +1,12 @@ decl test-lambdas : -> \unit def test-lambdas = { - const lambda1 = \\x -> x * x - const lambda2 = \\x -> x..hash: - const lambda3 = \\x y -> x + y + let lambda1 = \\x -> x * x + let lambda2 = \\x -> x..hash: + let lambda3 = \\x y -> x + y - const lambda4 = \\x -> { + let lambda4 = \\x -> { ; \io..print: x - const y = x + x + let y = x + x return y } } diff --git a/tests/match.lang b/tests/match.lang index d5ed074..5dcb3dd 100644 --- a/tests/match.lang +++ b/tests/match.lang @@ -8,7 +8,7 @@ def fruit-cost : fruit = { decl amount-to-string : \int -> \bool -> \string def amount-to-string : x is-zero-separated = { - const ans = match x with + let ans = match x with | 0 ?? is-zero-separated -> "Zero" | 0 | 1 | 2 | 3 | 4 -> "Few" | x ?? (5--9)..contains: x -> "Several" diff --git a/tests/memory.lang b/tests/memory.lang index c6a07f2..c0762f4 100644 --- a/tests/memory.lang +++ b/tests/memory.lang @@ -3,6 +3,6 @@ struct \struct-with-ref = decl test-memory : -> \unit def test-memory = { - const unique-ref1 <- \int..new: 5 + let unique-ref1 <- \int..new: 5 var unique-ref2 <- \array..of: 1 2 3 } diff --git a/tests/namespaces.lang b/tests/namespaces.lang index 1232fce..3c5f170 100644 --- a/tests/namespaces.lang +++ b/tests/namespaces.lang @@ -14,6 +14,6 @@ namespace var \array { decl something : -> \unit } -namespace const \array { +namespace let \array { decl something : -> \unit } diff --git a/tests/partitions.lang b/tests/partitions.lang index 5c2b1a4..4042809 100644 --- a/tests/partitions.lang +++ b/tests/partitions.lang @@ -1,10 +1,14 @@ test all.dev.syntax.testing { - const a = 31 + let a = 31 ; do-something: a } exec app.exe { - const b = true - const c = false + let b = true + let c = false ; do-something-different: b b c } + +example func.basic-example { + ; func: a b c // func executed +} diff --git a/tests/stdlib.lang b/tests/stdlib.lang deleted file mode 100644 index 46c451a..0000000 --- a/tests/stdlib.lang +++ /dev/null @@ -1,189 +0,0 @@ -basic \float[#ord #div #str] -basic \int[#ord #idiv #str] -basic \string[#ord #str #char-container #copy] -basic \char[#ord #str #copy] -basic \bool[#ord #str #copy] -basic \unit[#str #copy] - -// - -decl not : \bool -> \bool -def not : x = - (match x with - | true -> false - | false -> true) - -decl ( && ) : \bool -> \bool -> \bool -def ( && ) : x y = - match x with - | true -> ( - match y with - | true -> true - | false -> false - ) - | false -> false - -decl ( || ) : \bool -> \bool -> \bool -def ( || ) : x y = - match x with - | true -> true - | false -> ( - match y with - | true -> true - | false -> false - ) - -// - -typeclass \char-container = - & var size : -> \int - & var at : \int -> \char - -// - -typeclass \move = // TODO - & var ( <- ) : \move -> \unit - -typeclass \copy = - & var ( = ) : \copy -> \unit - -// - -typeclass \sum[#copy] = - & var ( += ) : \sum -> \unit - & var ( -= ) : \sum -> \unit - & var ( + ) : \sum -> \sum - & var ( - ) : \sum -> \sum - & zero : -> \sum - -namespace var \sum { - def ( + ) : x = { - var ans = self - ; ans += x - return ans - } - - def ( - ) : x = { - var ans = self - ; ans -= x - return ans - } -} - -typeclass \mult[#sum] = - & var ( *= ) : \mult -> \unit - & var ( * ) : \mult -> \mult - -namespace var \mult { - def ( * ) : x = { - var ans = self - ; ans *= x - return ans - } -} - -typeclass \idiv[#mult] = - & var div : \idiv -> \idiv - & var mod : \idiv -> \idiv - -namespace var \idiv { - def mod : x = self -. x * self..div: x -} - -typeclass \div[#mult] = - & var ( /= ) : \div -> \unit - & var ( / ) : \div -> \div - -namespace var \div { - def ( / ) : x = { - var ans = self - ; ans /= x - return ans - } -} - -// - -typeclass \eq = - & var ( == ) : \eq -> \bool - & var ( != ) : \eq -> \bool - -namespace var \eq { - def ( != ) : x = not: (self == x) -} - -// - -struct \order = - | $eq - | $lt - | $gt - -typeclass \ord[#eq] = - & var compare : \ord -> \order - & var ( < ) : \ord -> \bool - & var ( >= ) : \ord -> \bool - & var ( > ) : \ord -> \bool - & var ( <= ) : \ord -> \bool - -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 = - if self == x then $eq - elif self < x then $lt - else $gt - - def ( >= ) : x = not: (self < x) - def ( > ) : x = x < self - def ( <= ) : x = not: (x < self) -} - -// - -typeclass \show = - & var show : -> \string - -typeclass \read = - & read : \string -> \read - -typeclass \str[#show #read] - -// typeclass debug-show = // TODO -// & debugdshow : -> \string - -// - -typeclass \default = - & default : -> \default - -// - -typeclass \bounded = - & min-bound : -> \bounded - & max-bound : -> \bounded - & var is-max-bound : -> \bool - & var is-min-bound : -> \bool - -// - -typeclass \enum = - & var succ : -> \optional[enum] - & var pred : -> \optional[enum] - & to-enum : \int -> \enum - & var from-enum : -> \int - -// - -namespace io { - decl print : \string -> \unit - decl scan : -> \string -} - -decl random : -> \int // TODO - -// diff --git a/tests/test_code.lang b/tests/test_code.lang index 2dcd6dd..326aec4 100644 --- a/tests/test_code.lang +++ b/tests/test_code.lang @@ -7,32 +7,23 @@ basic \unit[#str #copy] // +namespace io { + decl print : \string -> \unit + decl scan : -> \string +} + +decl random : -> \int // TODO + +decl error : \string -> \unit + +// + decl not : \bool -> \bool def not : x = (match x with | true -> false | false -> true) -decl ( && ) : \bool -> \bool -> \bool -def ( && ) : x y = - match x with - | true -> ( - match y with - | true -> true - | false -> false - ) - | false -> false - -decl ( || ) : \bool -> \bool -> \bool -def ( || ) : x y = - match x with - | true -> true - | false -> ( - match y with - | true -> true - | false -> false - ) - // typeclass \char-container = @@ -179,15 +170,6 @@ typeclass \enum = // -namespace io { - decl print : \string -> \unit - decl scan : -> \string -} - -decl random : -> \int // TODO - -// - // // // bad // // typeclass \functor 'a = // // & fmap 'b ('f[#functor['b]]) : ('a -> 'b) -> \functor -> 'f @@ -231,7 +213,7 @@ def ( -- ) : begin end = { decl scan-int : -> \int def scan-int = \int..read: (\io..scan:) -decl print-int : \int -> \unit +decl print-int : ::x \int -> \unit def print-int : x = \io..print: (x..show:) decl scan-anything 'a[#read] : -> 'a @@ -277,6 +259,11 @@ def scan-three = & \io..scan: & \io..scan: & \io..scan: exec main { var n = scan-anything:[int] + + ; print-anything:[bool] (n < 2) // TODO: fix exception (arguments not present ??) + + if n > 1 then print-anything:[string] "aaa" // not work ?? + var x = (for _ in 0--n do scan-int:) // $array[int] & 0 var k? = if n < 2 then n * 2 +. 3 in @@ -285,6 +272,8 @@ exec main { ; print-anything:[int] n + ; print-int: ::x 123 + var & a & b & c = scan-three-t: ; \io..print: b var & d & e & f = scan-three: diff --git a/tests/tuples.lang b/tests/tuples.lang index 765cfa0..a3247e2 100644 --- a/tests/tuples.lang +++ b/tests/tuples.lang @@ -1,7 +1,7 @@ decl test-tuples : -> \unit def test-tuples = { var tuple1 = & ''a & 2 & "hello" - const & t1 & t2 & t3 = f: x + let & t1 & t2 & t3 = f: x ; tuple1`0 = ''b diff --git a/tests/variants.lang b/tests/variants.lang index 49b9019..c0ccd61 100644 --- a/tests/variants.lang +++ b/tests/variants.lang @@ -13,3 +13,4 @@ def test-variants = { | "hello" -> "nothing" | 11 -> "nothing" } +