diff --git a/include/execute_visitor.hpp b/include/execute_visitor.hpp index d621965..89e0dfb 100644 --- a/include/execute_visitor.hpp +++ b/include/execute_visitor.hpp @@ -140,6 +140,7 @@ private: void Visit(BoolLiteral* node) override; bool HandleCondition(Expression& condition, const BaseNode& base_node); + void CollectTypeContext(const ParametrizedType& type); template T* ExtractValue(utils::IdType value, const BaseNode& base_node) { @@ -167,6 +168,7 @@ private: utils::IdType current_value_; std::optional active_loop_control_expression_; std::optional return_value_; // TODO: work outside block ?? + std::optional is_const_definition_; }; } // namespace interpreter diff --git a/include/interpreter_tree.hpp b/include/interpreter_tree.hpp index 7cf3dbd..8deef00 100644 --- a/include/interpreter_tree.hpp +++ b/include/interpreter_tree.hpp @@ -501,6 +501,7 @@ struct BinaryOperatorExpression { SubExpression right_expression; utils::IdType function_id_; + bool is_method_ = false; }; struct UnaryOperatorExpression { diff --git a/include/utils.hpp b/include/utils.hpp index 098258a..34155f9 100644 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -2,6 +2,7 @@ #include #include +#include #include namespace utils { @@ -10,6 +11,8 @@ using std::size_t; using IdType = size_t; +const std::string ClassInternalVarName = "self"; + enum class ReferenceModifier { Reference = 0, UniqueReference = 1 }; enum class IsConstModifier { Const = 0, Var = 1 }; enum class ClassModifier { Struct = 0, Class = 1 }; diff --git a/include/values.hpp b/include/values.hpp index f72297f..f62ab88 100644 --- a/include/values.hpp +++ b/include/values.hpp @@ -48,11 +48,11 @@ public: struct VariantValue { public: VariantValue() = default; - VariantValue(TupleValue value) // TODO: add type & constructor?? + VariantValue(utils::IdType value) // TupleValue ?? // TODO: add type & constructor?? : value(value) {} public: - TupleValue value; + utils::IdType value; }; struct ReferenceToValue { diff --git a/src/.type_check_visitor.cpp.kate-swp b/src/.type_check_visitor.cpp.kate-swp new file mode 100644 index 0000000..b7cba33 Binary files /dev/null and b/src/.type_check_visitor.cpp.kate-swp differ diff --git a/src/execute_visitor.cpp b/src/execute_visitor.cpp index 985d92e..08f8809 100644 --- a/src/execute_visitor.cpp +++ b/src/execute_visitor.cpp @@ -35,8 +35,11 @@ void ExecuteVisitor::Visit(ImportStatement* node) {} // no value void ExecuteVisitor::Visit(AliasDefinitionStatement* node) {} // no value void ExecuteVisitor::Visit(VariableDefinitionStatement* node) { // visited on function call - Visitor::Visit(node->name); Visitor::Visit(node->value); + + is_const_definition_ = node->modifier; + Visitor::Visit(node->name); // current_type_ passed from value + is_const_definition_ = std::nullopt; } void ExecuteVisitor::Visit(FunctionDeclaration* node) {} // no value @@ -57,6 +60,7 @@ void ExecuteVisitor::Visit(PartitionStatement* node) { // Flow control ----------------- +// TODO void ExecuteVisitor::Visit(TypeConstructorPatternParameter* node) { if (node->name.has_value()) { // Visit(&node->name.value()); @@ -73,6 +77,7 @@ void ExecuteVisitor::Visit(TypeConstructorPattern* node) { } } +// TODO void ExecuteVisitor::Visit(MatchCase* node) { Visitor::Visit(node->value); if (node->condition.has_value()) { @@ -83,6 +88,7 @@ void ExecuteVisitor::Visit(MatchCase* node) { } } +// TODO void ExecuteVisitor::Visit(Match* node) { Visitor::Visit(node->value); for (auto& match_case : node->matches) { @@ -156,7 +162,7 @@ void ExecuteVisitor::Visit(WhileLoop* node) { void ExecuteVisitor::Visit(ForLoop* node) { std::vector result; - // TODO: extend on different interval types (not only array) + // TODO: extend to different interval types (not only array) Visitor::Visit(node->interval); info::value::ArrayValue* interval = ExtractValue(current_value_, node->base); @@ -206,7 +212,6 @@ void ExecuteVisitor::Visit(LoopLoop* node) { // Statements, expressions, blocks, etc. ----------------- void ExecuteVisitor::Visit(Block* node) { - // type_info_context_manager_.EnterContext(); // not needed ?? context_manager_.EnterContext(); for (auto& statement : node->statements) { @@ -217,8 +222,7 @@ void ExecuteVisitor::Visit(Block* node) { return; } } - // context_manager_.ExitContext(); - // type_info_context_manager_.ExitContext(); // not needed ?? + context_manager_.ExitContext(); current_value_ = context_manager_.AddValue( info::value::InternalValue(info::value::Unit()), @@ -226,7 +230,7 @@ void ExecuteVisitor::Visit(Block* node) { } void ExecuteVisitor::Visit(ScopedStatement* node) { - Visitor::Visit(node->statement); + Visitor::Visit(node->statement); // current_value_ passed from statement } void ExecuteVisitor::Visit(LoopControlExpression& node) { @@ -239,18 +243,55 @@ void ExecuteVisitor::Visit(LoopControlExpression& node) { // Operators void ExecuteVisitor::Visit(BinaryOperatorExpression* node) { - Visitor::Visit(node->left_expression); - Visitor::Visit(&node->operator_name); - Visitor::Visit(node->right_expression); + context_manager_.EnterContext(); + + auto maybe_function_definition = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_).definition; + + if (maybe_function_definition.has_value()) { + Visitor::Visit(node->left_expression); + // TODO: custom argument value types, references, etc. + current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); + context_manager_.DefineVariable( + node->is_method_ ? utils::ClassInternalVarName : maybe_function_definition.value().argument_names[0], + current_value_); + + Visitor::Visit(node->left_expression); + // TODO: custom argument value types, references, etc. + current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); + context_manager_.DefineVariable(maybe_function_definition.value().argument_names[node->is_method_ ? 0 : 1], current_value_); + + Visit(maybe_function_definition.value().node); + } else { + // TODO: builtin operators, etc. (imports?) + error_handling::HandleRuntimeError("Binary operator definition not found", node->base); + } + + context_manager_.ExitContext(); } +// TODO: methods?? void ExecuteVisitor::Visit(UnaryOperatorExpression* node) { - // Visit(&node->operator_name); - Visitor::Visit(node->expression); + context_manager_.EnterContext(); + + auto maybe_function_definition = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_).definition; + + if (maybe_function_definition.has_value()) { + Visitor::Visit(node->expression); + // TODO: custom argument value types, references, etc. + current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); + context_manager_.DefineVariable(maybe_function_definition.value().argument_names[0], current_value_); + + Visit(maybe_function_definition.value().node); + } else { + // TODO: builtin operators, etc. (imports?) + error_handling::HandleRuntimeError("Unary operator definition not found", node->base); + } + + context_manager_.ExitContext(); } void ExecuteVisitor::Visit(ReferenceExpression* node) { - // TODO: check, that therie is no references to "Tmp" + // TODO: check, that there is no references to "Tmp"?? Visit(node->expression.get()); utils::ValueType value_type = context_manager_.GetValueType(current_value_); @@ -279,25 +320,51 @@ void ExecuteVisitor::Visit(AccessExpression* node) { // Other Expressions void ExecuteVisitor::Visit(FunctionCallExpression* node) { + context_manager_.EnterContext(); if (node->prefix.has_value()) { if (std::holds_alternative>(node->prefix.value())) { Visitor::Visit(*std::get>(node->prefix.value())); + // modify value on const methods, etc. ?? + context_manager_.DefineVariable(utils::ClassInternalVarName, current_value_); } else if (std::holds_alternative>(node->prefix.value())) { - Visit(std::get>(node->prefix.value()).get()); + TypeExpression& prefix = *std::get>(node->prefix.value()); + + // TODO: abstract types, local abstract types, abstract types, ... as path entities + for (auto& path_type : prefix.path) { + CollectTypeContext(path_type); + } + + CollectTypeContext(prefix.type); } else { // error } } - // Visit(&node->name); + auto function_declaration = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_).declaration.value(); // checked in type_check_visitor - for (auto& parameter : node->parameters) { - Visit(parameter.get()); + for (size_t i = 0; i < node->parameters.size(); ++i) { + // TODO: local bastract types, absract types, etc. + + context_manager_.DefineLocalType(function_declaration.parameters[i].type, node->parameters[i]->type_id_.value()); // TODO: check } - for (auto& argument : node->arguments) { - Visitor::Visit(argument); + auto maybe_function_definition = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_).definition; + + if (maybe_function_definition.has_value()) { + for (size_t i = 0; i < node->arguments.size(); ++i) { + Visitor::Visit(node->arguments[i]); + // TODO: custom argument value types, references, etc. + current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); + context_manager_.DefineVariable(maybe_function_definition.value().argument_names[i], current_value_); + } + + Visit(maybe_function_definition.value().node); + } else { + // TODO: builtin functions, etc. (imports?) + error_handling::HandleRuntimeError("Function definition not found", node->base); } + + context_manager_.ExitContext(); } void ExecuteVisitor::Visit(TupleExpression* node) { @@ -313,16 +380,26 @@ void ExecuteVisitor::Visit(TupleExpression* node) { utils::ValueType::Tmp); } -// TODO -void ExecuteVisitor::Visit(VariantExpression* node) { // ?? +void ExecuteVisitor::Visit(VariantExpression* node) { + // TODO: decide about return type (variant) for (auto& expression : node->expressions) { Visitor::Visit(expression); info::value::OptionalValue* expression_value = ExtractValue(current_value_, node->base); if (expression_value->value.has_value()) { + current_value_ = context_manager_.AddValue( + info::value::VariantValue(expression_value->value.value()), + utils::ValueType::Tmp); - break; + current_value_ = context_manager_.AddValue( + info::value::OptionalValue(current_value_), + utils::ValueType::Tmp); + return; } } + + current_value_ = context_manager_.AddValue( + info::value::OptionalValue(), + utils::ValueType::Tmp); } void ExecuteVisitor::Visit(ReturnExpression* node) { @@ -330,6 +407,7 @@ void ExecuteVisitor::Visit(ReturnExpression* node) { return_value_ = current_value_; } +// TODO void ExecuteVisitor::Visit(TypeConstructorParameter* node) { if (node->name.has_value()) { // Visit(&node->name.value()); @@ -368,28 +446,105 @@ void ExecuteVisitor::Visit(ArrayExpression* node) { // Name -void ExecuteVisitor::Visit(NameExpression* node) { - for (auto& name : node->names) { - // Visit(&name); +void ExecuteVisitor::Visit(NameExpression* node) { // TODO + if (node->names.empty()) { + error_handling::HandleInternalError("Names array is empty", "ExecuteVisitor.NameExpression"); + } + + std::optional maybe_variable_value = + context_manager_.GetVariableInfo(node->names[0].name); + + if (!maybe_variable_value.has_value()) { + error_handling::HandleRuntimeError("Variable not found", node->base); + } + + current_value_ = maybe_variable_value.value(); + + if (node->names.size() > 1) { + utils::ValueType variable_value_type = context_manager_.GetValueType(current_value_); + + for (size_t i = 1; i < node->names.size(); ++i) { + std::optional maybe_field_value = context_manager_.GetAnyValue(current_value_)->GetFieldValue(node->names[i].name); // TODO + if (!maybe_field_value.has_value()) { + error_handling::HandleRuntimeError("Variable field not found", node->names[i].base); + } + + current_value_ = maybe_field_value.value(); + } + + current_value_ = context_manager_.ToModifiedValue(current_value_, variable_value_type); } } -void ExecuteVisitor::Visit(TupleName* node) { - for (auto& name : node->names) { - Visitor::Visit(name); +void ExecuteVisitor::Visit(TupleName* node) { // TODO: check + utils::IdType value = current_value_; + + std::optional maybe_tuple_value = context_manager_.GetValue(value); + + if (maybe_tuple_value.has_value()) { + error_handling::HandleRuntimeError("Mismatched value types in tuple variable definition", node->base); } + + if (maybe_tuple_value.value()->fields.size() != node->names.size()) { + error_handling::HandleRuntimeError("Mismatched field count in tuple variable definition", node->base); + } + + if (!is_const_definition_.has_value()) { + error_handling::HandleInternalError("No value in is_const_definition_", "TypeCheckVisitor.TupleName"); + } + + utils::ValueType value_type = context_manager_.GetValueType(value); + if (value_type == utils::ValueType::Const + && is_const_definition_.value() == utils::IsConstModifier::Var) { + error_handling::HandleRuntimeError("TupleName: value type expression not match variable definition modifier", node->base); + } + + for (size_t i = 0; i < node->names.size(); ++i) { + current_value_ = maybe_tuple_value.value()->fields[i].second; + + if (value_type == utils::ValueType::Tmp) { // TODO: ?? + current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Tmp); + } + + Visitor::Visit(node->names[i]); + } + + current_value_ = value; } +// TODO void ExecuteVisitor::Visit(VariantName* node) { - for (auto& name : node->names) { - Visitor::Visit(name); + utils::IdType value = current_value_; + + std::optional maybe_variant_value = context_manager_.GetValue(value); + + if (!maybe_variant_value.has_value()) { + error_handling::HandleRuntimeError("Mismatched value types in variant variable definition", node->base); } + + // TODO: find out, which constructor used + // set value to that constructor and None (empty OptionalValue) to others + + current_value_ = value; } -void ExecuteVisitor::Visit(AnnotatedName* node) { - // Visit(&node->name); - if (node->type.has_value()) { - Visitor::Visit(node->type.value()); +void ExecuteVisitor::Visit(AnnotatedName* node) { // TODO: check + utils::IdType value = current_value_; + + if (!is_const_definition_.has_value()) { + error_handling::HandleInternalError("No value in is_const_definition_", + "TypeCheckVisitor.AnnotatedName"); + } + + utils::ValueType value_type = context_manager_.GetValueType(current_value_); + if (value_type == utils::ValueType::Const + && is_const_definition_.value() == utils::IsConstModifier::Var) { + error_handling::HandleRuntimeError("AnnotatedName: value type expression not match variable definition modifier", node->base); + } + + current_value_ = context_manager_.ToModifiedValue(value, utils::IsConstModifierToValueType(is_const_definition_.value())); + if (!context_manager_.DefineVariable(node->name, current_value_)) { + error_handling::HandleRuntimeError("Variable name already present in context", node->base); } } @@ -460,5 +615,26 @@ bool ExecuteVisitor::HandleCondition(Expression& node, const BaseNode& base_node return *ExtractInternalValue(current_value_, base_node); } +// TODO: handle abstract types, handle local abstract types, etc. +void ExecuteVisitor::CollectTypeContext(const ParametrizedType& type) { + if (!type.type_id_.has_value()) { + return; + } + + auto maybe_type_info = namespace_visitor_.GetGlobalInfo()->GetTypeInfo(type.type_id_.value()); + + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("CollectTypeContext unimplemented anything except AnyType", "ExecuteVisitor.CollectTYpeContext"); + } + + info::definition::AnyType& type_info = *maybe_type_info.value(); // check, that has value ?? + + for (size_t i = 0; i < type.parameters.size(); ++i) { + if (type.parameters[i]->type_id_.has_value()) { + context_manager_.DefineLocalType(type_info.parameters[i].type, + type.parameters[i]->type_id_.value()); + } +} + } // namespace interpreter diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 8ffab68..1a8ec88 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -41,14 +41,14 @@ void TypeCheckVisitor::Visit(Namespace* node) { // TODO: two var namespces for c info::type::AbstractType(utils::AbstractTypeModifier::Abstract, node->type, requirements), IsConstModifierToValueType(node->modifier.value())); - context_manager_.EnterVariableContext("self", // TODO: different name ?? + context_manager_.EnterVariableContext(utils::ClassInternalVarName, abstract_type); context_manager_.DefineLocalType(node->type, abstract_type); } else if (node->link_type_id_.has_value()) { Visitor::Visit(*namespace_visitor_.GetGlobalInfo()->GetTypeInfo(node->link_type_id_.value()).value()->value); // handle error? context_manager_.EnterVariableContext( - "self", // TODO: different name + utils::ClassInternalVarName, // TODO: different name context_manager_.AddValue( info::type::DefinedType(node->link_type_id_.value(), current_type_, context_manager_.GetValueManager()), IsConstModifierToValueType(node->modifier.value()))); @@ -574,11 +574,11 @@ void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) { auto maybe_operator_id = namespace_visitor_.FindFunction(std::nullopt, node->operator_name); const info::definition::Function* operator_info = nullptr; - bool is_method = false; + node->is_method_ = false; if (maybe_operator_id.has_value()) { operator_info = &namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value()); - is_method = false; + node->is_method_ = false; } else { Visitor::Visit(node->left_expression); auto maybe_left_type = context_manager_.GetValue(current_type_); @@ -618,7 +618,7 @@ void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) { } operator_info = &namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value()); - is_method = true; + node->is_method_ = true; } if (!operator_info->declaration.has_value()) { @@ -629,7 +629,7 @@ void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) { error_handling::HandleTypecheckError("Operator definition not found", node->base); } - if (operator_info->argument_count != (is_method ? 2 : 3)) { // 2 + return type + if (operator_info->argument_count != (node->is_method_ ? 2 : 3)) { // 2 + return type error_handling::HandleTypecheckError("Operator wrong argument count", node->base); } @@ -637,10 +637,10 @@ void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) { error_handling::HandleTypecheckError("Operator with parameters", node->base); } - if (!is_method) { + if (!node->is_method_) { Visitor::Visit(*operator_info->declaration.value().argument_types[0]); - utils::IdType left_expression_type = current_type_; // TODO: type in context of deduced types + utils::IdType left_expression_type = current_type_; Visitor::Visit(node->left_expression); if (!context_manager_.AddValueRequirement(current_type_, left_expression_type)) { @@ -649,8 +649,8 @@ void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) { } - Visitor::Visit(*operator_info->declaration.value().argument_types[is_method ? 0 : 1]); - utils::IdType right_expression_type = current_type_; // TODO: type in context of deduced types + Visitor::Visit(*operator_info->declaration.value().argument_types[node->is_method_ ? 0 : 1]); + utils::IdType right_expression_type = current_type_; Visitor::Visit(node->right_expression); if (!context_manager_.AddValueRequirement(current_type_, right_expression_type)) { @@ -692,7 +692,7 @@ void TypeCheckVisitor::Visit(UnaryOperatorExpression* node) { } Visitor::Visit(*operator_info.declaration.value().argument_types[0]); - utils::IdType expression_type = current_type_; // TODO: type in context of deduced types + utils::IdType expression_type = current_type_; Visitor::Visit(node->expression); if (!context_manager_.AddValueRequirement(current_type_, expression_type)) { @@ -793,15 +793,19 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { maybe_function_id = maybe_const_function_id; } } else if (std::holds_alternative>(node->prefix.value())) { - TypeExpression* type_expression = std::get>(node->prefix.value()).get(); + TypeExpression& type_expression = *std::get>(node->prefix.value()); + + if (type_expression.array_size.has_value()) { + error_handling::HandleTypecheckError("Can't call function from array type namespace", node->base); + } std::vector path; - path.reserve(type_expression->path.size() + 1); + path.reserve(type_expression.path.size() + 1); - for (auto& path_type : type_expression->path) { + for (auto& path_type : type_expression.path) { path.push_back(path_type.type); } - path.push_back(type_expression->type.type); + path.push_back(type_expression.type.type); maybe_function_id = namespace_visitor_.FindFunction(path, node->name.name); @@ -814,7 +818,7 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { } if (!maybe_function_id.has_value()) { - error_handling::HandleTypecheckError("Can't find function", node->base); // InterlnalError ?? + error_handling::HandleTypecheckError("Can't find function", node->base); // InternalError ?? } std::optional maybe_function_declaration = @@ -1038,23 +1042,21 @@ void TypeCheckVisitor::Visit(NameExpression* node) { current_type_ = maybe_variable_type.value(); - if (node->names.size() == 1) { - return; - } + if (node->names.size() > 1) { + utils::ValueType variable_value_type = context_manager_.GetValueType(current_type_); - utils::ValueType variable_value_type = context_manager_.GetValueType(current_type_); + for (size_t i = 1; i < node->names.size(); ++i) { + std::optional maybe_type_value = context_manager_.GetAnyValue(current_type_)->GetFieldType(node->names[i].name); + if (!maybe_type_value.has_value()) { + error_handling::HandleTypecheckError("Variable field not found", node->names[i].base); + } - for (size_t i = 1; i < node->names.size(); ++i) { - std::optional maybe_type_value = context_manager_.GetAnyValue(current_type_)->GetFieldType(node->names[i].name); - if (!maybe_type_value.has_value()) { - error_handling::HandleTypecheckError("Variable field not found", node->names[i].base); + current_type_ = maybe_type_value.value(); } - current_type_ = maybe_type_value.value(); + current_type_ = context_manager_.ToModifiedValue(current_type_, variable_value_type); } - current_type_ = context_manager_.ToModifiedValue(current_type_, variable_value_type); - node->base.type_ = current_type_; } @@ -1083,7 +1085,7 @@ void TypeCheckVisitor::Visit(TupleName* node) { utils::ValueType value_type = context_manager_.GetValueType(type); if (value_type == utils::ValueType::Const && is_const_definition_.value() == utils::IsConstModifier::Var) { - error_handling::HandleTypecheckError("TupleName: value type expression not match from variable definition modifier", node->base); + error_handling::HandleTypecheckError("TupleName: value type expression not match variable definition modifier", node->base); } for (size_t i = 0; i < node->names.size(); ++i) { @@ -1126,7 +1128,7 @@ void TypeCheckVisitor::Visit(VariantName* node) { utils::ValueType value_type = context_manager_.GetValueType(type); if (value_type == utils::ValueType::Const && is_const_definition_.value() == utils::IsConstModifier::Var) { - error_handling::HandleTypecheckError("VariantName: value type of type and value type are diifferent", node->base); + error_handling::HandleTypecheckError("VariantName: value type of type and value type are different", node->base); } for (size_t i = 0; i < node->names.size(); ++i) { @@ -1163,7 +1165,7 @@ void TypeCheckVisitor::Visit(AnnotatedName* node) { utils::ValueType value_type = context_manager_.GetValueType(type); if (value_type == utils::ValueType::Const && is_const_definition_.value() == utils::IsConstModifier::Var) { - error_handling::HandleTypecheckError("TupleName: value type expression not match from variable definition modifier", node->base); + error_handling::HandleTypecheckError("TupleName: value type expression not match variable definition modifier", node->base); } type = context_manager_.ToModifiedValue(type, utils::IsConstModifierToValueType(is_const_definition_.value()));