mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-10 00:48:45 +00:00
RAII context handling for type check state, type proxy comparasion fixes
This commit is contained in:
parent
f36ff3638b
commit
f03f77191f
4 changed files with 160 additions and 112 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "expression_nodes.hpp"
|
#include "expression_nodes.hpp"
|
||||||
#include "sources_manager.hpp"
|
#include "sources_manager.hpp"
|
||||||
|
#include "type_check_utils.hpp"
|
||||||
#include "type_nodes.hpp"
|
#include "type_nodes.hpp"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
|
|
@ -11,159 +12,77 @@
|
||||||
|
|
||||||
namespace type_check {
|
namespace type_check {
|
||||||
|
|
||||||
// TODO: make context stack o top of RAII
|
|
||||||
class State {
|
|
||||||
public:
|
|
||||||
bool insert_variable(const std::string &name, nodes::TypeProxy type) {
|
|
||||||
if (contexts_.empty()) {
|
|
||||||
error_handling::handle_general_error(
|
|
||||||
"Insert variable into contexts_ with zero elements in State");
|
|
||||||
}
|
|
||||||
|
|
||||||
return contexts_.back().variables.insert({name, type}).second;
|
|
||||||
}
|
|
||||||
|
|
||||||
nodes::MaybeTypeProxy find_variable(const std::string &name) {
|
|
||||||
for (ssize_t i = contexts_.size(); i >= 0; --i) {
|
|
||||||
auto iter = contexts_[i].variables.find(name);
|
|
||||||
if (iter != contexts_[i].variables.end()) {
|
|
||||||
return iter->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void enter_context(const nodes::Node& node) { contexts_.emplace_back(node); }
|
|
||||||
|
|
||||||
// returns brought type, return type is merged with next context or with
|
|
||||||
// brought type in last context
|
|
||||||
nodes::MaybeTypeProxy exit_context() {
|
|
||||||
if (contexts_.empty()) {
|
|
||||||
error_handling::handle_general_error(
|
|
||||||
"Pop from contexts_ with zero elements in State");
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto brought_type = contexts_.back().brought_type;
|
|
||||||
const auto returned_type = contexts_.back().returned_type;
|
|
||||||
contexts_.pop_back();
|
|
||||||
|
|
||||||
if (contexts_.empty()) {
|
|
||||||
// TODO: merge returned and brought types
|
|
||||||
} else {
|
|
||||||
// TODO: merge to previous
|
|
||||||
}
|
|
||||||
|
|
||||||
return brought_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bring_type(nodes::TypeProxy type) {
|
|
||||||
if (contexts_.empty()) {
|
|
||||||
error_handling::handle_general_error(
|
|
||||||
"Set brought type to contexts_ with zero elements in State");
|
|
||||||
}
|
|
||||||
auto &brought_type = contexts_.back().brought_type;
|
|
||||||
if (brought_type.has_value() &&) {
|
|
||||||
// TODO
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
brought_type = type;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool return_type(nodes::TypeProxy type) {
|
|
||||||
if (contexts_.empty()) {
|
|
||||||
error_handling::handle_general_error(
|
|
||||||
"Set returned type to contexts_ with zero elements in State");
|
|
||||||
}
|
|
||||||
auto &returned_type = contexts_.back().returned_type;
|
|
||||||
if (returned_type.has_value() &&) {
|
|
||||||
// TODO
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
returned_type = type;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
class Context {
|
|
||||||
public:
|
|
||||||
Context(const nodes::Node& node) : node(node) {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
nodes::MaybeTypeProxy brought_type;
|
|
||||||
nodes::MaybeTypeProxy returned_type;
|
|
||||||
std::unordered_map<std::string, nodes::TypeProxy> variables;
|
|
||||||
const nodes::Node& node;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<Context> contexts_ = {{}};
|
|
||||||
};
|
|
||||||
|
|
||||||
class Arguments {
|
|
||||||
public:
|
|
||||||
nodes::MaybeTypeProxy expected_type = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
nodes::TypeCheckResult
|
nodes::TypeCheckResult
|
||||||
type_check_expression(const nodes::Expression &expression,
|
type_check_expression(const nodes::Expression &expression,
|
||||||
SourcesManager &sources_manager, State &state, const Arguments& arguments = {});
|
SourcesManager &sources_manager, State &state,
|
||||||
|
const Arguments &arguments = {});
|
||||||
|
|
||||||
// --- flow control
|
// --- flow control
|
||||||
|
|
||||||
nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
||||||
SourcesManager &sources_manager,
|
SourcesManager &sources_manager,
|
||||||
State &state, const Arguments& arguments = {});
|
State &state,
|
||||||
|
const Arguments &arguments = {});
|
||||||
|
|
||||||
nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression,
|
nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression,
|
||||||
SourcesManager &sources_manager,
|
SourcesManager &sources_manager,
|
||||||
State &state, const Arguments& arguments = {});
|
State &state,
|
||||||
|
const Arguments &arguments = {});
|
||||||
|
|
||||||
nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
|
nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
|
||||||
SourcesManager &sources_manager,
|
SourcesManager &sources_manager,
|
||||||
State &state, const Arguments& arguments = {});
|
State &state,
|
||||||
|
const Arguments &arguments = {});
|
||||||
|
|
||||||
// --- containers
|
// --- containers
|
||||||
|
|
||||||
nodes::TypeCheckResult type_check_container(const nodes::Container &expression,
|
nodes::TypeCheckResult type_check_container(const nodes::Container &expression,
|
||||||
SourcesManager &sources_manager,
|
SourcesManager &sources_manager,
|
||||||
State &state, const Arguments& arguments = {});
|
State &state,
|
||||||
|
const Arguments &arguments = {});
|
||||||
|
|
||||||
// --- modifiers
|
// --- modifiers
|
||||||
|
|
||||||
nodes::TypeCheckResult type_check_return(const nodes::Return &expression,
|
nodes::TypeCheckResult type_check_return(const nodes::Return &expression,
|
||||||
SourcesManager &sources_manager,
|
SourcesManager &sources_manager,
|
||||||
State &state, const Arguments& arguments = {});
|
State &state,
|
||||||
|
const Arguments &arguments = {});
|
||||||
|
|
||||||
nodes::TypeCheckResult
|
nodes::TypeCheckResult
|
||||||
type_check_name_definition(const nodes::NameDefinition &expression,
|
type_check_name_definition(const nodes::NameDefinition &expression,
|
||||||
SourcesManager &sources_manager, State &state, const Arguments& arguments = {});
|
SourcesManager &sources_manager, State &state,
|
||||||
|
const Arguments &arguments = {});
|
||||||
|
|
||||||
nodes::TypeCheckResult type_check_access(const nodes::Access &expression,
|
nodes::TypeCheckResult type_check_access(const nodes::Access &expression,
|
||||||
SourcesManager &sources_manager,
|
SourcesManager &sources_manager,
|
||||||
State &state, const Arguments& arguments = {});
|
State &state,
|
||||||
|
const Arguments &arguments = {});
|
||||||
|
|
||||||
nodes::TypeCheckResult
|
nodes::TypeCheckResult
|
||||||
type_check_loop_control(const nodes::LoopControl &expression,
|
type_check_loop_control(const nodes::LoopControl &expression,
|
||||||
SourcesManager &sources_manager, State &state, const Arguments& arguments = {});
|
SourcesManager &sources_manager, State &state,
|
||||||
|
const Arguments &arguments = {});
|
||||||
|
|
||||||
nodes::TypeCheckResult
|
nodes::TypeCheckResult
|
||||||
type_check_modifier_expression(const nodes::ModifierExpression &expression,
|
type_check_modifier_expression(const nodes::ModifierExpression &expression,
|
||||||
SourcesManager &sources_manager, State &state, const Arguments& arguments = {});
|
SourcesManager &sources_manager, State &state,
|
||||||
|
const Arguments &arguments = {});
|
||||||
|
|
||||||
// --- other
|
// --- other
|
||||||
|
|
||||||
nodes::TypeCheckResult
|
nodes::TypeCheckResult
|
||||||
type_check_name_expression(const nodes::NameExpression &expression,
|
type_check_name_expression(const nodes::NameExpression &expression,
|
||||||
SourcesManager &sources_manager, State &state, const Arguments& arguments = {});
|
SourcesManager &sources_manager, State &state,
|
||||||
|
const Arguments &arguments = {});
|
||||||
|
|
||||||
nodes::TypeCheckResult
|
nodes::TypeCheckResult
|
||||||
type_check_constructor(const nodes::Constructor &expression,
|
type_check_constructor(const nodes::Constructor &expression,
|
||||||
SourcesManager &sources_manager, State &state, const Arguments& arguments = {});
|
SourcesManager &sources_manager, State &state,
|
||||||
|
const Arguments &arguments = {});
|
||||||
|
|
||||||
nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
|
nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
|
||||||
SourcesManager &sources_manager,
|
SourcesManager &sources_manager,
|
||||||
State &state, const Arguments& arguments = {});
|
State &state,
|
||||||
|
const Arguments &arguments = {});
|
||||||
|
|
||||||
} // namespace type_check
|
} // namespace type_check
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < parameters_.size(); ++i) {
|
for (size_t i = 0; i < parameters_.size(); ++i) {
|
||||||
if (*parameters_[i].get() != *other.parameters_[i].get()) {
|
if (parameters_[i] != other.parameters_[i]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -161,7 +161,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < parameters_.size(); ++i) {
|
for (size_t i = 0; i < parameters_.size(); ++i) {
|
||||||
if (*parameters_[i].get() != *other.parameters_[i].get()) {
|
if (parameters_[i] != other.parameters_[i]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
130
include/type_check_utils.hpp
Normal file
130
include/type_check_utils.hpp
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "expression_nodes.hpp"
|
||||||
|
#include "sources_manager.hpp"
|
||||||
|
#include "type_check_utils.hpp"
|
||||||
|
#include "type_nodes.hpp"
|
||||||
|
#include "utils.hpp"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace type_check {
|
||||||
|
|
||||||
|
class ContextHolder;
|
||||||
|
|
||||||
|
class State {
|
||||||
|
friend ContextHolder;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool insert_variable(const std::string &name, nodes::TypeProxy type) {
|
||||||
|
if (contexts_.empty()) {
|
||||||
|
error_handling::handle_general_error(
|
||||||
|
"Insert variable into contexts_ with zero elements in State");
|
||||||
|
}
|
||||||
|
|
||||||
|
return contexts_.back().variables.insert({name, type}).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes::MaybeTypeProxy find_variable(const std::string &name) {
|
||||||
|
for (ssize_t i = contexts_.size(); i >= 0; --i) {
|
||||||
|
auto iter = contexts_[i].variables.find(name);
|
||||||
|
if (iter != contexts_[i].variables.end()) {
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bring_type(nodes::TypeProxy type) {
|
||||||
|
if (contexts_.empty()) {
|
||||||
|
error_handling::handle_general_error(
|
||||||
|
"Set brought type to contexts_ with zero elements in State");
|
||||||
|
}
|
||||||
|
auto &brought_type = contexts_.back().brought_type;
|
||||||
|
if (brought_type.has_value() &&) {
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
brought_type = type;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool return_type(nodes::TypeProxy type) {
|
||||||
|
if (contexts_.empty()) {
|
||||||
|
error_handling::handle_general_error(
|
||||||
|
"Set returned type to contexts_ with zero elements in State");
|
||||||
|
}
|
||||||
|
auto &returned_type = contexts_.back().returned_type;
|
||||||
|
if (returned_type.has_value() &&) {
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
returned_type = type;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void enter_context(const nodes::Node &node) { contexts_.emplace_back(node); }
|
||||||
|
|
||||||
|
// returns brought type, return type is merged with next context or with
|
||||||
|
// brought type in last context
|
||||||
|
nodes::MaybeTypeProxy exit_context() {
|
||||||
|
if (contexts_.empty()) {
|
||||||
|
error_handling::handle_general_error(
|
||||||
|
"Pop from contexts_ with zero elements in State");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto brought_type = contexts_.back().brought_type;
|
||||||
|
const auto returned_type = contexts_.back().returned_type;
|
||||||
|
contexts_.pop_back();
|
||||||
|
|
||||||
|
if (contexts_.empty()) {
|
||||||
|
// TODO: merge returned and brought types
|
||||||
|
} else {
|
||||||
|
// TODO: merge to previous
|
||||||
|
}
|
||||||
|
|
||||||
|
return brought_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
class Context {
|
||||||
|
public:
|
||||||
|
Context(const nodes::Node &node) : node(node) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
nodes::MaybeTypeProxy brought_type;
|
||||||
|
nodes::MaybeTypeProxy returned_type;
|
||||||
|
std::unordered_map<std::string, nodes::TypeProxy> variables;
|
||||||
|
const nodes::Node &node;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Context> contexts_ = {{}};
|
||||||
|
};
|
||||||
|
|
||||||
|
class Arguments {
|
||||||
|
public:
|
||||||
|
nodes::MaybeTypeProxy expected_type = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
class ContextHolder {
|
||||||
|
public:
|
||||||
|
ContextHolder(State &state, const nodes::Node &node) : state(state) {
|
||||||
|
state.enter_context(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
ContextHolder(const ContextHolder &) = delete;
|
||||||
|
ContextHolder(ContextHolder &&) = delete;
|
||||||
|
|
||||||
|
ContextHolder &operator=(const ContextHolder &) = delete;
|
||||||
|
ContextHolder &operator=(ContextHolder &&) = delete;
|
||||||
|
|
||||||
|
~ContextHolder() { state.exit_context(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
State &state;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace type_check
|
||||||
|
|
@ -194,8 +194,7 @@ nodes::TypeCheckResult type_check_array(const nodes::Container &expression,
|
||||||
if (!last_expression_result.has_value()) {
|
if (!last_expression_result.has_value()) {
|
||||||
last_expression_result = expression_result;
|
last_expression_result = expression_result;
|
||||||
} else {
|
} else {
|
||||||
if (*last_expression_result.value().get().get() !=
|
if (last_expression_result.value().get() != expression_result.get()) {
|
||||||
*expression_result.get().get()) {
|
|
||||||
sources_manager.get_error_log()->add_error(
|
sources_manager.get_error_log()->add_error(
|
||||||
error_handling::ErrorLog::ErrorMessage(
|
error_handling::ErrorLog::ErrorMessage(
|
||||||
*expression.get_expression(i),
|
*expression.get_expression(i),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue