Anyolite is a Crystal shard which adds a fully functional mruby (or even regular Ruby) interpreter to Crystal.
Anyolite allows for wrapping Crystal classes and functions into Ruby with little effort. This way, Ruby can be used as a scripting language to Crystal projects, with the major advantage of a similar syntax.
Useful links for an overview:
- Demo project: https://github.com/Anyolite/ScapoLite
- Wiki: https://github.com/Anyolite/anyolite/wiki
- Documentation: https://anyolite.github.io/anyolite
- Bindings to an mruby interpreter
- Near complete support to regular Ruby as alternative implementation (also known as MRI or CRuby)
- Wrapping of nearly arbitrary Crystal classes and methods to Ruby
- Easy syntax without unnecessary boilerplate code
- Simple system to prevent garbage collector conflicts
- Support for keyword arguments and default values
- Objects, arrays, hashes, structs, enums and unions as function arguments and return values are completely valid
- Ruby methods can be called at runtime as long as all their possible return value types are known
- Ruby closures can be handled as regular variables
- Methods and constants can be excluded, modified or renamed with annotations
- Options to compile scripts directly into the executable
You need to have the following programs installed (and in your PATH variable, if you are on Windows):
- Ruby (for building mruby)
- Rake (for building the whole project)
- Git (for downloading mruby)
- GCC or Microsoft Visual Studio 19 (for building the object files required for Anyolite, depending on your OS)
It is possible to use Anyolite with regular Ruby (MRI) instead of mruby. An instruction to install MRI can be found at Using Ruby instead of mruby in the wiki.
Put this shard as a requirement into your shard.yml project file and then call
shards install
from a terminal.
Alternatively, you can clone this repository into the lib folder of your project and run
rake build_shard
manually from a terminal or the MSVC Developer Console (on Windows) to install the shard without using the crystal shards program.
If you want to use other options for Anyolite, visit Changing build configurations in the wiki.
Imagine a Crystal class for a really bad RPG:
module RPGTest
class Entity
property hp : Int32
def initialize(@hp : Int32)
end
def damage(diff : Int32)
@hp -= diff
end
def yell(sound : String, loud : Bool = false)
if loud
puts "Entity yelled: #{sound.upcase}"
else
puts "Entity yelled: #{sound}"
end
end
def absorb_hp_from(other : Entity)
@hp += other.hp
other.hp = 0
end
end
end
Now, you want to wrap this class in Ruby. All you need to do is to execute the following code in Crystal (current commit; see documentation page for the version of the latest release):
require "anyolite"
Anyolite::RbInterpreter.create do |rb|
Anyolite.wrap(rb, RPGTest)
rb.load_script_from_file("examples/hp_example.rb")
end
Well, that's it already. The last line in the block calls the following example script:
a = RPGTest::Entity.new(hp: 20)
a.damage(diff: 13)
puts a.hp
b = RPGTest::Entity.new(hp: 10)
a.absorb_hp_from(other: b)
puts a.hp
puts b.hp
b.yell(sound: 'Ouch, you stole my HP!', loud: true)
a.yell(sound: 'Well, take better care of your public attributes!')
The example above gives a good overview over the things you can already do with Anyolite. More features will be added in the future.
See Limitations and solutions in the Wiki section for a detailed list.
https://en.wikipedia.org/wiki/Anyolite
In short, it is a rare variant of the crystalline mineral called zoisite, with ruby and other crystal shards (of pargasite) embedded.
The term 'anyoli' means 'green' in the Maasai language, thus naming 'anyolite'.
NOTE: This version requires recompilation of mruby and the C files.
NOTE: This version will only work with mruby 3.2.0 and above.
- Added direct bindings to
Regex
from Crystal (Regexp
in Ruby) - Added option to use a separate Ruby interpreter
- Added safeguard to catch non-fatal Crystal exceptions and raise them as Ruby errors
- Added option to transform procs into bytecode
- Added function to disable external program execution
- Added interpreter depth counter
- Updated to mruby 3.2.0
- Updated to MRI 3.0.5
- Added backtrace function for mruby
- Added option to fully protect Crystal values from the Ruby GC
- Added standalone wrappers for class properties
- Updated mruby config file to use
libucrt
instead ofmsvcrt
- Discarded old and problematic Regex mruby gem
- Made arguments for
Anyolite.call_rb_method_of_object
optional - Added automatic conversion from Ruby class names to class objects in method callers
- Improved testing script
- Added check for
RbValue
andRbRef
to some macro methods - Added ability to pass Ruby blocks via Crystal to Ruby function calls
- Added some internal methods to mruby to handle fibers
- Added some exception checking methods
- Added methods to check reference table size
- Removed now optional
Dir
gem from default build config - Removed need for
use_general_object_format_chars
flag for MRI - Added global option to use keyword args for optional arguments only
- Fixed error when running
shards install
on Windows - Fixed compilation warning messages for Windows
- Fixed problems with Regexes due to PCRE conflicts
- Fixed problems with Anyolite on Crystal 1.5.1
- Unspecified arguments now always correctly throw warnings instead of confusing errors
- Fixed compiletime error when casting to
Char
- Fixed errors when passing certain name arguments to Macros for calling Ruby functions
- Fixed
Anyolite.call_rb_method_of_object
argumentargs
not being optional - Fixed linker error due to typo in mruby bindings for block functions
- Fixed crash when casting Ruby numbers into objects in some cases
- Fixed script lines not printing exceptions
- Fixed memory leak when calling Ruby scripts and script lines
- Updated tests to account for reworked
inspect
method for enums - Fixed errors when building Anyolite in a path with spaces
- Fixed problems on Linux when
LD
is set, butgcc
should compile - Fixed Crystal functions for accessing global variables in mruby
- Fixed Anyolite to allow enums with types different than
Int32
- Automated generation of Ruby documentations for wrapped functions
- MRI support on Windows (does currently not work for some reason)
- MRI support for version 3.1.0 and up
- Support and continuous integration for Mac
- Support for bindings using
Data
andStruct
from Ruby - Multiple interpreters for mruby
- Add option to make script calls thread-safe
- Splat argument and/or arbitrary keyword passing
- Support for slices and bytes
- Classes as argument type
- Resolve context even in generic type union arguments
- General improvement of type resolution
- Bignum support
- Range support