DSL implementation question

T

tender flake

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", :eek:ffset => 0, :mode => "RW"
reg "status_reg", :eek:ffset => 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__, :eek:ffset...
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
 
J

Jeremy McAnally

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

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", :eek:ffset => 0, :mode => "RW"
reg "status_reg", :eek:ffset => 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__, :eek:ffset...
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
 
S

Sean O'Halpin

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", :eek:ffset => 0, :mode => "RW"
reg "status_reg", :eek:ffset => 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 :eek:ffset
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", :eek:ffset => 0, :mode => "RW"
reg "status_reg", :eek:ffset => 1, :mode => "R"
end

pp modules

Output:

#<ConfigBlock:0xb7b9b5c4
@depth=16,
@name="top_device",
@registers=
[#<Register:0xb7b9582c @mode="RW", @name="ctrl_reg", @offset=0>,
#<Register:0xb7b8ecfc @mode="R", @name="status_reg", @offset=1>]>

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 :eek:ffset, :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, :eek:ffset => 0, :mode => "RW"
reg :status_reg, :eek:ffset => 1, :mode => "WR"
end

#=> memory-map2.rb:35: mode must be one of R, W, RW - got String("WR")
(Doodle::ValidationError)

Regards,
Sean
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

C DSL anyone? 13
a DSL + scope problem 4
DSL help? 4
Help design a plugin system for a DSL 2
Help with the DSL (ish) config class 8
Help : a scoping question 2
Generator implementation 0
Can't get class name 1

Members online

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top