diff options
Diffstat (limited to 'include/ruby/impl')
143 files changed, 11622 insertions, 0 deletions
diff --git a/include/ruby/impl/anyargs.h b/include/ruby/impl/anyargs.h new file mode 100644 index 0000000000..d85a49b8a1 --- /dev/null +++ b/include/ruby/impl/anyargs.h @@ -0,0 +1,375 @@ +#ifndef RUBY3_ANYARGS_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ANYARGS_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Function overloads to issue warnings around #ANYARGS. + * + * For instance ::rb_define_method takes a pointer to #ANYARGS -ed functions, + * which in fact varies 18 different prototypes. We still need to preserve + * #ANYARGS for storages but why not check the consistencies if possible. With + * those complex macro overlays defined in this header file, use of a function + * pointer gets checked against the corresponding arity argument. + * + * ### Q&A ### + * + * - Q: Where did the magic number "18" came from in the description above? + * + * - A: Count the case branch of `vm_method.c:call_cfunc_invoker_func()`. Note + * also that the 18 branches has lasted for at least 25 years. See also + * commit 200e0ee2fd3c1c006c528874a88f684447215524. + * + * - Q: What is this `__weakref__` thing? + * + * - A: That is a kind of function overloading mechanism that GCC provides. In + * this case for instance `rb_define_method_00` is an alias of + * ::rb_define_method, with a strong type. + * + * - Q: What is this `__transparent_union__` thing? + * + * A: That is another kind of function overloading mechanism that GCC + * provides. In this case the attributed function pointer is either + * `VALUE(*)(int,VALUE*,VALUE)` or `VALUE(*)(int,const VALUE*,VALUE)`. + * + * This is better than `void*` or #ANYARGS because we can reject all other + * possibilities than the two. + * + * - Q: What does this #rb_define_method macro mean? + * + * - A: It selects appropriate alias of the ::rb_define_method function, + * depending on the last (arity) argument. + * + * - Q: Why the special case for ::rb_f_notimplement ? + * + * - A: Function pointer to ::rb_f_notimplement is special cased in + * `vm_method.c:rb_add_method_cfunc()`. That should be handled by the + * `__builtin_choose_expr` chain inside of #rb_define_method macro + * expansion. In order to do so, comparison like + * `(func == rb_f_notimplement)` is inappropriate for + * `__builtin_choose_expr`'s expression (which must be a compile-time + * integer constant but the address of ::rb_f_notimplement is not fixed + * until the linker). Instead we are using + * `__builtin_types_compatible_p`, and in doing so we need to distinguish + * ::rb_f_notimplement from others, by type. + */ +#include "ruby/3/attr/maybe_unused.h" +#include "ruby/3/attr/nonnull.h" +#include "ruby/3/attr/weakref.h" +#include "ruby/3/cast.h" +#include "ruby/3/config.h" +#include "ruby/3/has/attribute.h" +#include "ruby/3/intern/class.h" +#include "ruby/3/intern/vm.h" +#include "ruby/3/method.h" +#include "ruby/3/value.h" +#include "ruby/backward/2/stdarg.h" + +#if defined(__cplusplus) +# include "ruby/backward/cxxanyargs.hpp" + +#elif defined(_WIN32) || defined(__CYGWIN__) +# /* Skip due to [Bug #16134] */ + +#elif ! RUBY3_HAS_ATTRIBUTE(transparent_union) +# /* :TODO: improve here, please find a way to support. */ + +#elif ! defined(HAVE_VA_ARGS_MACRO) +# /* :TODO: improve here, please find a way to support. */ + +#else +# /** @cond INTERNAL_MACRO */ +# if ! defined(HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P) +# define RUBY3_CFUNC_IS_rb_f_notimplement(f) 0 +# else +# define RUBY3_CFUNC_IS_rb_f_notimplement(f) \ + __builtin_types_compatible_p( \ + __typeof__(f), \ + __typeof__(rb_f_notimplement)) +# endif + +# if ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) +# define RUBY3_ANYARGS_DISPATCH(expr, truthy, falsy) (falsy) +# else +# define RUBY3_ANYARGS_DISPATCH(expr, truthy, falsy) \ + __builtin_choose_expr( \ + __builtin_choose_expr( \ + __builtin_constant_p(expr), \ + (expr), 0), \ + (truthy), (falsy)) +# endif + +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_m2(n) RUBY3_ANYARGS_DISPATCH((n) == -2, rb_define_singleton_method_m2, rb_define_singleton_method_m3) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_m1(n) RUBY3_ANYARGS_DISPATCH((n) == -1, rb_define_singleton_method_m1, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_m2(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_00(n) RUBY3_ANYARGS_DISPATCH((n) == 0, rb_define_singleton_method_00, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_m1(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_01(n) RUBY3_ANYARGS_DISPATCH((n) == 1, rb_define_singleton_method_01, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_00(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_02(n) RUBY3_ANYARGS_DISPATCH((n) == 2, rb_define_singleton_method_02, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_01(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_03(n) RUBY3_ANYARGS_DISPATCH((n) == 3, rb_define_singleton_method_03, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_02(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_04(n) RUBY3_ANYARGS_DISPATCH((n) == 4, rb_define_singleton_method_04, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_03(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_05(n) RUBY3_ANYARGS_DISPATCH((n) == 5, rb_define_singleton_method_05, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_04(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_06(n) RUBY3_ANYARGS_DISPATCH((n) == 6, rb_define_singleton_method_06, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_05(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_07(n) RUBY3_ANYARGS_DISPATCH((n) == 7, rb_define_singleton_method_07, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_06(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_08(n) RUBY3_ANYARGS_DISPATCH((n) == 8, rb_define_singleton_method_08, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_07(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_09(n) RUBY3_ANYARGS_DISPATCH((n) == 9, rb_define_singleton_method_09, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_08(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_10(n) RUBY3_ANYARGS_DISPATCH((n) == 10, rb_define_singleton_method_10, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_09(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_11(n) RUBY3_ANYARGS_DISPATCH((n) == 11, rb_define_singleton_method_11, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_10(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_12(n) RUBY3_ANYARGS_DISPATCH((n) == 12, rb_define_singleton_method_12, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_11(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_13(n) RUBY3_ANYARGS_DISPATCH((n) == 13, rb_define_singleton_method_13, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_12(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_14(n) RUBY3_ANYARGS_DISPATCH((n) == 14, rb_define_singleton_method_14, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_13(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_15(n) RUBY3_ANYARGS_DISPATCH((n) == 15, rb_define_singleton_method_15, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_14(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_m2(n) RUBY3_ANYARGS_DISPATCH((n) == -2, rb_define_protected_method_m2, rb_define_protected_method_m3) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_m1(n) RUBY3_ANYARGS_DISPATCH((n) == -1, rb_define_protected_method_m1, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_m2(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_00(n) RUBY3_ANYARGS_DISPATCH((n) == 0, rb_define_protected_method_00, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_m1(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_01(n) RUBY3_ANYARGS_DISPATCH((n) == 1, rb_define_protected_method_01, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_00(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_02(n) RUBY3_ANYARGS_DISPATCH((n) == 2, rb_define_protected_method_02, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_01(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_03(n) RUBY3_ANYARGS_DISPATCH((n) == 3, rb_define_protected_method_03, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_02(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_04(n) RUBY3_ANYARGS_DISPATCH((n) == 4, rb_define_protected_method_04, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_03(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_05(n) RUBY3_ANYARGS_DISPATCH((n) == 5, rb_define_protected_method_05, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_04(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_06(n) RUBY3_ANYARGS_DISPATCH((n) == 6, rb_define_protected_method_06, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_05(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_07(n) RUBY3_ANYARGS_DISPATCH((n) == 7, rb_define_protected_method_07, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_06(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_08(n) RUBY3_ANYARGS_DISPATCH((n) == 8, rb_define_protected_method_08, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_07(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_09(n) RUBY3_ANYARGS_DISPATCH((n) == 9, rb_define_protected_method_09, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_08(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_10(n) RUBY3_ANYARGS_DISPATCH((n) == 10, rb_define_protected_method_10, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_09(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_11(n) RUBY3_ANYARGS_DISPATCH((n) == 11, rb_define_protected_method_11, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_10(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_12(n) RUBY3_ANYARGS_DISPATCH((n) == 12, rb_define_protected_method_12, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_11(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_13(n) RUBY3_ANYARGS_DISPATCH((n) == 13, rb_define_protected_method_13, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_12(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_14(n) RUBY3_ANYARGS_DISPATCH((n) == 14, rb_define_protected_method_14, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_13(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_15(n) RUBY3_ANYARGS_DISPATCH((n) == 15, rb_define_protected_method_15, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_14(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_m2(n) RUBY3_ANYARGS_DISPATCH((n) == -2, rb_define_private_method_m2, rb_define_private_method_m3) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_m1(n) RUBY3_ANYARGS_DISPATCH((n) == -1, rb_define_private_method_m1, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_m2(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_00(n) RUBY3_ANYARGS_DISPATCH((n) == 0, rb_define_private_method_00, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_m1(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_01(n) RUBY3_ANYARGS_DISPATCH((n) == 1, rb_define_private_method_01, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_00(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_02(n) RUBY3_ANYARGS_DISPATCH((n) == 2, rb_define_private_method_02, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_01(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_03(n) RUBY3_ANYARGS_DISPATCH((n) == 3, rb_define_private_method_03, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_02(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_04(n) RUBY3_ANYARGS_DISPATCH((n) == 4, rb_define_private_method_04, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_03(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_05(n) RUBY3_ANYARGS_DISPATCH((n) == 5, rb_define_private_method_05, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_04(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_06(n) RUBY3_ANYARGS_DISPATCH((n) == 6, rb_define_private_method_06, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_05(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_07(n) RUBY3_ANYARGS_DISPATCH((n) == 7, rb_define_private_method_07, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_06(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_08(n) RUBY3_ANYARGS_DISPATCH((n) == 8, rb_define_private_method_08, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_07(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_09(n) RUBY3_ANYARGS_DISPATCH((n) == 9, rb_define_private_method_09, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_08(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_10(n) RUBY3_ANYARGS_DISPATCH((n) == 10, rb_define_private_method_10, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_09(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_11(n) RUBY3_ANYARGS_DISPATCH((n) == 11, rb_define_private_method_11, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_10(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_12(n) RUBY3_ANYARGS_DISPATCH((n) == 12, rb_define_private_method_12, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_11(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_13(n) RUBY3_ANYARGS_DISPATCH((n) == 13, rb_define_private_method_13, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_12(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_14(n) RUBY3_ANYARGS_DISPATCH((n) == 14, rb_define_private_method_14, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_13(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method_15(n) RUBY3_ANYARGS_DISPATCH((n) == 15, rb_define_private_method_15, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_14(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_m2(n) RUBY3_ANYARGS_DISPATCH((n) == -2, rb_define_module_function_m2, rb_define_module_function_m3) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_m1(n) RUBY3_ANYARGS_DISPATCH((n) == -1, rb_define_module_function_m1, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_m2(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_00(n) RUBY3_ANYARGS_DISPATCH((n) == 0, rb_define_module_function_00, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_m1(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_01(n) RUBY3_ANYARGS_DISPATCH((n) == 1, rb_define_module_function_01, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_00(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_02(n) RUBY3_ANYARGS_DISPATCH((n) == 2, rb_define_module_function_02, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_01(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_03(n) RUBY3_ANYARGS_DISPATCH((n) == 3, rb_define_module_function_03, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_02(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_04(n) RUBY3_ANYARGS_DISPATCH((n) == 4, rb_define_module_function_04, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_03(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_05(n) RUBY3_ANYARGS_DISPATCH((n) == 5, rb_define_module_function_05, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_04(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_06(n) RUBY3_ANYARGS_DISPATCH((n) == 6, rb_define_module_function_06, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_05(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_07(n) RUBY3_ANYARGS_DISPATCH((n) == 7, rb_define_module_function_07, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_06(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_08(n) RUBY3_ANYARGS_DISPATCH((n) == 8, rb_define_module_function_08, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_07(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_09(n) RUBY3_ANYARGS_DISPATCH((n) == 9, rb_define_module_function_09, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_08(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_10(n) RUBY3_ANYARGS_DISPATCH((n) == 10, rb_define_module_function_10, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_09(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_11(n) RUBY3_ANYARGS_DISPATCH((n) == 11, rb_define_module_function_11, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_10(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_12(n) RUBY3_ANYARGS_DISPATCH((n) == 12, rb_define_module_function_12, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_11(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_13(n) RUBY3_ANYARGS_DISPATCH((n) == 13, rb_define_module_function_13, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_12(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_14(n) RUBY3_ANYARGS_DISPATCH((n) == 14, rb_define_module_function_14, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_13(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function_15(n) RUBY3_ANYARGS_DISPATCH((n) == 15, rb_define_module_function_15, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_14(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_m2(n) RUBY3_ANYARGS_DISPATCH((n) == -2, rb_define_global_function_m2, rb_define_global_function_m3) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_m1(n) RUBY3_ANYARGS_DISPATCH((n) == -1, rb_define_global_function_m1, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_m2(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_00(n) RUBY3_ANYARGS_DISPATCH((n) == 0, rb_define_global_function_00, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_m1(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_01(n) RUBY3_ANYARGS_DISPATCH((n) == 1, rb_define_global_function_01, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_00(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_02(n) RUBY3_ANYARGS_DISPATCH((n) == 2, rb_define_global_function_02, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_01(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_03(n) RUBY3_ANYARGS_DISPATCH((n) == 3, rb_define_global_function_03, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_02(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_04(n) RUBY3_ANYARGS_DISPATCH((n) == 4, rb_define_global_function_04, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_03(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_05(n) RUBY3_ANYARGS_DISPATCH((n) == 5, rb_define_global_function_05, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_04(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_06(n) RUBY3_ANYARGS_DISPATCH((n) == 6, rb_define_global_function_06, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_05(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_07(n) RUBY3_ANYARGS_DISPATCH((n) == 7, rb_define_global_function_07, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_06(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_08(n) RUBY3_ANYARGS_DISPATCH((n) == 8, rb_define_global_function_08, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_07(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_09(n) RUBY3_ANYARGS_DISPATCH((n) == 9, rb_define_global_function_09, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_08(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_10(n) RUBY3_ANYARGS_DISPATCH((n) == 10, rb_define_global_function_10, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_09(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_11(n) RUBY3_ANYARGS_DISPATCH((n) == 11, rb_define_global_function_11, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_10(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_12(n) RUBY3_ANYARGS_DISPATCH((n) == 12, rb_define_global_function_12, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_11(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_13(n) RUBY3_ANYARGS_DISPATCH((n) == 13, rb_define_global_function_13, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_12(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_14(n) RUBY3_ANYARGS_DISPATCH((n) == 14, rb_define_global_function_14, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_13(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function_15(n) RUBY3_ANYARGS_DISPATCH((n) == 15, rb_define_global_function_15, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_14(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_m2(n) RUBY3_ANYARGS_DISPATCH((n) == -2, rb_define_method_id_m2, rb_define_method_id_m3) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_m1(n) RUBY3_ANYARGS_DISPATCH((n) == -1, rb_define_method_id_m1, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_m2(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_00(n) RUBY3_ANYARGS_DISPATCH((n) == 0, rb_define_method_id_00, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_m1(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_01(n) RUBY3_ANYARGS_DISPATCH((n) == 1, rb_define_method_id_01, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_00(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_02(n) RUBY3_ANYARGS_DISPATCH((n) == 2, rb_define_method_id_02, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_01(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_03(n) RUBY3_ANYARGS_DISPATCH((n) == 3, rb_define_method_id_03, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_02(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_04(n) RUBY3_ANYARGS_DISPATCH((n) == 4, rb_define_method_id_04, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_03(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_05(n) RUBY3_ANYARGS_DISPATCH((n) == 5, rb_define_method_id_05, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_04(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_06(n) RUBY3_ANYARGS_DISPATCH((n) == 6, rb_define_method_id_06, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_05(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_07(n) RUBY3_ANYARGS_DISPATCH((n) == 7, rb_define_method_id_07, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_06(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_08(n) RUBY3_ANYARGS_DISPATCH((n) == 8, rb_define_method_id_08, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_07(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_09(n) RUBY3_ANYARGS_DISPATCH((n) == 9, rb_define_method_id_09, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_08(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_10(n) RUBY3_ANYARGS_DISPATCH((n) == 10, rb_define_method_id_10, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_09(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_11(n) RUBY3_ANYARGS_DISPATCH((n) == 11, rb_define_method_id_11, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_10(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_12(n) RUBY3_ANYARGS_DISPATCH((n) == 12, rb_define_method_id_12, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_11(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_13(n) RUBY3_ANYARGS_DISPATCH((n) == 13, rb_define_method_id_13, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_12(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_14(n) RUBY3_ANYARGS_DISPATCH((n) == 14, rb_define_method_id_14, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_13(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id_15(n) RUBY3_ANYARGS_DISPATCH((n) == 15, rb_define_method_id_15, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_14(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_m2(n) RUBY3_ANYARGS_DISPATCH((n) == -2, rb_define_method_m2, rb_define_method_m3) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_m1(n) RUBY3_ANYARGS_DISPATCH((n) == -1, rb_define_method_m1, RUBY3_ANYARGS_DISPATCH_rb_define_method_m2(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_00(n) RUBY3_ANYARGS_DISPATCH((n) == 0, rb_define_method_00, RUBY3_ANYARGS_DISPATCH_rb_define_method_m1(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_01(n) RUBY3_ANYARGS_DISPATCH((n) == 1, rb_define_method_01, RUBY3_ANYARGS_DISPATCH_rb_define_method_00(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_02(n) RUBY3_ANYARGS_DISPATCH((n) == 2, rb_define_method_02, RUBY3_ANYARGS_DISPATCH_rb_define_method_01(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_03(n) RUBY3_ANYARGS_DISPATCH((n) == 3, rb_define_method_03, RUBY3_ANYARGS_DISPATCH_rb_define_method_02(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_04(n) RUBY3_ANYARGS_DISPATCH((n) == 4, rb_define_method_04, RUBY3_ANYARGS_DISPATCH_rb_define_method_03(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_05(n) RUBY3_ANYARGS_DISPATCH((n) == 5, rb_define_method_05, RUBY3_ANYARGS_DISPATCH_rb_define_method_04(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_06(n) RUBY3_ANYARGS_DISPATCH((n) == 6, rb_define_method_06, RUBY3_ANYARGS_DISPATCH_rb_define_method_05(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_07(n) RUBY3_ANYARGS_DISPATCH((n) == 7, rb_define_method_07, RUBY3_ANYARGS_DISPATCH_rb_define_method_06(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_08(n) RUBY3_ANYARGS_DISPATCH((n) == 8, rb_define_method_08, RUBY3_ANYARGS_DISPATCH_rb_define_method_07(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_09(n) RUBY3_ANYARGS_DISPATCH((n) == 9, rb_define_method_09, RUBY3_ANYARGS_DISPATCH_rb_define_method_08(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_10(n) RUBY3_ANYARGS_DISPATCH((n) == 10, rb_define_method_10, RUBY3_ANYARGS_DISPATCH_rb_define_method_09(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_11(n) RUBY3_ANYARGS_DISPATCH((n) == 11, rb_define_method_11, RUBY3_ANYARGS_DISPATCH_rb_define_method_10(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_12(n) RUBY3_ANYARGS_DISPATCH((n) == 12, rb_define_method_12, RUBY3_ANYARGS_DISPATCH_rb_define_method_11(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_13(n) RUBY3_ANYARGS_DISPATCH((n) == 13, rb_define_method_13, RUBY3_ANYARGS_DISPATCH_rb_define_method_12(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_14(n) RUBY3_ANYARGS_DISPATCH((n) == 14, rb_define_method_14, RUBY3_ANYARGS_DISPATCH_rb_define_method_13(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_15(n) RUBY3_ANYARGS_DISPATCH((n) == 15, rb_define_method_15, RUBY3_ANYARGS_DISPATCH_rb_define_method_14(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method(n, f) RUBY3_ANYARGS_DISPATCH(RUBY3_CFUNC_IS_rb_f_notimplement(f), rb_define_singleton_method_m3, RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method_15(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_protected_method(n, f) RUBY3_ANYARGS_DISPATCH(RUBY3_CFUNC_IS_rb_f_notimplement(f), rb_define_protected_method_m3, RUBY3_ANYARGS_DISPATCH_rb_define_protected_method_15(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_private_method(n, f) RUBY3_ANYARGS_DISPATCH(RUBY3_CFUNC_IS_rb_f_notimplement(f), rb_define_private_method_m3, RUBY3_ANYARGS_DISPATCH_rb_define_private_method_15(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_module_function(n, f) RUBY3_ANYARGS_DISPATCH(RUBY3_CFUNC_IS_rb_f_notimplement(f), rb_define_module_function_m3, RUBY3_ANYARGS_DISPATCH_rb_define_module_function_15(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_global_function(n, f) RUBY3_ANYARGS_DISPATCH(RUBY3_CFUNC_IS_rb_f_notimplement(f), rb_define_global_function_m3, RUBY3_ANYARGS_DISPATCH_rb_define_global_function_15(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method_id(n, f) RUBY3_ANYARGS_DISPATCH(RUBY3_CFUNC_IS_rb_f_notimplement(f), rb_define_method_id_m3, RUBY3_ANYARGS_DISPATCH_rb_define_method_id_15(n)) +# define RUBY3_ANYARGS_DISPATCH_rb_define_method(n, f) RUBY3_ANYARGS_DISPATCH(RUBY3_CFUNC_IS_rb_f_notimplement(f), rb_define_method_m3, RUBY3_ANYARGS_DISPATCH_rb_define_method_15(n)) +# define RUBY3_ANYARGS_ATTRSET(sym) RUBY3_ATTR_MAYBE_UNUSED() RUBY3_ATTR_NONNULL() RUBY3_ATTR_WEAKREF(sym) +# define RUBY3_ANYARGS_DECL(sym, ...) \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _m3(__VA_ARGS__, VALUE(*)(ANYARGS), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _m2(__VA_ARGS__, VALUE(*)(VALUE, VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _m1(__VA_ARGS__, VALUE(*)(int, union { VALUE *x; const VALUE *y; } __attribute__((__transparent_union__)), VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _00(__VA_ARGS__, VALUE(*)(VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _01(__VA_ARGS__, VALUE(*)(VALUE, VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _02(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _03(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _04(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _05(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _06(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _07(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _08(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _09(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _10(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _11(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _12(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _13(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _14(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RUBY3_ANYARGS_ATTRSET(sym) static void sym ## _15(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); +RUBY3_ANYARGS_DECL(rb_define_singleton_method, VALUE, const char *) +RUBY3_ANYARGS_DECL(rb_define_protected_method, VALUE, const char *) +RUBY3_ANYARGS_DECL(rb_define_private_method, VALUE, const char *) +RUBY3_ANYARGS_DECL(rb_define_module_function, VALUE, const char *) +RUBY3_ANYARGS_DECL(rb_define_global_function, const char *) +RUBY3_ANYARGS_DECL(rb_define_method_id, VALUE, ID) +RUBY3_ANYARGS_DECL(rb_define_method, VALUE, const char *) +/** @endcond */ + +/** + * @brief Defines klass\#mid. + * @see ::rb_define_method + * @param klass Where the method lives. + * @param mid Name of the defining method. + * @param func Implementation of klass\#mid. + * @param arity Arity of klass\#mid. + */ +#define rb_define_method(klass, mid, func, arity) RUBY3_ANYARGS_DISPATCH_rb_define_method((arity), (func))((klass), (mid), (func), (arity)) + +/** + * @brief Defines klass\#mid. + * @see ::rb_define_method_id + * @param klass Where the method lives. + * @param mid Name of the defining method. + * @param func Implementation of klass\#mid. + * @param arity Arity of klass\#mid. + */ +#define rb_define_method_id(klass, mid, func, arity) RUBY3_ANYARGS_DISPATCH_rb_define_method_id((arity), (func))((klass), (mid), (func), (arity)) + +/** + * @brief Defines obj.mid. + * @see ::rb_define_singleton_method + * @param obj Where the method lives. + * @param mid Name of the defining method. + * @param func Implementation of obj.mid. + * @param arity Arity of obj.mid. + */ +#define rb_define_singleton_method(obj, mid, func, arity) RUBY3_ANYARGS_DISPATCH_rb_define_singleton_method((arity), (func))((obj), (mid), (func), (arity)) + +/** + * @brief Defines klass\#mid and make it protected. + * @see ::rb_define_protected_method + * @param klass Where the method lives. + * @param mid Name of the defining method. + * @param func Implementation of klass\#mid. + * @param arity Arity of klass\#mid. + */ +#define rb_define_protected_method(klass, mid, func, arity) RUBY3_ANYARGS_DISPATCH_rb_define_protected_method((arity), (func))((klass), (mid), (func), (arity)) + +/** + * @brief Defines klass\#mid and make it private. + * @see ::rb_define_private_method + * @param klass Where the method lives. + * @param mid Name of the defining method. + * @param func Implementation of klass\#mid. + * @param arity Arity of klass\#mid. + */ +#define rb_define_private_method(klass, mid, func, arity) RUBY3_ANYARGS_DISPATCH_rb_define_private_method((arity), (func))((klass), (mid), (func), (arity)) + +/** + * @brief Defines mod\#mid and make it a module function. + * @see ::rb_define_module_function + * @param mod Where the method lives. + * @param mid Name of the defining method. + * @param func Implementation of mod\#mid. + * @param arity Arity of mod\#mid. + */ +#define rb_define_module_function(mod, mid, func, arity) RUBY3_ANYARGS_DISPATCH_rb_define_module_function((arity), (func))((mod), (mid), (func), (arity)) + +/** + * @brief Defines ::rb_mKerbel \#mid. + * @see ::rb_define_gobal_function + * @param mid Name of the defining method. + * @param func Implementation of ::rb_mKernel \#mid. + * @param arity Arity of ::rb_mKernel \#mid. + */ +#define rb_define_global_function(mid, func, arity) RUBY3_ANYARGS_DISPATCH_rb_define_global_function((arity), (func))((mid), (func), (arity)) + +#endif /* __cplusplus */ + +/** + * This macro is to properly cast a function parameter of *_define_method + * family. It has been around since 1.x era so you can maximize backwards + * compatibility by using it. + * + * ```CXX + * rb_define_method(klass, "method", RUBY_METHOD_FUNC(func), arity); + * ``` + * + * @param func A pointer to a function that implements a method. + */ +#if ! defined(RUBY_DEVEL) +# define RUBY_METHOD_FUNC(func) RUBY3_CAST((VALUE (*)(ANYARGS))(func)) + +#elif ! RUBY_DEVEL +# define RUBY_METHOD_FUNC(func) RUBY3_CAST((VALUE (*)(ANYARGS))(func)) + +#elif ! defined(rb_define_method) +# define RUBY_METHOD_FUNC(func) RUBY3_CAST((VALUE (*)(ANYARGS))(func)) + +#else +# define RUBY_METHOD_FUNC(func) (func) + +#endif + +#endif /* RUBY3_ANYARGS_H */ diff --git a/include/ruby/impl/arithmetic.h b/include/ruby/impl/arithmetic.h new file mode 100644 index 0000000000..5dcdfcd9e4 --- /dev/null +++ b/include/ruby/impl/arithmetic.h @@ -0,0 +1,38 @@ +#ifndef RUBY3_ARITHMETIC_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMETIC_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Conversion between C's arithmtic types and Ruby's numeric types. + */ +#include "ruby/3/arithmetic/char.h" +#include "ruby/3/arithmetic/double.h" +#include "ruby/3/arithmetic/fixnum.h" +#include "ruby/3/arithmetic/gid_t.h" +#include "ruby/3/arithmetic/int.h" +#include "ruby/3/arithmetic/intptr_t.h" +#include "ruby/3/arithmetic/long.h" +#include "ruby/3/arithmetic/long_long.h" +#include "ruby/3/arithmetic/mode_t.h" +#include "ruby/3/arithmetic/off_t.h" +#include "ruby/3/arithmetic/pid_t.h" +#include "ruby/3/arithmetic/short.h" +#include "ruby/3/arithmetic/size_t.h" +#include "ruby/3/arithmetic/st_data_t.h" +#include "ruby/3/arithmetic/uid_t.h" +#endif /* RUBY3_ARITHMETIC_H */ diff --git a/include/ruby/impl/arithmetic/char.h b/include/ruby/impl/arithmetic/char.h new file mode 100644 index 0000000000..03afa0a406 --- /dev/null +++ b/include/ruby/impl/arithmetic/char.h @@ -0,0 +1,58 @@ +#ifndef RUBY3_ARITHMETIC_CHAR_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMETIC_CHAR_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `char` and Ruby's. + */ +#include "ruby/3/arithmetic/int.h" /* NUM2INT is here, but */ +#include "ruby/3/arithmetic/long.h" /* INT2FIX is here.*/ +#include "ruby/3/attr/artificial.h" +#include "ruby/3/attr/const.h" +#include "ruby/3/attr/constexpr.h" +#include "ruby/3/cast.h" +#include "ruby/3/core/rstring.h" +#include "ruby/3/value_type.h" + +#define RB_NUM2CHR rb_num2char_inline +#define NUM2CHR RB_NUM2CHR +#define CHR2FIX RB_CHR2FIX + +/** @cond INTERNAL_MACRO */ +#define RB_CHR2FIX RB_CHR2FIX +/** @endcond */ + +RUBY3_ATTR_CONST_ON_NDEBUG() +RUBY3_ATTR_CONSTEXPR_ON_NDEBUG(CXX14) +RUBY3_ATTR_ARTIFICIAL() +static inline VALUE +RB_CHR2FIX(unsigned char c) +{ + return RB_INT2FIX(c); +} + +static inline char +rb_num2char_inline(VALUE x) +{ + if (RB_TYPE_P(x, RUBY_T_STRING) && (RSTRING_LEN(x)>=1)) + return RSTRING_PTR(x)[0]; + else + return RUBY3_CAST((char)RB_NUM2INT(x)); +} + +#endif /* RUBY3_ARITHMETIC_CHAR_H */ diff --git a/include/ruby/impl/arithmetic/double.h b/include/ruby/impl/arithmetic/double.h new file mode 100644 index 0000000000..4a37611a21 --- /dev/null +++ b/include/ruby/impl/arithmetic/double.h @@ -0,0 +1,39 @@ +#ifndef RUBY3_ARITHMETIC_DOUBLE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMETIC_DOUBLE_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `double` and Ruby's. + */ +#include "ruby/3/attr/pure.h" +#include "ruby/3/dllexport.h" +#include "ruby/3/value.h" + +#define NUM2DBL rb_num2dbl +#define RFLOAT_VALUE rb_float_value +#define DBL2NUM rb_float_new + +RUBY3_SYMBOL_EXPORT_BEGIN() +double rb_num2dbl(VALUE); +RUBY3_ATTR_PURE() +double rb_float_value(VALUE); +VALUE rb_float_new(double); +VALUE rb_float_new_in_heap(double); +RUBY3_SYMBOL_EXPORT_END() + +#endif /* RUBY3_ARITHMETIC_DOUBLE_H */ diff --git a/include/ruby/impl/arithmetic/fixnum.h b/include/ruby/impl/arithmetic/fixnum.h new file mode 100644 index 0000000000..d7214e080b --- /dev/null +++ b/include/ruby/impl/arithmetic/fixnum.h @@ -0,0 +1,44 @@ +#ifndef RUBY3_ARITHMETIC_FIXNUM_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMETIC_FIXNUM_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Handling of integers formerly known as Fixnums. + */ +#include "ruby/backward/2/limits.h" + +#define FIXABLE RB_FIXABLE +#define FIXNUM_MAX RUBY_FIXNUM_MAX +#define FIXNUM_MIN RUBY_FIXNUM_MIN +#define NEGFIXABLE RB_NEGFIXABLE +#define POSFIXABLE RB_POSFIXABLE + +/* + * FIXABLE can be applied to anything, from double to intmax_t. The problem is + * double. On a 64bit system RUBY_FIXNUM_MAX is 4,611,686,018,427,387,903, + * which is not representable by a double. The nearest value that a double can + * represent is 4,611,686,018,427,387,904, which is not fixable. The + * seemingly-stragne "< FIXNUM_MAX + 1" expression below is due to this. + */ +#define RB_POSFIXABLE(_) ((_) < RUBY_FIXNUM_MAX + 1) +#define RB_NEGFIXABLE(_) ((_) >= RUBY_FIXNUM_MIN) +#define RB_FIXABLE(_) (RB_POSFIXABLE(_) && RB_NEGFIXABLE(_)) +#define RUBY_FIXNUM_MAX (LONG_MAX / 2) +#define RUBY_FIXNUM_MIN (LONG_MIN / 2) + +#endif /* RUBY3_ARITHMETIC_FIXNUM_H */ diff --git a/include/ruby/impl/arithmetic/gid_t.h b/include/ruby/impl/arithmetic/gid_t.h new file mode 100644 index 0000000000..7c4c1b00ed --- /dev/null +++ b/include/ruby/impl/arithmetic/gid_t.h @@ -0,0 +1,34 @@ +#ifndef RUBY3_ARITHMETIC_GID_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMETIC_GID_T_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `gid_t` and Ruby's. + */ +#include "ruby/3/config.h" +#include "ruby/3/arithmetic/long.h" + +#ifndef GIDT2NUM +# define GIDT2NUM RB_LONG2NUM +#endif + +#ifndef NUM2GIDT +# define NUM2GIDT RB_NUM2LONG +#endif + +#endif /* RUBY3_ARITHMETIC_GID_T_H */ diff --git a/include/ruby/impl/arithmetic/int.h b/include/ruby/impl/arithmetic/int.h new file mode 100644 index 0000000000..2ebf8081f9 --- /dev/null +++ b/include/ruby/impl/arithmetic/int.h @@ -0,0 +1,163 @@ +#ifndef RUBY3_ARITHMETIC_INT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMETIC_INT_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `int` and Ruby's. + */ +#include "ruby/3/config.h" +#include "ruby/3/arithmetic/fixnum.h" +#include "ruby/3/arithmetic/intptr_t.h" +#include "ruby/3/arithmetic/long.h" +#include "ruby/3/attr/artificial.h" +#include "ruby/3/attr/const.h" +#include "ruby/3/attr/constexpr.h" +#include "ruby/3/compiler_is.h" +#include "ruby/3/dllexport.h" +#include "ruby/3/special_consts.h" +#include "ruby/3/value.h" +#include "ruby/3/warning_push.h" +#include "ruby/assert.h" + +#define RB_INT2NUM rb_int2num_inline +#define RB_NUM2INT rb_num2int_inline +#define RB_UINT2NUM rb_uint2num_inline + +#define FIX2INT RB_FIX2INT +#define FIX2UINT RB_FIX2UINT +#define INT2NUM RB_INT2NUM +#define NUM2INT RB_NUM2INT +#define NUM2UINT RB_NUM2UINT +#define UINT2NUM RB_UINT2NUM + +/** @cond INTERNAL_MACRO */ +#define RB_FIX2INT RB_FIX2INT +#define RB_NUM2UINT RB_NUM2UINT +#define RB_FIX2UINT RB_FIX2UINT +/** @endcond */ + +RUBY3_SYMBOL_EXPORT_BEGIN() +long rb_num2int(VALUE); +long rb_fix2int(VALUE); +unsigned long rb_num2uint(VALUE); +unsigned long rb_fix2uint(VALUE); +RUBY3_SYMBOL_EXPORT_END() + +RUBY3_ATTR_ARTIFICIAL() +static inline int +RB_FIX2INT(VALUE x) +{ + /* "FIX2INT raises a TypeError if passed nil", says rubyspec. Not sure if + * that is a desired behaviour but just preserve backwards compatilibily. + */ +#if 0 + RUBY3_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); +#endif + long ret; + + if /* constexpr */ (sizeof(int) < sizeof(long)) { + ret = rb_fix2int(x); + } + else { + ret = RB_FIX2LONG(x); + } + + return RUBY3_CAST((int)ret); +} + +static inline int +rb_num2int_inline(VALUE x) +{ + long ret; + + if /* constexpr */ (sizeof(int) == sizeof(long)) { + ret = RB_NUM2LONG(x); + } + else if (RB_FIXNUM_P(x)) { + ret = rb_fix2int(x); + } + else { + ret = rb_num2int(x); + } + + return RUBY3_CAST((int)ret); +} + +RUBY3_ATTR_ARTIFICIAL() +static inline unsigned int +RB_NUM2UINT(VALUE x) +{ + unsigned long ret; + + if /* constexpr */ (sizeof(int) < sizeof(long)) { + ret = rb_num2uint(x); + } + else { + ret = RB_NUM2ULONG(x); + } + + return RUBY3_CAST((unsigned int)ret); +} + +RUBY3_ATTR_ARTIFICIAL() +static inline unsigned int +RB_FIX2UINT(VALUE x) +{ +#if 0 /* Ditto for RB_FIX2INT. */ + RUBY3_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); +#endif + unsigned long ret; + + if /* constexpr */ (sizeof(int) < sizeof(long)) { + ret = rb_fix2uint(x); + } + else { + ret = RB_FIX2ULONG(x); + } + + return RUBY3_CAST((unsigned int)ret); +} + +RUBY3_WARNING_PUSH() +#if RUBY3_COMPILER_IS(GCC) +RUBY3_WARNING_IGNORED(-Wtype-limits) /* We can ignore them here. */ +#elif RUBY3_HAS_WARNING("-Wtautological-constant-out-of-range-compare") +RUBY3_WARNING_IGNORED(-Wtautological-constant-out-of-range-compare) +#endif + +static inline VALUE +rb_int2num_inline(int v) +{ + if (RB_FIXABLE(v)) + return RB_INT2FIX(v); + else + return rb_int2big(v); +} + +static inline VALUE +rb_uint2num_inline(unsigned int v) +{ + if (RB_POSFIXABLE(v)) + return RB_LONG2FIX(v); + else + return rb_uint2big(v); +} + +RUBY3_WARNING_POP() + +#endif /* RUBY3_ARITHMETIC_INT_H */ diff --git a/include/ruby/impl/arithmetic/intptr_t.h b/include/ruby/impl/arithmetic/intptr_t.h new file mode 100644 index 0000000000..7eabf75a80 --- /dev/null +++ b/include/ruby/impl/arithmetic/intptr_t.h @@ -0,0 +1,42 @@ +#ifndef RUBY3_ARITHMETIC_INTPTR_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMETIC_INTPTR_T_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `intptr_t` and Ruby's. + */ +#include "ruby/3/config.h" + +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif + +#include "ruby/3/value.h" +#include "ruby/3/dllexport.h" + +#define rb_int_new rb_int2inum +#define rb_uint_new rb_uint2inum + +RUBY3_SYMBOL_EXPORT_BEGIN() +VALUE rb_int2big(intptr_t i); +VALUE rb_int2inum(intptr_t i); +VALUE rb_uint2big(uintptr_t i); +VALUE rb_uint2inum(uintptr_t i); +RUBY3_SYMBOL_EXPORT_END() + +#endif /* RUBY3_ARITHMETIC_INTPTR_T_H */ diff --git a/include/ruby/impl/arithmetic/long.h b/include/ruby/impl/arithmetic/long.h new file mode 100644 index 0000000000..3263c616b0 --- /dev/null +++ b/include/ruby/impl/arithmetic/long.h @@ -0,0 +1,244 @@ +#ifndef RUBY3_ARITHMETIC_LONG_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMETIC_LONG_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `long` and Ruby's. + * + * ### Q&A ### + * + * - Q: Why are INT2FIX etc. here, not in `int.h`? + * + * - A: Because they are in fact handling `long`. It seems someone did not + * understand the difference of `int` and `long` when they designed those + * macros. + */ +#include "ruby/3/config.h" +#include "ruby/3/arithmetic/fixnum.h" /* FIXABLE */ +#include "ruby/3/arithmetic/intptr_t.h" /* rb_int2big etc.*/ +#include "ruby/3/assume.h" +#include "ruby/3/attr/artificial.h" +#include "ruby/3/attr/cold.h" +#include "ruby/3/attr/const.h" +#include "ruby/3/attr/constexpr.h" +#include "ruby/3/attr/noreturn.h" +#include "ruby/3/cast.h" +#include "ruby/3/dllexport.h" +#include "ruby/3/special_consts.h" /* FIXNUM_FLAG */ +#include "ruby/3/value.h" +#include "ruby/assert.h" + +#define FIX2LONG RB_FIX2LONG +#define FIX2ULONG RB_FIX2ULONG +#define INT2FIX RB_INT2FIX +#define LONG2FIX RB_INT2FIX +#define LONG2NUM RB_LONG2NUM +#define NUM2LONG RB_NUM2LONG +#define NUM2ULONG RB_NUM2ULONG +#define RB_FIX2LONG rb_fix2long +#define RB_FIX2ULONG rb_fix2ulong +#define RB_LONG2FIX RB_INT2FIX +#define RB_LONG2NUM rb_long2num_inline +#define RB_NUM2LONG rb_num2long_inline +#define RB_NUM2ULONG rb_num2ulong_inline +#define RB_ULONG2NUM rb_ulong2num_inline +#define ULONG2NUM RB_ULONG2NUM +#define rb_fix_new RB_INT2FIX +#define rb_long2int rb_long2int_inline + +/** @cond INTERNAL_MACRO */ +#define RB_INT2FIX RB_INT2FIX +/** @endcond */ + +RUBY3_SYMBOL_EXPORT_BEGIN() + +RUBY3_ATTR_NORETURN() +RUBY3_ATTR_COLD() +void rb_out_of_int(SIGNED_VALUE num); + +long rb_num2long(VALUE num); +unsigned long rb_num2ulong(VALUE num); +RUBY3_SYMBOL_EXPORT_END() + +RUBY3_ATTR_CONST_ON_NDEBUG() +RUBY3_ATTR_CONSTEXPR_ON_NDEBUG(CXX14) +RUBY3_ATTR_ARTIFICIAL() +static inline VALUE +RB_INT2FIX(long i) +{ + RUBY3_ASSERT_OR_ASSUME(RB_FIXABLE(i)); + + /* :NOTE: VALUE can be wider than long. As j being unsigned, 2j+1 is fully + * defined. Also it can be compiled into a single LEA instruction. */ + const unsigned long j = i; + const unsigned long k = 2 * j + RUBY_FIXNUM_FLAG; + const long l = k; + const SIGNED_VALUE m = l; /* Sign extend */ + const VALUE n = m; + + RUBY3_ASSERT_OR_ASSUME(RB_FIXNUM_P(n)); + return n; +} + +static inline int +rb_long2int_inline(long n) +{ + int i = RUBY3_CAST((int)n); + + if /* constexpr */ (sizeof(long) <= sizeof(int)) { + RUBY3_ASSUME(i == n); + } + + if (i != n) + rb_out_of_int(n); + + return i; +} + +RUBY3_ATTR_CONST_ON_NDEBUG() +RUBY3_ATTR_CONSTEXPR_ON_NDEBUG(CXX14) +static inline long +ruby3_fix2long_by_idiv(VALUE x) +{ + RUBY3_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); + + /* :NOTE: VALUE can be wider than long. (x-1)/2 never overflows because + * RB_FIXNUM_P(x) holds. Also it has no portability issue like y>>1 + * below. */ + const SIGNED_VALUE y = x - RUBY_FIXNUM_FLAG; + const SIGNED_VALUE z = y / 2; + const long w = RUBY3_CAST((long)z); + + RUBY3_ASSERT_OR_ASSUME(RB_FIXABLE(w)); + return w; +} + +RUBY3_ATTR_CONST_ON_NDEBUG() +RUBY3_ATTR_CONSTEXPR_ON_NDEBUG(CXX14) +static inline long +ruby3_fix2long_by_shift(VALUE x) +{ + RUBY3_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); + + /* :NOTE: VALUE can be wider than long. If right shift is arithmetic, this + * is noticeably faster than above. */ + const SIGNED_VALUE y = x; + const SIGNED_VALUE z = y >> 1; + const long w = RUBY3_CAST((long)z); + + RUBY3_ASSERT_OR_ASSUME(RB_FIXABLE(w)); + return w; +} + +RUBY3_ATTR_CONST() +RUBY3_ATTR_CONSTEXPR(CXX11) +static inline bool +ruby3_right_shift_is_arithmetic_p(void) +{ + return (-1 >> 1) == -1; +} + +RUBY3_ATTR_CONST_ON_NDEBUG() +RUBY3_ATTR_CONSTEXPR_ON_NDEBUG(CXX14) +static inline long +rb_fix2long(VALUE x) +{ + if /* constexpr */ (ruby3_right_shift_is_arithmetic_p()) { + return ruby3_fix2long_by_shift(x); + } + else { + return ruby3_fix2long_by_idiv(x); + } +} + +RUBY3_ATTR_CONST_ON_NDEBUG() +RUBY3_ATTR_CONSTEXPR_ON_NDEBUG(CXX14) +static inline unsigned long +rb_fix2ulong(VALUE x) +{ + RUBY3_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); + return rb_fix2long(x); +} + +static inline long +rb_num2long_inline(VALUE x) +{ + if (RB_FIXNUM_P(x)) + return RB_FIX2LONG(x); + else + return rb_num2long(x); +} + +static inline unsigned long +rb_num2ulong_inline(VALUE x) +{ + /* This (negative fixnum would become a large unsigned long while negative + * bignum is an exception) has been THE behaviour of NUM2ULONG since the + * beginning. It is strange, but we can no longer change how it works at + * this moment. We have to get by with it. See also: + * https://bugs.ruby-lang.org/issues/9089 */ + if (RB_FIXNUM_P(x)) + return RB_FIX2ULONG(x); + else + return rb_num2ulong(x); +} + +static inline VALUE +rb_long2num_inline(long v) +{ + if (RB_FIXABLE(v)) + return RB_LONG2FIX(v); + else + return rb_int2big(v); +} + +static inline VALUE +rb_ulong2num_inline(unsigned long v) +{ + if (RB_POSFIXABLE(v)) + return RB_LONG2FIX(v); + else + return rb_uint2big(v); +} + +/** + * @cond INTERNAL_MACRO + * + * Following overload is necessary because sometimes INT2FIX is used as a enum + * value (e.g. `enum { FOO = INT2FIX(0) };`). THIS IS NG in theory because a + * VALUE does not fit into an enum (which must be a signed int). But we cannot + * break existing codes. + */ +#if RUBY3_HAS_ATTR_CONSTEXPR_CXX14 +# /* C++ can write constexpr as enum values. */ + +#elif ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) +# undef INT2FIX +# define INT2FIX(i) (RUBY3_CAST((VALUE)(i)) << 1 | RUBY_FIXNUM_FLAG) + +#else +# undef INT2FIX +# define INT2FIX(i) \ + __builtin_choose_expr( \ + __builtin_constant_p(i), \ + RUBY3_CAST((VALUE)(i)) << 1 | RUBY_FIXNUM_FLAG, \ + RB_INT2FIX(i)) +#endif +/** @endcond */ + +#endif /* RUBY3_ARITHMETIC_LONG_H */ diff --git a/include/ruby/impl/arithmetic/long_long.h b/include/ruby/impl/arithmetic/long_long.h new file mode 100644 index 0000000000..1dfe0f6f71 --- /dev/null +++ b/include/ruby/impl/arithmetic/long_long.h @@ -0,0 +1,53 @@ +#ifndef RUBY3_ARITHMETIC_LONG_LONG_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMETIC_LONG_LONG_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `long long` and Ruby's. + */ +#include "ruby/3/value.h" +#include "ruby/3/dllexport.h" +#include "ruby/3/special_consts.h" +#include "ruby/backward/2/long_long.h" + +#define RB_LL2NUM rb_ll2inum +#define RB_ULL2NUM rb_ull2inum +#define LL2NUM RB_LL2NUM +#define ULL2NUM RB_ULL2NUM +#define RB_NUM2LL rb_num2ll_inline +#define RB_NUM2ULL rb_num2ull +#define NUM2LL RB_NUM2LL +#define NUM2ULL RB_NUM2ULL + +RUBY3_SYMBOL_EXPORT_BEGIN() +VALUE rb_ll2inum(LONG_LONG); +VALUE rb_ull2inum(unsigned LONG_LONG); +LONG_LONG rb_num2ll(VALUE); +unsigned LONG_LONG rb_num2ull(VALUE); +RUBY3_SYMBOL_EXPORT_END() + +static inline LONG_LONG +rb_num2ll_inline(VALUE x) +{ + if (RB_FIXNUM_P(x)) + return RB_FIX2LONG(x); + else + return rb_num2ll(x); +} + +#endif /* RUBY3_ARITHMETIC_LONG_LONG_H */ diff --git a/include/ruby/impl/arithmetic/mode_t.h b/include/ruby/impl/arithmetic/mode_t.h new file mode 100644 index 0000000000..ea6386305a --- /dev/null +++ b/include/ruby/impl/arithmetic/mode_t.h @@ -0,0 +1,34 @@ +#ifndef RUBY3_ARITHMETIC_MODE_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMETIC_MODE_T_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `mode_t` and Ruby's. + */ +#include "ruby/3/config.h" +#include "ruby/3/arithmetic/int.h" + +#ifndef NUM2MODET +# define NUM2MODET RB_NUM2INT +#endif + +#ifndef MODET2NUM +# define MODET2NUM RB_INT2NUM +#endif + +#endif /* RUBY3_ARITHMETIC_MODE_T_H */ diff --git a/include/ruby/impl/arithmetic/off_t.h b/include/ruby/impl/arithmetic/off_t.h new file mode 100644 index 0000000000..03d0756257 --- /dev/null +++ b/include/ruby/impl/arithmetic/off_t.h @@ -0,0 +1,49 @@ +#ifndef RUBY3_ARITHMETIC_OFF_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMETIC_OFF_T_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `off_t` and Ruby's. + */ +#include "ruby/3/config.h" +#include "ruby/3/arithmetic/int.h" +#include "ruby/3/arithmetic/long.h" +#include "ruby/3/arithmetic/long_long.h" +#include "ruby/backward/2/long_long.h" + +#ifdef OFFT2NUM +# /* take that. */ +#elif SIZEOF_OFF_T == SIZEOF_LONG_LONG +# define OFFT2NUM RB_LL2NUM +#elif SIZEOF_OFF_T == SIZEOF_LONG +# define OFFT2NUM RB_LONG2NUM +#else +# define OFFT2NUM RB_INT2NUM +#endif + +#ifdef NUM2OFFT +# /* take that. */ +#elif SIZEOF_OFF_T == SIZEOF_LONG_LONG +# define NUM2OFFT RB_NUM2LL +#elif SIZEOF_OFF_T == SIZEOF_LONG +# define NUM2OFFT RB_NUM2LONG +#else +# define NUM2OFFT RB_NUM2INT +#endif + +#endif /* RUBY3_ARITHMETIC_OFF_T_H */ diff --git a/include/ruby/impl/arithmetic/pid_t.h b/include/ruby/impl/arithmetic/pid_t.h new file mode 100644 index 0000000000..e63d9e3049 --- /dev/null +++ b/include/ruby/impl/arithmetic/pid_t.h @@ -0,0 +1,34 @@ +#ifndef RUBY3_ARITHMETIC_PID_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMETIC_PID_T_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `pid_t` and Ruby's. + */ +#include "ruby/3/config.h" +#include "ruby/3/arithmetic/long.h" + +#ifndef PIDT2NUM +# define PIDT2NUM RB_LONG2NUM +#endif + +#ifndef NUM2PIDT +# define NUM2PIDT RB_NUM2LONG +#endif + +#endif /* RUBY3_ARITHMETIC_PID_T_H */ diff --git a/include/ruby/impl/arithmetic/short.h b/include/ruby/impl/arithmetic/short.h new file mode 100644 index 0000000000..4fb07a8d03 --- /dev/null +++ b/include/ruby/impl/arithmetic/short.h @@ -0,0 +1,54 @@ +#ifndef RUBY3_ARITHMETIC_SHORT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMETIC_SHORT_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `short` and Ruby's. + * + * Shyouhei wonders: why there is no SHORT2NUM, given there are both + * #USHORT2NUM and #CHR2FIX? + */ +#include "ruby/3/value.h" +#include "ruby/3/dllexport.h" +#include "ruby/3/special_consts.h" + +#define RB_NUM2SHORT rb_num2short_inline +#define RB_NUM2USHORT rb_num2ushort +#define NUM2SHORT RB_NUM2SHORT +#define NUM2USHORT RB_NUM2USHORT +#define USHORT2NUM RB_INT2FIX +#define RB_FIX2SHORT rb_fix2short +#define FIX2SHORT RB_FIX2SHORT + +RUBY3_SYMBOL_EXPORT_BEGIN() +short rb_num2short(VALUE); +unsigned short rb_num2ushort(VALUE); +short rb_fix2short(VALUE); +unsigned short rb_fix2ushort(VALUE); +RUBY3_SYMBOL_EXPORT_END() + +static inline short +rb_num2short_inline(VALUE x) +{ + if (RB_FIXNUM_P(x)) + return rb_fix2short(x); + else + return rb_num2short(x); +} + +#endif /* RUBY3_ARITHMETIC_SOHRT_H */ diff --git a/include/ruby/impl/arithmetic/size_t.h b/include/ruby/impl/arithmetic/size_t.h new file mode 100644 index 0000000000..848a3f1271 --- /dev/null +++ b/include/ruby/impl/arithmetic/size_t.h @@ -0,0 +1,51 @@ +#ifndef RUBY3_ARITHMETIC_SIZE_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMETIC_SIZE_T_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `size_t` and Ruby's. + */ +#include "ruby/3/config.h" +#include "ruby/3/arithmetic/int.h" +#include "ruby/3/arithmetic/long.h" +#include "ruby/3/arithmetic/long_long.h" +#include "ruby/backward/2/long_long.h" + +#if SIZEOF_SIZE_T == SIZEOF_LONG_LONG +# define SIZET2NUM RB_ULL2NUM +# define SSIZET2NUM RB_LL2NUM +#elif SIZEOF_SIZE_T == SIZEOF_LONG +# define SIZET2NUM RB_ULONG2NUM +# define SSIZET2NUM RB_LONG2NUM +#else +# define SIZET2NUM RB_UINT2NUM +# define SSIZET2NUM RB_INT2NUM +#endif + +#if SIZEOF_SIZE_T == SIZEOF_LONG_LONG +# define NUM2SIZET RB_NUM2ULL +# define NUM2SSIZET RB_NUM2LL +#elif SIZEOF_SIZE_T == SIZEOF_LONG +# define NUM2SIZET RB_NUM2ULONG +# define NUM2SSIZET RB_NUM2LONG +#else +# define NUM2SIZET RB_NUM2UINT +# define NUM2SSIZET RB_NUM2INT +#endif + +#endif /* RUBY3_ARITHMETIC_SIZE_T_H */ diff --git a/include/ruby/impl/arithmetic/st_data_t.h b/include/ruby/impl/arithmetic/st_data_t.h new file mode 100644 index 0000000000..f9a28ce1db --- /dev/null +++ b/include/ruby/impl/arithmetic/st_data_t.h @@ -0,0 +1,59 @@ +#ifndef RUBY3_ARITHMERIC_ST_DATA_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMERIC_ST_DATA_T_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `st_data_t` and Ruby's. + */ +#include "ruby/3/arithmetic/fixnum.h" +#include "ruby/3/arithmetic/long.h" +#include "ruby/3/attr/artificial.h" +#include "ruby/3/attr/const.h" +#include "ruby/3/attr/constexpr.h" +#include "ruby/3/cast.h" +#include "ruby/3/value.h" +#include "ruby/assert.h" +#include "ruby/st.h" + +#define ST2FIX RB_ST2FIX +/** @cond INTERNAL_MACRO */ +#define RB_ST2FIX RB_ST2FIX +/** @endcond */ + +RUBY3_ATTR_CONST_ON_NDEBUG() +RUBY3_ATTR_CONSTEXPR_ON_NDEBUG(CXX14) +RUBY3_ATTR_ARTIFICIAL() +/* See also [ruby-core:84395] [Bug #14218] [ruby-core:82687] [Bug #13877] */ +static inline VALUE +RB_ST2FIX(st_data_t i) +{ + SIGNED_VALUE x = i; + + if (x >= 0) { + x &= RUBY_FIXNUM_MAX; + } + else { + x |= RUBY_FIXNUM_MIN; + } + + RUBY3_ASSERT_OR_ASSUME(RB_FIXABLE(x)); + unsigned long y = RUBY3_CAST((unsigned long)x); + return RB_LONG2FIX(y); +} + +#endif /* RUBY3_ARITHMERIC_ST_DATA_T_H */ diff --git a/include/ruby/impl/arithmetic/uid_t.h b/include/ruby/impl/arithmetic/uid_t.h new file mode 100644 index 0000000000..c49b79e934 --- /dev/null +++ b/include/ruby/impl/arithmetic/uid_t.h @@ -0,0 +1,34 @@ +#ifndef RUBY3_ARITHMETIC_UID_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY3_ARITHMETIC_UID_T_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RUBY3` or `ruby3` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `uid_t` and Ruby's. + */ +#include "ruby/3/config.h" +#include "ruby/3/arithmetic/long.h" + +#ifndef UIDT2NUM +# define UIDT2NUM RB_LONG2NUM +#endif + +#ifndef NUM2UIDT +# define NUM2UIDT RB_NUM2LONG +#endif + +#endif /* RUBY3_ARITHMETIC_UID_T_H */ diff --git a/include/ruby/impl/assume.h b/include/ruby/impl/assume.h new file mode 100644 index 0000000000..98059d7cbf --- /dev/null +++ b/ |