wasm 0.0.1 → 0.0.2
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 +5 -5
- data/assets/mruby/include/mrbconf.h +143 -0
- data/assets/mruby/include/mruby.h +1284 -0
- data/assets/mruby/include/mruby/array.h +279 -0
- data/assets/mruby/include/mruby/boxing_nan.h +102 -0
- data/assets/mruby/include/mruby/boxing_no.h +56 -0
- data/assets/mruby/include/mruby/boxing_word.h +136 -0
- data/assets/mruby/include/mruby/class.h +94 -0
- data/assets/mruby/include/mruby/common.h +72 -0
- data/assets/mruby/include/mruby/compile.h +194 -0
- data/assets/mruby/include/mruby/data.h +75 -0
- data/assets/mruby/include/mruby/debug.h +66 -0
- data/assets/mruby/include/mruby/dump.h +196 -0
- data/assets/mruby/include/mruby/error.h +75 -0
- data/assets/mruby/include/mruby/gc.h +91 -0
- data/assets/mruby/include/mruby/hash.h +182 -0
- data/assets/mruby/include/mruby/irep.h +62 -0
- data/assets/mruby/include/mruby/istruct.h +47 -0
- data/assets/mruby/include/mruby/khash.h +274 -0
- data/assets/mruby/include/mruby/numeric.h +161 -0
- data/assets/mruby/include/mruby/object.h +45 -0
- data/assets/mruby/include/mruby/opcode.h +161 -0
- data/assets/mruby/include/mruby/proc.h +131 -0
- data/assets/mruby/include/mruby/range.h +49 -0
- data/assets/mruby/include/mruby/re.h +16 -0
- data/assets/mruby/include/mruby/string.h +440 -0
- data/assets/mruby/include/mruby/throw.h +55 -0
- data/assets/mruby/include/mruby/value.h +309 -0
- data/assets/mruby/include/mruby/variable.h +138 -0
- data/assets/mruby/include/mruby/version.h +110 -0
- data/assets/mruby/libmruby.a +0 -0
- data/assets/mruby_init.c +16 -0
- data/assets/template.html +17 -0
- data/bin/ruby-wasm +150 -0
- data/build_config.rb +13 -0
- data/lib/wasm.rb +0 -5
- data/lib/wasm/version.rb +4 -2
- metadata +46 -65
- data/.gitignore +0 -9
- data/.travis.yml +0 -5
- data/Gemfile +0 -4
- data/LICENSE.txt +0 -21
- data/README.md +0 -40
- data/Rakefile +0 -10
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/wasm.gemspec +0 -26
@@ -0,0 +1,62 @@
|
|
1
|
+
/*
|
2
|
+
** mruby/irep.h - mrb_irep structure
|
3
|
+
**
|
4
|
+
** See Copyright Notice in mruby.h
|
5
|
+
*/
|
6
|
+
|
7
|
+
#ifndef MRUBY_IREP_H
|
8
|
+
#define MRUBY_IREP_H
|
9
|
+
|
10
|
+
#include "common.h"
|
11
|
+
#include <mruby/compile.h>
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Compiled mruby scripts.
|
15
|
+
*/
|
16
|
+
MRB_BEGIN_DECL
|
17
|
+
|
18
|
+
enum irep_pool_type {
|
19
|
+
IREP_TT_STRING,
|
20
|
+
IREP_TT_FIXNUM,
|
21
|
+
IREP_TT_FLOAT,
|
22
|
+
};
|
23
|
+
|
24
|
+
struct mrb_locals {
|
25
|
+
mrb_sym name;
|
26
|
+
uint16_t r;
|
27
|
+
};
|
28
|
+
|
29
|
+
/* Program data array struct */
|
30
|
+
typedef struct mrb_irep {
|
31
|
+
uint16_t nlocals; /* Number of local variables */
|
32
|
+
uint16_t nregs; /* Number of register variables */
|
33
|
+
uint8_t flags;
|
34
|
+
|
35
|
+
mrb_code *iseq;
|
36
|
+
mrb_value *pool;
|
37
|
+
mrb_sym *syms;
|
38
|
+
struct mrb_irep **reps;
|
39
|
+
|
40
|
+
struct mrb_locals *lv;
|
41
|
+
/* debug info */
|
42
|
+
mrb_bool own_filename;
|
43
|
+
const char *filename;
|
44
|
+
uint16_t *lines;
|
45
|
+
struct mrb_irep_debug_info* debug_info;
|
46
|
+
|
47
|
+
int ilen, plen, slen, rlen, refcnt;
|
48
|
+
} mrb_irep;
|
49
|
+
|
50
|
+
#define MRB_ISEQ_NO_FREE 1
|
51
|
+
|
52
|
+
MRB_API mrb_irep *mrb_add_irep(mrb_state *mrb);
|
53
|
+
MRB_API mrb_value mrb_load_irep(mrb_state*, const uint8_t*);
|
54
|
+
MRB_API mrb_value mrb_load_irep_cxt(mrb_state*, const uint8_t*, mrbc_context*);
|
55
|
+
void mrb_irep_free(mrb_state*, struct mrb_irep*);
|
56
|
+
void mrb_irep_incref(mrb_state*, struct mrb_irep*);
|
57
|
+
void mrb_irep_decref(mrb_state*, struct mrb_irep*);
|
58
|
+
void mrb_irep_cutref(mrb_state*, struct mrb_irep*);
|
59
|
+
|
60
|
+
MRB_END_DECL
|
61
|
+
|
62
|
+
#endif /* MRUBY_IREP_H */
|
@@ -0,0 +1,47 @@
|
|
1
|
+
/*
|
2
|
+
** mruby/istruct.h - Inline structures
|
3
|
+
**
|
4
|
+
** See Copyright Notice in mruby.h
|
5
|
+
*/
|
6
|
+
|
7
|
+
#ifndef MRUBY_ISTRUCT_H
|
8
|
+
#define MRUBY_ISTRUCT_H
|
9
|
+
|
10
|
+
#include "common.h"
|
11
|
+
#include <string.h>
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Inline structures that fit in RVALUE
|
15
|
+
*
|
16
|
+
* They cannot have finalizer, and cannot have instance variables.
|
17
|
+
*/
|
18
|
+
MRB_BEGIN_DECL
|
19
|
+
|
20
|
+
#define ISTRUCT_DATA_SIZE (sizeof(void*) * 3)
|
21
|
+
|
22
|
+
struct RIstruct {
|
23
|
+
MRB_OBJECT_HEADER;
|
24
|
+
char inline_data[ISTRUCT_DATA_SIZE];
|
25
|
+
};
|
26
|
+
|
27
|
+
#define RISTRUCT(obj) ((struct RIstruct*)(mrb_ptr(obj)))
|
28
|
+
#define ISTRUCT_PTR(obj) (RISTRUCT(obj)->inline_data)
|
29
|
+
|
30
|
+
MRB_INLINE mrb_int mrb_istruct_size()
|
31
|
+
{
|
32
|
+
return ISTRUCT_DATA_SIZE;
|
33
|
+
}
|
34
|
+
|
35
|
+
MRB_INLINE void* mrb_istruct_ptr(mrb_value object)
|
36
|
+
{
|
37
|
+
return ISTRUCT_PTR(object);
|
38
|
+
}
|
39
|
+
|
40
|
+
MRB_INLINE void mrb_istruct_copy(mrb_value dest, mrb_value src)
|
41
|
+
{
|
42
|
+
memcpy(ISTRUCT_PTR(dest), ISTRUCT_PTR(src), ISTRUCT_DATA_SIZE);
|
43
|
+
}
|
44
|
+
|
45
|
+
MRB_END_DECL
|
46
|
+
|
47
|
+
#endif /* MRUBY_ISTRUCT_H */
|
@@ -0,0 +1,274 @@
|
|
1
|
+
/*
|
2
|
+
** mruby/khash.c - Hash for mruby
|
3
|
+
**
|
4
|
+
** See Copyright Notice in mruby.h
|
5
|
+
*/
|
6
|
+
|
7
|
+
#ifndef MRUBY_KHASH_H
|
8
|
+
#define MRUBY_KHASH_H
|
9
|
+
|
10
|
+
#include <string.h>
|
11
|
+
|
12
|
+
#include <mruby.h>
|
13
|
+
#include "common.h"
|
14
|
+
|
15
|
+
/**
|
16
|
+
* khash definitions used in mruby's hash table.
|
17
|
+
*/
|
18
|
+
MRB_BEGIN_DECL
|
19
|
+
|
20
|
+
typedef uint32_t khint_t;
|
21
|
+
typedef khint_t khiter_t;
|
22
|
+
|
23
|
+
#ifndef KHASH_DEFAULT_SIZE
|
24
|
+
# define KHASH_DEFAULT_SIZE 32
|
25
|
+
#endif
|
26
|
+
#define KHASH_MIN_SIZE 8
|
27
|
+
|
28
|
+
#define UPPER_BOUND(x) ((x)>>2|(x)>>1)
|
29
|
+
|
30
|
+
/* extern uint8_t __m[]; */
|
31
|
+
|
32
|
+
/* mask for flags */
|
33
|
+
static const uint8_t __m_empty[] = {0x02, 0x08, 0x20, 0x80};
|
34
|
+
static const uint8_t __m_del[] = {0x01, 0x04, 0x10, 0x40};
|
35
|
+
static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0};
|
36
|
+
|
37
|
+
|
38
|
+
#define __ac_isempty(ed_flag, i) (ed_flag[(i)/4]&__m_empty[(i)%4])
|
39
|
+
#define __ac_isdel(ed_flag, i) (ed_flag[(i)/4]&__m_del[(i)%4])
|
40
|
+
#define __ac_iseither(ed_flag, i) (ed_flag[(i)/4]&__m_either[(i)%4])
|
41
|
+
#define khash_power2(v) do { \
|
42
|
+
v--;\
|
43
|
+
v |= v >> 1;\
|
44
|
+
v |= v >> 2;\
|
45
|
+
v |= v >> 4;\
|
46
|
+
v |= v >> 8;\
|
47
|
+
v |= v >> 16;\
|
48
|
+
v++;\
|
49
|
+
} while (0)
|
50
|
+
#define khash_mask(h) ((h)->n_buckets-1)
|
51
|
+
#define khash_upper_bound(h) (UPPER_BOUND((h)->n_buckets))
|
52
|
+
|
53
|
+
/* declare struct kh_xxx and kh_xxx_funcs
|
54
|
+
|
55
|
+
name: hash name
|
56
|
+
khkey_t: key data type
|
57
|
+
khval_t: value data type
|
58
|
+
kh_is_map: (0: hash set / 1: hash map)
|
59
|
+
*/
|
60
|
+
#define KHASH_DECLARE(name, khkey_t, khval_t, kh_is_map) \
|
61
|
+
typedef struct kh_##name { \
|
62
|
+
khint_t n_buckets; \
|
63
|
+
khint_t size; \
|
64
|
+
khint_t n_occupied; \
|
65
|
+
uint8_t *ed_flags; \
|
66
|
+
khkey_t *keys; \
|
67
|
+
khval_t *vals; \
|
68
|
+
} kh_##name##_t; \
|
69
|
+
void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h); \
|
70
|
+
kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size); \
|
71
|
+
kh_##name##_t *kh_init_##name(mrb_state *mrb); \
|
72
|
+
void kh_destroy_##name(mrb_state *mrb, kh_##name##_t *h); \
|
73
|
+
void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h); \
|
74
|
+
khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key); \
|
75
|
+
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret); \
|
76
|
+
void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets); \
|
77
|
+
void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x); \
|
78
|
+
kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h);
|
79
|
+
|
80
|
+
static inline void
|
81
|
+
kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
|
82
|
+
{
|
83
|
+
while (len-- > 0) {
|
84
|
+
*p++ = c;
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
/* define kh_xxx_funcs
|
89
|
+
|
90
|
+
name: hash name
|
91
|
+
khkey_t: key data type
|
92
|
+
khval_t: value data type
|
93
|
+
kh_is_map: (0: hash set / 1: hash map)
|
94
|
+
__hash_func: hash function
|
95
|
+
__hash_equal: hash comparation function
|
96
|
+
*/
|
97
|
+
#define KHASH_DEFINE(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
|
98
|
+
void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \
|
99
|
+
{ \
|
100
|
+
khint_t sz = h->n_buckets; \
|
101
|
+
size_t len = sizeof(khkey_t) + (kh_is_map ? sizeof(khval_t) : 0); \
|
102
|
+
uint8_t *p = (uint8_t*)mrb_malloc(mrb, sizeof(uint8_t)*sz/4+len*sz); \
|
103
|
+
h->size = h->n_occupied = 0; \
|
104
|
+
h->keys = (khkey_t *)p; \
|
105
|
+
h->vals = kh_is_map ? (khval_t *)(p+sizeof(khkey_t)*sz) : NULL; \
|
106
|
+
h->ed_flags = p+len*sz; \
|
107
|
+
kh_fill_flags(h->ed_flags, 0xaa, sz/4); \
|
108
|
+
} \
|
109
|
+
kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size) { \
|
110
|
+
kh_##name##_t *h = (kh_##name##_t*)mrb_calloc(mrb, 1, sizeof(kh_##name##_t)); \
|
111
|
+
if (size < KHASH_MIN_SIZE) \
|
112
|
+
size = KHASH_MIN_SIZE; \
|
113
|
+
khash_power2(size); \
|
114
|
+
h->n_buckets = size; \
|
115
|
+
kh_alloc_##name(mrb, h); \
|
116
|
+
return h; \
|
117
|
+
} \
|
118
|
+
kh_##name##_t *kh_init_##name(mrb_state *mrb) { \
|
119
|
+
return kh_init_##name##_size(mrb, KHASH_DEFAULT_SIZE); \
|
120
|
+
} \
|
121
|
+
void kh_destroy_##name(mrb_state *mrb, kh_##name##_t *h) \
|
122
|
+
{ \
|
123
|
+
if (h) { \
|
124
|
+
mrb_free(mrb, h->keys); \
|
125
|
+
mrb_free(mrb, h); \
|
126
|
+
} \
|
127
|
+
} \
|
128
|
+
void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h) \
|
129
|
+
{ \
|
130
|
+
(void)mrb; \
|
131
|
+
if (h && h->ed_flags) { \
|
132
|
+
kh_fill_flags(h->ed_flags, 0xaa, h->n_buckets/4); \
|
133
|
+
h->size = h->n_occupied = 0; \
|
134
|
+
} \
|
135
|
+
} \
|
136
|
+
khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key) \
|
137
|
+
{ \
|
138
|
+
khint_t k = __hash_func(mrb,key) & khash_mask(h), step = 0; \
|
139
|
+
(void)mrb; \
|
140
|
+
while (!__ac_isempty(h->ed_flags, k)) { \
|
141
|
+
if (!__ac_isdel(h->ed_flags, k)) { \
|
142
|
+
if (__hash_equal(mrb,h->keys[k], key)) return k; \
|
143
|
+
} \
|
144
|
+
k = (k+(++step)) & khash_mask(h); \
|
145
|
+
} \
|
146
|
+
return kh_end(h); \
|
147
|
+
} \
|
148
|
+
void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets) \
|
149
|
+
{ \
|
150
|
+
if (new_n_buckets < KHASH_MIN_SIZE) \
|
151
|
+
new_n_buckets = KHASH_MIN_SIZE; \
|
152
|
+
khash_power2(new_n_buckets); \
|
153
|
+
{ \
|
154
|
+
kh_##name##_t hh; \
|
155
|
+
uint8_t *old_ed_flags = h->ed_flags; \
|
156
|
+
khkey_t *old_keys = h->keys; \
|
157
|
+
khval_t *old_vals = h->vals; \
|
158
|
+
khint_t old_n_buckets = h->n_buckets; \
|
159
|
+
khint_t i; \
|
160
|
+
hh.n_buckets = new_n_buckets; \
|
161
|
+
kh_alloc_##name(mrb, &hh); \
|
162
|
+
/* relocate */ \
|
163
|
+
for (i=0 ; i<old_n_buckets ; i++) { \
|
164
|
+
if (!__ac_iseither(old_ed_flags, i)) { \
|
165
|
+
khint_t k = kh_put_##name(mrb, &hh, old_keys[i], NULL); \
|
166
|
+
if (kh_is_map) kh_value(&hh,k) = old_vals[i]; \
|
167
|
+
} \
|
168
|
+
} \
|
169
|
+
/* copy hh to h */ \
|
170
|
+
*h = hh; \
|
171
|
+
mrb_free(mrb, old_keys); \
|
172
|
+
} \
|
173
|
+
} \
|
174
|
+
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \
|
175
|
+
{ \
|
176
|
+
khint_t k, del_k, step = 0; \
|
177
|
+
if (h->n_occupied >= khash_upper_bound(h)) { \
|
178
|
+
kh_resize_##name(mrb, h, h->n_buckets*2); \
|
179
|
+
} \
|
180
|
+
k = __hash_func(mrb,key) & khash_mask(h); \
|
181
|
+
del_k = kh_end(h); \
|
182
|
+
while (!__ac_isempty(h->ed_flags, k)) { \
|
183
|
+
if (!__ac_isdel(h->ed_flags, k)) { \
|
184
|
+
if (__hash_equal(mrb,h->keys[k], key)) { \
|
185
|
+
if (ret) *ret = 0; \
|
186
|
+
return k; \
|
187
|
+
} \
|
188
|
+
} \
|
189
|
+
else if (del_k == kh_end(h)) { \
|
190
|
+
del_k = k; \
|
191
|
+
} \
|
192
|
+
k = (k+(++step)) & khash_mask(h); \
|
193
|
+
} \
|
194
|
+
if (del_k != kh_end(h)) { \
|
195
|
+
/* put at del */ \
|
196
|
+
h->keys[del_k] = key; \
|
197
|
+
h->ed_flags[del_k/4] &= ~__m_del[del_k%4]; \
|
198
|
+
h->size++; \
|
199
|
+
if (ret) *ret = 2; \
|
200
|
+
return del_k; \
|
201
|
+
} \
|
202
|
+
else { \
|
203
|
+
/* put at empty */ \
|
204
|
+
h->keys[k] = key; \
|
205
|
+
h->ed_flags[k/4] &= ~__m_empty[k%4]; \
|
206
|
+
h->size++; \
|
207
|
+
h->n_occupied++; \
|
208
|
+
if (ret) *ret = 1; \
|
209
|
+
return k; \
|
210
|
+
} \
|
211
|
+
} \
|
212
|
+
void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x) \
|
213
|
+
{ \
|
214
|
+
(void)mrb; \
|
215
|
+
mrb_assert(x != h->n_buckets && !__ac_iseither(h->ed_flags, x)); \
|
216
|
+
h->ed_flags[x/4] |= __m_del[x%4]; \
|
217
|
+
h->size--; \
|
218
|
+
} \
|
219
|
+
kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h) \
|
220
|
+
{ \
|
221
|
+
kh_##name##_t *h2; \
|
222
|
+
khiter_t k, k2; \
|
223
|
+
\
|
224
|
+
h2 = kh_init_##name(mrb); \
|
225
|
+
for (k = kh_begin(h); k != kh_end(h); k++) { \
|
226
|
+
if (kh_exist(h, k)) { \
|
227
|
+
k2 = kh_put_##name(mrb, h2, kh_key(h, k), NULL); \
|
228
|
+
if (kh_is_map) kh_value(h2, k2) = kh_value(h, k); \
|
229
|
+
} \
|
230
|
+
} \
|
231
|
+
return h2; \
|
232
|
+
}
|
233
|
+
|
234
|
+
|
235
|
+
#define khash_t(name) kh_##name##_t
|
236
|
+
|
237
|
+
#define kh_init_size(name,mrb,size) kh_init_##name##_size(mrb,size)
|
238
|
+
#define kh_init(name,mrb) kh_init_##name(mrb)
|
239
|
+
#define kh_destroy(name, mrb, h) kh_destroy_##name(mrb, h)
|
240
|
+
#define kh_clear(name, mrb, h) kh_clear_##name(mrb, h)
|
241
|
+
#define kh_resize(name, mrb, h, s) kh_resize_##name(mrb, h, s)
|
242
|
+
#define kh_put(name, mrb, h, k) kh_put_##name(mrb, h, k, NULL)
|
243
|
+
#define kh_put2(name, mrb, h, k, r) kh_put_##name(mrb, h, k, r)
|
244
|
+
#define kh_get(name, mrb, h, k) kh_get_##name(mrb, h, k)
|
245
|
+
#define kh_del(name, mrb, h, k) kh_del_##name(mrb, h, k)
|
246
|
+
#define kh_copy(name, mrb, h) kh_copy_##name(mrb, h)
|
247
|
+
|
248
|
+
#define kh_exist(h, x) (!__ac_iseither((h)->ed_flags, (x)))
|
249
|
+
#define kh_key(h, x) ((h)->keys[x])
|
250
|
+
#define kh_val(h, x) ((h)->vals[x])
|
251
|
+
#define kh_value(h, x) ((h)->vals[x])
|
252
|
+
#define kh_begin(h) (khint_t)(0)
|
253
|
+
#define kh_end(h) ((h)->n_buckets)
|
254
|
+
#define kh_size(h) ((h)->size)
|
255
|
+
#define kh_n_buckets(h) ((h)->n_buckets)
|
256
|
+
|
257
|
+
#define kh_int_hash_func(mrb,key) (khint_t)((key)^((key)<<2)^((key)>>2))
|
258
|
+
#define kh_int_hash_equal(mrb,a, b) (a == b)
|
259
|
+
#define kh_int64_hash_func(mrb,key) (khint_t)((key)>>33^(key)^(key)<<11)
|
260
|
+
#define kh_int64_hash_equal(mrb,a, b) (a == b)
|
261
|
+
static inline khint_t __ac_X31_hash_string(const char *s)
|
262
|
+
{
|
263
|
+
khint_t h = *s;
|
264
|
+
if (h) for (++s ; *s; ++s) h = (h << 5) - h + *s;
|
265
|
+
return h;
|
266
|
+
}
|
267
|
+
#define kh_str_hash_func(mrb,key) __ac_X31_hash_string(key)
|
268
|
+
#define kh_str_hash_equal(mrb,a, b) (strcmp(a, b) == 0)
|
269
|
+
|
270
|
+
typedef const char *kh_cstr_t;
|
271
|
+
|
272
|
+
MRB_END_DECL
|
273
|
+
|
274
|
+
#endif /* MRUBY_KHASH_H */
|
@@ -0,0 +1,161 @@
|
|
1
|
+
/*
|
2
|
+
** mruby/numeric.h - Numeric, Integer, Float, Fixnum class
|
3
|
+
**
|
4
|
+
** See Copyright Notice in mruby.h
|
5
|
+
*/
|
6
|
+
|
7
|
+
#ifndef MRUBY_NUMERIC_H
|
8
|
+
#define MRUBY_NUMERIC_H
|
9
|
+
|
10
|
+
#include "common.h"
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Numeric class and it's sub-classes.
|
14
|
+
*
|
15
|
+
* Integer, Float and Fixnum
|
16
|
+
*/
|
17
|
+
MRB_BEGIN_DECL
|
18
|
+
|
19
|
+
#define TYPED_POSFIXABLE(f,t) ((f) <= (t)MRB_INT_MAX)
|
20
|
+
#define TYPED_NEGFIXABLE(f,t) ((f) >= (t)MRB_INT_MIN)
|
21
|
+
#define TYPED_FIXABLE(f,t) (TYPED_POSFIXABLE(f,t) && TYPED_NEGFIXABLE(f,t))
|
22
|
+
#define POSFIXABLE(f) TYPED_POSFIXABLE(f,mrb_int)
|
23
|
+
#define NEGFIXABLE(f) TYPED_NEGFIXABLE(f,mrb_int)
|
24
|
+
#define FIXABLE(f) TYPED_FIXABLE(f,mrb_int)
|
25
|
+
#ifndef MRB_WITHOUT_FLOAT
|
26
|
+
#define FIXABLE_FLOAT(f) TYPED_FIXABLE(f,double)
|
27
|
+
#endif
|
28
|
+
|
29
|
+
#ifndef MRB_WITHOUT_FLOAT
|
30
|
+
MRB_API mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val);
|
31
|
+
#endif
|
32
|
+
MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base);
|
33
|
+
/* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */
|
34
|
+
#ifndef MRB_WITHOUT_FLOAT
|
35
|
+
MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt);
|
36
|
+
MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x);
|
37
|
+
#endif
|
38
|
+
|
39
|
+
mrb_value mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y);
|
40
|
+
mrb_value mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y);
|
41
|
+
mrb_value mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y);
|
42
|
+
mrb_value mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y);
|
43
|
+
|
44
|
+
#ifndef __has_builtin
|
45
|
+
#define __has_builtin(x) 0
|
46
|
+
#endif
|
47
|
+
|
48
|
+
#if (defined(__GNUC__) && __GNUC__ >= 5) || \
|
49
|
+
(__has_builtin(__builtin_add_overflow) && \
|
50
|
+
__has_builtin(__builtin_sub_overflow) && \
|
51
|
+
__has_builtin(__builtin_mul_overflow))
|
52
|
+
# define MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
|
53
|
+
#endif
|
54
|
+
|
55
|
+
/*
|
56
|
+
// Clang 3.8 and 3.9 have problem compiling mruby in 32-bit mode, when MRB_INT64 is set
|
57
|
+
// because of missing __mulodi4 and similar functions in its runtime. We need to use custom
|
58
|
+
// implementation for them.
|
59
|
+
*/
|
60
|
+
#ifdef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
|
61
|
+
#if defined(__clang__) && (__clang_major__ == 3) && (__clang_minor__ >= 8) && \
|
62
|
+
defined(MRB_32BIT) && defined(MRB_INT64)
|
63
|
+
#undef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
|
64
|
+
#endif
|
65
|
+
#endif
|
66
|
+
|
67
|
+
#ifdef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
|
68
|
+
|
69
|
+
#ifndef MRB_WORD_BOXING
|
70
|
+
# define WBCHK(x) 0
|
71
|
+
#else
|
72
|
+
# define WBCHK(x) !FIXABLE(x)
|
73
|
+
#endif
|
74
|
+
|
75
|
+
static inline mrb_bool
|
76
|
+
mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum)
|
77
|
+
{
|
78
|
+
return __builtin_add_overflow(augend, addend, sum) || WBCHK(*sum);
|
79
|
+
}
|
80
|
+
|
81
|
+
static inline mrb_bool
|
82
|
+
mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference)
|
83
|
+
{
|
84
|
+
return __builtin_sub_overflow(minuend, subtrahend, difference) || WBCHK(*difference);
|
85
|
+
}
|
86
|
+
|
87
|
+
static inline mrb_bool
|
88
|
+
mrb_int_mul_overflow(mrb_int multiplier, mrb_int multiplicand, mrb_int *product)
|
89
|
+
{
|
90
|
+
return __builtin_mul_overflow(multiplier, multiplicand, product) || WBCHK(*product);
|
91
|
+
}
|
92
|
+
|
93
|
+
#undef WBCHK
|
94
|
+
|
95
|
+
#else
|
96
|
+
|
97
|
+
#define MRB_UINT_MAKE2(n) uint ## n ## _t
|
98
|
+
#define MRB_UINT_MAKE(n) MRB_UINT_MAKE2(n)
|
99
|
+
#define mrb_uint MRB_UINT_MAKE(MRB_INT_BIT)
|
100
|
+
|
101
|
+
#define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1 - MRB_FIXNUM_SHIFT))
|
102
|
+
|
103
|
+
static inline mrb_bool
|
104
|
+
mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum)
|
105
|
+
{
|
106
|
+
mrb_uint x = (mrb_uint)augend;
|
107
|
+
mrb_uint y = (mrb_uint)addend;
|
108
|
+
mrb_uint z = (mrb_uint)(x + y);
|
109
|
+
*sum = (mrb_int)z;
|
110
|
+
return !!(((x ^ z) & (y ^ z)) & MRB_INT_OVERFLOW_MASK);
|
111
|
+
}
|
112
|
+
|
113
|
+
static inline mrb_bool
|
114
|
+
mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference)
|
115
|
+
{
|
116
|
+
mrb_uint x = (mrb_uint)minuend;
|
117
|
+
mrb_uint y = (mrb_uint)subtrahend;
|
118
|
+
mrb_uint z = (mrb_uint)(x - y);
|
119
|
+
*difference = (mrb_int)z;
|
120
|
+
return !!(((x ^ z) & (~y ^ z)) & MRB_INT_OVERFLOW_MASK);
|
121
|
+
}
|
122
|
+
|
123
|
+
static inline mrb_bool
|
124
|
+
mrb_int_mul_overflow(mrb_int multiplier, mrb_int multiplicand, mrb_int *product)
|
125
|
+
{
|
126
|
+
#if MRB_INT_BIT == 32
|
127
|
+
int64_t n = (int64_t)multiplier * multiplicand;
|
128
|
+
*product = (mrb_int)n;
|
129
|
+
return !FIXABLE(n);
|
130
|
+
#else
|
131
|
+
if (multiplier > 0) {
|
132
|
+
if (multiplicand > 0) {
|
133
|
+
if (multiplier > MRB_INT_MAX / multiplicand) return TRUE;
|
134
|
+
}
|
135
|
+
else {
|
136
|
+
if (multiplicand < MRB_INT_MAX / multiplier) return TRUE;
|
137
|
+
}
|
138
|
+
}
|
139
|
+
else {
|
140
|
+
if (multiplicand > 0) {
|
141
|
+
if (multiplier < MRB_INT_MAX / multiplicand) return TRUE;
|
142
|
+
}
|
143
|
+
else {
|
144
|
+
if (multiplier != 0 && multiplicand < MRB_INT_MAX / multiplier) return TRUE;
|
145
|
+
}
|
146
|
+
}
|
147
|
+
*product = multiplier * multiplicand;
|
148
|
+
return FALSE;
|
149
|
+
#endif
|
150
|
+
}
|
151
|
+
|
152
|
+
#undef MRB_INT_OVERFLOW_MASK
|
153
|
+
#undef mrb_uint
|
154
|
+
#undef MRB_UINT_MAKE
|
155
|
+
#undef MRB_UINT_MAKE2
|
156
|
+
|
157
|
+
#endif
|
158
|
+
|
159
|
+
MRB_END_DECL
|
160
|
+
|
161
|
+
#endif /* MRUBY_NUMERIC_H */
|