1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package adt
16
17
18
19
20
21 type Constraints struct {
22
23 Pairs []PatternConstraint
24
25
26
27
28 Allowed Value
29 }
30
31
32
33
34
35
36
37
38
39
40 type PatternConstraint struct {
41 Pattern Value
42 Constraint *Vertex
43 }
44
45
46
47 func (n *nodeContext) insertListEllipsis(offset int, ellipsis Conjunct) {
48 ctx := n.ctx
49
50 var p Value
51 if offset == 0 {
52 p = &BasicType{
53 Src: ellipsis.Field().Source(),
54 K: IntKind,
55 }
56 } else {
57 p = &BoundValue{
58 Src: nil,
59 Op: GreaterEqualOp,
60 Value: ctx.NewInt64(int64(offset)),
61 }
62 }
63 n.insertConstraint(p, ellipsis)
64 }
65
66
67
68
69
70
71
72
73 func (n *nodeContext) insertConstraint(pattern Value, c Conjunct) bool {
74 if c.CloseInfo.cc == nil {
75 panic("constraint conjunct must have closeContext associated with it")
76 }
77
78 ctx := n.ctx
79 v := n.node
80
81 pcs := v.PatternConstraints
82 if pcs == nil {
83 pcs = &Constraints{}
84 v.PatternConstraints = pcs
85 }
86
87 var constraint *Vertex
88 for _, pc := range pcs.Pairs {
89 if Equal(ctx, pc.Pattern, pattern, 0) {
90 constraint = pc.Constraint
91 break
92 }
93 }
94
95 if constraint == nil {
96 constraint = &Vertex{}
97 pcs.Pairs = append(pcs.Pairs, PatternConstraint{
98 Pattern: pattern,
99 Constraint: constraint,
100 })
101 } else if constraint.hasConjunct(c) {
102
103 return false
104 }
105
106 constraint.addConjunctUnchecked(c)
107 return true
108 }
109
110
111
112 func matchPattern(ctx *OpContext, pattern Value, f Feature) bool {
113 if pattern == nil || !f.IsRegular() {
114 return false
115 }
116
117
118
119
120
121
122
123 var label Value
124 if int64(f.Index()) == MaxIndex {
125 f = 0
126 } else if f.IsString() {
127 label = f.ToValue(ctx)
128 }
129
130 return matchPatternValue(ctx, pattern, f, label)
131 }
132
133
134
135
136
137
138 func matchPatternValue(ctx *OpContext, pattern Value, f Feature, label Value) (result bool) {
139 pattern = Unwrap(pattern)
140 label = Unwrap(label)
141
142 if pattern == label {
143 return true
144 }
145
146
147 switch x := pattern.(type) {
148 case *Bottom:
149
150 if x == cycle {
151 err := ctx.NewPosf(pos(pattern), "cyclic pattern constraint")
152 for _, c := range ctx.vertex.Conjuncts {
153 addPositions(err, c)
154 }
155 ctx.AddBottom(&Bottom{
156 Err: err,
157 })
158 }
159 if ctx.errs == nil {
160 ctx.AddBottom(x)
161 }
162 return false
163
164 case *Top:
165 return true
166
167 case *BasicType:
168 k := label.Kind()
169 return x.K&k == k
170
171 case *BoundValue:
172 switch x.Kind() {
173 case StringKind:
174 if label == nil {
175 return false
176 }
177 str := label.(*String).Str
178 return x.validateStr(ctx, str)
179
180 case NumKind:
181 return x.validateInt(ctx, int64(f.Index()))
182 }
183
184 case *Num:
185 if !f.IsInt() {
186 return false
187 }
188 yi := int64(f.Index())
189 xi, err := x.X.Int64()
190 return err == nil && xi == yi
191
192 case *String:
193 y, ok := label.(*String)
194 return ok && x.Str == y.Str
195
196 case *Conjunction:
197 for _, a := range x.Values {
198 if !matchPatternValue(ctx, a, f, label) {
199 return false
200 }
201 }
202 return true
203
204 case *Disjunction:
205 for _, a := range x.Values {
206 if matchPatternValue(ctx, a, f, label) {
207 return true
208 }
209 }
210 return false
211 }
212
213
214
215
216
217
218
219
220 if label == nil {
221 label = f.ToValue(ctx)
222 }
223
224 n := ctx.newInlineVertex(nil, nil,
225 MakeConjunct(ctx.e, pattern, ctx.ci),
226 MakeConjunct(ctx.e, label, ctx.ci))
227 n.Finalize(ctx)
228 return n.Err(ctx) == nil
229 }
230
View as plain text