Skip to content

Instantly share code, notes, and snippets.

@asterite
Created October 13, 2014 00:20
Show Gist options
  • Select an option

  • Save asterite/370389c5e61f810c398a to your computer and use it in GitHub Desktop.

Select an option

Save asterite/370389c5e61f810c398a to your computer and use it in GitHub Desktop.
require "compiler/crystal/**"
include Crystal
class MyVisitor < Visitor
def initialize
@str = StringIO.new
end
def visit(node : ClassDef)
@str << %(_class = Ruby::Class.new "#{node.name}"\n)
end
def visit(node : Def)
@str << %(_class.def "#{node.name}", #{node.args.length}, )
@str << %[->(self : LibRuby::VALUE, ]
node.args.each do |arg|
@str << %(#{arg.name} : LibRuby::VALUE, )
end
@str << %[) do\n]
@str << node.body
@str << %(\nend)
false
end
def visit(node : Nop)
end
def visit(node : ASTNode)
raise "Unexpected node: #{node}"
end
def to_s(io : IO)
io << @str
end
end
node = Parser.parse(ARGV[0].gsub(/\\n/, "\n"))
visitor = MyVisitor.new
node.accept visitor
visitor.to_s(STDOUT)
lib LibRuby
type VALUE = Void*
type ID = Void*
$rb_cObject : VALUE
fun rb_define_global_function(name : UInt8*, f : Void*, args : Int32)
fun rb_eval_string(str : UInt8*) : VALUE
fun rb_str_new_cstr(str : UInt8*) : VALUE
fun rb_define_class(name : UInt8*, parent : VALUE) : VALUE
fun rb_define_method(clazz : VALUE, name : UInt8*, f : Void*, args : Int32)
fun rb_any_to_s(v : VALUE) : VALUE
fun rb_string_value_cstr(v : VALUE*) : UInt8*
fun rb_intern(name : UInt8*) : ID
fun rb_funcall(obj : VALUE, func : ID, args : Int32, ...) : VALUE
end
struct Nil
def to_ruby
Pointer(Void).new(8_u64) as LibRuby::VALUE
end
end
struct Bool
def to_ruby
Pointer(Void).new(self ? 0_u64 : 20_u64) as LibRuby::VALUE
end
end
class String
def to_ruby
LibRuby.rb_str_new_cstr(self)
end
end
module Ruby
ID_TO_S = LibRuby.rb_intern("to_s")
struct Class
def initialize(name)
@class = LibRuby.rb_define_class(name, LibRuby.rb_cObject)
end
def def(name, args, f)
LibRuby.rb_define_method(@class, name, f.pointer, args)
end
end
struct Value
@value :: LibRuby::VALUE
def initialize(@value : LibRuby::VALUE)
end
def to_unsafe
@value
end
def to_s
str = LibRuby.rb_funcall(self, ID_TO_S, 0)
String.new(LibRuby.rb_string_value_cstr(pointerof(str)))
end
end
def self.global_def(name, args, f)
LibRuby.rb_define_global_function(name, f.pointer, args)
end
end
macro ruby(code)
{{ run "ruby_processor", code }}
end
ruby(
class Foo
def foo(a)
a = Ruby::Value.new(a)
"From Crystal!! #{a.to_s}".to_ruby
end
end
)
redefine_main("Init_testruby") do |main|
{{main}}
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment