diff --git a/include/execute_visitor.hpp b/include/execute_visitor.hpp index 0d1da6e..9ee72c0 100644 --- a/include/execute_visitor.hpp +++ b/include/execute_visitor.hpp @@ -31,6 +31,11 @@ public: }; void ExecutePartition(interpreter::tokens::PartitionStatement* partition) { + for (size_t i = 0; i < info::type::InternalTypesCount; ++i) { + info::type::InternalType type = static_cast(i); + std::string type_name = info::type::ToString(type); + context_manager_.DefineLocalType(type_name, global_info_.FindAbstractType(type_name).value()->node->type->graph_id_); + } Visit(partition); } diff --git a/include/global_info.hpp b/include/global_info.hpp index fe95619..dbc94e1 100644 --- a/include/global_info.hpp +++ b/include/global_info.hpp @@ -93,8 +93,6 @@ public: std::optional FindLocalTypeId(const std::string& type); - std::optional FindAbstractTypeId(const std::string& abstract_type); - std::optional FindTypeclassId(const std::string& typeclass); std::optional FindConstructorId(const std::optional>& path, @@ -164,14 +162,6 @@ public: return global_info_.GetTypeInfo(id.value()); } - std::optional FindAbstractType(const std::string& abstract_type) { - std::optional id = FindAbstractTypeId(abstract_type); - if (!id.has_value()) { - return std::nullopt; - } - return &global_info_.GetAbstractTypeInfo(id.value()); - } - std::optional FindTypeclass(const std::string& typeclass) { std::optional id = FindTypeclassId(typeclass); if (!id.has_value()) { @@ -368,6 +358,16 @@ public: // function declarations & definitions should be added latter std::optional AddAnnotatedTypeToGraph(interpreter::tokens::AnnotatedType* node); + std::optional FindAbstractTypeId(const std::string& abstract_type); + + std::optional FindAbstractType(const std::string& abstract_type) { + std::optional id = FindAbstractTypeId(abstract_type); + if (!id.has_value()) { + return std::nullopt; + } + return &GetAbstractTypeInfo(id.value()); + } + private: void CollectFunctionInfo( utils::IdType current_namespace, diff --git a/include/interpreter_tree.hpp b/include/interpreter_tree.hpp index 62918d8..26e22bd 100644 --- a/include/interpreter_tree.hpp +++ b/include/interpreter_tree.hpp @@ -654,6 +654,7 @@ struct TypeExpression { ParametrizedType type; std::optional array_size; // if array; 0 - dynamic size + bool is_optional = false; // for optionals std::optional type_id_; std::optional constructor_id_; diff --git a/include/type_check_visitor.hpp b/include/type_check_visitor.hpp index f77f197..2746a8b 100644 --- a/include/type_check_visitor.hpp +++ b/include/type_check_visitor.hpp @@ -27,7 +27,7 @@ public: // init internal type abstrac types for (size_t i = 0; i < info::type::InternalTypesCount; ++i) { info::type::InternalType type = static_cast(i); - Visit(namespace_visitor_.FindAbstractType(info::type::ToString(type)).value()->node); + Visit(global_info_.FindAbstractType(info::type::ToString(type)).value()->node); } Visit(source_file); diff --git a/lang-parser b/lang-parser index ddb08e9..5346d00 160000 --- a/lang-parser +++ b/lang-parser @@ -1 +1 @@ -Subproject commit ddb08e9b65123324800d1126d38764764363c0e5 +Subproject commit 5346d008497d93d30db4933dc3744b3de35cebf8 diff --git a/src/.link_symbols_visitor.cpp.kate-swp b/src/.link_symbols_visitor.cpp.kate-swp new file mode 100644 index 0000000..aabc743 Binary files /dev/null and b/src/.link_symbols_visitor.cpp.kate-swp differ diff --git a/src/build_visitor.cpp b/src/build_visitor.cpp index 7a4219c..1023303 100644 --- a/src/build_visitor.cpp +++ b/src/build_visitor.cpp @@ -53,19 +53,11 @@ void BuildVisitor::Visit(Namespace* node) { auto parse_node = current_node_; - size_t child_count = parse_node.ChildCount(); - - if (child_count > 3) { // "namespace", ["var"/"const",] type, scope - std::string modifier = parse_node.NthChild(1).GetValue(); - if (modifier == "const") { - node->modifier = utils::ClassInternalsModifier::Const; - } else if (modifier == "var") { - node->modifier = utils::ClassInternalsModifier::Var; - } else { - error_handling::HandleInternalError("Can't parse namespace modifier", - "BuildVisitor.Namespace", - &node->base); - } + std::string modifier = parse_node.NthChild(1).GetValue(); + if (modifier == "const") { + node->modifier = utils::ClassInternalsModifier::Const; + } else if (modifier == "var") { + node->modifier = utils::ClassInternalsModifier::Var; } else { node->modifier = utils::ClassInternalsModifier::Static; } @@ -1380,17 +1372,50 @@ void BuildVisitor::Visit(TypeExpression* node) { Visit(&node->type); ++excluded_child_count; - current_node_ = current_node_.NextSibling(); + auto suffix_node1 = current_node_.NextSibling(); - if (!current_node_.IsNull()) { - current_node_ = current_node_.NextSibling(); - if (!current_node_.IsNull()) { - NumberLiteral literal; - Visit(&literal); - node->array_size = literal.value; - ++excluded_child_count; + // TODO: better structure // TODO: check + if (!suffix_node1.IsNull()) { + auto suffix_node2 = suffix_node1.NextSibling(); + if (!suffix_node2.IsNull()) { + auto suffix_node3 = suffix_node2.NextSibling(); + if (!suffix_node3.IsNull()) { + current_node_ = suffix_node2; + + NumberLiteral literal; + Visit(&literal); + node->array_size = literal.value; + ++excluded_child_count; + + node->is_optional = true; + } else { + if (suffix_node1.GetValue() == "_" && suffix_node2.GetValue() == "!") { + node->array_size = 0; + + node->is_optional = true; + } else if (suffix_node1.GetValue() == "_") { + current_node_ = suffix_node2; + + NumberLiteral literal; + Visit(&literal); + node->array_size = literal.value; + ++excluded_child_count; + } else { + error_handling::HandleInternalError("Undefined suffix (2 elements)", + "BuildVisitor.TypeExpression", + std::nullopt); + } + } } else { - node->array_size = 0; + if (suffix_node1.GetValue() == "_") { + node->array_size = 0; + } else if (suffix_node1.GetValue() == "!") { + node->is_optional = true; + } else { + error_handling::HandleInternalError("Undefined suffix (1 element)", + "BuildVisitor.TypeExpression", + std::nullopt); + } } } diff --git a/src/global_info.cpp b/src/global_info.cpp index 7a71961..ec1481e 100644 --- a/src/global_info.cpp +++ b/src/global_info.cpp @@ -235,7 +235,7 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddAbstractType(const std::string& a // error_handling::HandleNamesError("Can't redefine basic type as abstract type", base_node); // } - if (FindAbstractType(abstract_type).has_value()) { + if (global_info_.FindAbstractType(abstract_type).has_value()) { error_handling::HandleNamesError("More then one abstract type with the same name in namespace", base_node); } @@ -385,16 +385,6 @@ std::optional GlobalInfo::NamespaceVisitor::FindLocalTypeId(const return std::nullopt; } -std::optional GlobalInfo::NamespaceVisitor::FindAbstractTypeId(const std::string& abstract_type) { - auto abstract_type_id_iter = global_info_.name_to_abstract_type_.find(abstract_type); - - if (abstract_type_id_iter != global_info_.name_to_abstract_type_.end()) { - return abstract_type_id_iter->second; - } - - return std::nullopt; -} - std::optional GlobalInfo::NamespaceVisitor::FindTypeclassId(const std::string& typeclass) { auto typeclass_id_iter = global_info_.name_to_typeclass_.find(typeclass); @@ -578,6 +568,16 @@ std::optional GlobalInfo::AddAnnotatedTypeToGraph(interpreter::to TypeclassGraph::Modifier::Type); } +std::optional GlobalInfo::FindAbstractTypeId(const std::string& abstract_type) { + auto abstract_type_id_iter = name_to_abstract_type_.find(abstract_type); + + if (abstract_type_id_iter != name_to_abstract_type_.end()) { + return abstract_type_id_iter->second; + } + + return std::nullopt; +} + void GlobalInfo::CollectFunctionInfo( utils::IdType current_namespace, utils::ClassInternalsModifier modifier, diff --git a/src/link_symbols_visitor.cpp b/src/link_symbols_visitor.cpp index 37454fc..46fe1e6 100644 --- a/src/link_symbols_visitor.cpp +++ b/src/link_symbols_visitor.cpp @@ -134,7 +134,7 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) { if (maybe_type_namespace.has_value()) { info::definition::Namespace* type_namespace = maybe_type_namespace.value(); - for (ssize_t i = (ssize_t)node->path.size(); i >= 0; --i) { + for (ssize_t i = (ssize_t)node->path.size() - 1; i >= 0; --i) { info::definition::Namespace* parent_namespace = &global_info_.GetNamespaceInfo(type_namespace->parent_namespace); auto type_iter = parent_namespace->types.find(type_namespace->type_name); diff --git a/src/print_visitor.cpp b/src/print_visitor.cpp index 077d233..5fb9861 100644 --- a/src/print_visitor.cpp +++ b/src/print_visitor.cpp @@ -654,10 +654,14 @@ void PrintVisitor::Visit(VariantType* node) { } void PrintVisitor::Visit(TypeExpression* node) { - out_ << "[TypeExpression "; + out_ << "[TypeExpression"; if (node->array_size.has_value()) { - out_ << "[array size: " << node->array_size.value() << ']'; + out_ << " [array size: " << node->array_size.value() << ']'; + } + + if (node->is_optional) { + out_ << " [optional]"; } out_ << "] ("; diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 74087e7..c01835c 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -249,8 +249,6 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { returned_type_ = current_type_; } if (!context_manager_.EqualValues(returned_type, returned_type_.value())) { - error_handling::DebugPrint(context_manager_.GetAnyValue(returned_type)->ToString()); - error_handling::DebugPrint(context_manager_.GetAnyValue(returned_type_.value())->ToString()); error_handling::HandleTypecheckError("Wrong function return type", node->base); } returned_type_ = std::nullopt; @@ -284,7 +282,7 @@ void TypeCheckVisitor::Visit(TypeDefinitionStatement* node) { auto function_iter = type_functions.find(function.first); if (function_iter == type_functions.end() || !global_info_.GetFunctionInfo(function_iter->second).definition.has_value()) { - error_handling::HandleTypecheckError("Type is not satisfy typeclass requirements: " + function.first + " is not defined", node->base); + error_handling::HandleTypecheckError("Type not define all required functions: " + function.first + " is not defined", node->base); } } @@ -1281,35 +1279,24 @@ void TypeCheckVisitor::Visit(TypeExpression* node) { std::unordered_map context; CollectTypeExpressionContext(*node, context); - // TODO: -------- remove, unneeded ------ - // auto maybe_internal_type = info::type::ToInternalType(node->type.type); - // - // if (maybe_internal_type.has_value()) { // TODO: ??? - // // checks made in link_symbols_visitor - // current_type_ = - // context_manager_.AddValue( - // maybe_internal_type.value(), - // utils::ValueType::Tmp); - // } else { - std::optional maybe_local_abstract_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 ??) - std::optional maybe_type_info = - global_info_.GetTypeInfo(node->type.type_id_.value()); + std::optional maybe_local_abstract_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 ??) + std::optional maybe_type_info = + 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", - &node->base); - } - - VisitDefinedType(maybe_type_info.value(), context); - } else { - error_handling::HandleTypecheckError("Type not found", node->base); + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("No AnyType found (alias types, ... not implemented)", + "TypeCheckVisitor.TypeExpression", + &node->base); } - // } + + VisitDefinedType(maybe_type_info.value(), context); + } else { + error_handling::HandleTypecheckError("Type not found", node->base); + } if (node->array_size.has_value()) { current_type_ = context_manager_.AddValue( @@ -1317,6 +1304,12 @@ void TypeCheckVisitor::Visit(TypeExpression* node) { utils::ValueType::Tmp); } + if (node->is_optional) { + current_type_ = context_manager_.AddValue( + info::type::OptionalType(current_type_, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + } + node->base.type_ = current_type_; } @@ -1433,7 +1426,10 @@ void TypeCheckVisitor::CollectTypeExpressionContext(const TypeExpression& type_e utils::IdType TypeCheckVisitor::TypeInContext(utils::IdType type, const std::unordered_map& context) { info::type::Type type_in_context = *context_manager_.GetAnyValue(type); - type_in_context.InContext(context); + auto maybe_new_type = type_in_context.InContext(context); + if (maybe_new_type.has_value()) { + return maybe_new_type.value(); + } return context_manager_.AddValue(std::move(type_in_context), utils::ValueType::Tmp); } diff --git a/src/typed_print_visitor.cpp b/src/typed_print_visitor.cpp index c92bc83..0a7204e 100644 --- a/src/typed_print_visitor.cpp +++ b/src/typed_print_visitor.cpp @@ -920,9 +920,13 @@ void TypedPrintVisitor::Visit(TypeExpression* node) { out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); } - out_ << ") "; + out_ << ")"; if (node->array_size.has_value()) { - out_ << "[array size: " << node->array_size.value() << ']'; + out_ << " [array size: " << node->array_size.value() << ']'; + } + + if (node->is_optional) { + out_ << " [optional]"; } out_ << "] ("; diff --git a/tests/classes.lang b/tests/classes.lang index bb8e32c..f3487b1 100644 --- a/tests/classes.lang +++ b/tests/classes.lang @@ -17,7 +17,7 @@ struct (Complex : #Value) = struct Task = & name : String - & duration : Float + & duration : Float! class Employee = & name : String diff --git a/tests/test_code.lang b/tests/test_code.lang index 191d028..01a3951 100644 --- a/tests/test_code.lang +++ b/tests/test_code.lang @@ -149,7 +149,7 @@ typeclass Show = & var show : -> String typeclass Read = - & var read : String -> Read + & read : String -> Read typeclass (Str : #Show #Read) @@ -179,9 +179,11 @@ typeclass Enum = // -decl print : String -> Unit -decl scan : -> String -decl random : -> Int // TODO +namespace IO { + decl print : String -> Unit + decl scan : -> String + decl random : -> Int // TODO +} // @@ -211,19 +213,46 @@ def ( -- ) : begin end = { }) } -decl func : String -> Int -> Int -def func : s i = { - ; print: s - var x = s - ; print: (i.show:) - return 5 -} +// decl func : String -> Int -> Int +// def func : s i = { +// ; print: s +// var x = s +// ; print: (i.show:) +// return 5 +// } +// +// exec main { +// for i in 0--19 do func: "a" (i * 2 +. 3) +// ; print: ({ +// if true then bring scan: else { ; print: "aaa" } +// bring "nothing" +// ; print: "aaa" +// }) +// } + +decl scan_int : -> Int +def scan_int = Int.read: (IO.scan:) + +decl print_int : Int -> Unit +def print_int : x = IO.print: (x.show:) + +decl scan_anything ('A : #Read) : -> 'A +def scan_anything = 'A.read: (IO.scan:) + +decl print_anything ('A : #Show) : 'A -> Unit +def print_anything : x = IO.print: (x.show:) + +/* +struct Array 'A = & data : 'A_0 + +namespace Array { + decl construct : 'A_0 -> Array + def construct: x = $(Array 'A) & data = x +} // TODO: construct decl + default def -> segfault +*/ exec main { - for i in 0--19 do func: "a" (i * 2 +. 3) - ; print: ({ - if true then bring scan: else { ; print: "aaa" } - bring "nothing" - ; print: "aaa" - }) + var n = scan_anything Int: + var a = for _ in 0--n do scan_int: + ; print_anything Int: n }