-
Notifications
You must be signed in to change notification settings - Fork 2
/
sm.go
114 lines (97 loc) · 2.15 KB
/
sm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package main
import (
"strings"
)
type SMDecl struct {
RType string
Output string
SeqNo int
Steps map[string]*MethodDecl
HasDeclInit bool
}
func (p *SMDecl) AddStep(step *MethodDecl, addUntyped bool) {
if p.Steps == nil {
p.Steps = map[string]*MethodDecl{}
}
if !addUntyped && step.MType == 0 {
return
}
if dup := p.findStep(step.Name); dup != nil {
dup.Duplicate = true
return
}
step.StepNo = 1 + len(p.Steps)
if step.MType == DeclarationInit {
p.HasDeclInit = true
}
p.Steps[step.Name] = step
for i := range step.SubSteps {
p.AddStep(step.SubSteps[i], true)
}
}
func (p *SMDecl) findStep(name string) *MethodDecl {
if name == "" {
return nil
}
for {
if step := p.Steps[name]; step != nil {
return step
}
n := strings.IndexByte(name, '.')
if n < 0 {
return nil
}
name = name[n+1:]
}
}
func (p *SMDecl) Propagate() {
for _, step := range p.Steps {
step.CanPropagate = false
}
for _, step := range p.Steps {
for i := range step.Transitions {
tr := &step.Transitions[i]
tr.TransitionTo = p.findStep(tr.Transition)
tr.HiddenPropTo = p.findStep(tr.HiddenPropagate)
if tr.Migration == "" {
continue
}
if tr.TransitionTo != nil && tr.TransitionTo.AddMigration(tr.Migration) {
tr.TransitionTo.CanPropagate = true
}
if tr.HiddenPropTo != nil && tr.HiddenPropTo.AddMigration(tr.Migration) {
tr.HiddenPropTo.CanPropagate = true
}
if migrationTo := p.findStep(tr.Migration); migrationTo != nil && migrationTo.AddMigration(tr.Migration) {
migrationTo.CanPropagate = true
}
}
}
for {
didSomething := false
for _, step := range p.Steps {
if !step.CanPropagate {
continue
}
step.CanPropagate = false
for _, tr := range step.Transitions {
switch {
case tr.TransitionTo == nil:
case !tr.InheritMigration:
case tr.TransitionTo.AddMigrations(step):
tr.TransitionTo.CanPropagate = true
didSomething = true
}
switch {
case tr.HiddenPropTo == nil:
case tr.HiddenPropTo.AddMigrations(step):
tr.HiddenPropTo.CanPropagate = true
didSomething = true
}
}
}
if !didSomething {
return
}
}
}