Traversing the contents of a proc (for a DSL)

Hi List,

Is it possible to traverse and modify the statements inside a Proc
after it has been created?

I’m playing with a small DSL for HTML, which should look like this.

html {
head { title {“Hello World”} }
body {
h1 { “hello”}
p {
“text body”
“more text”
}
}
}

If it is possible to recursively traverse through the statements in
each block, I could join the lines together with the + operator, and
the implementation would be fairly easy - just recursive calls that
return text. But it does not look like this is possible…

An alternative would be to create a new object for each node in the
HTML (eg body or h1), and let each method call inside this node assign
its content to an array there. Less functional style and more
overhead, but doable. But this requires either that I catch the
creation of new strings (no idea if that is possible) for them to be
added to the node as well, or that I introduce a new method to create
strings.

Any comments highly appreciated!

cheers,
Siemen

Generally - no. A proc is compiled code, it doesn’t remember its own
source
code. There are libraries that provide some deeper introspection tools
– like
the ParseTree / Ruby2Ruby libraries. Also, there are several DSLs very
simllar
to what you’re talking about already – check out Markaby:

http://markaby.rubyforge.org/

On Sun, Nov 15, 2009 at 6:32 PM, Kyle [email protected] wrote:

Generally - no. A proc is compiled code, it doesn’t remember its own source
code. There are libraries that provide some deeper introspection tools –
like
the ParseTree / Ruby2Ruby libraries. Also, there are several DSLs very
simllar
to what you’re talking about already – check out Markaby:

http://markaby.rubyforge.org/

Thanks! The two introspection libs look really interesting.

I know that there are plenty of templating tools available. But I’m just
playing around with DSLs and chose HTML because it is such a well-known
domain with familiar problems.

For this little exercise, I’ll go with the solution with the extra
method
for text and objects for each node that I sketched because it has no
external dependencies…

cheers,

Siemen

On Nov 15, 2009, at 09:32 , Kyle wrote:

Generally - no. A proc is compiled code, it doesn’t remember its own source
code. There are libraries that provide some deeper introspection tools – like
the ParseTree / Ruby2Ruby libraries. Also, there are several DSLs very simllar
to what you’re talking about already – check out Markaby:

http://markaby.rubyforge.org/

agreed… except don’t look at markaby. It is overly complicated and
overly clevar (and slow as a result). Look at Ara’s tagz. Excellent
implementation.

On Nov 15, 2009, at 4:32 PM, Ryan D. wrote:

http://markaby.rubyforge.org/

agreed… except don’t look at markaby. It is overly complicated and
overly clevar (and slow as a result). Look at Ara’s tagz. Excellent
implementation.

Markaby is also Ruby 1.8 only, though I can’t figure out why. Some of
the clevarness kind of fails to be portable.

Regards,
Florian

On Nov 15, 2009, at 12:01 , Siemen B. wrote:

Thanks! The two introspection libs look really interesting.

I know that there are plenty of templating tools available. But I’m just
playing around with DSLs and chose HTML because it is such a well-known
domain with familiar problems.

The point wasn’t (necessarily) to use them, but to study them. You
simply don’t need to traverse the proc to do what you want to do.

Example (one of several variants):

end

end
end

PseudoLisp.convert do
happy
sad 42
end

#=> (happy)
#=> (sad 42)

On Mon, Nov 16, 2009 at 1:50 AM, Ryan D.
[email protected]wrote:

don’t need to traverse the proc to do what you want to do.

Yes, I will definitely have a look at them!

end

end
end

PseudoLisp.convert do
happy
“string created”
sad 42
end

#=> (happy)
#=> (sad 42)

Thanks a lot for the example!

There is one caveat with it - I also need to catch the creation of
strings.
Of course I can work around this by using a method call to construct
text
(eg text “text body”). Hm… maybe I can also hook into something with
ObjectSpace or String.new; I have to check that out when I come back to
my
dev machine…

– Siemen

PS. It looks like I’m always double posting for some reason, my
apologies,
List… I’ll hope it is fixed now…

PS. It looks like I’m always double posting for some reason, my apologies,
List… I’ll hope it is fixed now…

Are you posting form Google mail? For some reason that I don’t
understand, my posts always look double posted to me, but are only
actually posted the once.


Paul S.
http://www.nomadicfun.co.uk

[email protected]

Siemen B. wrote:

I’m playing with a small DSL for HTML, which should look like this.

html {
head { title {“Hello World”} }
body {
h1 { “hello”}
p {
“text body”
“more text”
}
}
}

If it is possible to recursively traverse through the statements in
each block, I could join the lines together with the + operator, and
the implementation would be fairly easy - just recursive calls that
return text. But it does not look like this is possible…

Two string literals on the same line are concatenated - so in the above
example you could get away with a simple pre-processor that joins the
lines together in the right places.

“foo” “bar”
=> “foobar”

However this won’t work for

str1
str2

If this is what you want - i.e. each expression appearing on a line of
its own has its value sent to the output string - then probably native
Ruby is not the right tool. HAML, ERB and Cucumber are examples of DSLs
where a non-Ruby syntax fits better.

On Mon, Nov 16, 2009 at 1:19 PM, Paul S. [email protected]
wrote:

Are you posting form Google mail? For some reason that I don’t
understand, my posts always look double posted to me, but are only
actually posted the once.

Yes I am, and it still looks like they are double-posted. Yours do not
to
me. Sounds reasonable, there is probably something weird going on with
its
conversation view algorithm…

On Mon, Nov 16, 2009 at 1:51 PM, Brian C. [email protected]
wrote:

}

lines together in the right places.
If this is what you want - i.e. each expression appearing on a line of
its own has its value sent to the output string - then probably native
Ruby is not the right tool. HAML, ERB and Cucumber are examples of DSLs
where a non-Ruby syntax fits better.

Yes. Again, this is more an exercise to see what can be done with an
inline
DSL, so I’ll just stick with what I got.

It would have been quite easy with Lisp though, as I would have access
to
each line and join them … But apart from that, I’m not fluent with Lisp
:slight_smile: