המסמך הזה משמש כהפניה מאוחדת לתיעוד של Common Expression Language (CEL). היא מפרטת את כל פקודות המאקרו, האופרטורים והפונקציות הרגילות, ומציינת את החתימות, ההתנהגויות וסטטוס התמיכה שלהם בכל מחסניות CEL הרשמיות.
פרטים נוספים על התנהגות השפה והמפרטים שלה זמינים בהגדרת השפה ב-CEL.
גרסאות של Stack
מסמך העיון הזה מבוסס על הגרסאות הבאות של חבילות CEL:
- CEL Go:
v0.30.0(ומגרסאות חדשות יותר) - CEL C++:
v0.16.0 - CEL Java:
v0.13.1 - CEL Python:
v0.1.3 - CEL C: תמונת מצב של פיתוח (לא פורסם)
מראות GitHub
ההטמעות הרשמיות של CEL משוכפלות ב-GitHub בארגון cel-expr:
1. Core Macros
אלה פקודות מאקרו מובנות שמתרחבות בזמן ההידור.
| Macro | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
has(container.field) |
בודקת אם שדה מסוים קיים בהודעה או אם מפתח מסוים קיים במפה. חתימות: has(container.field) -> boolדוגמאות: has(request.auth.claims.email) |
✓ | ✓ | ✓ | ✓ | ✓ |
list.all(var, predicate) |
הפונקציה בודקת אם כל הרכיבים ברשימה עומדים בתנאי. חתימות: list.all(var, predicate) -> boolדוגמאות: [1, 2, 3].all(x, x > 0) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.exists(var, predicate) |
הפונקציה בודקת אם לפחות רכיב אחד ברשימה עומד בתנאי. חתימות: list.exists(var, predicate) -> boolדוגמאות: [1, 2, 3].exists(x, x > 2) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.exists_one(var, predicate) |
הפונקציה בודקת אם יש בדיוק רכיב אחד ברשימה שעומד בתנאי. חתימות: list.exists_one(var, predicate) -> boolדוגמאות: [1, 2, 3].exists_one(x, x == 2) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.filter(var, predicate) |
מסנן רכיבים של רשימה לפי פרדיקט. חתימות: list.filter(var, predicate) -> listדוגמאות: [1, 2, 3].filter(x, x > 1) // [2, 3] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.map(var, transform) |
הופך כל רכיב ברשימה באמצעות ביטוי. חתימות: list.map(var, transform) -> listדוגמאות: [1, 2, 3].map(x, x * 2) // [2, 4, 6] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.map(var, filter, transform) |
הפונקציה הזו משנה רכיבים ברשימה שעומדים בתנאי של מסנן. חתימות: list.map(var, filter, transform) -> listדוגמאות: [1, 2, 3].map(x, x > 1, x * 2) // [4, 6] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
¹ נתמך בזמן ריצה של C כי פקודות מאקרו מורחבות להבנה במהלך הקומפילציה על ידי קומפיילר המארח.
2. מפעילים מרכזיים
| מפעיל | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
חשבוני (+, -, *, /, %) |
פעולות חשבוניות רגילות. שלילה (-x) וזהות (+x). שרשור רשימות (list + list) נתמך בשפות Go, C++, Java ו-Python.חתימות: T + T -> TT - T -> TT * T -> TT / T -> TT % T -> T-T -> T+T -> Tlist + list -> listדוגמאות: 1 + 2 * 3 // 7[1] + [2] // [1, 2] |
✓ | ✓ | ✓ | ✓ | ✓² |
השוואה (==, !=, <, <=, >, >=) |
השוואה רגילה. השוואות מספריות הן הטרוגניות (לדוגמה, 1 == 1.0).חתימות: T == T -> boolT != T -> boolT < T -> boolT <= T -> boolT > T -> boolT >= T -> boolדוגמאות: x < 42.01 == 1.0 // true |
✓ | ✓ | ✓ | ✓ | ✓ |
לוגי (!, &&, ||, ? :) |
NOT, AND, OR לוגיים ותנאי טרנרי. אפשר גם להשתמש בהערכה של מעגל קצר. חתימות: !bool -> boolbool && bool -> boolbool || bool -> boolbool ? T : T -> Tדוגמאות: x > 0 ? "positive" : "non-positive" |
✓ | ✓ | ✓ | ✓ | ✓ |
הוספה לאינדקס ([]) |
גישה לרכיב ברשימה לפי אינדקס, או מפתח חיפוש במפה. חתימות: list[int] -> Tmap[K] -> Vדוגמאות: tags[0]users['john'] |
✓ | ✓ | ✓ | ✓ | ✓ |
חברות (in) |
בודקים אם רכיב נמצא ברשימה או אם מפתח נמצא במפה. חתימות: T in list -> boolK in map -> boolדוגמאות: 'admin' in roles |
✓ | ✓ | ✓ | ✓ | ✓ |
² שרשור רשימות (list + list) לא נתמך בסביבת זמן הריצה של C,
אבל יש תמיכה באופרטורים אריתמטיים אחרים.
3. פונקציות ליבה
פונקציות כלליות ופונקציות מחרוזת
| פונקציה | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
size |
הפונקציה מחזירה את הגודל של מחרוזת (תווים), בייטים, רשימה או מפה. חתימות: size(T) -> int (כאשר T הוא string, bytes, list או map)דוגמאות: size("hello") // 5 |
✓ | ✓ | ✓ | ✓ | ✓ |
contains |
הפונקציה מחזירה אם המחרוזת מכילה מחרוזת משנה. חתימות: string.contains(string) -> boolדוגמאות: "hello".contains("ell") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
startsWith |
הפונקציה מחזירה אם המחרוזת מתחילה בקידומת. חתימות: string.startsWith(string) -> boolדוגמאות: "hello".startsWith("he") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
endsWith |
הפונקציה מחזירה אם המחרוזת מסתיימת בסיומת. חתימות: string.endsWith(string) -> boolדוגמאות: "hello".endsWith("lo") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
matches |
הפונקציה מחזירה ערך בוליאני שמציין אם המחרוזת תואמת לביטוי רגולרי של RE2. חתימות: string.matches(string) -> boolדוגמאות: "123".matches(r"^\d+$") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
פונקציות של בורר התאריך והשעה
הפונקציות האלה מחלצות רכיבים מ-google.protobuf.Timestamp או מ-google.protobuf.Duration.
| פונקציה | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
getFullYear |
הפונקציה מחזירה את השנה בת 4 ספרות. חתימות: timestamp.getFullYear([tz]) -> intדוגמאות: timestamp("2026-07-23T00:00:00Z").getFullYear() // 2026 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMonth |
הפונקציה מחזירה את החודש (0-11). חתימות: timestamp.getMonth([tz]) -> intדוגמאות: timestamp("2026-07-23T00:00:00Z").getMonth() // 6 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfMonth |
הפונקציה מחזירה את היום בחודש (1-31). חתימות: timestamp.getDayOfMonth([tz]) -> intדוגמאות: timestamp("2026-07-23T00:00:00Z").getDayOfMonth() // 23 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfWeek |
הפונקציה מחזירה את היום בשבוע (0 = יום ראשון). חתימות: timestamp.getDayOfWeek([tz]) -> intדוגמאות: timestamp("2026-07-23T00:00:00Z").getDayOfWeek() // 4 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfYear |
הפונקציה מחזירה את היום בשנה (0 עד 365). חתימות: timestamp.getDayOfYear([tz]) -> intדוגמאות: timestamp("2026-07-23T00:00:00Z").getDayOfYear() // 203 |
✓ | ✓ | ✓ | ✓ | ✗ |
getHours |
הפונקציה מחזירה את השעות (0-23). חתימות: timestamp.getHours([tz]) -> intduration.getHours() -> intדוגמאות: duration("1h30m").getHours() // 1 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMinutes |
הפונקציה מחזירה את הדקות (0-59). חתימות: timestamp.getMinutes([tz]) -> intduration.getMinutes() -> intדוגמאות: duration("1h30m").getMinutes() // 30 |
✓ | ✓ | ✓ | ✓ | ✗ |
getSeconds |
הפונקציה מחזירה את השניות (0-59). חתימות: timestamp.getSeconds([tz]) -> intduration.getSeconds() -> intדוגמאות: duration("1h30m45s").getSeconds() // 45 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMilliseconds |
הפונקציה מחזירה את אלפיות השנייה (0-999). חתימות: timestamp.getMilliseconds([tz]) -> intduration.getMilliseconds() -> intדוגמאות: duration("1.5s").getMilliseconds() // 500 |
✓ | ✓ | ✓ | ✓ | ✗ |
המרות של סוגים
| סוג המיקוד | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
bool |
הפונקציה ממירה לערך בוליאני. חתימות: bool(bool) -> boolbool(string) -> boolדוגמאות: bool("true") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
bytes |
הפונקציה ממירה לבייטים. חתימות: bytes(bytes) -> bytesbytes(string) -> bytesדוגמאות: bytes("hello") // b"hello" |
✓ | ✓ | ✓ | ✓ | ✓ |
double |
ממירה למספר נקודה צפה עם דיוק כפול. חתימות: double(double) -> doubledouble(int) -> doubledouble(uint) -> doubledouble(string) -> doubleדוגמאות: double(1) // 1.0 |
✓ | ✓ | ✓ | ✓ | ✓ |
duration |
הפונקציה ממירה לערך של משך. חתימות: duration(duration) -> durationduration(string) -> durationדוגמאות: duration("1.5s") // 1.5s duration |
✓ | ✓ | ✓ | ✓ | ✓ |
int |
ממירה למספר שלם חתום של 64 ביט. חתימות: int(int) -> intint(uint) -> intint(double) -> int (מעוגל לאפס)int(string) -> intint(timestamp) -> int (שניות מאז תקופת האפס)דוגמאות: int(1.5) // 1 |
✓ | ✓ | ✓ | ✓ | ✓ |
string |
הפונקציה ממירה למחרוזת. חתימות: string(T) -> string (תומך ב-bool, int, uint, double, bytes, timestamp, duration)דוגמאות: string(1.5) // "1.5" |
✓ | ✓ | ✓ | ✓ | ✓ |
timestamp |
הפונקציה ממירה לפורמט חותמת זמן. חתימות: timestamp(timestamp) -> timestamptimestamp(string) -> timestamp (RFC3339)דוגמאות: timestamp("2026-07-23T00:00:00Z") |
✓ | ✓ | ✓ | ✓ | ✓ |
uint |
ממירה למספר שלם לא חתום של 64 ביט. חתימות: uint(uint) -> uintuint(int) -> uintuint(double) -> uintuint(string) -> uintדוגמאות: uint(1) // 1u |
✓ | ✓ | ✓ | ✓ | ✓ |
dyn |
הפונקציה ממירה ערך לסוג דינמי לצורך בדיקת סוג. חתימות: dyn(T) -> dynדוגמאות: dyn([1, "two"]) |
✓ | ✓ | ✓ | ✓ | ✗ |
type |
הפונקציה מחזירה את סוג הערך. חתימות: type(T) -> typeדוגמאות: type(1) // int |
✓ | ✓ | ✓ | ✓ | ✗ |
4. תוספים (ספריות)
ספריית כריכות
| פונקציה | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
cel.bind |
הפונקציה מקשרת משתנה מקומי כדי למנוע הערכה כפולה. חתימות: cel.bind(varName, initExpr, resultExpr) -> Tדוגמאות: cel.bind(x, a + b, x * x) |
✓ (גרסה 0.15.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
איך מפעילים את התכונה
- הולכים: מעבירים את
ext.Bindings()אלcel.NewEnv(). - C++: מוסיפים את
BindingsCompilerLibrary()אלCompilerBuilder. (זמן הריצה מטופל באופן אוטומטי). - Java: מוסיפים את
CelExtensions.bindings()ל-CelCompilerול-CelRuntimebuilders. - Python: מייבאים את
cel_expr_python.ext.ext_bindingsומשתמשים ב-ExtBindings()ב-cel.NewEnv(extensions=[...]).
ספריית מקודדים
| פונקציה | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
base64.encode |
מקודד בייטים למחרוזת base64. חתימות: base64.encode(bytes) -> stringדוגמאות: base64.encode(b"hello") // "aGVsbG8=" |
✓ (גרסה 0.6.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
base64.decode |
מפענח מחרוזת base64 לבייטים. הפונקציה מחזירה שגיאה אם הקלט לא תקין. חתימות: base64.decode(string) -> bytesדוגמאות: base64.decode("aGVsbG8=") // b"hello" |
✓ (גרסה 0.6.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
json.encode |
הפונקציה יוצרת סריאליזציה של ערך CEL למחרוזת JSON. חתימות: json.encode(dyn) -> stringדוגמאות: json.encode([1, 2]) // "[1,2]" |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
איך מפעילים את התכונה
- הולכים: מעבירים את
ext.Encoders()אלcel.NewEnv(). - C++:
- קומפיילר: הוספה של
EncodersCompilerLibrary()אלCompilerBuilder. - זמן ריצה: התקשר אל
RegisterEncodersFunctions()בFunctionRegistry.
- קומפיילר: הוספה של
- Java: מוסיפים את
CelExtensions.encoders()ל-CelCompilerול-CelRuntimebuilders. - Python: מייבאים את
cel_expr_python.ext.ext_encodersומשתמשים ב-ExtEncoders()ב-cel.NewEnv(extensions=[...]).
ספריית מתמטיקה
| פונקציה | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
math.greatest |
הפונקציה מחזירה את המספר הגדול ביותר מבין הארגומנטים המספריים (או רשימה של מספרים). חתימות: math.greatest(arg, ...) -> Tדוגמאות: math.greatest(1, 3, 2) // 3 |
✓ (גרסה 0.13.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
math.least |
הפונקציה מחזירה את המספר הקטן ביותר מבין הארגומנטים המספריים (או רשימה של מספרים). חתימות: math.least(arg, ...) -> Tדוגמאות: math.least([1, 3, 2]) // 1 |
✓ (גרסה 0.13.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
math.abs |
ערך מוחלט. חתימות: math.abs(T) -> T (תומך ב-int, uint, double)דוגמאות: math.abs(-1) // 1 |
✓ (גרסה 0.21.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
math.sqrt |
שורש ריבועי. חתימות: math.sqrt(T) -> double (תומך ב-int, uint, double)דוגמאות: math.sqrt(9) // 3.0 |
✓ (גרסה 0.25.1) | ✓ (גרסה 0.12.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.1.1) | ✗ |
math.bitAnd |
ערך AND ברמת הביטים. חתימות: math.bitAnd(T, T) -> T (תומך ב-int, uint)דוגמאות: math.bitAnd(5, 3) // 1 |
✓ (גרסה 0.21.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
math.bitOr |
ערך OR ברמת הסיביות. חתימות: math.bitOr(T, T) -> T (תומך ב-int, uint)דוגמאות: math.bitOr(5, 3) // 7 |
✓ (גרסה 0.21.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
math.bitXor |
ערך XOR ברמת הביטים. חתימות: math.bitXor(T, T) -> T (תומך ב-int, uint)דוגמאות: math.bitXor(5, 3) // 6 |
✓ (גרסה 0.21.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
math.bitNot |
NOT ברמת הסיביות. חתימות: math.bitNot(T) -> T (תומך ב-int, uint)דוגמאות: math.bitNot(1) // -2 |
✓ (גרסה v0.21.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
math.bitShiftLeft |
הזזה שמאלה ברמת הביטים. חתימות: math.bitShiftLeft(T, int) -> T (תומך ב-int, uint)דוגמאות: math.bitShiftLeft(1, 2) // 4 |
✓ (גרסה v0.21.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
math.bitShiftRight |
הזזה בינארית ימינה. חתימות: math.bitShiftRight(T, int) -> T (תומך ב-int, uint)דוגמאות: math.bitShiftRight(4, 2) // 1 |
✓ (גרסה 0.21.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
math.ceil |
עיגול כלפי מעלה. חתימות: math.ceil(double) -> doubleדוגמאות: math.ceil(1.2) // 2.0 |
✓ (גרסה 0.21.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
math.floor |
עיגול כלפי מטה. חתימות: math.floor(double) -> doubleדוגמאות: math.floor(1.8) // 1.0 |
✓ (גרסה 0.21.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
math.round |
עיגול למספר השלם הקרוב ביותר. חתימות: math.round(double) -> doubleדוגמאות: math.round(1.5) // 2.0 |
✓ (גרסה v0.21.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
math.trunc |
עיגול בחיתוך (לכיוון אפס). חתימות: math.trunc(double) -> doubleדוגמאות: math.trunc(-1.8) // -1.0 |
✓ (גרסה v0.21.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
math.isInf |
הפונקציה בודקת אם הערך מסוג double הוא אינסוף חיובי או שלילי. חתימות: math.isInf(double) -> boolדוגמאות: math.isInf(1.0/0.0) // true |
✓ (גרסה v0.21.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
math.isNaN |
בודקת אם הערך מסוג double הוא NaN. חתימות: math.isNaN(double) -> boolדוגמאות: math.isNaN(0.0/0.0) // true |
✓ (גרסה v0.21.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
math.isFinite |
הפונקציה בודקת אם המספר מסוג double הוא סופי. חתימות: math.isFinite(double) -> boolדוגמאות: math.isFinite(1.2) // true |
✓ (גרסה v0.21.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
math.sign |
הפונקציה מחזירה את הסימן של הערך (-1, 0 או 1). חתימות: math.sign(T) -> T (תומכת ב-int, uint, double)דוגמאות: math.sign(-42) // -1 |
✓ (גרסה v0.21.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
איך מפעילים את התכונה
- הולכים: מעבירים את
ext.Math()אלcel.NewEnv(). - C++:
- מהדר: הוספה של
MathCompilerLibrary()אלCompilerBuilder. - זמן ריצה: התקשר אל
RegisterMathExtensionFunctions()בFunctionRegistry.
- מהדר: הוספה של
- Java: מוסיפים את
CelExtensions.math()ל-CelCompilerול-builders שלCelRuntime. - Python: מייבאים את
cel_expr_python.ext.ext_mathומשתמשים ב-ExtMath()ב-cel.NewEnv(extensions=[...]).
ספריית פרוטוקולים
| פונקציה | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
proto.getExt |
מחזירה שדה הרחבה של proto2, או ערך ברירת מחדל אם לא הוגדר ערך. חתימות: proto.getExt(msg, extName) -> Tדוגמאות: proto.getExt(msg, google.api.expr.test.int32_ext) |
✓ (גרסה 0.13.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
proto.hasExt |
בודקת אם שדה ההרחבה proto2 מוגדר. חתימות: proto.hasExt(msg, extName) -> boolדוגמאות: proto.hasExt(msg, google.api.expr.test.int32_ext) |
✓ (גרסה 0.13.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
איך מפעילים את התכונה
- הולכים: מעבירים את
ext.Protos()אלcel.NewEnv(). - C++: מוסיפים את
ProtoExtCompilerLibrary()אלCompilerBuilder. (זמן הריצה מטופל באופן אוטומטי). - Java: מוסיפים את
CelExtensions.protos()ל-CelCompilerול-builders שלCelRuntime. - Python: מייבאים את
cel_expr_python.ext.ext_protoומשתמשים ב-ExtProto()ב-cel.NewEnv(extensions=[...]).
ספריית הרשימות
| פונקציה | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
distinct |
מחזירה רכיבים ייחודיים. חתימות: list.distinct() -> listדוגמאות: [1, 2, 2].distinct() // [1, 2] |
✓ (גרסה 0.22.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.1.1) | ✗ |
flatten |
משטח את הרשימות המקוננות. חתימות: list.flatten([depth]) -> listדוגמאות: [[1], [2, 3]].flatten() // [1, 2, 3] |
✓ (גרסה 0.22.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.7.1) | ✓ (גרסה 0.1.1) | ✗ |
lists.range |
הפונקציה מחזירה רשימה של מספרים שלמים [0, ..., n-1].חתימות: lists.range(int) -> list(int)דוגמאות: lists.range(3) // [0, 1, 2] |
✓ (גרסה 0.22.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
reverse |
הופך את סדר הרשימה. חתימות: list.reverse() -> listדוגמאות: [1, 2].reverse() // [2, 1] |
✓ (גרסה 0.22.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.1.1) | ✗ |
slice |
רשימת משנה של החזרות (ההתחלה כוללת, הסוף לא כולל). חתימות: list.slice(start, end) -> listדוגמאות: [1, 2, 3].slice(1, 3) // [2, 3] |
✓ (גרסה 0.17.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.1.1) | ✗ |
sort |
ממיין רשימה של רכיבים להשוואה. חתימות: list.sort() -> listדוגמאות: [3, 1, 2].sort() // [1, 2, 3] |
✓ (גרסה 0.22.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.1.1) | ✗ |
sortBy |
ממיין את הרשימה לפי מפתח שמוערך מתוך הביטוי. חתימות: list.sortBy(var, expr) -> listדוגמאות: [{"val": 2}, {"val": 1}].sortBy(x, x.val) // [{"val": 1}, {"val": 2}] |
✓ (גרסה 0.22.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.1.1) | ✗ |
first |
הפונקציה מחזירה את הרכיב הראשון כאופציונלי. נדרש התוסף Optional. חתימות: list.first() -> optionalדוגמאות: [1, 2].first() // optional(1) |
✓ (גרסה v0.23.0) | ✓ (גרסה 0.15.0) | ✓ (גרסה 0.11.0) | ✓ (v0.1.2) | ✗ |
last |
מחזירה את הרכיב האחרון כאופציונלי. נדרש התוסף Optional. חתימות: list.last() -> optionalדוגמאות: [1, 2].last() // optional(2) |
✓ (גרסה v0.23.0) | ✓ (גרסה 0.15.0) | ✓ (גרסה 0.11.0) | ✓ (v0.1.2) | ✗ |
איך מפעילים את התכונה
- הולכים: מעבירים את
ext.Lists()אלcel.NewEnv(). - C++:
- קומפיילר: הוספה של
ListsCompilerLibrary()אלCompilerBuilder. - זמן ריצה: שיחה אל
RegisterListsFunctions()בFunctionRegistryואלRegisterListsMacros()בMacroRegistry.
- קומפיילר: הוספה של
- Java: מוסיפים את
CelExtensions.lists()אלCelCompilerואל builders שלCelRuntime. - Python: מפעילים דרך
cel.EnvConfigעל ידי הוספתlistsלרשימהextensionslist.
ספריית סטים
| פונקציה | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
sets.contains |
הפונקציה בודקת אם רשימה1 מכילה את כל הרכיבים של רשימה2. חתימות: sets.contains(list1, list2) -> boolדוגמאות: sets.contains([1, 2], [1]) // true |
✓ (גרסה 0.15.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה 0.6.0) | ✓ (גרסה 0.1.1) | ✗ |
sets.equivalent |
הפונקציה בודקת אם רשימות הן שוות (מכילות את אותם רכיבים ייחודיים). חתימות: sets.equivalent(list1, list2) -> boolדוגמאות: sets.equivalent([1, 2], [2, 1, 1]) // true |
✓ (גרסה 0.15.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה 0.6.0) | ✓ (גרסה 0.1.1) | ✗ |
sets.intersects |
הפונקציה בודקת אם יש לפחות רכיב אחד משותף ברשימות. חתימות: sets.intersects(list1, list2) -> boolדוגמאות: sets.intersects([1, 2], [2, 3]) // true |
✓ (גרסה 0.15.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה 0.6.0) | ✓ (גרסה 0.1.1) | ✗ |
איך מפעילים את התכונה
- הולכים: מעבירים את
ext.Sets()אלcel.NewEnv(). - C++:
- קומפיילר: הוספה של
SetsCompilerLibrary()אלCompilerBuilder. - זמן ריצה: התקשר אל
RegisterSetsFunctions()בFunctionRegistry.
- קומפיילר: הוספה של
- Java: מוסיפים את
CelExtensions.sets()אלCelCompilerואל builders שלCelRuntime. - Python: מפעילים דרך
cel.EnvConfigעל ידי הוספתsetsלרשימהextensionslist.
ספריית מחרוזות
| פונקציה | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
charAt |
הפונקציה מחזירה את התו באינדקס. חתימות: string.charAt(int) -> stringדוגמאות: "hello".charAt(1) // "e" |
✓ (גרסה 0.4.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
indexOf |
הפונקציה מחזירה את האינדקס של המופע הראשון של מחרוזת המשנה, או את הערך -1. חתימות: string.indexOf(substr, [start]) -> intדוגמאות: "hello".indexOf("l") // 2 |
✓ (גרסה 0.4.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
lastIndexOf |
הפונקציה מחזירה את האינדקס של המופע האחרון של מחרוזת משנה, או את הערך -1. חתימות: string.lastIndexOf(substr, [end]) -> intדוגמאות: "hello".lastIndexOf("l") // 3 |
✓ (גרסה 0.4.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
join |
משרשרת מחרוזות. חתימות: list(string).join([separator]) -> stringדוגמאות: ["a", "b"].join("-") // "a-b" |
✓ (גרסה 0.10.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
split |
מפצלת מחרוזת לפי מפריד. חתימות: string.split(separator, [limit]) -> list(string)דוגמאות: "a-b".split("-") // ["a", "b"] |
✓ (גרסה 0.4.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
substring |
מחזירה מחרוזת משנה (ההתחלה כוללת, הסוף לא כולל). חתימות: string.substring(start, [end]) -> stringדוגמאות: "hello".substring(1, 3) // "el" |
✓ (גרסה 0.4.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
trim |
חיתוך רווחים לבנים ב-Unicode. חתימות: string.trim() -> stringדוגמאות: " hello ".trim() // "hello" |
✓ (גרסה 0.4.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
replace |
מחליפה את המופעים של old ב-new. חתימות: string.replace(old, new, [limit]) -> stringדוגמאות: "hello".replace("l", "w") // "hewwo" |
✓ (גרסה 0.4.0) | ✓ (גרסה 0.10.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
reverse |
הפונקציה הופכת את מיקומי התווים (code points) ב-Unicode. חתימות: string.reverse() -> stringדוגמאות: "abc".reverse() // "cba" |
✓ (גרסה 0.18.0) | ✓ (גרסה 0.14.0) | ✓ (גרסה 0.13.0) | ✓ (גרסה 0.1.1) | ✗ |
lowerAscii |
הפונקציה ממירה תווים מסוג ASCII לאותיות קטנות. חתימות: string.lowerAscii() -> stringדוגמאות: "Hello".lowerAscii() // "hello" |
✓ (גרסה 0.6.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
upperAscii |
ממירה תווים של ASCII לאותיות רישיות. חתימות: string.upperAscii() -> stringדוגמאות: "Hello".upperAscii() // "HELLO" |
✓ (גרסה 0.6.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה v0.2.0) | ✓ (גרסה 0.1.1) | ✗ |
quote |
הפונקציה מסירה תווים מיוחדים ממחרוזת כדי לאפשר הדפסה בטוחה. חתימות: strings.quote(string) -> stringדוגמאות: strings.quote("a\tb") // "\"a\\tb\"" |
✓ (גרסה 0.14.0) | ✓ (v0.14.0) | ✓ (גרסה 0.13.0) | ✓ (גרסה 0.1.1) | ✗ |
format |
הפונקציה מעצבת את המחרוזת באמצעות placeholders בסגנון printf. חתימות: string.format(list) -> stringדוגמאות: "str: %s, int: %d".format(["a", 1]) // "str: a, int: 1" |
✓ (גרסה 0.14.0) | ✓ (גרסה 0.11.0) | ✗ | ✓ (גרסה 0.1.1) | ✗ |
איך מפעילים את התכונה
- הולכים: מעבירים את
ext.Strings()אלcel.NewEnv(). - C++:
- קומפיילר: הוספה של
StringsCompilerLibrary()אלCompilerBuilder. - זמן ריצה: התקשר אל
RegisterStringsFunctions()בFunctionRegistry.
- קומפיילר: הוספה של
- Java: מוסיפים את
CelExtensions.strings()אלCelCompilerואל builders שלCelRuntime. - Python: מייבאים את
cel_expr_python.ext.ext_stringsומשתמשים ב-ExtStrings()ב-cel.NewEnv(extensions=[...]).
ספריית ביטויים רגולריים
| פונקציה | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
regex.replace |
הפונקציה מחליפה התאמות במחרוזת החלפה (תומכת בהפניות חוזרות). חתימות: regex.replace(target, pat, repl, [limit]) -> stringדוגמאות: regex.replace("123-456", r"(\d+)-(\d+)", r"\2-\1") // "456-123" |
✓ (גרסה 0.25.1) | ✓ (גרסה 0.13.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
regex.extract |
הפונקציה מחזירה את ההתאמה הראשונה של התבנית (חייבת להיות קבוצה אחת לחילוץ). חתימות: regex.extract(target, pat) -> optional(string)דוגמאות: regex.extract("a123b", r"(\d+)") // optional("123") |
✓ (גרסה 0.25.1) | ✓ (גרסה 0.13.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
regex.extractAll |
הפונקציה מחזירה את כל ההתאמות של התבנית (חייבת להיות קבוצה אחת לחילוץ). חתימות: regex.extractAll(target, pat) -> list(string)דוגמאות: regex.extractAll("a1b2", r"(\d+)") // ["1", "2"] |
✓ (גרסה 0.25.1) | ✓ (גרסה 0.13.0) | ✓ (גרסה 0.10.1) | ✓ (גרסה 0.1.1) | ✗ |
איך מפעילים את התכונה
- הולכים: מעבירים את
ext.Regex()אלcel.NewEnv(). - C++:
- מהדר: הוספה של
RegexExtCompilerLibrary()אלCompilerBuilder. - זמן ריצה: התקשר אל
RegisterRegexExtensionFunctions()בFunctionRegistry.
- מהדר: הוספה של
- Java: מוסיפים את
CelExtensions.regex()ל-CelCompilerול-builders שלCelRuntime. - Python: כדי להפעיל את התוסף דרך
cel.EnvConfig, מוסיפים אתregexואתoptionalלרשימהextensions.
הבנות של שני משתנים
| Macro | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
all |
קיצור דרך לוגי של AND על מפתח/אינדקס וערך. חתימות: list.all(i, v, pred) -> boolmap.all(k, v, pred) -> boolדוגמאות: [1, 2].all(i, v, v > 0) // true |
✓ (גרסה 0.22.0) | ✓ (גרסה 0.14.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.1.1) | ✗ |
exists |
קיצור דרך לוגי של OR על מפתח/אינדקס וערך. חתימות: list.exists(i, v, pred) -> boolmap.exists(k, v, pred) -> boolדוגמאות: [1, 2].exists(i, v, v == 2) // true |
✓ (גרסה 0.22.0) | ✓ (גרסה 0.14.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.1.1) | ✗ |
existsOne |
הפונקציה בודקת אם יש בדיוק זוג אחד שעומד בתנאי. חתימות: list.existsOne(i, v, pred) -> boolmap.existsOne(k, v, pred) -> boolדוגמאות: [1, 2].existsOne(i, v, v == 2) // true |
✓ (גרסה 0.22.0) | ✓ (גרסה 0.14.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.1.1) | ✗ |
transformList |
הופך/מסנן רשימה/מפה לרשימה. חתימות: list.transformList(i, v, [filter], transform) -> listmap.transformList(k, v, [filter], transform) -> listדוגמאות: [1, 2].transformList(i, v, v * 2) // [2, 4] |
✓ (גרסה 0.22.0) | ✓ (גרסה 0.14.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.1.1) | ✗ |
transformMap |
הפונקציה ממירה ערכים של רשימה או מפה למפה (המפתחות נשארים קבועים). חתימות: list.transformMap(i, v, [filter], transform) -> mapmap.transformMap(k, v, [filter], transform) -> mapדוגמאות: [1, 2].transformMap(i, v, v * 2) // {0: 2, 1: 4} |
✓ (גרסה 0.22.0) | ✓ (גרסה 0.14.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.1.1) | ✗ |
transformMapEntry |
הופך למפה. חתימות: list.transformMapEntry(i, v, [filter], transform_entry) -> mapmap.transformMapEntry(k, v, [filter], transform_entry) -> mapדוגמאות: [1, 2].transformMapEntry(i, v, {string(v): v * 2}) // {"1": 2, "2": 4} |
✓ (גרסה 0.22.0) | ✓ (גרסה 0.14.0) | ✓ (גרסה 0.11.0) | ✓ (גרסה 0.1.1) | ✗ |
איך מפעילים את התכונה
- הולכים: מעבירים את
ext.TwoVarComprehensions()אלcel.NewEnv(). - C++:
- קומפיילר: הוספה של
ComprehensionsV2CompilerLibrary()אלCompilerBuilder. - זמן ריצה: שיחה אל
RegisterComprehensionsV2Functions()בFunctionRegistryואלRegisterComprehensionsV2Macros()בMacroRegistry.
- קומפיילר: הוספה של
- Java: מוסיפים את
CelExtensions.comprehensions()ל-CelCompilerול-CelRuntime. - Python: מפעילים דרך
cel.EnvConfigעל ידי הוספתtwo-var-comprehensionsלרשימהextensions.
ספריית סוגים מקוריים
| תכונה | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
| מבני נתונים מקוריים | רישום והפעלת סוגי נייטיב של מארח (מבני Go / אובייקטים פשוטים של Java) ב-CEL. דוגמאות: Account{id: 123} (אובייקט פשוט של Java שהופעל ב-CEL) |
✓ (גרסה 0.13.0) | ✗ | ✓ (גרסה 0.13.0) | ✗ | ✗ |
איך מפעילים את התכונה
- הוראה: מעבירים את
ext.NativeTypes(...)(עם סוגי ההשתקפות) אלcel.NewEnv(). - C++: אין תמיכה.
- Java: מוסיפים
CelExtensions.nativeTypes()(שמספק מחלקות Java) ל-buildersCelCompilerו-CelRuntime. - Python: לא אפשרי.
ספריית רשת
ספריית הרשת מספקת פונקציות לניתוח, לאימות ולשינוי של כתובות IP ובלוקים של CIDR.
| פונקציה | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
ip |
הפונקציה מנתחת מחרוזת לכתובת IP, או מחלצת את כתובת ה-IP מ-CIDR. חתימות: ip(string) -> IPCIDR.ip() -> IPדוגמאות: ip("192.168.0.1")cidr("192.168.0.0/24").ip() |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isIP |
הפונקציה בודקת אם מחרוזת היא כתובת IP חוקית. חתימות: isIP(string) -> boolדוגמאות: isIP("192.168.0.1") // true |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
ip.isCanonical |
הפונקציה בודקת אם מחרוזת של כתובת IP היא בפורמט קנוני. חתימות: ip.isCanonical(string) -> boolדוגמאות: ip.isCanonical("192.168.0.1") // true |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
cidr |
הפונקציה מנתחת מחרוזת לבלוק CIDR. חתימות: cidr(string) -> CIDRדוגמאות: cidr("192.168.0.0/24") |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isCIDR |
בודקת אם מחרוזת היא בלוק CIDR תקין. חתימות: isCIDR(string) -> boolדוגמאות: isCIDR("192.168.0.0/24") // true |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
containsIP |
הפונקציה בודקת אם בלוק CIDR מכיל כתובת IP. חתימות: CIDR.containsIP(IP) -> boolCIDR.containsIP(string) -> boolדוגמאות: cidr("192.168.0.0/24").containsIP(ip("192.168.0.1")) // true |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
containsCIDR |
בודקת אם בלוק CIDR מכיל בלוק CIDR אחר. חתימות: CIDR.containsCIDR(CIDR) -> boolCIDR.containsCIDR(string) -> boolדוגמאות: cidr("192.168.0.0/16").containsCIDR(cidr("192.168.1.0/24")) // true |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
family |
הפונקציה מחזירה את משפחת ה-IP (4 ל-IPv4, 6 ל-IPv6). חתימות: IP.family() -> intדוגמאות: ip("192.168.0.1").family() // 4 |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isGlobalUnicast |
הפונקציה בודקת אם כתובת ה-IP היא כתובת unicast גלובלית. חתימות: IP.isGlobalUnicast() -> boolדוגמאות: ip("192.168.0.1").isGlobalUnicast() // true |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLinkLocalMulticast |
הפונקציה בודקת אם כתובת ה-IP היא כתובת מולטיקאסט מקומית לקישור. חתימות: IP.isLinkLocalMulticast() -> boolדוגמאות: ip("224.0.0.1").isLinkLocalMulticast() // true |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLinkLocalUnicast |
הפונקציה בודקת אם כתובת ה-IP היא כתובת unicast מקומית לקישור. חתימות: IP.isLinkLocalUnicast() -> boolדוגמאות: ip("169.254.0.1").isLinkLocalUnicast() // true |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLoopback |
הפונקציה בודקת אם כתובת ה-IP היא כתובת לולאה חוזרת. חתימות: IP.isLoopback() -> boolדוגמאות: ip("127.0.0.1").isLoopback() // true |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isMask |
בודקת אם ה-CIDR הוא מסכה של רשת משנה חוקית. חתימות: CIDR.isMask() -> boolדוגמאות: cidr("255.255.255.0/24").isMask() // true |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isUnspecified |
הפונקציה בודקת אם כתובת ה-IP היא כתובת לא מוגדרת (למשל 0.0.0.0).חתימות: IP.isUnspecified() -> boolדוגמאות: ip("0.0.0.0").isUnspecified() // true |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
masked |
הפונקציה מחזירה את בלוק ה-CIDR המוסווה. חתימות: CIDR.masked() -> CIDRדוגמאות: cidr("192.168.0.1/24").masked() // 192.168.0.0/24 |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
prefixLength |
הפונקציה מחזירה את אורך הקידומת של בלוק ה-CIDR. חתימות: CIDR.prefixLength() -> intדוגמאות: cidr("192.168.0.0/24").prefixLength() // 24 |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
string |
הפונקציה ממירה כתובת IP או CIDR למחרוזת. חתימות: string(IP) -> stringstring(CIDR) -> stringדוגמאות: string(ip("192.168.0.1")) // "192.168.0.1" |
✓ (גרסה v0.29.0) | ✗ | ✗ | ✗ | ✗ |
איך מפעילים את התכונה
- הולכים: מעבירים את
ext.Network()אלcel.NewEnv(). - C++: אין תמיכה.
- Java: לא אפשרי.
- Python: לא אפשרי.
5. תכונות מתקדמות
סיכום התכונות המתקדמות
| תכונה | תיאור | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
| Partial Evaluation | הערכה עם קלט חסר; מחזירה ערכים לא ידועים או ביטוי פשוט. | ✓³ | ✓⁴ | ✓⁴ | ✗ | ✗ |
| Async Evaluation | ביצוע מקביל של פונקציות של תוספים שלא חוסם את הפעולה. | ✓⁵ | ✗ | ✓⁶ | ✗ | ✗ |
| כלי אימות של AST | בדיקות ניתוח סטטי מתבצעות ב-Checked AST אחרי בדיקת הסוג. | ✓ | ✓ | ✓ | ✗ | ✗ |
| AST Optimizers | שכתוב של AST (קיפול קבוע, הטמעה, CSE) כדי לשפר את הביצועים. | ✓ | ✓ | ✓ | ✗ | ✗ |
| מהדר המדיניות של CEL | הכלי קומפל מבני מדיניות מבוססי YAML ל-ASTs סטנדרטיים של CEL. | ✓ | ✓ | ✓ | ✗ | ✗ |
³ Go תומכת ביצירת Residual AST (AST שנחתך). ⁴ תמיכה ב-C++ וב-Java בהחזרת UnknownSet / CelUnknownSet בזמן ריצה, אבל אין חשיפה של ממשקי API ציבוריים ליצירת AST שיורי. ⁵ Go משתמש ב-AsyncBinding / AsyncOp להחזרת ערוצים. ⁶ Java משתמשת ב-CelAsyncRuntime ומחזירה ListenableFuture.
הערכה חלקית (לא ידועים)
הערכה חלקית מאפשרת להעריך ביטוי כשמוכרים רק חלק מהמשתנים (הארגומנטים) של הקלט. במקום להיכשל, ההערכה מפיקה תוצאה שמציינת מה חסר, או ביטוי פשוט יותר.
- Go: תמיכה מלאה. מאפשרת להגדיר
PartialActivationעם תבניות של מאפיינים לא מוכרים. הערכה מחזירה ערךtypes.Unknown. Go תומכת ביצירה של AST שיורי (Env.ResidualAst), שהוא AST מצומצם ופשוט שמכיל רק את החלקים של הביטוי שלא ניתן להעריך. - C++: תומך בערכי
Unknown. תבניות לא ידועות של מאפיינים מוגדרות דרךActivation::set_unknown_attribute_patterns. הפונקציה Evaluation מחזירה את הערךUnknownSet. בשלב הזה, ה-API הציבורי לא חושף יצירה שיורית של AST. - Java: תומך בהערכה חלקית באמצעות
PartialVarsשמועבר אלProgram.eval(). הערכה מחזירהCelUnknownSet. ממשק ה-API הציבורי לא חושף כרגע יצירת AST שיורית. - Python / C: אין תמיכה מקורית.
הערכה אסינכרונית
הערכה אסינכרונית מאפשרת לביטויי CEL לקרוא לפונקציות שמופעלות באופן אסינכרוני (למשל, ביצוע RPC או שאילתות במסד נתונים) ולחסום את ההערכה עד שהתוצאות יהיו זמינות, בלי לחסום את השרשור הראשי של ההפעלה.
- Go: תומך בהעמסת פונקציות אסינכרוניות באמצעות
AsyncBindingו-AsyncOp. פונקציות אסינכרוניות מחזירות ערוץ Go (<-chan ref.Val), והמתורגמן מנהל את הביצוע והסנכרון בו-זמנית. - Java: תומכת בהערכה אסינכרונית באמצעות
CelAsyncRuntimeו-AsyncProgram. הוא משתמש ב-ListenableFutureכדי לייצג ערכים בהמתנה, ומבצע הערכה עד לסיום באופן אוטומטי כשהערכים העתידיים נפתרים. - C++ / Python / C: אין תמיכה מובנית.
כלי אימות AST
כדי לאכוף אילוצים ספציפיים לדומיין לפני הפעלת התוכנית, מאמתים מבצעים ניתוח סטטי ב-AST שנבדק אחרי בדיקת הסוג.
- Go: תמיכה בממשק
ASTValidator. בין כלי האימות הקנוניים אפשר למצוא אתcel.validator.duration,cel.validator.timestamp,cel.validator.matches(ביטוי רגולרי),cel.validator.homogeneous_literalsו-cel.validator.comprehension_nesting_limit. - C++: תמיכה בערך
cel::Validator. האימותים הקנוניים כוללים אתAstDepthValidator,ComprehensionNestingLimitValidator,DurationLiteralValidator,HomogeneousLiteralValidator,MatchesValidatorו-TimestampLiteralValidator. - Java: תומך ב-
CelValidatorוב-CelAstValidator. בין כלי האימות הקנוניים אפשר למצוא אתAstDepthLimitValidator,ComprehensionNestingLimitValidator,DurationLiteralValidator,HomogeneousLiteralValidator,RegexLiteralValidatorו-TimestampLiteralValidator. - Python / C: אין תמיכה ישירה.
אופטימיזציות של AST
האופטימיזטורים כותבים מחדש את ה-AST כדי לשפר את ביצועי ההרצה. אופטימיזציה מתחלקת לשתי קטגוריות: אופטימיזציה סטטית ואופטימיזציה בזמן ריצה. C++, Java ו-Go תומכות באופטימיזציה של זמן ריצה. CEL Java ו-Go תומכות גם באופטימיזציות סטטיות.
אופטימיזציות אופייניות כוללות קיפול קבוע (הערכה מראש של ביטויי משנה עם קבועים כקלט) וביטול של ביטויי משנה משותפים (CSE).
- Go: תומך בקיפול AST במהלך קומפילציה או תכנון.
- C++: תומך בקיפול קבוע באמצעות התוסף
cel::extensions::EnableConstantFoldingבזמן התכנון. - Java: תמיכה בממשק
CelOptimizer. אופטימיזציות קנוניות כוללות אתConstantFoldingOptimizer(שיכול לקפל ענפים של מעגלים קצרים על ידי סימול של הערכה חלקית),InliningOptimizerו-SubexpressionOptimizer(CSE). - Python / C: אין תמיכה ישירה.
מהדר מדיניות CEL
מדיניות CEL היא פורמט מבוסס-YAML ליצירת מספר ביטויי CEL יחד עם משתנים, בלוקים של התאמות, פלט מותנה וכללים מקוננים. הוא מיועד למנועי מדיניות מורכבים (כמו Kubernetes Admission Control) שבהם ביטויי CEL בודדים יהפכו לבלתי קריאים.
הגדרה רשמית של השפה, תחביר וחבילת כלים לבדיקת תאימות מפורטים במפרט המדיניות של CEL.
הקומפיילר של המדיניות מקמפל את מדיניות ה-YAML הזו ל-AST CEL רגיל יחיד, כלומר היא תואמת באופן מלא לזמני ריצה רגילים של CEL ומקבלת בירושה את כל הביצועים והבטיחות.
- Go: נתמך באמצעות מדיניות Go.
- C++: נתמך באמצעות מדיניות C++.
- Java: נתמך באמצעות מדיניות Java.
- Python / C: אין תמיכה ישירה.