kanayago 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rubocop.yml +15 -0
- data/.rubocop_todo.yml +23 -0
- data/LICENSE.txt +21 -0
- data/README.md +79 -0
- data/Rakefile +182 -0
- data/ext/kanayago/ccan/check_type/check_type.h +63 -0
- data/ext/kanayago/ccan/container_of/container_of.h +142 -0
- data/ext/kanayago/ccan/list/list.h +791 -0
- data/ext/kanayago/ccan/str/str.h +17 -0
- data/ext/kanayago/constant.h +53 -0
- data/ext/kanayago/extconf.rb +21 -0
- data/ext/kanayago/id.h +347 -0
- data/ext/kanayago/id_table.h +39 -0
- data/ext/kanayago/internal/array.h +151 -0
- data/ext/kanayago/internal/basic_operators.h +64 -0
- data/ext/kanayago/internal/bignum.h +244 -0
- data/ext/kanayago/internal/bits.h +568 -0
- data/ext/kanayago/internal/compile.h +34 -0
- data/ext/kanayago/internal/compilers.h +107 -0
- data/ext/kanayago/internal/complex.h +29 -0
- data/ext/kanayago/internal/encoding.h +36 -0
- data/ext/kanayago/internal/error.h +218 -0
- data/ext/kanayago/internal/fixnum.h +184 -0
- data/ext/kanayago/internal/gc.h +322 -0
- data/ext/kanayago/internal/hash.h +191 -0
- data/ext/kanayago/internal/imemo.h +261 -0
- data/ext/kanayago/internal/io.h +140 -0
- data/ext/kanayago/internal/numeric.h +274 -0
- data/ext/kanayago/internal/parse.h +117 -0
- data/ext/kanayago/internal/rational.h +71 -0
- data/ext/kanayago/internal/re.h +28 -0
- data/ext/kanayago/internal/ruby_parser.h +125 -0
- data/ext/kanayago/internal/sanitizers.h +297 -0
- data/ext/kanayago/internal/serial.h +23 -0
- data/ext/kanayago/internal/static_assert.h +16 -0
- data/ext/kanayago/internal/string.h +186 -0
- data/ext/kanayago/internal/symbol.h +45 -0
- data/ext/kanayago/internal/thread.h +79 -0
- data/ext/kanayago/internal/variable.h +72 -0
- data/ext/kanayago/internal/vm.h +137 -0
- data/ext/kanayago/internal/warnings.h +16 -0
- data/ext/kanayago/internal.h +108 -0
- data/ext/kanayago/kanayago.c +420 -0
- data/ext/kanayago/kanayago.h +21 -0
- data/ext/kanayago/lex.c +302 -0
- data/ext/kanayago/method.h +255 -0
- data/ext/kanayago/node.c +440 -0
- data/ext/kanayago/node.h +111 -0
- data/ext/kanayago/node_name.inc +224 -0
- data/ext/kanayago/parse.c +26931 -0
- data/ext/kanayago/parse.h +244 -0
- data/ext/kanayago/parse.tmp.y +16145 -0
- data/ext/kanayago/parser_bits.h +564 -0
- data/ext/kanayago/parser_node.h +32 -0
- data/ext/kanayago/parser_st.c +164 -0
- data/ext/kanayago/parser_st.h +162 -0
- data/ext/kanayago/parser_value.h +106 -0
- data/ext/kanayago/probes.h +4 -0
- data/ext/kanayago/ruby_assert.h +14 -0
- data/ext/kanayago/ruby_atomic.h +23 -0
- data/ext/kanayago/ruby_parser.c +1165 -0
- data/ext/kanayago/rubyparser.h +1391 -0
- data/ext/kanayago/shape.h +234 -0
- data/ext/kanayago/st.c +2339 -0
- data/ext/kanayago/symbol.h +123 -0
- data/ext/kanayago/thread_pthread.h +168 -0
- data/ext/kanayago/universal_parser.c +230 -0
- data/ext/kanayago/vm_core.h +2215 -0
- data/ext/kanayago/vm_opts.h +67 -0
- data/lib/kanayago/version.rb +5 -0
- data/lib/kanayago.rb +11 -0
- data/sig/kanayago.rbs +4 -0
- metadata +116 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
#ifndef INTERNAL_COMPLEX_H /*-*-C-*-vi:se ft=c:*/
|
2
|
+
#define INTERNAL_COMPLEX_H
|
3
|
+
/**
|
4
|
+
* @author Ruby developers <ruby-core@ruby-lang.org>
|
5
|
+
* @copyright This file is a part of the programming language Ruby.
|
6
|
+
* Permission is hereby granted, to either redistribute and/or
|
7
|
+
* modify this file, provided that the conditions mentioned in the
|
8
|
+
* file COPYING are met. Consult the file for details.
|
9
|
+
* @brief Internal header for Complex.
|
10
|
+
*/
|
11
|
+
#include "ruby/internal/value.h" /* for struct RBasic */
|
12
|
+
|
13
|
+
struct RComplex {
|
14
|
+
struct RBasic basic;
|
15
|
+
VALUE real;
|
16
|
+
VALUE imag;
|
17
|
+
};
|
18
|
+
|
19
|
+
#define RCOMPLEX(obj) ((struct RComplex *)(obj))
|
20
|
+
|
21
|
+
/* shortcut macro for internal only */
|
22
|
+
#define RCOMPLEX_SET_REAL(cmp, r) RB_OBJ_WRITE((cmp), &RCOMPLEX(cmp)->real, (r))
|
23
|
+
#define RCOMPLEX_SET_IMAG(cmp, i) RB_OBJ_WRITE((cmp), &RCOMPLEX(cmp)->imag, (i))
|
24
|
+
|
25
|
+
/* complex.c */
|
26
|
+
VALUE rb_dbl_complex_new_polar_pi(double abs, double ang);
|
27
|
+
st_index_t rb_complex_hash(VALUE comp);
|
28
|
+
|
29
|
+
#endif /* INTERNAL_COMPLEX_H */
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#ifndef INTERNAL_ENCODING_H /*-*-C-*-vi:se ft=c:*/
|
2
|
+
#define INTERNAL_ENCODING_H
|
3
|
+
/**
|
4
|
+
* @author Ruby developers <ruby-core@ruby-lang.org>
|
5
|
+
* @copyright This file is a part of the programming language Ruby.
|
6
|
+
* Permission is hereby granted, to either redistribute and/or
|
7
|
+
* modify this file, provided that the conditions mentioned in the
|
8
|
+
* file COPYING are met. Consult the file for details.
|
9
|
+
* @brief Internal header for Encoding.
|
10
|
+
*/
|
11
|
+
#include "ruby/ruby.h" /* for ID */
|
12
|
+
#include "ruby/encoding.h" /* for rb_encoding */
|
13
|
+
|
14
|
+
#define rb_enc_autoload_p(enc) (!rb_enc_mbmaxlen(enc))
|
15
|
+
#define rb_is_usascii_enc(enc) ((enc) == rb_usascii_encoding())
|
16
|
+
#define rb_is_ascii8bit_enc(enc) ((enc) == rb_ascii8bit_encoding())
|
17
|
+
#define rb_is_locale_enc(enc) ((enc) == rb_locale_encoding())
|
18
|
+
|
19
|
+
/* encoding.c */
|
20
|
+
ID rb_id_encoding(void);
|
21
|
+
const char * rb_enc_inspect_name(rb_encoding *enc);
|
22
|
+
rb_encoding *rb_enc_get_from_index(int index);
|
23
|
+
rb_encoding *rb_enc_check_str(VALUE str1, VALUE str2);
|
24
|
+
int rb_encdb_replicate(const char *alias, const char *orig);
|
25
|
+
int rb_encdb_alias(const char *alias, const char *orig);
|
26
|
+
int rb_enc_autoload(rb_encoding *enc);
|
27
|
+
int rb_encdb_dummy(const char *name);
|
28
|
+
void rb_encdb_declare(const char *name);
|
29
|
+
void rb_enc_set_base(const char *name, const char *orig);
|
30
|
+
int rb_enc_set_dummy(int index);
|
31
|
+
PUREFUNC(int rb_data_is_encoding(VALUE obj));
|
32
|
+
|
33
|
+
/* vm.c */
|
34
|
+
void rb_free_global_enc_table(void);
|
35
|
+
|
36
|
+
#endif /* INTERNAL_ENCODING_H */
|
@@ -0,0 +1,218 @@
|
|
1
|
+
#ifndef INTERNAL_ERROR_H /*-*-C-*-vi:se ft=c:*/
|
2
|
+
#define INTERNAL_ERROR_H
|
3
|
+
/**
|
4
|
+
* @author Ruby developers <ruby-core@ruby-lang.org>
|
5
|
+
* @copyright This file is a part of the programming language Ruby.
|
6
|
+
* Permission is hereby granted, to either redistribute and/or
|
7
|
+
* modify this file, provided that the conditions mentioned in the
|
8
|
+
* file COPYING are met. Consult the file for details.
|
9
|
+
* @brief Internal header for Exception.
|
10
|
+
*/
|
11
|
+
#include "ruby/internal/config.h"
|
12
|
+
#include <stdarg.h> /* for va_list */
|
13
|
+
#include "internal/string.h" /* for rb_fstring_cstr */
|
14
|
+
#include "ruby/internal/stdbool.h" /* for bool */
|
15
|
+
#include "ruby/encoding.h" /* for rb_encoding */
|
16
|
+
#include "ruby/intern.h" /* for rb_exc_raise */
|
17
|
+
#include "ruby/ruby.h" /* for enum ruby_value_type */
|
18
|
+
|
19
|
+
#ifdef Check_Type
|
20
|
+
# undef Check_Type /* in ruby/ruby.h */
|
21
|
+
#endif
|
22
|
+
|
23
|
+
#ifdef rb_raise_static
|
24
|
+
# undef rb_raise_static
|
25
|
+
# undef rb_sys_fail_path
|
26
|
+
# undef rb_syserr_fail_path
|
27
|
+
#endif
|
28
|
+
|
29
|
+
#define rb_raise_static(e, m) \
|
30
|
+
rb_raise_cstr_i((e), rb_str_new_static((m), rb_strlen_lit(m)))
|
31
|
+
#ifdef RUBY_FUNCTION_NAME_STRING
|
32
|
+
# define rb_syserr_fail_path(err, path) rb_syserr_fail_path_in(RUBY_FUNCTION_NAME_STRING, (err), (path))
|
33
|
+
# define rb_syserr_new_path(err, path) rb_syserr_new_path_in(RUBY_FUNCTION_NAME_STRING, (err), (path))
|
34
|
+
#else
|
35
|
+
# define rb_syserr_fail_path(err, path) rb_syserr_fail_str((err), (path))
|
36
|
+
# define rb_syserr_new_path(err, path) rb_syserr_new_str((err), (path))
|
37
|
+
#endif
|
38
|
+
|
39
|
+
#define rb_sys_fail(mesg) \
|
40
|
+
do { \
|
41
|
+
int errno_to_fail = errno; \
|
42
|
+
rb_syserr_fail(errno_to_fail, (mesg)); \
|
43
|
+
} while (0)
|
44
|
+
|
45
|
+
#define rb_sys_fail_str(mesg) \
|
46
|
+
do { \
|
47
|
+
int errno_to_fail = errno; \
|
48
|
+
rb_syserr_fail_str(errno_to_fail, (mesg)); \
|
49
|
+
} while (0)
|
50
|
+
|
51
|
+
#define rb_sys_fail_path(path) \
|
52
|
+
do { \
|
53
|
+
int errno_to_fail = errno; \
|
54
|
+
rb_syserr_fail_path(errno_to_fail, (path)); \
|
55
|
+
} while (0)
|
56
|
+
|
57
|
+
#define rb_sys_fail_sprintf(...) \
|
58
|
+
do { \
|
59
|
+
int errno_to_fail = errno; \
|
60
|
+
rb_syserr_fail_str(errno_to_fail, rb_sprintf("" __VA_ARGS__)); \
|
61
|
+
} while (0)
|
62
|
+
|
63
|
+
/* error.c */
|
64
|
+
extern long rb_backtrace_length_limit;
|
65
|
+
extern VALUE rb_eEAGAIN;
|
66
|
+
extern VALUE rb_eEWOULDBLOCK;
|
67
|
+
extern VALUE rb_eEINPROGRESS;
|
68
|
+
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 0)
|
69
|
+
void rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args);
|
70
|
+
NORETURN(void rb_async_bug_errno(const char *,int));
|
71
|
+
const char *rb_builtin_type_name(int t);
|
72
|
+
const char *rb_builtin_class_name(VALUE x);
|
73
|
+
PRINTF_ARGS(void rb_warn_deprecated(const char *fmt, const char *suggest, ...), 1, 3);
|
74
|
+
PRINTF_ARGS(void rb_warn_deprecated_to_remove(const char *removal, const char *fmt, const char *suggest, ...), 2, 4);
|
75
|
+
#if RUBY_DEBUG
|
76
|
+
# include "ruby/version.h"
|
77
|
+
# define RUBY_VERSION_SINCE(major, minor) (RUBY_API_VERSION_CODE >= (major * 10000) + (minor) * 100)
|
78
|
+
# define RUBY_VERSION_BEFORE(major, minor) (RUBY_API_VERSION_CODE < (major * 10000) + (minor) * 100)
|
79
|
+
# if defined(RBIMPL_WARNING_PRAGMA0)
|
80
|
+
# define RBIMPL_TODO0(x) RBIMPL_WARNING_PRAGMA0(message(x))
|
81
|
+
# elif RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0)
|
82
|
+
# define RBIMPL_TODO0(x) __pragma(message(x))
|
83
|
+
# endif
|
84
|
+
|
85
|
+
# if RBIMPL_HAS_ATTRIBUTE(diagnose_if) || defined(__OPTIMIZE__)
|
86
|
+
|
87
|
+
#define RUBY_VERSION_isdigit(c) ('0'<=(c)&&(c)<='9')
|
88
|
+
// upto 99
|
89
|
+
#define RUBY_VERSION__number_len(v, ofs) \
|
90
|
+
(!RUBY_VERSION_isdigit((v)[ofs]) ? \
|
91
|
+
0 : !RUBY_VERSION_isdigit((v)[(ofs) + 1]) ? 1 : 2)
|
92
|
+
#define RUBY_VERSION__to_number(v, ofs) \
|
93
|
+
(!RUBY_VERSION_isdigit((v)[ofs]) ? \
|
94
|
+
0 : !RUBY_VERSION_isdigit((v)[(ofs) + 1]) ? \
|
95
|
+
((v)[ofs]-'0') : \
|
96
|
+
(((v)[ofs]-'0')*10+(v)[(ofs)+1]-'0'))
|
97
|
+
|
98
|
+
#define RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v) \
|
99
|
+
(RUBY_VERSION__to_number(v, 0) * 10000 + \
|
100
|
+
((v)[RUBY_VERSION__number_len(v, 0)] == '.' ? \
|
101
|
+
RUBY_VERSION__to_number(v, RUBY_VERSION__number_len(v, 0)+1) * 100 : 0))
|
102
|
+
#define RUBY_VERSION_STRING_SINCE(v) (RUBY_API_VERSION_CODE >= RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v))
|
103
|
+
#define RUBY_VERSION_STRING_BEFORE(v) (RUBY_API_VERSION_CODE < RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v))
|
104
|
+
|
105
|
+
# if RBIMPL_HAS_ATTRIBUTE(diagnose_if)
|
106
|
+
RBIMPL_ATTR_FORCEINLINE()
|
107
|
+
static void
|
108
|
+
rb_deprecated_method_to_be_removed(const char *removal)
|
109
|
+
RBIMPL_ATTR_DIAGNOSE_IF(!RUBY_VERSION_isdigit(removal[0]), "malformed version number", "error")
|
110
|
+
RBIMPL_ATTR_DIAGNOSE_IF(RUBY_VERSION_STRING_SINCE(removal), "deprecated method to be removed", "error")
|
111
|
+
{
|
112
|
+
}
|
113
|
+
# else
|
114
|
+
RBIMPL_ATTR_ERROR(("deprecated"))
|
115
|
+
void rb_deprecated_method_to_be_removed(const char *);
|
116
|
+
# define rb_deprecated_method_to_be_removed(removal) \
|
117
|
+
(sizeof(char[1-2*(!RUBY_VERSION_isdigit(removal[0]) || RUBY_VERSION_STRING_SINCE(removal))])!=1 ? \
|
118
|
+
rb_deprecated_method_to_be_removed(removal) : \
|
119
|
+
RBIMPL_ASSERT_NOTHING)
|
120
|
+
# endif
|
121
|
+
# define rb_warn_deprecated_to_remove_at(removal, ...) \
|
122
|
+
(rb_deprecated_method_to_be_removed(#removal), \
|
123
|
+
rb_warn_deprecated_to_remove(#removal, __VA_ARGS__))
|
124
|
+
# endif
|
125
|
+
#endif
|
126
|
+
#ifndef rb_warn_deprecated_to_remove_at
|
127
|
+
# define rb_warn_deprecated_to_remove_at(removal, ...) \
|
128
|
+
rb_warn_deprecated_to_remove(#removal, __VA_ARGS__)
|
129
|
+
#endif
|
130
|
+
#ifndef RUBY_VERSION_SINCE
|
131
|
+
# define RUBY_VERSION_SINCE(major, minor) 0
|
132
|
+
#endif
|
133
|
+
#ifndef RUBY_VERSION_BEFORE
|
134
|
+
# define RUBY_VERSION_BEFORE(major, minor) 0
|
135
|
+
#endif
|
136
|
+
#ifndef RBIMPL_TODO0
|
137
|
+
# define RBIMPL_TODO0(x)
|
138
|
+
#endif
|
139
|
+
#define RBIMPL_TODO(message) RBIMPL_TODO0("TODO: " message)
|
140
|
+
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 6, 0)
|
141
|
+
VALUE rb_syntax_error_append(VALUE, VALUE, int, int, rb_encoding*, const char*, va_list);
|
142
|
+
PRINTF_ARGS(void rb_enc_warn(rb_encoding *enc, const char *fmt, ...), 2, 3);
|
143
|
+
PRINTF_ARGS(void rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...), 2, 3);
|
144
|
+
PRINTF_ARGS(void rb_syserr_enc_warning(int err, rb_encoding *enc, const char *fmt, ...), 3, 4);
|
145
|
+
PRINTF_ARGS(void rb_enc_compile_warning(rb_encoding *enc, const char *file, int line, const char *fmt, ...), 4, 5);
|
146
|
+
PRINTF_ARGS(void rb_enc_compile_warn(rb_encoding *enc, const char *file, int line, const char *fmt, ...), 4, 5);
|
147
|
+
rb_warning_category_t rb_warning_category_from_name(VALUE category);
|
148
|
+
bool rb_warning_category_enabled_p(rb_warning_category_t category);
|
149
|
+
VALUE rb_name_err_new(VALUE mesg, VALUE recv, VALUE method);
|
150
|
+
VALUE rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv);
|
151
|
+
VALUE rb_key_err_new(VALUE mesg, VALUE recv, VALUE name);
|
152
|
+
PRINTF_ARGS(VALUE rb_warning_string(const char *fmt, ...), 1, 2);
|
153
|
+
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0)
|
154
|
+
NORETURN(void rb_vraise(VALUE, const char *, va_list));
|
155
|
+
NORETURN(static inline void rb_raise_cstr(VALUE etype, const char *mesg));
|
156
|
+
NORETURN(static inline void rb_raise_cstr_i(VALUE etype, VALUE mesg));
|
157
|
+
NORETURN(static inline void rb_name_err_raise_str(VALUE mesg, VALUE recv, VALUE name));
|
158
|
+
NORETURN(static inline void rb_name_err_raise(const char *mesg, VALUE recv, VALUE name));
|
159
|
+
NORETURN(static inline void rb_key_err_raise(VALUE mesg, VALUE recv, VALUE name));
|
160
|
+
static inline void Check_Type(VALUE v, enum ruby_value_type t);
|
161
|
+
static inline bool rb_typeddata_is_instance_of_inline(VALUE obj, const rb_data_type_t *data_type);
|
162
|
+
#define rb_typeddata_is_instance_of rb_typeddata_is_instance_of_inline
|
163
|
+
|
164
|
+
RUBY_SYMBOL_EXPORT_BEGIN
|
165
|
+
/* error.c (export) */
|
166
|
+
int rb_bug_reporter_add(void (*func)(FILE *, void *), void *data);
|
167
|
+
#ifdef RUBY_FUNCTION_NAME_STRING
|
168
|
+
NORETURN(void rb_sys_fail_path_in(const char *func_name, VALUE path));
|
169
|
+
NORETURN(void rb_syserr_fail_path_in(const char *func_name, int err, VALUE path));
|
170
|
+
VALUE rb_syserr_new_path_in(const char *func_name, int n, VALUE path);
|
171
|
+
#endif
|
172
|
+
RUBY_SYMBOL_EXPORT_END
|
173
|
+
|
174
|
+
/* vm.c */
|
175
|
+
void rb_free_warning(void);
|
176
|
+
|
177
|
+
static inline void
|
178
|
+
rb_raise_cstr_i(VALUE etype, VALUE mesg)
|
179
|
+
{
|
180
|
+
VALUE exc = rb_exc_new_str(etype, mesg);
|
181
|
+
rb_exc_raise(exc);
|
182
|
+
}
|
183
|
+
|
184
|
+
static inline void
|
185
|
+
rb_raise_cstr(VALUE etype, const char *mesg)
|
186
|
+
{
|
187
|
+
VALUE str = rb_str_new_cstr(mesg);
|
188
|
+
rb_raise_cstr_i(etype, str);
|
189
|
+
}
|
190
|
+
|
191
|
+
static inline void
|
192
|
+
rb_name_err_raise_str(VALUE mesg, VALUE recv, VALUE name)
|
193
|
+
{
|
194
|
+
VALUE exc = rb_name_err_new(mesg, recv, name);
|
195
|
+
rb_exc_raise(exc);
|
196
|
+
}
|
197
|
+
|
198
|
+
static inline void
|
199
|
+
rb_name_err_raise(const char *mesg, VALUE recv, VALUE name)
|
200
|
+
{
|
201
|
+
VALUE str = rb_fstring_cstr(mesg);
|
202
|
+
rb_name_err_raise_str(str, recv, name);
|
203
|
+
}
|
204
|
+
|
205
|
+
static inline void
|
206
|
+
rb_key_err_raise(VALUE mesg, VALUE recv, VALUE name)
|
207
|
+
{
|
208
|
+
VALUE exc = rb_key_err_new(mesg, recv, name);
|
209
|
+
rb_exc_raise(exc);
|
210
|
+
}
|
211
|
+
|
212
|
+
static inline bool
|
213
|
+
rb_typeddata_is_instance_of_inline(VALUE obj, const rb_data_type_t *data_type)
|
214
|
+
{
|
215
|
+
return RB_TYPE_P(obj, T_DATA) && RTYPEDDATA_P(obj) && (RTYPEDDATA_TYPE(obj) == data_type);
|
216
|
+
}
|
217
|
+
|
218
|
+
#endif /* INTERNAL_ERROR_H */
|
@@ -0,0 +1,184 @@
|
|
1
|
+
#ifndef INTERNAL_FIXNUM_H /*-*-C-*-vi:se ft=c:*/
|
2
|
+
#define INTERNAL_FIXNUM_H
|
3
|
+
/**
|
4
|
+
* @author Ruby developers <ruby-core@ruby-lang.org>
|
5
|
+
* @copyright This file is a part of the programming language Ruby.
|
6
|
+
* Permission is hereby granted, to either redistribute and/or
|
7
|
+
* modify this file, provided that the conditions mentioned in the
|
8
|
+
* file COPYING are met. Consult the file for details.
|
9
|
+
* @brief Internal header for Fixnums.
|
10
|
+
*/
|
11
|
+
#include "ruby/internal/config.h" /* for HAVE_LONG_LONG */
|
12
|
+
#include <limits.h> /* for CHAR_BIT */
|
13
|
+
#include "internal/compilers.h" /* for __has_builtin */
|
14
|
+
#include "ruby/internal/stdbool.h" /* for bool */
|
15
|
+
#include "ruby/intern.h" /* for rb_big_mul */
|
16
|
+
#include "ruby/ruby.h" /* for RB_FIXABLE */
|
17
|
+
|
18
|
+
#if HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
|
19
|
+
# define DLONG LONG_LONG
|
20
|
+
# define DL2NUM(x) LL2NUM(x)
|
21
|
+
#elif defined(HAVE_INT128_T) && !(defined(__OpenBSD__) && defined(__mips64__))
|
22
|
+
# define DLONG int128_t
|
23
|
+
# define DL2NUM(x) (RB_FIXABLE(x) ? LONG2FIX(x) : rb_int128t2big(x))
|
24
|
+
VALUE rb_int128t2big(int128_t n); /* in bignum.c */
|
25
|
+
#endif
|
26
|
+
|
27
|
+
static inline long rb_overflowed_fix_to_int(long x);
|
28
|
+
static inline VALUE rb_fix_plus_fix(VALUE x, VALUE y);
|
29
|
+
static inline VALUE rb_fix_minus_fix(VALUE x, VALUE y);
|
30
|
+
static inline VALUE rb_fix_mul_fix(VALUE x, VALUE y);
|
31
|
+
static inline void rb_fix_divmod_fix(VALUE x, VALUE y, VALUE *divp, VALUE *modp);
|
32
|
+
static inline VALUE rb_fix_div_fix(VALUE x, VALUE y);
|
33
|
+
static inline VALUE rb_fix_mod_fix(VALUE x, VALUE y);
|
34
|
+
static inline bool FIXNUM_POSITIVE_P(VALUE num);
|
35
|
+
static inline bool FIXNUM_NEGATIVE_P(VALUE num);
|
36
|
+
static inline bool FIXNUM_ZERO_P(VALUE num);
|
37
|
+
|
38
|
+
static inline long
|
39
|
+
rb_overflowed_fix_to_int(long x)
|
40
|
+
{
|
41
|
+
return (long)((unsigned long)(x >> 1) ^ (1LU << (SIZEOF_LONG * CHAR_BIT - 1)));
|
42
|
+
}
|
43
|
+
|
44
|
+
static inline VALUE
|
45
|
+
rb_fix_plus_fix(VALUE x, VALUE y)
|
46
|
+
{
|
47
|
+
#if !__has_builtin(__builtin_add_overflow)
|
48
|
+
long lz = FIX2LONG(x) + FIX2LONG(y);
|
49
|
+
return LONG2NUM(lz);
|
50
|
+
#else
|
51
|
+
long lz;
|
52
|
+
/* NOTE
|
53
|
+
* (1) `LONG2FIX(FIX2LONG(x)+FIX2LONG(y))`
|
54
|
+
+ = `((lx*2+1)/2 + (ly*2+1)/2)*2+1`
|
55
|
+
+ = `lx*2 + ly*2 + 1`
|
56
|
+
+ = `(lx*2+1) + (ly*2+1) - 1`
|
57
|
+
+ = `x + y - 1`
|
58
|
+
* (2) Fixnum's LSB is always 1.
|
59
|
+
* It means you can always run `x - 1` without overflow.
|
60
|
+
* (3) Of course `z = x + (y-1)` may overflow.
|
61
|
+
* At that time true value is
|
62
|
+
* * positive: 0b0 1xxx...1, and z = 0b1xxx...1
|
63
|
+
* * negative: 0b1 0xxx...1, and z = 0b0xxx...1
|
64
|
+
* To convert this true value to long,
|
65
|
+
* (a) Use arithmetic shift
|
66
|
+
* * positive: 0b11xxx...
|
67
|
+
* * negative: 0b00xxx...
|
68
|
+
* (b) invert MSB
|
69
|
+
* * positive: 0b01xxx...
|
70
|
+
* * negative: 0b10xxx...
|
71
|
+
*/
|
72
|
+
if (__builtin_add_overflow((long)x, (long)y-1, &lz)) {
|
73
|
+
return rb_int2big(rb_overflowed_fix_to_int(lz));
|
74
|
+
}
|
75
|
+
else {
|
76
|
+
return (VALUE)lz;
|
77
|
+
}
|
78
|
+
#endif
|
79
|
+
}
|
80
|
+
|
81
|
+
static inline VALUE
|
82
|
+
rb_fix_minus_fix(VALUE x, VALUE y)
|
83
|
+
{
|
84
|
+
#if !__has_builtin(__builtin_sub_overflow)
|
85
|
+
long lz = FIX2LONG(x) - FIX2LONG(y);
|
86
|
+
return LONG2NUM(lz);
|
87
|
+
#else
|
88
|
+
long lz;
|
89
|
+
if (__builtin_sub_overflow((long)x, (long)y-1, &lz)) {
|
90
|
+
return rb_int2big(rb_overflowed_fix_to_int(lz));
|
91
|
+
}
|
92
|
+
else {
|
93
|
+
return (VALUE)lz;
|
94
|
+
}
|
95
|
+
#endif
|
96
|
+
}
|
97
|
+
|
98
|
+
/* arguments must be Fixnum */
|
99
|
+
static inline VALUE
|
100
|
+
rb_fix_mul_fix(VALUE x, VALUE y)
|
101
|
+
{
|
102
|
+
long lx = FIX2LONG(x);
|
103
|
+
long ly = FIX2LONG(y);
|
104
|
+
#ifdef DLONG
|
105
|
+
return DL2NUM((DLONG)lx * (DLONG)ly);
|
106
|
+
#else
|
107
|
+
if (MUL_OVERFLOW_FIXNUM_P(lx, ly)) {
|
108
|
+
return rb_big_mul(rb_int2big(lx), rb_int2big(ly));
|
109
|
+
}
|
110
|
+
else {
|
111
|
+
return LONG2FIX(lx * ly);
|
112
|
+
}
|
113
|
+
#endif
|
114
|
+
}
|
115
|
+
|
116
|
+
/*
|
117
|
+
* This behaves different from C99 for negative arguments.
|
118
|
+
* Note that div may overflow fixnum.
|
119
|
+
*/
|
120
|
+
static inline void
|
121
|
+
rb_fix_divmod_fix(VALUE a, VALUE b, VALUE *divp, VALUE *modp)
|
122
|
+
{
|
123
|
+
/* assume / and % comply C99.
|
124
|
+
* ldiv(3) won't be inlined by GCC and clang.
|
125
|
+
* I expect / and % are compiled as single idiv.
|
126
|
+
*/
|
127
|
+
long x = FIX2LONG(a);
|
128
|
+
long y = FIX2LONG(b);
|
129
|
+
long div, mod;
|
130
|
+
if (x == FIXNUM_MIN && y == -1) {
|
131
|
+
if (divp) *divp = LONG2NUM(-FIXNUM_MIN);
|
132
|
+
if (modp) *modp = LONG2FIX(0);
|
133
|
+
return;
|
134
|
+
}
|
135
|
+
div = x / y;
|
136
|
+
mod = x % y;
|
137
|
+
if (y > 0 ? mod < 0 : mod > 0) {
|
138
|
+
mod += y;
|
139
|
+
div -= 1;
|
140
|
+
}
|
141
|
+
if (divp) *divp = LONG2FIX(div);
|
142
|
+
if (modp) *modp = LONG2FIX(mod);
|
143
|
+
}
|
144
|
+
|
145
|
+
/* div() for Ruby
|
146
|
+
* This behaves different from C99 for negative arguments.
|
147
|
+
*/
|
148
|
+
static inline VALUE
|
149
|
+
rb_fix_div_fix(VALUE x, VALUE y)
|
150
|
+
{
|
151
|
+
VALUE div;
|
152
|
+
rb_fix_divmod_fix(x, y, &div, NULL);
|
153
|
+
return div;
|
154
|
+
}
|
155
|
+
|
156
|
+
/* mod() for Ruby
|
157
|
+
* This behaves different from C99 for negative arguments.
|
158
|
+
*/
|
159
|
+
static inline VALUE
|
160
|
+
rb_fix_mod_fix(VALUE x, VALUE y)
|
161
|
+
{
|
162
|
+
VALUE mod;
|
163
|
+
rb_fix_divmod_fix(x, y, NULL, &mod);
|
164
|
+
return mod;
|
165
|
+
}
|
166
|
+
|
167
|
+
static inline bool
|
168
|
+
FIXNUM_POSITIVE_P(VALUE num)
|
169
|
+
{
|
170
|
+
return (SIGNED_VALUE)num > (SIGNED_VALUE)INT2FIX(0);
|
171
|
+
}
|
172
|
+
|
173
|
+
static inline bool
|
174
|
+
FIXNUM_NEGATIVE_P(VALUE num)
|
175
|
+
{
|
176
|
+
return (SIGNED_VALUE)num < 0;
|
177
|
+
}
|
178
|
+
|
179
|
+
static inline bool
|
180
|
+
FIXNUM_ZERO_P(VALUE num)
|
181
|
+
{
|
182
|
+
return num == INT2FIX(0);
|
183
|
+
}
|
184
|
+
#endif /* INTERNAL_FIXNUM_H */
|