1#include "prism/extension.h"
16VALUE rb_cPrismLocation;
18VALUE rb_cPrismComment;
19VALUE rb_cPrismInlineComment;
20VALUE rb_cPrismEmbDocComment;
21VALUE rb_cPrismMagicComment;
22VALUE rb_cPrismParseError;
23VALUE rb_cPrismParseWarning;
25VALUE rb_cPrismParseResult;
26VALUE rb_cPrismLexResult;
27VALUE rb_cPrismParseLexResult;
28VALUE rb_cPrismStringQuery;
30VALUE rb_cPrismCurrentVersionError;
32VALUE rb_cPrismDebugEncoding;
34ID rb_id_option_attach_comments;
35ID rb_id_option_command_line;
36ID rb_id_option_encoding;
37ID rb_id_option_filepath;
38ID rb_id_option_freeze;
39ID rb_id_option_frozen_string_literal;
41ID rb_id_option_main_script;
42ID rb_id_option_partial_script;
43ID rb_id_option_raise_error;
44ID rb_id_option_scopes;
45ID rb_id_option_version;
49ID rb_id_forwarding_positionals;
50ID rb_id_forwarding_keywords;
51ID rb_id_forwarding_block;
52ID rb_id_forwarding_all;
54ID rb_id_raise_error_plain;
55ID rb_id_raise_error_style;
56ID rb_id_raise_error_color;
71result_ok(
VALUE value) {
72 return (
result_t) { .type = RESULT_OK, .value = value };
76result_err(
VALUE value) {
77 return (
result_t) { .type = RESULT_ERR, .value = value };
82 if (result.type == RESULT_OK) {
98check_string(
VALUE value) {
105 return RSTRING_PTR(value);
124 if (!pm_options_scopes_init(options, scopes_count)) {
129 for (
size_t scope_index = 0; scope_index < scopes_count; scope_index++) {
151 for (
size_t name_index = 0; name_index < names_count; name_index++) {
161 if (
id == rb_id_forwarding_positionals) {
163 }
else if (
id == rb_id_forwarding_keywords) {
165 }
else if (
id == rb_id_forwarding_block) {
167 }
else if (
id == rb_id_forwarding_all) {
170 rb_raise(rb_eArgError,
"invalid forwarding value: %" PRIsVALUE, name);
180 pm_options_scope_init(options_scope, locals_count);
183 for (
size_t local_index = 0; local_index < locals_count; local_index++) {
193 pm_string_t *scope_local = pm_options_scope_local_mut(options_scope, local_index);
194 const char *name = rb_id2name(
SYM2ID(local));
195 pm_string_init(scope_local, (
const uint8_t *) name, strlen(name));
199 pm_options_scope_forwarding_set(options_scope, forwarding);
209 if (!pm_options_version_set(options,
ruby_version, 3)) {
212 pm_options_version_set_lowest(options);
215 pm_options_version_set_highest(options);
228 if (key_id == rb_id_option_filepath) {
229 if (!
NIL_P(value)) pm_options_filepath_set(options, check_string(value));
230 }
else if (key_id == rb_id_option_encoding) {
233 pm_options_encoding_locked_set(options,
true);
235 pm_options_encoding_set(options, rb_enc_name(rb_to_encoding(value)));
238 }
else if (key_id == rb_id_option_line) {
239 if (!
NIL_P(value)) pm_options_line_set(options,
NUM2INT(value));
240 }
else if (key_id == rb_id_option_frozen_string_literal) {
241 if (!
NIL_P(value)) pm_options_frozen_string_literal_set(options,
RTEST(value));
242 }
else if (key_id == rb_id_option_version) {
244 const char *version = check_string(value);
246 if (RSTRING_LEN(value) == 7 && strncmp(version,
"current", 7) == 0) {
247 if (!pm_options_version_set(options,
ruby_version, 3)) {
250 }
else if (RSTRING_LEN(value) == 7 && strncmp(version,
"nearest", 7) == 0) {
251 options_version_set_nearest(options);
252 }
else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
253 rb_raise(rb_eArgError,
"invalid version: %" PRIsVALUE, value);
256 }
else if (key_id == rb_id_option_scopes) {
257 if (!
NIL_P(value)) build_options_scopes(options, value);
258 }
else if (key_id == rb_id_option_command_line) {
260 const char *
string = check_string(value);
261 uint8_t command_line = 0;
263 for (
size_t index = 0; index < strlen(
string); index++) {
264 switch (
string[index]) {
271 default: rb_raise(rb_eArgError,
"invalid command line flag: '%c'",
string[index]);
break;
275 pm_options_command_line_set(options, command_line);
277 }
else if (key_id == rb_id_option_main_script) {
278 if (!
NIL_P(value)) pm_options_main_script_set(options,
RTEST(value));
279 }
else if (key_id == rb_id_option_partial_script) {
280 if (!
NIL_P(value)) pm_options_partial_script_set(options,
RTEST(value));
281 }
else if (key_id == rb_id_option_freeze) {
282 if (!
NIL_P(value)) pm_options_freeze_set(options,
RTEST(value));
283 }
else if (key_id == rb_id_option_attach_comments) {
284 if (!
NIL_P(value)) pm_options_attach_comments_set(options,
RTEST(value));
285 }
else if (key_id == rb_id_option_raise_error) {
287 if (value ==
Qtrue) {
297 const char *no_color = getenv(
"NO_COLOR");
298 if (no_color == NULL || no_color[0] ==
'\0') {
312 if (value_id == rb_id_raise_error_plain) {
314 }
else if (value_id == rb_id_raise_error_style) {
316 }
else if (value_id == rb_id_raise_error_color) {
319 rb_raise(rb_eArgError,
"invalid raise_error value: %" PRIsVALUE, value);
324 rb_raise(rb_eArgError,
"unknown keyword: %" PRIsVALUE, key);
345build_options(
VALUE argument) {
356 pm_options_line_set(options, 1);
357 options_version_set_nearest(options);
359 if (!
NIL_P(keywords)) {
364 rb_protect(build_options, (
VALUE) argument, &state);
367 pm_options_free(options);
372 if (!
NIL_P(filepath)) {
374 pm_options_free(options);
378 pm_options_filepath_set(options, RSTRING_PTR(filepath));
392 pm_options_free(options);
396 extract_options(options,
Qnil, keywords);
410 filepath = rb_protect(rb_get_path, filepath, &state);
412 pm_options_free(options);
416 *encoded_filepath = rb_str_encode_ospath(filepath);
417 extract_options(options, *encoded_filepath, keywords);
419 const char *source = (
const char *) pm_string_source(pm_options_filepath(options));
421 pm_source_t *pm_src = pm_source_file_new(source, &result);
427 pm_options_free(options);
430 int e = rb_w32_map_errno(GetLastError());
439 pm_options_free(options);
443 pm_options_free(options);
444 rb_raise(
rb_eRuntimeError,
"Unknown error (%d) initializing file: %s", result, source);
458 if (pm_parser_errors_size(parser) == 0)
return result_ok(
Qnil);
460 uint8_t raise_error = pm_options_raise_error(options);
461 if (raise_error == 0)
return result_ok(
Qnil);
464 if (buffer == NULL) {
474 VALUE message = rb_enc_str_new(pm_buffer_value(buffer), (
long) pm_buffer_length(buffer), message_encoding);
475 pm_buffer_free(buffer);
478 switch (error_level) {
482 rb_encoding *path_encoding_normal = path_encoding == NULL ? rb_utf8_encoding() : path_encoding;
483 VALUE path = rb_enc_str_new((
const char *) pm_string_source(pm_options_filepath(options)), pm_string_length(pm_options_filepath(options)), path_encoding_normal);
498 return result_err(error);
501#ifndef PRISM_EXCLUDE_SERIALIZATION
511dump_input(
const uint8_t *input,
size_t input_length,
const pm_options_t *options,
rb_encoding *path_encoding) {
516 result_t result = check_raise_error_option(parser, options, path_encoding);
517 if (result.type == RESULT_OK) {
520 pm_serialize(parser, node, buffer);
521 result = result_ok(
rb_str_new(pm_buffer_value(buffer), pm_buffer_length(buffer)));
522 pm_buffer_free(buffer);
531 pm_arena_free(arena);
547 VALUE string = string_options(argc, argv, options);
549 const uint8_t *source = (
const uint8_t *) RSTRING_PTR(
string);
550 size_t length = RSTRING_LEN(
string);
552#ifdef PRISM_BUILD_DEBUG
554 memcpy(dup, source, length);
555 source = (
const uint8_t *) dup;
558 result_t result = dump_input(source, length, options, NULL);
560#ifdef PRISM_BUILD_DEBUG
562 xfree_sized(dup, length);
568 pm_options_free(options);
569 return result_get(result);
584 VALUE encoded_filepath;
585 pm_source_t *src = file_options(argc, argv, options, &encoded_filepath);
587 result_t result = dump_input(pm_source_source(src), pm_source_length(src), options, rb_enc_get(encoded_filepath));
589 pm_options_free(options);
591 return result_get(result);
605rb_class_new_instance_freeze(
int argc,
const VALUE *argv,
VALUE klass,
bool freeze) {
615parser_location(
VALUE source,
bool freeze, uint32_t start, uint32_t length) {
617 return rb_class_new_instance_freeze(3, argv, rb_cPrismLocation, freeze);
623#define PARSER_LOCATION(source, freeze, location) \
624 parser_location(source, freeze, location.start, location.length)
633 return rb_class_new_instance_freeze(1, argv,
type, freeze);
646 rb_ary_store(comments, index++, parser_comment(source, freeze, comment));
660 VALUE key_loc = parser_location(source, freeze, key.start, key.length);
661 VALUE value_loc = parser_location(source, freeze, value.
start, value.
length);
663 VALUE argv[] = { key_loc, value_loc };
664 return rb_class_new_instance_freeze(2, argv, rb_cPrismMagicComment, freeze);
671parser_magic_comments(
const pm_parser_t *parser,
VALUE source,
bool freeze) {
690 if (data_loc->
length == 0) {
693 return parser_location(source, freeze, data_loc->
start, data_loc->
length);
704 VALUE location = PARSER_LOCATION(source, freeze, pm_diagnostic_location(diagnostic));
709 switch (error_level) {
711 level =
ID2SYM(rb_intern(
"syntax"));
714 level =
ID2SYM(rb_intern(
"argument"));
717 level =
ID2SYM(rb_intern(
"load"));
723 VALUE argv[] = {
type, message, location, level };
724 return rb_class_new_instance_freeze(4, argv, rb_cPrismParseError, freeze);
734 for (
const pm_diagnostic_t *error = pm_parser_errors_first(parser); error != NULL; error = pm_diagnostic_next(error)) {
735 rb_ary_push(errors, parser_error(error, encoding, source, freeze));
749 VALUE location = PARSER_LOCATION(source, freeze, pm_diagnostic_location(diagnostic));
754 switch (warning_level) {
756 level =
ID2SYM(rb_intern(
"default"));
759 level =
ID2SYM(rb_intern(
"verbose"));
765 VALUE argv[] = {
type, message, location, level };
766 return rb_class_new_instance_freeze(4, argv, rb_cPrismParseWarning, freeze);
776 for (
const pm_diagnostic_t *warning = pm_parser_warnings_first(parser); warning != NULL; warning = pm_diagnostic_next(warning)) {
777 rb_ary_push(warnings, parser_warning(warning, encoding, source, freeze));
791 uint32_t ranges_size = pm_parser_comment_ranges_size(parser);
792 *attachments =
rb_ary_new_capa(ranges_size == 0 ? 0 : (long) pm_parser_comments_size(parser));
793 *ranges =
rb_ary_new_capa(ranges_size == 0 ? 0 : (long) ranges_size + 1);
805 uint32_t ranges_size = pm_parser_comment_ranges_size(parser);
807 if (ranges_size > 0) {
810 for (
long index = 0; index < size; index++) {
811 rb_ary_store(attachments, index,
RARRAY_AREF(comments, pm_parser_comment_attachment(parser, (uint32_t) index)));
814 for (uint32_t node_id = 0; node_id < ranges_size; node_id++) {
817 if (range.length > 0) {
835 VALUE result_argv[] = {
837 parser_magic_comments(parser, source, freeze),
838 parser_data_loc(parser, source, freeze),
839 parser_errors(parser, encoding, source, freeze),
840 parser_warnings(parser, encoding, source, freeze),
845 return rb_class_new_instance_freeze(7, result_argv,
class, freeze);
873 VALUE value = pm_token_new(parser, token, parse_lex_data->encoding, parse_lex_data->source, parse_lex_data->freeze);
883parse_lex_encoding_changed_callback(
pm_parser_t *parser) {
885 parse_lex_data->encoding = rb_enc_find(pm_parser_encoding_name(parser));
891 VALUE tokens = parse_lex_data->tokens;
894 for (
long index = 0; index <
RARRAY_LEN(tokens); index++) {
899 rb_enc_associate(next_value, parse_lex_data->encoding);
902 VALUE next_token_argv[] = {
903 parse_lex_data->source,
912 if (parse_lex_data->freeze) {
927parse_lex_input(
const uint8_t *input,
size_t input_length,
const pm_options_t *options,
rb_encoding *path_encoding,
bool return_nodes) {
930 pm_parser_encoding_changed_callback_set(parser, parse_lex_encoding_changed_callback);
937 VALUE source =
rb_funcall(rb_cPrismSource, rb_id_source_for, 6, source_string,
LONG2NUM(pm_parser_start_line(parser)), offsets, comments, attachments, ranges);
942 .encoding = rb_enc_find(pm_parser_encoding_name(parser)),
943 .freeze = pm_options_freeze(options),
947 pm_parser_lex_callback_set(parser, parse_lex_token, data);
951 result_t result = check_raise_error_option(parser, options, path_encoding);
952 if (result.type == RESULT_OK) {
956 rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser));
957 rb_enc_associate(source_string, encoding);
960 for (
size_t index = 0; index < line_offsets->
size; index++) {
964 rb_funcall(source, rb_intern(
"replace_checksum"), 1,
ULL2NUM(pm_parser_checksum(parser)));
966 if (pm_options_freeze(options)) {
975 uint32_t ranges_size = pm_parser_comment_ranges_size(parser);
976 rb_ary_resize(comments, (
long) pm_parser_comments_size(parser));
978 if (ranges_size > 0) {
979 rb_ary_resize(attachments, (
long) pm_parser_comments_size(parser));
983 parser_comments(parser, comments, source, pm_options_freeze(options));
984 parser_attachments(parser, comments, attachments, ranges, pm_options_freeze(options));
988 rb_ary_push(value, pm_ast_new(parser, node, parse_lex_data.encoding, source, pm_options_freeze(options)));
991 result = result_ok(parse_result_create(rb_cPrismParseLexResult, parser, value, parse_lex_data.encoding, source, pm_options_freeze(options)));
993 result = result_ok(parse_result_create(rb_cPrismLexResult, parser, parse_lex_data.tokens, parse_lex_data.encoding, source, pm_options_freeze(options)));
998 pm_arena_free(arena);
1014 VALUE string = string_options(argc, argv, options);
1016 result_t result = parse_lex_input((
const uint8_t *) RSTRING_PTR(
string), RSTRING_LEN(
string), options, NULL,
false);
1017 pm_options_free(options);
1019 return result_get(result);
1034 VALUE encoded_filepath;
1035 pm_source_t *src = file_options(argc, argv, options, &encoded_filepath);
1037 result_t result = parse_lex_input(pm_source_source(src), pm_source_length(src), options, rb_enc_get(encoded_filepath),
false);
1038 pm_source_free(src);
1039 pm_options_free(options);
1041 return result_get(result);
1052parse_input(
const uint8_t *input,
size_t input_length,
const pm_options_t *options,
rb_encoding *path_encoding) {
1058 result_t result = check_raise_error_option(parser, options, path_encoding);
1059 if (result.type == RESULT_OK) {
1060 rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser));
1062 bool freeze = pm_options_freeze(options);
1064 VALUE attachments, ranges;
1065 parser_attachments_new(parser, &attachments, &ranges);
1067 VALUE source = pm_source_new(parser, encoding, comments, attachments, ranges, freeze);
1068 parser_comments(parser, comments, source, freeze);
1069 parser_attachments(parser, comments, attachments, ranges, freeze);
1071 VALUE value = pm_ast_new(parser, node, encoding, source, freeze);
1072 result = result_ok(parse_result_create(rb_cPrismParseResult, parser, value, encoding, source, freeze));
1076 pm_arena_free(arena);
1148 VALUE string = string_options(argc, argv, options);
1150 const uint8_t *source = (
const uint8_t *) RSTRING_PTR(
string);
1151 size_t length = RSTRING_LEN(
string);
1153#ifdef PRISM_BUILD_DEBUG
1155 memcpy(dup, source, length);
1156 source = (
const uint8_t *) dup;
1159 result_t result = parse_input(source, length, options, NULL);
1161#ifdef PRISM_BUILD_DEBUG
1163 xfree_sized(dup, length);
1169 pm_options_free(options);
1170 return result_get(result);
1182parse_file(
int argc,
VALUE *argv,
VALUE self) {
1185 VALUE encoded_filepath;
1186 pm_source_t *src = file_options(argc, argv, options, &encoded_filepath);
1188 result_t result = parse_input(pm_source_source(src), pm_source_length(src), options, rb_enc_get(encoded_filepath));
1189 pm_source_free(src);
1190 pm_options_free(options);
1192 return result_get(result);
1199profile_input(
const uint8_t *input,
size_t input_length,
const pm_options_t *options,
rb_encoding *path_encoding) {
1205 result_t result = check_raise_error_option(parser, options, path_encoding);
1207 pm_arena_free(arena);
1224 VALUE string = string_options(argc, argv, options);
1226 result_t result = profile_input((
const uint8_t *) RSTRING_PTR(
string), RSTRING_LEN(
string), options, NULL);
1227 pm_options_free(options);
1243profile_file(
int argc,
VALUE *argv,
VALUE self) {
1246 VALUE encoded_filepath;
1247 pm_source_t *src = file_options(argc, argv, options, &encoded_filepath);
1249 result_t result = profile_input(pm_source_source(src), pm_source_length(src), options, rb_enc_get(encoded_filepath));
1250 pm_source_free(src);
1251 pm_options_free(options);
1258parse_stream_eof(
void *stream) {
1277#define MAX_ENC_LEN 6
1285parse_stream_fgets(
char *
string,
int size,
void *stream) {
1304 const char *cstr = RSTRING_PTR(line);
1305 size_t length = (size_t) RSTRING_LEN(line);
1312 if (length > (
size_t) (size - 1)) {
1313 length = (size_t) (size - 1);
1316 memcpy(
string, cstr, length);
1317 string[length] =
'\0';
1333parse_stream(
int argc,
VALUE *argv,
VALUE self) {
1339 extract_options(options,
Qnil, keywords);
1341 pm_source_t *src = pm_source_stream_new((
void *) stream, parse_stream_fgets, parse_stream_eof);
1345 pm_node_t *node = pm_parse_stream(&parser, arena, src, options);
1347 result_t result = check_raise_error_option(parser, options, NULL);
1348 if (result.type == RESULT_OK) {
1349 rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser));
1352 VALUE attachments, ranges;
1353 parser_attachments_new(parser, &attachments, &ranges);
1355 VALUE source = pm_source_new(parser, encoding, comments, attachments, ranges, pm_options_freeze(options));
1356 parser_comments(parser, comments, source, pm_options_freeze(options));
1357 parser_attachments(parser, comments, attachments, ranges, pm_options_freeze(options));
1359 VALUE value = pm_ast_new(parser, node, encoding, source, pm_options_freeze(options));
1361 result = result_ok(parse_result_create(rb_cPrismParseResult, parser, value, encoding, source, pm_options_freeze(options)));
1364 pm_source_free(src);
1366 pm_arena_free(arena);
1367 pm_options_free(options);
1369 return result_get(result);
1376parse_input_comments(
const uint8_t *input,
size_t input_length,
const pm_options_t *options,
rb_encoding *path_encoding) {
1382 result_t result = check_raise_error_option(parser, options, path_encoding);
1383 if (result.type == RESULT_OK) {
1384 rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser));
1387 VALUE attachments, ranges;
1388 parser_attachments_new(parser, &attachments, &ranges);
1390 VALUE source = pm_source_new(parser, encoding, comments, attachments, ranges, pm_options_freeze(options));
1391 parser_comments(parser, comments, source, pm_options_freeze(options));
1392 parser_attachments(parser, comments, attachments, ranges, pm_options_freeze(options));
1394 result = result_ok(comments);
1398 pm_arena_free(arena);
1412parse_comments(
int argc,
VALUE *argv,
VALUE self) {
1414 VALUE string = string_options(argc, argv, options);
1416 result_t result = parse_input_comments((
const uint8_t *) RSTRING_PTR(
string), RSTRING_LEN(
string), options, NULL);
1417 pm_options_free(options);
1419 return result_get(result);
1431parse_file_comments(
int argc,
VALUE *argv,
VALUE self) {
1434 VALUE encoded_filepath;
1435 pm_source_t *src = file_options(argc, argv, options, &encoded_filepath);
1437 result_t result = parse_input_comments(pm_source_source(src), pm_source_length(src), options, rb_enc_get(encoded_filepath));
1438 pm_source_free(src);
1439 pm_options_free(options);
1441 return result_get(result);
1460parse_lex(
int argc,
VALUE *argv,
VALUE self) {
1462 VALUE string = string_options(argc, argv, options);
1464 result_t result = parse_lex_input((
const uint8_t *) RSTRING_PTR(
string), RSTRING_LEN(
string), options, NULL,
true);
1465 pm_options_free(options);
1467 return result_get(result);
1486parse_lex_file(
int argc,
VALUE *argv,
VALUE self) {
1489 VALUE encoded_filepath;
1490 pm_source_t *src = file_options(argc, argv, options, &encoded_filepath);
1492 result_t result = parse_lex_input(pm_source_source(src), pm_source_length(src), options, rb_enc_get(encoded_filepath),
true);
1493 pm_source_free(src);
1494 pm_options_free(options);
1496 return result_get(result);
1503parse_input_success_p(
const uint8_t *input,
size_t input_length,
const pm_options_t *options,
rb_encoding *path_encoding) {
1508 result_t result = check_raise_error_option(parser, options, path_encoding);
1509 if (result.type == RESULT_OK) {
1510 result = result_ok(pm_parser_errors_size(parser) == 0 ?
Qtrue :
Qfalse);
1514 pm_arena_free(arena);
1528parse_success_p(
int argc,
VALUE *argv,
VALUE self) {
1530 VALUE string = string_options(argc, argv, options);
1532 result_t result = parse_input_success_p((
const uint8_t *) RSTRING_PTR(
string), RSTRING_LEN(
string), options, NULL);
1533 pm_options_free(options);
1535 return result_get(result);
1547parse_failure_p(
int argc,
VALUE *argv,
VALUE self) {
1560parse_file_success_p(
int argc,
VALUE *argv,
VALUE self) {
1563 VALUE encoded_filepath;
1564 pm_source_t *src = file_options(argc, argv, options, &encoded_filepath);
1566 result_t result = parse_input_success_p(pm_source_source(src), pm_source_length(src), options, rb_enc_get(encoded_filepath));
1567 pm_source_free(src);
1568 pm_options_free(options);
1570 return result_get(result);
1582parse_file_failure_p(
int argc,
VALUE *argv,
VALUE self) {
1598 rb_raise(rb_eArgError,
"Invalid or non ascii-compatible encoding");
1618string_query_local_p(
VALUE self,
VALUE string) {
1619 const uint8_t *source = (
const uint8_t *) check_string(
string);
1620 return string_query(pm_string_query_local(source, RSTRING_LEN(
string), rb_enc_get(
string)->name));
1633string_query_constant_p(
VALUE self,
VALUE string) {
1634 const uint8_t *source = (
const uint8_t *) check_string(
string);
1635 return string_query(pm_string_query_constant(source, RSTRING_LEN(
string), rb_enc_get(
string)->name));
1646string_query_method_name_p(
VALUE self,
VALUE string) {
1647 const uint8_t *source = (
const uint8_t *) check_string(
string);
1648 return string_query(pm_string_query_method_name(source, RSTRING_LEN(
string), rb_enc_get(
string)->name));
1660string_query_keyword_p(
VALUE self,
VALUE string) {
1661 const uint8_t *source = (
const uint8_t *) check_string(
string);
1662 return string_query(pm_string_query_keyword(source, RSTRING_LEN(
string), rb_enc_get(
string)->name));
1672RUBY_FUNC_EXPORTED
void
1676 if (strcmp(pm_version(), EXPECTED_PRISM_VERSION) != 0) {
1679 "The prism library version (%s) does not match the expected version (%s)",
1681 EXPECTED_PRISM_VERSION
1685#ifdef HAVE_RB_EXT_RACTOR_SAFE
1690 VALUE mRuby = rb_define_module(
"Ruby"); rb_cPrism = rb_define_module_under(mRuby,
"Prism");
1691 rb_cPrismNode = rb_define_class_under(rb_cPrism,
"Node",
rb_cObject);
1692 rb_cPrismSource = rb_define_class_under(rb_cPrism,
"Source",
rb_cObject);
1693 rb_cPrismToken = rb_define_class_under(rb_cPrism,
"Token",
rb_cObject);
1694 rb_cPrismLocation = rb_define_class_under(rb_cPrism,
"Location",
rb_cObject);
1695 rb_cPrismComment = rb_define_class_under(rb_cPrism,
"Comment",
rb_cObject);
1696 rb_cPrismInlineComment = rb_define_class_under(rb_cPrism,
"InlineComment", rb_cPrismComment);
1697 rb_cPrismEmbDocComment = rb_define_class_under(rb_cPrism,
"EmbDocComment", rb_cPrismComment);
1698 rb_cPrismMagicComment = rb_define_class_under(rb_cPrism,
"MagicComment",
rb_cObject);
1699 rb_cPrismParseError = rb_define_class_under(rb_cPrism,
"ParseError",
rb_cObject);
1700 rb_cPrismParseWarning = rb_define_class_under(rb_cPrism,
"ParseWarning",
rb_cObject);
1701 rb_cPrismResult = rb_define_class_under(rb_cPrism,
"Result",
rb_cObject);
1702 rb_cPrismParseResult = rb_define_class_under(rb_cPrism,
"ParseResult", rb_cPrismResult);
1703 rb_cPrismLexResult = rb_define_class_under(rb_cPrism,
"LexResult", rb_cPrismResult);
1704 rb_cPrismParseLexResult = rb_define_class_under(rb_cPrism,
"ParseLexResult", rb_cPrismResult);
1705 rb_cPrismStringQuery = rb_define_class_under(rb_cPrism,
"StringQuery",
rb_cObject);
1706 rb_cPrismScope = rb_define_class_under(rb_cPrism,
"Scope",
rb_cObject);
1708 rb_cPrismCurrentVersionError =
rb_const_get(rb_cPrism, rb_intern(
"CurrentVersionError"));
1717 rb_id_option_frozen_string_literal =
rb_intern_const(
"frozen_string_literal");
1725 rb_id_source_for = rb_intern(
"for");
1727 rb_id_forwarding_positionals = rb_intern(
"*");
1728 rb_id_forwarding_keywords = rb_intern(
"**");
1729 rb_id_forwarding_block = rb_intern(
"&");
1730 rb_id_forwarding_all = rb_intern(
"...");
1757#ifndef PRISM_EXCLUDE_SERIALIZATION
1767 Init_prism_api_node();
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
pm_warning_level_t
The levels of warnings generated during parsing.
@ PM_WARNING_LEVEL_DEFAULT
For warnings which should be emitted if $VERBOSE != nil.
@ PM_WARNING_LEVEL_VERBOSE
For warnings which should be emitted if $VERBOSE == true.
pm_error_level_t
The levels of errors generated during parsing.
@ PM_ERROR_LEVEL_ARGUMENT
For errors that should raise an argument error.
@ PM_ERROR_LEVEL_LOAD
For errors that should raise a load error.
@ PM_ERROR_LEVEL_SYNTAX
For errors that should raise a syntax error.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
#define T_STRING
Old name of RUBY_T_STRING.
#define xfree
Old name of ruby_xfree.
#define INT2FIX
Old name of RB_INT2FIX.
#define ID2SYM
Old name of RB_ID2SYM.
#define ULONG2NUM
Old name of RB_ULONG2NUM.
#define SYM2ID
Old name of RB_SYM2ID.
#define xmalloc
Old name of ruby_xmalloc.
#define LONG2FIX
Old name of RB_INT2FIX.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define ULL2NUM
Old name of RB_ULL2NUM.
#define Qtrue
Old name of RUBY_Qtrue.
#define NUM2INT
Old name of RB_NUM2INT.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
#define NIL_P
Old name of RB_NIL_P.
#define T_SYMBOL
Old name of RUBY_T_SYMBOL.
#define SYMBOL_P
Old name of RB_SYMBOL_P.
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
void rb_syserr_fail(int e, const char *mesg)
Raises appropriate exception that represents a C errno.
VALUE rb_eNoMemError
NoMemoryError exception.
VALUE rb_eLoadError
LoadError exception.
VALUE rb_eTypeError
TypeError exception.
VALUE rb_eRuntimeError
RuntimeError exception.
VALUE rb_exc_new_str(VALUE etype, VALUE str)
Identical to rb_exc_new_cstr(), except it takes a Ruby's string instead of C's.
VALUE rb_eSyntaxError
SyntaxError exception.
VALUE rb_cObject
Object class.
VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
Allocates, then initialises an instance of the given class.
VALUE rb_stderr
STDERR constant.
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
VALUE rb_obj_freeze(VALUE obj)
Same as RB_OBJ_FREEZE(), but returns the given object.
VALUE rb_enc_str_new_cstr(const char *ptr, rb_encoding *enc)
Identical to rb_enc_str_new(), except it assumes the passed pointer is a pointer to a C string.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
VALUE rb_ary_entry(VALUE ary, rb_len_t off)
Queries an element of an array.
VALUE rb_ary_new_capa(rb_len_t capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
void rb_ary_store(VALUE ary, rb_len_t key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
VALUE rb_ary_resize(VALUE ary, rb_len_t len)
Expands or shrinks the passed array to the passed length.
VALUE rb_ary_replace(VALUE copy, VALUE orig)
Replaces the contents of the former object with the contents of the latter.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
void rb_ext_ractor_safe(bool flag)
Asserts that the extension library that calls this function is aware of Ractor.
#define rb_str_new(str, len)
Allocates an instance of rb_cString.
#define rb_exc_new_cstr(exc, str)
Identical to rb_exc_new(), except it assumes the passed pointer is a pointer to a C string.
VALUE rb_str_dup(VALUE str)
Duplicates a string.
VALUE rb_str_freeze(VALUE str)
This is the implementation of String#freeze.
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
#define rb_str_new_cstr(str)
Identical to rb_str_new, except it assumes the passed pointer is a pointer to a C string.
VALUE rb_const_get(VALUE space, ID name)
Identical to rb_const_defined(), except it returns the actual defined value.
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
VALUE rb_ivar_get(VALUE obj, ID name)
Identical to rb_iv_get(), except it accepts the name as an ID instead of a C string.
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
const char ruby_version[]
Stringised version.
VALUE type(ANYARGS)
ANYARGS-ed function type.
void rb_hash_foreach(VALUE q, int_type *w, VALUE e)
Iteration over the given hash.
static const uint8_t PM_OPTIONS_COMMAND_LINE_E
A bit representing whether or not the command line -e option was set.
static const uint8_t PM_OPTIONS_COMMAND_LINE_L
A bit representing whether or not the command line -l option was set.
static const uint8_t PM_OPTIONS_COMMAND_LINE_A
A bit representing whether or not the command line -a option was set.
static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_NONE
The default value for parameters.
static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_ALL
When the scope is forwarding with the ... parameter.
static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_POSITIONALS
When the scope is forwarding with the * parameter.
static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_KEYWORDS
When the scope is forwarding with the ** parameter.
static const uint8_t PM_OPTIONS_COMMAND_LINE_N
A bit representing whether or not the command line -n option was set.
static const uint8_t PM_OPTIONS_COMMAND_LINE_X
A bit representing whether or not the command line -x option was set.
static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_BLOCK
When the scope is forwarding with the & parameter.
static const uint8_t PM_OPTIONS_COMMAND_LINE_P
A bit representing whether or not the command line -p option was set.
PRISM_NODISCARD PRISM_EXPORTED_FUNCTION pm_parser_t * pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_options_t *options) PRISM_NONNULL(1)
Allocate and initialize a parser with the given start and end pointers.
PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser) PRISM_NONNULL(1)
Free both the memory held by the given parser and the parser itself.
PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse(pm_parser_t *parser) PRISM_NONNULL(1)
Initiate the parser with the given parser.
comment_range comments(const pm_parser_t *parser PRISM_LIFETIMEBOUND) noexcept
The comments found while parsing, in source order.
magic_comment_range magic_comments(const pm_parser_t *parser PRISM_LIFETIMEBOUND) noexcept
The magic comments found while parsing.
diagnostic_range errors(const pm_parser_t *parser PRISM_LIFETIMEBOUND) noexcept
The errors found while parsing.
diagnostic_range warnings(const pm_parser_t *parser PRISM_LIFETIMEBOUND) noexcept
The warnings found while parsing.
#define RARRAY_LEN
Just another name of rb_array_len.
#define RARRAY_AREF(a, i)
References an object in an array.
#define errno
Ractor-aware version of errno.
pm_source_init_result_t
Represents the result of initializing a source from a file.
@ PM_SOURCE_INIT_ERROR_GENERIC
Indicates a generic error from a source init function, where the type of error should be read from er...
@ PM_SOURCE_INIT_SUCCESS
Indicates that the source was successfully initialized.
@ PM_SOURCE_INIT_ERROR_DIRECTORY
Indicates that the file that was attempted to be opened was a directory.
#define RTEST
This is an old name of RB_TEST.
pm_string_query_t
Represents the results of a slice query.
@ PM_STRING_QUERY_TRUE
Returned if the result of the slice query is true.
@ PM_STRING_QUERY_ERROR
Returned if the encoding given to a slice query was invalid.
@ PM_STRING_QUERY_FALSE
Returned if the result of the slice query is false.
We need a struct here to pass through rb_protect and it has to be a single value.
This struct gets stored in the parser and passed in to the lex callback any time a new token is found...
A list of offsets of the start of lines in a string.
uint32_t * offsets
The list of offsets.
size_t size
The number of offsets in the list.
This struct represents a slice in the source code, defined by an offset and a length.
uint32_t start
The offset of the location from the start of the source.
uint32_t length
The length of the location.
This is the base structure that represents a node in the syntax tree.
A view of a sequence of bytes.
This struct represents a token in the Ruby source.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.