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
data/ext/prism/extension.c
CHANGED
@@ -19,34 +19,44 @@ VALUE rb_cPrismEmbDocComment;
|
|
19
19
|
VALUE rb_cPrismMagicComment;
|
20
20
|
VALUE rb_cPrismParseError;
|
21
21
|
VALUE rb_cPrismParseWarning;
|
22
|
+
VALUE rb_cPrismResult;
|
22
23
|
VALUE rb_cPrismParseResult;
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
24
|
+
VALUE rb_cPrismLexResult;
|
25
|
+
VALUE rb_cPrismParseLexResult;
|
26
|
+
VALUE rb_cPrismStringQuery;
|
27
|
+
VALUE rb_cPrismScope;
|
28
|
+
|
29
|
+
VALUE rb_cPrismDebugEncoding;
|
30
|
+
|
31
|
+
ID rb_id_option_command_line;
|
32
|
+
ID rb_id_option_encoding;
|
33
|
+
ID rb_id_option_filepath;
|
34
|
+
ID rb_id_option_freeze;
|
35
|
+
ID rb_id_option_frozen_string_literal;
|
36
|
+
ID rb_id_option_line;
|
37
|
+
ID rb_id_option_main_script;
|
38
|
+
ID rb_id_option_partial_script;
|
39
|
+
ID rb_id_option_scopes;
|
40
|
+
ID rb_id_option_version;
|
41
|
+
ID rb_id_source_for;
|
42
|
+
ID rb_id_forwarding_positionals;
|
43
|
+
ID rb_id_forwarding_keywords;
|
44
|
+
ID rb_id_forwarding_block;
|
45
|
+
ID rb_id_forwarding_all;
|
30
46
|
|
31
47
|
/******************************************************************************/
|
32
48
|
/* IO of Ruby code */
|
33
49
|
/******************************************************************************/
|
34
50
|
|
35
51
|
/**
|
36
|
-
* Check if the given VALUE is a string. If it's
|
37
|
-
*
|
38
|
-
* string.
|
52
|
+
* Check if the given VALUE is a string. If it's not a string, then raise a
|
53
|
+
* TypeError. Otherwise return the VALUE as a C string.
|
39
54
|
*/
|
40
55
|
static const char *
|
41
56
|
check_string(VALUE value) {
|
42
|
-
// If the value is nil, then we don't need to do anything.
|
43
|
-
if (NIL_P(value)) {
|
44
|
-
return NULL;
|
45
|
-
}
|
46
|
-
|
47
57
|
// Check if the value is a string. If it's not, then raise a type error.
|
48
58
|
if (!RB_TYPE_P(value, T_STRING)) {
|
49
|
-
rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected String)", rb_obj_class(value));
|
59
|
+
rb_raise(rb_eTypeError, "wrong argument type %" PRIsVALUE " (expected String)", rb_obj_class(value));
|
50
60
|
}
|
51
61
|
|
52
62
|
// Otherwise, return the value as a C string.
|
@@ -60,7 +70,7 @@ static void
|
|
60
70
|
input_load_string(pm_string_t *input, VALUE string) {
|
61
71
|
// Check if the string is a string. If it's not, then raise a type error.
|
62
72
|
if (!RB_TYPE_P(string, T_STRING)) {
|
63
|
-
rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected String)", rb_obj_class(string));
|
73
|
+
rb_raise(rb_eTypeError, "wrong argument type %" PRIsVALUE " (expected String)", rb_obj_class(string));
|
64
74
|
}
|
65
75
|
|
66
76
|
pm_string_constant_init(input, RSTRING_PTR(string), RSTRING_LEN(string));
|
@@ -82,26 +92,69 @@ build_options_scopes(pm_options_t *options, VALUE scopes) {
|
|
82
92
|
|
83
93
|
// Initialize the scopes array.
|
84
94
|
size_t scopes_count = RARRAY_LEN(scopes);
|
85
|
-
pm_options_scopes_init(options, scopes_count)
|
95
|
+
if (!pm_options_scopes_init(options, scopes_count)) {
|
96
|
+
rb_raise(rb_eNoMemError, "failed to allocate memory");
|
97
|
+
}
|
86
98
|
|
87
99
|
// Iterate over the scopes and add them to the options.
|
88
100
|
for (size_t scope_index = 0; scope_index < scopes_count; scope_index++) {
|
89
101
|
VALUE scope = rb_ary_entry(scopes, scope_index);
|
90
102
|
|
91
|
-
//
|
92
|
-
//
|
93
|
-
|
94
|
-
|
103
|
+
// The scope can be either an array or it can be a Prism::Scope object.
|
104
|
+
// Parse out the correct values here from either.
|
105
|
+
VALUE locals;
|
106
|
+
uint8_t forwarding = PM_OPTIONS_SCOPE_FORWARDING_NONE;
|
107
|
+
|
108
|
+
if (RB_TYPE_P(scope, T_ARRAY)) {
|
109
|
+
locals = scope;
|
110
|
+
} else if (rb_obj_is_kind_of(scope, rb_cPrismScope)) {
|
111
|
+
locals = rb_ivar_get(scope, rb_intern("@locals"));
|
112
|
+
if (!RB_TYPE_P(locals, T_ARRAY)) {
|
113
|
+
rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected Array)", rb_obj_class(locals));
|
114
|
+
}
|
115
|
+
|
116
|
+
VALUE names = rb_ivar_get(scope, rb_intern("@forwarding"));
|
117
|
+
if (!RB_TYPE_P(names, T_ARRAY)) {
|
118
|
+
rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected Array)", rb_obj_class(names));
|
119
|
+
}
|
120
|
+
|
121
|
+
size_t names_count = RARRAY_LEN(names);
|
122
|
+
for (size_t name_index = 0; name_index < names_count; name_index++) {
|
123
|
+
VALUE name = rb_ary_entry(names, name_index);
|
124
|
+
|
125
|
+
// Check that the name is a symbol. If it's not, then raise
|
126
|
+
// a type error.
|
127
|
+
if (!RB_TYPE_P(name, T_SYMBOL)) {
|
128
|
+
rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected Symbol)", rb_obj_class(name));
|
129
|
+
}
|
130
|
+
|
131
|
+
ID id = SYM2ID(name);
|
132
|
+
if (id == rb_id_forwarding_positionals) {
|
133
|
+
forwarding |= PM_OPTIONS_SCOPE_FORWARDING_POSITIONALS;
|
134
|
+
} else if (id == rb_id_forwarding_keywords) {
|
135
|
+
forwarding |= PM_OPTIONS_SCOPE_FORWARDING_KEYWORDS;
|
136
|
+
} else if (id == rb_id_forwarding_block) {
|
137
|
+
forwarding |= PM_OPTIONS_SCOPE_FORWARDING_BLOCK;
|
138
|
+
} else if (id == rb_id_forwarding_all) {
|
139
|
+
forwarding |= PM_OPTIONS_SCOPE_FORWARDING_ALL;
|
140
|
+
} else {
|
141
|
+
rb_raise(rb_eArgError, "invalid forwarding value: %" PRIsVALUE, name);
|
142
|
+
}
|
143
|
+
}
|
144
|
+
} else {
|
145
|
+
rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected Array or Prism::Scope)", rb_obj_class(scope));
|
95
146
|
}
|
96
147
|
|
97
148
|
// Initialize the scope array.
|
98
|
-
size_t locals_count = RARRAY_LEN(
|
149
|
+
size_t locals_count = RARRAY_LEN(locals);
|
99
150
|
pm_options_scope_t *options_scope = &options->scopes[scope_index];
|
100
|
-
pm_options_scope_init(options_scope, locals_count)
|
151
|
+
if (!pm_options_scope_init(options_scope, locals_count)) {
|
152
|
+
rb_raise(rb_eNoMemError, "failed to allocate memory");
|
153
|
+
}
|
101
154
|
|
102
155
|
// Iterate over the locals and add them to the scope.
|
103
156
|
for (size_t local_index = 0; local_index < locals_count; local_index++) {
|
104
|
-
VALUE local = rb_ary_entry(
|
157
|
+
VALUE local = rb_ary_entry(locals, local_index);
|
105
158
|
|
106
159
|
// Check that the local is a symbol. If it's not, then raise a
|
107
160
|
// type error.
|
@@ -114,6 +167,9 @@ build_options_scopes(pm_options_t *options, VALUE scopes) {
|
|
114
167
|
const char *name = rb_id2name(SYM2ID(local));
|
115
168
|
pm_string_constant_init(scope_local, name, strlen(name));
|
116
169
|
}
|
170
|
+
|
171
|
+
// Now set the forwarding options.
|
172
|
+
pm_options_scope_forwarding_set(options_scope, forwarding);
|
117
173
|
}
|
118
174
|
}
|
119
175
|
|
@@ -125,26 +181,57 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
|
|
125
181
|
pm_options_t *options = (pm_options_t *) argument;
|
126
182
|
ID key_id = SYM2ID(key);
|
127
183
|
|
128
|
-
if (key_id ==
|
184
|
+
if (key_id == rb_id_option_filepath) {
|
129
185
|
if (!NIL_P(value)) pm_options_filepath_set(options, check_string(value));
|
130
|
-
} else if (key_id ==
|
131
|
-
if (!NIL_P(value))
|
132
|
-
|
186
|
+
} else if (key_id == rb_id_option_encoding) {
|
187
|
+
if (!NIL_P(value)) {
|
188
|
+
if (value == Qfalse) {
|
189
|
+
pm_options_encoding_locked_set(options, true);
|
190
|
+
} else {
|
191
|
+
pm_options_encoding_set(options, rb_enc_name(rb_to_encoding(value)));
|
192
|
+
}
|
193
|
+
}
|
194
|
+
} else if (key_id == rb_id_option_line) {
|
133
195
|
if (!NIL_P(value)) pm_options_line_set(options, NUM2INT(value));
|
134
|
-
} else if (key_id ==
|
135
|
-
if (!NIL_P(value)) pm_options_frozen_string_literal_set(options, value
|
136
|
-
} else if (key_id ==
|
196
|
+
} else if (key_id == rb_id_option_frozen_string_literal) {
|
197
|
+
if (!NIL_P(value)) pm_options_frozen_string_literal_set(options, RTEST(value));
|
198
|
+
} else if (key_id == rb_id_option_version) {
|
137
199
|
if (!NIL_P(value)) {
|
138
200
|
const char *version = check_string(value);
|
139
201
|
|
140
202
|
if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
|
141
|
-
rb_raise(rb_eArgError, "invalid version: %"PRIsVALUE, value);
|
203
|
+
rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value);
|
142
204
|
}
|
143
205
|
}
|
144
|
-
} else if (key_id ==
|
206
|
+
} else if (key_id == rb_id_option_scopes) {
|
145
207
|
if (!NIL_P(value)) build_options_scopes(options, value);
|
208
|
+
} else if (key_id == rb_id_option_command_line) {
|
209
|
+
if (!NIL_P(value)) {
|
210
|
+
const char *string = check_string(value);
|
211
|
+
uint8_t command_line = 0;
|
212
|
+
|
213
|
+
for (size_t index = 0; index < strlen(string); index++) {
|
214
|
+
switch (string[index]) {
|
215
|
+
case 'a': command_line |= PM_OPTIONS_COMMAND_LINE_A; break;
|
216
|
+
case 'e': command_line |= PM_OPTIONS_COMMAND_LINE_E; break;
|
217
|
+
case 'l': command_line |= PM_OPTIONS_COMMAND_LINE_L; break;
|
218
|
+
case 'n': command_line |= PM_OPTIONS_COMMAND_LINE_N; break;
|
219
|
+
case 'p': command_line |= PM_OPTIONS_COMMAND_LINE_P; break;
|
220
|
+
case 'x': command_line |= PM_OPTIONS_COMMAND_LINE_X; break;
|
221
|
+
default: rb_raise(rb_eArgError, "invalid command line flag: '%c'", string[index]); break;
|
222
|
+
}
|
223
|
+
}
|
224
|
+
|
225
|
+
pm_options_command_line_set(options, command_line);
|
226
|
+
}
|
227
|
+
} else if (key_id == rb_id_option_main_script) {
|
228
|
+
if (!NIL_P(value)) pm_options_main_script_set(options, RTEST(value));
|
229
|
+
} else if (key_id == rb_id_option_partial_script) {
|
230
|
+
if (!NIL_P(value)) pm_options_partial_script_set(options, RTEST(value));
|
231
|
+
} else if (key_id == rb_id_option_freeze) {
|
232
|
+
if (!NIL_P(value)) pm_options_freeze_set(options, RTEST(value));
|
146
233
|
} else {
|
147
|
-
rb_raise(rb_eArgError, "unknown keyword: %"PRIsVALUE, key);
|
234
|
+
rb_raise(rb_eArgError, "unknown keyword: %" PRIsVALUE, key);
|
148
235
|
}
|
149
236
|
|
150
237
|
return ST_CONTINUE;
|
@@ -177,6 +264,7 @@ build_options(VALUE argument) {
|
|
177
264
|
static void
|
178
265
|
extract_options(pm_options_t *options, VALUE filepath, VALUE keywords) {
|
179
266
|
options->line = 1; // default
|
267
|
+
|
180
268
|
if (!NIL_P(keywords)) {
|
181
269
|
struct build_options_data data = { .options = options, .keywords = keywords };
|
182
270
|
struct build_options_data *argument = &data;
|
@@ -217,30 +305,46 @@ string_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options)
|
|
217
305
|
* Read options for methods that look like (filepath, **options).
|
218
306
|
*/
|
219
307
|
static void
|
220
|
-
file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options) {
|
308
|
+
file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, VALUE *encoded_filepath) {
|
221
309
|
VALUE filepath;
|
222
310
|
VALUE keywords;
|
223
311
|
rb_scan_args(argc, argv, "1:", &filepath, &keywords);
|
224
312
|
|
225
313
|
Check_Type(filepath, T_STRING);
|
314
|
+
*encoded_filepath = rb_str_encode_ospath(filepath);
|
315
|
+
extract_options(options, *encoded_filepath, keywords);
|
226
316
|
|
227
|
-
|
317
|
+
const char *source = (const char *) pm_string_source(&options->filepath);
|
318
|
+
pm_string_init_result_t result;
|
228
319
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
320
|
+
switch (result = pm_string_file_init(input, source)) {
|
321
|
+
case PM_STRING_INIT_SUCCESS:
|
322
|
+
break;
|
323
|
+
case PM_STRING_INIT_ERROR_GENERIC: {
|
324
|
+
pm_options_free(options);
|
233
325
|
|
234
326
|
#ifdef _WIN32
|
235
|
-
|
327
|
+
int e = rb_w32_map_errno(GetLastError());
|
236
328
|
#else
|
237
|
-
|
329
|
+
int e = errno;
|
238
330
|
#endif
|
239
331
|
|
240
|
-
|
332
|
+
rb_syserr_fail(e, source);
|
333
|
+
break;
|
334
|
+
}
|
335
|
+
case PM_STRING_INIT_ERROR_DIRECTORY:
|
336
|
+
pm_options_free(options);
|
337
|
+
rb_syserr_fail(EISDIR, source);
|
338
|
+
break;
|
339
|
+
default:
|
340
|
+
pm_options_free(options);
|
341
|
+
rb_raise(rb_eRuntimeError, "Unknown error (%d) initializing file: %s", result, source);
|
342
|
+
break;
|
241
343
|
}
|
242
344
|
}
|
243
345
|
|
346
|
+
#ifndef PRISM_EXCLUDE_SERIALIZATION
|
347
|
+
|
244
348
|
/******************************************************************************/
|
245
349
|
/* Serializing the AST */
|
246
350
|
/******************************************************************************/
|
@@ -282,17 +386,18 @@ dump(int argc, VALUE *argv, VALUE self) {
|
|
282
386
|
pm_options_t options = { 0 };
|
283
387
|
string_options(argc, argv, &input, &options);
|
284
388
|
|
285
|
-
#ifdef
|
389
|
+
#ifdef PRISM_BUILD_DEBUG
|
286
390
|
size_t length = pm_string_length(&input);
|
287
|
-
char* dup =
|
391
|
+
char* dup = xmalloc(length);
|
288
392
|
memcpy(dup, pm_string_source(&input), length);
|
289
393
|
pm_string_constant_init(&input, dup, length);
|
290
394
|
#endif
|
291
395
|
|
292
396
|
VALUE value = dump_input(&input, &options);
|
397
|
+
if (options.freeze) rb_obj_freeze(value);
|
293
398
|
|
294
|
-
#ifdef
|
295
|
-
|
399
|
+
#ifdef PRISM_BUILD_DEBUG
|
400
|
+
xfree(dup);
|
296
401
|
#endif
|
297
402
|
|
298
403
|
pm_string_free(&input);
|
@@ -313,7 +418,8 @@ dump_file(int argc, VALUE *argv, VALUE self) {
|
|
313
418
|
pm_string_t input;
|
314
419
|
pm_options_t options = { 0 };
|
315
420
|
|
316
|
-
|
421
|
+
VALUE encoded_filepath;
|
422
|
+
file_options(argc, argv, &input, &options, &encoded_filepath);
|
317
423
|
|
318
424
|
VALUE value = dump_input(&input, &options);
|
319
425
|
pm_string_free(&input);
|
@@ -322,60 +428,96 @@ dump_file(int argc, VALUE *argv, VALUE self) {
|
|
322
428
|
return value;
|
323
429
|
}
|
324
430
|
|
431
|
+
#endif
|
432
|
+
|
325
433
|
/******************************************************************************/
|
326
434
|
/* Extracting values for the parse result */
|
327
435
|
/******************************************************************************/
|
328
436
|
|
437
|
+
/**
|
438
|
+
* The same as rb_class_new_instance, but accepts an additional boolean to
|
439
|
+
* indicate whether or not the resulting class instance should be frozen.
|
440
|
+
*/
|
441
|
+
static inline VALUE
|
442
|
+
rb_class_new_instance_freeze(int argc, const VALUE *argv, VALUE klass, bool freeze) {
|
443
|
+
VALUE value = rb_class_new_instance(argc, argv, klass);
|
444
|
+
if (freeze) rb_obj_freeze(value);
|
445
|
+
return value;
|
446
|
+
}
|
447
|
+
|
448
|
+
/**
|
449
|
+
* Create a new Location instance from the given parser and bounds.
|
450
|
+
*/
|
451
|
+
static inline VALUE
|
452
|
+
parser_location(const pm_parser_t *parser, VALUE source, bool freeze, const uint8_t *start, size_t length) {
|
453
|
+
VALUE argv[] = { source, LONG2FIX(start - parser->start), LONG2FIX(length) };
|
454
|
+
return rb_class_new_instance_freeze(3, argv, rb_cPrismLocation, freeze);
|
455
|
+
}
|
456
|
+
|
457
|
+
/**
|
458
|
+
* Create a new Location instance from the given parser and location.
|
459
|
+
*/
|
460
|
+
#define PARSER_LOCATION_LOC(parser, source, freeze, loc) \
|
461
|
+
parser_location(parser, source, freeze, loc.start, (size_t) (loc.end - loc.start))
|
462
|
+
|
463
|
+
/**
|
464
|
+
* Build a new Comment instance from the given parser and comment.
|
465
|
+
*/
|
466
|
+
static inline VALUE
|
467
|
+
parser_comment(const pm_parser_t *parser, VALUE source, bool freeze, const pm_comment_t *comment) {
|
468
|
+
VALUE argv[] = { PARSER_LOCATION_LOC(parser, source, freeze, comment->location) };
|
469
|
+
VALUE type = (comment->type == PM_COMMENT_EMBDOC) ? rb_cPrismEmbDocComment : rb_cPrismInlineComment;
|
470
|
+
return rb_class_new_instance_freeze(1, argv, type, freeze);
|
471
|
+
}
|
472
|
+
|
329
473
|
/**
|
330
474
|
* Extract the comments out of the parser into an array.
|
331
475
|
*/
|
332
476
|
static VALUE
|
333
|
-
parser_comments(pm_parser_t *parser, VALUE source) {
|
334
|
-
VALUE comments =
|
335
|
-
|
336
|
-
for (
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
VALUE type = (comment->type == PM_COMMENT_EMBDOC) ? rb_cPrismEmbDocComment : rb_cPrismInlineComment;
|
344
|
-
VALUE comment_argv[] = { rb_class_new_instance(3, location_argv, rb_cPrismLocation) };
|
345
|
-
rb_ary_push(comments, rb_class_new_instance(1, comment_argv, type));
|
477
|
+
parser_comments(const pm_parser_t *parser, VALUE source, bool freeze) {
|
478
|
+
VALUE comments = rb_ary_new_capa(parser->comment_list.size);
|
479
|
+
|
480
|
+
for (
|
481
|
+
const pm_comment_t *comment = (const pm_comment_t *) parser->comment_list.head;
|
482
|
+
comment != NULL;
|
483
|
+
comment = (const pm_comment_t *) comment->node.next
|
484
|
+
) {
|
485
|
+
VALUE value = parser_comment(parser, source, freeze, comment);
|
486
|
+
rb_ary_push(comments, value);
|
346
487
|
}
|
347
488
|
|
489
|
+
if (freeze) rb_obj_freeze(comments);
|
348
490
|
return comments;
|
349
491
|
}
|
350
492
|
|
493
|
+
/**
|
494
|
+
* Build a new MagicComment instance from the given parser and magic comment.
|
495
|
+
*/
|
496
|
+
static inline VALUE
|
497
|
+
parser_magic_comment(const pm_parser_t *parser, VALUE source, bool freeze, const pm_magic_comment_t *magic_comment) {
|
498
|
+
VALUE key_loc = parser_location(parser, source, freeze, magic_comment->key_start, magic_comment->key_length);
|
499
|
+
VALUE value_loc = parser_location(parser, source, freeze, magic_comment->value_start, magic_comment->value_length);
|
500
|
+
VALUE argv[] = { key_loc, value_loc };
|
501
|
+
return rb_class_new_instance_freeze(2, argv, rb_cPrismMagicComment, freeze);
|
502
|
+
}
|
503
|
+
|
351
504
|
/**
|
352
505
|
* Extract the magic comments out of the parser into an array.
|
353
506
|
*/
|
354
507
|
static VALUE
|
355
|
-
parser_magic_comments(pm_parser_t *parser, VALUE source) {
|
356
|
-
VALUE magic_comments =
|
357
|
-
|
358
|
-
for (
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
VALUE value_loc_argv[] = {
|
366
|
-
source,
|
367
|
-
LONG2FIX(magic_comment->value_start - parser->start),
|
368
|
-
LONG2FIX(magic_comment->value_length)
|
369
|
-
};
|
370
|
-
|
371
|
-
VALUE magic_comment_argv[] = {
|
372
|
-
rb_class_new_instance(3, key_loc_argv, rb_cPrismLocation),
|
373
|
-
rb_class_new_instance(3, value_loc_argv, rb_cPrismLocation)
|
374
|
-
};
|
375
|
-
|
376
|
-
rb_ary_push(magic_comments, rb_class_new_instance(2, magic_comment_argv, rb_cPrismMagicComment));
|
508
|
+
parser_magic_comments(const pm_parser_t *parser, VALUE source, bool freeze) {
|
509
|
+
VALUE magic_comments = rb_ary_new_capa(parser->magic_comment_list.size);
|
510
|
+
|
511
|
+
for (
|
512
|
+
const pm_magic_comment_t *magic_comment = (const pm_magic_comment_t *) parser->magic_comment_list.head;
|
513
|
+
magic_comment != NULL;
|
514
|
+
magic_comment = (const pm_magic_comment_t *) magic_comment->node.next
|
515
|
+
) {
|
516
|
+
VALUE value = parser_magic_comment(parser, source, freeze, magic_comment);
|
517
|
+
rb_ary_push(magic_comments, value);
|
377
518
|
}
|
378
519
|
|
520
|
+
if (freeze) rb_obj_freeze(magic_comments);
|
379
521
|
return magic_comments;
|
380
522
|
}
|
381
523
|
|
@@ -384,17 +526,11 @@ parser_magic_comments(pm_parser_t *parser, VALUE source) {
|
|
384
526
|
* exists.
|
385
527
|
*/
|
386
528
|
static VALUE
|
387
|
-
parser_data_loc(const pm_parser_t *parser, VALUE source) {
|
529
|
+
parser_data_loc(const pm_parser_t *parser, VALUE source, bool freeze) {
|
388
530
|
if (parser->data_loc.end == NULL) {
|
389
531
|
return Qnil;
|
390
532
|
} else {
|
391
|
-
|
392
|
-
source,
|
393
|
-
LONG2FIX(parser->data_loc.start - parser->start),
|
394
|
-
LONG2FIX(parser->data_loc.end - parser->data_loc.start)
|
395
|
-
};
|
396
|
-
|
397
|
-
return rb_class_new_instance(3, argv, rb_cPrismLocation);
|
533
|
+
return PARSER_LOCATION_LOC(parser, source, freeze, parser->data_loc);
|
398
534
|
}
|
399
535
|
}
|
400
536
|
|
@@ -402,38 +538,39 @@ parser_data_loc(const pm_parser_t *parser, VALUE source) {
|
|
402
538
|
* Extract the errors out of the parser into an array.
|
403
539
|
*/
|
404
540
|
static VALUE
|
405
|
-
parser_errors(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
|
406
|
-
VALUE errors =
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
541
|
+
parser_errors(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bool freeze) {
|
542
|
+
VALUE errors = rb_ary_new_capa(parser->error_list.size);
|
543
|
+
|
544
|
+
for (
|
545
|
+
const pm_diagnostic_t *error = (const pm_diagnostic_t *) parser->error_list.head;
|
546
|
+
error != NULL;
|
547
|
+
error = (const pm_diagnostic_t *) error->node.next
|
548
|
+
) {
|
549
|
+
VALUE type = ID2SYM(rb_intern(pm_diagnostic_id_human(error->diag_id)));
|
550
|
+
VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(error->message, encoding));
|
551
|
+
VALUE location = PARSER_LOCATION_LOC(parser, source, freeze, error->location);
|
415
552
|
|
416
553
|
VALUE level = Qnil;
|
417
554
|
switch (error->level) {
|
418
|
-
case
|
419
|
-
level = ID2SYM(rb_intern("
|
555
|
+
case PM_ERROR_LEVEL_SYNTAX:
|
556
|
+
level = ID2SYM(rb_intern("syntax"));
|
420
557
|
break;
|
421
558
|
case PM_ERROR_LEVEL_ARGUMENT:
|
422
559
|
level = ID2SYM(rb_intern("argument"));
|
423
560
|
break;
|
561
|
+
case PM_ERROR_LEVEL_LOAD:
|
562
|
+
level = ID2SYM(rb_intern("load"));
|
563
|
+
break;
|
424
564
|
default:
|
425
565
|
rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, error->level);
|
426
566
|
}
|
427
567
|
|
428
|
-
VALUE
|
429
|
-
|
430
|
-
|
431
|
-
level
|
432
|
-
};
|
433
|
-
|
434
|
-
rb_ary_push(errors, rb_class_new_instance(3, error_argv, rb_cPrismParseError));
|
568
|
+
VALUE argv[] = { type, message, location, level };
|
569
|
+
VALUE value = rb_class_new_instance_freeze(4, argv, rb_cPrismParseError, freeze);
|
570
|
+
rb_ary_push(errors, value);
|
435
571
|
}
|
436
572
|
|
573
|
+
if (freeze) rb_obj_freeze(errors);
|
437
574
|
return errors;
|
438
575
|
}
|
439
576
|
|
@@ -441,16 +578,17 @@ parser_errors(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
|
|
441
578
|
* Extract the warnings out of the parser into an array.
|
442
579
|
*/
|
443
580
|
static VALUE
|
444
|
-
parser_warnings(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
|
445
|
-
VALUE warnings =
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
581
|
+
parser_warnings(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bool freeze) {
|
582
|
+
VALUE warnings = rb_ary_new_capa(parser->warning_list.size);
|
583
|
+
|
584
|
+
for (
|
585
|
+
const pm_diagnostic_t *warning = (const pm_diagnostic_t *) parser->warning_list.head;
|
586
|
+
warning != NULL;
|
587
|
+
warning = (const pm_diagnostic_t *) warning->node.next
|
588
|
+
) {
|
589
|
+
VALUE type = ID2SYM(rb_intern(pm_diagnostic_id_human(warning->diag_id)));
|
590
|
+
VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(warning->message, encoding));
|
591
|
+
VALUE location = PARSER_LOCATION_LOC(parser, source, freeze, warning->location);
|
454
592
|
|
455
593
|
VALUE level = Qnil;
|
456
594
|
switch (warning->level) {
|
@@ -464,18 +602,33 @@ parser_warnings(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
|
|
464
602
|
rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, warning->level);
|
465
603
|
}
|
466
604
|
|
467
|
-
VALUE
|
468
|
-
|
469
|
-
|
470
|
-
level
|
471
|
-
};
|
472
|
-
|
473
|
-
rb_ary_push(warnings, rb_class_new_instance(3, warning_argv, rb_cPrismParseWarning));
|
605
|
+
VALUE argv[] = { type, message, location, level };
|
606
|
+
VALUE value = rb_class_new_instance_freeze(4, argv, rb_cPrismParseWarning, freeze);
|
607
|
+
rb_ary_push(warnings, value);
|
474
608
|
}
|
475
609
|
|
610
|
+
if (freeze) rb_obj_freeze(warnings);
|
476
611
|
return warnings;
|
477
612
|
}
|
478
613
|
|
614
|
+
/**
|
615
|
+
* Create a new parse result from the given parser, value, encoding, and source.
|
616
|
+
*/
|
617
|
+
static VALUE
|
618
|
+
parse_result_create(VALUE class, const pm_parser_t *parser, VALUE value, rb_encoding *encoding, VALUE source, bool freeze) {
|
619
|
+
VALUE result_argv[] = {
|
620
|
+
value,
|
621
|
+
parser_comments(parser, source, freeze),
|
622
|
+
parser_magic_comments(parser, source, freeze),
|
623
|
+
parser_data_loc(parser, source, freeze),
|
624
|
+
parser_errors(parser, encoding, source, freeze),
|
625
|
+
parser_warnings(parser, encoding, source, freeze),
|
626
|
+
source
|
627
|
+
};
|
628
|
+
|
629
|
+
return rb_class_new_instance_freeze(7, result_argv, class, freeze);
|
630
|
+
}
|
631
|
+
|
479
632
|
/******************************************************************************/
|
480
633
|
/* Lexing Ruby code */
|
481
634
|
/******************************************************************************/
|
@@ -489,6 +642,7 @@ typedef struct {
|
|
489
642
|
VALUE source;
|
490
643
|
VALUE tokens;
|
491
644
|
rb_encoding *encoding;
|
645
|
+
bool freeze;
|
492
646
|
} parse_lex_data_t;
|
493
647
|
|
494
648
|
/**
|
@@ -500,9 +654,13 @@ static void
|
|
500
654
|
parse_lex_token(void *data, pm_parser_t *parser, pm_token_t *token) {
|
501
655
|
parse_lex_data_t *parse_lex_data = (parse_lex_data_t *) parser->lex_callback->data;
|
502
656
|
|
503
|
-
VALUE
|
504
|
-
|
505
|
-
|
657
|
+
VALUE value = pm_token_new(parser, token, parse_lex_data->encoding, parse_lex_data->source, parse_lex_data->freeze);
|
658
|
+
VALUE yields = rb_assoc_new(value, INT2FIX(parser->lex_state));
|
659
|
+
|
660
|
+
if (parse_lex_data->freeze) {
|
661
|
+
rb_obj_freeze(value);
|
662
|
+
rb_obj_freeze(yields);
|
663
|
+
}
|
506
664
|
|
507
665
|
rb_ary_push(parse_lex_data->tokens, yields);
|
508
666
|
}
|
@@ -522,14 +680,37 @@ parse_lex_encoding_changed_callback(pm_parser_t *parser) {
|
|
522
680
|
// one or two tokens, since the encoding can only change at the top of the
|
523
681
|
// file.
|
524
682
|
VALUE tokens = parse_lex_data->tokens;
|
683
|
+
VALUE next_tokens = rb_ary_new();
|
684
|
+
|
525
685
|
for (long index = 0; index < RARRAY_LEN(tokens); index++) {
|
526
686
|
VALUE yields = rb_ary_entry(tokens, index);
|
527
687
|
VALUE token = rb_ary_entry(yields, 0);
|
528
688
|
|
529
689
|
VALUE value = rb_ivar_get(token, rb_intern("@value"));
|
530
|
-
|
531
|
-
|
690
|
+
VALUE next_value = rb_str_dup(value);
|
691
|
+
|
692
|
+
rb_enc_associate(next_value, parse_lex_data->encoding);
|
693
|
+
if (parse_lex_data->freeze) rb_obj_freeze(next_value);
|
694
|
+
|
695
|
+
VALUE next_token_argv[] = {
|
696
|
+
parse_lex_data->source,
|
697
|
+
rb_ivar_get(token, rb_intern("@type")),
|
698
|
+
next_value,
|
699
|
+
rb_ivar_get(token, rb_intern("@location"))
|
700
|
+
};
|
701
|
+
|
702
|
+
VALUE next_token = rb_class_new_instance(4, next_token_argv, rb_cPrismToken);
|
703
|
+
VALUE next_yields = rb_assoc_new(next_token, rb_ary_entry(yields, 1));
|
704
|
+
|
705
|
+
if (parse_lex_data->freeze) {
|
706
|
+
rb_obj_freeze(next_token);
|
707
|
+
rb_obj_freeze(next_yields);
|
708
|
+
}
|
709
|
+
|
710
|
+
rb_ary_push(next_tokens, next_yields);
|
532
711
|
}
|
712
|
+
|
713
|
+
rb_ary_replace(parse_lex_data->tokens, next_tokens);
|
533
714
|
}
|
534
715
|
|
535
716
|
/**
|
@@ -543,14 +724,14 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod
|
|
543
724
|
pm_parser_register_encoding_changed_callback(&parser, parse_lex_encoding_changed_callback);
|
544
725
|
|
545
726
|
VALUE source_string = rb_str_new((const char *) pm_string_source(input), pm_string_length(input));
|
546
|
-
VALUE offsets =
|
547
|
-
VALUE
|
548
|
-
VALUE source = rb_class_new_instance(3, source_argv, rb_cPrismSource);
|
727
|
+
VALUE offsets = rb_ary_new_capa(parser.newline_list.size);
|
728
|
+
VALUE source = rb_funcall(rb_cPrismSource, rb_id_source_for, 3, source_string, LONG2NUM(parser.start_line), offsets);
|
549
729
|
|
550
730
|
parse_lex_data_t parse_lex_data = {
|
551
731
|
.source = source,
|
552
732
|
.tokens = rb_ary_new(),
|
553
|
-
.encoding = rb_utf8_encoding()
|
733
|
+
.encoding = rb_utf8_encoding(),
|
734
|
+
.freeze = options->freeze,
|
554
735
|
};
|
555
736
|
|
556
737
|
parse_lex_data_t *data = &parse_lex_data;
|
@@ -573,36 +754,36 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod
|
|
573
754
|
rb_ary_push(offsets, ULONG2NUM(parser.newline_list.offsets[index]));
|
574
755
|
}
|
575
756
|
|
576
|
-
|
757
|
+
if (options->freeze) {
|
758
|
+
rb_obj_freeze(source_string);
|
759
|
+
rb_obj_freeze(offsets);
|
760
|
+
rb_obj_freeze(source);
|
761
|
+
rb_obj_freeze(parse_lex_data.tokens);
|
762
|
+
}
|
763
|
+
|
764
|
+
VALUE result;
|
577
765
|
if (return_nodes) {
|
578
|
-
value = rb_ary_new_capa(2);
|
579
|
-
rb_ary_push(value, pm_ast_new(&parser, node, parse_lex_data.encoding, source));
|
766
|
+
VALUE value = rb_ary_new_capa(2);
|
767
|
+
rb_ary_push(value, pm_ast_new(&parser, node, parse_lex_data.encoding, source, options->freeze));
|
580
768
|
rb_ary_push(value, parse_lex_data.tokens);
|
769
|
+
if (options->freeze) rb_obj_freeze(value);
|
770
|
+
result = parse_result_create(rb_cPrismParseLexResult, &parser, value, parse_lex_data.encoding, source, options->freeze);
|
581
771
|
} else {
|
582
|
-
|
772
|
+
result = parse_result_create(rb_cPrismLexResult, &parser, parse_lex_data.tokens, parse_lex_data.encoding, source, options->freeze);
|
583
773
|
}
|
584
774
|
|
585
|
-
VALUE result_argv[] = {
|
586
|
-
value,
|
587
|
-
parser_comments(&parser, source),
|
588
|
-
parser_magic_comments(&parser, source),
|
589
|
-
parser_data_loc(&parser, source),
|
590
|
-
parser_errors(&parser, parse_lex_data.encoding, source),
|
591
|
-
parser_warnings(&parser, parse_lex_data.encoding, source),
|
592
|
-
source
|
593
|
-
};
|
594
|
-
|
595
775
|
pm_node_destroy(&parser, node);
|
596
776
|
pm_parser_free(&parser);
|
597
|
-
|
777
|
+
|
778
|
+
return result;
|
598
779
|
}
|
599
780
|
|
600
781
|
/**
|
601
782
|
* call-seq:
|
602
|
-
* Prism::lex(source, **options) ->
|
783
|
+
* Prism::lex(source, **options) -> LexResult
|
603
784
|
*
|
604
|
-
* Return an array of Token instances
|
605
|
-
* supported options, see Prism::parse.
|
785
|
+
* Return a LexResult instance that contains an array of Token instances
|
786
|
+
* corresponding to the given string. For supported options, see Prism::parse.
|
606
787
|
*/
|
607
788
|
static VALUE
|
608
789
|
lex(int argc, VALUE *argv, VALUE self) {
|
@@ -619,17 +800,18 @@ lex(int argc, VALUE *argv, VALUE self) {
|
|
619
800
|
|
620
801
|
/**
|
621
802
|
* call-seq:
|
622
|
-
* Prism::lex_file(filepath, **options) ->
|
803
|
+
* Prism::lex_file(filepath, **options) -> LexResult
|
623
804
|
*
|
624
|
-
* Return an array of Token instances
|
625
|
-
* supported options, see Prism::parse.
|
805
|
+
* Return a LexResult instance that contains an array of Token instances
|
806
|
+
* corresponding to the given file. For supported options, see Prism::parse.
|
626
807
|
*/
|
627
808
|
static VALUE
|
628
809
|
lex_file(int argc, VALUE *argv, VALUE self) {
|
629
810
|
pm_string_t input;
|
630
811
|
pm_options_t options = { 0 };
|
631
812
|
|
632
|
-
|
813
|
+
VALUE encoded_filepath;
|
814
|
+
file_options(argc, argv, &input, &options, &encoded_filepath);
|
633
815
|
|
634
816
|
VALUE value = parse_lex_input(&input, &options, false);
|
635
817
|
pm_string_free(&input);
|
@@ -653,18 +835,13 @@ parse_input(pm_string_t *input, const pm_options_t *options) {
|
|
653
835
|
pm_node_t *node = pm_parse(&parser);
|
654
836
|
rb_encoding *encoding = rb_enc_find(parser.encoding->name);
|
655
837
|
|
656
|
-
VALUE source = pm_source_new(&parser, encoding);
|
657
|
-
VALUE
|
658
|
-
|
659
|
-
parser_comments(&parser, source),
|
660
|
-
parser_magic_comments(&parser, source),
|
661
|
-
parser_data_loc(&parser, source),
|
662
|
-
parser_errors(&parser, encoding, source),
|
663
|
-
parser_warnings(&parser, encoding, source),
|
664
|
-
source
|
665
|
-
};
|
838
|
+
VALUE source = pm_source_new(&parser, encoding, options->freeze);
|
839
|
+
VALUE value = pm_ast_new(&parser, node, encoding, source, options->freeze);
|
840
|
+
VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source, options->freeze);
|
666
841
|
|
667
|
-
|
842
|
+
if (options->freeze) {
|
843
|
+
rb_obj_freeze(source);
|
844
|
+
}
|
668
845
|
|
669
846
|
pm_node_destroy(&parser, node);
|
670
847
|
pm_parser_free(&parser);
|
@@ -679,21 +856,40 @@ parse_input(pm_string_t *input, const pm_options_t *options) {
|
|
679
856
|
* Parse the given string and return a ParseResult instance. The options that
|
680
857
|
* are supported are:
|
681
858
|
*
|
682
|
-
* * `
|
683
|
-
*
|
859
|
+
* * `command_line` - either nil or a string of the various options that were
|
860
|
+
* set on the command line. Valid values are combinations of "a", "l",
|
861
|
+
* "n", "p", and "x".
|
684
862
|
* * `encoding` - the encoding of the source being parsed. This should be an
|
685
|
-
* encoding or nil
|
686
|
-
* * `
|
687
|
-
*
|
863
|
+
* encoding or nil.
|
864
|
+
* * `filepath` - the filepath of the source being parsed. This should be a
|
865
|
+
* string or nil.
|
866
|
+
* * `freeze` - whether or not to deeply freeze the AST. This should be a
|
867
|
+
* boolean or nil.
|
688
868
|
* * `frozen_string_literal` - whether or not the frozen string literal pragma
|
689
869
|
* has been set. This should be a boolean or nil.
|
690
|
-
* * `
|
691
|
-
*
|
692
|
-
*
|
693
|
-
*
|
870
|
+
* * `line` - the line number that the parse starts on. This should be an
|
871
|
+
* integer or nil. Note that this is 1-indexed.
|
872
|
+
* * `main_script` - a boolean indicating whether or not the source being parsed
|
873
|
+
* is the main script being run by the interpreter. This controls whether
|
874
|
+
* or not shebangs are parsed for additional flags and whether or not the
|
875
|
+
* parser will attempt to find a matching shebang if the first one does
|
876
|
+
* not contain the word "ruby".
|
877
|
+
* * `partial_script` - when the file being parsed is considered a "partial"
|
878
|
+
* script, jumps will not be marked as errors if they are not contained
|
879
|
+
* within loops/blocks. This is used in the case that you're parsing a
|
880
|
+
* script that you know will be embedded inside another script later, but
|
881
|
+
* you do not have that context yet. For example, when parsing an ERB
|
882
|
+
* template that will be evaluated inside another script.
|
694
883
|
* * `scopes` - the locals that are in scope surrounding the code that is being
|
695
884
|
* parsed. This should be an array of arrays of symbols or nil. Scopes are
|
696
885
|
* ordered from the outermost scope to the innermost one.
|
886
|
+
* * `version` - the version of Ruby syntax that prism should used to parse Ruby
|
887
|
+
* code. By default prism assumes you want to parse with the latest
|
888
|
+
* version of Ruby syntax (which you can trigger with `nil` or
|
889
|
+
* `"latest"`). You may also restrict the syntax to a specific version of
|
890
|
+
* Ruby, e.g., with `"3.3.0"`. To parse with the same syntax version that
|
891
|
+
* the current Ruby is running use `version: RUBY_VERSION`. Raises
|
892
|
+
* ArgumentError if the version is not currently supported by Prism.
|
697
893
|
*/
|
698
894
|
static VALUE
|
699
895
|
parse(int argc, VALUE *argv, VALUE self) {
|
@@ -701,17 +897,17 @@ parse(int argc, VALUE *argv, VALUE self) {
|
|
701
897
|
pm_options_t options = { 0 };
|
702
898
|
string_options(argc, argv, &input, &options);
|
703
899
|
|
704
|
-
#ifdef
|
900
|
+
#ifdef PRISM_BUILD_DEBUG
|
705
901
|
size_t length = pm_string_length(&input);
|
706
|
-
char* dup =
|
902
|
+
char* dup = xmalloc(length);
|
707
903
|
memcpy(dup, pm_string_source(&input), length);
|
708
904
|
pm_string_constant_init(&input, dup, length);
|
709
905
|
#endif
|
710
906
|
|
711
907
|
VALUE value = parse_input(&input, &options);
|
712
908
|
|
713
|
-
#ifdef
|
714
|
-
|
909
|
+
#ifdef PRISM_BUILD_DEBUG
|
910
|
+
xfree(dup);
|
715
911
|
#endif
|
716
912
|
|
717
913
|
pm_string_free(&input);
|
@@ -731,7 +927,8 @@ parse_file(int argc, VALUE *argv, VALUE self) {
|
|
731
927
|
pm_string_t input;
|
732
928
|
pm_options_t options = { 0 };
|
733
929
|
|
734
|
-
|
930
|
+
VALUE encoded_filepath;
|
931
|
+
file_options(argc, argv, &input, &options, &encoded_filepath);
|
735
932
|
|
736
933
|
VALUE value = parse_input(&input, &options);
|
737
934
|
pm_string_free(&input);
|
@@ -740,6 +937,117 @@ parse_file(int argc, VALUE *argv, VALUE self) {
|
|
740
937
|
return value;
|
741
938
|
}
|
742
939
|
|
940
|
+
/**
|
941
|
+
* Parse the given input and return nothing.
|
942
|
+
*/
|
943
|
+
static void
|
944
|
+
profile_input(pm_string_t *input, const pm_options_t *options) {
|
945
|
+
pm_parser_t parser;
|
946
|
+
pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options);
|
947
|
+
|
948
|
+
pm_node_t *node = pm_parse(&parser);
|
949
|
+
pm_node_destroy(&parser, node);
|
950
|
+
pm_parser_free(&parser);
|
951
|
+
}
|
952
|
+
|
953
|
+
/**
|
954
|
+
* call-seq:
|
955
|
+
* Prism::profile(source, **options) -> nil
|
956
|
+
*
|
957
|
+
* Parse the given string and return nothing. This method is meant to allow
|
958
|
+
* profilers to avoid the overhead of reifying the AST to Ruby. For supported
|
959
|
+
* options, see Prism::parse.
|
960
|
+
*/
|
961
|
+
static VALUE
|
962
|
+
profile(int argc, VALUE *argv, VALUE self) {
|
963
|
+
pm_string_t input;
|
964
|
+
pm_options_t options = { 0 };
|
965
|
+
|
966
|
+
string_options(argc, argv, &input, &options);
|
967
|
+
profile_input(&input, &options);
|
968
|
+
pm_string_free(&input);
|
969
|
+
pm_options_free(&options);
|
970
|
+
|
971
|
+
return Qnil;
|
972
|
+
}
|
973
|
+
|
974
|
+
/**
|
975
|
+
* call-seq:
|
976
|
+
* Prism::profile_file(filepath, **options) -> nil
|
977
|
+
*
|
978
|
+
* Parse the given file and return nothing. This method is meant to allow
|
979
|
+
* profilers to avoid the overhead of reifying the AST to Ruby. For supported
|
980
|
+
* options, see Prism::parse.
|
981
|
+
*/
|
982
|
+
static VALUE
|
983
|
+
profile_file(int argc, VALUE *argv, VALUE self) {
|
984
|
+
pm_string_t input;
|
985
|
+
pm_options_t options = { 0 };
|
986
|
+
|
987
|
+
VALUE encoded_filepath;
|
988
|
+
file_options(argc, argv, &input, &options, &encoded_filepath);
|
989
|
+
|
990
|
+
profile_input(&input, &options);
|
991
|
+
pm_string_free(&input);
|
992
|
+
pm_options_free(&options);
|
993
|
+
|
994
|
+
return Qnil;
|
995
|
+
}
|
996
|
+
|
997
|
+
/**
|
998
|
+
* An implementation of fgets that is suitable for use with Ruby IO objects.
|
999
|
+
*/
|
1000
|
+
static char *
|
1001
|
+
parse_stream_fgets(char *string, int size, void *stream) {
|
1002
|
+
RUBY_ASSERT(size > 0);
|
1003
|
+
|
1004
|
+
VALUE line = rb_funcall((VALUE) stream, rb_intern("gets"), 1, INT2FIX(size - 1));
|
1005
|
+
if (NIL_P(line)) {
|
1006
|
+
return NULL;
|
1007
|
+
}
|
1008
|
+
|
1009
|
+
const char *cstr = RSTRING_PTR(line);
|
1010
|
+
long length = RSTRING_LEN(line);
|
1011
|
+
|
1012
|
+
memcpy(string, cstr, length);
|
1013
|
+
string[length] = '\0';
|
1014
|
+
|
1015
|
+
return string;
|
1016
|
+
}
|
1017
|
+
|
1018
|
+
/**
|
1019
|
+
* call-seq:
|
1020
|
+
* Prism::parse_stream(stream, **options) -> ParseResult
|
1021
|
+
*
|
1022
|
+
* Parse the given object that responds to `gets` and return a ParseResult
|
1023
|
+
* instance. The options that are supported are the same as Prism::parse.
|
1024
|
+
*/
|
1025
|
+
static VALUE
|
1026
|
+
parse_stream(int argc, VALUE *argv, VALUE self) {
|
1027
|
+
VALUE stream;
|
1028
|
+
VALUE keywords;
|
1029
|
+
rb_scan_args(argc, argv, "1:", &stream, &keywords);
|
1030
|
+
|
1031
|
+
pm_options_t options = { 0 };
|
1032
|
+
extract_options(&options, Qnil, keywords);
|
1033
|
+
|
1034
|
+
pm_parser_t parser;
|
1035
|
+
pm_buffer_t buffer;
|
1036
|
+
|
1037
|
+
pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, &options);
|
1038
|
+
rb_encoding *encoding = rb_enc_find(parser.encoding->name);
|
1039
|
+
|
1040
|
+
VALUE source = pm_source_new(&parser, encoding, options.freeze);
|
1041
|
+
VALUE value = pm_ast_new(&parser, node, encoding, source, options.freeze);
|
1042
|
+
VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source, options.freeze);
|
1043
|
+
|
1044
|
+
pm_node_destroy(&parser, node);
|
1045
|
+
pm_buffer_free(&buffer);
|
1046
|
+
pm_parser_free(&parser);
|
1047
|
+
|
1048
|
+
return result;
|
1049
|
+
}
|
1050
|
+
|
743
1051
|
/**
|
744
1052
|
* Parse the given input and return an array of Comment objects.
|
745
1053
|
*/
|
@@ -751,8 +1059,8 @@ parse_input_comments(pm_string_t *input, const pm_options_t *options) {
|
|
751
1059
|
pm_node_t *node = pm_parse(&parser);
|
752
1060
|
rb_encoding *encoding = rb_enc_find(parser.encoding->name);
|
753
1061
|
|
754
|
-
VALUE source = pm_source_new(&parser, encoding);
|
755
|
-
VALUE comments = parser_comments(&parser, source);
|
1062
|
+
VALUE source = pm_source_new(&parser, encoding, options->freeze);
|
1063
|
+
VALUE comments = parser_comments(&parser, source, options->freeze);
|
756
1064
|
|
757
1065
|
pm_node_destroy(&parser, node);
|
758
1066
|
pm_parser_free(&parser);
|
@@ -792,7 +1100,8 @@ parse_file_comments(int argc, VALUE *argv, VALUE self) {
|
|
792
1100
|
pm_string_t input;
|
793
1101
|
pm_options_t options = { 0 };
|
794
1102
|
|
795
|
-
|
1103
|
+
VALUE encoded_filepath;
|
1104
|
+
file_options(argc, argv, &input, &options, &encoded_filepath);
|
796
1105
|
|
797
1106
|
VALUE value = parse_input_comments(&input, &options);
|
798
1107
|
pm_string_free(&input);
|
@@ -803,9 +1112,9 @@ parse_file_comments(int argc, VALUE *argv, VALUE self) {
|
|
803
1112
|
|
804
1113
|
/**
|
805
1114
|
* call-seq:
|
806
|
-
* Prism::parse_lex(source, **options) ->
|
1115
|
+
* Prism::parse_lex(source, **options) -> ParseLexResult
|
807
1116
|
*
|
808
|
-
* Parse the given string and return a
|
1117
|
+
* Parse the given string and return a ParseLexResult instance that contains a
|
809
1118
|
* 2-element array, where the first element is the AST and the second element is
|
810
1119
|
* an array of Token instances.
|
811
1120
|
*
|
@@ -830,9 +1139,9 @@ parse_lex(int argc, VALUE *argv, VALUE self) {
|
|
830
1139
|
|
831
1140
|
/**
|
832
1141
|
* call-seq:
|
833
|
-
* Prism::parse_lex_file(filepath, **options) ->
|
1142
|
+
* Prism::parse_lex_file(filepath, **options) -> ParseLexResult
|
834
1143
|
*
|
835
|
-
* Parse the given file and return a
|
1144
|
+
* Parse the given file and return a ParseLexResult instance that contains a
|
836
1145
|
* 2-element array, where the first element is the AST and the second element is
|
837
1146
|
* an array of Token instances.
|
838
1147
|
*
|
@@ -847,7 +1156,8 @@ parse_lex_file(int argc, VALUE *argv, VALUE self) {
|
|
847
1156
|
pm_string_t input;
|
848
1157
|
pm_options_t options = { 0 };
|
849
1158
|
|
850
|
-
|
1159
|
+
VALUE encoded_filepath;
|
1160
|
+
file_options(argc, argv, &input, &options, &encoded_filepath);
|
851
1161
|
|
852
1162
|
VALUE value = parse_lex_input(&input, &options, true);
|
853
1163
|
pm_string_free(&input);
|
@@ -875,7 +1185,7 @@ parse_input_success_p(pm_string_t *input, const pm_options_t *options) {
|
|
875
1185
|
|
876
1186
|
/**
|
877
1187
|
* call-seq:
|
878
|
-
* Prism::parse_success?(source, **options) ->
|
1188
|
+
* Prism::parse_success?(source, **options) -> bool
|
879
1189
|
*
|
880
1190
|
* Parse the given string and return true if it parses without errors. For
|
881
1191
|
* supported options, see Prism::parse.
|
@@ -895,7 +1205,19 @@ parse_success_p(int argc, VALUE *argv, VALUE self) {
|
|
895
1205
|
|
896
1206
|
/**
|
897
1207
|
* call-seq:
|
898
|
-
* Prism::
|
1208
|
+
* Prism::parse_failure?(source, **options) -> bool
|
1209
|
+
*
|
1210
|
+
* Parse the given string and return true if it parses with errors. For
|
1211
|
+
* supported options, see Prism::parse.
|
1212
|
+
*/
|
1213
|
+
static VALUE
|
1214
|
+
parse_failure_p(int argc, VALUE *argv, VALUE self) {
|
1215
|
+
return RTEST(parse_success_p(argc, argv, self)) ? Qfalse : Qtrue;
|
1216
|
+
}
|
1217
|
+
|
1218
|
+
/**
|
1219
|
+
* call-seq:
|
1220
|
+
* Prism::parse_file_success?(filepath, **options) -> bool
|
899
1221
|
*
|
900
1222
|
* Parse the given file and return true if it parses without errors. For
|
901
1223
|
* supported options, see Prism::parse.
|
@@ -905,7 +1227,8 @@ parse_file_success_p(int argc, VALUE *argv, VALUE self) {
|
|
905
1227
|
pm_string_t input;
|
906
1228
|
pm_options_t options = { 0 };
|
907
1229
|
|
908
|
-
|
1230
|
+
VALUE encoded_filepath;
|
1231
|
+
file_options(argc, argv, &input, &options, &encoded_filepath);
|
909
1232
|
|
910
1233
|
VALUE result = parse_input_success_p(&input, &options);
|
911
1234
|
pm_string_free(&input);
|
@@ -914,160 +1237,78 @@ parse_file_success_p(int argc, VALUE *argv, VALUE self) {
|
|
914
1237
|
return result;
|
915
1238
|
}
|
916
1239
|
|
917
|
-
/******************************************************************************/
|
918
|
-
/* Utility functions exposed to make testing easier */
|
919
|
-
/******************************************************************************/
|
920
|
-
|
921
1240
|
/**
|
922
1241
|
* call-seq:
|
923
|
-
*
|
1242
|
+
* Prism::parse_file_failure?(filepath, **options) -> bool
|
924
1243
|
*
|
925
|
-
*
|
926
|
-
*
|
927
|
-
* this function returns nil.
|
1244
|
+
* Parse the given file and return true if it parses with errors. For
|
1245
|
+
* supported options, see Prism::parse.
|
928
1246
|
*/
|
929
1247
|
static VALUE
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
if (!pm_regexp_named_capture_group_names((const uint8_t *) RSTRING_PTR(source), RSTRING_LEN(source), &string_list, false, PM_ENCODING_UTF_8_ENTRY)) {
|
934
|
-
pm_string_list_free(&string_list);
|
935
|
-
return Qnil;
|
936
|
-
}
|
937
|
-
|
938
|
-
VALUE names = rb_ary_new();
|
939
|
-
for (size_t index = 0; index < string_list.length; index++) {
|
940
|
-
const pm_string_t *string = &string_list.strings[index];
|
941
|
-
rb_ary_push(names, rb_str_new((const char *) pm_string_source(string), pm_string_length(string)));
|
942
|
-
}
|
943
|
-
|
944
|
-
pm_string_list_free(&string_list);
|
945
|
-
return names;
|
1248
|
+
parse_file_failure_p(int argc, VALUE *argv, VALUE self) {
|
1249
|
+
return RTEST(parse_file_success_p(argc, argv, self)) ? Qfalse : Qtrue;
|
946
1250
|
}
|
947
1251
|
|
1252
|
+
/******************************************************************************/
|
1253
|
+
/* String query methods */
|
1254
|
+
/******************************************************************************/
|
1255
|
+
|
948
1256
|
/**
|
949
|
-
* call
|
950
|
-
*
|
951
|
-
*
|
952
|
-
* Return a hash of information about the given source string's memory usage.
|
1257
|
+
* Process the result of a call to a string query method and return an
|
1258
|
+
* appropriate value.
|
953
1259
|
*/
|
954
1260
|
static VALUE
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
VALUE result = rb_hash_new();
|
968
|
-
rb_hash_aset(result, ID2SYM(rb_intern("length")), INT2FIX(length));
|
969
|
-
rb_hash_aset(result, ID2SYM(rb_intern("memsize")), INT2FIX(memsize.memsize));
|
970
|
-
rb_hash_aset(result, ID2SYM(rb_intern("node_count")), INT2FIX(memsize.node_count));
|
971
|
-
return result;
|
1261
|
+
string_query(pm_string_query_t result) {
|
1262
|
+
switch (result) {
|
1263
|
+
case PM_STRING_QUERY_ERROR:
|
1264
|
+
rb_raise(rb_eArgError, "Invalid or non ascii-compatible encoding");
|
1265
|
+
return Qfalse;
|
1266
|
+
case PM_STRING_QUERY_FALSE:
|
1267
|
+
return Qfalse;
|
1268
|
+
case PM_STRING_QUERY_TRUE:
|
1269
|
+
return Qtrue;
|
1270
|
+
}
|
1271
|
+
return Qfalse;
|
972
1272
|
}
|
973
1273
|
|
974
1274
|
/**
|
975
1275
|
* call-seq:
|
976
|
-
*
|
1276
|
+
* Prism::StringQuery::local?(string) -> bool
|
977
1277
|
*
|
978
|
-
*
|
979
|
-
*
|
1278
|
+
* Returns true if the string constitutes a valid local variable name. Note that
|
1279
|
+
* this means the names that can be set through Binding#local_variable_set, not
|
1280
|
+
* necessarily the ones that can be set through a local variable assignment.
|
980
1281
|
*/
|
981
1282
|
static VALUE
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
const char *checked = check_string(filepath);
|
986
|
-
Check_Type(filepath, T_STRING);
|
987
|
-
|
988
|
-
if (!pm_string_mapped_init(&input, checked)) {
|
989
|
-
#ifdef _WIN32
|
990
|
-
int e = rb_w32_map_errno(GetLastError());
|
991
|
-
#else
|
992
|
-
int e = errno;
|
993
|
-
#endif
|
994
|
-
|
995
|
-
rb_syserr_fail(e, checked);
|
996
|
-
}
|
997
|
-
|
998
|
-
pm_options_t options = { 0 };
|
999
|
-
pm_options_filepath_set(&options, checked);
|
1000
|
-
|
1001
|
-
pm_parser_t parser;
|
1002
|
-
pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), &options);
|
1003
|
-
|
1004
|
-
pm_node_t *node = pm_parse(&parser);
|
1005
|
-
pm_node_destroy(&parser, node);
|
1006
|
-
pm_parser_free(&parser);
|
1007
|
-
pm_options_free(&options);
|
1008
|
-
pm_string_free(&input);
|
1009
|
-
|
1010
|
-
return Qnil;
|
1283
|
+
string_query_local_p(VALUE self, VALUE string) {
|
1284
|
+
const uint8_t *source = (const uint8_t *) check_string(string);
|
1285
|
+
return string_query(pm_string_query_local(source, RSTRING_LEN(string), rb_enc_get(string)->name));
|
1011
1286
|
}
|
1012
1287
|
|
1013
1288
|
/**
|
1014
1289
|
* call-seq:
|
1015
|
-
*
|
1290
|
+
* Prism::StringQuery::constant?(string) -> bool
|
1016
1291
|
*
|
1017
|
-
*
|
1018
|
-
*
|
1292
|
+
* Returns true if the string constitutes a valid constant name. Note that this
|
1293
|
+
* means the names that can be set through Module#const_set, not necessarily the
|
1294
|
+
* ones that can be set through a constant assignment.
|
1019
1295
|
*/
|
1020
1296
|
static VALUE
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
pm_parser_t parser;
|
1026
|
-
pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), NULL);
|
1027
|
-
|
1028
|
-
pm_node_t *node = pm_parse(&parser);
|
1029
|
-
pm_buffer_t buffer = { 0 };
|
1030
|
-
|
1031
|
-
pm_prettyprint(&buffer, &parser, node);
|
1032
|
-
|
1033
|
-
rb_encoding *encoding = rb_enc_find(parser.encoding->name);
|
1034
|
-
VALUE string = rb_enc_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer), encoding);
|
1035
|
-
|
1036
|
-
pm_buffer_free(&buffer);
|
1037
|
-
pm_node_destroy(&parser, node);
|
1038
|
-
pm_parser_free(&parser);
|
1039
|
-
|
1040
|
-
return string;
|
1297
|
+
string_query_constant_p(VALUE self, VALUE string) {
|
1298
|
+
const uint8_t *source = (const uint8_t *) check_string(string);
|
1299
|
+
return string_query(pm_string_query_constant(source, RSTRING_LEN(string), rb_enc_get(string)->name));
|
1041
1300
|
}
|
1042
1301
|
|
1043
1302
|
/**
|
1044
1303
|
* call-seq:
|
1045
|
-
*
|
1304
|
+
* Prism::StringQuery::method_name?(string) -> bool
|
1046
1305
|
*
|
1047
|
-
*
|
1306
|
+
* Returns true if the string constitutes a valid method name.
|
1048
1307
|
*/
|
1049
1308
|
static VALUE
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
pm_parser_t parser;
|
1055
|
-
pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), NULL);
|
1056
|
-
|
1057
|
-
pm_node_t *node = pm_parse(&parser);
|
1058
|
-
pm_buffer_t buffer = { 0 };
|
1059
|
-
|
1060
|
-
pm_parser_errors_format(&parser, &buffer, RTEST(colorize));
|
1061
|
-
|
1062
|
-
rb_encoding *encoding = rb_enc_find(parser.encoding->name);
|
1063
|
-
VALUE result = rb_enc_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer), encoding);
|
1064
|
-
|
1065
|
-
pm_buffer_free(&buffer);
|
1066
|
-
pm_node_destroy(&parser, node);
|
1067
|
-
pm_parser_free(&parser);
|
1068
|
-
pm_string_free(&input);
|
1069
|
-
|
1070
|
-
return result;
|
1309
|
+
string_query_method_name_p(VALUE self, VALUE string) {
|
1310
|
+
const uint8_t *source = (const uint8_t *) check_string(string);
|
1311
|
+
return string_query(pm_string_query_method_name(source, RSTRING_LEN(string), rb_enc_get(string)->name));
|
1071
1312
|
}
|
1072
1313
|
|
1073
1314
|
/******************************************************************************/
|
@@ -1103,51 +1344,61 @@ Init_prism(void) {
|
|
1103
1344
|
rb_cPrismMagicComment = rb_define_class_under(rb_cPrism, "MagicComment", rb_cObject);
|
1104
1345
|
rb_cPrismParseError = rb_define_class_under(rb_cPrism, "ParseError", rb_cObject);
|
1105
1346
|
rb_cPrismParseWarning = rb_define_class_under(rb_cPrism, "ParseWarning", rb_cObject);
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1347
|
+
rb_cPrismResult = rb_define_class_under(rb_cPrism, "Result", rb_cObject);
|
1348
|
+
rb_cPrismParseResult = rb_define_class_under(rb_cPrism, "ParseResult", rb_cPrismResult);
|
1349
|
+
rb_cPrismLexResult = rb_define_class_under(rb_cPrism, "LexResult", rb_cPrismResult);
|
1350
|
+
rb_cPrismParseLexResult = rb_define_class_under(rb_cPrism, "ParseLexResult", rb_cPrismResult);
|
1351
|
+
rb_cPrismStringQuery = rb_define_class_under(rb_cPrism, "StringQuery", rb_cObject);
|
1352
|
+
rb_cPrismScope = rb_define_class_under(rb_cPrism, "Scope", rb_cObject);
|
1353
|
+
|
1354
|
+
// Intern all of the IDs eagerly that we support so that we don't have to do
|
1355
|
+
// it every time we parse.
|
1356
|
+
rb_id_option_command_line = rb_intern_const("command_line");
|
1357
|
+
rb_id_option_encoding = rb_intern_const("encoding");
|
1358
|
+
rb_id_option_filepath = rb_intern_const("filepath");
|
1359
|
+
rb_id_option_freeze = rb_intern_const("freeze");
|
1360
|
+
rb_id_option_frozen_string_literal = rb_intern_const("frozen_string_literal");
|
1361
|
+
rb_id_option_line = rb_intern_const("line");
|
1362
|
+
rb_id_option_main_script = rb_intern_const("main_script");
|
1363
|
+
rb_id_option_partial_script = rb_intern_const("partial_script");
|
1364
|
+
rb_id_option_scopes = rb_intern_const("scopes");
|
1365
|
+
rb_id_option_version = rb_intern_const("version");
|
1366
|
+
rb_id_source_for = rb_intern("for");
|
1367
|
+
rb_id_forwarding_positionals = rb_intern("*");
|
1368
|
+
rb_id_forwarding_keywords = rb_intern("**");
|
1369
|
+
rb_id_forwarding_block = rb_intern("&");
|
1370
|
+
rb_id_forwarding_all = rb_intern("...");
|
1116
1371
|
|
1117
1372
|
/**
|
1118
1373
|
* The version of the prism library.
|
1119
1374
|
*/
|
1120
|
-
rb_define_const(rb_cPrism, "VERSION",
|
1121
|
-
|
1122
|
-
/**
|
1123
|
-
* The backend of the parser that prism is using to parse Ruby code. This
|
1124
|
-
* can be either :CEXT or :FFI. On runtimes that support C extensions, we
|
1125
|
-
* default to :CEXT. Otherwise we use :FFI.
|
1126
|
-
*/
|
1127
|
-
rb_define_const(rb_cPrism, "BACKEND", ID2SYM(rb_intern("CEXT")));
|
1375
|
+
rb_define_const(rb_cPrism, "VERSION", rb_str_freeze(rb_str_new_cstr(EXPECTED_PRISM_VERSION)));
|
1128
1376
|
|
1129
1377
|
// First, the functions that have to do with lexing and parsing.
|
1130
|
-
rb_define_singleton_method(rb_cPrism, "dump", dump, -1);
|
1131
|
-
rb_define_singleton_method(rb_cPrism, "dump_file", dump_file, -1);
|
1132
1378
|
rb_define_singleton_method(rb_cPrism, "lex", lex, -1);
|
1133
1379
|
rb_define_singleton_method(rb_cPrism, "lex_file", lex_file, -1);
|
1134
1380
|
rb_define_singleton_method(rb_cPrism, "parse", parse, -1);
|
1135
1381
|
rb_define_singleton_method(rb_cPrism, "parse_file", parse_file, -1);
|
1382
|
+
rb_define_singleton_method(rb_cPrism, "profile", profile, -1);
|
1383
|
+
rb_define_singleton_method(rb_cPrism, "profile_file", profile_file, -1);
|
1384
|
+
rb_define_singleton_method(rb_cPrism, "parse_stream", parse_stream, -1);
|
1136
1385
|
rb_define_singleton_method(rb_cPrism, "parse_comments", parse_comments, -1);
|
1137
1386
|
rb_define_singleton_method(rb_cPrism, "parse_file_comments", parse_file_comments, -1);
|
1138
1387
|
rb_define_singleton_method(rb_cPrism, "parse_lex", parse_lex, -1);
|
1139
1388
|
rb_define_singleton_method(rb_cPrism, "parse_lex_file", parse_lex_file, -1);
|
1140
1389
|
rb_define_singleton_method(rb_cPrism, "parse_success?", parse_success_p, -1);
|
1390
|
+
rb_define_singleton_method(rb_cPrism, "parse_failure?", parse_failure_p, -1);
|
1141
1391
|
rb_define_singleton_method(rb_cPrism, "parse_file_success?", parse_file_success_p, -1);
|
1392
|
+
rb_define_singleton_method(rb_cPrism, "parse_file_failure?", parse_file_failure_p, -1);
|
1393
|
+
|
1394
|
+
#ifndef PRISM_EXCLUDE_SERIALIZATION
|
1395
|
+
rb_define_singleton_method(rb_cPrism, "dump", dump, -1);
|
1396
|
+
rb_define_singleton_method(rb_cPrism, "dump_file", dump_file, -1);
|
1397
|
+
#endif
|
1142
1398
|
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
rb_define_singleton_method(rb_cPrismDebug, "named_captures", named_captures, 1);
|
1147
|
-
rb_define_singleton_method(rb_cPrismDebug, "memsize", memsize, 1);
|
1148
|
-
rb_define_singleton_method(rb_cPrismDebug, "profile_file", profile_file, 1);
|
1149
|
-
rb_define_singleton_method(rb_cPrismDebug, "inspect_node", inspect_node, 1);
|
1150
|
-
rb_define_singleton_method(rb_cPrismDebug, "format_errors", format_errors, 2);
|
1399
|
+
rb_define_singleton_method(rb_cPrismStringQuery, "local?", string_query_local_p, 1);
|
1400
|
+
rb_define_singleton_method(rb_cPrismStringQuery, "constant?", string_query_constant_p, 1);
|
1401
|
+
rb_define_singleton_method(rb_cPrismStringQuery, "method_name?", string_query_method_name_p, 1);
|
1151
1402
|
|
1152
1403
|
// Next, initialize the other APIs.
|
1153
1404
|
Init_prism_api_node();
|