...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package list
20
21 import (
22 "sort"
23
24 "cuelang.org/go/cue"
25 "cuelang.org/go/internal/core/adt"
26 "cuelang.org/go/internal/types"
27 )
28
29
30 type valueSorter struct {
31 ctx *adt.OpContext
32 a []cue.Value
33 err error
34
35 cmp *adt.Vertex
36 less *adt.Vertex
37 x *adt.Vertex
38 y *adt.Vertex
39 }
40
41 func (s *valueSorter) ret() ([]cue.Value, error) {
42 if s.err != nil {
43 return nil, s.err
44 }
45
46 return s.a, nil
47 }
48
49 func (s *valueSorter) Len() int { return len(s.a) }
50 func (s *valueSorter) Swap(i, j int) { s.a[i], s.a[j] = s.a[j], s.a[i] }
51 func (s *valueSorter) Less(i, j int) bool {
52 if s.err != nil {
53 return false
54 }
55 var x, y types.Value
56 s.a[i].Core(&x)
57 s.a[j].Core(&y)
58
59
60
61 saveCmp := *s.cmp
62 saveLess := *s.less
63 saveX := *s.x
64 saveY := *s.y
65
66 for _, c := range x.V.Conjuncts {
67 s.x.AddConjunct(c)
68 }
69 for _, c := range y.V.Conjuncts {
70 s.y.AddConjunct(c)
71 }
72
73
74
75
76
77
78
79
80
81
82
83
84 s.less.Finalize(s.ctx)
85 isLess := s.ctx.BoolValue(s.less)
86 if b := s.less.Err(s.ctx); b != nil && s.err == nil {
87 s.err = b.Err
88 return true
89 }
90
91 *s.less = saveLess
92 *s.cmp = saveCmp
93 *s.x = saveX
94 *s.y = saveY
95
96 return isLess
97 }
98
99 var less = cue.ParsePath("less")
100
101 func makeValueSorter(list []cue.Value, cmp cue.Value) (s valueSorter) {
102 if v := cmp.LookupPath(less); !v.Exists() {
103 return valueSorter{err: v.Err()}
104 }
105
106 var v types.Value
107 cmp.Core(&v)
108 ctx := adt.NewContext(v.R, v.V)
109
110 n := &adt.Vertex{
111 Label: v.V.Label,
112 Parent: v.V.Parent,
113 Conjuncts: v.V.Conjuncts,
114 }
115 n.CompleteArcs(ctx)
116
117 s = valueSorter{
118 a: list,
119 ctx: ctx,
120 cmp: n,
121 less: getArc(ctx, n, "less"),
122 x: getArc(ctx, n, "x"),
123 y: getArc(ctx, n, "y"),
124 }
125
126
127
128
129
130
131
132 return s
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146 func Sort(list []cue.Value, cmp cue.Value) (sorted []cue.Value, err error) {
147 s := makeValueSorter(list, cmp)
148
149
150 sort.Stable(&s)
151 return s.ret()
152 }
153
154 func getArc(ctx *adt.OpContext, v *adt.Vertex, s string) *adt.Vertex {
155 f := ctx.StringLabel(s)
156 arc, _ := v.GetArc(ctx, f, 0)
157 return arc
158 }
159
160
161 func SortStable(list []cue.Value, cmp cue.Value) (sorted []cue.Value, err error) {
162 s := makeValueSorter(list, cmp)
163 sort.Stable(&s)
164 return s.ret()
165 }
166
167
168 func SortStrings(a []string) []string {
169 sort.Strings(a)
170 return a
171 }
172
173
174
175
176 func IsSorted(list []cue.Value, cmp cue.Value) bool {
177 s := makeValueSorter(list, cmp)
178 return sort.IsSorted(&s)
179 }
180
181
182 func IsSortedStrings(a []string) bool {
183 return sort.StringsAreSorted(a)
184 }
185
View as plain text