mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-05 22:48:42 +00:00
part of type_check_visitor
This commit is contained in:
parent
94ef8702fb
commit
f7e985a448
10 changed files with 377 additions and 88 deletions
31
include/builtin_methods.hpp
Normal file
31
include/builtin_methods.hpp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
// for clangd
|
||||
#include "types.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
// TODO
|
||||
|
||||
namespace info {
|
||||
|
||||
struct BuiltinFunction {
|
||||
public:
|
||||
BuiltinFunction(const std::vector<utils::IdType>& argument_types, utils::IdType return_type)
|
||||
: argument_types(argument_types), return_type(return_type) {}
|
||||
|
||||
static std::optional<BuiltinFunction> FindMethod(const std::string& name, info::type::TypeManager& type_manager) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
static std::optional<BuiltinFunction> FindStaticMethod(const std::string& name, info::type::TypeManager& type_manager) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<utils::IdType> argument_types;
|
||||
utils::IdType return_type;
|
||||
};
|
||||
|
||||
} // namespace info
|
||||
|
|
@ -17,6 +17,8 @@ namespace interpreter {
|
|||
|
||||
namespace info::definition {
|
||||
|
||||
struct Namespace;
|
||||
|
||||
struct TypeUsage {
|
||||
interpreter::tokens::TypeExpression* node;
|
||||
};
|
||||
|
|
@ -42,6 +44,8 @@ struct AnyType {
|
|||
Parameter type;
|
||||
std::vector<Parameter> parameters;
|
||||
interpreter::tokens::AnyType* value;
|
||||
|
||||
Namespace* parent_namespace = nullptr;
|
||||
};
|
||||
|
||||
struct Type {
|
||||
|
|
@ -52,6 +56,7 @@ struct Constructor {
|
|||
std::string name;
|
||||
size_t order;
|
||||
utils::IdType type_id;
|
||||
std::optional<interpreter::tokens::TupleType*> constructor_tuple_node;
|
||||
};
|
||||
|
||||
struct FunctionDeclaration {
|
||||
|
|
@ -90,7 +95,7 @@ struct Namespace {
|
|||
std::unordered_map<std::string, Namespace> namespaces;
|
||||
std::unordered_map<std::string, Namespace> variable_namespaces;
|
||||
|
||||
Namespace* parent_namespace = nullptr;;
|
||||
Namespace* parent_namespace = nullptr;
|
||||
|
||||
std::optional<Modifier> modifier; // modifier => variable namespace
|
||||
std::string type_name;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
// for clangd
|
||||
#include "definitions.hpp"
|
||||
#include "interpreter_tree.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace info {
|
||||
|
|
@ -82,6 +83,10 @@ public:
|
|||
const std::vector<std::string>& GetCurrentPath() {
|
||||
return current_path_;
|
||||
}
|
||||
|
||||
definition::Namespace* GetCurrentNamespace() {
|
||||
return namespace_stack_.back();
|
||||
}
|
||||
private:
|
||||
NamespaceVisitor(GlobalInfo& global_info) : global_info_(global_info),
|
||||
namespace_stack_({&global_info.global_namespace_}) {}
|
||||
|
|
@ -104,23 +109,31 @@ public:
|
|||
}
|
||||
|
||||
// remember about vector realloc
|
||||
definition::Function* GetFunctionInfo(utils::IdType id) {
|
||||
return &functions_[id];
|
||||
const definition::Function& GetFunctionInfo(utils::IdType id) {
|
||||
return functions_.at(id);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const std::optional<T>& GetTypeInfo(utils::IdType id) {
|
||||
if (!std::holds_alternative<T>(types_.at(id).type)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return std::get<T>(types_[id].type);
|
||||
}
|
||||
|
||||
// remember about vector realloc
|
||||
definition::Type* GetTypeInfo(utils::IdType id) {
|
||||
return &types_[id];
|
||||
const definition::Type& GetAnyTypeInfo(utils::IdType id) {
|
||||
return types_.at(id);
|
||||
}
|
||||
|
||||
// remember about vector realloc
|
||||
definition::Typeclass* GetTypeclassInfo(utils::IdType id) {
|
||||
return &typeclasses_[id];
|
||||
const definition::Typeclass& GetTypeclassInfo(utils::IdType id) {
|
||||
return typeclasses_.at(id);
|
||||
}
|
||||
|
||||
// remember about vector realloc
|
||||
definition::Constructor* GetConstructorInfo(utils::IdType id) {
|
||||
return &constructors_[id];
|
||||
const definition::Constructor& GetConstructorInfo(utils::IdType id) {
|
||||
return constructors_.at(id);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -231,7 +231,6 @@ struct ParametrizedTypeclass;
|
|||
// Typeclass & Type
|
||||
|
||||
struct ParametrizedType;
|
||||
// TypeSubExpression -> ParametrizedType
|
||||
|
||||
//
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
// for clangd
|
||||
#include "interpreter_tree.hpp"
|
||||
#include "type_info_contexts.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "visitor.hpp"
|
||||
|
|
@ -119,6 +120,17 @@ private:
|
|||
void Visit(CharLiteral* node) override;
|
||||
void Visit(UnitLiteral* node) override;
|
||||
|
||||
//
|
||||
|
||||
void CollectTypeContext(const ParametrizedType& type,
|
||||
std::unordered_map<std::string, utils::IdType>& context);
|
||||
|
||||
void CollectTypeExpressionContext(const TypeExpression& type_expression,
|
||||
std::unordered_map<std::string, utils::IdType>& context);
|
||||
|
||||
utils::IdType TypeInContext(utils::IdType type,
|
||||
const std::unordered_map<std::string, utils::IdType>& context);
|
||||
|
||||
private:
|
||||
info::GlobalInfo::NamespaceVisitor namespace_visitor_;
|
||||
info::TypeInfoContextManager& context_manager_;
|
||||
|
|
|
|||
|
|
@ -48,9 +48,14 @@ public:
|
|||
bool operator<(const DefinedType& type) const;
|
||||
bool operator>(const DefinedType& type) const;
|
||||
|
||||
utils::IdType GetTypeId() {
|
||||
utils::IdType GetTypeId() const {
|
||||
return type_id_;
|
||||
}
|
||||
|
||||
utils::IdType GetType() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
private:
|
||||
utils::IdType type_id_; // in defined types
|
||||
utils::IdType type_; // in types manager, created using context types (if specific type)
|
||||
|
|
@ -82,6 +87,7 @@ public:
|
|||
const std::vector<std::pair<std::optional<std::string>, utils::IdType>>& GetFields() const {
|
||||
return fields_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<std::string> name_;
|
||||
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields_;
|
||||
|
|
@ -103,6 +109,7 @@ public:
|
|||
const std::vector<TupleType>& GetConstructors() const {
|
||||
return constructors_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<std::string> name_;
|
||||
std::vector<TupleType> constructors_;
|
||||
|
|
@ -119,6 +126,7 @@ public:
|
|||
bool Same(const OptionalType& type) const;
|
||||
bool operator<(const OptionalType& type) const;
|
||||
bool operator>(const OptionalType& type) const;
|
||||
|
||||
private:
|
||||
utils::IdType type_;
|
||||
TypeManager* type_manager_ = nullptr;
|
||||
|
|
@ -136,6 +144,7 @@ public:
|
|||
bool Same(const ReferenceToType& type) const;
|
||||
bool operator<(const ReferenceToType& type) const;
|
||||
bool operator>(const ReferenceToType& type) const;
|
||||
|
||||
private:
|
||||
std::vector<utils::ReferenceType> references_;
|
||||
utils::IdType type_;
|
||||
|
|
@ -156,6 +165,7 @@ public:
|
|||
bool Same(const FunctionType& type) const;
|
||||
bool operator<(const FunctionType& type) const;
|
||||
bool operator>(const FunctionType& type) const;
|
||||
|
||||
private:
|
||||
std::vector<utils::IdType> argument_types_;
|
||||
utils::IdType return_type_;
|
||||
|
|
@ -178,6 +188,7 @@ public:
|
|||
utils::IdType GetElementsType() {
|
||||
return elements_type_;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t size_; // = 0 for dynamic
|
||||
utils::IdType elements_type_;
|
||||
|
|
@ -193,6 +204,7 @@ public:
|
|||
bool Same(const Type& type) const;
|
||||
bool operator<(const Type& type) const; // TODO: rule exceptions
|
||||
bool operator>(const Type& type) const;
|
||||
|
||||
private:
|
||||
std::variant<AbstractType,
|
||||
DefinedType,
|
||||
|
|
@ -216,6 +228,7 @@ public:
|
|||
|
||||
bool AddTypeRequirement(utils::IdType type, utils::IdType requrement);
|
||||
bool EqualTypes(utils::IdType first_type, utils::IdType second_type);
|
||||
|
||||
private:
|
||||
std::vector<info::type::Type> types_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) {
|
|||
}
|
||||
|
||||
any_type_info.value = &node->value;
|
||||
any_type_info.parent_namespace = namespace_visitor_.GetCurrentNamespace();
|
||||
|
||||
std::string type = any_type_info.type.type;
|
||||
|
||||
|
|
|
|||
|
|
@ -127,6 +127,8 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type,
|
|||
|
||||
definition::Type& moved_type_info = global_info_.types_.back();
|
||||
|
||||
// TODO: constructors for tuple types, function types (??), array types (??), ...
|
||||
|
||||
if (std::holds_alternative<definition::AnyType>(moved_type_info.type)) {
|
||||
definition::AnyType& any_type_info = std::get<definition::AnyType>(moved_type_info.type);
|
||||
if (std::holds_alternative<std::unique_ptr<interpreter::tokens::VariantType>>(*any_type_info.value)) {
|
||||
|
|
@ -142,7 +144,10 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type,
|
|||
constructor_name = std::get<interpreter::tokens::Constructor>(variant_type_info.constructors[i]);
|
||||
} else if (std::holds_alternative<
|
||||
std::unique_ptr<interpreter::tokens::TupleType>>(variant_type_info.constructors[i])) {
|
||||
auto maybe_constructor_name = std::get<std::unique_ptr<interpreter::tokens::TupleType>>(variant_type_info.constructors[i])->type;
|
||||
constructor_info.constructor_tuple_node =
|
||||
std::get<std::unique_ptr<interpreter::tokens::TupleType>>(variant_type_info.constructors[i]).get();
|
||||
|
||||
auto maybe_constructor_name = constructor_info.constructor_tuple_node.value()->type;
|
||||
|
||||
if (maybe_constructor_name.has_value()) {
|
||||
constructor_name = maybe_constructor_name.value();
|
||||
|
|
|
|||
|
|
@ -53,6 +53,16 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) { // TODO: check
|
|||
error_handling::HandleTypecheckError("Type or constructor not found");
|
||||
}
|
||||
|
||||
if (node->constructor_id_.has_value()) {
|
||||
utils::IdType constructor_type_id = namespace_visitor_.GetGlobalInfo()->GetConstructorInfo(node->constructor_id_.value()).type_id;
|
||||
|
||||
if (node->type_id_.has_value() && node->type_id_.value() != constructor_type_id) {
|
||||
error_handling::HandleTypecheckError("Contructor and type with same name have different types");
|
||||
}
|
||||
|
||||
node->type_id_ = constructor_type_id;
|
||||
}
|
||||
|
||||
if (node->type_id_.has_value()) {
|
||||
node->type.type_id_ = node->type_id_.value();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
#include <asm-generic/errno.h>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
|
||||
// for clangd
|
||||
|
|
@ -114,13 +116,13 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
|
|||
|
||||
context_manager_.EnterContext();
|
||||
|
||||
info::definition::Function* function_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_);
|
||||
const info::definition::Function& function_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_);
|
||||
|
||||
if (!function_info->declaration.has_value()) {
|
||||
if (!function_info.declaration.has_value()) {
|
||||
error_handling::HandleTypecheckError("Function defined, but not declared");
|
||||
}
|
||||
|
||||
info::definition::FunctionDeclaration& declaration = function_info->declaration.value();
|
||||
const info::definition::FunctionDeclaration& declaration = function_info.declaration.value();
|
||||
|
||||
for (auto parameter : declaration.parameters) {
|
||||
std::vector<utils::IdType> requirements;
|
||||
|
|
@ -137,14 +139,17 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
|
|||
|
||||
// Visit(node->definition.get()); // ??
|
||||
for (size_t i = 0; i < node->definition->arguments.size(); ++i) {
|
||||
current_type_ = ConstructAnyType(declaration.argument_types[i]); // TODO
|
||||
if (!context_manager_.DefineVariable(node->definition->arguments[i].name, current_type_)) {
|
||||
Visitor::Visit(*declaration.argument_types[i]); // TODO: ConstructAnyType
|
||||
if (!context_manager_.DefineVariable(node->definition->arguments[i].name, current_type_, true)) { // TODO: watch to reference
|
||||
error_handling::HandleTypecheckError("Can't define function argument variable: name redefinition");
|
||||
}
|
||||
}
|
||||
|
||||
Visitor::Visit(*declaration.argument_types.back()); // TODO: ConstructAnyType
|
||||
utils::IdType return_type = current_type_;
|
||||
|
||||
Visitor::Visit(node->value);
|
||||
if (!context_manager_.EqualTypes(ConstructAnyType(declaration.argument_types.back()), current_type_)) {
|
||||
if (!context_manager_.EqualTypes(return_type, current_type_)) {
|
||||
error_handling::HandleTypecheckError("Wrong function return type");
|
||||
}
|
||||
|
||||
|
|
@ -370,31 +375,44 @@ void TypeCheckVisitor::Visit(LoopControlExpression& node) { // enum
|
|||
|
||||
// Operators
|
||||
|
||||
// -------------------------- TODO --------------------------
|
||||
// TODO
|
||||
// TODO: operator parameters (deduction?), etc.
|
||||
void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) {
|
||||
auto maybe_operator_id = namespace_visitor_.FindFunction({}, node->operator_name);
|
||||
auto maybe_operator_id = namespace_visitor_.FindFunction(std::nullopt, node->operator_name);
|
||||
|
||||
if (!maybe_operator_id.has_value()) {
|
||||
error_handling::HandleTypecheckError("Operator not found");
|
||||
}
|
||||
|
||||
auto operator_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value());
|
||||
const info::definition::Function& operator_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value());
|
||||
|
||||
if (operator_info->argument_count != 2) {
|
||||
if (!operator_info.declaration.has_value()) {
|
||||
error_handling::HandleTypecheckError("Operator declaration not found");
|
||||
}
|
||||
|
||||
if (!operator_info.definition.has_value()) { // TODO: builtin
|
||||
error_handling::HandleTypecheckError("Operator definition not found");
|
||||
}
|
||||
|
||||
if (operator_info.argument_count != 2) {
|
||||
error_handling::HandleTypecheckError("Operator wrong argument count");
|
||||
}
|
||||
|
||||
if (!operator_info->declaration.has_value() || !operator_info->definition.has_value()) {
|
||||
error_handling::HandleTypecheckError("Operator declaration or definition not found");
|
||||
if (operator_info.declaration->parameters.size() > 0) {
|
||||
error_handling::HandleTypecheckError("Operator with parameters");
|
||||
}
|
||||
|
||||
Visitor::Visit(*operator_info.declaration.value().argument_types[0]);
|
||||
utils::IdType left_expression_type = current_type_;
|
||||
|
||||
Visitor::Visit(node->left_expression);
|
||||
context_manager_.AddTypeRequirement(current_type_,
|
||||
ConstructAnyType(operator_info->declaration.value().argument_types[0])); // TODO
|
||||
context_manager_.AddTypeRequirement(current_type_, left_expression_type); // TODO: ConstructAnyType
|
||||
|
||||
Visitor::Visit(*operator_info.declaration.value().argument_types[1]);
|
||||
utils::IdType right_expression_type = current_type_;
|
||||
|
||||
Visitor::Visit(node->right_expression);
|
||||
context_manager_.AddTypeRequirement(current_type_,
|
||||
ConstructAnyType(operator_info->declaration.value().argument_types[1])); // TODO
|
||||
context_manager_.AddTypeRequirement(current_type_, right_expression_type); // TODO: ConstructAnyType
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -406,19 +424,29 @@ void TypeCheckVisitor::Visit(UnaryOperatorExpression* node) {
|
|||
error_handling::HandleTypecheckError("Operator not found");
|
||||
}
|
||||
|
||||
auto operator_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value());
|
||||
const info::definition::Function& operator_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value());
|
||||
|
||||
if (operator_info->argument_count != 1) {
|
||||
if (!operator_info.declaration.has_value()) {
|
||||
error_handling::HandleTypecheckError("Operator declaration not found");
|
||||
}
|
||||
|
||||
if (!operator_info.definition.has_value()) { // TODO: builtin
|
||||
error_handling::HandleTypecheckError("Operator definition not found");
|
||||
}
|
||||
|
||||
if (operator_info.argument_count != 1) {
|
||||
error_handling::HandleTypecheckError("Operator wrong argument count");
|
||||
}
|
||||
|
||||
if (!operator_info->declaration.has_value() || !operator_info->definition.has_value()) {
|
||||
error_handling::HandleTypecheckError("Operator declaration or definition not found");
|
||||
if (operator_info.declaration->parameters.size() > 0) {
|
||||
error_handling::HandleTypecheckError("Operator with parameters");
|
||||
}
|
||||
|
||||
Visitor::Visit(*operator_info.declaration.value().argument_types[0]);
|
||||
utils::IdType expression_type = current_type_;
|
||||
|
||||
Visitor::Visit(node->expression);
|
||||
context_manager_.AddTypeRequirement(current_type_,
|
||||
ConstructAnyType(operator_info->declaration.value().argument_types[0])); // TODO
|
||||
context_manager_.AddTypeRequirement(current_type_, expression_type); // TODO: ConstructAnyType
|
||||
}
|
||||
|
||||
void TypeCheckVisitor::Visit(ReferenceExpression* node) {
|
||||
|
|
@ -447,53 +475,128 @@ void TypeCheckVisitor::Visit(AccessExpression* node) {
|
|||
// Other Expressions
|
||||
|
||||
// TODO
|
||||
// TODO: builtin functions/methods
|
||||
// TODO: alias types, abstract types, etc.
|
||||
void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
|
||||
std::optional<utils::IdType> maybe_function_id;
|
||||
std::unordered_map<std::string, utils::IdType> context;
|
||||
|
||||
// guaranteed, that name.size() > 0
|
||||
if (node->name.name[0] == '_') { // TODO: manage pointers to function
|
||||
error_handling::HandleInternalError("Builtin functions/methods weren't implemented yet", "TypeCheckVisitor.FunctionCallExpresssion");
|
||||
}
|
||||
|
||||
if (node->prefix.has_value()) {
|
||||
|
||||
if (std::holds_alternative<std::unique_ptr<SubExpressionToken>>(node->prefix.value())) {
|
||||
Visitor::Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node->prefix.value()));
|
||||
// TODO
|
||||
|
||||
std::optional<info::type::DefinedType*> maybe_expression_type = context_manager_.GetType<info::type::DefinedType>(current_type_);
|
||||
|
||||
if (!maybe_expression_type.has_value()) {
|
||||
error_handling::HandleTypecheckError("There is no non-builtin methods for not defined type");
|
||||
}
|
||||
|
||||
utils::IdType type_id = maybe_expression_type.value()->GetTypeId();
|
||||
|
||||
const std::optional<info::definition::AnyType>& maybe_type_info = namespace_visitor_.GetGlobalInfo()->GetTypeInfo<info::definition::AnyType>(type_id);
|
||||
|
||||
if (!maybe_type_info.has_value()) {
|
||||
error_handling::HandleInternalError("Functions/Methods implemented only for AnyType", "TypeCheckVisitor.FunctionCallExpresssion");
|
||||
}
|
||||
|
||||
// TODO: better decision ??
|
||||
maybe_function_id = maybe_type_info.value().parent_namespace->variable_namespaces.at(maybe_type_info->type.type).functions[node->name.name];
|
||||
} else if (std::holds_alternative<std::unique_ptr<TypeExpression>>(node->prefix.value())) {
|
||||
Visit(std::get<std::unique_ptr<TypeExpression>>(node->prefix.value()).get());
|
||||
// TODO
|
||||
TypeExpression* type_expression = std::get<std::unique_ptr<TypeExpression>>(node->prefix.value()).get();
|
||||
|
||||
std::vector<std::string> path;
|
||||
path.reserve(type_expression->path.size() + 1);
|
||||
|
||||
for (auto& path_type : type_expression->path) {
|
||||
path.push_back(path_type.type);
|
||||
}
|
||||
path.push_back(type_expression->type.type);
|
||||
|
||||
maybe_function_id = namespace_visitor_.FindFunction(path, node->name.name);
|
||||
|
||||
CollectTypeExpressionContext(*std::get<std::unique_ptr<TypeExpression>>(node->prefix.value()), context);
|
||||
} else {
|
||||
// error
|
||||
}
|
||||
|
||||
current_type_ = /*...*/; // TODO
|
||||
} else {
|
||||
maybe_function_id = namespace_visitor_.FindFunction(std::nullopt, node->name.name);
|
||||
}
|
||||
|
||||
if (!std::holds_alternative<info::type::FunctionType>(context_manager_.GetType(current_type_))) {
|
||||
error_handling::HandleTypecheckError("Mismatched types in function call expression");
|
||||
if (!maybe_function_id.has_value()) {
|
||||
error_handling::HandleTypecheckError("Can't find function"); // InterlnalError ??
|
||||
}
|
||||
|
||||
info::type::FunctionType type_value = std::get<info::type::FunctionType>(context_manager_.GetType(current_type_));
|
||||
std::optional<info::definition::FunctionDeclaration> maybe_function_declaration =
|
||||
namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_function_id.value()).declaration;
|
||||
if (!maybe_function_declaration.has_value()) {
|
||||
error_handling::HandleTypecheckError("No function declaration found for function in function call expression");
|
||||
}
|
||||
info::definition::FunctionDeclaration function_declaration = maybe_function_declaration.value();
|
||||
|
||||
// TODO: ??
|
||||
// // Visitor::Visit(function_declaration.node->type.get());
|
||||
// //
|
||||
// // std::optional<info::type::FunctionType*> maybe_type_value = context_manager_.GetType<info::type::FunctionType>(current_type_);
|
||||
// // if (!maybe_type_value.has_value()) {
|
||||
// // error_handling::HandleInternalError("Type of function is not FunctionType", "TypeCheckVisitor.FunctionCallExpresssion");
|
||||
// // }
|
||||
// //
|
||||
// // info::type::FunctionType* type_value = maybe_type_value.value();
|
||||
|
||||
//
|
||||
|
||||
size_t argument_num = 0;
|
||||
size_t paramater_num = 0;
|
||||
|
||||
// TODO: parameters and arguments should be separated, parameters go first
|
||||
for (size_t i = 0; i < node->arguments.size(); ++i) {
|
||||
Visitor::Visit(node->arguments[i]);
|
||||
if (std::holds_alternative<TypeSubExpression>(node->arguments[i])) {
|
||||
// TODO
|
||||
if (std::holds_alternative<std::unique_ptr<TypeExpression>>(node->arguments[i])) {
|
||||
if (function_declaration.parameters.size() <= paramater_num) {
|
||||
error_handling::HandleTypecheckError("Mismatched parameter count in function call expression");
|
||||
}
|
||||
|
||||
std::string parameter_name = function_declaration.parameters[paramater_num].type;
|
||||
|
||||
if (context.count(parameter_name) != 0) {
|
||||
error_handling::HandleInternalError("Local abstract types with same name in one context", "TypeCheckVisitor.FunctionCallExpresssion"); // TypecheckError ??
|
||||
}
|
||||
|
||||
context[parameter_name] = current_type_;
|
||||
|
||||
++paramater_num;
|
||||
} else if (std::holds_alternative<SubExpressionToken>(node->arguments[i])) {
|
||||
if (type_value.argument_types.size() <= argument_num) {
|
||||
if (function_declaration.argument_types.size() <= argument_num) {
|
||||
error_handling::HandleTypecheckError("Mismatched argument count in function call expression");
|
||||
}
|
||||
|
||||
context_manager_.AddTypeRequirement(current_type_, type_value.argument_types[argument_num]);
|
||||
// TODO: not full context, if arguments and parameters not sepoarated
|
||||
|
||||
Visitor::Visit(*function_declaration.argument_types[argument_num]);
|
||||
context_manager_.AddTypeRequirement(current_type_, TypeInContext(current_type_, context));
|
||||
|
||||
++argument_num;
|
||||
} else {
|
||||
// error
|
||||
}
|
||||
}
|
||||
|
||||
if (type_value.argument_types.size() != argument_num) {
|
||||
if (function_declaration.parameters.size() != paramater_num) {
|
||||
error_handling::HandleTypecheckError("Mismatched parameter count in function call expression");
|
||||
}
|
||||
|
||||
if (function_declaration.argument_types.size() + 1 != argument_num) {
|
||||
error_handling::HandleTypecheckError("Mismatched argument count in function call expression");
|
||||
}
|
||||
|
||||
current_type_ = type_value.return_type;
|
||||
Visitor::Visit(*function_declaration.argument_types.back()); // add return type to info ??
|
||||
current_type_ = TypeInContext(current_type_, context);
|
||||
}
|
||||
|
||||
void TypeCheckVisitor::Visit(TupleExpression* node) {
|
||||
|
|
@ -530,41 +633,86 @@ void TypeCheckVisitor::Visit(ReturnExpression* node) {
|
|||
}
|
||||
|
||||
// TODO
|
||||
void Visitor::Visit(TypeConstructorParameter* node) {
|
||||
if (node->name.has_value()) {
|
||||
Visit(&node->name.value());
|
||||
}
|
||||
Visit(node->value);
|
||||
}
|
||||
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());
|
||||
if (!node->constructor->constructor_id_.has_value()) {
|
||||
error_handling::HandleTypecheckError("Type constructor name not found");
|
||||
}
|
||||
|
||||
utils::IdType type = node->constructor->constructor_id_.value();
|
||||
|
||||
|
||||
// TODO: check if exist
|
||||
info::definition::AnyType* type_info = &std::get<info::definition::AnyType>(
|
||||
namespace_visitor_.GetGlobalInfo()->GetTypeInfo(context_manager_.GetType<info::type::DefinedType>(type).value()->GetTypeId())->type);
|
||||
|
||||
for (size_t i = 0; i < node->parameters.size(); ++i) {
|
||||
// TODO: remove variable on move
|
||||
Visitor::Visit(node->parameters[i].value);
|
||||
// TODO: type in context of parameters
|
||||
// TODO: require ??
|
||||
context_manager_.EqualTypes(ConstructAnyType(type_info), current_type_); // TODO
|
||||
if (!node->constructor->type_id_.has_value()) {
|
||||
error_handling::HandleInternalError("Type constructor without type", "TypeCheckVisitor.TypeConstructor");
|
||||
}
|
||||
|
||||
current_type_ = type;
|
||||
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<std::string, utils::IdType> context;
|
||||
CollectTypeExpressionContext(*node->constructor, context);
|
||||
|
||||
// TODO: handle alias types
|
||||
const std::optional<info::definition::AnyType>& maybe_type_info =
|
||||
namespace_visitor_.GetGlobalInfo()->GetTypeInfo<info::definition::AnyType>(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();
|
||||
|
||||
// TODO: check if exist
|
||||
/*info::definition::AnyType* type_info = &std::get<info::definition::AnyType>(
|
||||
namespace_visitor_.GetGlobalInfo()->GetTypeInfo(context_manager_.GetType<info::type::DefinedType>(type).value()->GetTypeId())->type);*/
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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) {
|
||||
error_handling::HandleTypecheckError("Type constructor: name of parameter and name in constructor don't match each other");
|
||||
}
|
||||
} else {
|
||||
if (constructor_fields->entities[i].first.has_value()) {
|
||||
error_handling::HandleTypecheckError("Type constructor: unnamed pprameter corresponds named field");
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
Visitor::Visit(*type_info.value);
|
||||
current_type_ = TypeInContext(current_type_, context);
|
||||
}
|
||||
|
||||
// TODO
|
||||
void TypeCheckVisitor::Visit(LambdaFunction* node) {
|
||||
error_handling::HandleInternalError("Unimplemented", "TypeCheckVisitor.LambdaFunction");
|
||||
error_handling::HandleInternalError("Unimplemented (unsolved type deduction problems)", "TypeCheckVisitor.LambdaFunction");
|
||||
}
|
||||
|
||||
void TypeCheckVisitor::Visit(ArrayExpression* node) {
|
||||
|
|
@ -615,6 +763,11 @@ void TypeCheckVisitor::Visit(NameExpression* node) { // TODO: ?? functions witho
|
|||
void TypeCheckVisitor::Visit(TupleName* node) {
|
||||
utils::IdType type = current_type_;
|
||||
|
||||
std::optional<info::type::DefinedType*> maybe_defined_type_value = context_manager_.GetType<info::type::DefinedType>(type);
|
||||
if (maybe_defined_type_value.has_value()) {
|
||||
type = maybe_defined_type_value.value()->GetType();
|
||||
}
|
||||
|
||||
std::optional<info::type::TupleType*> maybe_type_value = context_manager_.GetType<info::type::TupleType>(type);
|
||||
|
||||
if (maybe_type_value.has_value()) {
|
||||
|
|
@ -635,6 +788,11 @@ void TypeCheckVisitor::Visit(TupleName* node) {
|
|||
void TypeCheckVisitor::Visit(VariantName* node) {
|
||||
utils::IdType type = current_type_;
|
||||
|
||||
std::optional<info::type::DefinedType*> maybe_defined_type_value = context_manager_.GetType<info::type::DefinedType>(type);
|
||||
if (maybe_defined_type_value.has_value()) {
|
||||
type = maybe_defined_type_value.value()->GetType();
|
||||
}
|
||||
|
||||
std::optional<info::type::VariantType*> maybe_type_value = context_manager_.GetType<info::type::VariantType>(type);
|
||||
|
||||
if (!maybe_type_value.has_value()) {
|
||||
|
|
@ -731,13 +889,21 @@ void TypeCheckVisitor::Visit(VariantType* node) {
|
|||
current_type_ = context_manager_.AddType(info::type::VariantType(node->type, constructors));
|
||||
}
|
||||
|
||||
// TODO, different for constructors
|
||||
// TODO different for constructors
|
||||
// TODO handle local abstract types, abstract types, aliases, etc.
|
||||
void TypeCheckVisitor::Visit(TypeExpression* node) {
|
||||
// TODO: type in context of parameters
|
||||
utils::IdType type = ConstructAnyType(/*...*/); // TODO
|
||||
std::unordered_map<std::string, utils::IdType> context;
|
||||
CollectTypeExpressionContext(*node, context);
|
||||
|
||||
current_type_ = context_manager_.AddType(
|
||||
info::type::DefinedType(node->type_id_, type, context_manager_.GetTypeManager()));
|
||||
const std::optional<info::definition::AnyType>& maybe_type_info =
|
||||
namespace_visitor_.GetGlobalInfo()->GetTypeInfo<info::definition::AnyType>(node->type.type_id_.value());
|
||||
|
||||
if (!maybe_type_info.has_value()) { // TODO: add alias, abstract, ... types
|
||||
error_handling::HandleInternalError("No any type found", "TypeCheckVisitor.TypeExpression");
|
||||
}
|
||||
|
||||
Visitor::Visit(*maybe_type_info.value().value);
|
||||
current_type_ = TypeInContext(current_type_, context); // TODO: check
|
||||
}
|
||||
|
||||
void TypeCheckVisitor::Visit(ExtendedScopedAnyType* node) {
|
||||
|
|
@ -759,20 +925,7 @@ void Visitor::Visit(ParametrizedTypeclass* node) {
|
|||
|
||||
// Typeclass & Type -----------------
|
||||
|
||||
void TypeCheckVisitor::Visit(ParametrizedType* node) { // TODO: always used in TypeExpression ??
|
||||
utils::IdType type;
|
||||
|
||||
// type.paramaters.reserve(node->parameters.size());
|
||||
// for (auto& paramater : node->parameters) {
|
||||
// Visitor::Visit(paramater);
|
||||
// type.paramaters.push_back(current_type_);
|
||||
// }
|
||||
|
||||
// TODO: type in context of parameters
|
||||
ConstructAnyType(/*any type from node*/); // TODO. ??
|
||||
|
||||
current_type_ = context_manager_.AddType(info::type::DefinedType(node->type_expression->type_id_, type, context_manager_.GetTypeManager()));
|
||||
}
|
||||
void TypeCheckVisitor::Visit(ParametrizedType* node) {} // Used in TypeExpression
|
||||
|
||||
// Identifiers, constants, etc. -----------------
|
||||
|
||||
|
|
@ -794,4 +947,51 @@ void TypeCheckVisitor::Visit(CharLiteral* node) {
|
|||
current_type_ = context_manager_.AddType(info::type::InternalType::Char);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void TypeCheckVisitor::CollectTypeContext(const ParametrizedType& type,
|
||||
std::unordered_map<std::string, utils::IdType>& context) {
|
||||
if (!type.type_id_.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::optional<info::definition::AnyType>& maybe_type_info =
|
||||
namespace_visitor_.GetGlobalInfo()->GetTypeInfo<info::definition::AnyType>(type.type_id_.value());
|
||||
|
||||
if (!maybe_type_info.has_value()) {
|
||||
error_handling::HandleInternalError("Wrong type id", "TypeCheckVisitor.CollectTypeContext");
|
||||
}
|
||||
|
||||
const info::definition::AnyType& type_info = maybe_type_info.value();
|
||||
|
||||
if (type_info.parameters.size() != type.parameters.size()) {
|
||||
error_handling::HandleTypecheckError("Wrong type parameters count");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < type.parameters.size(); ++i) {
|
||||
Visit(type.parameters[i].get());
|
||||
|
||||
if (context.count(type_info.parameters[i].type) != 0) {
|
||||
error_handling::HandleInternalError("Same parameter type names", "TypeCheckVisitor.CollectTypeContext");
|
||||
}
|
||||
|
||||
context[type_info.parameters[i].type] = current_type_;
|
||||
}
|
||||
}
|
||||
|
||||
void TypeCheckVisitor::CollectTypeExpressionContext(const TypeExpression& type_expression,
|
||||
std::unordered_map<std::string, utils::IdType>& context) {
|
||||
for (auto& path_type : type_expression.path) {
|
||||
CollectTypeContext(path_type, context);
|
||||
}
|
||||
CollectTypeContext(type_expression.type, context);
|
||||
}
|
||||
|
||||
utils::IdType TypeCheckVisitor::TypeInContext(utils::IdType type,
|
||||
const std::unordered_map<std::string, utils::IdType>& context) {
|
||||
info::type::Type type_in_context = info::type::Type(context_manager_.GetAnyType(type));
|
||||
type_in_context.InContext(context);
|
||||
return context_manager_.AddType(std::move(type_in_context));
|
||||
}
|
||||
|
||||
} // namespace interpreter
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue