From: Sean O'Halpin Date: 2008-04-05T08:54:11+09:00 Subject: Re: DSL implementation question On Fri, Apr 4, 2008 at 4:49 AM, tender flake wrote: > Hello, > > I'm trying to write a simple DSL to define memory maps of hardware > devices. > Something like: > > cfg_block "top_device", :depth => 16 do > reg "ctrl_reg", :offset => 0, :mode => "RW" > reg "status_reg", :offset => 1, :mode => "R" > end > > I've implemented something but I am not satisfied with it. Hi, I wrote Doodle to do this kind of thing (gem install doodle): require 'doodle' require 'pp' class Register < Doodle::Base has :name has :offset has :mode end class ConfigBlock < Doodle::Base has :name has :depth has :registers, :init => [], :collect => { :reg => Register } end def cfg_block(*args, &block) ConfigBlock(*args, &block) end modules = cfg_block "top_device", :depth => 16 do reg "ctrl_reg", :offset => 0, :mode => "RW" reg "status_reg", :offset => 1, :mode => "R" end pp modules Output: #, #]> If you wanted validation on the parameters, you could do something like: require 'doodle' class Named < Doodle::Base has :name, :kind => String do from Symbol do |sym| sym.to_s end end end class Register < Named has :offset, :kind => Integer do must "be in range 0-15" do |offset| (0..15).include?(offset) end end has :mode, :kind => String do |mode| valid_modes = %w[R W RW] must "be one of #{valid_modes.join(', ')}" do |mode| valid_modes.include?(mode) end end end class ConfigBlock < Named has :depth, :kind => Integer has :registers, :init => [], :collect => { :reg => Register } end def cfg_block(*args, &block) ConfigBlock(*args, &block) end modules = cfg_block :top_device, :depth => 16 do reg :ctrl_reg, :offset => 0, :mode => "RW" reg :status_reg, :offset => 1, :mode => "WR" end #=> memory-map2.rb:35: mode must be one of R, W, RW - got String("WR") (Doodle::ValidationError) Regards, Sean