From 3fff1d57dcc2f009d4060a4593b70a3b25718336 Mon Sep 17 00:00:00 2001 From: Emily Samp Date: Mon, 3 Jun 2024 10:20:56 -0500 Subject: [PATCH 1/5] Add `--parser` option and use it to decide whether to parse with Sorbet or prism If `--parser=prism`, diverge in the `pipeline.cc` file and run a separate method that parses the source with prism. --- main/options/options.cc | 31 +++++++++++++++++++++++++++++ main/options/options.h | 6 ++++++ main/pipeline/pipeline.cc | 42 ++++++++++++++++++++++++++++++++------- 3 files changed, 72 insertions(+), 7 deletions(-) diff --git a/main/options/options.cc b/main/options/options.cc index 986bafff194..e6b380ea065 100644 --- a/main/options/options.cc +++ b/main/options/options.cc @@ -163,6 +163,11 @@ struct StopAfterOptions { Phase flag; }; +struct ParserOptions { + string option; + Parser flag; +}; + const vector stop_after_options({ {"init", Phase::INIT}, {"parser", Phase::PARSER}, @@ -175,6 +180,11 @@ const vector stop_after_options({ {"inferencer", Phase::INFERENCER}, }); +const vector parser_options({ + {"sorbet", Parser::SORBET}, + {"prism", Parser::PRISM}, +}); + core::TrackUntyped text2TrackUntyped(string_view key, spdlog::logger &logger) { if (key == "") { return core::TrackUntyped::Everywhere; @@ -548,6 +558,9 @@ buildOptions(const vector()->default_value("sorbet"), + "{sorbet, prism}"); + for (auto &provider : semanticExtensionProviders) { provider->injectOptions(options); } @@ -625,6 +638,22 @@ Phase extractStopAfter(cxxopts::ParseResult &raw, shared_ptr log return Phase::INIT; } +Parser extractParser(cxxopts::ParseResult &raw, shared_ptr logger) { + string opt = raw["parser"].as(); + for (auto &known : parser_options) { + if (known.option == opt) { + return known.flag; + } + } + vector allOptions; + for (auto &known : parser_options) { + allOptions.emplace_back(known.option); + } + + logger->error("Unknown --parser option: {}\nValid values: {}", opt, fmt::join(allOptions, ", ")); + return Parser::SORBET; +} + // Given a path, strips any trailing forward slashes (/) at the end of the path. string_view stripTrailingSlashes(string_view path) { while (path.back() == '/') { @@ -783,6 +812,7 @@ void readOptions(Options &opts, throw EarlyReturnWithCode(1); } opts.stopAfterPhase = extractStopAfter(raw, logger); + opts.parser = extractParser(raw, logger); opts.silenceErrors = raw["quiet"].as(); opts.autocorrect = raw["autocorrect"].as(); @@ -1156,6 +1186,7 @@ void readOptions(Options &opts, fmt::print("Sorbet typechecker {}\n", sorbet_full_version_string); throw EarlyReturnWithCode(0); } + } catch (cxxopts::OptionParseException &e) { logger->info("{}. To see all available options pass `--help`.", e.what()); throw EarlyReturnWithCode(1); diff --git a/main/options/options.h b/main/options/options.h index e40a9e72744..a2d96be5753 100644 --- a/main/options/options.h +++ b/main/options/options.h @@ -106,6 +106,11 @@ enum class Phase { INFERENCER, }; +enum class Parser { + PRISM, + SORBET, +}; + struct AutogenConstCacheConfig { // A file which contains a cache that can be used to potentially skip autogen std::string cacheFile; @@ -127,6 +132,7 @@ constexpr size_t MAX_CACHE_SIZE_BYTES = 1L * 1024 * 1024 * 1024; // 1 GiB struct Options { Printers print; Phase stopAfterPhase = Phase::INFERENCER; + Parser parser = Parser::SORBET; bool noStdlib = false; // Should we monitor STDOUT for HUP and exit if it hangs up. This is a diff --git a/main/pipeline/pipeline.cc b/main/pipeline/pipeline.cc index eecadde8bb6..2f2cf616242 100644 --- a/main/pipeline/pipeline.cc +++ b/main/pipeline/pipeline.cc @@ -46,8 +46,10 @@ #include "rewriter/rewriter.h" extern "C" { - #include "prism.h" +#include "prism.h" } +#include "parser/Builder.h" +#include using namespace std; @@ -122,6 +124,7 @@ unique_ptr runParser(core::GlobalState &gs, core::FileRef file, co auto settings = parser::Parser::Settings{traceLexer, traceParser, indentationAware}; nodes = parser::Parser::run(gs, file, settings); } + if (print.ParseTree.enabled) { print.ParseTree.fmt("{}\n", nodes->toStringWithTabs(gs, 0)); } @@ -137,6 +140,26 @@ unique_ptr runParser(core::GlobalState &gs, core::FileRef file, co return nodes; } +unique_ptr runPrismParser(core::GlobalState &gs, core::FileRef file, const options::Printers &print, + bool traceLexer, bool traceParser) { + auto source = file.data(gs).source(); + + const parser::Builder builder(gs, file); + + pm_parser_t parser; + pm_parser_init(&parser, reinterpret_cast(source.data()), source.size(), NULL); + + pm_node_t *root = pm_parse(&parser); + + // TODO: figure out what traceParser does + std::unique_ptr ast; // builder.build(, traceParser); + + pm_node_destroy(&parser, root); + pm_parser_free(&parser); + + return ast; +} + ast::ExpressionPtr runDesugar(core::GlobalState &gs, core::FileRef file, unique_ptr parseTree, const options::Printers &print) { Timer timeit(gs.tracer(), "runDesugar", {{"file", string(file.data(gs).path())}}); @@ -194,6 +217,8 @@ ast::ExpressionPtr desugarOne(const options::Options &opts, core::GlobalState &g ast::ParsedFile indexOne(const options::Options &opts, core::GlobalState &lgs, core::FileRef file, ast::ExpressionPtr tree) { auto &print = opts.print; + auto &parser = opts.parser; + ast::ParsedFile rewritten{nullptr, file}; Timer timeit(lgs.tracer(), "indexOne", {{"file", string(file.data(lgs).path())}}); @@ -203,7 +228,15 @@ ast::ParsedFile indexOne(const options::Options &opts, core::GlobalState &lgs, c if (file.data(lgs).strictLevel == core::StrictLevel::Ignore) { return emptyParsedFile(file); } - auto parseTree = runParser(lgs, file, print, opts.traceLexer, opts.traceParser); + + unique_ptr parseTree; + + if (parser == options::Parser::SORBET) { + parseTree = runParser(lgs, file, print, opts.traceLexer, opts.traceParser); + } else if (parser == options::Parser::PRISM) { + parseTree = runPrismParser(lgs, file, print, opts.traceLexer, opts.traceParser); + } // Any other option would have been handled in the options parser + if (opts.stopAfterPhase == options::Phase::PARSER) { return emptyParsedFile(file); } @@ -607,11 +640,6 @@ vector index(core::GlobalState &gs, absl::Span f vector ret; vector empty; - // TODO: remove once we are actually parsing with prism - cout << "***" - << pm_version() - << "***"; - if (opts.stopAfterPhase == options::Phase::INIT) { return empty; } From 6259fa9c77c54edaf3ae6cbceee376ac72c1e4c7 Mon Sep 17 00:00:00 2001 From: Emily Samp Date: Tue, 4 Jun 2024 10:33:40 -0500 Subject: [PATCH 2/5] Implement parsing a program with just an integer This involves setting up a `convertPrismToSorbet` method that checks against every possible node type. Program and Statements are basically skipped because Sorbet doesn't use them, and then Integer is converted from a prism node to a Sorbet node. Co-authored-by: Vinicius Stock --- main/pipeline/pipeline.cc | 192 +++++++++++++++++++++++++++++++++++++- 1 file changed, 187 insertions(+), 5 deletions(-) diff --git a/main/pipeline/pipeline.cc b/main/pipeline/pipeline.cc index 2f2cf616242..cfd5c454a72 100644 --- a/main/pipeline/pipeline.cc +++ b/main/pipeline/pipeline.cc @@ -48,7 +48,7 @@ extern "C" { #include "prism.h" } -#include "parser/Builder.h" +#include "core/LocOffsets.h" #include using namespace std; @@ -140,19 +140,201 @@ unique_ptr runParser(core::GlobalState &gs, core::FileRef file, co return nodes; } +core::LocOffsets locOffset(pm_location_t *loc, pm_parser_t *parser) { + uint32_t locStart = static_cast(loc->start - parser->start); + uint32_t locEnd = static_cast(loc->end - parser->start); + + return core::LocOffsets{locStart, locEnd}; +} + +unique_ptr convertPrismToSorbet(pm_node_t *node, pm_parser_t *parser) { + switch (PM_NODE_TYPE(node)) { + case PM_PROGRAM_NODE: { + pm_statements_node *stmts = ((pm_program_node *)node)->statements; + return convertPrismToSorbet((pm_node *)stmts, parser); + + break; + } + case PM_STATEMENTS_NODE: { + pm_node_list *body = &((pm_statements_node *)node)->body; + // TODO: Handle multiple statements + pm_node *first = body->nodes[0]; + + return convertPrismToSorbet(first, parser); + + break; + } + case PM_INTEGER_NODE: { + pm_location_t *loc = &node->location; + pm_integer_node *intNode = (pm_integer_node *)node; + + return make_unique(locOffset(loc, parser), std::to_string(intNode->value.value)); + + break; + } + case PM_ALIAS_GLOBAL_VARIABLE_NODE: + case PM_ALIAS_METHOD_NODE: + case PM_ALTERNATION_PATTERN_NODE: + case PM_AND_NODE: + case PM_ARGUMENTS_NODE: + case PM_ARRAY_NODE: + case PM_ARRAY_PATTERN_NODE: + case PM_ASSOC_NODE: + case PM_ASSOC_SPLAT_NODE: + case PM_BACK_REFERENCE_READ_NODE: + case PM_BEGIN_NODE: + case PM_BLOCK_ARGUMENT_NODE: + case PM_BLOCK_LOCAL_VARIABLE_NODE: + case PM_BLOCK_NODE: + case PM_BLOCK_PARAMETER_NODE: + case PM_BLOCK_PARAMETERS_NODE: + case PM_BREAK_NODE: + case PM_CALL_AND_WRITE_NODE: + case PM_CALL_NODE: + case PM_CALL_OPERATOR_WRITE_NODE: + case PM_CALL_OR_WRITE_NODE: + case PM_CALL_TARGET_NODE: + case PM_CAPTURE_PATTERN_NODE: + case PM_CASE_MATCH_NODE: + case PM_CASE_NODE: + case PM_CLASS_NODE: + case PM_CLASS_VARIABLE_AND_WRITE_NODE: + case PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE: + case PM_CLASS_VARIABLE_OR_WRITE_NODE: + case PM_CLASS_VARIABLE_READ_NODE: + case PM_CLASS_VARIABLE_TARGET_NODE: + case PM_CLASS_VARIABLE_WRITE_NODE: + case PM_CONSTANT_AND_WRITE_NODE: + case PM_CONSTANT_OPERATOR_WRITE_NODE: + case PM_CONSTANT_OR_WRITE_NODE: + case PM_CONSTANT_PATH_AND_WRITE_NODE: + case PM_CONSTANT_PATH_NODE: + case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE: + case PM_CONSTANT_PATH_OR_WRITE_NODE: + case PM_CONSTANT_PATH_TARGET_NODE: + case PM_CONSTANT_PATH_WRITE_NODE: + case PM_CONSTANT_READ_NODE: + case PM_CONSTANT_TARGET_NODE: + case PM_CONSTANT_WRITE_NODE: + case PM_DEF_NODE: + case PM_DEFINED_NODE: + case PM_ELSE_NODE: + case PM_EMBEDDED_STATEMENTS_NODE: + case PM_EMBEDDED_VARIABLE_NODE: + case PM_ENSURE_NODE: + case PM_FALSE_NODE: + case PM_FIND_PATTERN_NODE: + case PM_FLIP_FLOP_NODE: + case PM_FLOAT_NODE: + case PM_FOR_NODE: + case PM_FORWARDING_ARGUMENTS_NODE: + case PM_FORWARDING_PARAMETER_NODE: + case PM_FORWARDING_SUPER_NODE: + case PM_GLOBAL_VARIABLE_AND_WRITE_NODE: + case PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE: + case PM_GLOBAL_VARIABLE_OR_WRITE_NODE: + case PM_GLOBAL_VARIABLE_READ_NODE: + case PM_GLOBAL_VARIABLE_TARGET_NODE: + case PM_GLOBAL_VARIABLE_WRITE_NODE: + case PM_HASH_NODE: + case PM_HASH_PATTERN_NODE: + case PM_IF_NODE: + case PM_IMAGINARY_NODE: + case PM_IMPLICIT_NODE: + case PM_IMPLICIT_REST_NODE: + case PM_IN_NODE: + case PM_INDEX_AND_WRITE_NODE: + case PM_INDEX_OPERATOR_WRITE_NODE: + case PM_INDEX_OR_WRITE_NODE: + case PM_INDEX_TARGET_NODE: + case PM_INSTANCE_VARIABLE_AND_WRITE_NODE: + case PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE: + case PM_INSTANCE_VARIABLE_OR_WRITE_NODE: + case PM_INSTANCE_VARIABLE_READ_NODE: + case PM_INSTANCE_VARIABLE_TARGET_NODE: + case PM_INSTANCE_VARIABLE_WRITE_NODE: + case PM_INTERPOLATED_MATCH_LAST_LINE_NODE: + case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: + case PM_INTERPOLATED_STRING_NODE: + case PM_INTERPOLATED_SYMBOL_NODE: + case PM_INTERPOLATED_X_STRING_NODE: + case PM_IT_PARAMETERS_NODE: + case PM_KEYWORD_HASH_NODE: + case PM_KEYWORD_REST_PARAMETER_NODE: + case PM_LAMBDA_NODE: + case PM_LOCAL_VARIABLE_AND_WRITE_NODE: + case PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE: + case PM_LOCAL_VARIABLE_OR_WRITE_NODE: + case PM_LOCAL_VARIABLE_READ_NODE: + case PM_LOCAL_VARIABLE_TARGET_NODE: + case PM_LOCAL_VARIABLE_WRITE_NODE: + case PM_MATCH_LAST_LINE_NODE: + case PM_MATCH_PREDICATE_NODE: + case PM_MATCH_REQUIRED_NODE: + case PM_MATCH_WRITE_NODE: + case PM_MISSING_NODE: + case PM_MODULE_NODE: + case PM_MULTI_TARGET_NODE: + case PM_MULTI_WRITE_NODE: + case PM_NEXT_NODE: + case PM_NIL_NODE: + case PM_NO_KEYWORDS_PARAMETER_NODE: + case PM_NUMBERED_PARAMETERS_NODE: + case PM_NUMBERED_REFERENCE_READ_NODE: + case PM_OPTIONAL_KEYWORD_PARAMETER_NODE: + case PM_OPTIONAL_PARAMETER_NODE: + case PM_OR_NODE: + case PM_PARAMETERS_NODE: + case PM_PARENTHESES_NODE: + case PM_PINNED_EXPRESSION_NODE: + case PM_PINNED_VARIABLE_NODE: + case PM_POST_EXECUTION_NODE: + case PM_PRE_EXECUTION_NODE: + case PM_RANGE_NODE: + case PM_RATIONAL_NODE: + case PM_REDO_NODE: + case PM_REGULAR_EXPRESSION_NODE: + case PM_REQUIRED_KEYWORD_PARAMETER_NODE: + case PM_REQUIRED_PARAMETER_NODE: + case PM_RESCUE_MODIFIER_NODE: + case PM_RESCUE_NODE: + case PM_REST_PARAMETER_NODE: + case PM_RETRY_NODE: + case PM_RETURN_NODE: + case PM_SELF_NODE: + case PM_SHAREABLE_CONSTANT_NODE: + case PM_SINGLETON_CLASS_NODE: + case PM_SOURCE_ENCODING_NODE: + case PM_SOURCE_FILE_NODE: + case PM_SOURCE_LINE_NODE: + case PM_SPLAT_NODE: + case PM_STRING_NODE: + case PM_SUPER_NODE: + case PM_SYMBOL_NODE: + case PM_TRUE_NODE: + case PM_UNDEF_NODE: + case PM_UNLESS_NODE: + case PM_UNTIL_NODE: + case PM_WHEN_NODE: + case PM_WHILE_NODE: + case PM_X_STRING_NODE: + case PM_YIELD_NODE: + case PM_SCOPE_NODE: + std::unique_ptr ast; + return ast; + } +} + unique_ptr runPrismParser(core::GlobalState &gs, core::FileRef file, const options::Printers &print, bool traceLexer, bool traceParser) { auto source = file.data(gs).source(); - const parser::Builder builder(gs, file); - pm_parser_t parser; pm_parser_init(&parser, reinterpret_cast(source.data()), source.size(), NULL); pm_node_t *root = pm_parse(&parser); - // TODO: figure out what traceParser does - std::unique_ptr ast; // builder.build(, traceParser); + std::unique_ptr ast = convertPrismToSorbet(root, &parser); pm_node_destroy(&parser, root); pm_parser_free(&parser); From b920eee10a64eaa3bb3fa079b81cad234114923f Mon Sep 17 00:00:00 2001 From: Emily Samp Date: Wed, 5 Jun 2024 15:45:42 -0500 Subject: [PATCH 3/5] Implement string parsing --- main/pipeline/pipeline.cc | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/main/pipeline/pipeline.cc b/main/pipeline/pipeline.cc index cfd5c454a72..a1cc54be70b 100644 --- a/main/pipeline/pipeline.cc +++ b/main/pipeline/pipeline.cc @@ -144,14 +144,26 @@ core::LocOffsets locOffset(pm_location_t *loc, pm_parser_t *parser) { uint32_t locStart = static_cast(loc->start - parser->start); uint32_t locEnd = static_cast(loc->end - parser->start); + std::cout << "locStart: " << locStart << std::endl; + std::cout << "locEnd: " << locEnd << std::endl; + return core::LocOffsets{locStart, locEnd}; } -unique_ptr convertPrismToSorbet(pm_node_t *node, pm_parser_t *parser) { +const unique_ptr convertPrismToSorbet(pm_node_t *node, pm_parser_t *parser, core::GlobalState &gs) { switch (PM_NODE_TYPE(node)) { + case PM_INTEGER_NODE: { + pm_integer_node *intNode = (pm_integer_node *)node; + pm_location_t *loc = &intNode->base.location; + + // Will only work for positive, 32-bit integers + return make_unique(locOffset(loc, parser), std::to_string(intNode->value.value)); + + break; + } case PM_PROGRAM_NODE: { pm_statements_node *stmts = ((pm_program_node *)node)->statements; - return convertPrismToSorbet((pm_node *)stmts, parser); + return convertPrismToSorbet((pm_node *)stmts, parser, gs); break; } @@ -160,15 +172,20 @@ unique_ptr convertPrismToSorbet(pm_node_t *node, pm_parser_t *pars // TODO: Handle multiple statements pm_node *first = body->nodes[0]; - return convertPrismToSorbet(first, parser); + return convertPrismToSorbet(first, parser, gs); break; } - case PM_INTEGER_NODE: { - pm_location_t *loc = &node->location; - pm_integer_node *intNode = (pm_integer_node *)node; + case PM_STRING_NODE: { + pm_string_node *strNode = (pm_string_node *)node; + pm_location_t *loc = &strNode->base.location; - return make_unique(locOffset(loc, parser), std::to_string(intNode->value.value)); + auto unescaped = &strNode->unescaped; + auto source = + std::string(reinterpret_cast(pm_string_source(unescaped)), pm_string_length(unescaped)); + + // TODO: handle different string encodings + return make_unique(locOffset(loc, parser), gs.enterNameUTF8(source)); break; } @@ -308,7 +325,6 @@ unique_ptr convertPrismToSorbet(pm_node_t *node, pm_parser_t *pars case PM_SOURCE_FILE_NODE: case PM_SOURCE_LINE_NODE: case PM_SPLAT_NODE: - case PM_STRING_NODE: case PM_SUPER_NODE: case PM_SYMBOL_NODE: case PM_TRUE_NODE: @@ -329,12 +345,13 @@ unique_ptr runPrismParser(core::GlobalState &gs, core::FileRef fil bool traceLexer, bool traceParser) { auto source = file.data(gs).source(); + core::UnfreezeNameTable nameTableAccess(gs); + pm_parser_t parser; pm_parser_init(&parser, reinterpret_cast(source.data()), source.size(), NULL); pm_node_t *root = pm_parse(&parser); - - std::unique_ptr ast = convertPrismToSorbet(root, &parser); + std::unique_ptr ast = convertPrismToSorbet(root, &parser, gs); pm_node_destroy(&parser, root); pm_parser_free(&parser); From 9cdd1dfa641edb7cd05e39a3a51dbf260577a963 Mon Sep 17 00:00:00 2001 From: Emily Samp Date: Wed, 5 Jun 2024 15:50:04 -0500 Subject: [PATCH 4/5] Implement float parsing --- main/pipeline/pipeline.cc | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/main/pipeline/pipeline.cc b/main/pipeline/pipeline.cc index a1cc54be70b..1cd4e4d0702 100644 --- a/main/pipeline/pipeline.cc +++ b/main/pipeline/pipeline.cc @@ -152,32 +152,32 @@ core::LocOffsets locOffset(pm_location_t *loc, pm_parser_t *parser) { const unique_ptr convertPrismToSorbet(pm_node_t *node, pm_parser_t *parser, core::GlobalState &gs) { switch (PM_NODE_TYPE(node)) { + case PM_FLOAT_NODE: { + auto floatNode = reinterpret_cast(node); + pm_location_t *loc = &floatNode->base.location; + + return make_unique(locOffset(loc, parser), std::to_string(floatNode->value)); + } case PM_INTEGER_NODE: { - pm_integer_node *intNode = (pm_integer_node *)node; + auto intNode = reinterpret_cast(node); pm_location_t *loc = &intNode->base.location; // Will only work for positive, 32-bit integers return make_unique(locOffset(loc, parser), std::to_string(intNode->value.value)); - - break; } case PM_PROGRAM_NODE: { - pm_statements_node *stmts = ((pm_program_node *)node)->statements; + pm_statements_node *stmts = (reinterpret_cast(node))->statements; return convertPrismToSorbet((pm_node *)stmts, parser, gs); - - break; } case PM_STATEMENTS_NODE: { - pm_node_list *body = &((pm_statements_node *)node)->body; + pm_node_list *body = &(reinterpret_cast(node))->body; // TODO: Handle multiple statements pm_node *first = body->nodes[0]; return convertPrismToSorbet(first, parser, gs); - - break; } case PM_STRING_NODE: { - pm_string_node *strNode = (pm_string_node *)node; + auto strNode = reinterpret_cast(node); pm_location_t *loc = &strNode->base.location; auto unescaped = &strNode->unescaped; @@ -186,8 +186,6 @@ const unique_ptr convertPrismToSorbet(pm_node_t *node, pm_parser_t // TODO: handle different string encodings return make_unique(locOffset(loc, parser), gs.enterNameUTF8(source)); - - break; } case PM_ALIAS_GLOBAL_VARIABLE_NODE: case PM_ALIAS_METHOD_NODE: @@ -242,7 +240,6 @@ const unique_ptr convertPrismToSorbet(pm_node_t *node, pm_parser_t case PM_FALSE_NODE: case PM_FIND_PATTERN_NODE: case PM_FLIP_FLOP_NODE: - case PM_FLOAT_NODE: case PM_FOR_NODE: case PM_FORWARDING_ARGUMENTS_NODE: case PM_FORWARDING_PARAMETER_NODE: From d549d27455f5ee7628ea656a664695edb88446df Mon Sep 17 00:00:00 2001 From: Emily Samp Date: Wed, 5 Jun 2024 16:03:58 -0500 Subject: [PATCH 5/5] Implement rational parsing --- main/pipeline/pipeline.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/main/pipeline/pipeline.cc b/main/pipeline/pipeline.cc index 1cd4e4d0702..5f54cd364c5 100644 --- a/main/pipeline/pipeline.cc +++ b/main/pipeline/pipeline.cc @@ -169,6 +169,19 @@ const unique_ptr convertPrismToSorbet(pm_node_t *node, pm_parser_t pm_statements_node *stmts = (reinterpret_cast(node))->statements; return convertPrismToSorbet((pm_node *)stmts, parser, gs); } + case PM_RATIONAL_NODE: { + auto *rationalNode = reinterpret_cast(node); + pm_location_t *loc = &rationalNode->base.location; + + const uint8_t *start = rationalNode->numeric->location.start; + const uint8_t *end = rationalNode->numeric->location.end; + + std::string value = std::string(reinterpret_cast(start), end - start); + + return make_unique(locOffset(loc, parser), value); + + break; + } case PM_STATEMENTS_NODE: { pm_node_list *body = &(reinterpret_cast(node))->body; // TODO: Handle multiple statements @@ -305,7 +318,6 @@ const unique_ptr convertPrismToSorbet(pm_node_t *node, pm_parser_t case PM_POST_EXECUTION_NODE: case PM_PRE_EXECUTION_NODE: case PM_RANGE_NODE: - case PM_RATIONAL_NODE: case PM_REDO_NODE: case PM_REGULAR_EXPRESSION_NODE: case PM_REQUIRED_KEYWORD_PARAMETER_NODE: