d = DynamicMethod.new("Int32, UInt32*, UInt32")
g = d.get_generator
g.begin_exception_block do
g.call "static Throws.ThrowException()"
g.br_s "EndOfMethod"
g.catch("Exception") do
g.call "ToString()"
g.call "static Console.WriteLine(String)"
end
g.label "EndOfMethod"
g.ldc_i4 Qnil
g.ret
end
I'd love it if folks could comment on how this syntax might be improved in
Ruby before I crank out the underlying MC++ / Ruby code ...
Thanks!
-John
http://www.iunknown.com
Are you the person who got the Google summer of code grant to do a Ruby/.NET
bridge?
Phil
> Are you the person who got the Google summer of code grant to do a Ruby/.NET
> bridge?
Wasn't that a Summer of Code grant to do a Ruby.NET compiler...? ;)
It was great meeting you at RubyConf!
We can avoid having to do all the "g." prefixes on the methods like this:
module CLR_IL
def use_generator(g)
@il_generator = g
end
def begin_exception_block
@il_generator.begin_exception_block
end
def call(s)
@il_generator.call(s)
end
end
then your example becomes
d = DynamicMethod.new("Int32, UInt32*, UInt32")
g = d.get_generator
use_generator(g)
begin_exception_block do
call "static Throws.ThrowException()"
br_s "EndOfMethod"
...etc...
Of course, we could use method_missing in module CLR_IL to avoid
having to write each of the individual wrappers that forward to
@il_generator.whatever.
Wayne Vucenic
No Bugs Software
"Ruby and C++ Agile Contract Programming in Silicon Valley"
It was great meeting you too! Thanks for the suggestion - I was already
thinking along the lines of moving everything to modules, and your example
really drives home just how much better the syntax can be if I implement
method_missing on the module itself. Hopefully I'll have something working
early next week so that I can post some code for folks to try out.
Thanks for the suggestion!
-John
http://www.iunknown.com
I just noticed that I left out the line
include CLR_IL
before the line
d = DynamicMethod.new("Int32, UInt32*, UInt32")
> Hopefully I'll have something working
> early next week so that I can post some code for folks to try out.
I'm looking forward to seeing this.
By the way, iunknown.com is such an outrageously good domain name for a COM guy!
Wayne
require 'RbDynamicMethod'
include RbDynamicMethod
include ILGenerator
create_ruby_method('say_hello') do
ldstr 'Hello, World'
call 'static System.Console.WriteLine(System.String)'
ldc_i4_4
ret
end
say_hello
This code generates a Ruby method with a VALUE (int, VALUE*, VALUE)
signature. The create_ruby_method yields to the block, and uses
method_missing to generate the IL instructions. Once the block has finished
executing, I bake the dynamic method into the RbDynamicMethod module.
Overall I'm pretty happy with this syntax. I'm attaching the implementation
of ILGenerator below for those who are curious. The MC++ part
(RbDynamicMethod) weighs in at about 160 lines of code.
Comments appreciated!
Thanks
-John
http://www.iunknown.com
module ILGenerator
include RbDynamicMethod
@@op_codes = {
'ldstr' => 's',
'call' => 'm',
'ret' => nil,
'ldc_i4_4' => nil
}
def create_ruby_method(name)
method = create_dynamic_method('', 'System.UInt32', 'System.Int32,
System.UInt32*,System.UInt32')
@@g = get_cil_generator(method)
yield if block_given?
define_ruby_method(method, name)
end
def parse_method_ref(sig)
re = /(static )?(.*)\.(\w+)\((.*)\)/
m = re.match(sig)
is_static = m[1] == 'static '
type_name = m[2]
method_name = m[3]
parameters = m[4]
return is_static, type_name, method_name, parameters
end
def method_missing(name, *parameters)
op_code = name.to_s
type = @@op_codes[op_code]
case type
when 's': emit_string(@@g, op_code, parameters[0])
when 'm': emit_method_ref(@@g, op_code,
*parse_method_ref(parameters[0]))
when nil: emit(@@g, op_code)
end
end
end
> create_ruby_method('say_hello') do
> ldstr 'Hello, World'
> call 'static System.Console.WriteLine(System.String)'
> ldc_i4_4
> ret
> end
>
> say_hello
This is pretty cool and I would really like to see a Ruby in Ruby
compiler that utilizes this for generating .NET byte code. I've spend
some time thinking on it and might do that at next year's Summer of Code
(if I am accepted) if it hasn't already been done by then.
Will you continue working on it? Where is this going?
I'm getting ready to ship a build of RbDynamicMethod tonight so that folks
can take a look at it. So hang in there - should be about 4 hours before I
ship :)
Cheers,
-John
http://www.iunknown.com