Rubinius Hits Primetime: Let the FUD Begin

February 14th, 2007 | 2 comments

For being a very young project (Evan’s been working on it about a year, but it’s only been in the public view for a few months), Rubinius has quickly hit primetime with the first (that I know of) FUD-ish review The basic premise is that pypy had money, minds, and at least one goal to produce a simpler VM than CPython, but as it nears 1.0 it’s much more complex than CPython. And since Rubinius is at least lacking in official monetary backing, it’s got a real tough row to hoe. Maybe; but I’m unconvinced.

The jury is still out on the mind-share Rubinius will ultimately attract. We’re certainly not sneezing at anyone’s contribution. And if you hang out in the channel, you might notice some rather interesting conversations between the JRuby folks and the Rubinius folks. You’ll definitely hear conversations about PIC, STM, concurrency models that make you go “Ohh” (thanks MenTaLguY), the possibilities of LLVM, even JIT’ing (though, to hear JP tell it, we’re hopelessly unqualified for that). I’d guess a who’s-who on Rubinius would turn up some rather accomplished folks. Personally, It is encouraging that I didn’t have to write the book on compilers to be able to hack on Rubinius. But really, do you have to know everything to jump into a project and start learning and applying it?

Let’s just say, I’m sure glad Linus was not deterred by the fact that IBM, SCO, AT&T, and Micro$oft had billions of dollars to spend on operating system development. Anyway, I’ll bet the “Yes, but does it scale?” posts will be showing up shortly. C’mon JP, live a little.

TSort in sirb

February 12th, 2007 | 0 comments

They say good things come in threes, or perhaps I’ll bore you with another post about Rubinius, but what the heck. So, the other day I imported Ruby’s standard library from the SVN repository into the Rubinius repository. I’ve been itching to go through and see what successfully loads. Ah, now that we have sirb, the perfect opportunity presents itself.


$ ./shotgun/rubinius apps/irb/sirb.rb
sirb(eval):000> require 'tsort'
Couldn't find tsort.rbc in runtime/compiler.rba (No such file/-1)
Couldn't find tsort.rb in runtime/compiler.rba (No such file/-1)
Unable to find 'tsort' to load
                 main.raise at bootstrap/04kernel.rb:26
               main.require at core/compile.rb:91
       main.__eval_script__ at (eval):1
    CompiledMethod#activate at bootstrap/compiled_method.rb:52
            main.__script__ at apps/irb/sirb.rb:79
                  main.load at core/compile.rb:56
            main.__script__ at core/__loader.rb:50

Hmm. Oh, yes! I think we need to check load path. (I’ve since added stdlib to the default load path.)


sirb(eval):001> p $:
[".", "runtime/compiler.rba", "lib"]
=> nil
sirb(eval):002> $:.push "stdlib" 
=> [".", "runtime/compiler.rba", "lib", "stdlib"]
sirb(eval):003> require 'tsort'
Couldn't find tsort.rbc in runtime/compiler.rba (No such file/-1)
Couldn't find tsort.rb in runtime/compiler.rba (No such file/-1)
=> true

Oh baby. Just ignore those couple complaints. It’s that => true that we’re looking for. Nice! Now, we’ll just try the example in the tsort.rb file.


sirb(eval):004> class Hash
sirb(eval):005>   include TSort
sirb(eval):006>   alias :tsort_each_node :each_key
sirb(eval):007>   def tsort_each_child(node, &block)
sirb(eval):008>     fetch(node).each(&block)
sirb(eval):009>   end
sirb(eval):010> end
=> nil
sirb(eval):011> {1=>[2, 3], 2=>[3], 3=>[], 4=>[]}.tsort
=> [3, 2, 1, 4]
sirb(eval):012> {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}.strongly_connected_components
=> [[4], [2, 3], [1]]
sirb(eval):013>

Excellent! Er, what’s that? Did I hear you say, “So, big deal, tsort.rb isn’t that tough”? Well, ok, it isn’t. (I didn’t even know about TSort before browsing through the source.) But, we can do other stuff, too.


sirb(eval):008> require 'csv'
=> true
sirb(eval):009>

