jruby-prism-parser 0.24.0-java → 1.4.0-java
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 +4 -4
- data/BSDmakefile +58 -0
- data/CHANGELOG.md +269 -1
- data/CONTRIBUTING.md +0 -4
- data/Makefile +25 -18
- data/README.md +57 -6
- data/config.yml +1724 -140
- data/docs/build_system.md +39 -11
- data/docs/configuration.md +4 -0
- data/docs/cruby_compilation.md +1 -1
- data/docs/fuzzing.md +1 -1
- data/docs/parser_translation.md +14 -9
- data/docs/parsing_rules.md +4 -1
- data/docs/releasing.md +8 -10
- data/docs/relocation.md +34 -0
- data/docs/ripper_translation.md +72 -0
- data/docs/ruby_api.md +2 -1
- data/docs/serialization.md +29 -5
- data/ext/prism/api_node.c +3395 -1999
- data/ext/prism/api_pack.c +9 -0
- data/ext/prism/extconf.rb +55 -34
- data/ext/prism/extension.c +597 -346
- data/ext/prism/extension.h +6 -5
- data/include/prism/ast.h +2612 -455
- data/include/prism/defines.h +160 -2
- data/include/prism/diagnostic.h +188 -76
- data/include/prism/encoding.h +22 -4
- data/include/prism/node.h +89 -17
- data/include/prism/options.h +224 -12
- data/include/prism/pack.h +11 -0
- data/include/prism/parser.h +267 -66
- data/include/prism/prettyprint.h +8 -0
- data/include/prism/regexp.h +18 -8
- data/include/prism/static_literals.h +121 -0
- data/include/prism/util/pm_buffer.h +75 -2
- data/include/prism/util/pm_char.h +1 -2
- data/include/prism/util/pm_constant_pool.h +18 -9
- data/include/prism/util/pm_integer.h +126 -0
- data/include/prism/util/pm_list.h +1 -1
- data/include/prism/util/pm_newline_list.h +19 -0
- data/include/prism/util/pm_string.h +48 -8
- data/include/prism/version.h +3 -3
- data/include/prism.h +99 -5
- data/jruby-prism.jar +0 -0
- data/lib/prism/compiler.rb +11 -1
- data/lib/prism/desugar_compiler.rb +113 -74
- data/lib/prism/dispatcher.rb +45 -1
- data/lib/prism/dot_visitor.rb +201 -77
- data/lib/prism/dsl.rb +673 -461
- data/lib/prism/ffi.rb +233 -45
- data/lib/prism/inspect_visitor.rb +2389 -0
- data/lib/prism/lex_compat.rb +35 -16
- data/lib/prism/mutation_compiler.rb +24 -8
- data/lib/prism/node.rb +7731 -8460
- data/lib/prism/node_ext.rb +328 -32
- data/lib/prism/pack.rb +4 -0
- data/lib/prism/parse_result/comments.rb +34 -24
- data/lib/prism/parse_result/errors.rb +65 -0
- data/lib/prism/parse_result/newlines.rb +102 -12
- data/lib/prism/parse_result.rb +448 -44
- data/lib/prism/pattern.rb +28 -10
- data/lib/prism/polyfill/append_as_bytes.rb +15 -0
- data/lib/prism/polyfill/byteindex.rb +13 -0
- data/lib/prism/polyfill/unpack1.rb +14 -0
- data/lib/prism/reflection.rb +413 -0
- data/lib/prism/relocation.rb +504 -0
- data/lib/prism/serialize.rb +1940 -1198
- data/lib/prism/string_query.rb +30 -0
- data/lib/prism/translation/parser/builder.rb +61 -0
- data/lib/prism/translation/parser/compiler.rb +569 -195
- data/lib/prism/translation/parser/lexer.rb +516 -39
- data/lib/prism/translation/parser.rb +177 -12
- data/lib/prism/translation/parser33.rb +1 -1
- data/lib/prism/translation/parser34.rb +1 -1
- data/lib/prism/translation/parser35.rb +12 -0
- data/lib/prism/translation/ripper/sexp.rb +125 -0
- data/lib/prism/translation/ripper/shim.rb +5 -0
- data/lib/prism/translation/ripper.rb +3224 -462
- data/lib/prism/translation/ruby_parser.rb +194 -69
- data/lib/prism/translation.rb +4 -1
- data/lib/prism/version.rb +1 -1
- data/lib/prism/visitor.rb +13 -0
- data/lib/prism.rb +17 -27
- data/prism.gemspec +57 -17
- data/rbi/prism/compiler.rbi +12 -0
- data/rbi/prism/dsl.rbi +524 -0
- data/rbi/prism/inspect_visitor.rbi +12 -0
- data/rbi/prism/node.rbi +8722 -0
- data/rbi/prism/node_ext.rbi +107 -0
- data/rbi/prism/parse_result.rbi +404 -0
- data/rbi/prism/reflection.rbi +58 -0
- data/rbi/prism/string_query.rbi +12 -0
- data/rbi/prism/translation/parser.rbi +11 -0
- data/rbi/prism/translation/parser33.rbi +6 -0
- data/rbi/prism/translation/parser34.rbi +6 -0
- data/rbi/prism/translation/parser35.rbi +6 -0
- data/rbi/prism/translation/ripper.rbi +15 -0
- data/rbi/prism/visitor.rbi +473 -0
- data/rbi/prism.rbi +44 -7745
- data/sig/prism/compiler.rbs +9 -0
- data/sig/prism/dispatcher.rbs +16 -0
- data/sig/prism/dot_visitor.rbs +6 -0
- data/sig/prism/dsl.rbs +351 -0
- data/sig/prism/inspect_visitor.rbs +22 -0
- data/sig/prism/lex_compat.rbs +10 -0
- data/sig/prism/mutation_compiler.rbs +159 -0
- data/sig/prism/node.rbs +3614 -0
- data/sig/prism/node_ext.rbs +82 -0
- data/sig/prism/pack.rbs +43 -0
- data/sig/prism/parse_result.rbs +192 -0
- data/sig/prism/pattern.rbs +13 -0
- data/sig/prism/reflection.rbs +50 -0
- data/sig/prism/relocation.rbs +185 -0
- data/sig/prism/serialize.rbs +8 -0
- data/sig/prism/string_query.rbs +11 -0
- data/sig/prism/visitor.rbs +169 -0
- data/sig/prism.rbs +248 -4767
- data/src/diagnostic.c +672 -230
- data/src/encoding.c +211 -108
- data/src/node.c +7541 -1653
- data/src/options.c +135 -20
- data/src/pack.c +33 -17
- data/src/prettyprint.c +1543 -1485
- data/src/prism.c +7813 -3050
- data/src/regexp.c +225 -73
- data/src/serialize.c +101 -77
- data/src/static_literals.c +617 -0
- data/src/token_type.c +14 -13
- data/src/util/pm_buffer.c +187 -20
- data/src/util/pm_char.c +5 -5
- data/src/util/pm_constant_pool.c +39 -19
- data/src/util/pm_integer.c +670 -0
- data/src/util/pm_list.c +1 -1
- data/src/util/pm_newline_list.c +43 -5
- data/src/util/pm_string.c +213 -33
- data/src/util/pm_strncasecmp.c +13 -1
- data/src/util/pm_strpbrk.c +32 -6
- metadata +55 -19
- data/docs/ripper.md +0 -36
- data/include/prism/util/pm_state_stack.h +0 -42
- data/include/prism/util/pm_string_list.h +0 -44
- data/lib/prism/debug.rb +0 -206
- data/lib/prism/node_inspector.rb +0 -68
- data/lib/prism/translation/parser/rubocop.rb +0 -45
- data/rbi/prism_static.rbi +0 -207
- data/sig/prism_static.rbs +0 -201
- data/src/util/pm_state_stack.c +0 -25
- data/src/util/pm_string_list.c +0 -28
@@ -0,0 +1,670 @@
|
|
1
|
+
#include "prism/util/pm_integer.h"
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Pull out the length and values from the integer, regardless of the form in
|
5
|
+
* which the length/values are stored.
|
6
|
+
*/
|
7
|
+
#define INTEGER_EXTRACT(integer, length_variable, values_variable) \
|
8
|
+
if ((integer)->values == NULL) { \
|
9
|
+
length_variable = 1; \
|
10
|
+
values_variable = &(integer)->value; \
|
11
|
+
} else { \
|
12
|
+
length_variable = (integer)->length; \
|
13
|
+
values_variable = (integer)->values; \
|
14
|
+
}
|
15
|
+
|
16
|
+
/**
|
17
|
+
* Adds two positive pm_integer_t with the given base.
|
18
|
+
* Return pm_integer_t with values allocated. Not normalized.
|
19
|
+
*/
|
20
|
+
static void
|
21
|
+
big_add(pm_integer_t *destination, pm_integer_t *left, pm_integer_t *right, uint64_t base) {
|
22
|
+
size_t left_length;
|
23
|
+
uint32_t *left_values;
|
24
|
+
INTEGER_EXTRACT(left, left_length, left_values)
|
25
|
+
|
26
|
+
size_t right_length;
|
27
|
+
uint32_t *right_values;
|
28
|
+
INTEGER_EXTRACT(right, right_length, right_values)
|
29
|
+
|
30
|
+
size_t length = left_length < right_length ? right_length : left_length;
|
31
|
+
uint32_t *values = (uint32_t *) xmalloc(sizeof(uint32_t) * (length + 1));
|
32
|
+
if (values == NULL) return;
|
33
|
+
|
34
|
+
uint64_t carry = 0;
|
35
|
+
for (size_t index = 0; index < length; index++) {
|
36
|
+
uint64_t sum = carry + (index < left_length ? left_values[index] : 0) + (index < right_length ? right_values[index] : 0);
|
37
|
+
values[index] = (uint32_t) (sum % base);
|
38
|
+
carry = sum / base;
|
39
|
+
}
|
40
|
+
|
41
|
+
if (carry > 0) {
|
42
|
+
values[length] = (uint32_t) carry;
|
43
|
+
length++;
|
44
|
+
}
|
45
|
+
|
46
|
+
*destination = (pm_integer_t) { length, values, 0, false };
|
47
|
+
}
|
48
|
+
|
49
|
+
/**
|
50
|
+
* Internal use for karatsuba_multiply. Calculates `a - b - c` with the given
|
51
|
+
* base. Assume a, b, c, a - b - c all to be positive.
|
52
|
+
* Return pm_integer_t with values allocated. Not normalized.
|
53
|
+
*/
|
54
|
+
static void
|
55
|
+
big_sub2(pm_integer_t *destination, pm_integer_t *a, pm_integer_t *b, pm_integer_t *c, uint64_t base) {
|
56
|
+
size_t a_length;
|
57
|
+
uint32_t *a_values;
|
58
|
+
INTEGER_EXTRACT(a, a_length, a_values)
|
59
|
+
|
60
|
+
size_t b_length;
|
61
|
+
uint32_t *b_values;
|
62
|
+
INTEGER_EXTRACT(b, b_length, b_values)
|
63
|
+
|
64
|
+
size_t c_length;
|
65
|
+
uint32_t *c_values;
|
66
|
+
INTEGER_EXTRACT(c, c_length, c_values)
|
67
|
+
|
68
|
+
uint32_t *values = (uint32_t*) xmalloc(sizeof(uint32_t) * a_length);
|
69
|
+
int64_t carry = 0;
|
70
|
+
|
71
|
+
for (size_t index = 0; index < a_length; index++) {
|
72
|
+
int64_t sub = (
|
73
|
+
carry +
|
74
|
+
a_values[index] -
|
75
|
+
(index < b_length ? b_values[index] : 0) -
|
76
|
+
(index < c_length ? c_values[index] : 0)
|
77
|
+
);
|
78
|
+
|
79
|
+
if (sub >= 0) {
|
80
|
+
values[index] = (uint32_t) sub;
|
81
|
+
carry = 0;
|
82
|
+
} else {
|
83
|
+
sub += 2 * (int64_t) base;
|
84
|
+
values[index] = (uint32_t) ((uint64_t) sub % base);
|
85
|
+
carry = sub / (int64_t) base - 2;
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
while (a_length > 1 && values[a_length - 1] == 0) a_length--;
|
90
|
+
*destination = (pm_integer_t) { a_length, values, 0, false };
|
91
|
+
}
|
92
|
+
|
93
|
+
/**
|
94
|
+
* Multiply two positive integers with the given base using karatsuba algorithm.
|
95
|
+
* Return pm_integer_t with values allocated. Not normalized.
|
96
|
+
*/
|
97
|
+
static void
|
98
|
+
karatsuba_multiply(pm_integer_t *destination, pm_integer_t *left, pm_integer_t *right, uint64_t base) {
|
99
|
+
size_t left_length;
|
100
|
+
uint32_t *left_values;
|
101
|
+
INTEGER_EXTRACT(left, left_length, left_values)
|
102
|
+
|
103
|
+
size_t right_length;
|
104
|
+
uint32_t *right_values;
|
105
|
+
INTEGER_EXTRACT(right, right_length, right_values)
|
106
|
+
|
107
|
+
if (left_length > right_length) {
|
108
|
+
size_t temporary_length = left_length;
|
109
|
+
left_length = right_length;
|
110
|
+
right_length = temporary_length;
|
111
|
+
|
112
|
+
uint32_t *temporary_values = left_values;
|
113
|
+
left_values = right_values;
|
114
|
+
right_values = temporary_values;
|
115
|
+
}
|
116
|
+
|
117
|
+
if (left_length <= 10) {
|
118
|
+
size_t length = left_length + right_length;
|
119
|
+
uint32_t *values = (uint32_t *) xcalloc(length, sizeof(uint32_t));
|
120
|
+
if (values == NULL) return;
|
121
|
+
|
122
|
+
for (size_t left_index = 0; left_index < left_length; left_index++) {
|
123
|
+
uint32_t carry = 0;
|
124
|
+
for (size_t right_index = 0; right_index < right_length; right_index++) {
|
125
|
+
uint64_t product = (uint64_t) left_values[left_index] * right_values[right_index] + values[left_index + right_index] + carry;
|
126
|
+
values[left_index + right_index] = (uint32_t) (product % base);
|
127
|
+
carry = (uint32_t) (product / base);
|
128
|
+
}
|
129
|
+
values[left_index + right_length] = carry;
|
130
|
+
}
|
131
|
+
|
132
|
+
while (length > 1 && values[length - 1] == 0) length--;
|
133
|
+
*destination = (pm_integer_t) { length, values, 0, false };
|
134
|
+
return;
|
135
|
+
}
|
136
|
+
|
137
|
+
if (left_length * 2 <= right_length) {
|
138
|
+
uint32_t *values = (uint32_t *) xcalloc(left_length + right_length, sizeof(uint32_t));
|
139
|
+
|
140
|
+
for (size_t start_offset = 0; start_offset < right_length; start_offset += left_length) {
|
141
|
+
size_t end_offset = start_offset + left_length;
|
142
|
+
if (end_offset > right_length) end_offset = right_length;
|
143
|
+
|
144
|
+
pm_integer_t sliced_left = {
|
145
|
+
.length = left_length,
|
146
|
+
.values = left_values,
|
147
|
+
.value = 0,
|
148
|
+
.negative = false
|
149
|
+
};
|
150
|
+
|
151
|
+
pm_integer_t sliced_right = {
|
152
|
+
.length = end_offset - start_offset,
|
153
|
+
.values = right_values + start_offset,
|
154
|
+
.value = 0,
|
155
|
+
.negative = false
|
156
|
+
};
|
157
|
+
|
158
|
+
pm_integer_t product;
|
159
|
+
karatsuba_multiply(&product, &sliced_left, &sliced_right, base);
|
160
|
+
|
161
|
+
uint32_t carry = 0;
|
162
|
+
for (size_t index = 0; index < product.length; index++) {
|
163
|
+
uint64_t sum = (uint64_t) values[start_offset + index] + product.values[index] + carry;
|
164
|
+
values[start_offset + index] = (uint32_t) (sum % base);
|
165
|
+
carry = (uint32_t) (sum / base);
|
166
|
+
}
|
167
|
+
|
168
|
+
if (carry > 0) values[start_offset + product.length] += carry;
|
169
|
+
pm_integer_free(&product);
|
170
|
+
}
|
171
|
+
|
172
|
+
*destination = (pm_integer_t) { left_length + right_length, values, 0, false };
|
173
|
+
return;
|
174
|
+
}
|
175
|
+
|
176
|
+
size_t half = left_length / 2;
|
177
|
+
pm_integer_t x0 = { half, left_values, 0, false };
|
178
|
+
pm_integer_t x1 = { left_length - half, left_values + half, 0, false };
|
179
|
+
pm_integer_t y0 = { half, right_values, 0, false };
|
180
|
+
pm_integer_t y1 = { right_length - half, right_values + half, 0, false };
|
181
|
+
|
182
|
+
pm_integer_t z0 = { 0 };
|
183
|
+
karatsuba_multiply(&z0, &x0, &y0, base);
|
184
|
+
|
185
|
+
pm_integer_t z2 = { 0 };
|
186
|
+
karatsuba_multiply(&z2, &x1, &y1, base);
|
187
|
+
|
188
|
+
// For simplicity to avoid considering negative values,
|
189
|
+
// use `z1 = (x0 + x1) * (y0 + y1) - z0 - z2` instead of original karatsuba algorithm.
|
190
|
+
pm_integer_t x01 = { 0 };
|
191
|
+
big_add(&x01, &x0, &x1, base);
|
192
|
+
|
193
|
+
pm_integer_t y01 = { 0 };
|
194
|
+
big_add(&y01, &y0, &y1, base);
|
195
|
+
|
196
|
+
pm_integer_t xy = { 0 };
|
197
|
+
karatsuba_multiply(&xy, &x01, &y01, base);
|
198
|
+
|
199
|
+
pm_integer_t z1;
|
200
|
+
big_sub2(&z1, &xy, &z0, &z2, base);
|
201
|
+
|
202
|
+
size_t length = left_length + right_length;
|
203
|
+
uint32_t *values = (uint32_t*) xcalloc(length, sizeof(uint32_t));
|
204
|
+
|
205
|
+
assert(z0.values != NULL);
|
206
|
+
memcpy(values, z0.values, sizeof(uint32_t) * z0.length);
|
207
|
+
|
208
|
+
assert(z2.values != NULL);
|
209
|
+
memcpy(values + 2 * half, z2.values, sizeof(uint32_t) * z2.length);
|
210
|
+
|
211
|
+
uint32_t carry = 0;
|
212
|
+
for(size_t index = 0; index < z1.length; index++) {
|
213
|
+
uint64_t sum = (uint64_t) carry + values[index + half] + z1.values[index];
|
214
|
+
values[index + half] = (uint32_t) (sum % base);
|
215
|
+
carry = (uint32_t) (sum / base);
|
216
|
+
}
|
217
|
+
|
218
|
+
for(size_t index = half + z1.length; carry > 0; index++) {
|
219
|
+
uint64_t sum = (uint64_t) carry + values[index];
|
220
|
+
values[index] = (uint32_t) (sum % base);
|
221
|
+
carry = (uint32_t) (sum / base);
|
222
|
+
}
|
223
|
+
|
224
|
+
while (length > 1 && values[length - 1] == 0) length--;
|
225
|
+
pm_integer_free(&z0);
|
226
|
+
pm_integer_free(&z1);
|
227
|
+
pm_integer_free(&z2);
|
228
|
+
pm_integer_free(&x01);
|
229
|
+
pm_integer_free(&y01);
|
230
|
+
pm_integer_free(&xy);
|
231
|
+
|
232
|
+
*destination = (pm_integer_t) { length, values, 0, false };
|
233
|
+
}
|
234
|
+
|
235
|
+
/**
|
236
|
+
* The values of a hexadecimal digit, where the index is the ASCII character.
|
237
|
+
* Note that there's an odd exception here where _ is mapped to 0. This is
|
238
|
+
* because it's possible for us to end up trying to parse a number that has
|
239
|
+
* already had an error attached to it, and we want to provide _something_ to
|
240
|
+
* the user.
|
241
|
+
*/
|
242
|
+
static const int8_t pm_integer_parse_digit_values[256] = {
|
243
|
+
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
244
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x
|
245
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 1x
|
246
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 2x
|
247
|
+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 3x
|
248
|
+
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 4x
|
249
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, // 5x
|
250
|
+
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 6x
|
251
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 7x
|
252
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 8x
|
253
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 9x
|
254
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Ax
|
255
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Bx
|
256
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Cx
|
257
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Dx
|
258
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Ex
|
259
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Fx
|
260
|
+
};
|
261
|
+
|
262
|
+
/**
|
263
|
+
* Return the value of a hexadecimal digit in a uint8_t.
|
264
|
+
*/
|
265
|
+
static uint8_t
|
266
|
+
pm_integer_parse_digit(const uint8_t character) {
|
267
|
+
int8_t value = pm_integer_parse_digit_values[character];
|
268
|
+
assert(value != -1 && "invalid digit");
|
269
|
+
|
270
|
+
return (uint8_t) value;
|
271
|
+
}
|
272
|
+
|
273
|
+
/**
|
274
|
+
* Create a pm_integer_t from uint64_t with the given base. It is assumed that
|
275
|
+
* the memory for the pm_integer_t pointer has been zeroed.
|
276
|
+
*/
|
277
|
+
static void
|
278
|
+
pm_integer_from_uint64(pm_integer_t *integer, uint64_t value, uint64_t base) {
|
279
|
+
if (value < base) {
|
280
|
+
integer->value = (uint32_t) value;
|
281
|
+
return;
|
282
|
+
}
|
283
|
+
|
284
|
+
size_t length = 0;
|
285
|
+
uint64_t length_value = value;
|
286
|
+
while (length_value > 0) {
|
287
|
+
length++;
|
288
|
+
length_value /= base;
|
289
|
+
}
|
290
|
+
|
291
|
+
uint32_t *values = (uint32_t *) xmalloc(sizeof(uint32_t) * length);
|
292
|
+
if (values == NULL) return;
|
293
|
+
|
294
|
+
for (size_t value_index = 0; value_index < length; value_index++) {
|
295
|
+
values[value_index] = (uint32_t) (value % base);
|
296
|
+
value /= base;
|
297
|
+
}
|
298
|
+
|
299
|
+
integer->length = length;
|
300
|
+
integer->values = values;
|
301
|
+
}
|
302
|
+
|
303
|
+
/**
|
304
|
+
* Normalize pm_integer_t.
|
305
|
+
* Heading zero values will be removed. If the integer fits into uint32_t,
|
306
|
+
* values is set to NULL, length is set to 0, and value field will be used.
|
307
|
+
*/
|
308
|
+
static void
|
309
|
+
pm_integer_normalize(pm_integer_t *integer) {
|
310
|
+
if (integer->values == NULL) {
|
311
|
+
return;
|
312
|
+
}
|
313
|
+
|
314
|
+
while (integer->length > 1 && integer->values[integer->length - 1] == 0) {
|
315
|
+
integer->length--;
|
316
|
+
}
|
317
|
+
|
318
|
+
if (integer->length > 1) {
|
319
|
+
return;
|
320
|
+
}
|
321
|
+
|
322
|
+
uint32_t value = integer->values[0];
|
323
|
+
bool negative = integer->negative && value != 0;
|
324
|
+
|
325
|
+
pm_integer_free(integer);
|
326
|
+
*integer = (pm_integer_t) { .values = NULL, .value = value, .length = 0, .negative = negative };
|
327
|
+
}
|
328
|
+
|
329
|
+
/**
|
330
|
+
* Convert base of the integer.
|
331
|
+
* In practice, it converts 10**9 to 1<<32 or 1<<32 to 10**9.
|
332
|
+
*/
|
333
|
+
static void
|
334
|
+
pm_integer_convert_base(pm_integer_t *destination, const pm_integer_t *source, uint64_t base_from, uint64_t base_to) {
|
335
|
+
size_t source_length;
|
336
|
+
const uint32_t *source_values;
|
337
|
+
INTEGER_EXTRACT(source, source_length, source_values)
|
338
|
+
|
339
|
+
size_t bigints_length = (source_length + 1) / 2;
|
340
|
+
assert(bigints_length > 0);
|
341
|
+
|
342
|
+
pm_integer_t *bigints = (pm_integer_t *) xcalloc(bigints_length, sizeof(pm_integer_t));
|
343
|
+
if (bigints == NULL) return;
|
344
|
+
|
345
|
+
for (size_t index = 0; index < source_length; index += 2) {
|
346
|
+
uint64_t value = source_values[index] + base_from * (index + 1 < source_length ? source_values[index + 1] : 0);
|
347
|
+
pm_integer_from_uint64(&bigints[index / 2], value, base_to);
|
348
|
+
}
|
349
|
+
|
350
|
+
pm_integer_t base = { 0 };
|
351
|
+
pm_integer_from_uint64(&base, base_from, base_to);
|
352
|
+
|
353
|
+
while (bigints_length > 1) {
|
354
|
+
pm_integer_t next_base;
|
355
|
+
karatsuba_multiply(&next_base, &base, &base, base_to);
|
356
|
+
|
357
|
+
pm_integer_free(&base);
|
358
|
+
base = next_base;
|
359
|
+
|
360
|
+
size_t next_length = (bigints_length + 1) / 2;
|
361
|
+
pm_integer_t *next_bigints = (pm_integer_t *) xcalloc(next_length, sizeof(pm_integer_t));
|
362
|
+
|
363
|
+
for (size_t bigints_index = 0; bigints_index < bigints_length; bigints_index += 2) {
|
364
|
+
if (bigints_index + 1 == bigints_length) {
|
365
|
+
next_bigints[bigints_index / 2] = bigints[bigints_index];
|
366
|
+
} else {
|
367
|
+
pm_integer_t multiplied = { 0 };
|
368
|
+
karatsuba_multiply(&multiplied, &base, &bigints[bigints_index + 1], base_to);
|
369
|
+
|
370
|
+
big_add(&next_bigints[bigints_index / 2], &bigints[bigints_index], &multiplied, base_to);
|
371
|
+
pm_integer_free(&bigints[bigints_index]);
|
372
|
+
pm_integer_free(&bigints[bigints_index + 1]);
|
373
|
+
pm_integer_free(&multiplied);
|
374
|
+
}
|
375
|
+
}
|
376
|
+
|
377
|
+
xfree(bigints);
|
378
|
+
bigints = next_bigints;
|
379
|
+
bigints_length = next_length;
|
380
|
+
}
|
381
|
+
|
382
|
+
*destination = bigints[0];
|
383
|
+
destination->negative = source->negative;
|
384
|
+
pm_integer_normalize(destination);
|
385
|
+
|
386
|
+
xfree(bigints);
|
387
|
+
pm_integer_free(&base);
|
388
|
+
}
|
389
|
+
|
390
|
+
#undef INTEGER_EXTRACT
|
391
|
+
|
392
|
+
/**
|
393
|
+
* Convert digits to integer with the given power-of-two base.
|
394
|
+
*/
|
395
|
+
static void
|
396
|
+
pm_integer_parse_powof2(pm_integer_t *integer, uint32_t base, const uint8_t *digits, size_t digits_length) {
|
397
|
+
size_t bit = 1;
|
398
|
+
while (base > (uint32_t) (1 << bit)) bit++;
|
399
|
+
|
400
|
+
size_t length = (digits_length * bit + 31) / 32;
|
401
|
+
uint32_t *values = (uint32_t *) xcalloc(length, sizeof(uint32_t));
|
402
|
+
|
403
|
+
for (size_t digit_index = 0; digit_index < digits_length; digit_index++) {
|
404
|
+
size_t bit_position = bit * (digits_length - digit_index - 1);
|
405
|
+
uint32_t value = digits[digit_index];
|
406
|
+
|
407
|
+
size_t index = bit_position / 32;
|
408
|
+
size_t shift = bit_position % 32;
|
409
|
+
|
410
|
+
values[index] |= value << shift;
|
411
|
+
if (32 - shift < bit) values[index + 1] |= value >> (32 - shift);
|
412
|
+
}
|
413
|
+
|
414
|
+
while (length > 1 && values[length - 1] == 0) length--;
|
415
|
+
*integer = (pm_integer_t) { .length = length, .values = values, .value = 0, .negative = false };
|
416
|
+
pm_integer_normalize(integer);
|
417
|
+
}
|
418
|
+
|
419
|
+
/**
|
420
|
+
* Convert decimal digits to pm_integer_t.
|
421
|
+
*/
|
422
|
+
static void
|
423
|
+
pm_integer_parse_decimal(pm_integer_t *integer, const uint8_t *digits, size_t digits_length) {
|
424
|
+
const size_t batch = 9;
|
425
|
+
size_t length = (digits_length + batch - 1) / batch;
|
426
|
+
|
427
|
+
uint32_t *values = (uint32_t *) xcalloc(length, sizeof(uint32_t));
|
428
|
+
uint32_t value = 0;
|
429
|
+
|
430
|
+
for (size_t digits_index = 0; digits_index < digits_length; digits_index++) {
|
431
|
+
value = value * 10 + digits[digits_index];
|
432
|
+
|
433
|
+
size_t reverse_index = digits_length - digits_index - 1;
|
434
|
+
if (reverse_index % batch == 0) {
|
435
|
+
values[reverse_index / batch] = value;
|
436
|
+
value = 0;
|
437
|
+
}
|
438
|
+
}
|
439
|
+
|
440
|
+
// Convert base from 10**9 to 1<<32.
|
441
|
+
pm_integer_convert_base(integer, &((pm_integer_t) { .length = length, .values = values, .value = 0, .negative = false }), 1000000000, ((uint64_t) 1 << 32));
|
442
|
+
xfree(values);
|
443
|
+
}
|
444
|
+
|
445
|
+
/**
|
446
|
+
* Parse a large integer from a string that does not fit into uint32_t.
|
447
|
+
*/
|
448
|
+
static void
|
449
|
+
pm_integer_parse_big(pm_integer_t *integer, uint32_t multiplier, const uint8_t *start, const uint8_t *end) {
|
450
|
+
// Allocate an array to store digits.
|
451
|
+
uint8_t *digits = xmalloc(sizeof(uint8_t) * (size_t) (end - start));
|
452
|
+
size_t digits_length = 0;
|
453
|
+
|
454
|
+
for (; start < end; start++) {
|
455
|
+
if (*start == '_') continue;
|
456
|
+
digits[digits_length++] = pm_integer_parse_digit(*start);
|
457
|
+
}
|
458
|
+
|
459
|
+
// Construct pm_integer_t from the digits.
|
460
|
+
if (multiplier == 10) {
|
461
|
+
pm_integer_parse_decimal(integer, digits, digits_length);
|
462
|
+
} else {
|
463
|
+
pm_integer_parse_powof2(integer, multiplier, digits, digits_length);
|
464
|
+
}
|
465
|
+
|
466
|
+
xfree(digits);
|
467
|
+
}
|
468
|
+
|
469
|
+
/**
|
470
|
+
* Parse an integer from a string. This assumes that the format of the integer
|
471
|
+
* has already been validated, as internal validation checks are not performed
|
472
|
+
* here.
|
473
|
+
*/
|
474
|
+
void
|
475
|
+
pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end) {
|
476
|
+
// Ignore unary +. Unary - is parsed differently and will not end up here.
|
477
|
+
// Instead, it will modify the parsed integer later.
|
478
|
+
if (*start == '+') start++;
|
479
|
+
|
480
|
+
// Determine the multiplier from the base, and skip past any prefixes.
|
481
|
+
uint32_t multiplier = 10;
|
482
|
+
switch (base) {
|
483
|
+
case PM_INTEGER_BASE_DEFAULT:
|
484
|
+
while (*start == '0') start++; // 01 -> 1
|
485
|
+
break;
|
486
|
+
case PM_INTEGER_BASE_BINARY:
|
487
|
+
start += 2; // 0b
|
488
|
+
multiplier = 2;
|
489
|
+
break;
|
490
|
+
case PM_INTEGER_BASE_OCTAL:
|
491
|
+
start++; // 0
|
492
|
+
if (*start == '_' || *start == 'o' || *start == 'O') start++; // o
|
493
|
+
multiplier = 8;
|
494
|
+
break;
|
495
|
+
case PM_INTEGER_BASE_DECIMAL:
|
496
|
+
if (*start == '0' && (end - start) > 1) start += 2; // 0d
|
497
|
+
break;
|
498
|
+
case PM_INTEGER_BASE_HEXADECIMAL:
|
499
|
+
start += 2; // 0x
|
500
|
+
multiplier = 16;
|
501
|
+
break;
|
502
|
+
case PM_INTEGER_BASE_UNKNOWN:
|
503
|
+
if (*start == '0' && (end - start) > 1) {
|
504
|
+
switch (start[1]) {
|
505
|
+
case '_': start += 2; multiplier = 8; break;
|
506
|
+
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': start++; multiplier = 8; break;
|
507
|
+
case 'b': case 'B': start += 2; multiplier = 2; break;
|
508
|
+
case 'o': case 'O': start += 2; multiplier = 8; break;
|
509
|
+
case 'd': case 'D': start += 2; break;
|
510
|
+
case 'x': case 'X': start += 2; multiplier = 16; break;
|
511
|
+
default: assert(false && "unreachable"); break;
|
512
|
+
}
|
513
|
+
}
|
514
|
+
break;
|
515
|
+
}
|
516
|
+
|
517
|
+
// It's possible that we've consumed everything at this point if there is an
|
518
|
+
// invalid integer. If this is the case, we'll just return 0.
|
519
|
+
if (start >= end) return;
|
520
|
+
|
521
|
+
const uint8_t *cursor = start;
|
522
|
+
uint64_t value = (uint64_t) pm_integer_parse_digit(*cursor++);
|
523
|
+
|
524
|
+
for (; cursor < end; cursor++) {
|
525
|
+
if (*cursor == '_') continue;
|
526
|
+
value = value * multiplier + (uint64_t) pm_integer_parse_digit(*cursor);
|
527
|
+
|
528
|
+
if (value > UINT32_MAX) {
|
529
|
+
// If the integer is too large to fit into a single uint32_t, then
|
530
|
+
// we'll parse it as a big integer.
|
531
|
+
pm_integer_parse_big(integer, multiplier, start, end);
|
532
|
+
return;
|
533
|
+
}
|
534
|
+
}
|
535
|
+
|
536
|
+
integer->value = (uint32_t) value;
|
537
|
+
}
|
538
|
+
|
539
|
+
/**
|
540
|
+
* Compare two integers. This function returns -1 if the left integer is less
|
541
|
+
* than the right integer, 0 if they are equal, and 1 if the left integer is
|
542
|
+
* greater than the right integer.
|
543
|
+
*/
|
544
|
+
int
|
545
|
+
pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right) {
|
546
|
+
if (left->negative != right->negative) return left->negative ? -1 : 1;
|
547
|
+
int negative = left->negative ? -1 : 1;
|
548
|
+
|
549
|
+
if (left->values == NULL && right->values == NULL) {
|
550
|
+
if (left->value < right->value) return -1 * negative;
|
551
|
+
if (left->value > right->value) return 1 * negative;
|
552
|
+
return 0;
|
553
|
+
}
|
554
|
+
|
555
|
+
if (left->values == NULL || left->length < right->length) return -1 * negative;
|
556
|
+
if (right->values == NULL || left->length > right->length) return 1 * negative;
|
557
|
+
|
558
|
+
for (size_t index = 0; index < left->length; index++) {
|
559
|
+
size_t value_index = left->length - index - 1;
|
560
|
+
uint32_t left_value = left->values[value_index];
|
561
|
+
uint32_t right_value = right->values[value_index];
|
562
|
+
|
563
|
+
if (left_value < right_value) return -1 * negative;
|
564
|
+
if (left_value > right_value) return 1 * negative;
|
565
|
+
}
|
566
|
+
|
567
|
+
return 0;
|
568
|
+
}
|
569
|
+
|
570
|
+
/**
|
571
|
+
* Reduce a ratio of integers to its simplest form.
|
572
|
+
*/
|
573
|
+
void pm_integers_reduce(pm_integer_t *numerator, pm_integer_t *denominator) {
|
574
|
+
// If either the numerator or denominator do not fit into a 32-bit integer,
|
575
|
+
// then this function is a no-op. In the future, we may consider reducing
|
576
|
+
// even the larger numbers, but for now we're going to keep it simple.
|
577
|
+
if (
|
578
|
+
// If the numerator doesn't fit into a 32-bit integer, return early.
|
579
|
+
numerator->length != 0 ||
|
580
|
+
// If the denominator doesn't fit into a 32-bit integer, return early.
|
581
|
+
denominator->length != 0 ||
|
582
|
+
// If the numerator is 0, then return early.
|
583
|
+
numerator->value == 0 ||
|
584
|
+
// If the denominator is 1, then return early.
|
585
|
+
denominator->value == 1
|
586
|
+
) return;
|
587
|
+
|
588
|
+
// Find the greatest common divisor of the numerator and denominator.
|
589
|
+
uint32_t divisor = numerator->value;
|
590
|
+
uint32_t remainder = denominator->value;
|
591
|
+
|
592
|
+
while (remainder != 0) {
|
593
|
+
uint32_t temporary = remainder;
|
594
|
+
remainder = divisor % remainder;
|
595
|
+
divisor = temporary;
|
596
|
+
}
|
597
|
+
|
598
|
+
// Divide the numerator and denominator by the greatest common divisor.
|
599
|
+
numerator->value /= divisor;
|
600
|
+
denominator->value /= divisor;
|
601
|
+
}
|
602
|
+
|
603
|
+
/**
|
604
|
+
* Convert an integer to a decimal string.
|
605
|
+
*/
|
606
|
+
PRISM_EXPORTED_FUNCTION void
|
607
|
+
pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer) {
|
608
|
+
if (integer->negative) {
|
609
|
+
pm_buffer_append_byte(buffer, '-');
|
610
|
+
}
|
611
|
+
|
612
|
+
// If the integer fits into a single uint32_t, then we can just append the
|
613
|
+
// value directly to the buffer.
|
614
|
+
if (integer->values == NULL) {
|
615
|
+
pm_buffer_append_format(buffer, "%" PRIu32, integer->value);
|
616
|
+
return;
|
617
|
+
}
|
618
|
+
|
619
|
+
// If the integer is two uint32_t values, then we can | them together and
|
620
|
+
// append the result to the buffer.
|
621
|
+
if (integer->length == 2) {
|
622
|
+
const uint64_t value = ((uint64_t) integer->values[0]) | ((uint64_t) integer->values[1] << 32);
|
623
|
+
pm_buffer_append_format(buffer, "%" PRIu64, value);
|
624
|
+
return;
|
625
|
+
}
|
626
|
+
|
627
|
+
// Otherwise, first we'll convert the base from 1<<32 to 10**9.
|
628
|
+
pm_integer_t converted = { 0 };
|
629
|
+
pm_integer_convert_base(&converted, integer, (uint64_t) 1 << 32, 1000000000);
|
630
|
+
|
631
|
+
if (converted.values == NULL) {
|
632
|
+
pm_buffer_append_format(buffer, "%" PRIu32, converted.value);
|
633
|
+
pm_integer_free(&converted);
|
634
|
+
return;
|
635
|
+
}
|
636
|
+
|
637
|
+
// Allocate a buffer that we'll copy the decimal digits into.
|
638
|
+
size_t digits_length = converted.length * 9;
|
639
|
+
char *digits = xcalloc(digits_length, sizeof(char));
|
640
|
+
if (digits == NULL) return;
|
641
|
+
|
642
|
+
// Pack bigdecimal to digits.
|
643
|
+
for (size_t value_index = 0; value_index < converted.length; value_index++) {
|
644
|
+
uint32_t value = converted.values[value_index];
|
645
|
+
|
646
|
+
for (size_t digit_index = 0; digit_index < 9; digit_index++) {
|
647
|
+
digits[digits_length - 9 * value_index - digit_index - 1] = (char) ('0' + value % 10);
|
648
|
+
value /= 10;
|
649
|
+
}
|
650
|
+
}
|
651
|
+
|
652
|
+
size_t start_offset = 0;
|
653
|
+
while (start_offset < digits_length - 1 && digits[start_offset] == '0') start_offset++;
|
654
|
+
|
655
|
+
// Finally, append the string to the buffer and free the digits.
|
656
|
+
pm_buffer_append_string(buffer, digits + start_offset, digits_length - start_offset);
|
657
|
+
xfree(digits);
|
658
|
+
pm_integer_free(&converted);
|
659
|
+
}
|
660
|
+
|
661
|
+
/**
|
662
|
+
* Free the internal memory of an integer. This memory will only be allocated if
|
663
|
+
* the integer exceeds the size of a single uint32_t.
|
664
|
+
*/
|
665
|
+
PRISM_EXPORTED_FUNCTION void
|
666
|
+
pm_integer_free(pm_integer_t *integer) {
|
667
|
+
if (integer->values) {
|
668
|
+
xfree(integer->values);
|
669
|
+
}
|
670
|
+
}
|