part of type_check_visitor done

This commit is contained in:
ProgramSnail 2023-04-22 19:30:16 +03:00
parent 6fc91aafa0
commit 656f58bcde
14 changed files with 891 additions and 539 deletions

View file

@ -117,6 +117,8 @@ void FindSymbolsVisitor::Visit(FunctionDeclaration* node) {
info.argument_type_nodes[i] = &node->type->types[i];
}
info.node = node;
if (was_in_statement) {
current_info_ = std::move(info);
} else {
@ -148,7 +150,7 @@ void FindSymbolsVisitor::Visit(FunctionDefinitionStatement* node) {
node->return_type_graph_id_ = namespace_visitor_.GetAbstractTypeGraph()->AddVertex();
info.expression = &node->value;
info.node = node;
node->function_id_ = namespace_visitor_.AddFunctionDefinition(definition->name, std::move(info));

View file

@ -1,5 +1,6 @@
// for clangd
#include "../include/global_info.hpp"
#include "../include/error_handling.hpp"
namespace info {
@ -63,9 +64,13 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDeclaration(const std::st
id = global_info_.functions_.size();
namespace_stack_.back()->functions[name] = id;
global_info_.functions_.emplace_back();
global_info_.functions_.back().argument_count = function_declaration_info.argument_types.size();
global_info_.functions_.back().declaration = std::move(function_declaration_info);
} else {
id = function_id_iter->second;
if (global_info_.functions_.back().argument_count != function_declaration_info.argument_types.size()) {
error_handling::HandleInternalError("Not same argument count in function definition and declaration", "GlobalInfo");
}
global_info_.functions_[id].declaration = std::move(function_declaration_info);
}
@ -82,9 +87,13 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDefinition(const std::str
id = global_info_.functions_.size();
namespace_stack_.back()->functions[name] = id;
global_info_.functions_.emplace_back();
global_info_.functions_.back().argument_count = function_definition_info.argument_names.size();
global_info_.functions_.back().definition = std::move(function_definition_info);
} else {
id = function_id_iter->second;
if (global_info_.functions_.back().argument_count != function_definition_info.argument_names.size()) {
error_handling::HandleInternalError("Not same argument count in function definition and declaration", "GlobalInfo");
}
global_info_.functions_[id].definition = std::move(function_definition_info);
}

View file

@ -54,7 +54,7 @@ void LinkSymbolsVisitor::Visit(AliasDefinitionStatement* node) {
for (size_t i = 0; i <node->parameters.size(); ++i) {
abstract_types_.DefineType(node->parameters[i], node->parameter_graph_ids_[i]);
}
Visit(node->value.get());
Visitor::Visit(node->value.get());
abstract_types_.ExitContext();
}
@ -68,10 +68,10 @@ void LinkSymbolsVisitor::Visit(VariableDefinitionStatement* node) {
void LinkSymbolsVisitor::Visit(FunctionDeclaration* node) {
abstract_types_.EnterContext();
for (auto& parameter : node->parameters) {
Visit(parameter.get());
Visitor::Visit(parameter.get());
abstract_types_.DefineType(parameter->type, parameter->type_graph_id_);
}
Visit(node->type.get());
Visitor::Visit(node->type.get());
abstract_types_.ExitContext();
}
@ -90,7 +90,7 @@ void LinkSymbolsVisitor::Visit(TypeDefinitionStatement* node) {
}
void LinkSymbolsVisitor::Visit(AbstractTypeDefinitionStatement* node) {
Visit(node->type.get());
Visitor::Visit(node->type.get());
// TODO: can't be used before definition
abstract_types_.DefineType(node->type->type, node->type->type_graph_id_);
}
@ -108,224 +108,54 @@ void LinkSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) {
void LinkSymbolsVisitor::Visit(FunctionDefinition* node) {
for (auto& parameter : node->parameters) {
Visit(parameter.get());
Visitor::Visit(parameter.get());
abstract_types_.DefineType(parameter->type, parameter->type_graph_id_);
}
}
void LinkSymbolsVisitor::Visit(TypeDefinition* node) {
Visit(node->type.get());
Visitor::Visit(node->type.get());
for (auto& parameter : node->parameters) {
Visit(parameter.get());
Visitor::Visit(parameter.get());
abstract_types_.DefineType(parameter->type, parameter->type_graph_id_);
}
}
void LinkSymbolsVisitor::Visit(AnyAnnotatedType* node) {
// TODO check ??
if (!node->typeclasses.empty() > 0) {
for (auto& typeclass : node->typeclasses) {
Visitor::Visit(typeclass);
}
}
}
// Flow control -----------------
void LinkSymbolsVisitor::Visit(MatchCase* node) {
Visitor::Visit(node->value);
if (node->condition.has_value()) {
Visitor::Visit(node->condition.value());
}
if (node->statement.has_value()) {
Visitor::Visit(node->statement.value());
}
}
void LinkSymbolsVisitor::Visit(Match* node) {
Visitor::Visit(node->value);
for (auto& match_case : node->matches) {
Visit(&match_case);
}
}
void LinkSymbolsVisitor::Visit(Condition* node) {
Visitor::Visit(node->conditions[0]);
Visitor::Visit(node->statements[0]);
for (size_t i = 1; i < node->conditions.size(); ++i) {
Visitor::Visit(node->conditions[i]);
Visitor::Visit(node->statements[i]);
}
if (node->statements.size() > node->conditions.size()) {
Visitor::Visit(node->statements[node->conditions.size()]);
}
}
void LinkSymbolsVisitor::Visit(DoWhileLoop* node) {
Visitor::Visit(node->statement);
Visitor::Visit(node->condition);
}
void LinkSymbolsVisitor::Visit(WhileLoop* node) {
Visitor::Visit(node->condition);
Visitor::Visit(node->statement);
}
void LinkSymbolsVisitor::Visit(ForLoop* node) {
Visitor::Visit(node->variable);
Visitor::Visit(node->interval);
Visitor::Visit(node->statement);
}
void LinkSymbolsVisitor::Visit(LoopLoop* node) {
Visitor::Visit(node->statement);
}
// Statements, expressions, blocks, etc. -----------------
void LinkSymbolsVisitor::Visit(Block* node) {
for (auto& statement : node->statements) {
Visitor::Visit(statement);
}
}
void LinkSymbolsVisitor::Visit(ScopedStatement* node) {
Visitor::Visit(node->statement);
}
void LinkSymbolsVisitor::Visit(LoopControlExpression& node) {}
// Operators
void LinkSymbolsVisitor::Visit(BinaryOperatorExpression* node) {
Visitor::Visit(node->left_expression);
Visitor::Visit(node->right_expression);
}
void LinkSymbolsVisitor::Visit(UnaryOperatorExpression* node) {
Visitor::Visit(node->expression);
}
void LinkSymbolsVisitor::Visit(ReferenceExpression* node) {
Visit(node->expression.get());
}
void LinkSymbolsVisitor::Visit(AccessExpression* node) {
Visitor::Visit(node->name.get());
Visitor::Visit(node->id);
}
// Other Expressions
void LinkSymbolsVisitor::Visit(FunctionCallExpression* node) {
Visit(node->name.get());
for (auto& argument : node->arguments) {
Visitor::Visit(argument);
}
}
void LinkSymbolsVisitor::Visit(TupleExpression* node) {
for (auto& expression : node->expressions) {
Visitor::Visit(expression);
}
}
void LinkSymbolsVisitor::Visit(VariantExpression* node) {
for (auto& expression : node->expressions) {
Visitor::Visit(expression);
}
}
void LinkSymbolsVisitor::Visit(ReturnExpression* node) {
Visitor::Visit(node->expression);
}
void LinkSymbolsVisitor::Visit(TypeConstructor* node) {
Visit(node->type.get());
for (auto& parameter : node->parameters) {
Visitor::Visit(std::get<2>(parameter));
}
}
// TODO: move to find_symbols_visitor
void LinkSymbolsVisitor::Visit(LambdaFunction* node) {
abstract_types_.EnterContext();
for (auto& parameter : node->parameters) {
Visit(parameter.get());
Visitor::Visit(parameter.get());
abstract_types_.DefineType(parameter->type, parameter->type_graph_id_);
}
////////////
node->argument_graph_ids_.resize(node->arguments.size());
for (size_t i = 0; i < node->arguments.size(); ++i) {
node->argument_graph_ids_[i] = namespace_visitor_.GetAbstractTypeGraph()->AddVertex();
}
node->return_type_graph_id_ = namespace_visitor_.GetAbstractTypeGraph()->AddVertex();
///////////
Visitor::Visit(node->expression);
abstract_types_.ExitContext();
}
void LinkSymbolsVisitor::Visit(ArrayExpression* node) {
for (auto& element : node->elements) {
Visitor::Visit(element);
}
}
// Name
void LinkSymbolsVisitor::Visit(NameExpression* node) {
for (auto& variable_namespace : node->namespaces) {
Visitor::Visit(variable_namespace);
}
// for (auto& expression : node->expressions) {
// Visit(expression);
// }
}
void LinkSymbolsVisitor::Visit(TupleName* node) {
for (auto& name : node->names) {
Visitor::Visit(name);
}
}
void LinkSymbolsVisitor::Visit(VariantName* node) {
for (auto& name : node->names) {
Visitor::Visit(name);
}
}
void LinkSymbolsVisitor::Visit(AnnotatedName* node) {
if (node->type.has_value()) {
Visitor::Visit(node->type.value());
}
}
// Type, typeclass, etc. -----------------
// Type
void LinkSymbolsVisitor::Visit(FunctionType* node) {
for (auto& type : node->types) {
Visitor::Visit(type);
}
}
void LinkSymbolsVisitor::Visit(TupleType* node) {
for (auto& entity : node->entities) {
Visit(entity.second.get());
}
}
void LinkSymbolsVisitor::Visit(VariantType* node) {
for (auto& constructor : node->constructors) {
if (std::holds_alternative<Constructor>(constructor)) {
// do nothing
} else if (std::holds_alternative<std::unique_ptr<TupleType>>(constructor)) {
Visit(std::get<std::unique_ptr<TupleType>>(constructor).get());
} else {
// error
}
}
}
void LinkSymbolsVisitor::Visit(ParametrizedType* node) {
Visit(node->type_expression.get());
for (auto& parameter : node->parameters) {
Visitor::Visit(parameter);
}
}
void LinkSymbolsVisitor::Visit(TypeExpression* node) {
std::vector<std::string> path;
path.reserve(node->namespaces.size());
@ -361,19 +191,8 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) {
}
}
void LinkSymbolsVisitor::Visit(ExtendedScopedAnyType* node) {
Visitor::Visit(node->type);
}
// Typeclass
void LinkSymbolsVisitor::Visit(ParametrizedTypeclass* node) {
Visit(node->typeclass_expression.get());
for (auto& parameter : node->parameters) {
Visitor::Visit(parameter);
}
}
void LinkSymbolsVisitor::Visit(TypeclassExpression* node) {
std::vector<std::string> path;
path.reserve(node->namespaces.size());

View file

@ -250,7 +250,7 @@ void PrintVisitor::Visit(AnyAnnotatedType* node) {
out_ << "[Annotated (Abstract) Type ";
Visit(&node->type);
out_ << ']';
if (!node->typeclasses.empty() > 0) {
if (!node->typeclasses.empty()) {
out_ << " (";
for (auto& typeclass : node->typeclasses) {
Visitor::Visit(typeclass);

View file

@ -1,5 +1,9 @@
#include "../include/type_check_visitor.hpp"
#include <memory>
#include <variant>
// for clangd
#include "../include/type_check_visitor.hpp"
#include "../include/error_handling.hpp"
// TODO
@ -17,26 +21,30 @@ void TypeCheckVisitor::Visit(SourceFile* node) {
// error
}
}
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
void TypeCheckVisitor::Visit(Sources* node) {
for (auto& statement : node->statements) {
Visitor::Visit(statement);
}
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
// Namespaces, partitions -----------------
void TypeCheckVisitor::Visit(Partition* node) {
Visit(node->scope.get());
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
void TypeCheckVisitor::Visit(Namespace* node) {
if (node->name.has_value()) {
// TODO: add modifiers
node->variable_type_ = info::type::Type {info::type::DefinedType {node->type_id_.value()}};
context_manager_.EnterVariableContext(node->name.value().name,
&node->variable_type_.value());
context_manager_.AddType(info::type::DefinedType {node->type_id_.value()}));
}
namespace_visitor_.EnterNamespace(node->type);
@ -44,6 +52,8 @@ void TypeCheckVisitor::Visit(Namespace* node) {
Visit(node->scope.get());
namespace_visitor_.ExitNamespace();
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
// Definitions -----------------
@ -51,364 +61,520 @@ void TypeCheckVisitor::Visit(Namespace* node) {
void TypeCheckVisitor::Visit(ImportStatement* node) {}
void TypeCheckVisitor::Visit(AliasDefinitionStatement* node) {
// TODO check, that all paramaters used
// check, that all paramaters used ??
utils::IdType type = context_manager_.AddType(info::type::DefinedType {node->type_id_}); // ??
Visit(node->value.get());
context_manager_.EqualTypes(type, current_type_);
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
void TypeCheckVisitor::Visit(VariableDefinitionStatement* node) {
// TODO: remove variable on move
// TODO: add modifiers
Visitor::Visit(node->value);
// current_type from value automatically passed to name definitions
Visitor::Visit(node->name);
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
void TypeCheckVisitor::Visit(FunctionDeclaration* node) {
// later check, that function definition requirements are satisfied
// check later that function definition requirements are satisfied
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
Visit(node->definition.get());
// check, that all paramaters used ??
context_manager_.EnterContext();
// Visit(node->definition.get()); // ??
for (size_t i = 0; i < node->definition->arguments.size(); ++i) {
context_manager_.DefineVariable(node->definition->arguments[i].name,
context_manager_.AddType(info::type::AbstractType { node->argument_graph_ids_[i] }));
}
Visitor::Visit(node->value);
context_manager_.EqualTypes(
context_manager_.AddType(info::type::AbstractType { node->return_type_graph_id_ }), current_type_);
context_manager_.ExitContext();
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
void TypeCheckVisitor::Visit(TypeDefinitionStatement* node) {
switch (node->modifier) {
case TypeDefinitionStatement::Struct:
break;
case TypeDefinitionStatement::Class:
break;
}
Visit(node->definition.get());
Visitor::Visit(node->value);
// TODO: add modifiers
// check, that all paramaters used ??
// TODO: defined type typeclasses
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) {
switch (node->modifier) {
case AbstractTypeDefinitionStatement::Basic:
break;
case AbstractTypeDefinitionStatement::Abstract:
break;
utils::IdType type = context_manager_.AddType(info::type::AbstractType {node->type_graph_id_} );
// Visit(node->type.get()); ??
for (auto& typeclass : node->type->typeclasses) { // TODO
Visitor::Visit(typeclass);
context_manager_.AddTypeRequirement(type, current_type_);
}
Visit(node->type.get());
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
void TypeCheckVisitor::Visit(TypeclassDefinitionStatement* node) {
Visit(node->definition.get());
if (!node->requirements.empty()) {
}
for (auto& requirement : node->requirements) {
Visit(requirement.get());
}
// check, that all paramaters used ??
// TODO: needed ??
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
// Definition parts
void TypeCheckVisitor::Visit(FunctionDefinition* node) {
switch (node->modifier) {
case FunctionDefinition::Operator:
break;
case FunctionDefinition::Function:
break;
}
Visit(&node->name);
if (!node->parameters.empty()) {
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
}
if (!node->arguments.empty()) {
for (auto& argument : node->arguments) {
Visit(&argument);
}
}
// TODO: needed ??
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
void TypeCheckVisitor::Visit(TypeDefinition* node) {
Visit(node->type.get());
if (!node->parameters.empty()) {
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
}
// TODO: needed ??
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
// used on upper levels
void TypeCheckVisitor::Visit(AnyAnnotatedType* node) {
Visit(&node->type);
if (!node->typeclasses.empty() > 0) {
for (auto& typeclass : node->typeclasses) {
Visitor::Visit(typeclass);
}
}
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
// Flow control -----------------
void TypeCheckVisitor::Visit(MatchCase* node) {
Visitor::Visit(node->value);
Visitor::Visit(node->value); // TODO: literal & name instead of expression
if (node->condition.has_value()) {
Visitor::Visit(node->condition.value());
}
context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Bool), current_type_);
if (node->statement.has_value()) {
Visitor::Visit(node->statement.value());
}
// current_type_ from statement is current_type_ for MatchCase
}
void TypeCheckVisitor::Visit(Match* node) {
void TypeCheckVisitor::Visit(Match* node) { // TODO return variant type ?? (problems with same types)
// TODO: types can be different in statement
utils::IdType type;
Visitor::Visit(node->value);
for (auto& match_case : node->matches) {
Visit(&match_case);
for (size_t i = 0; i < node->matches.size(); ++i) {
Visit(&node->matches[i]);
if (i == 0) {
type = current_type_;
} else {
context_manager_.EqualTypes(type, current_type_);
}
}
current_type_ = type;
}
void TypeCheckVisitor::Visit(Condition* node) {
Visitor::Visit(node->conditions[0]);
Visitor::Visit(node->statements[0]);
for (size_t i = 1; i < node->conditions.size(); ++i) {
void TypeCheckVisitor::Visit(Condition* node) { // TODO return variant type ?? (problem with same types)
// TODO: types can be different in statement
utils::IdType type;
for (size_t i = 0; i < node->conditions.size(); ++i) {
Visitor::Visit(node->conditions[i]);
context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Bool), current_type_);
Visitor::Visit(node->statements[i]);
if (i == 0) {
type = current_type_;
} else {
context_manager_.EqualTypes(type, current_type_);
}
}
if (node->statements.size() > node->conditions.size()) {
Visitor::Visit(node->statements[node->conditions.size()]);
context_manager_.EqualTypes(type, current_type_);
current_type_ = type;
} else {
current_type_ = context_manager_.AddType(info::type::OptionalType {type});
}
}
void TypeCheckVisitor::Visit(DoWhileLoop* node) {
out_ << "[Do] (\n";
Visitor::Visit(node->statement);
out_ << ") [while] (";
Visitor::Visit(node->condition);
out_ << ")\n";
context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Bool), current_type_);
Visitor::Visit(node->statement);
info::type::ArrayType type;
type.size = 0;
type.elements_type = current_type_;
current_type_ = context_manager_.AddType(type);
}
void TypeCheckVisitor::Visit(WhileLoop* node) {
out_ << "[While] (";
Visitor::Visit(node->statement);
out_ << ") [do] (\n";
Visitor::Visit(node->condition);
out_ << ")\n";
}
void TypeCheckVisitor::Visit(ForLoop* node) {
out_ << "[For] (";
Visitor::Visit(node->variable);
out_ << ") [in] (";
Visitor::Visit(node->interval);
out_ << ") [do] (\n";
context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Bool), current_type_);
Visitor::Visit(node->statement);
out_ << ")\n";
info::type::ArrayType type;
type.size = 0;
type.elements_type = current_type_;
current_type_ = context_manager_.AddType(type);
}
void TypeCheckVisitor::Visit(ForLoop* node) {
Visitor::Visit(node->interval);
if (!std::holds_alternative<info::type::ArrayType>(context_manager_.GetType(current_type_))) {
error_handling::HandleTypecheckError("For loop interval type mismatch");
}
info::type::ArrayType type_value =
std::get<info::type::ArrayType>(context_manager_.GetType(current_type_));
current_type_ = context_manager_.AddType(type_value.elements_type);
Visitor::Visit(node->variable);
Visitor::Visit(node->statement);
info::type::ArrayType type;
type.size = 0;
type.elements_type = current_type_;
current_type_ = context_manager_.AddType(type);
}
void TypeCheckVisitor::Visit(LoopLoop* node) {
out_ << "[Loop] (\n";
Visitor::Visit(node->statement);
out_ << ")\n";
info::type::ArrayType type;
type.size = 0;
type.elements_type = current_type_;
current_type_ = context_manager_.AddType(type);
}
// Statements, expressions, blocks, etc. -----------------
void TypeCheckVisitor::Visit(Block* node) {
out_ << "[Block] {\n";
void TypeCheckVisitor::Visit(Block* node) { // TODO return variant type ?? (problem with same types)
utils::IdType type;
bool is_first_returned_type = true;
for (auto& statement : node->statements) {
returned_type_ = std::nullopt;
Visitor::Visit(statement);
if (returned_type_.has_value()) {
if (is_first_returned_type) {
type = returned_type_.value();
is_first_returned_type = false;
} else {
context_manager_.EqualTypes(type, returned_type_.value());
}
}
}
out_ << "}\n";
if (is_first_returned_type) {
type = context_manager_.AddType(info::type::InternalType::Unit);
}
current_type_ = type;
}
void TypeCheckVisitor::Visit(ScopedStatement* node) {
out_ << "[Scoped] ( ";
Visitor::Visit(node->statement);
out_ << ")\n";
// current_type_ is type of statement
}
void TypeCheckVisitor::Visit(LoopControlExpression& node) { // enum
switch (node) {
case LoopControlExpression::Break:
out_ << "[Break]\n";
break;
case LoopControlExpression::Continue:
out_ << "[Continue]\n";
break;
}
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
// Operators
// -------------------------- TODO --------------------------
void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) {
out_ << "[BinaryOperator] (";
Visitor::Visit(node->left_expression);
out_ << ") [";
Visit(&node->operator_name);
out_ << "] (";
Visitor::Visit(node->right_expression);
out_ << ')';
auto maybe_operator_id = namespace_visitor_.FindFunction({}, 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());
if (operator_info->argument_count != 2) {
error_handling::HandleTypecheckError("Operator wrong argument count");
}
if (operator_info->definition.has_value()) {
Visitor::Visit(node->left_expression);
context_manager_.AddTypeRequirement(current_type_,
context_manager_.AddType(info::type::AbstractType {operator_info->definition.value().node->argument_graph_ids_[0]}));
Visitor::Visit(node->right_expression);
context_manager_.AddTypeRequirement(current_type_,
context_manager_.AddType(info::type::AbstractType {operator_info->definition.value().node->argument_graph_ids_[1]}));
} else if (operator_info->declaration.has_value()) {
// TODO: get argument types
} else {
error_handling::HandleInternalError("Operator definition and declaration both not found", "TypeCheckVisitor");
}
}
// -------------------------- TODO --------------------------
void TypeCheckVisitor::Visit(UnaryOperatorExpression* node) {
out_ << "[UnaryOperator ";
Visit(&node->operator_name);
out_ << "] (";
Visitor::Visit(node->expression);
out_ << ')';
auto maybe_operator_id = namespace_visitor_.FindFunction({}, 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());
if (operator_info->argument_count != 1) {
error_handling::HandleTypecheckError("Operator wrong argument count");
}
if (operator_info->definition.has_value()) {
Visitor::Visit(node->expression);
context_manager_.AddTypeRequirement(current_type_,
context_manager_.AddType(info::type::AbstractType {operator_info->definition.value().node->argument_graph_ids_[0]}));
} else if (operator_info->declaration.has_value()) {
// TODO: get argument type
} else {
error_handling::HandleInternalError("Operator definition and declaration both not found", "TypeCheckVisitor");
}
}
void TypeCheckVisitor::Visit(ReferenceExpression* node) {
out_ << "[ReferenceExpression ";
for (auto& reference : node->references) {
switch (reference) {
case ReferenceType::Reference:
out_ << '~';
break;
case ReferenceType::UniqueReference:
out_ << '@';
break;
}
}
out_ << "] (";
Visit(node->expression.get());
out_ << ')';
info::type::ReferenceToType type;
type.references = node->references;
type.type = current_type_;
current_type_ = context_manager_.AddType(type);
}
void TypeCheckVisitor::Visit(AccessExpression* node) { // TODO
Visitor::Visit(node->name);
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 ?
Visitor::Visit(node->name.get());
if (!std::holds_alternative<info::type::ArrayType>(context_manager_.GetType(current_type_))) {
error_handling::HandleTypecheckError("Access type mismatch");
}
info::type::ArrayType type_value =
std::get<info::type::ArrayType>(context_manager_.GetType(current_type_));
current_type_ = context_manager_.AddType(type_value.elements_type);
}
// Other Expressions
// -------------------------- TODO --------------------------
void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
out_ << "[FunctionCall ";
// TODO: add function paramaters
Visit(node->name.get());
out_ << "] (";
for (auto& argument : node->arguments) {
Visitor::Visit(argument);
out_ << ", ";
}
out_ << ")";
if (!std::holds_alternative<info::type::FunctionType>(context_manager_.GetType(current_type_))) {
error_handling::HandleTypecheckError("Mismatched types in function call expression");
}
info::type::FunctionType type_value = std::get<info::type::FunctionType>(context_manager_.GetType(current_type_));
if (type_value.argument_types.size() != node->arguments.size()) {
error_handling::HandleTypecheckError("Mismatched argument count in function call expression");
}
for (size_t i = 0; i < node->arguments.size(); ++i) {
Visitor::Visit(node->arguments[i]);
if (std::holds_alternative<std::string>(node->arguments[i])) {
} else if (std::holds_alternative<info::type::TupleType>(node->arguments[i])) {
} else {
// error
}
context_manager_.AddTypeRequirement(current_type_, type_value.argument_types[i]);
}
current_type_ = type_value.return_type;
}
void TypeCheckVisitor::Visit(TupleExpression* node) {
out_ << "[TupleExpression] (";
info::type::TupleType type;
type.fields.reserve(node->expressions.size());
for (auto& expression : node->expressions) {
out_ << "&";
Visitor::Visit(expression);
type.fields.push_back({std::nullopt, current_type_});
}
out_ << ")";
current_type_ = context_manager_.AddType(std::move(type));
}
void TypeCheckVisitor::Visit(VariantExpression* node) {
out_ << "[VariantExpression] (";
info::type::VariantType type;
for (auto& expression : node->expressions) {
out_ << "|";
info::type::TupleType constructor;
Visitor::Visit(expression);
constructor.fields.push_back({std::nullopt, current_type_}); // ??
type.constructors.push_back(constructor);
}
out_ << ")";
current_type_ = context_manager_.AddType(std::move(type));
}
void TypeCheckVisitor::Visit(ReturnExpression* node) {
Visitor::Visit(node->expression);
}
void TypeCheckVisitor::Visit(TypeConstructor* node) {
out_ << "[TypeConstructor ";
Visit(node->type.get());
out_ << "]\n(";
// -------------------------- TODO --------------------------
void TypeCheckVisitor::Visit(TypeConstructor* node) { // TODO: find constructor names, etc.
utils::IdType type;
bool is_first = true;
for (auto& parameter : node->parameters) {
if (!is_first) {
out_ << ")\n";
is_first = false;
}
out_ << '(';
Visit(&std::get<0>(parameter));
switch (std::get<1>(parameter)) {
case TypeConstructor::Assign:
out_ << " = ";
break;
case TypeConstructor::Move:
out_ << " <- ";
break;
}
Visitor::Visit(std::get<2>(parameter));
Visit(node->type.get());
type = current_type_;
info::AnyTypeInfo* type_info = &std::get<info::AnyTypeInfo>(
namespace_visitor_.GetGlobalInfo()->GetTypeInfo(
std::get<info::type::DefinedType>(context_manager_.GetType(type)).type_id)->type);
for (size_t i = 0; i < node->parameters.size(); ++i) {
//Visit(&std::get<0>(parameter));
// TODO: remove variable on move
Visitor::Visit(std::get<2>(node->parameters[i]));
//context_manager_.EqualTypes(/* TODO type_info->get_field(paramater).type */, current_type_);
}
out_ << ")\n";
current_type_ = type;
}
void TypeCheckVisitor::Visit(LambdaFunction* node) {
out_ << "[LambdaFunction] (";
for (auto& parameter : node->parameters) {
Visit(parameter.get());
info::type::FunctionType type;
// for (auto& parameter : node->parameters) {
// Visit(parameter.get());
// }
type.argument_types.reserve(node->argument_graph_ids_.size());
for (auto& argument_graph_id : node->argument_graph_ids_) {
type.argument_types.push_back(context_manager_.AddType(info::type::AbstractType {argument_graph_id}));
}
if (!node->parameters.empty()) {
out_ << ") : (";
}
for (auto& argument : node->arguments) {
Visit(&argument);
}
out_ << ") -> (\n";
type.return_type = context_manager_.AddType(info::type::AbstractType {node->return_type_graph_id_});
Visitor::Visit(node->expression);
out_ << ")\n";
context_manager_.AddTypeRequirement(type.return_type, current_type_); // right order ??
current_type_ = context_manager_.AddType(std::move(type));
}
void TypeCheckVisitor::Visit(ArrayExpression* node) {
out_ << "[ArrayExpression] ([";
for (auto& element : node->elements) {
Visitor::Visit(element);
out_ << ';';
info::type::ArrayType type;
type.size = node->elements.size();
for (size_t i = 0; i < node->elements.size(); ++i) {
Visitor::Visit(node->elements[i]);
if (i == 0) {
type.elements_type = current_type_;
} else {
context_manager_.EqualTypes(type.elements_type.value(), current_type_);
}
}
out_ << "])";
current_type_ = context_manager_.AddType(std::move(type));
}
// Name
void TypeCheckVisitor::Visit(NameExpression* node) {
out_ << "[NameExpression] (";
for (auto& variable_namespace : node->namespaces) {
Visitor::Visit(variable_namespace);
out_ << '.';
}
for (size_t i = 0; i < node->expressions.size(); ++i) {
Visitor::Visit(node->expressions[i]);
if (i + 1 < node->expressions.size()) {
out_ << '.';
// -------------------------- TODO --------------------------
void TypeCheckVisitor::Visit(NameExpression* node) { // TODO: ?? functions without arguments ??
std::vector<std::string> path;
std::string type_name;
path.reserve(node->namespaces.size());
for (size_t i = 0; i < node->namespaces.size(); ++i) {
std::string current_name;
if (std::holds_alternative<std::unique_ptr<std::string>>(node->namespaces[i])) {
current_name = *std::get<std::unique_ptr<std::string>>(node->namespaces[i]);
} else if (std::holds_alternative<std::unique_ptr<ParametrizedType>>(node->namespaces[i])) {
Visit(std::get<std::unique_ptr<ParametrizedType>>(node->namespaces[i]).get());
// TODO: use current_type_
}
if (i + 1 == node->namespaces.size()) {
type_name = std::move(current_name);
} else {
path.push_back(std::move(current_name));
}
}
out_ << ')';
// auto name_type = namespace_visitor_.FindType();
path.push_back(type_name);
auto name_namespace = namespace_visitor_.FindNamespace(path);
for (size_t i = 0; i < node->expressions.size(); ++i) {
// Visitor::Visit(node->expressions[i]);
}
}
void TypeCheckVisitor::Visit(TupleName* node) {
utils::IdType type = current_type_;
auto type_value = std::get_if<info::type::TupleType>(context_manager_.GetType(type));
if (type_value = nullptr) {
if (!std::holds_alternative<info::type::TupleType>(context_manager_.GetType(type))) {
error_handling::HandleTypecheckError("Mismatched types in tuple variable definition");
}
if (type_value->constructors.size() != node->names.size()) {
info::type::TupleType type_value = std::get<info::type::TupleType>(context_manager_.GetType(type));
if (type_value.fields.size() != node->names.size()) {
error_handling::HandleTypecheckError("Mismatched field count in tuple variable definition");
}
for (auto& name : node->names) {
current_type_ = type_value->fields[i];
Visitor::Visit(name);
for (size_t i = 0; i < node->names.size(); ++i) {
current_type_ = type_value.fields[i].second;
Visitor::Visit(node->names[i]);
}
current_type_ = type;
}
void TypeCheckVisitor::Visit(VariantName* node) { // TODO
void TypeCheckVisitor::Visit(VariantName* node) {
utils::IdType type = current_type_;
auto type_value = std::get_if<info::type::VariantType>(context_manager_.GetType(type));
if (type_value = nullptr) {
if (!std::holds_alternative<info::type::VariantType>(context_manager_.GetType(type))) {
error_handling::HandleTypecheckError("Mismatched types in variant variable definition");
}
if (type_value->constructors.size() != node->names.size()) {
info::type::VariantType type_value = std::get<info::type::VariantType>(context_manager_.GetType(type));
if (type_value.constructors.size() != node->names.size()) {
error_handling::HandleTypecheckError("Mismatched variant count in variant variable definition");
}
for (size_t i = 0; i < node->names.size(); ++i) {
current_type_ = info::type::VariantType::MakeOptional(type_value->constructors[i]);
Visitor::Visit(name);
if (std::holds_alternative<std::string>(type_value.constructors[i])) {
current_type_ = context_manager_.AddType(info::type::OptionalType {});
} else if (std::holds_alternative<info::type::TupleType>(type_value.constructors[i])) {
// TODO: optimize
current_type_ = context_manager_.AddType(info::type::OptionalType { context_manager_.AddType(std::get<info::type::TupleType>(type_value.constructors[i])) });
} else {
// error
}
Visitor::Visit(node->names[i]);
}
current_type_ = type;
@ -428,9 +594,9 @@ void TypeCheckVisitor::Visit(AnnotatedName* node) {
void TypeCheckVisitor::Visit(FunctionType* node) {
info::type::FunctionType type;
type.argument_type_ids.reserve(node->types.size());
for (auto& type : node->types) {
Visitor::Visit(type);
type.argument_types.reserve(node->types.size());
for (auto& argument_type : node->types) {
Visitor::Visit(argument_type);
type.argument_types.push_back(current_type_);
}
@ -474,8 +640,7 @@ void TypeCheckVisitor::Visit(VariantType* node) {
void TypeCheckVisitor::Visit(ParametrizedType* node) {
info::type::DefinedType type;
Visit(node->type_expression.get());
type.type = current_type_;
type.type_id = node->type_expression->type_id_;
type.paramaters.reserve(node->parameters.size());
for (auto& paramater : node->parameters) {

View file

@ -319,4 +319,363 @@ void Visitor::Visit(Literal& node) {
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Sources -----------------
void Visitor::Visit(SourceFile* node) {
for (auto& statement : node->statements) {
if (std::holds_alternative<Partition>(statement)) {
Visit(&std::get<Partition>(statement));
} else if (std::holds_alternative<SourceStatement>(statement)) {
Visit(std::get<SourceStatement>(statement));
} else {
// error
}
}
}
void Visitor::Visit(Sources* node) {
for (auto& statement : node->statements) {
Visit(statement);
}
}
// Namespaces, partitions -----------------
void Visitor::Visit(Partition* node) {
Visit(node->scope.get());
}
void Visitor::Visit(Namespace* node) {
if (node->name.has_value()) {
Visit(&node->name.value());
}
Visit(&node->type);
Visit(node->scope.get());
}
// Definitions -----------------
void Visitor::Visit(ImportStatement* node) {
for (auto& symbol : node->symbols) {
Visit(&symbol);
}
}
void Visitor::Visit(AliasDefinitionStatement* node) {
Visit(&node->type);
Visit(node->value.get());
}
void Visitor::Visit(VariableDefinitionStatement* node) {
Visit(node->name);
Visit(node->value);
}
void Visitor::Visit(FunctionDeclaration* node) {
Visit(&node->name);
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
Visit(node->type.get());
}
void Visitor::Visit(FunctionDefinitionStatement* node) {
Visit(node->definition.get());
Visit(node->value);
}
void Visitor::Visit(TypeDefinitionStatement* node) {
Visit(node->definition.get());
Visit(node->value);
}
void Visitor::Visit(AbstractTypeDefinitionStatement* node) {
Visit(node->type.get());
}
void Visitor::Visit(TypeclassDefinitionStatement* node) {
Visit(node->definition.get());
for (auto& requirement : node->requirements) {
Visit(requirement.get());
}
}
// Definition parts
void Visitor::Visit(FunctionDefinition* node) {
Visit(&node->name);
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
for (auto& argument : node->arguments) {
Visit(&argument);
}
}
void Visitor::Visit(TypeDefinition* node) {
Visit(node->type.get());
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
}
void Visitor::Visit(AnyAnnotatedType* node) {
Visit(&node->type);
for (auto& typeclass : node->typeclasses) {
Visit(typeclass);
}
}
// Flow control -----------------
void Visitor::Visit(MatchCase* node) {
Visit(node->value);
if (node->condition.has_value()) {
Visit(node->condition.value());
}
if (node->statement.has_value()) {
Visit(node->statement.value());
}
}
void Visitor::Visit(Match* node) {
Visit(node->value);
for (auto& match_case : node->matches) {
Visit(&match_case);
}
}
void Visitor::Visit(Condition* node) {
for (size_t i = 0; i < node->conditions.size(); ++i) {
Visit(node->conditions[i]);
Visit(node->statements[i]);
}
if (node->statements.size() > node->conditions.size()) {
Visit(node->statements[node->conditions.size()]);
}
}
void Visitor::Visit(DoWhileLoop* node) {
Visit(node->statement);
Visit(node->condition);
}
void Visitor::Visit(WhileLoop* node) {
Visit(node->condition);
Visit(node->statement);
}
void Visitor::Visit(ForLoop* node) {
Visit(node->variable);
Visit(node->interval);
Visit(node->statement);
}
void Visitor::Visit(LoopLoop* node) {
Visit(node->statement);
}
// Statements, expressions, blocks, etc. -----------------
void Visitor::Visit(Block* node) {
for (auto& statement : node->statements) {
Visit(statement);
}
}
void Visitor::Visit(ScopedStatement* node) {
Visit(node->statement);
}
void Visitor::Visit(LoopControlExpression& node) {} // enum
// Operators
void Visitor::Visit(BinaryOperatorExpression* node) {
Visit(node->left_expression);
Visit(&node->operator_name);
Visit(node->right_expression);
}
void Visitor::Visit(UnaryOperatorExpression* node) {
Visit(&node->operator_name);
Visit(node->expression);
}
void Visitor::Visit(ReferenceExpression* node) {
Visit(node->expression.get());
}
void Visitor::Visit(AccessExpression* node) {
Visit(node->name.get());
Visit(node->id);
}
// Other Expressions
void Visitor::Visit(FunctionCallExpression* node) {
Visit(node->name.get());
for (auto& argument : node->arguments) {
Visit(argument);
}
}
void Visitor::Visit(TupleExpression* node) {
for (auto& expression : node->expressions) {
Visit(expression);
}
}
void Visitor::Visit(VariantExpression* node) {
for (auto& expression : node->expressions) {
Visit(expression);
}
}
void Visitor::Visit(ReturnExpression* node) {
Visit(node->expression);
}
void Visitor::Visit(TypeConstructor* node) {
Visit(node->type.get());
for (auto& parameter : node->parameters) {
Visit(&std::get<0>(parameter));
Visit(std::get<2>(parameter));
}
}
void Visitor::Visit(LambdaFunction* node) {
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
for (auto& argument : node->arguments) {
Visit(&argument);
}
Visit(node->expression);
}
void Visitor::Visit(ArrayExpression* node) {
for (auto& element : node->elements) {
Visit(element);
}
}
// Name
void Visitor::Visit(NameExpression* node) {
for (auto& variable_namespace : node->namespaces) {
Visit(variable_namespace);
}
for (size_t i = 0; i < node->expressions.size(); ++i) {
Visit(&node->expressions[i]);
}
}
void Visitor::Visit(TupleName* node) {
for (auto& name : node->names) {
Visit(name);
}
}
void Visitor::Visit(VariantName* node) {
for (auto& name : node->names) {
Visit(name);
}
}
void Visitor::Visit(AnnotatedName* node) {
Visit(&node->name);
if (node->type.has_value()) {
Visitor::Visit(node->type.value());
}
}
// Type, typeclass, etc. -----------------
// Type
void Visitor::Visit(FunctionType* node) {
for (auto& type : node->types) {
Visitor::Visit(type);
}
}
void Visitor::Visit(TupleType* node) {
if (node->type.has_value()) {
Visit(&node->type.value());
}
for (auto& entity : node->entities) {
if (entity.first.has_value()) {
Visit(&entity.first.value());
}
Visit(entity.second.get());
}
}
void Visitor::Visit(VariantType* node) {
if (node->type.has_value()) {
Visit(&node->type.value());
}
for (auto& constructor : node->constructors) {
if (std::holds_alternative<Constructor>(constructor)) {
Visit(&std::get<Constructor>(constructor));
} else if (std::holds_alternative<std::unique_ptr<TupleType>>(constructor)) {
Visit(std::get<std::unique_ptr<TupleType>>(constructor).get());
} else {
// error
}
}
}
void Visitor::Visit(ParametrizedType* node) {
Visit(node->type_expression.get());
for (auto& parameter : node->parameters) {
Visit(parameter);
}
}
void Visitor::Visit(TypeExpression* node) {
for (auto& type_namespace : node->namespaces) {
Visit(type_namespace);
}
Visit(&node->type);
}
void Visitor::Visit(ExtendedScopedAnyType* node) {
Visit(node->type);
}
// Typeclass
void Visitor::Visit(ParametrizedTypeclass* node) {
Visit(node->typeclass_expression.get());
for (auto& parameter : node->parameters) {
Visit(parameter);
}
}
void Visitor::Visit(TypeclassExpression* node) {
for (auto& typeclass_namespace : node->namespaces) {
Visit(typeclass_namespace);
}
Visit(&node->typeclass);
}
// Identifiers, constants, etc. -----------------
void Visitor::Visit(ExtendedName* node) {}
void Visitor::Visit(std::string* node) {} // std::string
void Visitor::Visit(FloatNumberLiteral* node) {}
void Visitor::Visit(NumberLiteral* node) {}
void Visitor::Visit(StringLiteral* node) {}
void Visitor::Visit(CharLiteral* node) {}
} // namespace interpreter