From: Jeremy McAnally Date: 2008-04-04T13:14:42+09:00 Subject: Re: DSL implementation question You'd do something like this: def cfg_block(name, params={}, &block) # Other stuff my_obj.instance_eval &block end ...where my_obj is the object that you were previously yielding. :) --Jeremy On Thu, Apr 3, 2008 at 11:49 PM, 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. > > The problem I have is about scoping. How can I make the reg command > in my > small DSL exemple above execute in the context of the object created > by the > cfg_block method? The way I implemented this is by passing the > created > cfg_block object as a block parameter and then passing it to every reg > command. E.g: > > cfg_block "top_device", :depth => 16 do |__dev__| > reg "ctrl_reg", __dev__, :offset... > end > > I consider this redundant since I'd like the context to provide the > cfg_block reference. I tried multiple things but haven't figured it > out > using blocks. Is there a way to get rid of __dev__? > > Suggestions would be greatly appreciated. Thanks in advance. > > My implementation follows below: > > module Register_defs > > class Cfg_Block < Hash > > def initialize(name, params={}) > self[:name] = name > self[:regs] = {} > self.merge!(params) > end > > def add_reg(reg) > self[:regs][reg[:name]] = reg > end > > end > > class Register < Hash > def initialize(name, cfg_block, params={}) > self[:name] = name > self.merge!(params) > cfg_block.add_reg(self) > end > > end > > def cfg_block(name, params={}) > cfg_block = Cfg_Block.new(name, params) > yield(cfg_block) > cfg_block > end > > def reg(name, cfg_block, params={}) > reg = Register.new(name, cfg_block, params) > yield(reg) > reg > end > > end > > include Register_defs > > modules = cfg_block "top_block" do |cb| > > reg "reg1", cb, :addr => 0 do > # do something > end > > reg "reg2", cb, :addr => 0 do > # do something else > end > > end > > p modules > > > > > > -- http://jeremymcanally.com/ http://entp.com Read my books: Ruby in Practice (http://manning.com/mcanally/) My free Ruby e-book (http://humblelittlerubybook.com/) Or, my blogs: http://mrneighborly.com http://rubyinpractice.com