blaze lisp
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
5.6 KiB

/*
* Copyright (C) 2023 Riyyi
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <memory> // std::static_pointer_cast
#include <string>
#include <string_view>
// -----------------------------------------
// TODO: Move these ruc/test/macro.h -> ruc/src/meta/macro.h
#define GET_2TH_ARG(arg1, arg2, ...) arg2
#define GET_3TH_ARG(arg1, arg2, arg3, ...) arg3
#define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4
#define GET_5TH_ARG(arg1, arg2, arg3, arg4, arg5, ...) arg5
#define GET_6TH_ARG(arg1, arg2, arg3, arg4, arg5, arg6, ...) arg6
#define MACRO_CHOOSER_1(macro, ...) \
GET_2TH_ARG(__VA_ARGS__, macro##_1, )
#define MACRO_CHOOSER_2(macro, ...) \
GET_3TH_ARG(__VA_ARGS__, macro##_2, macro##_1, )
#define MACRO_CHOOSER_3(macro, ...) \
GET_4TH_ARG(__VA_ARGS__, macro##_3, macro##_2, macro##_1, )
#define MACRO_CHOOSER_4(macro, ...) \
GET_5TH_ARG(__VA_ARGS__, macro##_4, macro##_3, macro##_2, macro##_1, )
#define MACRO_CHOOSER_5(macro, ...) \
GET_6TH_ARG(__VA_ARGS__, macro##_5, macro##_4, macro##_3, macro##_2, macro##_1, )
// -----------------------------------------
#define CHECK_ARG_COUNT_IS_IMPL(name, size, expected, result) \
if (size != expected) { \
Error::the().add(format("wrong number of arguments: {}, {}", name, size)); \
return result; \
}
#define CHECK_ARG_COUNT_IS_3(name, size, expected) \
CHECK_ARG_COUNT_IS_IMPL(name, size, expected, nullptr)
#define CHECK_ARG_COUNT_IS_4(name, size, expected, result) \
CHECK_ARG_COUNT_IS_IMPL(name, size, expected, result)
#define CHECK_ARG_COUNT_IS(...) \
MACRO_CHOOSER_4(CHECK_ARG_COUNT_IS, __VA_ARGS__) \
(__VA_ARGS__)
// -----------------------------------------
#define CHECK_ARG_COUNT_AT_LEAST_IMPL(name, size, min, result) \
if (size < min) { \
Error::the().add(format("wrong number of arguments: {}, {}", name, size)); \
return result; \
}
#define CHECK_ARG_COUNT_AT_LEAST_3(name, size, min) \
CHECK_ARG_COUNT_AT_LEAST_IMPL(name, size, min, nullptr)
#define CHECK_ARG_COUNT_AT_LEAST_4(name, size, min, result) \
CHECK_ARG_COUNT_AT_LEAST_IMPL(name, size, min, result)
#define CHECK_ARG_COUNT_AT_LEAST(...) \
MACRO_CHOOSER_4(CHECK_ARG_COUNT_AT_LEAST, __VA_ARGS__) \
(__VA_ARGS__)
// -----------------------------------------
#define CHECK_ARG_COUNT_BETWEEN_IMPL(name, size, min, max, result) \
if (size < min || size > max) { \
Error::the().add(format("wrong number of arguments: {}, {}", name, size)); \
return result; \
}
#define CHECK_ARG_COUNT_BETWEEN_4(name, size, min, max) \
CHECK_ARG_COUNT_BETWEEN_IMPL(name, size, min, max, nullptr)
#define CHECK_ARG_COUNT_BETWEEN_5(name, size, min, max, result) \
CHECK_ARG_COUNT_BETWEEN_IMPL(name, size, min, max, result)
#define CHECK_ARG_COUNT_BETWEEN(...) \
MACRO_CHOOSER_5(CHECK_ARG_COUNT_BETWEEN, __VA_ARGS__) \
(__VA_ARGS__)
// -----------------------------------------
#define CHECK_ARG_COUNT_EVEN_IMPL(name, size, result) \
if (size % 2 != 0) { \
Error::the().add(format("wrong number of arguments: {}, {}", name, size)); \
return result; \
}
#define CHECK_ARG_COUNT_EVEN_2(name, size) \
CHECK_ARG_COUNT_EVEN_IMPL(name, size, nullptr)
#define CHECK_ARG_COUNT_EVEN_3(name, size, result) \
CHECK_ARG_COUNT_EVEN_IMPL(name, size, result)
#define CHECK_ARG_COUNT_EVEN(...) \
MACRO_CHOOSER_3(CHECK_ARG_COUNT_EVEN, __VA_ARGS__) \
(__VA_ARGS__)
// -----------------------------------------
#define IS_VALUE_IMPL(type, value, result) \
if (!is<type>(value.get())) { \
Error::the().add(format("wrong argument type: {}, {}", #type, value)); \
return result; \
}
#define IS_VALUE_2(type, value) \
IS_VALUE_IMPL(type, value, nullptr)
#define IS_VALUE_3(type, value, result) \
IS_VALUE_IMPL(type, value, result)
#define IS_VALUE(...) \
MACRO_CHOOSER_3(IS_VALUE, __VA_ARGS__) \
(__VA_ARGS__)
// -----------------------------------------
#define VALUE_CAST_IMPL(variable, type, value, result) \
IS_VALUE(type, value, result); \
auto variable = std::static_pointer_cast<type>(value);
#define VALUE_CAST_3(variable, type, value) \
VALUE_CAST_IMPL(variable, type, value, nullptr)
#define VALUE_CAST_4(variable, type, value, result) \
VALUE_CAST_IMPL(variable, type, value, result)
#define VALUE_CAST(...) \
MACRO_CHOOSER_4(VALUE_CAST, __VA_ARGS__) \
(__VA_ARGS__)
// -----------------------------------------
namespace blaze {
template<typename It, typename C>
inline bool isLast(It it, const C& container)
{
return (it != container.end()) && (next(it) == container.end());
}
inline std::string replaceAll(std::string text, std::string_view search, std::string_view replace)
{
size_t search_length = search.length();
size_t replace_length = replace.length();
size_t position = text.find(search, 0);
while (position != std::string::npos) {
text.replace(position, search_length, replace);
position += replace_length;
position = text.find(search, position);
}
return text;
}
} // namespace blaze