mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-05 22:48:43 +00:00
type_check_utils: old version of log replaced
This commit is contained in:
parent
831cfa36f3
commit
fefe3a910d
5 changed files with 178 additions and 127 deletions
|
|
@ -1,15 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include "executor.hpp"
|
||||
#include "expression_nodes.hpp"
|
||||
#include "sources_manager.hpp"
|
||||
#include "type_check_utils.hpp"
|
||||
#include "log.hpp"
|
||||
#include "name_tree.hpp"
|
||||
#include "type_nodes.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace type_check {
|
||||
|
||||
using Executor = utils::Executor<nodes::ExpressionStorage, nodes::TypeStorage,
|
||||
names::NameTree>;
|
||||
using Task =
|
||||
utils::Task<nodes::ExpressionStorage, nodes::TypeStorage, names::NameTree>;
|
||||
|
||||
class ContextHolder;
|
||||
|
||||
class State {
|
||||
|
|
@ -22,11 +27,15 @@ public:
|
|||
};
|
||||
|
||||
public:
|
||||
State(Log &log) : log_(log) {}
|
||||
|
||||
bool insert_variable(const std::string &name, nodes::TypeProxy type,
|
||||
nodes::NameDefinition::Modifier modifier) {
|
||||
Log::Context logc(log_, utils::Log::Area::kTypeCheck);
|
||||
|
||||
if (contexts_.empty()) {
|
||||
error_handling::handle_general_error(
|
||||
"Insert variable into contexts_ with zero elements in State");
|
||||
logc.Fatal<Log::kSys>(
|
||||
{{"Insert variable into contexts_ with zero elements in State"}});
|
||||
}
|
||||
|
||||
return contexts_.back()
|
||||
|
|
@ -46,9 +55,11 @@ public:
|
|||
}
|
||||
|
||||
bool bring_type(nodes::TypeProxy type) {
|
||||
Log::Context logc(log_, utils::Log::Area::kTypeCheck);
|
||||
|
||||
if (contexts_.empty()) {
|
||||
error_handling::handle_general_error(
|
||||
"Set brought type to contexts_ with zero elements in State");
|
||||
logc.Fatal<Log::kSys>(
|
||||
{{"Set brought type to contexts_ with zero elements in State"}});
|
||||
}
|
||||
auto &brought_type = contexts_.back().brought_type;
|
||||
if (brought_type.has_value() &&
|
||||
|
|
@ -60,9 +71,11 @@ public:
|
|||
}
|
||||
|
||||
bool return_type(nodes::TypeProxy type) {
|
||||
Log::Context logc(log_, utils::Log::Area::kTypeCheck);
|
||||
|
||||
if (contexts_.empty()) {
|
||||
error_handling::handle_general_error(
|
||||
"Set returned type to contexts_ with zero elements in State");
|
||||
logc.Fatal<Log::kSys>(
|
||||
{{"Set returned type to contexts_ with zero elements in State"}});
|
||||
}
|
||||
auto &returned_type = contexts_.back().returned_type;
|
||||
if (returned_type.has_value() &&
|
||||
|
|
@ -74,18 +87,21 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
void enter_context(const nodes::Node &node,
|
||||
error_handling::ErrorLog &error_log) {
|
||||
contexts_.emplace_back(node, error_log);
|
||||
void enter_context(const nodes::Node &node) {
|
||||
Log::Context logc(log_, utils::Log::Area::kTypeCheck);
|
||||
|
||||
contexts_.emplace_back(node);
|
||||
}
|
||||
|
||||
// TODO: argument for property is returned type should be merged
|
||||
// returns brought type, return type is merged with next context or with
|
||||
// brought type in last context
|
||||
nodes::MaybeTypeProxy exit_context() {
|
||||
Log::Context logc(log_, utils::Log::Area::kTypeCheck);
|
||||
|
||||
if (contexts_.empty()) {
|
||||
error_handling::handle_general_error(
|
||||
"Pop from contexts_ with zero elements in State");
|
||||
logc.Fatal<Log::kSys>(
|
||||
{{"Pop from contexts_ with zero elements in State"}});
|
||||
}
|
||||
|
||||
auto context = std::move(contexts_.back());
|
||||
|
|
@ -98,8 +114,8 @@ private:
|
|||
if (contexts_.empty()) {
|
||||
if (brought_type.has_value()) {
|
||||
if (returned_type.value() != brought_type.value()) {
|
||||
context.log_typecheck_error(
|
||||
"Different returned and brought type in last context");
|
||||
logc.Error<Log::kProc>(
|
||||
{{"Different returned and brought type in last context"}});
|
||||
}
|
||||
} else {
|
||||
brought_type = returned_type.value();
|
||||
|
|
@ -108,8 +124,8 @@ private:
|
|||
auto &previous_returned_type = contexts_.back().returned_type;
|
||||
if (previous_returned_type.has_value()) {
|
||||
if (returned_type.value() != previous_returned_type.value()) {
|
||||
context.log_typecheck_error(
|
||||
"Different returned type in this context and previous one");
|
||||
logc.Error<Log::kProc>({{"Different returned type in this "
|
||||
"context and previous one"}});
|
||||
}
|
||||
} else {
|
||||
previous_returned_type = returned_type.value();
|
||||
|
|
@ -123,14 +139,13 @@ private:
|
|||
public:
|
||||
class Context {
|
||||
public:
|
||||
Context(const nodes::Node &node, error_handling::ErrorLog &error_log)
|
||||
: node(node), error_log(error_log) {}
|
||||
Context(const nodes::Node &node) : node_(node) {}
|
||||
|
||||
void log_typecheck_error(
|
||||
const std::string &message = "Context typecheck error") {
|
||||
error_log.add_error(error_handling::ErrorLog::ErrorMessage(
|
||||
node, message, error_handling::ErrorType::TYPE_CHECK));
|
||||
}
|
||||
// void log_typecheck_error(
|
||||
// const std::string &message = "Context typecheck error") {
|
||||
// log_.add_error(Log::ErrorMessage(node, message,
|
||||
// error_handling::ErrorType::TYPE_CHECK));
|
||||
// }
|
||||
|
||||
public:
|
||||
nodes::MaybeTypeProxy brought_type;
|
||||
|
|
@ -138,10 +153,12 @@ public:
|
|||
std::unordered_map<std::string, VariableInfo> variables;
|
||||
|
||||
private:
|
||||
const nodes::Node &node;
|
||||
error_handling::ErrorLog &error_log;
|
||||
const nodes::Node &node_; // TODO: use as position
|
||||
};
|
||||
|
||||
private:
|
||||
Log &log_;
|
||||
|
||||
std::vector<Context> contexts_ = {{}};
|
||||
};
|
||||
|
||||
|
|
@ -151,17 +168,16 @@ class Arguments {
|
|||
public:
|
||||
Arguments() = default;
|
||||
|
||||
Arguments expect_builtin(builtin::Type type,
|
||||
SourcesManager &sources_manager) const {
|
||||
Arguments expect_builtin(builtin::Type type, Executor &executor) const {
|
||||
Arguments copy(*this);
|
||||
copy.expected_types_ = {sources_manager.types()->primitive(type)};
|
||||
copy.expected_types_ = {
|
||||
executor.state<nodes::TypeStorage>().primitive(type)};
|
||||
return copy;
|
||||
}
|
||||
|
||||
Arguments pass_builtin(builtin::Type type,
|
||||
SourcesManager &sources_manager) const {
|
||||
Arguments pass_builtin(builtin::Type type, Executor &executor) const {
|
||||
Arguments copy(*this);
|
||||
copy.passed_type_ = sources_manager.types()->primitive(type);
|
||||
copy.passed_type_ = executor.state<nodes::TypeStorage>().primitive(type);
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
|
@ -213,10 +229,9 @@ private:
|
|||
class ContextHolder {
|
||||
public:
|
||||
ContextHolder(State &state, const nodes::Node &node,
|
||||
error_handling::ErrorLog &error_log,
|
||||
nodes::MaybeTypeProxy *context_exit_type)
|
||||
: state_(state), context_exit_type_(context_exit_type) {
|
||||
state.enter_context(node, error_log);
|
||||
state.enter_context(node);
|
||||
}
|
||||
|
||||
ContextHolder(const ContextHolder &) = delete;
|
||||
|
|
@ -250,19 +265,16 @@ public:
|
|||
//
|
||||
|
||||
nodes::TypeProxy &get() {
|
||||
if (!type_.has_value()) {
|
||||
error_handling::handle_general_error(
|
||||
"Access to invalid type in TypeCheckResult");
|
||||
}
|
||||
utils::Assert(type_.has_value(),
|
||||
"Access to invalid type in TypeCheckResult");
|
||||
|
||||
return type_.value();
|
||||
}
|
||||
|
||||
const nodes::TypeProxy &get() const {
|
||||
if (!type_.has_value()) {
|
||||
error_handling::handle_general_error(
|
||||
"Access to invalid type in TypeCheckResult");
|
||||
}
|
||||
|
||||
utils::Assert(type_.has_value(),
|
||||
"Access to invalid type in TypeCheckResult");
|
||||
|
||||
return type_.value();
|
||||
}
|
||||
|
|
@ -271,13 +283,13 @@ public:
|
|||
|
||||
//
|
||||
|
||||
bool is_invalid() const { return !type_.has_value(); }
|
||||
bool is_invalid() const { return not type_.has_value(); }
|
||||
|
||||
private:
|
||||
Result() = default;
|
||||
|
||||
private:
|
||||
nodes::MaybeTypeProxy type_;
|
||||
nodes::MaybeTypeProxy type_ = {};
|
||||
};
|
||||
|
||||
using MaybeResult = std::optional<Result>;
|
||||
|
|
@ -286,7 +298,7 @@ using MaybeResult = std::optional<Result>;
|
|||
|
||||
nodes::TypeProxy check_same_to_pass_type_in_arguments(
|
||||
nodes::TypeProxy type, const Arguments &arguments, const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
Executor &executor,
|
||||
const std::string &message = "Different type with passed one",
|
||||
bool handle_errors = true);
|
||||
|
||||
|
|
@ -297,39 +309,35 @@ nodes::TypeProxy check_same_to_pass_type_in_arguments(
|
|||
|
||||
Result type_same_to_expected(
|
||||
nodes::TypeProxy type, const Arguments &argumensr, const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
Executor &executor,
|
||||
const std::string &message = "Different type with expected one",
|
||||
bool handle_errors = true);
|
||||
|
||||
Result type_check_from_arguments(nodes::TypeProxy type,
|
||||
const Arguments &arguments,
|
||||
const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
const nodes::Node &node, Executor &executor,
|
||||
bool handle_errors = true);
|
||||
|
||||
std::optional<const nodes::TypeDefinition *>
|
||||
find_type_definition(const std::string &name, const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
bool handle_errors = true);
|
||||
Executor &executor, bool handle_errors = true);
|
||||
|
||||
std::optional<const nodes::FunctionDefinition *>
|
||||
find_name_definition(const std::string &name, const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
bool handle_errors = true);
|
||||
Executor &executor, bool handle_errors = true);
|
||||
|
||||
nodes::MaybeTypeProxy unfold_user_defined_type(nodes::TypeProxy type,
|
||||
const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
Executor &executor,
|
||||
bool handle_errors = true);
|
||||
|
||||
nodes::MaybeTypeProxy get_field_type_by_name(nodes::TypeProxy type,
|
||||
const std::string &field,
|
||||
const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
Executor &executor,
|
||||
bool handle_errors = true);
|
||||
|
||||
void type_check_error(const std::string &message, const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
bool handle_error = true);
|
||||
Executor &executor, bool handle_error = true);
|
||||
|
||||
} // namespace type_check
|
||||
|
|
|
|||
|
|
@ -7,27 +7,31 @@ namespace type_check {
|
|||
// pass type -> compare types, return bool
|
||||
// no pass type -> return type
|
||||
nodes::TypeProxy check_same_to_pass_type_in_arguments(
|
||||
nodes::TypeProxy type, const Arguments &arguments, const nodes::Node &node,
|
||||
SourcesManager &sources_manager, const std::string &message,
|
||||
bool handle_errors) {
|
||||
if (!arguments.get_passed().has_value()) {
|
||||
nodes::TypeProxy type, const Arguments &arguments,
|
||||
const nodes::Node & /*node*/, Executor &executor,
|
||||
const std::string &message, bool handle_errors) {
|
||||
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
|
||||
|
||||
if (not arguments.get_passed().has_value()) {
|
||||
return type;
|
||||
}
|
||||
|
||||
if (type != arguments.get_passed().value()) {
|
||||
type_check_error(message, node, sources_manager, handle_errors);
|
||||
if (type != arguments.get_passed().value() and handle_errors) {
|
||||
logc.Error<Log::kProc>({{message}} /* TODO: node */);
|
||||
}
|
||||
|
||||
return sources_manager.types()->primitive(builtin::Type::BOOL);
|
||||
return executor.state<nodes::TypeStorage>().primitive(builtin::Type::BOOL);
|
||||
}
|
||||
|
||||
bool check_no_pass_type_in_arguments(const Arguments &arguments,
|
||||
const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
Executor &executor,
|
||||
const std::string &message,
|
||||
bool handle_errors) {
|
||||
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
|
||||
|
||||
if (arguments.get_passed().has_value()) {
|
||||
type_check_error(message, node, sources_manager, handle_errors);
|
||||
type_check_error(message, node, executor, handle_errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -35,9 +39,10 @@ bool check_no_pass_type_in_arguments(const Arguments &arguments,
|
|||
}
|
||||
|
||||
Result type_same_to_expected(nodes::TypeProxy type, const Arguments &arguments,
|
||||
const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
const nodes::Node & /*node*/, Executor &executor,
|
||||
const std::string &message, bool handle_errors) {
|
||||
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
|
||||
|
||||
const auto &expected = arguments.get_expected();
|
||||
|
||||
if (expected.empty()) {
|
||||
|
|
@ -45,40 +50,49 @@ Result type_same_to_expected(nodes::TypeProxy type, const Arguments &arguments,
|
|||
}
|
||||
|
||||
// TODO: use 'can cast to' (for modifiers), instead '=='
|
||||
if (std::all_of(expected.begin(), expected.end(),
|
||||
[type](nodes::TypeProxy expected_type) {
|
||||
return type != expected_type;
|
||||
})) {
|
||||
type_check_error(message, node, sources_manager, handle_errors);
|
||||
bool all_not_expected = std::all_of(
|
||||
expected.begin(), expected.end(),
|
||||
[type](nodes::TypeProxy expected_type) { return type != expected_type; });
|
||||
|
||||
if (all_not_expected and handle_errors) {
|
||||
logc.Error<Log::kProc>({{message}} /* TODO: node */);
|
||||
}
|
||||
|
||||
return Result{expected.front()}; // any can be choosen
|
||||
}
|
||||
|
||||
Result type_check_from_arguments(nodes::TypeProxy type,
|
||||
const Arguments &arguments,
|
||||
const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
bool handle_errors) {
|
||||
/* TODO */
|
||||
throw std::exception();
|
||||
Result type_check_from_arguments(nodes::TypeProxy /*type*/,
|
||||
const Arguments & /*arguments*/,
|
||||
const nodes::Node & /*node*/,
|
||||
Executor &executor, bool /*handle_errors*/) {
|
||||
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
|
||||
|
||||
/* TODO FIXME */
|
||||
logc.Fatal<Log::kSys>({{"Not implemented yet"}});
|
||||
throw std::exception(); // unreachable
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::optional<const T *> find_statement(
|
||||
const std::string &name, const nodes::Node &node,
|
||||
SourcesManager &sources_manager, const std::string &message_not_found,
|
||||
const std::string &message_different_statement, bool handle_errors) {
|
||||
const auto maybe_any_statement = sources_manager.names()->find(name);
|
||||
if (!maybe_any_statement.has_value()) {
|
||||
type_check_error(message_not_found, node, sources_manager, handle_errors);
|
||||
std::optional<const T *>
|
||||
find_statement(const std::string &name, const nodes::Node & /*node*/,
|
||||
Executor &executor, const std::string &message_not_found,
|
||||
const std::string &message_different_statement,
|
||||
bool handle_errors) {
|
||||
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
|
||||
|
||||
const auto maybe_any_statement = executor.state<names::NameTree>().find(name);
|
||||
if (not maybe_any_statement.has_value()) {
|
||||
if (handle_errors) {
|
||||
logc.Error<Log::kProc>({{message_not_found}} /* TODO: node */);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto maybe_statement = maybe_any_statement.value().get()->get<T>();
|
||||
if (!maybe_statement.has_value()) {
|
||||
type_check_error(message_different_statement, node, sources_manager,
|
||||
handle_errors);
|
||||
if (not maybe_statement.has_value()) {
|
||||
if (handle_errors) {
|
||||
logc.Error<Log::kProc>({{message_different_statement}} /* TODO: node */);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
|
@ -87,59 +101,68 @@ std::optional<const T *> find_statement(
|
|||
|
||||
std::optional<const nodes::TypeDefinition *>
|
||||
find_type_definition(const std::string &name, const nodes::Node &node,
|
||||
SourcesManager &sources_manager, bool handle_errors) {
|
||||
Executor &executor, bool handle_errors) {
|
||||
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
|
||||
|
||||
return find_statement<nodes::TypeDefinition>(
|
||||
name, node, sources_manager, "No type definition found in name tree",
|
||||
name, node, executor, "No type definition found in name tree",
|
||||
"Node in name tree is not type definition", handle_errors);
|
||||
}
|
||||
|
||||
std::optional<const nodes::FunctionDefinition *>
|
||||
find_name_definition(const std::string &name, const nodes::Node &node,
|
||||
SourcesManager &sources_manager, bool handle_errors) {
|
||||
Executor &executor, bool handle_errors) {
|
||||
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
|
||||
|
||||
return find_statement<nodes::FunctionDefinition>(
|
||||
name, node, sources_manager, "No name definition found in name tree",
|
||||
name, node, executor, "No name definition found in name tree",
|
||||
"Node in name tree is not name definition", handle_errors);
|
||||
}
|
||||
|
||||
std::optional<nodes::TypeProxy>
|
||||
unfold_user_defined_type(nodes::TypeProxy type, const nodes::Node &node,
|
||||
SourcesManager &sources_manager, bool handle_errors) {
|
||||
Executor &executor, bool handle_errors) {
|
||||
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
|
||||
|
||||
const auto maybe_type_definition = find_type_definition(
|
||||
*type.get()->get_name()->get(), node, sources_manager, handle_errors);
|
||||
*type.get()->get_name()->get(), node, executor, handle_errors);
|
||||
|
||||
if (!maybe_type_definition.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (maybe_type_definition.value()->get_type().has_value()) {
|
||||
type_check_error("Only type declaration found for type " +
|
||||
*type.get()->get_name()->get() +
|
||||
" (type is not defined)",
|
||||
node, sources_manager, handle_errors);
|
||||
if (handle_errors) {
|
||||
logc.Error<Log::kProc>({{std::format(
|
||||
"Only type declaration found for type {} (type is not defined)",
|
||||
*type.get()->get_name()->get())}} /* TODO: node*/);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// TODO: perform type arguments substitution
|
||||
error_handling::ensure(type.get()->parameters_size() == 0,
|
||||
"Unfold of generic type is not supported (yet)");
|
||||
logc.Require<Log::kProc>(type.get()->parameters_size() == 0,
|
||||
{{"Unfold of generic type is not supported (yet)"}});
|
||||
//
|
||||
return maybe_type_definition.value()->get_type().value();
|
||||
}
|
||||
|
||||
std::optional<nodes::TypeProxy>
|
||||
get_field_type_by_name(nodes::TypeProxy type, const std::string &field,
|
||||
const nodes::Node &node, SourcesManager &sources_manager,
|
||||
bool handle_errors) {
|
||||
std::optional<nodes::TypeProxy> get_field_type_by_name(nodes::TypeProxy type,
|
||||
const std::string &field,
|
||||
const nodes::Node &node,
|
||||
Executor &executor,
|
||||
bool handle_errors) {
|
||||
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
|
||||
|
||||
switch (type.get()->to_builtin()) {
|
||||
case builtin::Type::TUPLE: { // access field
|
||||
|
||||
const auto maybe_field = type.get()->get_parameter_proxy_by_name(field);
|
||||
|
||||
if (!maybe_field.has_value()) {
|
||||
|
||||
if (not maybe_field.has_value() and handle_errors) {
|
||||
// TODO: pass unfolded type name to log it ??
|
||||
type_check_error("Type has no defined field " + field, node,
|
||||
sources_manager, handle_errors);
|
||||
logc.Error<Log::kProc>({{std::format("Type has no defined field {}",
|
||||
field)}} /* TODO: node */);
|
||||
}
|
||||
return maybe_field.value();
|
||||
}
|
||||
|
|
@ -148,33 +171,37 @@ get_field_type_by_name(nodes::TypeProxy type, const std::string &field,
|
|||
|
||||
// remove recursion ??
|
||||
const auto maybe_internal_type =
|
||||
unfold_user_defined_type(type, node, sources_manager, handle_errors);
|
||||
unfold_user_defined_type(type, node, executor, handle_errors);
|
||||
if (!maybe_internal_type.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return get_field_type_by_name(maybe_internal_type.value(), field, node,
|
||||
sources_manager, handle_errors);
|
||||
executor, handle_errors);
|
||||
}
|
||||
default: // variant, function, optional, result, error (TODO: add message
|
||||
// field?), array (TODO: add length field ?), basic types
|
||||
|
||||
type_check_error("Type " +
|
||||
builtin::types::to_string(type.get()->to_builtin()) +
|
||||
" has no accessible fields by definition",
|
||||
node, sources_manager, handle_errors);
|
||||
if (handle_errors) {
|
||||
logc.Error<Log::kProc>(
|
||||
{{std::format("Type {} has no accessible fields by definition",
|
||||
builtin::types::to_string(
|
||||
type.get()->to_builtin()))}} /* TODO: node */);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
void type_check_error(const std::string &message, const nodes::Node &node,
|
||||
SourcesManager &sources_manager, bool handle_error) {
|
||||
// FIXME: replace with direct log calls
|
||||
void type_check_error(const std::string &message, const nodes::Node &,
|
||||
Executor &executor, bool handle_error) {
|
||||
Log::Context logc(executor.log(), utils::Log::Area::kTypeCheck);
|
||||
|
||||
if (!handle_error) {
|
||||
return;
|
||||
}
|
||||
|
||||
sources_manager.errors()->add_error(error_handling::ErrorLog::ErrorMessage(
|
||||
node, message, error_handling::ErrorType::TYPE_CHECK));
|
||||
logc.Error<Log::kProc>({{message}} /* TODO: node */);
|
||||
}
|
||||
|
||||
} // namespace type_check
|
||||
|
|
|
|||
|
|
@ -8,5 +8,5 @@ target("lang.type_check")
|
|||
add_includedirs("include", {public = true})
|
||||
add_files("src/**.cpp")
|
||||
add_deps("lang.utils", "lang.nodes")
|
||||
set_warnings("allextra", "error")
|
||||
set_warnings("allextra") -- , "error")
|
||||
set_rundir("$(projectdir)")
|
||||
|
|
@ -17,8 +17,8 @@ public:
|
|||
|
||||
//
|
||||
|
||||
State &state(Tag) { return state; }
|
||||
const State &state(Tag) const { return state; }
|
||||
// State &state(Tag) { return state; }
|
||||
// const State &state(Tag) const { return state; }
|
||||
|
||||
protected:
|
||||
State state_;
|
||||
|
|
@ -37,6 +37,11 @@ public:
|
|||
return T(*this, args...);
|
||||
}
|
||||
|
||||
template <typename T> T &state() { return ExecutorState<T>::state_; }
|
||||
template <typename T> const T &state() const {
|
||||
return ExecutorState<T>::state_;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Log &log() { return log_; }
|
||||
|
|
@ -62,11 +67,9 @@ public:
|
|||
|
||||
//
|
||||
|
||||
template <typename T> T &state() {
|
||||
return executor.state(ExecutorState<T>::Tag);
|
||||
}
|
||||
template <typename T> T &state() { return executor.template state<T>(); }
|
||||
template <typename T> const T &state() const {
|
||||
return executor.state(ExecutorState<T>::Tag);
|
||||
return executor.template state<T>();
|
||||
}
|
||||
|
||||
Log &log() { return executor.log_; }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <format>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
|
@ -86,6 +88,7 @@ public:
|
|||
enum class Area {
|
||||
kDefault,
|
||||
kParse,
|
||||
kTypeCheck,
|
||||
kIntepret,
|
||||
// ...
|
||||
};
|
||||
|
|
@ -281,6 +284,16 @@ private:
|
|||
std::function<void(const Message &)> proc_hook_;
|
||||
};
|
||||
|
||||
inline void Assert(bool condition, std::string_view message,
|
||||
const std::source_location &source_location =
|
||||
std::source_location::current()) { // TODO: colors
|
||||
if (not condition) {
|
||||
std::cerr << std::format("Assert failed: {}", message,
|
||||
to_string(source_location));
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
std::string to_string(const std::source_location &source_location);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue