Refuse a name read once only when read whole, and name every way out in the scope and draw-group refusals
This commit is contained in:
+1
-1
@@ -15,7 +15,7 @@ replacement, and each removed path, column or flag.
|
|||||||
`repeat` binds picks again on every iteration. Refused at `New`: a name bound twice
|
`repeat` binds picks again on every iteration. Refused at `New`: a name bound twice
|
||||||
outside any `repeat`, twice in one `repeat`, or both inside a `repeat` and outside it; a
|
outside any `repeat`, twice in one `repeat`, or both inside a `repeat` and outside it; a
|
||||||
name that is a field or an option; a binding of anything but a reference; a binding in a
|
name that is a field or an option; a binding of anything but a reference; a binding in a
|
||||||
choice's item; a binding nothing reads, or one read once, which the reference spells; a
|
choice's item; a binding nothing reads, or one read once whole, which the reference spells; a
|
||||||
path through a name that selects a row; a read of a name rendering a field twice where a
|
path through a name that selects a row; a read of a name rendering a field twice where a
|
||||||
path through the name reads it; reads of a name in two draw groups, or inside a
|
path through the name reads it; reads of a name in two draw groups, or inside a
|
||||||
`repeat`, where what it names reads a reference path; and a binding in a table. A field, column,
|
`repeat`, where what it names reads a reference path; and a binding in a table. A field, column,
|
||||||
|
|||||||
@@ -731,8 +731,8 @@ Rejected at load, each error naming what to write instead:
|
|||||||
- a name that is a field or an option;
|
- a name that is a field or an option;
|
||||||
- a binding of anything but a reference;
|
- a binding of anything but a reference;
|
||||||
- a binding in a choice's item, which every other item would leave unbound;
|
- a binding in a choice's item, which every other item would leave unbound;
|
||||||
- a binding nothing reads, or read once outside a `repeat`, which the reference spells:
|
- a binding nothing reads, or read once whole outside a `repeat`, which the reference
|
||||||
`{/word as w}{w}` is `{/word}`, and `{/word as w}{w.x}` is `{/word.x}`;
|
spells: `{/word as w}{w}` is `{/word}`;
|
||||||
- a path through a name that selects a row;
|
- a path through a name that selects a row;
|
||||||
- a read of a name rendering a field twice, where a path through the name reads it;
|
- a read of a name rendering a field twice, where a path through the name reads it;
|
||||||
- reads of a name in two draw groups, or inside a `repeat`, where what it names reads a
|
- reads of a name in two draw groups, or inside a `repeat`, where what it names reads a
|
||||||
|
|||||||
@@ -297,6 +297,9 @@ func checkBind(t formatToken) error {
|
|||||||
if _, _, err := refShape(ref); err != nil {
|
if _, _, err := refShape(ref); err != nil {
|
||||||
return fmt.Errorf("token {%s}: %w", t.body, err)
|
return fmt.Errorf("token {%s}: %w", t.body, err)
|
||||||
}
|
}
|
||||||
|
if name == "" {
|
||||||
|
return fmt.Errorf("token {%s}: a binding names nothing; write {%s as n}", t.body, ref)
|
||||||
|
}
|
||||||
if isOption(name) {
|
if isOption(name) {
|
||||||
return fmt.Errorf("token {%s}: %q is an option and can never be a name", t.body, name)
|
return fmt.Errorf("token {%s}: %q is an option and can never be a name", t.body, name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,11 +138,8 @@ func (sc *nameScope) settle() error {
|
|||||||
if len(b.uses) == 0 {
|
if len(b.uses) == 0 {
|
||||||
return fmt.Errorf("%stoken {%s}: nothing reads name %q; drop the token", b.where, b.body, b.name)
|
return fmt.Errorf("%stoken {%s}: nothing reads name %q; drop the token", b.where, b.body, b.name)
|
||||||
}
|
}
|
||||||
if r := b.uses[0]; len(b.uses) == 1 && !r.nested {
|
if r := b.uses[0]; len(b.uses) == 1 && r.tail == "" && !r.nested {
|
||||||
spelling := b.ref
|
spelling := b.ref
|
||||||
if r.tail != "" {
|
|
||||||
spelling += "." + r.tail
|
|
||||||
}
|
|
||||||
if !r.operand {
|
if !r.operand {
|
||||||
spelling = "{" + spelling + "}"
|
spelling = "{" + spelling + "}"
|
||||||
}
|
}
|
||||||
@@ -203,9 +200,18 @@ func resolveReads(n node, where, group string, scopes []*nameScope) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// unresolved is the refusal of u, a read no field or name answers: naming the names the read sees,
|
// unresolved is the refusal of u, a read no field or name answers: naming the repeat binding the
|
||||||
// else the repeat binding the name where the read cannot see it.
|
// name where the read cannot see it, else the names the read sees.
|
||||||
func unresolved(where string, u unboundRead, seen *nameScope, scopes []*nameScope) error {
|
func unresolved(where string, u unboundRead, seen *nameScope, scopes []*nameScope) error {
|
||||||
|
for _, sc := range scopes {
|
||||||
|
if b, ok := sc.bindings[u.head]; ok {
|
||||||
|
at := strings.TrimSuffix(b.where, ": ")
|
||||||
|
if at == "" {
|
||||||
|
at = "the root template"
|
||||||
|
}
|
||||||
|
return fmt.Errorf("%s%w; name %q is bound inside the repeat at %s, which a read outside the repeat cannot see; bind it outside the repeat to read one pick on every line", where, u.err, u.head, at)
|
||||||
|
}
|
||||||
|
}
|
||||||
var visible []string
|
var visible []string
|
||||||
for sc := seen; sc != nil; sc = sc.up {
|
for sc := seen; sc != nil; sc = sc.up {
|
||||||
for _, b := range sc.order {
|
for _, b := range sc.order {
|
||||||
@@ -216,11 +222,6 @@ func unresolved(where string, u unboundRead, seen *nameScope, scopes []*nameScop
|
|||||||
sort.Strings(visible)
|
sort.Strings(visible)
|
||||||
return fmt.Errorf("%stoken {%s}: no field or name %q; the names bound here are %v", where, u.body, u.head, visible)
|
return fmt.Errorf("%stoken {%s}: no field or name %q; the names bound here are %v", where, u.body, u.head, visible)
|
||||||
}
|
}
|
||||||
for _, sc := range scopes {
|
|
||||||
if b, ok := sc.bindings[u.head]; ok {
|
|
||||||
return fmt.Errorf("%s%w; name %q is bound inside the repeat at %s, which a read outside the repeat cannot see; bind it outside the repeat to read one pick on every line", where, u.err, u.head, strings.TrimSuffix(b.where, ": "))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fmt.Errorf("%s%w", where, u.err)
|
return fmt.Errorf("%s%w", where, u.err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,7 +273,7 @@ func linkNames(path string, t *template) error {
|
|||||||
func linkName(t *template, a *arm) error {
|
func linkName(t *template, a *arm) error {
|
||||||
b := t.nameScope.lookup(a.head)
|
b := t.nameScope.lookup(a.head)
|
||||||
if hasSelector(a.tail) {
|
if hasSelector(a.tail) {
|
||||||
return fmt.Errorf("a path through name %q selects no row; read it directly, {%s.%s}, or bind the row to a name of its own", a.head, b.ref, joinSegments(a.tail))
|
return fmt.Errorf("a path through name %q may not select a row; read it directly, {%s.%s}, or bind the row to a name of its own", a.head, b.ref, joinSegments(a.tail))
|
||||||
}
|
}
|
||||||
full := append(b.tail[:len(b.tail):len(b.tail)], a.tail...)
|
full := append(b.tail[:len(b.tail):len(b.tail)], a.tail...)
|
||||||
if err := checkPathResolves(b.head, full, a.head); err != nil {
|
if err := checkPathResolves(b.head, full, a.head); err != nil {
|
||||||
@@ -327,10 +328,10 @@ func (b *nameBinding) checkUses() error {
|
|||||||
}
|
}
|
||||||
for _, u := range b.uses {
|
for _, u := range b.uses {
|
||||||
if u.nested {
|
if u.nested {
|
||||||
return fmt.Errorf("name %q is read inside a repeat, and what it names reads a reference path, which each iteration draws apart; bind the name inside the repeat", b.name)
|
return fmt.Errorf("name %q is read inside a repeat, and what it names reads a reference path, which each iteration draws apart; bind the name inside the repeat, or bind a second name there", b.name)
|
||||||
}
|
}
|
||||||
if u.group != b.uses[0].group {
|
if u.group != b.uses[0].group {
|
||||||
return fmt.Errorf("name %q is read in two draw groups, %s and %s, and what it names reads a reference path, which each draw group draws apart; read the name in one draw group", b.name, groupSpelling(b.uses[0].group), groupSpelling(u.group))
|
return fmt.Errorf("name %q is read in two draw groups, %s and %s, and what it names reads a reference path, which each draw group draws apart; read the name in one draw group, or bind a name in each", b.name, groupSpelling(b.uses[0].group), groupSpelling(u.group))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Reference in New Issue
Block a user