Move frameStack into env.go and the name steps of resolveTemplates into name.go, and hold a binding's target in a named field
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/larvit/fejkdata/internal/builtinfunc"
|
||||
"github.com/larvit/fejkdata/internal/grammar"
|
||||
)
|
||||
|
||||
@@ -30,7 +31,7 @@ type nameBinding struct {
|
||||
binder *template
|
||||
|
||||
// Filled by `resolveTemplates`, once every check it runs passed:
|
||||
nameTarget
|
||||
target nameTarget
|
||||
// addressed is every key a read of the name lands on or passes, the spelling of the
|
||||
// first read reaching it beside it; a pick keeps the draws at these keys, and only these.
|
||||
addressed map[pickKey]string
|
||||
@@ -45,6 +46,13 @@ type nameUse struct {
|
||||
operand, noRef, nested bool
|
||||
}
|
||||
|
||||
// nameTarget is what a binding resolves to in the assembled tree: start, the node its head names, and
|
||||
// the path it reads into that node.
|
||||
type nameTarget struct {
|
||||
start node
|
||||
tail []string
|
||||
}
|
||||
|
||||
// bindsField reports whether b binds a path into a field, so a read of it stays in the category.
|
||||
func (b *nameBinding) bindsField() bool { return !grammar.IsRef(b.ref) }
|
||||
|
||||
@@ -257,3 +265,54 @@ func namedReads(t *template) []namedReadAt {
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// nameTargets resolves what each binding of ts binds, from its binder's references.
|
||||
func nameTargets(ts []templateSite) map[*nameBinding]nameTarget {
|
||||
targets := map[*nameBinding]nameTarget{}
|
||||
for _, s := range ts {
|
||||
for _, tok := range s.t.tokens {
|
||||
if tok.Kind == grammar.NameBind {
|
||||
a := splitArm(tok.BoundRef, s.t.refs.byName)
|
||||
targets[s.t.nameScope.bindings[tok.Bound]] = nameTarget{start: s.t.startOf(a.head), tail: a.tail}
|
||||
}
|
||||
}
|
||||
}
|
||||
return targets
|
||||
}
|
||||
|
||||
// addressedKeys is every key the reads of each name in ts land on or pass, from the name's own
|
||||
// level, with the spelling of the first read reaching it.
|
||||
func addressedKeys(ts []templateSite, targets map[*nameBinding]nameTarget) map[*nameBinding]map[pickKey]string {
|
||||
keys := map[*nameBinding]map[pickKey]string{}
|
||||
for _, s := range ts {
|
||||
for _, r := range namedReads(s.t) {
|
||||
b := r.a.named
|
||||
if keys[b] == nil {
|
||||
keys[b] = map[pickKey]string{}
|
||||
}
|
||||
for _, key := range r.a.levels[len(targets[b].tail):] {
|
||||
if _, seen := keys[b][key]; !seen {
|
||||
keys[b][key] = r.a.spelling
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
func nameUses(ts []templateSite) map[*nameBinding][]nameUse {
|
||||
uses := map[*nameBinding][]nameUse{}
|
||||
for _, s := range ts {
|
||||
for _, r := range namedReads(s.t) {
|
||||
b := r.a.named
|
||||
uses[b] = append(uses[b], nameUse{
|
||||
tail: grammar.JoinSegments(r.a.tail),
|
||||
in: s.t,
|
||||
operand: r.operand,
|
||||
noRef: r.operand && builtinfunc.NoRefOperands(r.o.Fn),
|
||||
nested: s.t.nameScope != b.scope,
|
||||
})
|
||||
}
|
||||
}
|
||||
return uses
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user