# Has anyone started working on a Ruby =\> Crystal codemod / transpiler / converter?

**URL:** <https://forum.crystal-lang.org/t/has-anyone-started-working-on-a-ruby-crystal-codemod-transpiler-converter/1440>\
**Category:** Community\
**Created:** [December 3, 2019, 7:10pm UTC](https://forum.crystal-lang.org/t/has-anyone-started-working-on-a-ruby-crystal-codemod-transpiler-converter/1440 "2019-12-03T19:10:16Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![ndbroadbent](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ndbroadbent/32/637_2.png) [@ndbroadbent](https://forum.crystal-lang.org/u/ndbroadbent)\
**Post date:** [December 3, 2019, 7:10pm UTC](https://forum.crystal-lang.org/t/has-anyone-started-working-on-a-ruby-crystal-codemod-transpiler-converter/1440/1 "2019-12-03T19:10:16Z")

</div>

I’ve read the [Crystal for Rubyist](https://github.com/crystal-lang/crystal/wiki/Crystal-for-Rubyists) wiki page, and this [Reddit comment](https://www.reddit.com/r/crystal_programming/comments/bfjwye/how_easy_is_it_to_port_ruby_apps_frameworks_over/elfirh9/) about some of the challenges.

But I can also think of a lot of examples that could be easily automated and save some time:

- Rename all file extensions from `.rb` to `.cr`
- Translate methods / operators with different names, e.g.:
  - `include?` -\> `includes?`
  - `key?` -\> `has_key?`
  - `detect` -\> `find`
  - `collect` -\> `map`
  - `respond_to?` -\> `responds_to?`
  - `length`, `count` -\> `size`
  - ` __dir__ ` -\> ` __DIR__ `
  - `and` -\> `&&`
  - `or` -\> `||`
  - `require_relative "foo"` -\> `require "./foo"`

- Replace single quoted strings with double quotes

Then run the Crystal type-checker + formatter + ameba on the result and start fixing the remaining issues.

I was surprised that I couldn’t find anything on Google or the [Implementations/Compilers section in awesome-ruby](https://github.com/veelenga/awesome-crystal#implementationscompilers).

I use a couple of very small Ruby gems that should be very easy to port to Crystal, such as this [bad\_words\_detector](https://github.com/hairyhum/bad-words.ruby). So I’m interested in working on a codemod/translator to help with some of these cases.

I think the easiest way might be to fork [rufo](https://github.com/ruby-formatter/rufo) and make it generate semi-valid Crystal.

---

<div class="post-metadata">

**Author:** ![ndbroadbent](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ndbroadbent/32/637_2.png) [@ndbroadbent](https://forum.crystal-lang.org/u/ndbroadbent)\
**Post date:** [December 3, 2019, 7:55pm UTC](https://forum.crystal-lang.org/t/has-anyone-started-working-on-a-ruby-crystal-codemod-transpiler-converter/1440/2 "2019-12-03T19:55:16Z")

</div>

I decided to fork rufo and created a [ruby\_crystal\_codemod](https://github.com/DocSpring/ruby_crystal_codemod) repo on GitHub.

Haha I just started working on a few of the easy changes, and then @asterite popped up in the git history!

 ![06%20AM](https://canada1.discourse-cdn.com/flex036/uploads/crystal_lang/original/1X/989ea427de6205cd67b55a15e2e97e48c44a8102.png)

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [December 3, 2019, 8:18pm UTC](https://forum.crystal-lang.org/t/has-anyone-started-working-on-a-ruby-crystal-codemod-transpiler-converter/1440/3 "2019-12-03T20:18:20Z")

</div>

> [@ndbroadbent](#):
>
> Haha I just started working on a few of the easy changes, and then @asterite popped up in the git history!

😆

I created rufo! It was previously under my github account but I eventually gave up: maintaining one big open source project is already a lot of work! 🙂

I think translating Crystal syntax to Ruby is a good idea, I’m curious about the result. Doing it without a semantic pass might break in some cases. For example what if I do have a `detect` method on a custom class and you go ahead and rename it to `find`? Then it won’t work.

Also, the std is similar but not exactly the same so there might be some friction there too.

Another thing to consider is macros: in Crystal they work at the AST level and there’s no way to translate that to Ruby… unless you actually run the semantic phase to expand macros, but that also involves typing the entire program.

So one idea would be to type-check crystal, then instead of generating LLVM code you would generate Ruby code… but it gets tricky with things like inline assembly, or methods that should invoke Ruby methods instead of being translated to Ruby (for example String, Array or IO methods… or anything that uses pointers).

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [December 3, 2019, 8:21pm UTC](https://forum.crystal-lang.org/t/has-anyone-started-working-on-a-ruby-crystal-codemod-transpiler-converter/1440/4 "2019-12-03T20:21:43Z")

</div>

> <https://github.com/ruby-formatter/rufo/commit/1bbde1f313f7403b400ce906920db59298a551d7>

It’s a bit scary to see that already more than 2 years passed… what is going on with time??

---

<div class="post-metadata">

**Author:** ![ndbroadbent](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ndbroadbent/32/637_2.png) [@ndbroadbent](https://forum.crystal-lang.org/u/ndbroadbent)\
**Post date:** [December 3, 2019, 9:05pm UTC](https://forum.crystal-lang.org/t/has-anyone-started-working-on-a-ruby-crystal-codemod-transpiler-converter/1440/5 "2019-12-03T21:05:35Z")

</div>

Oh that’s awesome, I didn’t realize that!

I’m also interested in converting Crystal syntax to Ruby, and [I posted about that here](https://forum.crystal-lang.org/t/would-it-be-possible-to-transpile-crystal-ruby/1425). My idea was just so that I could run some simple Crystal code using Ruby’s interpreter, so I would have access to a real REPL where I can modify variables and define new methods.

But in this case I’m trying to see if I can go the other direction and transpile some Ruby code into the Crystal syntax. I think this could make it easier to port some simple Ruby libraries.

A semantic pass would be really great, but I don’t know if that would be feasible in a Ruby codebase without any type annotations. But I could probably do a simple regex search to see if any of the source files contains `def detect`, and then show a big warning in the output.

I have a really simple proof-of-concept working now! [https://github.com/DocSpring/ruby\_crystal\_codemod/tree/master/example\_code](https://github.com/DocSpring/ruby_crystal_codemod/tree/master/example_code)

It just handles the following cases:

- Rename all file extensions from `.rb` to `.cr`
- Replace single quoted strings with double quotes (default in rufo)
- `require_relative "foo"` -\> `require "./foo"`
- ` __dir__ ` -\> ` __DIR__ `

And now Ruby and Crystal can both run the code and produce exactly the same output.

Haha but my implementation is extremely bad. I kept trying to find some way to reach into the next tokens and modify them, but I couldn’t get anything to work. So I just resorted to [this crazy `@wait_for_consume_token_count_then_set_relative_path` counter](https://github.com/DocSpring/ruby_crystal_codemod/commit/cd170b6bf65e532a0fa692896d102f58416497fc#diff-84346c33a4721cb1dca2b2cb62d12d0eR3136-R3141) to get something working.

Is there any easy way to [update the path string in `#visit_command` and add `./`?](https://github.com/DocSpring/ruby_crystal_codemod/commit/cd170b6bf65e532a0fa692896d102f58416497fc#diff-84346c33a4721cb1dca2b2cb62d12d0eR1175-R1180)

---

<div class="post-metadata">

**Author:** ![wontruefree](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/wontruefree/32/1467_2.png) [@wontruefree](https://forum.crystal-lang.org/u/wontruefree)\
**Post date:** [December 4, 2019, 6:08pm UTC](https://forum.crystal-lang.org/t/has-anyone-started-working-on-a-ruby-crystal-codemod-transpiler-converter/1440/6 "2019-12-04T18:08:04Z")

</div>

When I give talks on Crystal this idea comes up a lot. It would be really nice to point people to something like this even if it only covers basic libraries.

---

<div class="post-metadata">

**Author:** ![ndbroadbent](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ndbroadbent/32/637_2.png) [@ndbroadbent](https://forum.crystal-lang.org/u/ndbroadbent)\
**Post date:** [December 5, 2019, 10:20am UTC](https://forum.crystal-lang.org/t/has-anyone-started-working-on-a-ruby-crystal-codemod-transpiler-converter/1440/7 "2019-12-05T10:20:55Z")

</div>

Wow I just realized that I could translate many Sorbet type annotations into Crystal type annotations! I’m definitely going to add that to the roadmap. I’d love to make it as easy as possible for some of the engineers at these companies to start looking into Crystal:

 ![36 PM](https://canada1.discourse-cdn.com/flex036/uploads/crystal_lang/original/1X/080d1476ba03bcc97567273bdf08634cc670b209.png)

---

<div class="post-metadata">

**Author:** ![wontruefree](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/wontruefree/32/1467_2.png) [@wontruefree](https://forum.crystal-lang.org/u/wontruefree)\
**Post date:** [December 5, 2019, 9:53pm UTC](https://forum.crystal-lang.org/t/has-anyone-started-working-on-a-ruby-crystal-codemod-transpiler-converter/1440/8 "2019-12-05T21:53:12Z")

</div>

if anyone is interested the repo is here.

> **[DocSpring/ruby\_crystal\_codemod](https://github.com/DocSpring/ruby_crystal_codemod)**
>
> A codemod / transpiler that can help you convert Ruby into Crystal - DocSpring/ruby\_crystal\_codemod

---

<div class="post-metadata">

**Author:** ![drosehn](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/drosehn/32/72_2.png) [@drosehn](https://forum.crystal-lang.org/u/drosehn)\
**Post date:** [December 5, 2019, 10:51pm UTC](https://forum.crystal-lang.org/t/has-anyone-started-working-on-a-ruby-crystal-codemod-transpiler-converter/1440/9 "2019-12-05T22:51:00Z")

</div>

I’m not confident that this is a good idea, at least not until Crystal passes the 1.0 point. Like many people I started out thinking it would be great to convert programs between ruby and crystal. At first you pick a few small-ish programs and it seems like this would be easy and very useful.

But as I tried to convert larger and more complex ruby programs to crystal, I found that for some programs you’ll really want to rethink what your program is doing. Maybe you can get it running, but in some way which is much worse that what you’d get if you rewrote it by hand.

And the people who would be the most interested in this are people who know ruby well, but haven’t learned all of crystal. That means once they have some initial program running, they’ll be tempted use this sub-optimal crystal program as a template for new crystal programs that they write.

I am sure this kind of transpiler will always be very tempting, but based on my experience you’ll soon get annoyed at all the little details that you have to handle to make a correct and reliable transpiler, and you’ll switch your focus on other projects.

---

<div class="post-metadata">

**Author:** ![ndbroadbent](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ndbroadbent/32/637_2.png) [@ndbroadbent](https://forum.crystal-lang.org/u/ndbroadbent)\
**Post date:** [December 6, 2019, 11:35am UTC](https://forum.crystal-lang.org/t/has-anyone-started-working-on-a-ruby-crystal-codemod-transpiler-converter/1440/10 "2019-12-06T11:35:08Z")

</div>

@drosehn You’re probably right, but it’s been a lot of fun to work on! I think I will probably keep working on as a hobby project / academic exercise to learn more about the Crystal language.

I added this special `#~# BEGIN / END` comment syntax (inspired by the Rufo test suite!), so it’s now [possible to write Ruby and Crystal in the same file](https://github.com/DocSpring/ruby_crystal_codemod#writing-ruby--crystal-in-the-same-file).

I got [most of the easy transformations done](https://github.com/DocSpring/ruby_crystal_codemod#status), but I’m really excited about the idea of transforming Sorbet Type Annotations.

I’m also really interested in the idea of automatically instrumenting Ruby code to keep track of all the variable assignments, and building up a list of all the possible types that it sees at run-time. Then I could pass that to the transpiler so that it converts them into type annotations. (Maybe using Sorbet annotations as an intermediate step, so that people can also use this for Sorbet.)

---

<div class="post-metadata">

**Author:** ![bcardiff](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/bcardiff/32/3_2.png) [@bcardiff](https://forum.crystal-lang.org/u/bcardiff)\
**Post date:** [December 6, 2019, 5:29pm UTC](https://forum.crystal-lang.org/t/has-anyone-started-working-on-a-ruby-crystal-codemod-transpiler-converter/1440/11 "2019-12-06T17:29:55Z")

</div>

Although I don’t expect to directly translate a full app it could lead to a translator assistant for snippets and scripts.

It can help for users migrating from Ruby to Crystal to learn the delta in a more interactive way rather than reading.

It might be more interesting if the criteria of the diffs are available at hand and not only the changes in the code, but it’s still valuable IMO.

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [January 26, 2026, 12:36pm UTC](https://forum.crystal-lang.org/t/has-anyone-started-working-on-a-ruby-crystal-codemod-transpiler-converter/1440/13 "2026-01-26T12:36:17Z")

</div>

A post was split to a new topic: [Lexing Crystal for a Crystal to Ruby transpiler](https://forum.crystal-lang.org/t/lexing-crystal-for-a-crystal-to-ruby-transpiler/8676)
