mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
rebase: update kubernetes to latest
updating the kubernetes release to the latest in main go.mod Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
committed by
mergify[bot]
parent
63c4c05b35
commit
5a66991bb3
16
vendor/github.com/google/cel-go/common/ast/BUILD.bazel
generated
vendored
16
vendor/github.com/google/cel-go/common/ast/BUILD.bazel
generated
vendored
@ -1,12 +1,7 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
package(
|
||||
default_visibility = [
|
||||
"//cel:__subpackages__",
|
||||
"//checker:__subpackages__",
|
||||
"//common:__subpackages__",
|
||||
"//interpreter:__subpackages__",
|
||||
],
|
||||
default_visibility = ["//visibility:public"],
|
||||
licenses = ["notice"], # Apache 2.0
|
||||
)
|
||||
|
||||
@ -14,10 +9,14 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"ast.go",
|
||||
"conversion.go",
|
||||
"expr.go",
|
||||
"factory.go",
|
||||
"navigable.go",
|
||||
],
|
||||
importpath = "github.com/google/cel-go/common/ast",
|
||||
deps = [
|
||||
"//common:go_default_library",
|
||||
"//common/types:go_default_library",
|
||||
"//common/types/ref:go_default_library",
|
||||
"@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
|
||||
@ -29,7 +28,9 @@ go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"ast_test.go",
|
||||
"conversion_test.go",
|
||||
"expr_test.go",
|
||||
"navigable_test.go",
|
||||
],
|
||||
embed = [
|
||||
":go_default_library",
|
||||
@ -48,5 +49,6 @@ go_test(
|
||||
"//test/proto3pb:go_default_library",
|
||||
"@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
"@org_golang_google_protobuf//encoding/prototext:go_default_library",
|
||||
],
|
||||
)
|
||||
)
|
||||
|
480
vendor/github.com/google/cel-go/common/ast/ast.go
generated
vendored
480
vendor/github.com/google/cel-go/common/ast/ast.go
generated
vendored
@ -16,74 +16,361 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/cel-go/common"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
|
||||
structpb "google.golang.org/protobuf/types/known/structpb"
|
||||
|
||||
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
|
||||
)
|
||||
|
||||
// CheckedAST contains a protobuf expression and source info along with CEL-native type and reference information.
|
||||
type CheckedAST struct {
|
||||
Expr *exprpb.Expr
|
||||
SourceInfo *exprpb.SourceInfo
|
||||
TypeMap map[int64]*types.Type
|
||||
ReferenceMap map[int64]*ReferenceInfo
|
||||
// AST contains a protobuf expression and source info along with CEL-native type and reference information.
|
||||
type AST struct {
|
||||
expr Expr
|
||||
sourceInfo *SourceInfo
|
||||
typeMap map[int64]*types.Type
|
||||
refMap map[int64]*ReferenceInfo
|
||||
}
|
||||
|
||||
// CheckedASTToCheckedExpr converts a CheckedAST to a CheckedExpr protobouf.
|
||||
func CheckedASTToCheckedExpr(ast *CheckedAST) (*exprpb.CheckedExpr, error) {
|
||||
refMap := make(map[int64]*exprpb.Reference, len(ast.ReferenceMap))
|
||||
for id, ref := range ast.ReferenceMap {
|
||||
r, err := ReferenceInfoToReferenceExpr(ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
refMap[id] = r
|
||||
// Expr returns the root ast.Expr value in the AST.
|
||||
func (a *AST) Expr() Expr {
|
||||
if a == nil {
|
||||
return nilExpr
|
||||
}
|
||||
typeMap := make(map[int64]*exprpb.Type, len(ast.TypeMap))
|
||||
for id, typ := range ast.TypeMap {
|
||||
t, err := types.TypeToExprType(typ)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
typeMap[id] = t
|
||||
}
|
||||
return &exprpb.CheckedExpr{
|
||||
Expr: ast.Expr,
|
||||
SourceInfo: ast.SourceInfo,
|
||||
ReferenceMap: refMap,
|
||||
TypeMap: typeMap,
|
||||
}, nil
|
||||
return a.expr
|
||||
}
|
||||
|
||||
// CheckedExprToCheckedAST converts a CheckedExpr protobuf to a CheckedAST instance.
|
||||
func CheckedExprToCheckedAST(checked *exprpb.CheckedExpr) (*CheckedAST, error) {
|
||||
refMap := make(map[int64]*ReferenceInfo, len(checked.GetReferenceMap()))
|
||||
for id, ref := range checked.GetReferenceMap() {
|
||||
r, err := ReferenceExprToReferenceInfo(ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
refMap[id] = r
|
||||
// SourceInfo returns the source metadata associated with the parse / type-check passes.
|
||||
func (a *AST) SourceInfo() *SourceInfo {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
typeMap := make(map[int64]*types.Type, len(checked.GetTypeMap()))
|
||||
for id, typ := range checked.GetTypeMap() {
|
||||
t, err := types.ExprTypeToType(typ)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
typeMap[id] = t
|
||||
return a.sourceInfo
|
||||
}
|
||||
|
||||
// GetType returns the type for the expression at the given id, if one exists, else types.DynType.
|
||||
func (a *AST) GetType(id int64) *types.Type {
|
||||
if t, found := a.TypeMap()[id]; found {
|
||||
return t
|
||||
}
|
||||
return &CheckedAST{
|
||||
Expr: checked.GetExpr(),
|
||||
SourceInfo: checked.GetSourceInfo(),
|
||||
ReferenceMap: refMap,
|
||||
TypeMap: typeMap,
|
||||
}, nil
|
||||
return types.DynType
|
||||
}
|
||||
|
||||
// SetType sets the type of the expression node at the given id.
|
||||
func (a *AST) SetType(id int64, t *types.Type) {
|
||||
if a == nil {
|
||||
return
|
||||
}
|
||||
a.typeMap[id] = t
|
||||
}
|
||||
|
||||
// TypeMap returns the map of expression ids to type-checked types.
|
||||
//
|
||||
// If the AST is not type-checked, the map will be empty.
|
||||
func (a *AST) TypeMap() map[int64]*types.Type {
|
||||
if a == nil {
|
||||
return map[int64]*types.Type{}
|
||||
}
|
||||
return a.typeMap
|
||||
}
|
||||
|
||||
// GetOverloadIDs returns the set of overload function names for a given expression id.
|
||||
//
|
||||
// If the expression id is not a function call, or the AST is not type-checked, the result will be empty.
|
||||
func (a *AST) GetOverloadIDs(id int64) []string {
|
||||
if ref, found := a.ReferenceMap()[id]; found {
|
||||
return ref.OverloadIDs
|
||||
}
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// ReferenceMap returns the map of expression id to identifier, constant, and function references.
|
||||
func (a *AST) ReferenceMap() map[int64]*ReferenceInfo {
|
||||
if a == nil {
|
||||
return map[int64]*ReferenceInfo{}
|
||||
}
|
||||
return a.refMap
|
||||
}
|
||||
|
||||
// SetReference adds a reference to the checked AST type map.
|
||||
func (a *AST) SetReference(id int64, r *ReferenceInfo) {
|
||||
if a == nil {
|
||||
return
|
||||
}
|
||||
a.refMap[id] = r
|
||||
}
|
||||
|
||||
// IsChecked returns whether the AST is type-checked.
|
||||
func (a *AST) IsChecked() bool {
|
||||
return a != nil && len(a.TypeMap()) > 0
|
||||
}
|
||||
|
||||
// NewAST creates a base AST instance with an ast.Expr and ast.SourceInfo value.
|
||||
func NewAST(e Expr, sourceInfo *SourceInfo) *AST {
|
||||
if e == nil {
|
||||
e = nilExpr
|
||||
}
|
||||
return &AST{
|
||||
expr: e,
|
||||
sourceInfo: sourceInfo,
|
||||
typeMap: make(map[int64]*types.Type),
|
||||
refMap: make(map[int64]*ReferenceInfo),
|
||||
}
|
||||
}
|
||||
|
||||
// NewCheckedAST wraps an parsed AST and augments it with type and reference metadata.
|
||||
func NewCheckedAST(parsed *AST, typeMap map[int64]*types.Type, refMap map[int64]*ReferenceInfo) *AST {
|
||||
return &AST{
|
||||
expr: parsed.Expr(),
|
||||
sourceInfo: parsed.SourceInfo(),
|
||||
typeMap: typeMap,
|
||||
refMap: refMap,
|
||||
}
|
||||
}
|
||||
|
||||
// Copy creates a deep copy of the Expr and SourceInfo values in the input AST.
|
||||
//
|
||||
// Copies of the Expr value are generated using an internal default ExprFactory.
|
||||
func Copy(a *AST) *AST {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
e := defaultFactory.CopyExpr(a.expr)
|
||||
if !a.IsChecked() {
|
||||
return NewAST(e, CopySourceInfo(a.SourceInfo()))
|
||||
}
|
||||
typesCopy := make(map[int64]*types.Type, len(a.typeMap))
|
||||
for id, t := range a.typeMap {
|
||||
typesCopy[id] = t
|
||||
}
|
||||
refsCopy := make(map[int64]*ReferenceInfo, len(a.refMap))
|
||||
for id, r := range a.refMap {
|
||||
refsCopy[id] = r
|
||||
}
|
||||
return NewCheckedAST(NewAST(e, CopySourceInfo(a.SourceInfo())), typesCopy, refsCopy)
|
||||
}
|
||||
|
||||
// MaxID returns the upper-bound, non-inclusive, of ids present within the AST's Expr value.
|
||||
func MaxID(a *AST) int64 {
|
||||
visitor := &maxIDVisitor{maxID: 1}
|
||||
PostOrderVisit(a.Expr(), visitor)
|
||||
for id, call := range a.SourceInfo().MacroCalls() {
|
||||
PostOrderVisit(call, visitor)
|
||||
if id > visitor.maxID {
|
||||
visitor.maxID = id + 1
|
||||
}
|
||||
}
|
||||
return visitor.maxID + 1
|
||||
}
|
||||
|
||||
// NewSourceInfo creates a simple SourceInfo object from an input common.Source value.
|
||||
func NewSourceInfo(src common.Source) *SourceInfo {
|
||||
var lineOffsets []int32
|
||||
var desc string
|
||||
baseLine := int32(0)
|
||||
baseCol := int32(0)
|
||||
if src != nil {
|
||||
desc = src.Description()
|
||||
lineOffsets = src.LineOffsets()
|
||||
// Determine whether the source metadata should be computed relative
|
||||
// to a base line and column value. This can be determined by requesting
|
||||
// the location for offset 0 from the source object.
|
||||
if loc, found := src.OffsetLocation(0); found {
|
||||
baseLine = int32(loc.Line()) - 1
|
||||
baseCol = int32(loc.Column())
|
||||
}
|
||||
}
|
||||
return &SourceInfo{
|
||||
desc: desc,
|
||||
lines: lineOffsets,
|
||||
baseLine: baseLine,
|
||||
baseCol: baseCol,
|
||||
offsetRanges: make(map[int64]OffsetRange),
|
||||
macroCalls: make(map[int64]Expr),
|
||||
}
|
||||
}
|
||||
|
||||
// CopySourceInfo creates a deep copy of the MacroCalls within the input SourceInfo.
|
||||
//
|
||||
// Copies of macro Expr values are generated using an internal default ExprFactory.
|
||||
func CopySourceInfo(info *SourceInfo) *SourceInfo {
|
||||
if info == nil {
|
||||
return nil
|
||||
}
|
||||
rangesCopy := make(map[int64]OffsetRange, len(info.offsetRanges))
|
||||
for id, off := range info.offsetRanges {
|
||||
rangesCopy[id] = off
|
||||
}
|
||||
callsCopy := make(map[int64]Expr, len(info.macroCalls))
|
||||
for id, call := range info.macroCalls {
|
||||
callsCopy[id] = defaultFactory.CopyExpr(call)
|
||||
}
|
||||
return &SourceInfo{
|
||||
syntax: info.syntax,
|
||||
desc: info.desc,
|
||||
lines: info.lines,
|
||||
baseLine: info.baseLine,
|
||||
baseCol: info.baseCol,
|
||||
offsetRanges: rangesCopy,
|
||||
macroCalls: callsCopy,
|
||||
}
|
||||
}
|
||||
|
||||
// SourceInfo records basic information about the expression as a textual input and
|
||||
// as a parsed expression value.
|
||||
type SourceInfo struct {
|
||||
syntax string
|
||||
desc string
|
||||
lines []int32
|
||||
baseLine int32
|
||||
baseCol int32
|
||||
offsetRanges map[int64]OffsetRange
|
||||
macroCalls map[int64]Expr
|
||||
}
|
||||
|
||||
// SyntaxVersion returns the syntax version associated with the text expression.
|
||||
func (s *SourceInfo) SyntaxVersion() string {
|
||||
if s == nil {
|
||||
return ""
|
||||
}
|
||||
return s.syntax
|
||||
}
|
||||
|
||||
// Description provides information about where the expression came from.
|
||||
func (s *SourceInfo) Description() string {
|
||||
if s == nil {
|
||||
return ""
|
||||
}
|
||||
return s.desc
|
||||
}
|
||||
|
||||
// LineOffsets returns a list of the 0-based character offsets in the input text where newlines appear.
|
||||
func (s *SourceInfo) LineOffsets() []int32 {
|
||||
if s == nil {
|
||||
return []int32{}
|
||||
}
|
||||
return s.lines
|
||||
}
|
||||
|
||||
// MacroCalls returns a map of expression id to ast.Expr value where the id represents the expression
|
||||
// node where the macro was inserted into the AST, and the ast.Expr value represents the original call
|
||||
// signature which was replaced.
|
||||
func (s *SourceInfo) MacroCalls() map[int64]Expr {
|
||||
if s == nil {
|
||||
return map[int64]Expr{}
|
||||
}
|
||||
return s.macroCalls
|
||||
}
|
||||
|
||||
// GetMacroCall returns the original ast.Expr value for the given expression if it was generated via
|
||||
// a macro replacement.
|
||||
//
|
||||
// Note, parsing options must be enabled to track macro calls before this method will return a value.
|
||||
func (s *SourceInfo) GetMacroCall(id int64) (Expr, bool) {
|
||||
e, found := s.MacroCalls()[id]
|
||||
return e, found
|
||||
}
|
||||
|
||||
// SetMacroCall records a macro call at a specific location.
|
||||
func (s *SourceInfo) SetMacroCall(id int64, e Expr) {
|
||||
if s != nil {
|
||||
s.macroCalls[id] = e
|
||||
}
|
||||
}
|
||||
|
||||
// ClearMacroCall removes the macro call at the given expression id.
|
||||
func (s *SourceInfo) ClearMacroCall(id int64) {
|
||||
if s != nil {
|
||||
delete(s.macroCalls, id)
|
||||
}
|
||||
}
|
||||
|
||||
// OffsetRanges returns a map of expression id to OffsetRange values where the range indicates either:
|
||||
// the start and end position in the input stream where the expression occurs, or the start position
|
||||
// only. If the range only captures start position, the stop position of the range will be equal to
|
||||
// the start.
|
||||
func (s *SourceInfo) OffsetRanges() map[int64]OffsetRange {
|
||||
if s == nil {
|
||||
return map[int64]OffsetRange{}
|
||||
}
|
||||
return s.offsetRanges
|
||||
}
|
||||
|
||||
// GetOffsetRange retrieves an OffsetRange for the given expression id if one exists.
|
||||
func (s *SourceInfo) GetOffsetRange(id int64) (OffsetRange, bool) {
|
||||
if s == nil {
|
||||
return OffsetRange{}, false
|
||||
}
|
||||
o, found := s.offsetRanges[id]
|
||||
return o, found
|
||||
}
|
||||
|
||||
// SetOffsetRange sets the OffsetRange for the given expression id.
|
||||
func (s *SourceInfo) SetOffsetRange(id int64, o OffsetRange) {
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
s.offsetRanges[id] = o
|
||||
}
|
||||
|
||||
// GetStartLocation calculates the human-readable 1-based line and 0-based column of the first character
|
||||
// of the expression node at the id.
|
||||
func (s *SourceInfo) GetStartLocation(id int64) common.Location {
|
||||
if o, found := s.GetOffsetRange(id); found {
|
||||
line := 1
|
||||
col := int(o.Start)
|
||||
for _, lineOffset := range s.LineOffsets() {
|
||||
if lineOffset < o.Start {
|
||||
line++
|
||||
col = int(o.Start - lineOffset)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return common.NewLocation(line, col)
|
||||
}
|
||||
return common.NoLocation
|
||||
}
|
||||
|
||||
// GetStopLocation calculates the human-readable 1-based line and 0-based column of the last character for
|
||||
// the expression node at the given id.
|
||||
//
|
||||
// If the SourceInfo was generated from a serialized protobuf representation, the stop location will
|
||||
// be identical to the start location for the expression.
|
||||
func (s *SourceInfo) GetStopLocation(id int64) common.Location {
|
||||
if o, found := s.GetOffsetRange(id); found {
|
||||
line := 1
|
||||
col := int(o.Stop)
|
||||
for _, lineOffset := range s.LineOffsets() {
|
||||
if lineOffset < o.Stop {
|
||||
line++
|
||||
col = int(o.Stop - lineOffset)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return common.NewLocation(line, col)
|
||||
}
|
||||
return common.NoLocation
|
||||
}
|
||||
|
||||
// ComputeOffset calculates the 0-based character offset from a 1-based line and 0-based column.
|
||||
func (s *SourceInfo) ComputeOffset(line, col int32) int32 {
|
||||
if s != nil {
|
||||
line = s.baseLine + line
|
||||
col = s.baseCol + col
|
||||
}
|
||||
if line == 1 {
|
||||
return col
|
||||
}
|
||||
if line < 1 || line > int32(len(s.LineOffsets())) {
|
||||
return -1
|
||||
}
|
||||
offset := s.LineOffsets()[line-2]
|
||||
return offset + col
|
||||
}
|
||||
|
||||
// OffsetRange captures the start and stop positions of a section of text in the input expression.
|
||||
type OffsetRange struct {
|
||||
Start int32
|
||||
Stop int32
|
||||
}
|
||||
|
||||
// ReferenceInfo contains a CEL native representation of an identifier reference which may refer to
|
||||
@ -149,78 +436,21 @@ func (r *ReferenceInfo) Equals(other *ReferenceInfo) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ReferenceInfoToReferenceExpr converts a ReferenceInfo instance to a protobuf Reference suitable for serialization.
|
||||
func ReferenceInfoToReferenceExpr(info *ReferenceInfo) (*exprpb.Reference, error) {
|
||||
c, err := ValToConstant(info.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &exprpb.Reference{
|
||||
Name: info.Name,
|
||||
OverloadId: info.OverloadIDs,
|
||||
Value: c,
|
||||
}, nil
|
||||
type maxIDVisitor struct {
|
||||
maxID int64
|
||||
*baseVisitor
|
||||
}
|
||||
|
||||
// ReferenceExprToReferenceInfo converts a protobuf Reference into a CEL-native ReferenceInfo instance.
|
||||
func ReferenceExprToReferenceInfo(ref *exprpb.Reference) (*ReferenceInfo, error) {
|
||||
v, err := ConstantToVal(ref.GetValue())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// VisitExpr updates the max identifier if the incoming expression id is greater than previously observed.
|
||||
func (v *maxIDVisitor) VisitExpr(e Expr) {
|
||||
if v.maxID < e.ID() {
|
||||
v.maxID = e.ID()
|
||||
}
|
||||
return &ReferenceInfo{
|
||||
Name: ref.GetName(),
|
||||
OverloadIDs: ref.GetOverloadId(),
|
||||
Value: v,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ValToConstant converts a CEL-native ref.Val to a protobuf Constant.
|
||||
//
|
||||
// Only simple scalar types are supported by this method.
|
||||
func ValToConstant(v ref.Val) (*exprpb.Constant, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
// VisitEntryExpr updates the max identifier if the incoming entry id is greater than previously observed.
|
||||
func (v *maxIDVisitor) VisitEntryExpr(e EntryExpr) {
|
||||
if v.maxID < e.ID() {
|
||||
v.maxID = e.ID()
|
||||
}
|
||||
switch v.Type() {
|
||||
case types.BoolType:
|
||||
return &exprpb.Constant{ConstantKind: &exprpb.Constant_BoolValue{BoolValue: v.Value().(bool)}}, nil
|
||||
case types.BytesType:
|
||||
return &exprpb.Constant{ConstantKind: &exprpb.Constant_BytesValue{BytesValue: v.Value().([]byte)}}, nil
|
||||
case types.DoubleType:
|
||||
return &exprpb.Constant{ConstantKind: &exprpb.Constant_DoubleValue{DoubleValue: v.Value().(float64)}}, nil
|
||||
case types.IntType:
|
||||
return &exprpb.Constant{ConstantKind: &exprpb.Constant_Int64Value{Int64Value: v.Value().(int64)}}, nil
|
||||
case types.NullType:
|
||||
return &exprpb.Constant{ConstantKind: &exprpb.Constant_NullValue{NullValue: structpb.NullValue_NULL_VALUE}}, nil
|
||||
case types.StringType:
|
||||
return &exprpb.Constant{ConstantKind: &exprpb.Constant_StringValue{StringValue: v.Value().(string)}}, nil
|
||||
case types.UintType:
|
||||
return &exprpb.Constant{ConstantKind: &exprpb.Constant_Uint64Value{Uint64Value: v.Value().(uint64)}}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported constant kind: %v", v.Type())
|
||||
}
|
||||
|
||||
// ConstantToVal converts a protobuf Constant to a CEL-native ref.Val.
|
||||
func ConstantToVal(c *exprpb.Constant) (ref.Val, error) {
|
||||
if c == nil {
|
||||
return nil, nil
|
||||
}
|
||||
switch c.GetConstantKind().(type) {
|
||||
case *exprpb.Constant_BoolValue:
|
||||
return types.Bool(c.GetBoolValue()), nil
|
||||
case *exprpb.Constant_BytesValue:
|
||||
return types.Bytes(c.GetBytesValue()), nil
|
||||
case *exprpb.Constant_DoubleValue:
|
||||
return types.Double(c.GetDoubleValue()), nil
|
||||
case *exprpb.Constant_Int64Value:
|
||||
return types.Int(c.GetInt64Value()), nil
|
||||
case *exprpb.Constant_NullValue:
|
||||
return types.NullValue, nil
|
||||
case *exprpb.Constant_StringValue:
|
||||
return types.String(c.GetStringValue()), nil
|
||||
case *exprpb.Constant_Uint64Value:
|
||||
return types.Uint(c.GetUint64Value()), nil
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported constant kind: %v", c.GetConstantKind())
|
||||
}
|
||||
|
632
vendor/github.com/google/cel-go/common/ast/conversion.go
generated
vendored
Normal file
632
vendor/github.com/google/cel-go/common/ast/conversion.go
generated
vendored
Normal file
@ -0,0 +1,632 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
|
||||
structpb "google.golang.org/protobuf/types/known/structpb"
|
||||
|
||||
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
|
||||
)
|
||||
|
||||
// ToProto converts an AST to a CheckedExpr protobouf.
|
||||
func ToProto(ast *AST) (*exprpb.CheckedExpr, error) {
|
||||
refMap := make(map[int64]*exprpb.Reference, len(ast.ReferenceMap()))
|
||||
for id, ref := range ast.ReferenceMap() {
|
||||
r, err := ReferenceInfoToProto(ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
refMap[id] = r
|
||||
}
|
||||
typeMap := make(map[int64]*exprpb.Type, len(ast.TypeMap()))
|
||||
for id, typ := range ast.TypeMap() {
|
||||
t, err := types.TypeToExprType(typ)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
typeMap[id] = t
|
||||
}
|
||||
e, err := ExprToProto(ast.Expr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info, err := SourceInfoToProto(ast.SourceInfo())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &exprpb.CheckedExpr{
|
||||
Expr: e,
|
||||
SourceInfo: info,
|
||||
ReferenceMap: refMap,
|
||||
TypeMap: typeMap,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ToAST converts a CheckedExpr protobuf to an AST instance.
|
||||
func ToAST(checked *exprpb.CheckedExpr) (*AST, error) {
|
||||
refMap := make(map[int64]*ReferenceInfo, len(checked.GetReferenceMap()))
|
||||
for id, ref := range checked.GetReferenceMap() {
|
||||
r, err := ProtoToReferenceInfo(ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
refMap[id] = r
|
||||
}
|
||||
typeMap := make(map[int64]*types.Type, len(checked.GetTypeMap()))
|
||||
for id, typ := range checked.GetTypeMap() {
|
||||
t, err := types.ExprTypeToType(typ)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
typeMap[id] = t
|
||||
}
|
||||
info, err := ProtoToSourceInfo(checked.GetSourceInfo())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
root, err := ProtoToExpr(checked.GetExpr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ast := NewCheckedAST(NewAST(root, info), typeMap, refMap)
|
||||
return ast, nil
|
||||
}
|
||||
|
||||
// ProtoToExpr converts a protobuf Expr value to an ast.Expr value.
|
||||
func ProtoToExpr(e *exprpb.Expr) (Expr, error) {
|
||||
factory := NewExprFactory()
|
||||
return exprInternal(factory, e)
|
||||
}
|
||||
|
||||
// ProtoToEntryExpr converts a protobuf struct/map entry to an ast.EntryExpr
|
||||
func ProtoToEntryExpr(e *exprpb.Expr_CreateStruct_Entry) (EntryExpr, error) {
|
||||
factory := NewExprFactory()
|
||||
switch e.GetKeyKind().(type) {
|
||||
case *exprpb.Expr_CreateStruct_Entry_FieldKey:
|
||||
return exprStructField(factory, e.GetId(), e)
|
||||
case *exprpb.Expr_CreateStruct_Entry_MapKey:
|
||||
return exprMapEntry(factory, e.GetId(), e)
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported expr entry kind: %v", e)
|
||||
}
|
||||
|
||||
func exprInternal(factory ExprFactory, e *exprpb.Expr) (Expr, error) {
|
||||
id := e.GetId()
|
||||
switch e.GetExprKind().(type) {
|
||||
case *exprpb.Expr_CallExpr:
|
||||
return exprCall(factory, id, e.GetCallExpr())
|
||||
case *exprpb.Expr_ComprehensionExpr:
|
||||
return exprComprehension(factory, id, e.GetComprehensionExpr())
|
||||
case *exprpb.Expr_ConstExpr:
|
||||
return exprLiteral(factory, id, e.GetConstExpr())
|
||||
case *exprpb.Expr_IdentExpr:
|
||||
return exprIdent(factory, id, e.GetIdentExpr())
|
||||
case *exprpb.Expr_ListExpr:
|
||||
return exprList(factory, id, e.GetListExpr())
|
||||
case *exprpb.Expr_SelectExpr:
|
||||
return exprSelect(factory, id, e.GetSelectExpr())
|
||||
case *exprpb.Expr_StructExpr:
|
||||
s := e.GetStructExpr()
|
||||
if s.GetMessageName() != "" {
|
||||
return exprStruct(factory, id, s)
|
||||
}
|
||||
return exprMap(factory, id, s)
|
||||
}
|
||||
return factory.NewUnspecifiedExpr(id), nil
|
||||
}
|
||||
|
||||
func exprCall(factory ExprFactory, id int64, call *exprpb.Expr_Call) (Expr, error) {
|
||||
var err error
|
||||
args := make([]Expr, len(call.GetArgs()))
|
||||
for i, a := range call.GetArgs() {
|
||||
args[i], err = exprInternal(factory, a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if call.GetTarget() == nil {
|
||||
return factory.NewCall(id, call.GetFunction(), args...), nil
|
||||
}
|
||||
|
||||
target, err := exprInternal(factory, call.GetTarget())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return factory.NewMemberCall(id, call.GetFunction(), target, args...), nil
|
||||
}
|
||||
|
||||
func exprComprehension(factory ExprFactory, id int64, comp *exprpb.Expr_Comprehension) (Expr, error) {
|
||||
iterRange, err := exprInternal(factory, comp.GetIterRange())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
accuInit, err := exprInternal(factory, comp.GetAccuInit())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
loopCond, err := exprInternal(factory, comp.GetLoopCondition())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
loopStep, err := exprInternal(factory, comp.GetLoopStep())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err := exprInternal(factory, comp.GetResult())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return factory.NewComprehension(id,
|
||||
iterRange,
|
||||
comp.GetIterVar(),
|
||||
comp.GetAccuVar(),
|
||||
accuInit,
|
||||
loopCond,
|
||||
loopStep,
|
||||
result), nil
|
||||
}
|
||||
|
||||
func exprLiteral(factory ExprFactory, id int64, c *exprpb.Constant) (Expr, error) {
|
||||
val, err := ConstantToVal(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return factory.NewLiteral(id, val), nil
|
||||
}
|
||||
|
||||
func exprIdent(factory ExprFactory, id int64, i *exprpb.Expr_Ident) (Expr, error) {
|
||||
return factory.NewIdent(id, i.GetName()), nil
|
||||
}
|
||||
|
||||
func exprList(factory ExprFactory, id int64, l *exprpb.Expr_CreateList) (Expr, error) {
|
||||
elems := make([]Expr, len(l.GetElements()))
|
||||
for i, e := range l.GetElements() {
|
||||
elem, err := exprInternal(factory, e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
elems[i] = elem
|
||||
}
|
||||
return factory.NewList(id, elems, l.GetOptionalIndices()), nil
|
||||
}
|
||||
|
||||
func exprMap(factory ExprFactory, id int64, s *exprpb.Expr_CreateStruct) (Expr, error) {
|
||||
entries := make([]EntryExpr, len(s.GetEntries()))
|
||||
var err error
|
||||
for i, entry := range s.GetEntries() {
|
||||
entries[i], err = exprMapEntry(factory, entry.GetId(), entry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return factory.NewMap(id, entries), nil
|
||||
}
|
||||
|
||||
func exprMapEntry(factory ExprFactory, id int64, e *exprpb.Expr_CreateStruct_Entry) (EntryExpr, error) {
|
||||
k, err := exprInternal(factory, e.GetMapKey())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v, err := exprInternal(factory, e.GetValue())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return factory.NewMapEntry(id, k, v, e.GetOptionalEntry()), nil
|
||||
}
|
||||
|
||||
func exprSelect(factory ExprFactory, id int64, s *exprpb.Expr_Select) (Expr, error) {
|
||||
op, err := exprInternal(factory, s.GetOperand())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if s.GetTestOnly() {
|
||||
return factory.NewPresenceTest(id, op, s.GetField()), nil
|
||||
}
|
||||
return factory.NewSelect(id, op, s.GetField()), nil
|
||||
}
|
||||
|
||||
func exprStruct(factory ExprFactory, id int64, s *exprpb.Expr_CreateStruct) (Expr, error) {
|
||||
fields := make([]EntryExpr, len(s.GetEntries()))
|
||||
var err error
|
||||
for i, field := range s.GetEntries() {
|
||||
fields[i], err = exprStructField(factory, field.GetId(), field)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return factory.NewStruct(id, s.GetMessageName(), fields), nil
|
||||
}
|
||||
|
||||
func exprStructField(factory ExprFactory, id int64, f *exprpb.Expr_CreateStruct_Entry) (EntryExpr, error) {
|
||||
v, err := exprInternal(factory, f.GetValue())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return factory.NewStructField(id, f.GetFieldKey(), v, f.GetOptionalEntry()), nil
|
||||
}
|
||||
|
||||
// ExprToProto serializes an ast.Expr value to a protobuf Expr representation.
|
||||
func ExprToProto(e Expr) (*exprpb.Expr, error) {
|
||||
if e == nil {
|
||||
return &exprpb.Expr{}, nil
|
||||
}
|
||||
switch e.Kind() {
|
||||
case CallKind:
|
||||
return protoCall(e.ID(), e.AsCall())
|
||||
case ComprehensionKind:
|
||||
return protoComprehension(e.ID(), e.AsComprehension())
|
||||
case IdentKind:
|
||||
return protoIdent(e.ID(), e.AsIdent())
|
||||
case ListKind:
|
||||
return protoList(e.ID(), e.AsList())
|
||||
case LiteralKind:
|
||||
return protoLiteral(e.ID(), e.AsLiteral())
|
||||
case MapKind:
|
||||
return protoMap(e.ID(), e.AsMap())
|
||||
case SelectKind:
|
||||
return protoSelect(e.ID(), e.AsSelect())
|
||||
case StructKind:
|
||||
return protoStruct(e.ID(), e.AsStruct())
|
||||
case UnspecifiedExprKind:
|
||||
// Handle the case where a macro reference may be getting translated.
|
||||
// A nested macro 'pointer' is a non-zero expression id with no kind set.
|
||||
if e.ID() != 0 {
|
||||
return &exprpb.Expr{Id: e.ID()}, nil
|
||||
}
|
||||
return &exprpb.Expr{}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported expr kind: %v", e)
|
||||
}
|
||||
|
||||
// EntryExprToProto converts an ast.EntryExpr to a protobuf CreateStruct entry
|
||||
func EntryExprToProto(e EntryExpr) (*exprpb.Expr_CreateStruct_Entry, error) {
|
||||
switch e.Kind() {
|
||||
case MapEntryKind:
|
||||
return protoMapEntry(e.ID(), e.AsMapEntry())
|
||||
case StructFieldKind:
|
||||
return protoStructField(e.ID(), e.AsStructField())
|
||||
case UnspecifiedEntryExprKind:
|
||||
return &exprpb.Expr_CreateStruct_Entry{}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported expr entry kind: %v", e)
|
||||
}
|
||||
|
||||
func protoCall(id int64, call CallExpr) (*exprpb.Expr, error) {
|
||||
var err error
|
||||
var target *exprpb.Expr
|
||||
if call.IsMemberFunction() {
|
||||
target, err = ExprToProto(call.Target())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
callArgs := call.Args()
|
||||
args := make([]*exprpb.Expr, len(callArgs))
|
||||
for i, a := range callArgs {
|
||||
args[i], err = ExprToProto(a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &exprpb.Expr{
|
||||
Id: id,
|
||||
ExprKind: &exprpb.Expr_CallExpr{
|
||||
CallExpr: &exprpb.Expr_Call{
|
||||
Function: call.FunctionName(),
|
||||
Target: target,
|
||||
Args: args,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func protoComprehension(id int64, comp ComprehensionExpr) (*exprpb.Expr, error) {
|
||||
iterRange, err := ExprToProto(comp.IterRange())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
accuInit, err := ExprToProto(comp.AccuInit())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
loopCond, err := ExprToProto(comp.LoopCondition())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
loopStep, err := ExprToProto(comp.LoopStep())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err := ExprToProto(comp.Result())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &exprpb.Expr{
|
||||
Id: id,
|
||||
ExprKind: &exprpb.Expr_ComprehensionExpr{
|
||||
ComprehensionExpr: &exprpb.Expr_Comprehension{
|
||||
IterVar: comp.IterVar(),
|
||||
IterRange: iterRange,
|
||||
AccuVar: comp.AccuVar(),
|
||||
AccuInit: accuInit,
|
||||
LoopCondition: loopCond,
|
||||
LoopStep: loopStep,
|
||||
Result: result,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func protoIdent(id int64, name string) (*exprpb.Expr, error) {
|
||||
return &exprpb.Expr{
|
||||
Id: id,
|
||||
ExprKind: &exprpb.Expr_IdentExpr{
|
||||
IdentExpr: &exprpb.Expr_Ident{
|
||||
Name: name,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func protoList(id int64, list ListExpr) (*exprpb.Expr, error) {
|
||||
var err error
|
||||
elems := make([]*exprpb.Expr, list.Size())
|
||||
for i, e := range list.Elements() {
|
||||
elems[i], err = ExprToProto(e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &exprpb.Expr{
|
||||
Id: id,
|
||||
ExprKind: &exprpb.Expr_ListExpr{
|
||||
ListExpr: &exprpb.Expr_CreateList{
|
||||
Elements: elems,
|
||||
OptionalIndices: list.OptionalIndices(),
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func protoLiteral(id int64, val ref.Val) (*exprpb.Expr, error) {
|
||||
c, err := ValToConstant(val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &exprpb.Expr{
|
||||
Id: id,
|
||||
ExprKind: &exprpb.Expr_ConstExpr{
|
||||
ConstExpr: c,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func protoMap(id int64, m MapExpr) (*exprpb.Expr, error) {
|
||||
entries := make([]*exprpb.Expr_CreateStruct_Entry, len(m.Entries()))
|
||||
var err error
|
||||
for i, e := range m.Entries() {
|
||||
entries[i], err = EntryExprToProto(e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &exprpb.Expr{
|
||||
Id: id,
|
||||
ExprKind: &exprpb.Expr_StructExpr{
|
||||
StructExpr: &exprpb.Expr_CreateStruct{
|
||||
Entries: entries,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func protoMapEntry(id int64, e MapEntry) (*exprpb.Expr_CreateStruct_Entry, error) {
|
||||
k, err := ExprToProto(e.Key())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v, err := ExprToProto(e.Value())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &exprpb.Expr_CreateStruct_Entry{
|
||||
Id: id,
|
||||
KeyKind: &exprpb.Expr_CreateStruct_Entry_MapKey{
|
||||
MapKey: k,
|
||||
},
|
||||
Value: v,
|
||||
OptionalEntry: e.IsOptional(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func protoSelect(id int64, s SelectExpr) (*exprpb.Expr, error) {
|
||||
op, err := ExprToProto(s.Operand())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &exprpb.Expr{
|
||||
Id: id,
|
||||
ExprKind: &exprpb.Expr_SelectExpr{
|
||||
SelectExpr: &exprpb.Expr_Select{
|
||||
Operand: op,
|
||||
Field: s.FieldName(),
|
||||
TestOnly: s.IsTestOnly(),
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func protoStruct(id int64, s StructExpr) (*exprpb.Expr, error) {
|
||||
entries := make([]*exprpb.Expr_CreateStruct_Entry, len(s.Fields()))
|
||||
var err error
|
||||
for i, e := range s.Fields() {
|
||||
entries[i], err = EntryExprToProto(e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &exprpb.Expr{
|
||||
Id: id,
|
||||
ExprKind: &exprpb.Expr_StructExpr{
|
||||
StructExpr: &exprpb.Expr_CreateStruct{
|
||||
MessageName: s.TypeName(),
|
||||
Entries: entries,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func protoStructField(id int64, f StructField) (*exprpb.Expr_CreateStruct_Entry, error) {
|
||||
v, err := ExprToProto(f.Value())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &exprpb.Expr_CreateStruct_Entry{
|
||||
Id: id,
|
||||
KeyKind: &exprpb.Expr_CreateStruct_Entry_FieldKey{
|
||||
FieldKey: f.Name(),
|
||||
},
|
||||
Value: v,
|
||||
OptionalEntry: f.IsOptional(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SourceInfoToProto serializes an ast.SourceInfo value to a protobuf SourceInfo object.
|
||||
func SourceInfoToProto(info *SourceInfo) (*exprpb.SourceInfo, error) {
|
||||
if info == nil {
|
||||
return &exprpb.SourceInfo{}, nil
|
||||
}
|
||||
sourceInfo := &exprpb.SourceInfo{
|
||||
SyntaxVersion: info.SyntaxVersion(),
|
||||
Location: info.Description(),
|
||||
LineOffsets: info.LineOffsets(),
|
||||
Positions: make(map[int64]int32, len(info.OffsetRanges())),
|
||||
MacroCalls: make(map[int64]*exprpb.Expr, len(info.MacroCalls())),
|
||||
}
|
||||
for id, offset := range info.OffsetRanges() {
|
||||
sourceInfo.Positions[id] = offset.Start
|
||||
}
|
||||
for id, e := range info.MacroCalls() {
|
||||
call, err := ExprToProto(e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sourceInfo.MacroCalls[id] = call
|
||||
}
|
||||
return sourceInfo, nil
|
||||
}
|
||||
|
||||
// ProtoToSourceInfo deserializes the protobuf into a native SourceInfo value.
|
||||
func ProtoToSourceInfo(info *exprpb.SourceInfo) (*SourceInfo, error) {
|
||||
sourceInfo := &SourceInfo{
|
||||
syntax: info.GetSyntaxVersion(),
|
||||
desc: info.GetLocation(),
|
||||
lines: info.GetLineOffsets(),
|
||||
offsetRanges: make(map[int64]OffsetRange, len(info.GetPositions())),
|
||||
macroCalls: make(map[int64]Expr, len(info.GetMacroCalls())),
|
||||
}
|
||||
for id, offset := range info.GetPositions() {
|
||||
sourceInfo.SetOffsetRange(id, OffsetRange{Start: offset, Stop: offset})
|
||||
}
|
||||
for id, e := range info.GetMacroCalls() {
|
||||
call, err := ProtoToExpr(e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sourceInfo.SetMacroCall(id, call)
|
||||
}
|
||||
return sourceInfo, nil
|
||||
}
|
||||
|
||||
// ReferenceInfoToProto converts a ReferenceInfo instance to a protobuf Reference suitable for serialization.
|
||||
func ReferenceInfoToProto(info *ReferenceInfo) (*exprpb.Reference, error) {
|
||||
c, err := ValToConstant(info.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &exprpb.Reference{
|
||||
Name: info.Name,
|
||||
OverloadId: info.OverloadIDs,
|
||||
Value: c,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ProtoToReferenceInfo converts a protobuf Reference into a CEL-native ReferenceInfo instance.
|
||||
func ProtoToReferenceInfo(ref *exprpb.Reference) (*ReferenceInfo, error) {
|
||||
v, err := ConstantToVal(ref.GetValue())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ReferenceInfo{
|
||||
Name: ref.GetName(),
|
||||
OverloadIDs: ref.GetOverloadId(),
|
||||
Value: v,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ValToConstant converts a CEL-native ref.Val to a protobuf Constant.
|
||||
//
|
||||
// Only simple scalar types are supported by this method.
|
||||
func ValToConstant(v ref.Val) (*exprpb.Constant, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
switch v.Type() {
|
||||
case types.BoolType:
|
||||
return &exprpb.Constant{ConstantKind: &exprpb.Constant_BoolValue{BoolValue: v.Value().(bool)}}, nil
|
||||
case types.BytesType:
|
||||
return &exprpb.Constant{ConstantKind: &exprpb.Constant_BytesValue{BytesValue: v.Value().([]byte)}}, nil
|
||||
case types.DoubleType:
|
||||
return &exprpb.Constant{ConstantKind: &exprpb.Constant_DoubleValue{DoubleValue: v.Value().(float64)}}, nil
|
||||
case types.IntType:
|
||||
return &exprpb.Constant{ConstantKind: &exprpb.Constant_Int64Value{Int64Value: v.Value().(int64)}}, nil
|
||||
case types.NullType:
|
||||
return &exprpb.Constant{ConstantKind: &exprpb.Constant_NullValue{NullValue: structpb.NullValue_NULL_VALUE}}, nil
|
||||
case types.StringType:
|
||||
return &exprpb.Constant{ConstantKind: &exprpb.Constant_StringValue{StringValue: v.Value().(string)}}, nil
|
||||
case types.UintType:
|
||||
return &exprpb.Constant{ConstantKind: &exprpb.Constant_Uint64Value{Uint64Value: v.Value().(uint64)}}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported constant kind: %v", v.Type())
|
||||
}
|
||||
|
||||
// ConstantToVal converts a protobuf Constant to a CEL-native ref.Val.
|
||||
func ConstantToVal(c *exprpb.Constant) (ref.Val, error) {
|
||||
if c == nil {
|
||||
return nil, nil
|
||||
}
|
||||
switch c.GetConstantKind().(type) {
|
||||
case *exprpb.Constant_BoolValue:
|
||||
return types.Bool(c.GetBoolValue()), nil
|
||||
case *exprpb.Constant_BytesValue:
|
||||
return types.Bytes(c.GetBytesValue()), nil
|
||||
case *exprpb.Constant_DoubleValue:
|
||||
return types.Double(c.GetDoubleValue()), nil
|
||||
case *exprpb.Constant_Int64Value:
|
||||
return types.Int(c.GetInt64Value()), nil
|
||||
case *exprpb.Constant_NullValue:
|
||||
return types.NullValue, nil
|
||||
case *exprpb.Constant_StringValue:
|
||||
return types.String(c.GetStringValue()), nil
|
||||
case *exprpb.Constant_Uint64Value:
|
||||
return types.Uint(c.GetUint64Value()), nil
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported constant kind: %v", c.GetConstantKind())
|
||||
}
|
1131
vendor/github.com/google/cel-go/common/ast/expr.go
generated
vendored
1131
vendor/github.com/google/cel-go/common/ast/expr.go
generated
vendored
File diff suppressed because it is too large
Load Diff
303
vendor/github.com/google/cel-go/common/ast/factory.go
generated
vendored
Normal file
303
vendor/github.com/google/cel-go/common/ast/factory.go
generated
vendored
Normal file
@ -0,0 +1,303 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ast
|
||||
|
||||
import "github.com/google/cel-go/common/types/ref"
|
||||
|
||||
// ExprFactory interfaces defines a set of methods necessary for building native expression values.
|
||||
type ExprFactory interface {
|
||||
// CopyExpr creates a deep copy of the input Expr value.
|
||||
CopyExpr(Expr) Expr
|
||||
|
||||
// CopyEntryExpr creates a deep copy of the input EntryExpr value.
|
||||
CopyEntryExpr(EntryExpr) EntryExpr
|
||||
|
||||
// NewCall creates an Expr value representing a global function call.
|
||||
NewCall(id int64, function string, args ...Expr) Expr
|
||||
|
||||
// NewComprehension creates an Expr value representing a comprehension over a value range.
|
||||
NewComprehension(id int64, iterRange Expr, iterVar, accuVar string, accuInit, loopCondition, loopStep, result Expr) Expr
|
||||
|
||||
// NewMemberCall creates an Expr value representing a member function call.
|
||||
NewMemberCall(id int64, function string, receiver Expr, args ...Expr) Expr
|
||||
|
||||
// NewIdent creates an Expr value representing an identifier.
|
||||
NewIdent(id int64, name string) Expr
|
||||
|
||||
// NewAccuIdent creates an Expr value representing an accumulator identifier within a
|
||||
//comprehension.
|
||||
NewAccuIdent(id int64) Expr
|
||||
|
||||
// NewLiteral creates an Expr value representing a literal value, such as a string or integer.
|
||||
NewLiteral(id int64, value ref.Val) Expr
|
||||
|
||||
// NewList creates an Expr value representing a list literal expression with optional indices.
|
||||
//
|
||||
// Optional indicies will typically be empty unless the CEL optional types are enabled.
|
||||
NewList(id int64, elems []Expr, optIndices []int32) Expr
|
||||
|
||||
// NewMap creates an Expr value representing a map literal expression
|
||||
NewMap(id int64, entries []EntryExpr) Expr
|
||||
|
||||
// NewMapEntry creates a MapEntry with a given key, value, and a flag indicating whether
|
||||
// the key is optionally set.
|
||||
NewMapEntry(id int64, key, value Expr, isOptional bool) EntryExpr
|
||||
|
||||
// NewPresenceTest creates an Expr representing a field presence test on an operand expression.
|
||||
NewPresenceTest(id int64, operand Expr, field string) Expr
|
||||
|
||||
// NewSelect creates an Expr representing a field selection on an operand expression.
|
||||
NewSelect(id int64, operand Expr, field string) Expr
|
||||
|
||||
// NewStruct creates an Expr value representing a struct literal with a given type name and a
|
||||
// set of field initializers.
|
||||
NewStruct(id int64, typeName string, fields []EntryExpr) Expr
|
||||
|
||||
// NewStructField creates a StructField with a given field name, value, and a flag indicating
|
||||
// whether the field is optionally set.
|
||||
NewStructField(id int64, field string, value Expr, isOptional bool) EntryExpr
|
||||
|
||||
// NewUnspecifiedExpr creates an empty expression node.
|
||||
NewUnspecifiedExpr(id int64) Expr
|
||||
|
||||
isExprFactory()
|
||||
}
|
||||
|
||||
type baseExprFactory struct{}
|
||||
|
||||
// NewExprFactory creates an ExprFactory instance.
|
||||
func NewExprFactory() ExprFactory {
|
||||
return &baseExprFactory{}
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) NewCall(id int64, function string, args ...Expr) Expr {
|
||||
if len(args) == 0 {
|
||||
args = []Expr{}
|
||||
}
|
||||
return fac.newExpr(
|
||||
id,
|
||||
&baseCallExpr{
|
||||
function: function,
|
||||
target: nilExpr,
|
||||
args: args,
|
||||
isMember: false,
|
||||
})
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) NewMemberCall(id int64, function string, target Expr, args ...Expr) Expr {
|
||||
if len(args) == 0 {
|
||||
args = []Expr{}
|
||||
}
|
||||
return fac.newExpr(
|
||||
id,
|
||||
&baseCallExpr{
|
||||
function: function,
|
||||
target: target,
|
||||
args: args,
|
||||
isMember: true,
|
||||
})
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) NewComprehension(id int64, iterRange Expr, iterVar, accuVar string, accuInit, loopCond, loopStep, result Expr) Expr {
|
||||
return fac.newExpr(
|
||||
id,
|
||||
&baseComprehensionExpr{
|
||||
iterRange: iterRange,
|
||||
iterVar: iterVar,
|
||||
accuVar: accuVar,
|
||||
accuInit: accuInit,
|
||||
loopCond: loopCond,
|
||||
loopStep: loopStep,
|
||||
result: result,
|
||||
})
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) NewIdent(id int64, name string) Expr {
|
||||
return fac.newExpr(id, baseIdentExpr(name))
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) NewAccuIdent(id int64) Expr {
|
||||
return fac.NewIdent(id, "__result__")
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) NewLiteral(id int64, value ref.Val) Expr {
|
||||
return fac.newExpr(id, &baseLiteral{Val: value})
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) NewList(id int64, elems []Expr, optIndices []int32) Expr {
|
||||
optIndexMap := make(map[int32]struct{}, len(optIndices))
|
||||
for _, idx := range optIndices {
|
||||
optIndexMap[idx] = struct{}{}
|
||||
}
|
||||
return fac.newExpr(id,
|
||||
&baseListExpr{
|
||||
elements: elems,
|
||||
optIndices: optIndices,
|
||||
optIndexMap: optIndexMap,
|
||||
})
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) NewMap(id int64, entries []EntryExpr) Expr {
|
||||
return fac.newExpr(id, &baseMapExpr{entries: entries})
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) NewMapEntry(id int64, key, value Expr, isOptional bool) EntryExpr {
|
||||
return fac.newEntryExpr(
|
||||
id,
|
||||
&baseMapEntry{
|
||||
key: key,
|
||||
value: value,
|
||||
isOptional: isOptional,
|
||||
})
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) NewPresenceTest(id int64, operand Expr, field string) Expr {
|
||||
return fac.newExpr(
|
||||
id,
|
||||
&baseSelectExpr{
|
||||
operand: operand,
|
||||
field: field,
|
||||
testOnly: true,
|
||||
})
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) NewSelect(id int64, operand Expr, field string) Expr {
|
||||
return fac.newExpr(
|
||||
id,
|
||||
&baseSelectExpr{
|
||||
operand: operand,
|
||||
field: field,
|
||||
})
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) NewStruct(id int64, typeName string, fields []EntryExpr) Expr {
|
||||
return fac.newExpr(
|
||||
id,
|
||||
&baseStructExpr{
|
||||
typeName: typeName,
|
||||
fields: fields,
|
||||
})
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) NewStructField(id int64, field string, value Expr, isOptional bool) EntryExpr {
|
||||
return fac.newEntryExpr(
|
||||
id,
|
||||
&baseStructField{
|
||||
field: field,
|
||||
value: value,
|
||||
isOptional: isOptional,
|
||||
})
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) NewUnspecifiedExpr(id int64) Expr {
|
||||
return fac.newExpr(id, nil)
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) CopyExpr(e Expr) Expr {
|
||||
// unwrap navigable expressions to avoid unnecessary allocations during copying.
|
||||
if nav, ok := e.(*navigableExprImpl); ok {
|
||||
e = nav.Expr
|
||||
}
|
||||
switch e.Kind() {
|
||||
case CallKind:
|
||||
c := e.AsCall()
|
||||
argsCopy := make([]Expr, len(c.Args()))
|
||||
for i, arg := range c.Args() {
|
||||
argsCopy[i] = fac.CopyExpr(arg)
|
||||
}
|
||||
if !c.IsMemberFunction() {
|
||||
return fac.NewCall(e.ID(), c.FunctionName(), argsCopy...)
|
||||
}
|
||||
return fac.NewMemberCall(e.ID(), c.FunctionName(), fac.CopyExpr(c.Target()), argsCopy...)
|
||||
case ComprehensionKind:
|
||||
compre := e.AsComprehension()
|
||||
return fac.NewComprehension(e.ID(),
|
||||
fac.CopyExpr(compre.IterRange()),
|
||||
compre.IterVar(),
|
||||
compre.AccuVar(),
|
||||
fac.CopyExpr(compre.AccuInit()),
|
||||
fac.CopyExpr(compre.LoopCondition()),
|
||||
fac.CopyExpr(compre.LoopStep()),
|
||||
fac.CopyExpr(compre.Result()))
|
||||
case IdentKind:
|
||||
return fac.NewIdent(e.ID(), e.AsIdent())
|
||||
case ListKind:
|
||||
l := e.AsList()
|
||||
elemsCopy := make([]Expr, l.Size())
|
||||
for i, elem := range l.Elements() {
|
||||
elemsCopy[i] = fac.CopyExpr(elem)
|
||||
}
|
||||
return fac.NewList(e.ID(), elemsCopy, l.OptionalIndices())
|
||||
case LiteralKind:
|
||||
return fac.NewLiteral(e.ID(), e.AsLiteral())
|
||||
case MapKind:
|
||||
m := e.AsMap()
|
||||
entriesCopy := make([]EntryExpr, m.Size())
|
||||
for i, entry := range m.Entries() {
|
||||
entriesCopy[i] = fac.CopyEntryExpr(entry)
|
||||
}
|
||||
return fac.NewMap(e.ID(), entriesCopy)
|
||||
case SelectKind:
|
||||
s := e.AsSelect()
|
||||
if s.IsTestOnly() {
|
||||
return fac.NewPresenceTest(e.ID(), fac.CopyExpr(s.Operand()), s.FieldName())
|
||||
}
|
||||
return fac.NewSelect(e.ID(), fac.CopyExpr(s.Operand()), s.FieldName())
|
||||
case StructKind:
|
||||
s := e.AsStruct()
|
||||
fieldsCopy := make([]EntryExpr, len(s.Fields()))
|
||||
for i, field := range s.Fields() {
|
||||
fieldsCopy[i] = fac.CopyEntryExpr(field)
|
||||
}
|
||||
return fac.NewStruct(e.ID(), s.TypeName(), fieldsCopy)
|
||||
default:
|
||||
return fac.NewUnspecifiedExpr(e.ID())
|
||||
}
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) CopyEntryExpr(e EntryExpr) EntryExpr {
|
||||
switch e.Kind() {
|
||||
case MapEntryKind:
|
||||
entry := e.AsMapEntry()
|
||||
return fac.NewMapEntry(e.ID(),
|
||||
fac.CopyExpr(entry.Key()), fac.CopyExpr(entry.Value()), entry.IsOptional())
|
||||
case StructFieldKind:
|
||||
field := e.AsStructField()
|
||||
return fac.NewStructField(e.ID(),
|
||||
field.Name(), fac.CopyExpr(field.Value()), field.IsOptional())
|
||||
default:
|
||||
return fac.newEntryExpr(e.ID(), nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (*baseExprFactory) isExprFactory() {}
|
||||
|
||||
func (fac *baseExprFactory) newExpr(id int64, e exprKindCase) Expr {
|
||||
return &expr{
|
||||
id: id,
|
||||
exprKindCase: e,
|
||||
}
|
||||
}
|
||||
|
||||
func (fac *baseExprFactory) newEntryExpr(id int64, e entryExprKindCase) EntryExpr {
|
||||
return &entryExpr{
|
||||
id: id,
|
||||
entryExprKindCase: e,
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
defaultFactory = &baseExprFactory{}
|
||||
)
|
652
vendor/github.com/google/cel-go/common/ast/navigable.go
generated
vendored
Normal file
652
vendor/github.com/google/cel-go/common/ast/navigable.go
generated
vendored
Normal file
@ -0,0 +1,652 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ast
|
||||
|
||||
import (
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
)
|
||||
|
||||
// NavigableExpr represents the base navigable expression value with methods to inspect the
|
||||
// parent and child expressions.
|
||||
type NavigableExpr interface {
|
||||
Expr
|
||||
|
||||
// Type of the expression.
|
||||
//
|
||||
// If the expression is type-checked, the type check metadata is returned. If the expression
|
||||
// has not been type-checked, the types.DynType value is returned.
|
||||
Type() *types.Type
|
||||
|
||||
// Parent returns the parent expression node, if one exists.
|
||||
Parent() (NavigableExpr, bool)
|
||||
|
||||
// Children returns a list of child expression nodes.
|
||||
Children() []NavigableExpr
|
||||
|
||||
// Depth indicates the depth in the expression tree.
|
||||
//
|
||||
// The root expression has depth 0.
|
||||
Depth() int
|
||||
}
|
||||
|
||||
// NavigateAST converts an AST to a NavigableExpr
|
||||
func NavigateAST(ast *AST) NavigableExpr {
|
||||
return NavigateExpr(ast, ast.Expr())
|
||||
}
|
||||
|
||||
// NavigateExpr creates a NavigableExpr whose type information is backed by the input AST.
|
||||
//
|
||||
// If the expression is already a NavigableExpr, the parent and depth information will be
|
||||
// propagated on the new NavigableExpr value; otherwise, the expr value will be treated
|
||||
// as though it is the root of the expression graph with a depth of 0.
|
||||
func NavigateExpr(ast *AST, expr Expr) NavigableExpr {
|
||||
depth := 0
|
||||
var parent NavigableExpr = nil
|
||||
if nav, ok := expr.(NavigableExpr); ok {
|
||||
depth = nav.Depth()
|
||||
parent, _ = nav.Parent()
|
||||
}
|
||||
return newNavigableExpr(ast, parent, expr, depth)
|
||||
}
|
||||
|
||||
// ExprMatcher takes a NavigableExpr in and indicates whether the value is a match.
|
||||
//
|
||||
// This function type should be use with the `Match` and `MatchList` calls.
|
||||
type ExprMatcher func(NavigableExpr) bool
|
||||
|
||||
// ConstantValueMatcher returns an ExprMatcher which will return true if the input NavigableExpr
|
||||
// is comprised of all constant values, such as a simple literal or even list and map literal.
|
||||
func ConstantValueMatcher() ExprMatcher {
|
||||
return matchIsConstantValue
|
||||
}
|
||||
|
||||
// KindMatcher returns an ExprMatcher which will return true if the input NavigableExpr.Kind() matches
|
||||
// the specified `kind`.
|
||||
func KindMatcher(kind ExprKind) ExprMatcher {
|
||||
return func(e NavigableExpr) bool {
|
||||
return e.Kind() == kind
|
||||
}
|
||||
}
|
||||
|
||||
// FunctionMatcher returns an ExprMatcher which will match NavigableExpr nodes of CallKind type whose
|
||||
// function name is equal to `funcName`.
|
||||
func FunctionMatcher(funcName string) ExprMatcher {
|
||||
return func(e NavigableExpr) bool {
|
||||
if e.Kind() != CallKind {
|
||||
return false
|
||||
}
|
||||
return e.AsCall().FunctionName() == funcName
|
||||
}
|
||||
}
|
||||
|
||||
// AllMatcher returns true for all descendants of a NavigableExpr, effectively flattening them into a list.
|
||||
//
|
||||
// Such a result would work well with subsequent MatchList calls.
|
||||
func AllMatcher() ExprMatcher {
|
||||
return func(NavigableExpr) bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// MatchDescendants takes a NavigableExpr and ExprMatcher and produces a list of NavigableExpr values
|
||||
// matching the input criteria in post-order (bottom up).
|
||||
func MatchDescendants(expr NavigableExpr, matcher ExprMatcher) []NavigableExpr {
|
||||
matches := []NavigableExpr{}
|
||||
navVisitor := &baseVisitor{
|
||||
visitExpr: func(e Expr) {
|
||||
nav := e.(NavigableExpr)
|
||||
if matcher(nav) {
|
||||
matches = append(matches, nav)
|
||||
}
|
||||
},
|
||||
}
|
||||
visit(expr, navVisitor, postOrder, 0, 0)
|
||||
return matches
|
||||
}
|
||||
|
||||
// MatchSubset applies an ExprMatcher to a list of NavigableExpr values and their descendants, producing a
|
||||
// subset of NavigableExpr values which match.
|
||||
func MatchSubset(exprs []NavigableExpr, matcher ExprMatcher) []NavigableExpr {
|
||||
matches := []NavigableExpr{}
|
||||
navVisitor := &baseVisitor{
|
||||
visitExpr: func(e Expr) {
|
||||
nav := e.(NavigableExpr)
|
||||
if matcher(nav) {
|
||||
matches = append(matches, nav)
|
||||
}
|
||||
},
|
||||
}
|
||||
for _, expr := range exprs {
|
||||
visit(expr, navVisitor, postOrder, 0, 1)
|
||||
}
|
||||
return matches
|
||||
}
|
||||
|
||||
// Visitor defines an object for visiting Expr and EntryExpr nodes within an expression graph.
|
||||
type Visitor interface {
|
||||
// VisitExpr visits the input expression.
|
||||
VisitExpr(Expr)
|
||||
|
||||
// VisitEntryExpr visits the input entry expression, i.e. a struct field or map entry.
|
||||
VisitEntryExpr(EntryExpr)
|
||||
}
|
||||
|
||||
type baseVisitor struct {
|
||||
visitExpr func(Expr)
|
||||
visitEntryExpr func(EntryExpr)
|
||||
}
|
||||
|
||||
// VisitExpr visits the Expr if the internal expr visitor has been configured.
|
||||
func (v *baseVisitor) VisitExpr(e Expr) {
|
||||
if v.visitExpr != nil {
|
||||
v.visitExpr(e)
|
||||
}
|
||||
}
|
||||
|
||||
// VisitEntryExpr visits the entry if the internal expr entry visitor has been configured.
|
||||
func (v *baseVisitor) VisitEntryExpr(e EntryExpr) {
|
||||
if v.visitEntryExpr != nil {
|
||||
v.visitEntryExpr(e)
|
||||
}
|
||||
}
|
||||
|
||||
// NewExprVisitor creates a visitor which only visits expression nodes.
|
||||
func NewExprVisitor(v func(Expr)) Visitor {
|
||||
return &baseVisitor{
|
||||
visitExpr: v,
|
||||
visitEntryExpr: nil,
|
||||
}
|
||||
}
|
||||
|
||||
// PostOrderVisit walks the expression graph and calls the visitor in post-order (bottom-up).
|
||||
func PostOrderVisit(expr Expr, visitor Visitor) {
|
||||
visit(expr, visitor, postOrder, 0, 0)
|
||||
}
|
||||
|
||||
// PreOrderVisit walks the expression graph and calls the visitor in pre-order (top-down).
|
||||
func PreOrderVisit(expr Expr, visitor Visitor) {
|
||||
visit(expr, visitor, preOrder, 0, 0)
|
||||
}
|
||||
|
||||
type visitOrder int
|
||||
|
||||
const (
|
||||
preOrder = iota + 1
|
||||
postOrder
|
||||
)
|
||||
|
||||
// TODO: consider exposing a way to configure a limit for the max visit depth.
|
||||
// It's possible that we could want to configure this on the NewExprVisitor()
|
||||
// and through MatchDescendents() / MaxID().
|
||||
func visit(expr Expr, visitor Visitor, order visitOrder, depth, maxDepth int) {
|
||||
if maxDepth > 0 && depth == maxDepth {
|
||||
return
|
||||
}
|
||||
if order == preOrder {
|
||||
visitor.VisitExpr(expr)
|
||||
}
|
||||
switch expr.Kind() {
|
||||
case CallKind:
|
||||
c := expr.AsCall()
|
||||
if c.IsMemberFunction() {
|
||||
visit(c.Target(), visitor, order, depth+1, maxDepth)
|
||||
}
|
||||
for _, arg := range c.Args() {
|
||||
visit(arg, visitor, order, depth+1, maxDepth)
|
||||
}
|
||||
case ComprehensionKind:
|
||||
c := expr.AsComprehension()
|
||||
visit(c.IterRange(), visitor, order, depth+1, maxDepth)
|
||||
visit(c.AccuInit(), visitor, order, depth+1, maxDepth)
|
||||
visit(c.LoopCondition(), visitor, order, depth+1, maxDepth)
|
||||
visit(c.LoopStep(), visitor, order, depth+1, maxDepth)
|
||||
visit(c.Result(), visitor, order, depth+1, maxDepth)
|
||||
case ListKind:
|
||||
l := expr.AsList()
|
||||
for _, elem := range l.Elements() {
|
||||
visit(elem, visitor, order, depth+1, maxDepth)
|
||||
}
|
||||
case MapKind:
|
||||
m := expr.AsMap()
|
||||
for _, e := range m.Entries() {
|
||||
if order == preOrder {
|
||||
visitor.VisitEntryExpr(e)
|
||||
}
|
||||
entry := e.AsMapEntry()
|
||||
visit(entry.Key(), visitor, order, depth+1, maxDepth)
|
||||
visit(entry.Value(), visitor, order, depth+1, maxDepth)
|
||||
if order == postOrder {
|
||||
visitor.VisitEntryExpr(e)
|
||||
}
|
||||
}
|
||||
case SelectKind:
|
||||
visit(expr.AsSelect().Operand(), visitor, order, depth+1, maxDepth)
|
||||
case StructKind:
|
||||
s := expr.AsStruct()
|
||||
for _, f := range s.Fields() {
|
||||
visitor.VisitEntryExpr(f)
|
||||
visit(f.AsStructField().Value(), visitor, order, depth+1, maxDepth)
|
||||
}
|
||||
}
|
||||
if order == postOrder {
|
||||
visitor.VisitExpr(expr)
|
||||
}
|
||||
}
|
||||
|
||||
func matchIsConstantValue(e NavigableExpr) bool {
|
||||
if e.Kind() == LiteralKind {
|
||||
return true
|
||||
}
|
||||
if e.Kind() == StructKind || e.Kind() == MapKind || e.Kind() == ListKind {
|
||||
for _, child := range e.Children() {
|
||||
if !matchIsConstantValue(child) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func newNavigableExpr(ast *AST, parent NavigableExpr, expr Expr, depth int) NavigableExpr {
|
||||
// Reduce navigable expression nesting by unwrapping the embedded Expr value.
|
||||
if nav, ok := expr.(*navigableExprImpl); ok {
|
||||
expr = nav.Expr
|
||||
}
|
||||
nav := &navigableExprImpl{
|
||||
Expr: expr,
|
||||
depth: depth,
|
||||
ast: ast,
|
||||
parent: parent,
|
||||
createChildren: getChildFactory(expr),
|
||||
}
|
||||
return nav
|
||||
}
|
||||
|
||||
type navigableExprImpl struct {
|
||||
Expr
|
||||
depth int
|
||||
ast *AST
|
||||
parent NavigableExpr
|
||||
createChildren childFactory
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) Parent() (NavigableExpr, bool) {
|
||||
if nav.parent != nil {
|
||||
return nav.parent, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) ID() int64 {
|
||||
return nav.Expr.ID()
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) Kind() ExprKind {
|
||||
return nav.Expr.Kind()
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) Type() *types.Type {
|
||||
return nav.ast.GetType(nav.ID())
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) Children() []NavigableExpr {
|
||||
return nav.createChildren(nav)
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) Depth() int {
|
||||
return nav.depth
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) AsCall() CallExpr {
|
||||
return navigableCallImpl{navigableExprImpl: nav}
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) AsComprehension() ComprehensionExpr {
|
||||
return navigableComprehensionImpl{navigableExprImpl: nav}
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) AsIdent() string {
|
||||
return nav.Expr.AsIdent()
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) AsList() ListExpr {
|
||||
return navigableListImpl{navigableExprImpl: nav}
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) AsLiteral() ref.Val {
|
||||
return nav.Expr.AsLiteral()
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) AsMap() MapExpr {
|
||||
return navigableMapImpl{navigableExprImpl: nav}
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) AsSelect() SelectExpr {
|
||||
return navigableSelectImpl{navigableExprImpl: nav}
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) AsStruct() StructExpr {
|
||||
return navigableStructImpl{navigableExprImpl: nav}
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) createChild(e Expr) NavigableExpr {
|
||||
return newNavigableExpr(nav.ast, nav, e, nav.depth+1)
|
||||
}
|
||||
|
||||
func (nav *navigableExprImpl) isExpr() {}
|
||||
|
||||
type navigableCallImpl struct {
|
||||
*navigableExprImpl
|
||||
}
|
||||
|
||||
func (call navigableCallImpl) FunctionName() string {
|
||||
return call.Expr.AsCall().FunctionName()
|
||||
}
|
||||
|
||||
func (call navigableCallImpl) IsMemberFunction() bool {
|
||||
return call.Expr.AsCall().IsMemberFunction()
|
||||
}
|
||||
|
||||
func (call navigableCallImpl) Target() Expr {
|
||||
t := call.Expr.AsCall().Target()
|
||||
if t != nil {
|
||||
return call.createChild(t)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (call navigableCallImpl) Args() []Expr {
|
||||
args := call.Expr.AsCall().Args()
|
||||
navArgs := make([]Expr, len(args))
|
||||
for i, a := range args {
|
||||
navArgs[i] = call.createChild(a)
|
||||
}
|
||||
return navArgs
|
||||
}
|
||||
|
||||
type navigableComprehensionImpl struct {
|
||||
*navigableExprImpl
|
||||
}
|
||||
|
||||
func (comp navigableComprehensionImpl) IterRange() Expr {
|
||||
return comp.createChild(comp.Expr.AsComprehension().IterRange())
|
||||
}
|
||||
|
||||
func (comp navigableComprehensionImpl) IterVar() string {
|
||||
return comp.Expr.AsComprehension().IterVar()
|
||||
}
|
||||
|
||||
func (comp navigableComprehensionImpl) AccuVar() string {
|
||||
return comp.Expr.AsComprehension().AccuVar()
|
||||
}
|
||||
|
||||
func (comp navigableComprehensionImpl) AccuInit() Expr {
|
||||
return comp.createChild(comp.Expr.AsComprehension().AccuInit())
|
||||
}
|
||||
|
||||
func (comp navigableComprehensionImpl) LoopCondition() Expr {
|
||||
return comp.createChild(comp.Expr.AsComprehension().LoopCondition())
|
||||
}
|
||||
|
||||
func (comp navigableComprehensionImpl) LoopStep() Expr {
|
||||
return comp.createChild(comp.Expr.AsComprehension().LoopStep())
|
||||
}
|
||||
|
||||
func (comp navigableComprehensionImpl) Result() Expr {
|
||||
return comp.createChild(comp.Expr.AsComprehension().Result())
|
||||
}
|
||||
|
||||
type navigableListImpl struct {
|
||||
*navigableExprImpl
|
||||
}
|
||||
|
||||
func (l navigableListImpl) Elements() []Expr {
|
||||
pbElems := l.Expr.AsList().Elements()
|
||||
elems := make([]Expr, len(pbElems))
|
||||
for i := 0; i < len(pbElems); i++ {
|
||||
elems[i] = l.createChild(pbElems[i])
|
||||
}
|
||||
return elems
|
||||
}
|
||||
|
||||
func (l navigableListImpl) IsOptional(index int32) bool {
|
||||
return l.Expr.AsList().IsOptional(index)
|
||||
}
|
||||
|
||||
func (l navigableListImpl) OptionalIndices() []int32 {
|
||||
return l.Expr.AsList().OptionalIndices()
|
||||
}
|
||||
|
||||
func (l navigableListImpl) Size() int {
|
||||
return l.Expr.AsList().Size()
|
||||
}
|
||||
|
||||
type navigableMapImpl struct {
|
||||
*navigableExprImpl
|
||||
}
|
||||
|
||||
func (m navigableMapImpl) Entries() []EntryExpr {
|
||||
mapExpr := m.Expr.AsMap()
|
||||
entries := make([]EntryExpr, len(mapExpr.Entries()))
|
||||
for i, e := range mapExpr.Entries() {
|
||||
entry := e.AsMapEntry()
|
||||
entries[i] = &entryExpr{
|
||||
id: e.ID(),
|
||||
entryExprKindCase: navigableEntryImpl{
|
||||
key: m.createChild(entry.Key()),
|
||||
val: m.createChild(entry.Value()),
|
||||
isOpt: entry.IsOptional(),
|
||||
},
|
||||
}
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
func (m navigableMapImpl) Size() int {
|
||||
return m.Expr.AsMap().Size()
|
||||
}
|
||||
|
||||
type navigableEntryImpl struct {
|
||||
key NavigableExpr
|
||||
val NavigableExpr
|
||||
isOpt bool
|
||||
}
|
||||
|
||||
func (e navigableEntryImpl) Kind() EntryExprKind {
|
||||
return MapEntryKind
|
||||
}
|
||||
|
||||
func (e navigableEntryImpl) Key() Expr {
|
||||
return e.key
|
||||
}
|
||||
|
||||
func (e navigableEntryImpl) Value() Expr {
|
||||
return e.val
|
||||
}
|
||||
|
||||
func (e navigableEntryImpl) IsOptional() bool {
|
||||
return e.isOpt
|
||||
}
|
||||
|
||||
func (e navigableEntryImpl) renumberIDs(IDGenerator) {}
|
||||
|
||||
func (e navigableEntryImpl) isEntryExpr() {}
|
||||
|
||||
type navigableSelectImpl struct {
|
||||
*navigableExprImpl
|
||||
}
|
||||
|
||||
func (sel navigableSelectImpl) FieldName() string {
|
||||
return sel.Expr.AsSelect().FieldName()
|
||||
}
|
||||
|
||||
func (sel navigableSelectImpl) IsTestOnly() bool {
|
||||
return sel.Expr.AsSelect().IsTestOnly()
|
||||
}
|
||||
|
||||
func (sel navigableSelectImpl) Operand() Expr {
|
||||
return sel.createChild(sel.Expr.AsSelect().Operand())
|
||||
}
|
||||
|
||||
type navigableStructImpl struct {
|
||||
*navigableExprImpl
|
||||
}
|
||||
|
||||
func (s navigableStructImpl) TypeName() string {
|
||||
return s.Expr.AsStruct().TypeName()
|
||||
}
|
||||
|
||||
func (s navigableStructImpl) Fields() []EntryExpr {
|
||||
fieldInits := s.Expr.AsStruct().Fields()
|
||||
fields := make([]EntryExpr, len(fieldInits))
|
||||
for i, f := range fieldInits {
|
||||
field := f.AsStructField()
|
||||
fields[i] = &entryExpr{
|
||||
id: f.ID(),
|
||||
entryExprKindCase: navigableFieldImpl{
|
||||
name: field.Name(),
|
||||
val: s.createChild(field.Value()),
|
||||
isOpt: field.IsOptional(),
|
||||
},
|
||||
}
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
type navigableFieldImpl struct {
|
||||
name string
|
||||
val NavigableExpr
|
||||
isOpt bool
|
||||
}
|
||||
|
||||
func (f navigableFieldImpl) Kind() EntryExprKind {
|
||||
return StructFieldKind
|
||||
}
|
||||
|
||||
func (f navigableFieldImpl) Name() string {
|
||||
return f.name
|
||||
}
|
||||
|
||||
func (f navigableFieldImpl) Value() Expr {
|
||||
return f.val
|
||||
}
|
||||
|
||||
func (f navigableFieldImpl) IsOptional() bool {
|
||||
return f.isOpt
|
||||
}
|
||||
|
||||
func (f navigableFieldImpl) renumberIDs(IDGenerator) {}
|
||||
|
||||
func (f navigableFieldImpl) isEntryExpr() {}
|
||||
|
||||
func getChildFactory(expr Expr) childFactory {
|
||||
if expr == nil {
|
||||
return noopFactory
|
||||
}
|
||||
switch expr.Kind() {
|
||||
case LiteralKind:
|
||||
return noopFactory
|
||||
case IdentKind:
|
||||
return noopFactory
|
||||
case SelectKind:
|
||||
return selectFactory
|
||||
case CallKind:
|
||||
return callArgFactory
|
||||
case ListKind:
|
||||
return listElemFactory
|
||||
case MapKind:
|
||||
return mapEntryFactory
|
||||
case StructKind:
|
||||
return structEntryFactory
|
||||
case ComprehensionKind:
|
||||
return comprehensionFactory
|
||||
default:
|
||||
return noopFactory
|
||||
}
|
||||
}
|
||||
|
||||
type childFactory func(*navigableExprImpl) []NavigableExpr
|
||||
|
||||
func noopFactory(*navigableExprImpl) []NavigableExpr {
|
||||
return nil
|
||||
}
|
||||
|
||||
func selectFactory(nav *navigableExprImpl) []NavigableExpr {
|
||||
return []NavigableExpr{nav.createChild(nav.AsSelect().Operand())}
|
||||
}
|
||||
|
||||
func callArgFactory(nav *navigableExprImpl) []NavigableExpr {
|
||||
call := nav.Expr.AsCall()
|
||||
argCount := len(call.Args())
|
||||
if call.IsMemberFunction() {
|
||||
argCount++
|
||||
}
|
||||
navExprs := make([]NavigableExpr, argCount)
|
||||
i := 0
|
||||
if call.IsMemberFunction() {
|
||||
navExprs[i] = nav.createChild(call.Target())
|
||||
i++
|
||||
}
|
||||
for _, arg := range call.Args() {
|
||||
navExprs[i] = nav.createChild(arg)
|
||||
i++
|
||||
}
|
||||
return navExprs
|
||||
}
|
||||
|
||||
func listElemFactory(nav *navigableExprImpl) []NavigableExpr {
|
||||
l := nav.Expr.AsList()
|
||||
navExprs := make([]NavigableExpr, len(l.Elements()))
|
||||
for i, e := range l.Elements() {
|
||||
navExprs[i] = nav.createChild(e)
|
||||
}
|
||||
return navExprs
|
||||
}
|
||||
|
||||
func structEntryFactory(nav *navigableExprImpl) []NavigableExpr {
|
||||
s := nav.Expr.AsStruct()
|
||||
entries := make([]NavigableExpr, len(s.Fields()))
|
||||
for i, e := range s.Fields() {
|
||||
f := e.AsStructField()
|
||||
entries[i] = nav.createChild(f.Value())
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
func mapEntryFactory(nav *navigableExprImpl) []NavigableExpr {
|
||||
m := nav.Expr.AsMap()
|
||||
entries := make([]NavigableExpr, len(m.Entries())*2)
|
||||
j := 0
|
||||
for _, e := range m.Entries() {
|
||||
mapEntry := e.AsMapEntry()
|
||||
entries[j] = nav.createChild(mapEntry.Key())
|
||||
entries[j+1] = nav.createChild(mapEntry.Value())
|
||||
j += 2
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
func comprehensionFactory(nav *navigableExprImpl) []NavigableExpr {
|
||||
compre := nav.Expr.AsComprehension()
|
||||
return []NavigableExpr{
|
||||
nav.createChild(compre.IterRange()),
|
||||
nav.createChild(compre.AccuInit()),
|
||||
nav.createChild(compre.LoopCondition()),
|
||||
nav.createChild(compre.LoopStep()),
|
||||
nav.createChild(compre.Result()),
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user