Files
fejkdata/holdset.go
T

75 lines
1.9 KiB
Go

package fejkdata
import (
"strings"
)
// holdSet is one render's reference draws: the unnamed draw group's, and each named one's.
type holdSet struct {
unnamed hold
named map[string]*hold
}
// renderScope is where a render reads its reference paths: a hold set, in the draw group of the
// template rendering, and the pin set a table's columns read their row from: a whole read's own,
// else the hold's. It passes by value, and what is read from it reaches a map key, an interface or
// a func value only as a copy; else sc, and with it every render's hold set, moves to the heap.
type renderScope struct {
set *holdSet
group string
pins *pinSet
}
func eagerHoldSet() holdSet {
return holdSet{unnamed: hold{variant: map[string]node{}, value: map[string]draw{}}}
}
// renderOnce renders n as one render, over a hold set of its own.
func renderOnce(s *session, n node) string {
var set holdSet
return render(s, n, renderScope{set: &set})
}
// expandAnew expands one repeat iteration of t as a render of its own, in no group. Inlined into
// render's loop, its hold set would move to the heap.
//
//go:noinline
func expandAnew(s *session, t *template) string {
var set holdSet
if s.trace != nil {
s.trace.repeatDepth++
defer func() { s.trace.repeatDepth-- }()
}
return expand(s, t, renderScope{set: &set})
}
// in is the scope t renders in: its draw group where it names one, else its caller's.
func (sc renderScope) in(t *template) renderScope {
if t.drawGroupKey != "" {
sc.group = t.drawGroupKey
}
return sc
}
func (sc renderScope) rows() *pinSet {
if sc.pins != nil {
return sc.pins
}
return &sc.hold().pins
}
func (sc renderScope) hold() *hold {
if sc.group == "" {
return &sc.set.unnamed
}
d, drew := sc.set.named[sc.group]
if !drew {
if sc.set.named == nil {
sc.set.named = map[string]*hold{}
}
d = &hold{variant: map[string]node{}, value: map[string]draw{}}
sc.set.named[strings.Clone(sc.group)] = d
}
return d
}