Yep, that’s right, csv.rb compiles! But, I’ll spare you the pain that ensued trying to use it. Baby steps. Ok, enough fun. C’mon kids, there’s a bunch of the core library still to implement!

Sirb: The Rubinius Loupe

February 11th, 2007 | 3 comments

If my previous post about sirb got you drooling a bit, read on. I’ve added some simple command line arguments to sirb that enable you to request that s-expressions, assembly, or bytecodes (or all of them) are printed each time through the RCEPL loop. You can get a hint at all the goodness by passing the -h switch.


$ ./shotgun/rubinius apps/irb/sirb.rb -h -p -x -s -b
  Usage: sirb [options]
    sirb is a RCEPL (read, compile, execute, print, loop) program for rubinius

    Options: 
            -p   Print the parsed s-expression
            -x   Print the normalized s-expression.
            -s   Print assembly instructions.
            -b   Print bytecode encoding.

sirb(eval):0> puts "Hello, Rubinius. You rock my world!" 

S-exp:
[:newline, 1, "(eval)", [:fcall, :puts, [:array, [:str, "Hello, Rubinius. You rock my world!", 0]]]]

Normalized S-exp:
[:newline, 1, "(eval)", [:call, [:self], :puts, [:array, [:str, "Hello, Rubinius. You rock my world!", 0]]]]

Asm:
#line 1
push_literal 0
string_dup
push self
send puts 1
ret

Bytecodes:
"\v\000\000\000\000:\f)\000\000\000\001\000\000\000\001'\000\000\000" 
Hello, Rubinius. You rock my world!
=> nil
sirb(eval):1>

As I mentioned, sirb is rudimentary at the moment. But it shows you how much can be done with Rubinius right now. Swell! And, a big thanks to mae for fixing up how the output of the execution prints (no more ["foo"]).

Irb on Rubinius

February 11th, 2007 | 2 comments

There are cat people and dog people, but when I say “Man’s best friend”, I don’t mean either. I’m talking about that program that feels like a home away from home: irb. So, I’ve been chomping at the bit to get something resembling irb running with Rubinius.

Today, a few of us pdx.rb folks got together for some Rubinius hacking. Of course, irb was one of the things I proposed that we work on. We had a go at it, but in the end we didn’t get too far. irb is no trivial application. But, I think a good part of it was my fault. I’ve been working on these specs for so long, where at the moment we’re forced to send everything to rubinius in a subprocess, that I failed to grasp that we would have a persistent machine. Anyway, let’s cut this short: Folks, we have a rudimentary sirb!


sirb(eval):0> class Hello
sirb(eval):1> def greet
sirb(eval):2> puts "Hello, irb!" 
sirb(eval):3> end
sirb(eval):4> end
=> nil
sirb(eval):5> Hello.new.greet
=> Hello, irb!
["Hello, irb!"]
sirb(eval):6> @s = "Hello, earthling" 
=> "Hello, earthling" 
sirb(eval):7> p @s
=> "Hello, earthling" 
["Hello, earthling"]
sirb(eval):8> Hello
=> Hello
sirb(eval):9> Hello.class
=> Class
sirb(eval):10> Hello.new
=> #<Hello:0x6696cc>
sirb(eval):11> 

In the words of Napolean Dynamite: Sweet. Of course, it is pretty rough right now. You’ll notice the use of an instance variable, @a. That’s because I couldn’t figure out how to get local variables to work. Basically, everything is evaluating with the default receiver being an instance of Object.

Well, warts and all, I think it’s a beautiful thing.

Waiter, there's a Tuple in my Array

February 8th, 2007 | 0 comments

Implementing Ruby in Ruby raises some challenges. In the beginning, Ruby was implemented in C. Well, at least the interpreter and core libraries. In C, you have the standard library that provides things like the math functions, functions for manipulating arrays of chars, which can be considered strings of text, etc. So, what happens when you want to build Ruby with Ruby? Well, you use Ruby, of course. And since Ruby is a class-based language, you probably will use a class. Ladies and Gentlemen, meet Tuple.

