Closed Lewix closed 10 years ago
Why do we mix src and raw? I guess src should be used in every place.
LGTM.
@tiarkrompf Can we merge this?
One thing I want to make sure is that we are not going to quadratic complexity by repeatedly copying generated strings from nested blocks. How is this handled?
It also seems emitBlock
is called implicitly, but getBlockResult
is still explicit. I would suggest to swap it. emitBlock
is a recursive call, and I think we should keep those visible.
No, the strings are not copied when generating nested blocks. A string such as:
// context
$block
// more context
Gets broken into a list of context parts (["// context\n", "\n// more context"]
) and a list of arguments ([block]
). The gen
string interpolator will interleave printing the contexts and the arguments to stream
, as you would expect. However if it encounters an Block[_]
argument, instead of calling stream.println
, it simply calls emitBlock
. This way, the emitBlock
method does the printing rather than gen
having to copy the string produced by emitBlock
into the stream.
The code where this is handled is in GenericNestedCodeGen
and GenericCodeGen
.
I agree it would be better to have emitBlock
explicit and getBlockResult
implicit, but I'm not sure if that's possible. I would need emitBlock(block)
to be passed to the string evaluator by name, but I get a "no by-name parameter type allowed here" error if I try to.
Thanks for clarifying -- sounds good.
For emitBlock
, maybe we can do something like this:
${nestedBlock(block}}
And have nestedBlock
create a thunk, i.e. a dummy object that wraps the block, and then call emitBlock
as before when we process that object later.
Ok, how about using a case class called NestedBlock
. Then the code becomes:
gen"""val $sym = {
|${NestedBlock(b)}
|$b
|}"""
I have a slight preference for a method as the public API for reasons of modularity: you can override a method in a subtrait, but you cannot override a case class.
I just noticed a missing $
sign in ArrayOps.scala
due to my last commit. It should say out(i) = $blk
. The timing is unfortunate, so would you like me to submit another PR? It might be simpler for you to just add the $
yourself. Sorry about this.
Just submit another pull request as that is the usual policy.
The changes in this pull request add two string interpolators,
gen
andsrc
, which simplify writing code generation cases. Both of the interpolators automate:On top of this,
gen
callsstream.println
on the strings andemitBlock
on any blocks. The result is that code such as:Now looks like this: