Skip to content

Commit

Permalink
fix non-section cross-doc number range ordering
Browse files Browse the repository at this point in the history
  • Loading branch information
mandelsoft committed Jan 7, 2023
1 parent fb98325 commit 61940a2
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 70 deletions.
9 changes: 6 additions & 3 deletions doc/examples.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@

<a/><a id="/examples"/><a id="section-1"/>
## 4 Examples
This document shows example for the <a href="syntax.md#/syntax">generator syntax</a>
This document shows examples for the <a href="syntax.md#/syntax">generator syntax</a>

<a/><a id="filestructure"/><a id="section-1-1"/>
### 4.1 Filestructure
&nbsp;&nbsp;&nbsp;&nbsp; [2-a A typical source tree](syntax.md#tree)<br>
&nbsp;&nbsp;&nbsp;&nbsp; [2-b A typical source document](syntax.md#example)<br>
&nbsp;&nbsp;&nbsp;&nbsp; [2-c Anchors in scoped environments](syntax.md#anchors)<br>
&nbsp;&nbsp;&nbsp;&nbsp; [2-d The Figure Number Range used in this Documentation](syntax.md#nr)<br>
&nbsp;&nbsp;&nbsp;&nbsp; [3-a Explicit Table of Contents for Linked Documents](statements.md#reftoc)<br>
3 changes: 2 additions & 1 deletion scanner/resolution.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,10 +374,11 @@ func LinkFor(ri RefInfo, preferred ...string) utils2.Link {
type Unscoped interface {
GetDocument() Document
GetParentDocument() Document
GetRootContext() ResolutionContext
GetDocumentForLink(l utils2.Link) Document

NextId(typ string) labels.Rule
RequestDocument(link utils2.Link, d Document) error
RequestDocument(link utils2.Link, location Location) error
RequestNumberRange(typ string)
GetNumberRange(typ string) NumberRange
SetNumberRangeFor(d Document, id TaggedId, typ string, nr NumberRange) HierarchyLabel
Expand Down
6 changes: 3 additions & 3 deletions src/examples.mdg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{{section /examples}}Examples
This document shows example for the {{link #/syntax}}generator syntax{{endlink}}
{{section filestructure}}Filestructure
{{endsection}}
This document shows examples for the {{link #/syntax}}generator syntax{{endlink}}

{{toc example}}
{{endsection}}
2 changes: 1 addition & 1 deletion statements/sectionref/n_sectionref.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func (n *sectionrefnode) Register(ctx scanner.ResolutionContext) error {
return err
}
ctx.SetNodeContext(n, nctx)
err = ctx.RequestDocument(nctx.GetLink(), ctx.GetDocument())
err = ctx.RequestDocument(nctx.GetLink(), n.Location())
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion statements/toc/n_toc.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func (n *tocnode) Emit(ctx scanner.ResolutionContext) error {
}
}
} else {
list = TreeTOCIds(ctx, n.typ)
list = TreeTOCIds(ctx.GetRootContext(), n.typ)
}

if len(list) == 0 {
Expand Down
73 changes: 51 additions & 22 deletions tree/resolution.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ func (r *resolvedRef) Anchor() string {
var _ scanner.ResolvedRef = (*resolvedRef)(nil)

type StructInfo struct {
document scanner.Document
ranges map[string]scanner.NumberRange
docinfo *DocumentInfo
ranges map[string]scanner.NumberRange
}

func NewStructInfo(d scanner.Document) *StructInfo {
func NewStructInfo(di *DocumentInfo) *StructInfo {
return &StructInfo{
document: d,
ranges: map[string]scanner.NumberRange{},
docinfo: di,
ranges: map[string]scanner.NumberRange{},
}
}

Expand All @@ -65,14 +65,14 @@ type NumberRangeInfo struct {
}

type RootInfo struct {
document scanner.Document
ranges map[string]*NumberRangeInfo
docinfo *DocumentInfo
ranges map[string]*NumberRangeInfo
}

func NewRootInfo(d scanner.Document) *RootInfo {
func NewRootInfo(di *DocumentInfo) *RootInfo {
return &RootInfo{
document: d,
ranges: map[string]*NumberRangeInfo{},
docinfo: di,
ranges: map[string]*NumberRangeInfo{},
}
}

Expand Down Expand Up @@ -133,7 +133,7 @@ func (i *DocumentInfo) Emit(w scanner.Writer, target string) error {
}

func (i *DocumentInfo) IsRoot() bool {
return i.rootinfo.document == i.document
return i.rootinfo.docinfo == i
}

func (i *DocumentInfo) Walk(f scanner.Resolver) error {
Expand Down Expand Up @@ -294,6 +294,35 @@ type unresolved struct {
err error
}

type docref struct {
location scanner.Location
docinfo *DocumentInfo
link utils2.Link
}
type docrefs struct {
order []*docref
links map[utils2.Link]*docref
}

func newDocRefs() *docrefs {
return &docrefs{
links: map[utils2.Link]*docref{},
}
}

func (r *docrefs) Add(link utils2.Link, loc scanner.Location) error {
if cur := r.links[link]; cur != nil {
return fmt.Errorf("%s: document ref %q already requested by %s", loc, link, cur.location)
}
cur := &docref{
location: loc,
link: link,
}
r.order = append(r.order, cur)
r.links[link] = cur
return nil
}

type ResolutionContext struct {
scope
ids
Expand All @@ -303,7 +332,8 @@ type ResolutionContext struct {

docinfo *DocumentInfo

docrefs map[utils2.Link]scanner.Document
docrefs *docrefs

numberranges utils2.Set[string]
writer scanner.Writer
target string
Expand All @@ -317,9 +347,9 @@ func NewResolutionContext(res *Resolution, di *DocumentInfo) *ResolutionContext
ctx := &ResolutionContext{
resolution: res,
docinfo: di,
docrefs: newDocRefs(),
ids: scanner.Ids{},
callstack: scanner.NewCallStack(),
docrefs: map[utils2.Link]scanner.Document{},
numberranges: utils2.Set[string]{},
}
ctx.scope = scanner.NewScope(res, res, ctx, di.document, "")
Expand Down Expand Up @@ -351,7 +381,7 @@ func (r *ResolutionContext) GetParentDocument() scanner.Document {
if p == nil {
return nil
}
return p.document
return p.docinfo.document
}

func (r *ResolutionContext) GetDocumentForLink(l utils2.Link) scanner.Document {
Expand All @@ -373,13 +403,8 @@ func (c *ResolutionContext) RequestNumberRange(typ string) {
c.numberranges.Add(typ)
}

func (c *ResolutionContext) RequestDocument(link utils2.Link, d scanner.Document) error {
r := c.docrefs[link]
if r != nil {
return fmt.Errorf("document ref %q already requested by %s", link, d.GetRefPath())
}
c.docrefs[link] = d
return nil
func (c *ResolutionContext) RequestDocument(link utils2.Link, loc scanner.Location) error {
return c.docrefs.Add(link, loc)
}

func (r *ResolutionContext) LookupTag(typ string, tag string) scanner.NodeContext {
Expand Down Expand Up @@ -412,6 +437,10 @@ func (r *ResolutionContext) SetNumberRangeFor(d scanner.Document, id scanner.Tag
return next.Current()
}

func (r *ResolutionContext) GetRootContext() scanner.ResolutionContext {
return r.docinfo.rootinfo.docinfo.context
}

func (r *ResolutionContext) GetLabelInfosForType(typ string) map[labels.LabelId]scanner.TreeLabelInfo {
result := map[labels.LabelId]scanner.TreeLabelInfo{}
for _, id := range r.scope.GetIdsForType(typ) {
Expand All @@ -438,7 +467,7 @@ func (r *ResolutionContext) appendIdsForType(typ string, result map[labels.Label
result[id] = info
}
for _, di := range r.resolution.documents {
if di.structinfo != nil && di.structinfo.document == r.docinfo.document {
if di.structinfo != nil && di.structinfo.docinfo == r.docinfo {
di.context.appendIdsForType(typ, result)
}
}
Expand Down
104 changes: 65 additions & 39 deletions tree/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,47 +152,59 @@ func (t *tree) ResolveBlocks(res *Resolution) error {
}

func (t *tree) ResolveStructural(res *Resolution) error {
found := map[scanner.Document]*docref{}
for _, di := range res.documents {
for l, d := range di.context.docrefs {
for l, ref := range di.context.docrefs.links {
var target scanner.Document
if l.IsTag() {
ri := res.refindex[l]
if ri == nil {
return fmt.Errorf("structural tag reference %q in %s cannot be resolved", l, d.Source())
return fmt.Errorf("%s: structural tag reference %q cannot be resolved", ref.location, di.Source())
}
target = ri.Context().GetDocument()
} else {
target = t.documents[l.Path()]
if target == nil {
return fmt.Errorf("structural document reference %q in %s cannot be resolved", l, d.Source())
return fmt.Errorf("%s: structural document reference %q cannot be resolved", ref.location, di.Source())
}
}
di := res.documents[target.GetRefPath()]
if di.structinfo != nil {
return fmt.Errorf("duplicate structural usage of document %s: %s and %s", target.Source(), di.structinfo.document.Source(), d.Source())
ti := res.documents[target.GetRefPath()]
if ti.structinfo != nil {
return fmt.Errorf("%s: duplicate structural usage of document %s: %s", ref.location, target.Source(), found[target].location)
}
fmt.Printf("%s: found structural usage in %s\n", target.Source(), d.Source())
found := false
fmt.Printf("%s: found structural usage in %s\n", target.Source(), di.Source())
sect := false
for _, n := range target.GetNodes() {
if _, ok := n.(section.SectionNode); ok {
if found {
fmt.Printf("structural document %s used in %s may contain only one top level section\n", target.Source(), d.Source())
if sect {
return fmt.Errorf("%s: structural document %s may contain only one top level section\n", ref.location, target.Source())
}
sect = true
}
}
di.structinfo = NewStructInfo(d)
ti.structinfo = NewStructInfo(di)
ref.docinfo = ti
found[target] = ref
}
}
return nil
}

func (t *tree) ResolveNumberRanges(res *Resolution) error {
for _, di := range res.documents {
err := t.resolveNumberRanges(res, di, utils.History{})
err := t.resolveDocumentOrder(res, di, utils.History{})
if err != nil {
return err
}
}
for _, di := range res.documents {
if di.IsRoot() {
err := t.resolveNumberRanges(di)
if err != nil {
return err
}
}
}

for _, di := range res.documents {
if di.IsRoot() {
Expand All @@ -205,6 +217,33 @@ func (t *tree) ResolveNumberRanges(res *Resolution) error {
return nil
}

func (t *tree) resolveDocumentOrder(res *Resolution, di *DocumentInfo, hist utils.History) error {
if di.rootinfo != nil {
return nil
}

hist, cycle := hist.Add(di.Source())
if cycle != nil {
return fmt.Errorf("structural cycle %s", hist)
}

var root *RootInfo
master := di.structinfo
if master != nil {
err := t.resolveDocumentOrder(res, res.documents[master.docinfo.GetRefPath()], hist)
if err != nil {
return err
}
root = res.documents[master.docinfo.GetRefPath()].rootinfo
fmt.Printf("%s: sub structure for %s\n", di.Source(), root.docinfo.Source())
} else {
fmt.Printf("%s: root document\n", di.Source())
root = NewRootInfo(di)
}
di.rootinfo = root
return nil
}

func (t *tree) resolveLabels(di *DocumentInfo, nr *NumberRangeInfo, hist utils.History, resolved map[string]bool) error {
if resolved[nr.Type()] {
return nil
Expand All @@ -229,30 +268,8 @@ func (t *tree) resolveLabels(di *DocumentInfo, nr *NumberRangeInfo, hist utils.H
return nil
}

func (t *tree) resolveNumberRanges(res *Resolution, di *DocumentInfo, hist utils.History) error {
if di.rootinfo != nil {
return nil
}

hist, cycle := hist.Add(di.Source())
if cycle != nil {
return fmt.Errorf("structural cycle %s", hist)
}

var root *RootInfo
master := di.structinfo
if master != nil {
err := t.resolveNumberRanges(res, res.documents[master.document.GetRefPath()], hist)
if err != nil {
return err
}
root = res.documents[master.document.GetRefPath()].rootinfo
fmt.Printf("%s: sub structure for %s\n", di.Source(), root.document.Source())
} else {
fmt.Printf("%s: root document\n", di.Source())
root = NewRootInfo(di.document)
}

func (t *tree) resolveNumberRanges(di *DocumentInfo) error {
root := di.rootinfo
fmt.Printf("%s: found numberranges: %s\n", di.Source(), strings.Join(utils.SortedMapKeys(di.context.numberranges), ", "))
rules := di.document.GetLabelRules()
for typ := range di.context.numberranges {
Expand Down Expand Up @@ -318,16 +335,25 @@ func (t *tree) resolveNumberRanges(res *Resolution, di *DocumentInfo, hist utils
}
}

di.rootinfo = root

for _, nr := range root.ranges {
err := checkCycle(di, nr, nil)
if err != nil {
return err
}
}
fmt.Printf(" resolve %s\n", di.GetRefPath())
return di.Walk(scanner.Resolve[scanner.LabelResolver](di.context))
err := di.Walk(scanner.Resolve[scanner.LabelResolver](di.context))
if err != nil {
return err
}

for _, ref := range di.context.docrefs.order {
err := t.resolveNumberRanges(ref.docinfo)
if err != nil {
return err
}
}
return nil
}

func checkCycle(di *DocumentInfo, nr *NumberRangeInfo, hist utils.History) error {
Expand Down

0 comments on commit 61940a2

Please sign in to comment.