IL Generator syntax proposal

J

John Lam

------=_Part_949_1409715.1133543816267
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

In my rewrite of my Ruby <=3D> CLR bridge, I've been thinking about pushing
most of the logic into Ruby, and leaving as little as possible in Managed
C++. I was just hacking around this morning in emacs thinking about what th=
e
syntax for an IL generator should look like, and this was what I came up
with:

d =3D DynamicMethod.new("Int32, UInt32*, UInt32")
g =3D 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

------=_Part_949_1409715.1133543816267--
 
P

Phil Tomson

------=_Part_949_1409715.1133543816267
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

In my rewrite of my Ruby <=3D> CLR bridge, I've been thinking about pushing
most of the logic into Ruby, and leaving as little as possible in Managed
C++. I was just hacking around this morning in emacs thinking about what th=
e
syntax for an IL generator should look like, and this was what I came up
with:

d =3D DynamicMethod.new("Int32, UInt32*, UInt32")
g =3D 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 ...

Are you the person who got the Google summer of code grant to do a Ruby/.NET
bridge?

Phil
 
F

Florian Groß

Phil said:
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...? ;)
 
W

Wayne Vucenic

Hi John,

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 =3D 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 =3D DynamicMethod.new("Int32, UInt32*, UInt32")
g =3D 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"
 
J

John Lam

------=_Part_19308_4772661.1133663290150
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Hi Wayne,

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

------=_Part_19308_4772661.1133663290150--
 
W

Wayne Vucenic

Hi John,

I just noticed that I left out the line

include CLR_IL

before the line

d =3D 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
 
J

John Lam

------=_Part_32086_21553279.1133758250113
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

I had some free cycles this evening to do a first pass implementation of
some of the ideas that Wayne proposed, and here's the net result:

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 =3D {
'ldstr' =3D> 's',
'call' =3D> 'm',
'ret' =3D> nil,
'ldc_i4_4' =3D> nil
}

def create_ruby_method(name)
method =3D create_dynamic_method('', 'System.UInt32', 'System.Int32,
System.UInt32*,System.UInt32')
@@g =3D get_cil_generator(method)
yield if block_given?
define_ruby_method(method, name)
end

def parse_method_ref(sig)
re =3D /(static )?(.*)\.(\w+)\((.*)\)/
m =3D re.match(sig)
is_static =3D m[1] =3D=3D 'static '
type_name =3D m[2]
method_name =3D m[3]
parameters =3D m[4]
return is_static, type_name, method_name, parameters
end

def method_missing(name, *parameters)
op_code =3D name.to_s
type =3D @@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

------=_Part_32086_21553279.1133758250113--
 
F

Florian Groß

John said:
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?
 
J

John Lam

------=_Part_21644_19822681.1133916963943
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

This is going to be the way that I implement my Ruby <=3D> CLR bridge. I go=
t
to a point where there was just too much C++ code, and it was getting hard
to add features. There is only about 300 lines of C++ code in
RbDynamicMethod, and I suspect there won't be much more that's needed.
Everything else is going to be implemented in Ruby.

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


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?

------=_Part_21644_19822681.1133916963943--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top