Skip to content

Commit c1aa5d3

Browse files
committed
Goddamnyou unrolling, fixed a bug and test it
1 parent 1bd798e commit c1aa5d3

File tree

3 files changed

+93
-18
lines changed

3 files changed

+93
-18
lines changed

token/transform.go

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ func UnrollPointers(root Token) Token {
7373
log.Debug("start unrolling pointers by cloning them")
7474

7575
parents := make(map[Token]Token)
76-
changed := make(map[Token]struct{})
7776

7877
originals := make(map[Token]Token)
7978
originalClones := make(map[Token]Token)
@@ -178,8 +177,6 @@ func UnrollPointers(root Token) Token {
178177
if iTok.parent != nil {
179178
log.Debugf("replace in (%p)%#v", iTok.parent.tok, iTok.parent.tok)
180179

181-
changed[iTok.parent.tok] = struct{}{}
182-
183180
switch tt := iTok.parent.tok.(type) {
184181
case ForwardToken:
185182
tt.InternalReplace(t, c)
@@ -230,7 +227,6 @@ func UnrollPointers(root Token) Token {
230227
REMOVE:
231228
for tt != nil {
232229
delete(parents, tt.tok)
233-
delete(changed, tt.tok)
234230

235231
switch l := tt.tok.(type) {
236232
case ForwardToken:
@@ -291,23 +287,21 @@ func UnrollPointers(root Token) Token {
291287
}
292288
}
293289

294-
// we need to update some tokens with the same child to regenerate clones
295-
for child := range changed {
296-
parent := parents[child]
297-
298-
if parent == nil {
299-
continue
300-
}
301-
302-
log.Debugf("update (%p)%#v with child (%p)%#v", parent, parent, child, child)
303-
304-
switch tt := parent.(type) {
290+
// force regeneration of possible cloned tokens
291+
WalkInternalTail(root, func(tok Token) error {
292+
switch t := tok.(type) {
305293
case ForwardToken:
306-
tt.InternalReplace(child, child)
294+
c := t.InternalGet()
295+
t.InternalReplace(c, c)
307296
case ListToken:
308-
tt.InternalReplace(child, child)
297+
for i := 0; i < t.InternalLen(); i++ {
298+
c, _ := t.InternalGet(i)
299+
t.InternalReplace(c, c)
300+
}
309301
}
310-
}
302+
303+
return nil
304+
})
311305

312306
log.Debug("finished unrolling")
313307

token/transform_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package token_test
2+
3+
import (
4+
"testing"
5+
6+
. "github.com/zimmski/tavor/test/assert"
7+
8+
"github.com/zimmski/tavor/token"
9+
"github.com/zimmski/tavor/token/lists"
10+
"github.com/zimmski/tavor/token/primitives"
11+
)
12+
13+
func TestUnrollPointers(t *testing.T) {
14+
{
15+
// Corner case: START = "group" +(START | "a")
16+
// This should not leave any pointer in the internal as well as in the external representation
17+
18+
var tok *token.Token
19+
20+
p := primitives.NewEmptyPointer(tok)
21+
s := lists.NewAll(
22+
primitives.NewConstantString("group"),
23+
lists.NewRepeat(
24+
lists.NewOne(
25+
p,
26+
primitives.NewConstantString("a"),
27+
),
28+
1,
29+
2,
30+
),
31+
)
32+
33+
err := p.Set(s)
34+
Nil(t, err)
35+
36+
unrolled := token.UnrollPointers(s)
37+
38+
token.WalkInternal(unrolled, func(tok token.Token) error {
39+
if _, ok := tok.(*primitives.Pointer); ok {
40+
t.Fatalf("Found pointer in the internal structure %#v", tok)
41+
}
42+
43+
return nil
44+
})
45+
46+
token.Walk(unrolled, func(tok token.Token) error {
47+
if _, ok := tok.(*primitives.Pointer); ok {
48+
t.Fatalf("Found pointer in the external structure %#v", tok)
49+
}
50+
51+
return nil
52+
})
53+
}
54+
}

token/walk.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,33 @@ func WalkInternal(root Token, walkFunc func(tok Token) error) error {
8080
return nil
8181
}
8282

83+
// WalkInternalTail traverses a internal token graph beginning from the given token and calls for every newly visited token the given function after it has traversed all children.
84+
// A depth-first algorithm is used to traverse the graph. If the given walk function returns an error, the whole walk process ends by returning the error back to the caller
85+
func WalkInternalTail(root Token, walkFunc func(tok Token) error) error {
86+
switch t := root.(type) {
87+
case ForwardToken:
88+
if v := t.InternalGet(); v != nil {
89+
if err := WalkInternalTail(v, walkFunc); err != nil {
90+
return err
91+
}
92+
}
93+
case ListToken:
94+
for i := 0; i < t.InternalLen(); i++ {
95+
c, _ := t.InternalGet(i)
96+
97+
if err := WalkInternalTail(c, walkFunc); err != nil {
98+
return err
99+
}
100+
}
101+
}
102+
103+
if err := walkFunc(root); err != nil {
104+
return err
105+
}
106+
107+
return nil
108+
}
109+
83110
// ReleaseTokens traverses the token graph and calls Release for every release token
84111
func ReleaseTokens(root Token) {
85112
_ = Walk(root, func(tok Token) error {

0 commit comments

Comments
 (0)