In Rubinius, the class Tuple is present for all to see. And it’s put to good use, underlying the implementation of Array for instance. You can use it, too:


sirb:001> t = Tuple.new(3) => #<Tuple: nil, nil, nil>
sirb:002> t.put(1, "foo")  => #<Tuple: nil, "foo", nil>
sirb:003> t.shift          => #<Tuple: nil, "foo">

Here’s another example. Have you noticed the chr method available on instances of Integer. Well, while implementing some String methods, I decided it would be nice to say, some_str[i].isspace. If you’ve used C, you know that there is this thing ctype that has macros or functions like isspace. Stumbling around a bit, I finally decided to add a module CType and mix that in to Integer. Works pretty well.

So, there’s Tuple in all its glory sitting right in the middle of your Array. Is that a problem? I don’t think so. This is Ruby, folks. Duck typing, open classes, mixins, methods appearing and disappearing any old time of the day are the norm. To clarify, the behavior of the core classes, like Array, which have a different implementation in Rubinius from that of the C one used in MRI, will not change. In other words, if you use Array methods, they’ll behave like Array methods.

I say, if your code depends on a class only having certain elements when you invoke Foo.ancestors, for Pete’s sake, refactor. And if you happen to have a ByteArray or Tuple in your application, refactor that, too. We’re the VM, we get certain privileges. Now, suppose you wrote your application to use all the deliciousness of Rubinius, thereby demonstrating you are a wise and thoughtful old soul. (Yes, that’s right, CompiledMethod, Method, MethodContext, BlockContext, BlockEnvironment, and more are classes. Yum. And that is just the tip of the iceberg, I assure you.) But, you heavily built in dependencies on, say, Tuple, and now you’re complaining it doesn’t run on MRI… Well, here’s your warning. In other words, don’t be that silly.

However, if this raises concerns for you, here’s a suggestion: We’re working feverishly on RSpec specs for all of the core and standard Ruby libraries. We also have a directory for incompatibilities in the Rubinius implementation, which is predictably found in spec/core/incompatible. Feel free to join us in writing these specs. That way, you can run them against your favorite Ruby implementation and know what works. Perhaps, you can even integrate this knowledge into your own project’s specs. You are writing specs for your projects, aren’t you?

Happy New Year

February 8th, 2007 | 0 comments

Sometime between Jan 1 and Chinese New Year it finally dawns on me that we’ve begun a, well, new year. I start writing the correct dates on checks, the bank honors them, the rent gets paid. Things go much more smoothly.

So, while trying to keep up with the homework from my brilliant professor of game theory, I thought I’d write a few predictions for 2007. Sure, some of these you could call resolutions, but since it’s up to me to do them, lumping them into the predictions category might up my percentage correct score.

This blog will finally get a real theme, shorter posts, an articles section, recent and popular links. Also, I’m going to spruce up the RSS served to be more useful in a reader. Finally, to break the asymmetry of time, I’ll be putting titles of upcoming posts in before the post appears. When it does, the title will become a link.

2007 will be the year of the alternate Ruby implementations. Several will be competing with MRI (Matz’s Ruby Interpreter) for your love and admiration. Among these are YARV, JRuby and Rubinius . One of those will have a tremendous impact on enterprise coding and another will have a tremendous impact on CS in general. We’ll see how that pans out. I’ll be posting more about Rubinius soon. In the meantime, don’t miss the wonderful, appreciated, and tireless work of Pat on the On-Ruby Blog to evangelize Rubinius and other cool projects.

I’ll be learning at least one new application this year: Omnigraffle. This comes highly recommended by our Creative Director, Allison. Truth is, design and graphics is way more interesting to me than plain ol’ code, but writing code usually wins out in a duel, so I’m hoping to even things out a bit.

Finally, I hope to collaborate on writing a book; I’ll let you guess the topic. And if things go well, I’ll be co-announcing a currently top secret project. Ahh, I see the eyebrows rising. Also on my list of things to write about are some more thoughts on d3 and our experiences with it at PLANET ARGON.

In the near future, check out What’s the Big Idea and Another Liberating Constraint: Contracts.