Skip to content

Commit 7ee8256

Browse files
committed
update readme
1 parent b14fa55 commit 7ee8256

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# CEL Pre-processor
2+
3+
This repo contains a simple CEL pre-processor.
4+
This allows passing in higher-level CEL expressions, and emitting standard ones.
5+
6+
This is done using CEL's own parser and macro system.
7+
The pre-processor allows defining custom macros, expands them, and emits the expanded expression.
8+
Builtin macros are *not* expanded, so the result is not overly bloated.
9+
10+
## Examples
11+
12+
Input: `has(self.x) && default(self.y, 0)`
13+
Output: `has(self.x) && (has(self.y) ? self.y : 0)`
14+
15+
Input: `self.index(x, z, b)`
16+
Output: `(has(self.x) && has(self.x.z) && has(self.x.z.b)) ? self.x.z.b : null`
17+
18+
## Status
19+
20+
This is a complete WIP at this point, but I will likely pick up work in the future.

main.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,14 @@ func foldl[T any](slice []T, combine func(T, T) T) T {
3333
return result
3434
}
3535

36+
//func simpleBuilder(name string,)
37+
3638
func main() {
3739
expr := os.Args[1]
3840
prsr, err := parser.NewParser(
3941
parser.Macros(
42+
// Usage: `self.index(x, z, b)`
43+
// This does a nil-safe traversal of
4044
cel.ReceiverVarArgMacro("index",
4145
func(mef cel.MacroExprFactory, base celast.Expr, args []celast.Expr) (celast.Expr, *cel.Error) {
4246
if len(args) == 0 {
@@ -56,6 +60,30 @@ func main() {
5660
final := mef.NewCall(operators.Conditional, check, selects(mef, base, args...), mef.NewLiteral(types.NullValue))
5761
return final, nil
5862
}),
63+
// Usage: `oneof(self.x, self.y, self.z)`
64+
// This checks that 0 or 1 of these fields is set, mirroring Protobuf one-of checking logic.
65+
cel.GlobalVarArgMacro("oneof",
66+
func(mef cel.MacroExprFactory, base celast.Expr, args []celast.Expr) (celast.Expr, *cel.Error) {
67+
if len(args) < 2 {
68+
return nil, mef.NewError(base.ID(), "oneof requires at least 2 arg")
69+
}
70+
checks := []celast.Expr{}
71+
for _, arg := range args{
72+
73+
has := mef.NewCall(operators.Has, arg)
74+
logExpr("sum", arg)
75+
check := mef.NewCall(operators.Conditional, has, mef.NewLiteral(types.Int(1)), mef.NewLiteral(types.Int(0)))
76+
checks = append(checks, check)
77+
}
78+
sum := foldl(checks, func(l, r celast.Expr) celast.Expr {
79+
return mef.NewCall(operators.Add, l, r)
80+
})
81+
82+
final := mef.NewCall(operators.LessEquals, sum, mef.NewLiteral(types.Int(1)))
83+
return final, nil
84+
}),
85+
// Usage: `default(self.x, 'DEF')`.
86+
// This returns self.x if its set, else 'DEF'
5987
cel.GlobalMacro("default", 2,
6088
func(mef cel.MacroExprFactory, iterRange celast.Expr, args []celast.Expr) (celast.Expr, *cel.Error) {
6189
has := mef.NewCall(operators.Has, args[0])

0 commit comments

Comments
 (0)