In article [email protected],
Robert K. [email protected] wrote:
pnew.call
’ a
block?
There is one way: you can use instance_eval with a block. This
essentially just rebinds self but this is good enough often.
Your example (even if the rebinding part worked) would likely suffer
from a different problem: a is not known as local variable in the
block so the compilation would probably not create code that reads the
local variable a.
Right, that’s why instance_eval doesn’t work for this case either.
Often there are alternative approaches, such as providing an argument
to the block that makes certain data accessible.
True. And that might be a possibility.
If you have a use
case in mind I’d be glad to try to come up with more suggestions.
Mainly I’m trying to make a DSL look prettier and reduce duplication.
The DSL is for simulating chip designs (RHDL).
I was going to have the user define a circuit, or logic gate, like so:
class AndGate < RHDL
inputs :a, :b
outputs :out
define_behavior { out << a & b }
end
And that particular gate definition would work, however given a
different case:
class Counter < RHDL
inputs :clk, :rst
outputs :count_out
variables :count=>0
define_behavior {
process(clk) {
if clk.event and clk == 1
if rst == 1
count = 0
else
count += 1
end
count_out << count
end
}
}
end
Now we have a problem, but I’ll have to explain a lot before I can get
to
that…
The ‘inputs’ and ‘outputs’ methods create accessors for instance vars so
that
in the define_behavior block with follows the user can refer to what
will be
instance variables without needing to append ‘@’ to them (they’re
accessed via
methods). It’s an aesthetics issue: I didn’t want the user to have to
know
about instance vars and appanding ‘@’. It seems to work well.
However, notice the ‘variables’ method. The idea there is that there
could be
some variables used in the define_behavior block (and this was the case
with
the previous incarnation of RHDL, so I didn’t want to lose that
functionality).
Now by ‘variable’ here I mean that I want a variable that also has scope
within the define_behavior block. The define_behavior block will be
called
many, many times during a simulation and I don’t want the variable to be
re-initialzed on each call. It’s a bit like:
def counter(init)
count = init
lambda { count += 1 }
end
count_val = counter(2)
count_val.call #=> 3
count_val.call #=> 4…
Ok, so now the issue is that the block being passed to define_method
above
might need to refer to a ‘variable’ (from the variables list), but the
problem
is that those variables don’t exist yet when the block gets constructed
or
evaluated (or whatever we call what happens when ‘{…}’ is
encountered).
I could make the user provide arguments to the block as you mentioned:
class Counter < RHDL
inputs :clk, :rst
outputs :count_out
variables :count=>0
define_behavior {|count|
#....
}
end
But they would be repeating themselves, no? 
So that’s why I was trying to dynamically create a method that would
have the
variables in the scope of the method and then the proc bound to that
scope.
I suppose another way to do it would be to do:
class Counter < RHDL
inputs :clk, :rst
outputs :count_out
def initialize
count = 0
define_behavior {
#.... do something with count ...
}
end
end
This is sort of how RHDL is now. There’s no need for a ‘variables’
method
since you just declare your variables in the ‘initialize’ method. I was
trying
to get away from the explicit ‘initialize’ definition. But maybe it’s
not
such a bad thing. ‘count’ would then be available to the block passed
to
define_behavior.
The other alternative is the one that Jim F. mentioned:
class Counter < RHDL
inputs :clk, :rst
outputs :count_out
variables :count=>0, :foo=>42
define_behavior %q{
#.... do something with count, foo ...
}
end
In that case defne_behavior takes a string instead of a block. That
solves the
problem because the string can be evaluated later in different contexts.
But the ‘%q’ is kind of ugly 
So it’s a matter of tradeoffs… The other thing to keep in mind is that
I want
to make it fairly easy to translate this DSL to another language (VHDL).
Having the explicit ‘variables’ declaration would probably make that
easier
because it matches VHDL’s semantics& syntax very closely.
Phil