[antlr-interest] Organization of complex template structures

Mike Pagel mike at mpagel.de
Sun Dec 21 03:38:17 PST 2008


Nice example!

What you describe and especially the suggested solution does come back 
to the class method analogy: your solution is exactly how multiple 
inheritance is solved in languages like C++. If you have methods (here 
templates) with identical names in two inherited classes (here groups), 
you have to prefix them with the class (here group) name.

I would be careful though to suggest such an approach as multiple 
inheritance does have drawbacks in terms of maintenance.

Since you always can mimic inheritance through composition, your 
template group could simply refer or use the "nautic" as well as the 
"html" group/library. So instead of adding multiple inheritance I would 
rather see a feature to have group "imports" (as done in Java). They 
could trigger the group loading mechanism just done when inheriting a 
group and add the imported group's templates to the namespace of the 
current group. To avoid confusion and name clashes the imported 
templates should require scoping when called, just as done in your example:

---- pseudo template group ----

group myappgroup;

import html;
import nautic;

generate() ::=
<<
...
<html.anchor()>
...
<nautic.anchor()>
...
 >>

---- template group end ----

I think that would be a clean approach without entangling in multiple 
inheritance's diamond of death, which will add benefit by allowing to 
cleanly structure your template libraries.

Mike


Peter Stirling schrieb:
> It appears that the 'expected' use of StringTemplate is that templates 
> used together are all written by a single organisation, if not single 
> programmer, am I wrong in this belief? That composition through 
> inheritance is available, but existing only for replacing elements in 
> ways that both parent and child groups are aware will happen?
>
>
> My understanding of what he has brought up is that template groups 
> don't appear to support programming in-the-large.
>
> I have a web-site, while writing the actual content I also build a 
> library of templates that do html in my style.
>
>     Libraries are good.
>
> If I want to write a second web-site which re-uses these short-cuts 
> then the stringtemplate 'way' is to move the shared elements into 
> their own group and then both sites will need to inherit from this group.
>
> Fictitious example ahoy!
>
> A site creator wishes to use two libraries, one for pure html 
> convenience, the second with useful trivia about all things nautical. 
> Neither library was written by our hapless author.
> StringTemplate currently only offers single-inheritance for group 
> composition, and it should be fairly obvious that these groups do not 
> share a meaningful inheritance relationship (but as StringTemplate 
> only offers single inheritance then you would be forced to linear-ise 
> a relationship between them and the client templates favouring one or 
> the other). Worse is yet to come.
>
> The html library contains a $anchor()$ template which does various 
> sensible things with urls.
>
> The nautical library has a $anchor()$ template that evaluates to 
> description in agonising detail of the various forms of metal hooks 
> used for tethering ships.
>
> By changing the order of inheritance you can decide which template 
> will 'win', but if the goal is to access both in different contexts 
> then your only recourse is a manual rename of one of them. These 
> libraries are unlikely to have been written by the same person 
> (otherwise the names wouldn't conflict) this means that new versions 
> of either library will require our hapless author to find out whether 
> new template name conflicts have occurred and then perform more manual 
> renames (in addition to any that he identified from previous versions).
>
> For this use-case it makes sense (to me) to have a different kind of 
> group that you can inherit from, one that will recognise a prefix 
> (that the client templates will use) that maps to a particular group, 
> from which to return the actual template instance.
>
> Something along the lines of:
>
> bag = new StringTemplateGroupBag()
> bag.put( "ships", new StringTemplateGroup( ... ) );
> bag.put( "html", new StringTemplateGroup( ... ) );
>
> client = new StringTemplateGroup( ... );
> client.setSuperGroup( bag );
>
> And then the client templates can access templates from one or the 
> other with some kind of absolute syntax $/html.anchor()$ perhaps?.
>
> Or am I missing something in the API?
>
> On 21 Dec 2008, at 10:05 am, Mike Pagel wrote:
>
>> Thanks for your explanation. But even if I set aside the class/method
>> analogy: how would I organize my templates then? From what you wrote I
>> basically see that typically a template calls other templates within the
>> same group. So how can I reuse a template for instance across different
>> projects? Copy and paste it into the other project's template group
>> file? Merge this and the other project's group files?
>>
>> You are basically saying that all templates reside in a single group
>> with inheritance being a feature to be used mainly for retargeting, but
>> that's not practical for large scale projects. Other template engines
>> like XPAND (open architectureware), T4 from MS DSL Tools, MD Workbench
>> from Sodius, JET, ... *all* support splitting up your template project
>> into trees of template files that can call each into each other. This
>> way a template that knows how to serialize an attribute to something
>> like "int i" can be used for class attributes as well as for method
>> arguments, without the whole template zoo residing in a single group.
>>
>> Another example: if a want to create the three elements of an MVP style
>> application I will create at least three files, one for the business
>> object model, one for the view and one for the presenter. Would I create
>> three different template groups, one for each file? But how do those
>> groups then share common templates? By (single) inheritance? Or would I
>> have to put all templates into a single group? That's gonna be some 
>> file!
>>
>> Is it really true that ST assumes most of the templates for a given
>> project sit inside a single group?
>>
>> Mike
>>
>>
>>
>> Loring Craymer schrieb:
>>> Your understanding is flawed--template groups are not classes, nor are
>>> templates methods.  Treating them as such is likely to cause you
>>> grief.  Think rather that template groups are a convenience for
>>> argument checking against a template interface.  That way, changing
>>> template groups makes it possible to switch from, say, generating Java
>>> code to C# just by switching template groups.  Template groups are a
>>> mechanism for retargeting.  Switching individual template groups within
>>> an application while leaving others unchanged is not a common usage
>>> pattern.
>>>
>>> Instead of thinking of templates as methods, take a
>>> simpler view:  arguments fill "holes" in templates and the arguments
>>> should be thought of in "instantiated" form.  Thinking of arguments as
>>> dynamically invoked methods misses an important level of abstraction:
>>> argument evaluation is independent of template evaluation and is
>>> side-effect free.  [It is possible to implement side-effects as the
>>> result of evaluation through reflection, but the results are
>>> unpredictable.  Do not do this!]
>>>
>>> It is possible to invoke other
>>> templates in the same group from within a template, but you should see
>>> this as a macro invocation, and the facility as a convenience to allow
>>> factoring.  Almost always, the invoked template is local to the
>>> template group (not declared in the interface).  Such invocations tend
>>> to be uncommon.
>>>
>>> --Loring
>>>
>>>
>>>
>>>
>>> ----- Original Message ----
>>>
>>>> From: Mike Pagel <mike at mpagel.de>
>>>> To: antlr-interest at antlr.org
>>>> Sent: Saturday, December 20, 2008 7:45:01 AM
>>>> Subject: [antlr-interest] Organization of complex template structures
>>>>
>>>> Hi there,
>>>>
>>>> I am wondering how to best go about structuring complex sets of string
>>>> templates. As I understand the current mechanisms, a template group is
>>>> pretty much a class with its templates being the class methods. You 
>>>> can
>>>> build inheritance structures between groups and thereby overriding
>>>> templates (the methods) and call super group (class) templates.
>>>>
>>>> This allows to build up some structure in terms of reusing basic
>>>> templates and if required specialize certain pieces. But in the 
>>>> end, you
>>>> always call a template (method) that is part of or being inherited 
>>>> by a
>>>> specific leaf template group (class). Once the thread of control is
>>>> within a template group there is no means to call templates in other
>>>> groups, except for the groups which belong to inheritance line of the
>>>> leaf group (if I'm not missing anything).
>>>>
>>>> So far I find this limiting, e.g. if my model describes (Java) classes
>>>> and I want to generate the class code. Then my leaf template group may
>>>> be a "class.stg" with all kinds of templates like "generateMethods()"
>>>> and "generateAttributes()". The implementation of those template now
>>>> should invoke templates from a group "Methods.stg" and another group
>>>> "Attributes.stg". (This example may not be pressing the issue but it's
>>>> easy to follow.)
>>>>
>>>> Now I cannot derive "Class.stg" from both other groups, nor can I
>>>> somehow call into these groups (like calling static members 
>>>> functions of
>>>> another class in code). What would be a good way to express this with
>>>> the current mechanisms or is there actually a limitation?
>>>>
>>>> Thanks a lot,
>>>> Mike
>>>>
>>>> List: http://www.antlr.org/mailman/listinfo/antlr-interest
>>>> Unsubscribe:
>>>> http://www.antlr.org/mailman/options/antlr-interest/your-email-address
>>>>
>>>
>>>
>>>
>>>
>>>
>>> List: http://www.antlr.org/mailman/listinfo/antlr-interest
>>> Unsubscribe: 
>>> http://www.antlr.org/mailman/options/antlr-interest/your-email-address
>>>
>>
>> List: http://www.antlr.org/mailman/listinfo/antlr-interest
>> Unsubscribe: 
>> http://www.antlr.org/mailman/options/antlr-interest/your-email-address
>


More information about the antlr-interest mailing list