1 package filtering
2
3 import (
4 "fmt"
5
6 expr "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
7 "google.golang.org/protobuf/proto"
8 "google.golang.org/protobuf/reflect/protoreflect"
9 )
10
11
12 func NewStringConstant(value string) *expr.Constant {
13 return &expr.Constant{
14 ConstantKind: &expr.Constant_StringValue{
15 StringValue: value,
16 },
17 }
18 }
19
20
21 func NewFunctionDeclaration(name string, overloads ...*expr.Decl_FunctionDecl_Overload) *expr.Decl {
22 return &expr.Decl{
23 Name: name,
24 DeclKind: &expr.Decl_Function{
25 Function: &expr.Decl_FunctionDecl{
26 Overloads: overloads,
27 },
28 },
29 }
30 }
31
32
33 func NewFunctionOverload(id string, result *expr.Type, params ...*expr.Type) *expr.Decl_FunctionDecl_Overload {
34 return &expr.Decl_FunctionDecl_Overload{
35 OverloadId: id,
36 ResultType: result,
37 Params: params,
38 }
39 }
40
41
42 func NewIdentDeclaration(name string, identType *expr.Type) *expr.Decl {
43 return &expr.Decl{
44 Name: name,
45 DeclKind: &expr.Decl_Ident{
46 Ident: &expr.Decl_IdentDecl{
47 Type: identType,
48 },
49 },
50 }
51 }
52
53
54 func NewConstantDeclaration(name string, constantType *expr.Type, constantValue *expr.Constant) *expr.Decl {
55 return &expr.Decl{
56 Name: name,
57 DeclKind: &expr.Decl_Ident{
58 Ident: &expr.Decl_IdentDecl{
59 Type: constantType,
60 Value: constantValue,
61 },
62 },
63 }
64 }
65
66
67 type Declarations struct {
68 idents map[string]*expr.Decl
69 functions map[string]*expr.Decl
70 enums map[string]protoreflect.EnumType
71 }
72
73
74 type DeclarationOption func(*Declarations) error
75
76
77 func DeclareStandardFunctions() DeclarationOption {
78 return func(declarations *Declarations) error {
79 for _, declaration := range StandardFunctionDeclarations() {
80 if err := declarations.declare(declaration); err != nil {
81 return err
82 }
83 }
84 return nil
85 }
86 }
87
88
89 func DeclareFunction(name string, overloads ...*expr.Decl_FunctionDecl_Overload) DeclarationOption {
90 return func(declarations *Declarations) error {
91 return declarations.declareFunction(name, overloads...)
92 }
93 }
94
95
96 func DeclareIdent(name string, t *expr.Type) DeclarationOption {
97 return func(declarations *Declarations) error {
98 return declarations.declareIdent(name, t)
99 }
100 }
101
102 func DeclareEnumIdent(name string, enumType protoreflect.EnumType) DeclarationOption {
103 return func(declarations *Declarations) error {
104 return declarations.declareEnumIdent(name, enumType)
105 }
106 }
107
108
109 func NewDeclarations(opts ...DeclarationOption) (*Declarations, error) {
110 d := &Declarations{
111 idents: make(map[string]*expr.Decl),
112 functions: make(map[string]*expr.Decl),
113 enums: make(map[string]protoreflect.EnumType),
114 }
115 for _, opt := range opts {
116 if err := opt(d); err != nil {
117 return nil, err
118 }
119 }
120 return d, nil
121 }
122
123 func (d *Declarations) LookupIdent(name string) (*expr.Decl, bool) {
124 result, ok := d.idents[name]
125 return result, ok
126 }
127
128 func (d *Declarations) LookupFunction(name string) (*expr.Decl, bool) {
129 result, ok := d.functions[name]
130 return result, ok
131 }
132
133 func (d *Declarations) LookupEnumIdent(name string) (protoreflect.EnumType, bool) {
134 result, ok := d.enums[name]
135 return result, ok
136 }
137
138 func (d *Declarations) declareIdent(name string, t *expr.Type) error {
139 if _, ok := d.idents[name]; ok {
140 return fmt.Errorf("redeclaration of %s", name)
141 }
142 d.idents[name] = NewIdentDeclaration(name, t)
143 return nil
144 }
145
146 func (d *Declarations) declareConstant(name string, constantType *expr.Type, constantValue *expr.Constant) error {
147 constantDecl := NewConstantDeclaration(name, constantType, constantValue)
148 if existingIdent, ok := d.idents[name]; ok {
149 if !proto.Equal(constantDecl, existingIdent) {
150 return fmt.Errorf("redeclaration of %s", name)
151 }
152 return nil
153 }
154 d.idents[name] = constantDecl
155 return nil
156 }
157
158 func (d *Declarations) declareEnumIdent(name string, enumType protoreflect.EnumType) error {
159 if _, ok := d.enums[name]; ok {
160 return fmt.Errorf("redeclaration of %s", name)
161 }
162 d.enums[name] = enumType
163 enumIdentType := TypeEnum(enumType)
164 if err := d.declareIdent(name, enumIdentType); err != nil {
165 return err
166 }
167 for _, fn := range []string{
168 FunctionEquals,
169 FunctionNotEquals,
170 } {
171 if err := d.declareFunction(
172 fn,
173 NewFunctionOverload(fn+"_"+enumIdentType.GetMessageType(), TypeBool, enumIdentType, enumIdentType),
174 ); err != nil {
175 return err
176 }
177 }
178 values := enumType.Descriptor().Values()
179 for i := 0; i < values.Len(); i++ {
180 valueName := string(values.Get(i).Name())
181 if err := d.declareConstant(valueName, enumIdentType, NewStringConstant(valueName)); err != nil {
182 return err
183 }
184 }
185 return nil
186 }
187
188 func (d *Declarations) declareFunction(name string, overloads ...*expr.Decl_FunctionDecl_Overload) error {
189 decl, ok := d.functions[name]
190 if !ok {
191 decl = NewFunctionDeclaration(name)
192 d.functions[name] = decl
193 }
194 function := decl.GetFunction()
195 NewOverloadLoop:
196 for _, newOverload := range overloads {
197 for _, existingOverload := range function.GetOverloads() {
198 if newOverload.GetOverloadId() == existingOverload.GetOverloadId() {
199 if !proto.Equal(newOverload, existingOverload) {
200 return fmt.Errorf("redeclaration of overload %s", existingOverload.GetOverloadId())
201 }
202 continue NewOverloadLoop
203 }
204 }
205 function.Overloads = append(function.Overloads, newOverload)
206 }
207 return nil
208 }
209
210 func (d *Declarations) declare(decl *expr.Decl) error {
211 switch decl.GetDeclKind().(type) {
212 case *expr.Decl_Function:
213 return d.declareFunction(decl.GetName(), decl.GetFunction().GetOverloads()...)
214 case *expr.Decl_Ident:
215 if decl.GetIdent().GetValue() != nil {
216 return d.declareConstant(decl.GetName(), decl.GetIdent().GetType(), decl.GetIdent().GetValue())
217 }
218 return d.declareIdent(decl.GetName(), decl.GetIdent().GetType())
219 default:
220 return fmt.Errorf("unsupported declaration kind")
221 }
222 }
223
View as plain text