[stringtemplate-interest] [ST4 Beta4] Default args are not always evaluated in the context of their template

Udo Borkowski ub at abego-software.de
Thu Feb 17 12:45:27 PST 2011


> ... Remember you are passing the template and not its evaluated
> result to t2. ...

Yes, that's the way the stuff is currently implemented. But passing the subtemplate to t2 is not the issue. I can (and want to) pass the template around and still get the result I expect. It is mainly the question in what context the subtemplate is evaluated later. If it is the context of the template it was defined in everything would be fine.

And this is what I understood when reading Terence's comment "default args … have the same context of the template itself". Why did he mentioned this explicitly if not there is something special about the way default args are handled?

Currently it looks to me (after my tests) like an anonymous templates used in a default args is not handled differently from an anonymous templates defined somewhere else, especially regarding the way names are resolved: names are resolved dynamically when the subtemplate is evaluated, looking up the call chain. Of cause this also means the arguments of the template are visible to the subtemplates (i.e. there is no need to mention explicitly that "default arguments can see the other arguments).


> If you want to pass the evaluated result to t2, you need to
> use parentheses (the "tostring" operator) as follows:

…
> <t2(p1="B",p2=(p2))>
>> 


OK, that would also be possible. However I want to avoid "toString" whenever possible: 
a) maybe p2 is never used later (because of some "if" or so) then the "toString" would have been a waste of time. 
b) calling toString to early may get you in trouble when it comes to formatting/indenting.

Also: here the "toString" is introduced to fix an issue with the default arg. I.e. I need to change my template body just because I added a default value to a parameter (assume the template was first used without default args).


Udo



On 17.02.2011, at 15:45, Sam Harwell wrote:

> That's correct. Remember you are passing the template and not its evaluated
> result to t2. If you want to pass the evaluated result to t2, you need to
> use parentheses (the "tostring" operator) as follows:
> 
> t1(p1,p2={<p1>}) ::= <<
>  inside t1: p1=<p1>, p2=<p2>
> <t2(p1="B",p2=(p2))>
>>> 
> 
> Sam
> 
> -----Original Message-----
> From: stringtemplate-interest-bounces at antlr.org
> [mailto:stringtemplate-interest-bounces at antlr.org] On Behalf Of Udo
> Borkowski
> Sent: Thursday, February 17, 2011 5:04 AM
> To: stringtemplate-interest List
> Subject: [stringtemplate-interest] [ST4 Beta4] Default args are not always
> evaluated in the context of their template
> 
> Ter wrote in a recent mail:
> 
>> In ST v4, the default args are formally defined to have the same context
> as the template itself, hence, default arguments can see the other
> arguments.
>> 
> 
> 
> Based on this I expected the default args are also evaluated in the context
> of the template, e.g. if t1 is defined as
> 
> 	t1(p1,p2={<p1>}) ::= <<.>>
> 
> and I call
> 
> 	<t1(p1="A")>
> 
> p1 and p2 both will have the value "A". 
> 
> As it turns out this is not always the case.
> 
> 
> When the name "p1" is later used in a different template called inside of t1
> the new value of p1 is also applied to the default arg (and not the value
> defined in the context of t1). 
> 
> Here a complete example:
> 
> -----------
> t1(p1,p2={<p1>}) ::= <<
>  inside t1: p1=<p1>, p2=<p2>
> <t2(p1="B",p2=p2)>
>>> 
> 
> t2(p1,p2) ::= <<
>  inside t2: p1=<p1>, p2=<p2>
>>> 
> 
> main() ::= <<
> Use default value for p2
> <t1(p1="A")>
>>> 
> ------------
> 
> This will output:
> -------------
> Use default value for p2
>  inside t1: p1=A, p2=A
>  inside t2: p1=B, p2=B
> ----------
> 
> However I had expected:
> -------------
> Use default value for p2
>  inside t1: p1=A, p2=A
>  inside t2: p1=B, p2=A
> ----------
> 
> i.e. I expected p2 to be "A" in the template t2, too, as this is the default
> value defined in the context of t1.
> 
> It looks like the names in a default value expression/subtemplate are
> resolved the "normal" way by dynamically looking up the call chain for the
> name, starting "at the current scope", i.e. "the point when the default
> value template is currently expanded". I expected the lookup starts with the
> template argument definition in t1(p1,p2={<p1>}). If this fails a "normal"
> lookup may be performed.
> 
> I know one could "fix" the above example by changing the definition of t1
> from
> 
> 	t1(p1,p2={<p1>}) ::= <<.>>
> to 
> 	t1(p1,p2={<(p1)>}) ::= <<.>>
> 
> i.e. force to "stringify" the default value in the argument definition. 
> 
> However 
> a) I am not sure if this is obvious for the "casual user".  (BTW: is this
> "{<(p1)>}" behavior documented somewhere? I learned this by reading the
> source code.)
> 
> b) this does not work in all cases. E.g. the template definition
> 
> 	t3(p1,p2={<p1>x}) ::= <<.>>
> 
> (i.e. append an "x" to the value of p1 to create p2) could not be fixed this
> way.
> 
> 
> To fix the issue I assume one needs to remember the context of the default
> value subtemplate (i.e. the argument list) with the subtemplate instance and
> check this context first before doing the normal dynamic name lookup.
> 
> 
> Udo
> 
> _______________________________________________
> stringtemplate-interest mailing list
> stringtemplate-interest at antlr.org
> http://www.antlr.org/mailman/listinfo/stringtemplate-interest
> 



More information about the stringtemplate-interest mailing list