Jan 30 2007

F3/swiby style declaration blocks

madlep

swiby is a proof of concept framework inspired by F3. Both use a hierarchical block format for defining Java/Swing visual elements. eg:

Frame {
  title "Hello World F3"
  width 200
  content {
    Label {
      text bind(model, :saying)
    }
  }
  visible true
}

I was looking through the documentation, and got curious as to how the class level block declaration is actually implemented in swiby. After a bit of digging around, it is relatively straight forward.

There is some code in swiby that looks kinda like this:

def component_factory(class_name)
  eval %{
    def #{class_name}(&block)
      x = #{class_name}.new
      x.instance_eval(&block)
      x
    end
  }
end

I’ve removed the error handling and some extra functionality, but the basic idea is the same. component_factory is called for each class that is required to be instantiated as a declared block. Here’s an example:

class Foo
end

class Bar
end

component_factory :Foo
component_factory :Bar

my_foo = Foo {
  @my_bar = Bar {
    @baz = 'baz'
  }
}

puts my_foo.inspect

Which outputs:
#<Foo:0x60544 @my_bar=#<Bar:0x604e0 @baz="baz">>

A Foo instance has been created containing a Bar instance, with a variable of baz. This sort of syntax could be useful for DSL implemented in Ruby.

One limitation I ran into, is that calling attr_accessor methods don’t get recognized (they just get defined as local variables that go out of scope at the end of the block) - but that may just be a limitation of useing instance_eval to set the newly created object as the object in scope as self.