@@ -12,8 +12,11 @@ import (
1212
1313// common holds the information shared by related templates.
1414type common struct {
15- tmpl map [string ][]* Template // Map from name to defined templates.
16- muTmpl sync.RWMutex // protects tmpl
15+ // Map from name to defined templates. There is a slice of templates,
16+ // because there are generations of previously defined templates with the
17+ // same name.
18+ tmpl map [string ][]* Template
19+ muTmpl sync.RWMutex // protects tmpl
1720 option option
1821 // We use two maps, one for parsing and one for execution.
1922 // This separation makes the API cleaner since it doesn't
@@ -91,14 +94,14 @@ func (t *Template) Clone() (*Template, error) {
9194 }
9295 t .muTmpl .RLock ()
9396 defer t .muTmpl .RUnlock ()
94- for k , stack := range t .tmpl {
97+ for k , generations := range t .tmpl {
9598 if k == t .name {
96- nt .tmpl [t .name ] = append (nt .tmpl [t .name ], nt ) // TODO: double-check this - maybe should just be assigning new slice
99+ nt .tmpl [t .name ] = append (nt .tmpl [t .name ], nt )
97100 continue
98101 }
99102 // The associated templates share nt's common structure.
100- for i := range stack {
101- tmpl := stack [i ].copy (nt .common )
103+ for i := range generations {
104+ tmpl := generations [i ].copy (nt .common )
102105 nt .tmpl [k ] = append (nt .tmpl [k ], tmpl )
103106 }
104107 }
@@ -152,8 +155,8 @@ func (t *Template) Templates() []*Template {
152155 t .muTmpl .RLock ()
153156 defer t .muTmpl .RUnlock ()
154157 m := make ([]* Template , 0 , len (t .tmpl ))
155- for _ , stack := range t .tmpl {
156- m = append (m , stack [0 ]) // TODO: runtime assert there is at least one? invariant check
158+ for _ , generations := range t .tmpl {
159+ m = append (m , generations [0 ])
157160 }
158161 return m
159162}
@@ -196,20 +199,20 @@ func (t *Template) Lookup(name string) *Template {
196199 return t .lookup (name , 0 )
197200}
198201
199- func (t * Template ) LookupWithScope (name string , scope int ) * Template {
202+ func (t * Template ) LookupByLevel (name string , level int ) * Template {
200203 if t .common == nil {
201204 return nil
202205 }
203206 t .muTmpl .RLock ()
204207 defer t .muTmpl .RUnlock ()
205- return t .lookup (name , scope )
208+ return t .lookup (name , level )
206209}
207210
208- func (t * Template ) lookup (name string , scope int ) * Template {
209- if scope >= len (t .tmpl [name ]) {
211+ func (t * Template ) lookup (name string , level int ) * Template {
212+ if level < 0 || level >= len (t .tmpl [name ]) {
210213 return nil
211214 }
212- return t.tmpl [name ][scope ] // TODO: invariant check: at least one
215+ return t.tmpl [name ][level ]
213216}
214217
215218// Parse parses text as a template body for t.
@@ -251,10 +254,17 @@ func (t *Template) associate(new *Template, tree *parse.Tree) bool {
251254 // don't replace it with an empty template.
252255 return false
253256 }
254- stack := t .tmpl [new .name ]
255- stack = append (stack , nil )
256- copy (stack [1 :], stack [0 :])
257- stack [0 ] = new
258- t .tmpl [new .name ] = stack
257+
258+ // associating a template with the name of an existing one retains a
259+ // reference to the original, pushing the new one to the front of a slice
260+ // of previously defined templates, so that previously defined templates by
261+ // that name can be accessed by indexing into the slice, each successive
262+ // level being an older generation.
263+ generations := t .tmpl [new .name ]
264+ generations = append (generations , nil )
265+ copy (generations [1 :], generations [0 :])
266+ generations [0 ] = new
267+ t .tmpl [new .name ] = generations
268+
259269 return true
260270}
0 commit comments