mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-07 15:38:49 +00:00
utils functions, expect, ensure, error handling refactoring (string -> string_view), std::source_location
This commit is contained in:
parent
5afbaf06ae
commit
d6a3ce1946
7 changed files with 149 additions and 29 deletions
1
.ignore
Normal file
1
.ignore
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
deps/
|
||||||
|
|
@ -8,58 +8,64 @@
|
||||||
|
|
||||||
namespace error_handling {
|
namespace error_handling {
|
||||||
|
|
||||||
inline void print_position(std::ostream &out,
|
inline void handle_internal_error(
|
||||||
std::pair<size_t, size_t> start_position,
|
std::string_view message, const nodes::Node &node,
|
||||||
std::pair<size_t, size_t> end_position) {
|
const std::source_location &location = std::source_location::current()) {
|
||||||
out << '[' << start_position.first + 1 << ", " << start_position.second + 1
|
|
||||||
<< "] - [" << end_position.first + 1 << ", " << end_position.second + 1
|
|
||||||
<< ']';
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void handle_internal_error(const std::string &message,
|
|
||||||
const nodes::Node &node) {
|
|
||||||
std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at ";
|
std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at ";
|
||||||
print_position(std::cerr, node.get_start_position(), node.get_end_position());
|
print_position(std::cerr, node.get_start_position(), node.get_end_position());
|
||||||
std::cerr << ".\n";
|
std::cerr << ".\n";
|
||||||
|
print_source_location(std::cerr, location);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void handle_internal_error(const std::string &message,
|
inline void handle_internal_error(
|
||||||
parser::ParseTree::Node node) {
|
std::string_view message, parser::ParseTree::Node node,
|
||||||
|
const std::source_location &location = std::source_location::current()) {
|
||||||
std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at ";
|
std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at ";
|
||||||
print_position(std::cerr, node.get_start_point(), node.get_end_point());
|
print_position(std::cerr, node.get_start_point(), node.get_end_point());
|
||||||
std::cerr << ".\n";
|
std::cerr << ".\n";
|
||||||
|
print_source_location(std::cerr, location);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void handle_parsing_error(const std::string &message,
|
inline void handle_parsing_error(
|
||||||
parser::ParseTree::Node parse_node) {
|
std::string_view message, parser::ParseTree::Node parse_node,
|
||||||
|
const std::source_location &location = std::source_location::current()) {
|
||||||
std::cerr << "\x1b[1;31mParsing Error:\x1b[0m " << message << " at ";
|
std::cerr << "\x1b[1;31mParsing Error:\x1b[0m " << message << " at ";
|
||||||
print_position(std::cerr, parse_node.get_start_point(),
|
print_position(std::cerr, parse_node.get_start_point(),
|
||||||
parse_node.get_end_point());
|
parse_node.get_end_point());
|
||||||
std::cerr << ".\n";
|
std::cerr << ".\n";
|
||||||
|
print_source_location(std::cerr, location);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void handle_typecheck_error(const std::string &message,
|
inline void handle_typecheck_error(
|
||||||
nodes::Node node) {
|
std::string_view message, nodes::Node node,
|
||||||
|
const std::source_location &location = std::source_location::current()) {
|
||||||
std::cerr << "\x1b[1;31mTypecheck Error:\x1b[0m " << message << " at ";
|
std::cerr << "\x1b[1;31mTypecheck Error:\x1b[0m " << message << " at ";
|
||||||
print_position(std::cerr, node.get_start_position(), node.get_end_position());
|
print_position(std::cerr, node.get_start_position(), node.get_end_position());
|
||||||
std::cerr << ".\n";
|
std::cerr << ".\n";
|
||||||
|
print_source_location(std::cerr, location);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void handle_runtime_error(const std::string &message, nodes::Node node) {
|
inline void handle_runtime_error(
|
||||||
|
std::string_view message, nodes::Node node,
|
||||||
|
const std::source_location &location = std::source_location::current()) {
|
||||||
std::cerr << "\x1b[1;31mRuntime Error:\x1b[0m " << message << " at ";
|
std::cerr << "\x1b[1;31mRuntime Error:\x1b[0m " << message << " at ";
|
||||||
print_position(std::cerr, node.get_start_position(), node.get_end_position());
|
print_position(std::cerr, node.get_start_position(), node.get_end_position());
|
||||||
std::cerr << ".\n";
|
std::cerr << ".\n";
|
||||||
|
print_source_location(std::cerr, location);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void handle_names_error(const std::string &message, nodes::Node node) {
|
inline void handle_names_error(
|
||||||
|
std::string_view message, nodes::Node node,
|
||||||
|
const std::source_location &location = std::source_location::current()) {
|
||||||
std::cerr << "\x1b[1;31mNames Error:\x1b[0m " << message << " at ";
|
std::cerr << "\x1b[1;31mNames Error:\x1b[0m " << message << " at ";
|
||||||
print_position(std::cerr, node.get_start_position(), node.get_end_position());
|
print_position(std::cerr, node.get_start_position(), node.get_end_position());
|
||||||
std::cerr << ".\n";
|
std::cerr << ".\n";
|
||||||
|
print_source_location(std::cerr, location);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <ranges>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace nodes {
|
namespace nodes {
|
||||||
|
|
||||||
|
|
@ -222,6 +225,8 @@ private:
|
||||||
|
|
||||||
class Identifier : public Node {
|
class Identifier : public Node {
|
||||||
public:
|
public:
|
||||||
|
static constexpr char NAME_DELIMITER = '.';
|
||||||
|
|
||||||
enum IdentifierType {
|
enum IdentifierType {
|
||||||
SIMPLE_NAME,
|
SIMPLE_NAME,
|
||||||
SIMPLE_TYPE,
|
SIMPLE_TYPE,
|
||||||
|
|
@ -251,18 +256,51 @@ public:
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
void append_before(const std::string &name) { value_ = name + "." + value_; }
|
void append_before(const std::string &name) {
|
||||||
|
value_ = name + NAME_DELIMITER + value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_before(
|
||||||
|
const Identifier &identifier,
|
||||||
|
std::source_location location = std::source_location::current()) {
|
||||||
|
error_handling::expect(identifier.type_ == type_,
|
||||||
|
"different Identifier types on append_before",
|
||||||
|
location);
|
||||||
|
value_ = *identifier.get() + NAME_DELIMITER + value_;
|
||||||
|
}
|
||||||
|
|
||||||
void append_after(const std::string &name) {
|
void append_after(const std::string &name) {
|
||||||
value_ += "." + name;
|
value_ += NAME_DELIMITER + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_after(
|
||||||
|
const Identifier &identifier,
|
||||||
|
std::source_location location = std::source_location::current()) {
|
||||||
|
error_handling::expect(identifier.type_ == type_,
|
||||||
|
"different Identifier types on append_after",
|
||||||
|
location);
|
||||||
|
value_ += NAME_DELIMITER + *identifier.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Identifier> git_fragments() const {
|
||||||
|
std::vector<Identifier> fragments;
|
||||||
|
for (auto &&fragment_name :
|
||||||
|
std::ranges::views::split(value_, NAME_DELIMITER)) {
|
||||||
|
fragments.emplace_back(
|
||||||
|
*this, type_,
|
||||||
|
std::string(fragment_name.begin(), fragment_name.end()));
|
||||||
|
}
|
||||||
|
return fragments;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Identifier, Identifier> split_first() {
|
std::pair<Identifier, Identifier> split_first() {
|
||||||
const auto pos = value_.find('.');
|
const auto pos = value_.find(NAME_DELIMITER);
|
||||||
if (pos == std::string::npos) {
|
if (pos == std::string::npos) {
|
||||||
return {Identifier(*this, type_, ""), *this};
|
return {Identifier(*this, type_, ""), *this};
|
||||||
}
|
}
|
||||||
return {Identifier(*this, type_, value_.substr(0, pos)), Identifier(*this, type_, value_.substr(pos + 1))}; // '.' is leaved out
|
return {
|
||||||
|
Identifier(*this, type_, value_.substr(0, pos)),
|
||||||
|
Identifier(*this, type_, value_.substr(pos + 1))}; // '.' is leaved out
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include "builtin_types.hpp"
|
#include "builtin_types.hpp"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
@ -75,13 +76,40 @@ public:
|
||||||
|
|
||||||
size_t parameters_size() const { return parameters_.size(); }
|
size_t parameters_size() const { return parameters_.size(); }
|
||||||
|
|
||||||
Type *get_parameter(size_t id) { return parameters_.at(id).get(); }
|
TypeProxy get_parameter_proxy(size_t id) const { return parameters_.at(id); }
|
||||||
|
|
||||||
|
Type *get_parameter(size_t id) { return get_parameter_proxy(id).get(); }
|
||||||
|
|
||||||
const Type *get_parameter(size_t id) const {
|
const Type *get_parameter(size_t id) const {
|
||||||
return parameters_.at(id).get();
|
return get_parameter_proxy(id).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeProxy get_parameter_proxy(size_t id) const { return parameters_.at(id); }
|
// TODO: cache with map ??
|
||||||
|
std::optional<TypeProxy>
|
||||||
|
get_parameter_proxy_by_name(const std::string &name) const {
|
||||||
|
const auto it = std::find_if(
|
||||||
|
parameters_.begin(), parameters_.end(), [&name](const auto ¶meter) {
|
||||||
|
return parameter.get()->has_annotation() &&
|
||||||
|
*parameter.get()->get_annotation().value() == name;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != parameters_.end()) {
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<const Type *>
|
||||||
|
get_parameter_by_name(const std::string &name) const {
|
||||||
|
const auto proxy = get_parameter_proxy_by_name(name);
|
||||||
|
return proxy.has_value() ? proxy.value().get()
|
||||||
|
: std::optional<const Type *>{};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<Type *> get_parameter_by_name(const std::string &name) {
|
||||||
|
auto proxy = get_parameter_proxy_by_name(name);
|
||||||
|
return proxy.has_value() ? proxy.value().get() : std::optional<Type *>{};
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
@ -93,6 +121,8 @@ public:
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
bool has_annotation() const { return annotation_.has_value(); }
|
||||||
|
|
||||||
std::optional<std::string *> get_annotation() {
|
std::optional<std::string *> get_annotation() {
|
||||||
if (annotation_.has_value()) {
|
if (annotation_.has_value()) {
|
||||||
return &annotation_.value();
|
return &annotation_.value();
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,55 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <source_location>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace error_handling {
|
namespace error_handling {
|
||||||
|
|
||||||
inline void handle_general_error(const std::string &message) {
|
inline void print_position(std::ostream &out,
|
||||||
|
std::pair<size_t, size_t> start_position,
|
||||||
|
std::pair<size_t, size_t> end_position) {
|
||||||
|
out << '[' << start_position.first + 1 << ", " << start_position.second + 1
|
||||||
|
<< "] - [" << end_position.first + 1 << ", " << end_position.second + 1
|
||||||
|
<< ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void print_source_location(std::ostream &out,
|
||||||
|
const std::source_location &location) {
|
||||||
|
out << "\x1b[1;33mSOURCE LOCATION:\x1b[0m " << location.file_name() << "("
|
||||||
|
<< location.line() << ":" << location.column() << ") `"
|
||||||
|
<< location.function_name() << "`.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void handle_general_error(std::string_view message) {
|
||||||
std::cerr << "\x1b[1;31mGeneral Error:\x1b[0m " << message << ".\n";
|
std::cerr << "\x1b[1;31mGeneral Error:\x1b[0m " << message << ".\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
expect(bool condition, std::string_view failure_message,
|
||||||
|
const std::source_location &location = std::source_location::current()) {
|
||||||
|
|
||||||
|
if (!condition) {
|
||||||
|
std::cerr << "\x1b[1;33mExpected condition failed (compiler error):\x1b[0m "
|
||||||
|
<< failure_message << ".\n";
|
||||||
|
print_source_location(std::cerr, location);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
ensure(bool condition, std::string_view failure_message,
|
||||||
|
const std::source_location &location = std::source_location::current()) {
|
||||||
|
|
||||||
|
if (!condition) {
|
||||||
|
std::cerr << "\x1b[1;33mEnsured condition failed (compiler error):\x1b[0m "
|
||||||
|
<< failure_message << ".\n";
|
||||||
|
print_source_location(std::cerr, location);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace error_handling
|
} // namespace error_handling
|
||||||
|
|
||||||
namespace utils {
|
namespace utils {
|
||||||
|
|
|
||||||
|
|
@ -381,6 +381,7 @@ nodes::TypeCheckResult type_check_return(const nodes::Return &expression,
|
||||||
arguments, expression, sources_manager);
|
arguments, expression, sources_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: warning if name is same to package prefix, function prefix, etc. ??
|
||||||
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,
|
SourcesManager &sources_manager, State &state,
|
||||||
|
|
@ -541,13 +542,17 @@ type_check_name_expression(const nodes::NameExpression &expression,
|
||||||
const Arguments &arguments) {
|
const Arguments &arguments) {
|
||||||
// TODO: constraints ??
|
// TODO: constraints ??
|
||||||
|
|
||||||
|
const auto name = expression.get_name();
|
||||||
|
for (size_t i = 0; i < /*fragments_count*/; ++i) { // go in prefixes and try to find matching var name
|
||||||
|
}
|
||||||
|
|
||||||
// --- TODO --- deal with passed type --- TODO --- (additional argument)
|
// --- TODO --- deal with passed type --- TODO --- (additional argument)
|
||||||
// TODO: deal with given ->(out) Args (type not expected, but passed into)
|
// TODO: deal with given ->(out) Args (type not expected, but passed into)
|
||||||
|
|
||||||
// TODO: check, if there is variable with this name
|
// TODO: check, if there is variable with this name
|
||||||
// TODO: check var + fields
|
// TODO: check var + fields
|
||||||
const auto maybe_function_definition = find_name_definition_handle_errors(
|
const auto maybe_function_definition = find_name_definition_handle_errors(
|
||||||
*expression.get_name()->get(), expression, sources_manager);
|
*name->get(), expression, sources_manager);
|
||||||
if (!maybe_function_definition.has_value()) {
|
if (!maybe_function_definition.has_value()) {
|
||||||
return nodes::TypeCheckResult::construct_invalid_result();
|
return nodes::TypeCheckResult::construct_invalid_result();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ namespace printers {
|
||||||
|
|
||||||
// TODO: better printing format for builtin types
|
// TODO: better printing format for builtin types
|
||||||
void print_type(const nodes::Type &type, printers::Printer &printer) {
|
void print_type(const nodes::Type &type, printers::Printer &printer) {
|
||||||
if (type.get_annotation().has_value()) {
|
if (type.has_annotation()) {
|
||||||
print_annotation(*type.get_annotation().value(), printer);
|
print_annotation(*type.get_annotation().value(), printer);
|
||||||
printer.space();
|
printer.space();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue