yarp 0.10.0 → 0.12.0
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/CHANGELOG.md +50 -1
- data/CONTRIBUTING.md +7 -0
- data/config.yml +259 -49
- data/docs/configuration.md +0 -1
- data/docs/mapping.md +91 -91
- data/docs/serialization.md +23 -20
- data/ext/yarp/api_node.c +1268 -419
- data/ext/yarp/extension.c +9 -2
- data/ext/yarp/extension.h +2 -2
- data/include/yarp/ast.h +471 -318
- data/include/yarp/diagnostic.h +203 -1
- data/include/yarp/enc/yp_encoding.h +1 -1
- data/include/yarp/node.h +0 -4
- data/include/yarp/parser.h +44 -16
- data/include/yarp/util/yp_char.h +22 -6
- data/include/yarp/util/yp_constant_pool.h +11 -4
- data/include/yarp/version.h +2 -2
- data/lib/yarp/desugar_visitor.rb +19 -19
- data/lib/yarp/mutation_visitor.rb +50 -15
- data/lib/yarp/node.rb +6455 -443
- data/lib/yarp/parse_result/comments.rb +172 -0
- data/lib/yarp/parse_result/newlines.rb +60 -0
- data/lib/yarp/pattern.rb +239 -0
- data/lib/yarp/serialize.rb +173 -140
- data/lib/yarp.rb +151 -76
- data/src/diagnostic.c +259 -2
- data/src/enc/yp_unicode.c +5 -5
- data/src/node.c +984 -872
- data/src/prettyprint.c +461 -203
- data/src/serialize.c +380 -185
- data/src/unescape.c +20 -20
- data/src/util/yp_char.c +59 -16
- data/src/util/yp_constant_pool.c +97 -13
- data/src/util/yp_newline_list.c +5 -1
- data/src/util/yp_string_list.c +4 -1
- data/src/yarp.c +2313 -1675
- data/yarp.gemspec +4 -1
- metadata +5 -2
data/src/unescape.c
CHANGED
@@ -94,7 +94,7 @@ static inline size_t
|
|
94
94
|
unescape_hexadecimal(const uint8_t *backslash, uint8_t *value, const uint8_t *end, yp_list_t *error_list) {
|
95
95
|
*value = 0;
|
96
96
|
if (backslash + 2 >= end || !yp_char_is_hexadecimal_digit(backslash[2])) {
|
97
|
-
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2,
|
97
|
+
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, YP_ERR_ESCAPE_INVALID_HEXADECIMAL);
|
98
98
|
return 2;
|
99
99
|
}
|
100
100
|
*value = unescape_hexadecimal_digit(backslash[2]);
|
@@ -157,7 +157,7 @@ unescape_unicode_write(uint8_t *dest, uint32_t value, const uint8_t *start, cons
|
|
157
157
|
// If we get here, then the value is too big. This is an error, but we don't
|
158
158
|
// want to just crash, so instead we'll add an error to the error list and put
|
159
159
|
// in a replacement character instead.
|
160
|
-
if (error_list) yp_diagnostic_list_append(error_list, start, end,
|
160
|
+
if (error_list) yp_diagnostic_list_append(error_list, start, end, YP_ERR_ESCAPE_INVALID_UNICODE);
|
161
161
|
dest[0] = 0xEF;
|
162
162
|
dest[1] = 0xBF;
|
163
163
|
dest[2] = 0xBD;
|
@@ -235,7 +235,7 @@ unescape(
|
|
235
235
|
// \unnnn Unicode character, where nnnn is exactly 4 hexadecimal digits ([0-9a-fA-F])
|
236
236
|
case 'u': {
|
237
237
|
if ((flags & YP_UNESCAPE_FLAG_CONTROL) | (flags & YP_UNESCAPE_FLAG_META)) {
|
238
|
-
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2,
|
238
|
+
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, YP_ERR_ESCAPE_INVALID_UNICODE_CM_FLAGS);
|
239
239
|
return backslash + 2;
|
240
240
|
}
|
241
241
|
|
@@ -252,11 +252,11 @@ unescape(
|
|
252
252
|
|
253
253
|
// \u{nnnn} character literal allows only 1-6 hexadecimal digits
|
254
254
|
if (hexadecimal_length > 6) {
|
255
|
-
if (error_list) yp_diagnostic_list_append(error_list, unicode_cursor, unicode_cursor + hexadecimal_length,
|
255
|
+
if (error_list) yp_diagnostic_list_append(error_list, unicode_cursor, unicode_cursor + hexadecimal_length, YP_ERR_ESCAPE_INVALID_UNICODE_LONG);
|
256
256
|
}
|
257
257
|
// there are not hexadecimal characters
|
258
258
|
else if (hexadecimal_length == 0) {
|
259
|
-
if (error_list) yp_diagnostic_list_append(error_list, unicode_cursor, unicode_cursor + hexadecimal_length,
|
259
|
+
if (error_list) yp_diagnostic_list_append(error_list, unicode_cursor, unicode_cursor + hexadecimal_length, YP_ERR_ESCAPE_INVALID_UNICODE);
|
260
260
|
return unicode_cursor;
|
261
261
|
}
|
262
262
|
|
@@ -277,13 +277,13 @@ unescape(
|
|
277
277
|
|
278
278
|
// ?\u{nnnn} character literal should contain only one codepoint and cannot be like ?\u{nnnn mmmm}
|
279
279
|
if (flags & YP_UNESCAPE_FLAG_EXPECT_SINGLE && codepoints_count > 1) {
|
280
|
-
if (error_list) yp_diagnostic_list_append(error_list, extra_codepoints_start, unicode_cursor - 1,
|
280
|
+
if (error_list) yp_diagnostic_list_append(error_list, extra_codepoints_start, unicode_cursor - 1, YP_ERR_ESCAPE_INVALID_UNICODE_LITERAL);
|
281
281
|
}
|
282
282
|
|
283
283
|
if (unicode_cursor < end && *unicode_cursor == '}') {
|
284
284
|
unicode_cursor++;
|
285
285
|
} else {
|
286
|
-
if (error_list) yp_diagnostic_list_append(error_list, backslash, unicode_cursor,
|
286
|
+
if (error_list) yp_diagnostic_list_append(error_list, backslash, unicode_cursor, YP_ERR_ESCAPE_INVALID_UNICODE_TERM);
|
287
287
|
}
|
288
288
|
|
289
289
|
return unicode_cursor;
|
@@ -298,7 +298,7 @@ unescape(
|
|
298
298
|
return backslash + 6;
|
299
299
|
}
|
300
300
|
|
301
|
-
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2,
|
301
|
+
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, YP_ERR_ESCAPE_INVALID_UNICODE);
|
302
302
|
return backslash + 2;
|
303
303
|
}
|
304
304
|
// \c\M-x meta control character, where x is an ASCII printable character
|
@@ -306,12 +306,12 @@ unescape(
|
|
306
306
|
// \cx control character, where x is an ASCII printable character
|
307
307
|
case 'c':
|
308
308
|
if (backslash + 2 >= end) {
|
309
|
-
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1,
|
309
|
+
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, YP_ERR_ESCAPE_INVALID_CONTROL);
|
310
310
|
return end;
|
311
311
|
}
|
312
312
|
|
313
313
|
if (flags & YP_UNESCAPE_FLAG_CONTROL) {
|
314
|
-
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1,
|
314
|
+
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, YP_ERR_ESCAPE_INVALID_CONTROL_REPEAT);
|
315
315
|
return backslash + 2;
|
316
316
|
}
|
317
317
|
|
@@ -325,7 +325,7 @@ unescape(
|
|
325
325
|
return backslash + 3;
|
326
326
|
default: {
|
327
327
|
if (!char_is_ascii_printable(backslash[2])) {
|
328
|
-
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1,
|
328
|
+
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, YP_ERR_ESCAPE_INVALID_CONTROL);
|
329
329
|
return backslash + 2;
|
330
330
|
}
|
331
331
|
|
@@ -339,17 +339,17 @@ unescape(
|
|
339
339
|
// \C-? delete, ASCII 7Fh (DEL)
|
340
340
|
case 'C':
|
341
341
|
if (backslash + 3 >= end) {
|
342
|
-
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1,
|
342
|
+
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, YP_ERR_ESCAPE_INVALID_CONTROL);
|
343
343
|
return end;
|
344
344
|
}
|
345
345
|
|
346
346
|
if (flags & YP_UNESCAPE_FLAG_CONTROL) {
|
347
|
-
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1,
|
347
|
+
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, YP_ERR_ESCAPE_INVALID_CONTROL_REPEAT);
|
348
348
|
return backslash + 2;
|
349
349
|
}
|
350
350
|
|
351
351
|
if (backslash[2] != '-') {
|
352
|
-
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1,
|
352
|
+
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, YP_ERR_ESCAPE_INVALID_CONTROL);
|
353
353
|
return backslash + 2;
|
354
354
|
}
|
355
355
|
|
@@ -363,7 +363,7 @@ unescape(
|
|
363
363
|
return backslash + 4;
|
364
364
|
default:
|
365
365
|
if (!char_is_ascii_printable(backslash[3])) {
|
366
|
-
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2,
|
366
|
+
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, YP_ERR_ESCAPE_INVALID_CONTROL);
|
367
367
|
return backslash + 2;
|
368
368
|
}
|
369
369
|
|
@@ -377,17 +377,17 @@ unescape(
|
|
377
377
|
// \M-x meta character, where x is an ASCII printable character
|
378
378
|
case 'M': {
|
379
379
|
if (backslash + 3 >= end) {
|
380
|
-
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1,
|
380
|
+
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, YP_ERR_ESCAPE_INVALID_META);
|
381
381
|
return end;
|
382
382
|
}
|
383
383
|
|
384
384
|
if (flags & YP_UNESCAPE_FLAG_META) {
|
385
|
-
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2,
|
385
|
+
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, YP_ERR_ESCAPE_INVALID_META_REPEAT);
|
386
386
|
return backslash + 2;
|
387
387
|
}
|
388
388
|
|
389
389
|
if (backslash[2] != '-') {
|
390
|
-
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2,
|
390
|
+
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, YP_ERR_ESCAPE_INVALID_META);
|
391
391
|
return backslash + 2;
|
392
392
|
}
|
393
393
|
|
@@ -402,7 +402,7 @@ unescape(
|
|
402
402
|
return backslash + 4;
|
403
403
|
}
|
404
404
|
|
405
|
-
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2,
|
405
|
+
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, YP_ERR_ESCAPE_INVALID_META);
|
406
406
|
return backslash + 3;
|
407
407
|
}
|
408
408
|
// \n
|
@@ -474,7 +474,7 @@ yp_unescape_manipulate_string_or_char_literal(yp_parser_t *parser, yp_string_t *
|
|
474
474
|
// within the string.
|
475
475
|
uint8_t *allocated = malloc(string->length);
|
476
476
|
if (allocated == NULL) {
|
477
|
-
yp_diagnostic_list_append(&parser->error_list, string->source, string->source + string->length,
|
477
|
+
yp_diagnostic_list_append(&parser->error_list, string->source, string->source + string->length, YP_ERR_MALLOC_FAILED);
|
478
478
|
return;
|
479
479
|
}
|
480
480
|
|
data/src/util/yp_char.c
CHANGED
@@ -75,7 +75,7 @@ yp_strspn_whitespace(const uint8_t *string, ptrdiff_t length) {
|
|
75
75
|
// whitespace while also tracking the location of each newline. Disallows
|
76
76
|
// searching past the given maximum number of characters.
|
77
77
|
size_t
|
78
|
-
yp_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, yp_newline_list_t *newline_list
|
78
|
+
yp_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, yp_newline_list_t *newline_list) {
|
79
79
|
if (length <= 0) return 0;
|
80
80
|
|
81
81
|
size_t size = 0;
|
@@ -83,12 +83,7 @@ yp_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, yp_newlin
|
|
83
83
|
|
84
84
|
while (size < maximum && (yp_byte_table[string[size]] & YP_CHAR_BIT_WHITESPACE)) {
|
85
85
|
if (string[size] == '\n') {
|
86
|
-
|
87
|
-
return size + 1;
|
88
|
-
}
|
89
|
-
else {
|
90
|
-
yp_newline_list_append(newline_list, string + size);
|
91
|
-
}
|
86
|
+
yp_newline_list_append(newline_list, string + size);
|
92
87
|
}
|
93
88
|
|
94
89
|
size++;
|
@@ -128,6 +123,9 @@ yp_char_is_inline_whitespace(const uint8_t b) {
|
|
128
123
|
return yp_char_is_char_kind(b, YP_CHAR_BIT_INLINE_WHITESPACE);
|
129
124
|
}
|
130
125
|
|
126
|
+
// Scan through the string and return the number of characters at the start of
|
127
|
+
// the string that match the given kind. Disallows searching past the given
|
128
|
+
// maximum number of characters.
|
131
129
|
static inline size_t
|
132
130
|
yp_strspn_number_kind(const uint8_t *string, ptrdiff_t length, uint8_t kind) {
|
133
131
|
if (length <= 0) return 0;
|
@@ -139,20 +137,57 @@ yp_strspn_number_kind(const uint8_t *string, ptrdiff_t length, uint8_t kind) {
|
|
139
137
|
return size;
|
140
138
|
}
|
141
139
|
|
140
|
+
// Scan through the string and return the number of characters at the start of
|
141
|
+
// the string that match the given kind. Disallows searching past the given
|
142
|
+
// maximum number of characters.
|
143
|
+
//
|
144
|
+
// Additionally, report the location of the last invalid underscore character
|
145
|
+
// found in the string through the out invalid parameter.
|
146
|
+
static inline size_t
|
147
|
+
yp_strspn_number_kind_underscores(const uint8_t *string, ptrdiff_t length, const uint8_t **invalid, uint8_t kind) {
|
148
|
+
if (length <= 0) return 0;
|
149
|
+
|
150
|
+
size_t size = 0;
|
151
|
+
size_t maximum = (size_t) length;
|
152
|
+
|
153
|
+
bool underscore = false;
|
154
|
+
while (size < maximum && (yp_number_table[string[size]] & kind)) {
|
155
|
+
if (string[size] == '_') {
|
156
|
+
if (underscore) *invalid = string + size;
|
157
|
+
underscore = true;
|
158
|
+
} else {
|
159
|
+
underscore = false;
|
160
|
+
}
|
161
|
+
|
162
|
+
size++;
|
163
|
+
}
|
164
|
+
|
165
|
+
if (string[size - 1] == '_') *invalid = string + size - 1;
|
166
|
+
return size;
|
167
|
+
}
|
168
|
+
|
142
169
|
// Returns the number of characters at the start of the string that are binary
|
143
170
|
// digits or underscores. Disallows searching past the given maximum number of
|
144
171
|
// characters.
|
172
|
+
//
|
173
|
+
// If multiple underscores are found in a row or if an underscore is
|
174
|
+
// found at the end of the number, then the invalid pointer is set to the index
|
175
|
+
// of the first invalid underscore.
|
145
176
|
size_t
|
146
|
-
yp_strspn_binary_number(const uint8_t *string, ptrdiff_t length) {
|
147
|
-
return
|
177
|
+
yp_strspn_binary_number(const uint8_t *string, ptrdiff_t length, const uint8_t **invalid) {
|
178
|
+
return yp_strspn_number_kind_underscores(string, length, invalid, YP_NUMBER_BIT_BINARY_NUMBER);
|
148
179
|
}
|
149
180
|
|
150
181
|
// Returns the number of characters at the start of the string that are octal
|
151
|
-
// digits or underscores.
|
182
|
+
// digits or underscores. Disallows searching past the given maximum number of
|
152
183
|
// characters.
|
184
|
+
//
|
185
|
+
// If multiple underscores are found in a row or if an underscore is
|
186
|
+
// found at the end of the number, then the invalid pointer is set to the index
|
187
|
+
// of the first invalid underscore.
|
153
188
|
size_t
|
154
|
-
yp_strspn_octal_number(const uint8_t *string, ptrdiff_t length) {
|
155
|
-
return
|
189
|
+
yp_strspn_octal_number(const uint8_t *string, ptrdiff_t length, const uint8_t **invalid) {
|
190
|
+
return yp_strspn_number_kind_underscores(string, length, invalid, YP_NUMBER_BIT_OCTAL_NUMBER);
|
156
191
|
}
|
157
192
|
|
158
193
|
// Returns the number of characters at the start of the string that are decimal
|
@@ -165,9 +200,13 @@ yp_strspn_decimal_digit(const uint8_t *string, ptrdiff_t length) {
|
|
165
200
|
// Returns the number of characters at the start of the string that are decimal
|
166
201
|
// digits or underscores. Disallows searching past the given maximum number of
|
167
202
|
// characters.
|
203
|
+
//
|
204
|
+
// If multiple underscores are found in a row or if an underscore is
|
205
|
+
// found at the end of the number, then the invalid pointer is set to the index
|
206
|
+
// of the first invalid underscore.
|
168
207
|
size_t
|
169
|
-
yp_strspn_decimal_number(const uint8_t *string, ptrdiff_t length) {
|
170
|
-
return
|
208
|
+
yp_strspn_decimal_number(const uint8_t *string, ptrdiff_t length, const uint8_t **invalid) {
|
209
|
+
return yp_strspn_number_kind_underscores(string, length, invalid, YP_NUMBER_BIT_DECIMAL_NUMBER);
|
171
210
|
}
|
172
211
|
|
173
212
|
// Returns the number of characters at the start of the string that are
|
@@ -181,9 +220,13 @@ yp_strspn_hexadecimal_digit(const uint8_t *string, ptrdiff_t length) {
|
|
181
220
|
// Returns the number of characters at the start of the string that are
|
182
221
|
// hexadecimal digits or underscores. Disallows searching past the given maximum
|
183
222
|
// number of characters.
|
223
|
+
//
|
224
|
+
// If multiple underscores are found in a row or if an underscore is
|
225
|
+
// found at the end of the number, then the invalid pointer is set to the index
|
226
|
+
// of the first invalid underscore.
|
184
227
|
size_t
|
185
|
-
yp_strspn_hexadecimal_number(const uint8_t *string, ptrdiff_t length) {
|
186
|
-
return
|
228
|
+
yp_strspn_hexadecimal_number(const uint8_t *string, ptrdiff_t length, const uint8_t **invalid) {
|
229
|
+
return yp_strspn_number_kind_underscores(string, length, invalid, YP_NUMBER_BIT_HEXADECIMAL_NUMBER);
|
187
230
|
}
|
188
231
|
|
189
232
|
static inline bool
|
data/src/util/yp_constant_pool.c
CHANGED
@@ -59,10 +59,42 @@ yp_constant_pool_hash(const uint8_t *start, size_t length) {
|
|
59
59
|
return value;
|
60
60
|
}
|
61
61
|
|
62
|
+
// https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
|
63
|
+
static size_t
|
64
|
+
next_power_of_two(size_t v) {
|
65
|
+
// Avoid underflow in subtraction on next line.
|
66
|
+
if (v == 0) {
|
67
|
+
// 1 is the nearest power of 2 to 0 (2^0)
|
68
|
+
return 1;
|
69
|
+
}
|
70
|
+
v--;
|
71
|
+
v |= v >> 1;
|
72
|
+
v |= v >> 2;
|
73
|
+
v |= v >> 4;
|
74
|
+
v |= v >> 8;
|
75
|
+
v |= v >> 16;
|
76
|
+
#if defined(__LP64__) || defined(_WIN64)
|
77
|
+
v |= v >> 32;
|
78
|
+
#endif
|
79
|
+
v++;
|
80
|
+
return v;
|
81
|
+
}
|
82
|
+
|
83
|
+
#ifndef NDEBUG
|
84
|
+
static bool
|
85
|
+
is_power_of_two(size_t size) {
|
86
|
+
return (size & (size - 1)) == 0;
|
87
|
+
}
|
88
|
+
#endif
|
89
|
+
|
62
90
|
// Resize a constant pool to a given capacity.
|
63
91
|
static inline bool
|
64
92
|
yp_constant_pool_resize(yp_constant_pool_t *pool) {
|
93
|
+
assert(is_power_of_two(pool->capacity));
|
65
94
|
size_t next_capacity = pool->capacity * 2;
|
95
|
+
if (next_capacity < pool->capacity) return false;
|
96
|
+
|
97
|
+
const size_t mask = next_capacity - 1;
|
66
98
|
yp_constant_t *next_constants = calloc(next_capacity, sizeof(yp_constant_t));
|
67
99
|
if (next_constants == NULL) return false;
|
68
100
|
|
@@ -74,13 +106,13 @@ yp_constant_pool_resize(yp_constant_pool_t *pool) {
|
|
74
106
|
// If an id is set on this constant, then we know we have content here.
|
75
107
|
// In this case we need to insert it into the next constant pool.
|
76
108
|
if (constant->id != 0) {
|
77
|
-
size_t next_index = constant->hash
|
109
|
+
size_t next_index = constant->hash & mask;
|
78
110
|
|
79
111
|
// This implements linear scanning to find the next available slot
|
80
112
|
// in case this index is already taken. We don't need to bother
|
81
113
|
// comparing the values since we know that the hash is unique.
|
82
114
|
while (next_constants[next_index].id != 0) {
|
83
|
-
next_index = (next_index + 1)
|
115
|
+
next_index = (next_index + 1) & mask;
|
84
116
|
}
|
85
117
|
|
86
118
|
// Here we copy over the entire constant, which includes the id so
|
@@ -98,6 +130,10 @@ yp_constant_pool_resize(yp_constant_pool_t *pool) {
|
|
98
130
|
// Initialize a new constant pool with a given capacity.
|
99
131
|
bool
|
100
132
|
yp_constant_pool_init(yp_constant_pool_t *pool, size_t capacity) {
|
133
|
+
const size_t size_t_max = (~((size_t) 0));
|
134
|
+
if (capacity >= ((size_t_max / 2) + 1)) return false;
|
135
|
+
|
136
|
+
capacity = next_power_of_two(capacity);
|
101
137
|
pool->constants = calloc(capacity, sizeof(yp_constant_t));
|
102
138
|
if (pool->constants == NULL) return false;
|
103
139
|
|
@@ -106,16 +142,17 @@ yp_constant_pool_init(yp_constant_pool_t *pool, size_t capacity) {
|
|
106
142
|
return true;
|
107
143
|
}
|
108
144
|
|
109
|
-
// Insert a constant into a constant pool
|
110
|
-
|
111
|
-
|
112
|
-
yp_constant_pool_insert(yp_constant_pool_t *pool, const uint8_t *start, size_t length) {
|
145
|
+
// Insert a constant into a constant pool and return its index in the pool.
|
146
|
+
static inline yp_constant_id_t
|
147
|
+
yp_constant_pool_insert(yp_constant_pool_t *pool, const uint8_t *start, size_t length, bool owned) {
|
113
148
|
if (pool->size >= (pool->capacity / 4 * 3)) {
|
114
149
|
if (!yp_constant_pool_resize(pool)) return 0;
|
115
150
|
}
|
116
151
|
|
152
|
+
assert(is_power_of_two(pool->capacity));
|
153
|
+
const size_t mask = pool->capacity - 1;
|
117
154
|
size_t hash = yp_constant_pool_hash(start, length);
|
118
|
-
size_t index = hash
|
155
|
+
size_t index = hash & mask;
|
119
156
|
yp_constant_t *constant;
|
120
157
|
|
121
158
|
while (constant = &pool->constants[index], constant->id != 0) {
|
@@ -123,25 +160,72 @@ yp_constant_pool_insert(yp_constant_pool_t *pool, const uint8_t *start, size_t l
|
|
123
160
|
// same as the content we are trying to insert. If it is, then we can
|
124
161
|
// return the id of the existing constant.
|
125
162
|
if ((constant->length == length) && memcmp(constant->start, start, length) == 0) {
|
126
|
-
|
163
|
+
// Since we have found a match, we need to check if this is
|
164
|
+
// attempting to insert a shared or an owned constant. We want to
|
165
|
+
// prefer shared constants since they don't require allocations.
|
166
|
+
if (owned) {
|
167
|
+
// If we're attempting to insert an owned constant and we have
|
168
|
+
// an existing constant, then either way we don't want the given
|
169
|
+
// memory. Either it's duplicated with the existing constant or
|
170
|
+
// it's not necessary because we have a shared version.
|
171
|
+
free((void *) start);
|
172
|
+
} else if (constant->owned) {
|
173
|
+
// If we're attempting to insert a shared constant and the
|
174
|
+
// existing constant is owned, then we can free the owned
|
175
|
+
// constant and replace it with the shared constant.
|
176
|
+
free((void *) constant->start);
|
177
|
+
constant->start = start;
|
178
|
+
constant->owned = false;
|
179
|
+
}
|
180
|
+
|
181
|
+
return constant->id;
|
127
182
|
}
|
128
183
|
|
129
|
-
index = (index + 1)
|
184
|
+
index = (index + 1) & mask;
|
130
185
|
}
|
131
186
|
|
132
|
-
|
133
|
-
pool->
|
134
|
-
|
187
|
+
pool->size++;
|
188
|
+
assert(pool->size < ((size_t) (1 << 31)));
|
189
|
+
|
190
|
+
*constant = (yp_constant_t) {
|
191
|
+
.id = (unsigned int) (pool->size & 0x7FFFFFFF),
|
192
|
+
.owned = owned,
|
135
193
|
.start = start,
|
136
194
|
.length = length,
|
137
195
|
.hash = hash
|
138
196
|
};
|
139
197
|
|
140
|
-
return id;
|
198
|
+
return constant->id;
|
199
|
+
}
|
200
|
+
|
201
|
+
// Insert a constant into a constant pool. Returns the id of the constant, or 0
|
202
|
+
// if any potential calls to resize fail.
|
203
|
+
yp_constant_id_t
|
204
|
+
yp_constant_pool_insert_shared(yp_constant_pool_t *pool, const uint8_t *start, size_t length) {
|
205
|
+
return yp_constant_pool_insert(pool, start, length, false);
|
206
|
+
}
|
207
|
+
|
208
|
+
// Insert a constant into a constant pool from memory that is now owned by the
|
209
|
+
// constant pool. Returns the id of the constant, or 0 if any potential calls to
|
210
|
+
// resize fail.
|
211
|
+
yp_constant_id_t
|
212
|
+
yp_constant_pool_insert_owned(yp_constant_pool_t *pool, const uint8_t *start, size_t length) {
|
213
|
+
return yp_constant_pool_insert(pool, start, length, true);
|
141
214
|
}
|
142
215
|
|
143
216
|
// Free the memory associated with a constant pool.
|
144
217
|
void
|
145
218
|
yp_constant_pool_free(yp_constant_pool_t *pool) {
|
219
|
+
// For each constant in the current constant pool, free the contents if the
|
220
|
+
// contents are owned.
|
221
|
+
for (uint32_t index = 0; index < pool->capacity; index++) {
|
222
|
+
yp_constant_t *constant = &pool->constants[index];
|
223
|
+
|
224
|
+
// If an id is set on this constant, then we know we have content here.
|
225
|
+
if (constant->id != 0 && constant->owned) {
|
226
|
+
free((void *) constant->start);
|
227
|
+
}
|
228
|
+
}
|
229
|
+
|
146
230
|
free(pool->constants);
|
147
231
|
}
|
data/src/util/yp_newline_list.c
CHANGED
@@ -25,8 +25,12 @@ yp_newline_list_init(yp_newline_list_t *list, const uint8_t *start, size_t capac
|
|
25
25
|
bool
|
26
26
|
yp_newline_list_append(yp_newline_list_t *list, const uint8_t *cursor) {
|
27
27
|
if (list->size == list->capacity) {
|
28
|
+
size_t *original_offsets = list->offsets;
|
29
|
+
|
28
30
|
list->capacity = (list->capacity * 3) / 2;
|
29
|
-
list->offsets = (size_t *)
|
31
|
+
list->offsets = (size_t *) calloc(list->capacity, sizeof(size_t));
|
32
|
+
memcpy(list->offsets, original_offsets, list->size * sizeof(size_t));
|
33
|
+
free(original_offsets);
|
30
34
|
if (list->offsets == NULL) return false;
|
31
35
|
}
|
32
36
|
|
data/src/util/yp_string_list.c
CHANGED
@@ -12,8 +12,11 @@ yp_string_list_init(yp_string_list_t *string_list) {
|
|
12
12
|
void
|
13
13
|
yp_string_list_append(yp_string_list_t *string_list, yp_string_t *string) {
|
14
14
|
if (string_list->length + 1 > string_list->capacity) {
|
15
|
+
yp_string_t *original_string = string_list->strings;
|
15
16
|
string_list->capacity *= 2;
|
16
|
-
string_list->strings = (yp_string_t *)
|
17
|
+
string_list->strings = (yp_string_t *) malloc(string_list->capacity * sizeof(yp_string_t));
|
18
|
+
memcpy(string_list->strings, original_string, (string_list->length) * sizeof(yp_string_t));
|
19
|
+
free(original_string);
|
17
20
|
}
|
18
21
|
|
19
22
|
string_list->strings[string_list->length++] = *string;
|