From: tender flake Date: 2008-04-04T12:49:09+09:00 Subject: DSL implementation question 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