-
Notifications
You must be signed in to change notification settings - Fork 1
/
domain.go
146 lines (120 loc) · 3.79 KB
/
domain.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package main
import (
"golang.org/x/exp/maps"
"golang.org/x/exp/slices"
"reflect"
"strings"
)
// An Identifier follows the rules of a Go identifier, e.g. UnvalidatedOrder.
type Identifier string
// ChoiceName is a unique identifier of an existing local type (e.g. UnvalidatedOrder or ValidatedOrder).
// This type will later receive marker methods.
type ChoiceName Identifier
// Comment may be empty, a single line or multiline text.
type Comment string
// A ChoiceTypeDeclaration aggregates all information about a new ChoiceType which must be generated.
type ChoiceTypeDeclaration struct {
Doc Comment
Name Identifier
Funcs []FuncSpec
Choices []Identifier
Error bool
EmbeddedInterfaces []Identifier
}
type FuncSpec struct {
Name Identifier
Params []Identifier
Results []Identifier
}
// SuperSet is a set of local type identifiers which are equal or the super set of something else.
type SuperSet []Identifier
// ChoiceSubSetType annotates all super set types.
type ChoiceSubSetType struct {
ChoiceTypeDeclaration
SubsetOf SuperSet
}
// DetermineSuperSets transforms from declarations to subset types.
type DetermineSuperSets func([]ChoiceTypeDeclaration) []ChoiceSubSetType
// A ChoiceTypeMember belongs to all its contained ChoiceTypes.
type ChoiceTypeMember struct {
Name Identifier
BelongsTo []Identifier
Error bool
}
func (c ChoiceTypeMember) ShortName() string {
return strings.ToLower(string(rune(c.Name[0])))
}
func determineSuperSets(decls []ChoiceTypeDeclaration) []ChoiceSubSetType {
var types []ChoiceSubSetType
for _, decl := range decls {
types = append(types, ChoiceSubSetType{
ChoiceTypeDeclaration: decl,
SubsetOf: mapEach(superSets(decl, decls), func(t ChoiceTypeDeclaration) Identifier {
return t.Name
}),
})
}
return types
}
func determineChoiceTypeMembers(decls []ChoiceSubSetType) []ChoiceTypeMember {
members := map[Identifier]ChoiceTypeMember{}
for _, decl := range decls {
for _, choice := range decl.Choices {
t := members[choice]
t.Name = choice
t.Error = decl.Error
// implements the higher interface i.e. Praktikum (Pflicht is part of Praktikum)
if !slices.Contains(t.BelongsTo, decl.Name) {
t.BelongsTo = append(t.BelongsTo, decl.Name)
}
// implements the next higher interface(s) i.e. SonstigeArbeit (Pflicht is part of Praktikum is part of SonstigeArbeit)
for _, interf := range decl.EmbeddedInterfaces {
if !slices.Contains(t.BelongsTo, interf) {
t.BelongsTo = append(t.BelongsTo, interf)
}
}
// implements the highest interface, if interfaces are more nested i.e. Arbeit (Pflicht is part of Praktikum, is part of
// SonstigeArbeit is part of Arbeit
for _, d := range decls {
for _, c := range d.Choices {
for _, i := range decl.EmbeddedInterfaces {
if c == i {
if !slices.Contains(t.BelongsTo, d.Name) {
t.BelongsTo = append(t.BelongsTo, d.Name)
}
}
}
}
}
members[choice] = t
}
}
for k, _ := range members {
for _, d := range decls {
if k == d.Name {
delete(members, k)
}
}
}
values := maps.Values(members)
// Order members alphabetically for a stable generation output.
slices.SortFunc(values, func(a, b ChoiceTypeMember) bool {
return a.Name < b.Name
})
return values
}
func superSets(decls ChoiceTypeDeclaration, other []ChoiceTypeDeclaration) []ChoiceTypeDeclaration {
var superSets []ChoiceTypeDeclaration
dstSet := slices.Clone(decls.Choices)
for _, declaration := range other {
otherDecl := slices.Clone(declaration.Choices)
slices.Sort(otherDecl)
if slices.Equal(intersect(dstSet, otherDecl), dstSet) {
superSets = append(superSets, declaration)
}
}
return superSets
}
func getType(v interface{}) reflect.Type {
return reflect.TypeOf(v)
}