diff --git a/src/print_visitor.cpp b/src/print_visitor.cpp index 7b6da0e..c3d73e1 100644 --- a/src/print_visitor.cpp +++ b/src/print_visitor.cpp @@ -53,10 +53,10 @@ void PrintVisitor::Visit(Namespace* node) { out_ << "[Namespace] "; if (node->modifier.has_value()) { switch (node->modifier.value()) { - case Namespace::Const: + case utils::IsConstModifier::Const: out_ << "const "; break; - case Namespace::Var: + case utils::IsConstModifier::Var: out_ << "var "; break; } @@ -88,13 +88,13 @@ void PrintVisitor::Visit(ImportStatement* node) { void PrintVisitor::Visit(AliasDefinitionStatement* node) { out_ << "[Alias "; switch (node->modifier) { - case AliasDefinitionStatement::Alias: + case utils::AliasModifier::Alias: out_ << "alias"; break; - case AliasDefinitionStatement::Type: + case utils::AliasModifier::Type: out_ << "type"; break; - case AliasDefinitionStatement::Let: + case utils::AliasModifier::Let: out_ << "let"; break; } @@ -108,10 +108,10 @@ void PrintVisitor::Visit(AliasDefinitionStatement* node) { void PrintVisitor::Visit(VariableDefinitionStatement* node) { out_ << "[Variable "; switch (node->modifier) { - case VariableDefinitionStatement::Const: + case utils::IsConstModifier::Const: out_ << "const"; break; - case VariableDefinitionStatement::Var: + case utils::IsConstModifier::Var: out_ << "var"; break; } @@ -145,10 +145,10 @@ void PrintVisitor::Visit(FunctionDefinitionStatement* node) { void PrintVisitor::Visit(TypeDefinitionStatement* node) { out_ << "[Type "; switch (node->modifier) { - case TypeDefinitionStatement::Struct: + case utils::ClassModifier::Struct: out_ << "struct"; break; - case TypeDefinitionStatement::Class: + case utils::ClassModifier::Class: out_ << "class"; break; } @@ -162,10 +162,10 @@ void PrintVisitor::Visit(TypeDefinitionStatement* node) { void PrintVisitor::Visit(AbstractTypeDefinitionStatement* node) { out_ << "[AbstractType "; switch (node->modifier) { - case AbstractTypeDefinitionStatement::Basic: + case utils::AbstractTypeModifier::Basic: out_ << "basic"; break; - case AbstractTypeDefinitionStatement::Abstract: + case utils::AbstractTypeModifier::Abstract: out_ << "abstract"; break; } @@ -193,10 +193,10 @@ void PrintVisitor::Visit(TypeclassDefinitionStatement* node) { void PrintVisitor::Visit(FunctionDefinition* node) { out_ << "[FunctionDefinition "; switch (node->modifier) { - case FunctionDefinition::Operator: + case utils::FunctionTypeModifier::Operator: out_ << "operator"; break; - case FunctionDefinition::Function: + case utils::FunctionTypeModifier::Function: out_ << "function"; break; } @@ -397,10 +397,10 @@ void PrintVisitor::Visit(ReferenceExpression* node) { out_ << "[ReferenceExpression "; for (auto& reference : node->references) { switch (reference) { - case utils::ReferenceType::Reference: + case utils::ReferenceModifier::Reference: out_ << '~'; break; - case utils::ReferenceType::UniqueReference: + case utils::ReferenceModifier::UniqueReference: out_ << '@'; break; } @@ -481,10 +481,10 @@ void PrintVisitor::Visit(TypeConstructorParameter* node) { if (node->name.has_value()) { Visit(&node->name.value()); switch (node->asignment_modifier.value()) { - case TypeConstructorParameter::Assign: + case utils::AssignmentModifier::Assign: out_ << " = "; break; - case TypeConstructorParameter::Move: + case utils::AssignmentModifier::Move: out_ << " <- "; break; } @@ -650,10 +650,10 @@ void PrintVisitor::Visit(ExtendedScopedAnyType* node) { out_ << "[ExtendedScopedAnyType "; for (auto& reference : node->references) { switch (reference) { - case utils::ReferenceType::Reference: + case utils::ReferenceModifier::Reference: out_ << '~'; break; - case utils::ReferenceType::UniqueReference: + case utils::ReferenceModifier::UniqueReference: out_ << '@'; break; } diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index bead6c2..f74da56 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -235,13 +235,7 @@ void TypeCheckVisitor::Visit(AnyAnnotatedType* node) { // TODO <----- | current position | // TODO -void Visitor::Visit(TypeConstructorPatternParameter* node) { - if (node->name.has_value()) { - Visit(&node->name.value()); - } - node-> - Visit(node->value); -} +void Visitor::Visit(TypeConstructorPatternParameter* node) {} // Handled in TypeConstructorPattern // TODO void Visitor::Visit(TypeConstructorPattern* node) { @@ -251,10 +245,99 @@ void Visitor::Visit(TypeConstructorPattern* node) { } } +/* +void TypeCheckVisitor::Visit(TypeConstructor* node) { + if (!node->constructor->constructor_id_.has_value()) { + error_handling::HandleTypecheckError("Type constructor name not found", node->base); + } + + if (!node->constructor->type_id_.has_value()) { + error_handling::HandleInternalError("Type constructor without type", "TypeCheckVisitor.TypeConstructor"); + } + + utils::IdType constructor_id = node->constructor->constructor_id_.value(); + + info::definition::Constructor constructor_info = namespace_visitor_.GetGlobalInfo()->GetConstructorInfo(constructor_id); + + utils::IdType type_id = constructor_info.type_id; + + std::unordered_map context; + CollectTypeExpressionContext(*node->constructor, context); + + // TODO: handle alias types + const std::optional& maybe_type_info = + namespace_visitor_.GetGlobalInfo()->GetTypeInfo(type_id); + + if (!maybe_type_info.has_value()) { // TODO + error_handling::HandleInternalError("Implemented only for AnyType", "TypeCheckVisitor.LambdaFunction"); + } + + const info::definition::AnyType& type_info = maybe_type_info.value(); + + if (constructor_info.constructor_tuple_node.has_value()) { + + TupleType* constructor_fields = constructor_info.constructor_tuple_node.value(); + + if (constructor_fields->entities.size() != node->parameters.size()) { + error_handling::HandleTypecheckError("Type constructor parameters count mismatch", node->base); + } + + for (size_t i = 0; i < node->parameters.size(); ++i) { + // TODO: remove variable on move + if (node->parameters[i].name.has_value()) { + if (!constructor_fields->entities[i].first.has_value() + || constructor_fields->entities[i].first.value().name != node->parameters[i].name.value().name) { + error_handling::HandleTypecheckError("Type constructor: name of parameter and name in constructor don't match each other", node->base); + } + } else { + if (constructor_fields->entities[i].first.has_value()) { + error_handling::HandleTypecheckError("Type constructor: unnamed pprameter corresponds named field", node->base); + } + } + + Visitor::Visit(constructor_fields->entities[i].second.get()); + utils::IdType parameter_type = TypeInContext(current_type_, context); + + Visitor::Visit(node->parameters[i].value); + + context_manager_.EqualTypes(TypeInContext(parameter_type, context), current_type_); + } + + } else { + if (node->parameters.size() > 0) { + error_handling::HandleTypecheckError("Parameters for untyped type constructor", node->base); + } + } + + Visitor::Visit(*type_info.value); + current_type_ = TypeInContext(current_type_, context); +} +*/ + void TypeCheckVisitor::Visit(MatchCase* node) { // value type passed as current_type_ is_const_definition_ = true; // TODO: or var?? Visitor::Visit(node->value); + + switch (node->value.index()) { + case 0: + context_manager_.DefineVariable(std::get<0>(node->value)->name, + current_type_, + is_const_definition_.value()); + break; + case 1: + + Visitor::Visit(*std::get<1>(node->value).get()); + + break; + case 2: + Visit(std::get>(node->value).get()); + break; + default: + // error + break; + } + is_const_definition_ = std::nullopt; if (node->condition.has_value()) { @@ -270,7 +353,7 @@ void TypeCheckVisitor::Visit(MatchCase* node) { // current_type_ from statement is current_type_ for MatchCase } -void TypeCheckVisitor::Visit(Match* node) { // TODO return variant type ?? (problems with same types) +void TypeCheckVisitor::Visit(Match* node) { // TODO: types can be different in block statement utils::IdType type; @@ -304,7 +387,7 @@ void TypeCheckVisitor::Visit(Match* node) { // TODO return variant type ?? (prob current_type_ = type; } -void TypeCheckVisitor::Visit(Condition* node) { // TODO return variant type ?? (problem with same types) +void TypeCheckVisitor::Visit(Condition* node) { // TODO: types can be different in statement utils::IdType type; @@ -369,7 +452,7 @@ void TypeCheckVisitor::Visit(ForLoop* node) { } current_type_ = context_manager_.AddType(maybe_interval_type.value()->GetElementsType()); - Visitor::Visit(node->variable); // type passed to variable definition + Visitor::Visit(node->variable); // type passed to variable definition throught current_type_ Visitor::Visit(node->statement); @@ -386,18 +469,19 @@ void TypeCheckVisitor::Visit(LoopLoop* node) { // Statements, expressions, blocks, etc. ----------------- -void TypeCheckVisitor::Visit(Block* node) { // TODO return variant type ?? (problem with same types) +void TypeCheckVisitor::Visit(Block* node) { + // TODO: types can be different in statement utils::IdType type; - bool is_first_returned_type = true; + bool is_type_found = false; for (auto& statement : node->statements) { returned_type_ = std::nullopt; Visitor::Visit(statement); if (returned_type_.has_value()) { - if (is_first_returned_type) { + if (!is_type_found) { type = returned_type_.value(); - is_first_returned_type = false; + is_type_found = true; } else { if (!context_manager_.EqualTypes(type, returned_type_.value())) { error_handling::HandleTypecheckError("Different return types in block", node->base); @@ -406,7 +490,7 @@ void TypeCheckVisitor::Visit(Block* node) { // TODO return variant type ?? (prob } } - if (is_first_returned_type) { + if (!is_type_found) { type = context_manager_.AddType(info::type::InternalType::Unit); } @@ -424,9 +508,8 @@ void TypeCheckVisitor::Visit(LoopControlExpression& node) { // enum // Operators -// TODO -// TODO: operator parameters (deduction?), etc. void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) { + // TODO: Check, that type is not abstract ?? auto maybe_operator_id = namespace_visitor_.FindFunction(std::nullopt, node->operator_name); if (!maybe_operator_id.has_value()) { @@ -439,7 +522,7 @@ void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) { error_handling::HandleTypecheckError("Operator declaration not found", node->base); } - if (!operator_info.definition.has_value()) { // TODO: builtin + if (!operator_info.definition.has_value()) { // TODO: builtin, etc. error_handling::HandleTypecheckError("Operator definition not found", node->base); } @@ -452,21 +535,24 @@ void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) { } Visitor::Visit(*operator_info.declaration.value().argument_types[0]); - utils::IdType left_expression_type = current_type_; + utils::IdType left_expression_type = current_type_; // TODO: type in context of deduced types Visitor::Visit(node->left_expression); - context_manager_.AddTypeRequirement(current_type_, left_expression_type); // TODO: ConstructAnyType + if (!context_manager_.AddTypeRequirement(current_type_, left_expression_type)) { + error_handling::HandleTypecheckError("Operator left expression has wrong type", node->base); + } Visitor::Visit(*operator_info.declaration.value().argument_types[1]); - utils::IdType right_expression_type = current_type_; + utils::IdType right_expression_type = current_type_; // TODO: type in context of deduced types Visitor::Visit(node->right_expression); - context_manager_.AddTypeRequirement(current_type_, right_expression_type); // TODO: ConstructAnyType - + if (!context_manager_.AddTypeRequirement(current_type_, right_expression_type)) { + error_handling::HandleTypecheckError("Operator right expression has wrong type", node->base); + } } -// -------------------------- TODO -------------------------- void TypeCheckVisitor::Visit(UnaryOperatorExpression* node) { + // TODO: Check, that type is not abstract ?? auto maybe_operator_id = namespace_visitor_.FindFunction({}, node->operator_name); if (!maybe_operator_id.has_value()) { @@ -479,7 +565,7 @@ void TypeCheckVisitor::Visit(UnaryOperatorExpression* node) { error_handling::HandleTypecheckError("Operator declaration not found", node->base); } - if (!operator_info.definition.has_value()) { // TODO: builtin + if (!operator_info.definition.has_value()) { // TODO: builtin, etc. error_handling::HandleTypecheckError("Operator definition not found", node->base); } @@ -492,10 +578,12 @@ void TypeCheckVisitor::Visit(UnaryOperatorExpression* node) { } Visitor::Visit(*operator_info.declaration.value().argument_types[0]); - utils::IdType expression_type = current_type_; + utils::IdType expression_type = current_type_; // TODO: type in context of deduced types Visitor::Visit(node->expression); - context_manager_.AddTypeRequirement(current_type_, expression_type); // TODO: ConstructAnyType + if (!context_manager_.AddTypeRequirement(current_type_, expression_type)) { + error_handling::HandleTypecheckError("Operator expression has wrong type", node->base); + } } void TypeCheckVisitor::Visit(ReferenceExpression* node) { @@ -507,15 +595,17 @@ void TypeCheckVisitor::Visit(ReferenceExpression* node) { void TypeCheckVisitor::Visit(AccessExpression* node) { Visitor::Visit(node->id); - context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Int), current_type_); - // TODO: separate type for counting ? + if (!context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Int), current_type_)) { + error_handling::HandleTypecheckError("Access index has wrong type (not Int)", node->base); + } Visitor::Visit(node->name.get()); std::optional maybe_type_value = context_manager_.GetType(current_type_); if (!maybe_type_value.has_value()) { - error_handling::HandleTypecheckError("Access type mismatch", node->base); + error_handling::HandleTypecheckError("Access type is not array", node->base); + // TODO: redifinitions for other types and tuples (with const index) ?? } current_type_ = maybe_type_value.value()->GetElementsType(); @@ -526,6 +616,7 @@ void TypeCheckVisitor::Visit(AccessExpression* node) { // TODO // TODO: builtin functions/methods // TODO: alias types, abstract types, etc. +// TODO: deduce function parameter types void TypeCheckVisitor::Visit(FunctionCallExpression* node) { std::optional maybe_function_id; std::unordered_map context; @@ -556,8 +647,21 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { "TypeCheckVisitor.FunctionCallExpresssion"); } + + std::optional maybe_const_function_id = maybe_type_info.value().parent_namespace->const_namespaces.at(maybe_type_info->type.type).functions[node->name.name]; + // TODO: better decision ?? - maybe_function_id = maybe_type_info.value().parent_namespace->variable_namespaces.at(maybe_type_info->type.type).functions[node->name.name]; + if (/*is var expression*/) { + maybe_function_id = maybe_type_info.value().parent_namespace->var_namespaces.at(maybe_type_info->type.type).functions[node->name.name]; + } + + if (maybe_const_function_id.has_value() && maybe_function_id.has_value()) { // TODO: handle on link_types stage + error_handling::HandleTypecheckError("Redefinition of method: const & var", node->base); + } + + if (!maybe_function_id.has_value()) { + maybe_function_id = maybe_const_function_id; + } } else if (std::holds_alternative>(node->prefix.value())) { TypeExpression* type_expression = std::get>(node->prefix.value()).get(); @@ -613,9 +717,11 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { error_handling::HandleTypecheckError("Mismatched argument count in function call expression", node->base); } for (size_t i = 0; i < node->arguments.size(); ++i) { - Visitor::Visit(node->arguments[i]); Visitor::Visit(*function_declaration.argument_types[i]); - context_manager_.AddTypeRequirement(current_type_, TypeInContext(current_type_, context)); + utils::IdType argument_type = TypeInContext(current_type_, context); + + Visitor::Visit(node->arguments[i]); + context_manager_.AddTypeRequirement(current_type_, argument_type); } Visitor::Visit(*function_declaration.argument_types.back()); // add return type to info ?? @@ -634,7 +740,7 @@ void TypeCheckVisitor::Visit(TupleExpression* node) { info::type::TupleType(std::nullopt, fields, context_manager_.GetTypeManager())); } -// TODO +// ?? void TypeCheckVisitor::Visit(VariantExpression* node) { std::vector constructors; @@ -655,13 +761,9 @@ void TypeCheckVisitor::Visit(ReturnExpression* node) { returned_type_ = current_type_; } -// TODO void Visitor::Visit(TypeConstructorParameter* node) {} // Handeled in TypeConstructor visit -// TODO -// TODO: get argument types, etc. -void TypeCheckVisitor::Visit(TypeConstructor* node) { // TODO: find constructor names, etc. - // Visit(node->constructor.get()); +void TypeCheckVisitor::Visit(TypeConstructor* node) { if (!node->constructor->constructor_id_.has_value()) { error_handling::HandleTypecheckError("Type constructor name not found", node->base); } @@ -689,10 +791,6 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { // TODO: find constructor const info::definition::AnyType& type_info = maybe_type_info.value(); - // TODO: check if exist - /*info::definition::AnyType* type_info = &std::get( - namespace_visitor_.GetGlobalInfo()->GetTypeInfo(context_manager_.GetType(type).value()->GetTypeId())->type);*/ - if (constructor_info.constructor_tuple_node.has_value()) { TupleType* constructor_fields = constructor_info.constructor_tuple_node.value(); @@ -703,7 +801,6 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { // TODO: find constructor for (size_t i = 0; i < node->parameters.size(); ++i) { // TODO: remove variable on move - // TODO: check that has name <-> has name in constructor <- chck correctness if (node->parameters[i].name.has_value()) { if (!constructor_fields->entities[i].first.has_value() || constructor_fields->entities[i].first.value().name != node->parameters[i].name.value().name) { @@ -733,8 +830,7 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { // TODO: find constructor current_type_ = TypeInContext(current_type_, context); } -// TODO -void TypeCheckVisitor::Visit(LambdaFunction* node) { +void TypeCheckVisitor::Visit(LambdaFunction* node) { // TODO error_handling::HandleInternalError("Unimplemented (unsolved type deduction problems)", "TypeCheckVisitor.LambdaFunction"); } @@ -753,35 +849,32 @@ void TypeCheckVisitor::Visit(ArrayExpression* node) { } } + if (node->elements.size() == 0) { + error_handling::HandleInternalError("Element size is 0", "TypeCheckVisitor.ArrayExpression"); + } + current_type_ = context_manager_.AddType( info::type::ArrayType(node->elements.size(), elements_type, context_manager_.GetTypeManager())); } // Name -// -------------------------- TODO -------------------------- -void TypeCheckVisitor::Visit(NameExpression* node) { // TODO: ?? functions without arguments ?? - std::vector path; - std::string type_name; - - path.reserve(node->names.size()); - for (size_t i = 0; i < node->names.size(); ++i) { - std::string current_name = node->names[i].name; - if (i + 1 == node->names.size()) { - type_name = std::move(current_name); - } else { - path.push_back(std::move(current_name)); - } +// TODO +void TypeCheckVisitor::Visit(NameExpression* node) { + // TODO: move, etc. + if (node->names.size() == 0) { + error_handling::HandleInternalError("Name expression with zero names", "TypeCheckVisitor.NameExpression"); } - // auto name_type = namespace_visitor_.FindType(); - path.push_back(type_name); - auto name_namespace = namespace_visitor_.FindNamespace(path); + auto maybe_variable_info = context_manager_.GetVariableInfo(node->names[0].name); - for (size_t i = 0; i < node->names.size(); ++i) { - // Visitor::Visit(node->expressions[i]); + if (!maybe_variable_info.has_value()) { + error_handling::HandleTypecheckError("Variable not found", node->names[0].base); } + // TODO: get variable field + + return ; } void TypeCheckVisitor::Visit(TupleName* node) { @@ -864,7 +957,6 @@ void TypeCheckVisitor::Visit(AnnotatedName* node) { void TypeCheckVisitor::Visit(FunctionType* node) { std::vector argument_types(node->types.size()); - for (auto& argument_type : node->types) { Visitor::Visit(argument_type); argument_types.push_back(current_type_); @@ -913,7 +1005,6 @@ void TypeCheckVisitor::Visit(VariantType* node) { current_type_ = context_manager_.AddType(info::type::VariantType(node->type, constructors)); } -// TODO different for constructors // TODO handle local abstract types, abstract types, aliases, etc. void TypeCheckVisitor::Visit(TypeExpression* node) { std::unordered_map context; @@ -949,8 +1040,7 @@ void TypeCheckVisitor::Visit(ExtendedScopedAnyType* node) { // Typeclass -// TODO -void Visitor::Visit(ParametrizedTypeclass* node) { +void Visitor::Visit(ParametrizedTypeclass* node) { // TODO ?? Visit(&node->typeclass); for (auto& parameter : node->parameters) { Visit(parameter.get()); @@ -959,12 +1049,10 @@ void Visitor::Visit(ParametrizedTypeclass* node) { // Typeclass & Type ----------------- -void TypeCheckVisitor::Visit(ParametrizedType* node) {} // Used in TypeExpression +void TypeCheckVisitor::Visit(ParametrizedType* node) {} // Handled in TypeExpression // Identifiers, constants, etc. ----------------- -// TODO don't make dublicates of the same types - void TypeCheckVisitor::Visit(FloatNumberLiteral* node) { current_type_ = context_manager_.AddType(info::type::InternalType::Float); }