Anyolite 1.0.0

After nearly two years it is finally time for the first full release of Anyolite!

Anyolite (https://github.com/Anyolite/anyolite) is a Crystal shard that includes a Ruby interpreter (either mruby or regular Ruby) into Crystal and allows for binding Crystal classes and functions directly to Ruby.

You can bind entire module hierarchies to Ruby with one single code line, you can call Ruby functions and manipulate Ruby objects from Crystal, and even share objects between both languages without worrying about memory leaks or Garbage Collector clashes. Anyolite helps you focus on the more important tasks instead of struggling with the mruby/Ruby API.

It is also possible to compile entire Ruby scripts to bytecode and even include them into your executable, all at compiletime!

The latest releases mostly provided bugfixes, better code quality and a small Wiki at https://github.com/Anyolite/anyolite/wiki. If you want to test Anyolite, there is also a small demo console game at https://github.com/Anyolite/ScapoLite, which uses many features of Anyolite.

Generally, Anyolite should be a perfect tool for scripting utilities in games, science or other applications, as it combines the performance of Crystal with the flexibility of Ruby, wherever you need it, without boilerplate code.

If you have any questions about Anyolite, feel free to ask!

33 Likes

Congrats on this milestone!!

2 Likes

Amazing!!

1 Like

Awesome!

1 Like

This is huge and opens a lot of possibilities, integrations and use-cases with Crystal and Ruby! Huge milestone!

1 Like

Help please. I submitted two issues, one to having difficulty running the tests in a new clone of the repo · Issue #36 · Anyolite/anyolite · GitHub and one at anyolite 1,1,0 incompatibility? · Issue #1 · Anyolite/ScapoLite · GitHub. Thanks

2 Likes

Just a quick question (I haven’t checked your github yet) : Can it be done the other way around, we use Ruby libraries in Crystal?"

Yes, this should be possible!

There are currently some limitations to this (you effectively have to embed the Ruby interpreter into your project and then install the gems), but other wise this should work perfectly fine.

Well done ! Huge job. Very useful !

1 Like

I’m a newbie to Crystal so please forgive me if my questions have obvious answers:

  1. How do I retrieve the result of a script? e.g. I have a Crystal HTTP server that runs an Anyolite script and I want the script’s result as a JSON string to return to the client.

  2. The documentation says don’t create more than one interpreter but it’s possible I’d want one for each concurrent client of my HTTP server, is that possible?

Thanks.

  1. You can’t get the result of a script file directly, but you can always call a script line using Anyolite.eval (see Anyolite - anyolite 1.1.0). This will return either a generic Ruby reference or ensure a specific type at compiletime (if you pass it to the cast_to keyword).
  2. Sadly this doesn’t seem to be easily possible (see Multiple interpreters · Anyolite/anyolite · Discussion #28 · GitHub) and I’m aware of the limitations caused by it. Is there a specific argument against using a single interpreter for all clients?

Hopefully I could help a bit. If you have any subsequent questions or if something doesn’t work, I’ll gladly try to answer them.

Thank you for the offer of assistance, I do appreciate it :slightly_smiling_face:
Below is a skeleton of a methodology that seems to give me what I want, I would just need a convention that each script must expose a run function.

Crystal

require "anyolite"

Anyolite::RbInterpreter.create do |rb|
  Anyolite.set_gv("$request", "Steve")
  rb.load_script_from_file("src/test.rb")
  response = Anyolite.eval("run", String)
  puts response
end

Ruby [test.rb]

$response = "Hello, "

def run()
  return $response += $request
end

Would I need to use a mutex if I were to do this?
To be honest for my immediate use case I don’t expect any concurrency but it’s always good to know for the future, especially if you find an application architecture that you enjoy and would like to use again.

How would I adapt my snippet above to return a Hash from Anyolite.eval() ?

I will return to your post about your use case later, but I can quickly answer your questions about the hashes. Usually something like this should work, if your scripts always return hashes from a String into a union of String and Int32:

Anyolite.eval("run", cast_to: Hash(String, String | Int32))

You still have to specify the type, since Crystal wants to know all possible types for a variable at compiletime - but you can do unions. If something other than the specified type is passed from Ruby, this line will throw an exception at runtime.

Thanks for this. Did you consider using Crystal’s built-in interpreter that comes with the compiler instead?

I did consider that, but it’s not really clear if the performance would be worth it and if it would work at all:

That sounds interesting…
Are you able to provide a snippet demonstrating how to use it?

Crystal currently uses it for the REPL. I don’t know if it has an interface. It’d make the build process simpler by removing C dependencies and maybe remove a few of the interop limitations that come from Crystal and Ruby being different languages. It’s currently experimental though and in’t enabled for some toolchains by default and it still has bugs.

This is a bit off-topic from embedding the Crystal interpreter, but here are three lesser known Ruby implementations for embedded systems (the mruby family).

  • mruby
    General-purpose embedded Ruby. Compiler and VM are separate. Supports most of Ruby’s syntax. Too heavy for small microcontrollers, but used in systems like satellites. Matz’s current main project.

  • mruby/c
    A much lighter version with only a VM. It runs bytecode generated by mruby, making them interoperable. Designed for resource-constrained MCUs. Known use cases include industrial devices like sewing machines.

  • PicoRuby
    Combines a minimal Ruby compiler with mruby/c. Optimized for RP2040 boards like the Raspberry Pi Pico. Often used in hobbyist projects such as custom keyboards.

If you search for real-world use cases of these mruby projects, most press releases are in Japanese, and results mainly point to companies in Hukuoka and Shimane (where Matz lives).

Still, these implementations are open source, and technically adventurous communities such as Crystal may benefit directly or indirectly from them…