Upgrade dependent version: github.com/open-policy-agent/opa (#5315)
Upgrade dependent version: github.com/open-policy-agent/opa v0.18.0 -> v0.45.0 Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io> Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>
This commit is contained in:
338
vendor/github.com/open-policy-agent/opa/ast/index.go
generated
vendored
338
vendor/github.com/open-policy-agent/opa/ast/index.go
generated
vendored
@@ -6,7 +6,6 @@ package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -17,26 +16,27 @@ import (
|
||||
type RuleIndex interface {
|
||||
|
||||
// Build tries to construct an index for the given rules. If the index was
|
||||
// constructed, ok is true, otherwise false.
|
||||
Build(rules []*Rule) (ok bool)
|
||||
// constructed, it returns true, otherwise false.
|
||||
Build(rules []*Rule) bool
|
||||
|
||||
// Lookup searches the index for rules that will match the provided
|
||||
// resolver. If the resolver returns an error, it is returned via err.
|
||||
Lookup(resolver ValueResolver) (result *IndexResult, err error)
|
||||
Lookup(resolver ValueResolver) (*IndexResult, error)
|
||||
|
||||
// AllRules traverses the index and returns all rules that will match
|
||||
// the provided resolver without any optimizations (effectively with
|
||||
// indexing disabled). If the resolver returns an error, it is returned
|
||||
// via err.
|
||||
AllRules(resolver ValueResolver) (result *IndexResult, err error)
|
||||
AllRules(resolver ValueResolver) (*IndexResult, error)
|
||||
}
|
||||
|
||||
// IndexResult contains the result of an index lookup.
|
||||
type IndexResult struct {
|
||||
Kind DocKind
|
||||
Rules []*Rule
|
||||
Else map[*Rule][]*Rule
|
||||
Default *Rule
|
||||
Kind DocKind
|
||||
Rules []*Rule
|
||||
Else map[*Rule][]*Rule
|
||||
Default *Rule
|
||||
EarlyExit bool
|
||||
}
|
||||
|
||||
// NewIndexResult returns a new IndexResult object.
|
||||
@@ -53,16 +53,18 @@ func (ir *IndexResult) Empty() bool {
|
||||
}
|
||||
|
||||
type baseDocEqIndex struct {
|
||||
isVirtual func(Ref) bool
|
||||
root *trieNode
|
||||
defaultRule *Rule
|
||||
kind DocKind
|
||||
skipIndexing Set
|
||||
isVirtual func(Ref) bool
|
||||
root *trieNode
|
||||
defaultRule *Rule
|
||||
kind DocKind
|
||||
}
|
||||
|
||||
func newBaseDocEqIndex(isVirtual func(Ref) bool) *baseDocEqIndex {
|
||||
return &baseDocEqIndex{
|
||||
isVirtual: isVirtual,
|
||||
root: newTrieNodeImpl(),
|
||||
skipIndexing: NewSet(NewTerm(InternalPrint.Ref())),
|
||||
isVirtual: isVirtual,
|
||||
root: newTrieNodeImpl(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,8 +83,17 @@ func (i *baseDocEqIndex) Build(rules []*Rule) bool {
|
||||
i.defaultRule = rule
|
||||
return false
|
||||
}
|
||||
var skip bool
|
||||
for _, expr := range rule.Body {
|
||||
indices.Update(rule, expr)
|
||||
if op := expr.OperatorTerm(); op != nil && i.skipIndexing.Contains(op) {
|
||||
skip = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !skip {
|
||||
for _, expr := range rule.Body {
|
||||
indices.Update(rule, expr)
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
@@ -104,13 +115,11 @@ func (i *baseDocEqIndex) Build(rules []*Rule) bool {
|
||||
// Insert rule into trie with (insertion order, priority order)
|
||||
// tuple. Retaining the insertion order allows us to return rules
|
||||
// in the order they were passed to this function.
|
||||
node.rules = append(node.rules, &ruleNode{[...]int{idx, prio}, rule})
|
||||
node.append([...]int{idx, prio}, rule)
|
||||
prio++
|
||||
return false
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -133,6 +142,7 @@ func (i *baseDocEqIndex) Lookup(resolver ValueResolver) (*IndexResult, error) {
|
||||
})
|
||||
nodes := tr.unordered[pos]
|
||||
root := nodes[0].rule
|
||||
|
||||
result.Rules = append(result.Rules, root)
|
||||
if len(nodes) > 1 {
|
||||
result.Else[root] = make([]*Rule, len(nodes)-1)
|
||||
@@ -142,6 +152,8 @@ func (i *baseDocEqIndex) Lookup(resolver ValueResolver) (*IndexResult, error) {
|
||||
}
|
||||
}
|
||||
|
||||
result.EarlyExit = tr.values.Len() == 1 && tr.values.Slice()[0].IsGround()
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -171,6 +183,8 @@ func (i *baseDocEqIndex) AllRules(resolver ValueResolver) (*IndexResult, error)
|
||||
}
|
||||
}
|
||||
|
||||
result.EarlyExit = tr.values.Len() == 1 && tr.values.Slice()[0].IsGround()
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -180,18 +194,19 @@ type ruleWalker struct {
|
||||
|
||||
func (r *ruleWalker) Do(x interface{}) trieWalker {
|
||||
tn := x.(*trieNode)
|
||||
for _, rn := range tn.rules {
|
||||
r.result.Add(rn)
|
||||
}
|
||||
r.result.Add(tn)
|
||||
return r
|
||||
}
|
||||
|
||||
type valueMapper func(Value) Value
|
||||
type valueMapper struct {
|
||||
Key string
|
||||
MapValue func(Value) Value
|
||||
}
|
||||
|
||||
type refindex struct {
|
||||
Ref Ref
|
||||
Value Value
|
||||
Mapper func(Value) Value
|
||||
Mapper *valueMapper
|
||||
}
|
||||
|
||||
type refindices struct {
|
||||
@@ -231,12 +246,15 @@ func (i *refindices) Update(rule *Rule, expr *Expr) {
|
||||
|
||||
op := expr.Operator()
|
||||
|
||||
if op.Equal(Equality.Ref()) || op.Equal(Equal.Ref()) {
|
||||
|
||||
if op.Equal(Equality.Ref()) {
|
||||
i.updateEq(rule, expr)
|
||||
} else if op.Equal(Equal.Ref()) && len(expr.Operands()) == 2 {
|
||||
// NOTE(tsandall): if equal() is called with more than two arguments the
|
||||
// output value is being captured in which case the indexer cannot
|
||||
// exclude the rule if the equal() call would return false (because the
|
||||
// false value must still be produced.)
|
||||
i.updateEq(rule, expr)
|
||||
|
||||
} else if op.Equal(GlobMatch.Ref()) {
|
||||
|
||||
i.updateGlobMatch(rule, expr)
|
||||
}
|
||||
}
|
||||
@@ -256,8 +274,13 @@ func (i *refindices) Sorted() []Ref {
|
||||
return false
|
||||
})
|
||||
|
||||
sort.Slice(i.sorted, func(i, j int) bool {
|
||||
return counts[i] > counts[j]
|
||||
sort.Slice(i.sorted, func(a, b int) bool {
|
||||
if counts[a] > counts[b] {
|
||||
return true
|
||||
} else if counts[b] > counts[a] {
|
||||
return false
|
||||
}
|
||||
return i.sorted[a][0].Loc().Compare(i.sorted[b][0].Loc()) < 0
|
||||
})
|
||||
}
|
||||
|
||||
@@ -275,7 +298,7 @@ func (i *refindices) Value(rule *Rule, ref Ref) Value {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *refindices) Mapper(rule *Rule, ref Ref) valueMapper {
|
||||
func (i *refindices) Mapper(rule *Rule, ref Ref) *valueMapper {
|
||||
if index := i.index(rule, ref); index != nil {
|
||||
return index.Mapper
|
||||
}
|
||||
@@ -284,20 +307,19 @@ func (i *refindices) Mapper(rule *Rule, ref Ref) valueMapper {
|
||||
|
||||
func (i *refindices) updateEq(rule *Rule, expr *Expr) {
|
||||
a, b := expr.Operand(0), expr.Operand(1)
|
||||
if ref, value, ok := eqOperandsToRefAndValue(i.isVirtual, a, b); ok {
|
||||
i.insert(rule, &refindex{
|
||||
Ref: ref,
|
||||
Value: value,
|
||||
})
|
||||
} else if ref, value, ok := eqOperandsToRefAndValue(i.isVirtual, b, a); ok {
|
||||
i.insert(rule, &refindex{
|
||||
Ref: ref,
|
||||
Value: value,
|
||||
})
|
||||
args := rule.Head.Args
|
||||
if idx, ok := eqOperandsToRefAndValue(i.isVirtual, args, a, b); ok {
|
||||
i.insert(rule, idx)
|
||||
return
|
||||
}
|
||||
if idx, ok := eqOperandsToRefAndValue(i.isVirtual, args, b, a); ok {
|
||||
i.insert(rule, idx)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (i *refindices) updateGlobMatch(rule *Rule, expr *Expr) {
|
||||
args := rule.Head.Args
|
||||
|
||||
delim, ok := globDelimiterToString(expr.Operand(1))
|
||||
if !ok {
|
||||
@@ -307,22 +329,36 @@ func (i *refindices) updateGlobMatch(rule *Rule, expr *Expr) {
|
||||
if arr := globPatternToArray(expr.Operand(0), delim); arr != nil {
|
||||
// The 3rd operand of glob.match is the value to match. We assume the
|
||||
// 3rd operand was a reference that has been rewritten and bound to a
|
||||
// variable earlier in the query.
|
||||
// variable earlier in the query OR a function argument variable.
|
||||
match := expr.Operand(2)
|
||||
if _, ok := match.Value.(Var); ok {
|
||||
var ref Ref
|
||||
for _, other := range i.rules[rule] {
|
||||
if _, ok := other.Value.(Var); ok && other.Value.Compare(match.Value) == 0 {
|
||||
i.insert(rule, &refindex{
|
||||
Ref: other.Ref,
|
||||
Value: arr.Value,
|
||||
Mapper: func(v Value) Value {
|
||||
ref = other.Ref
|
||||
}
|
||||
}
|
||||
if ref == nil {
|
||||
for j, arg := range args {
|
||||
if arg.Equal(match) {
|
||||
ref = Ref{FunctionArgRootDocument, IntNumberTerm(j)}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ref != nil {
|
||||
i.insert(rule, &refindex{
|
||||
Ref: ref,
|
||||
Value: arr.Value,
|
||||
Mapper: &valueMapper{
|
||||
Key: delim,
|
||||
MapValue: func(v Value) Value {
|
||||
if s, ok := v.(String); ok {
|
||||
return stringSliceToArray(splitStringEscaped(string(s), delim))
|
||||
}
|
||||
return v
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -363,26 +399,34 @@ type trieWalker interface {
|
||||
type trieTraversalResult struct {
|
||||
unordered map[int][]*ruleNode
|
||||
ordering []int
|
||||
values Set
|
||||
}
|
||||
|
||||
func newTrieTraversalResult() *trieTraversalResult {
|
||||
return &trieTraversalResult{
|
||||
unordered: map[int][]*ruleNode{},
|
||||
values: NewSet(),
|
||||
}
|
||||
}
|
||||
|
||||
func (tr *trieTraversalResult) Add(node *ruleNode) {
|
||||
root := node.prio[0]
|
||||
nodes, ok := tr.unordered[root]
|
||||
if !ok {
|
||||
tr.ordering = append(tr.ordering, root)
|
||||
func (tr *trieTraversalResult) Add(t *trieNode) {
|
||||
for _, node := range t.rules {
|
||||
root := node.prio[0]
|
||||
nodes, ok := tr.unordered[root]
|
||||
if !ok {
|
||||
tr.ordering = append(tr.ordering, root)
|
||||
}
|
||||
tr.unordered[root] = append(nodes, node)
|
||||
}
|
||||
if t.values != nil {
|
||||
t.values.Foreach(func(v *Term) { tr.values.Add(v) })
|
||||
}
|
||||
tr.unordered[root] = append(nodes, node)
|
||||
}
|
||||
|
||||
type trieNode struct {
|
||||
ref Ref
|
||||
mapper valueMapper
|
||||
values Set
|
||||
mappers []*valueMapper
|
||||
next *trieNode
|
||||
any *trieNode
|
||||
undefined *trieNode
|
||||
@@ -410,7 +454,7 @@ func (node *trieNode) String() string {
|
||||
flags = append(flags, fmt.Sprintf("array:%p", node.array))
|
||||
}
|
||||
if len(node.scalars) > 0 {
|
||||
buf := []string{}
|
||||
buf := make([]string, 0, len(node.scalars))
|
||||
for k, v := range node.scalars {
|
||||
buf = append(buf, fmt.Sprintf("scalar(%v):%p", k, v))
|
||||
}
|
||||
@@ -420,12 +464,28 @@ func (node *trieNode) String() string {
|
||||
if len(node.rules) > 0 {
|
||||
flags = append(flags, fmt.Sprintf("%d rule(s)", len(node.rules)))
|
||||
}
|
||||
if node.mapper != nil {
|
||||
flags = append(flags, "mapper")
|
||||
if len(node.mappers) > 0 {
|
||||
flags = append(flags, fmt.Sprintf("%d mapper(s)", len(node.mappers)))
|
||||
}
|
||||
if l := node.values.Len(); l > 0 {
|
||||
flags = append(flags, fmt.Sprintf("%d value(s)", l))
|
||||
}
|
||||
return strings.Join(flags, " ")
|
||||
}
|
||||
|
||||
func (node *trieNode) append(prio [2]int, rule *Rule) {
|
||||
node.rules = append(node.rules, &ruleNode{prio, rule})
|
||||
|
||||
if node.values != nil {
|
||||
node.values.Add(rule.Head.Value)
|
||||
return
|
||||
}
|
||||
|
||||
if node.values == nil && rule.Head.DocKind() == CompleteDoc {
|
||||
node.values = NewSet(rule.Head.Value)
|
||||
}
|
||||
}
|
||||
|
||||
type ruleNode struct {
|
||||
prio [2]int
|
||||
rule *Rule
|
||||
@@ -459,14 +519,16 @@ func (node *trieNode) Do(walker trieWalker) {
|
||||
}
|
||||
}
|
||||
|
||||
func (node *trieNode) Insert(ref Ref, value Value, mapper valueMapper) *trieNode {
|
||||
func (node *trieNode) Insert(ref Ref, value Value, mapper *valueMapper) *trieNode {
|
||||
|
||||
if node.next == nil {
|
||||
node.next = newTrieNodeImpl()
|
||||
node.next.ref = ref
|
||||
}
|
||||
|
||||
node.next.mapper = mapper
|
||||
if mapper != nil {
|
||||
node.next.addMapper(mapper)
|
||||
}
|
||||
|
||||
return node.next.insertValue(value)
|
||||
}
|
||||
@@ -477,13 +539,20 @@ func (node *trieNode) Traverse(resolver ValueResolver, tr *trieTraversalResult)
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := range node.rules {
|
||||
tr.Add(node.rules[i])
|
||||
}
|
||||
tr.Add(node)
|
||||
|
||||
return node.next.traverse(resolver, tr)
|
||||
}
|
||||
|
||||
func (node *trieNode) addMapper(mapper *valueMapper) {
|
||||
for i := range node.mappers {
|
||||
if node.mappers[i].Key == mapper.Key {
|
||||
return
|
||||
}
|
||||
}
|
||||
node.mappers = append(node.mappers, mapper)
|
||||
}
|
||||
|
||||
func (node *trieNode) insertValue(value Value) *trieNode {
|
||||
|
||||
switch value := value.(type) {
|
||||
@@ -504,7 +573,7 @@ func (node *trieNode) insertValue(value Value) *trieNode {
|
||||
node.scalars[value] = child
|
||||
}
|
||||
return child
|
||||
case Array:
|
||||
case *Array:
|
||||
if node.array == nil {
|
||||
node.array = newTrieNodeImpl()
|
||||
}
|
||||
@@ -514,25 +583,25 @@ func (node *trieNode) insertValue(value Value) *trieNode {
|
||||
panic("illegal value")
|
||||
}
|
||||
|
||||
func (node *trieNode) insertArray(arr Array) *trieNode {
|
||||
func (node *trieNode) insertArray(arr *Array) *trieNode {
|
||||
|
||||
if len(arr) == 0 {
|
||||
if arr.Len() == 0 {
|
||||
return node
|
||||
}
|
||||
|
||||
switch head := arr[0].Value.(type) {
|
||||
switch head := arr.Elem(0).Value.(type) {
|
||||
case Var:
|
||||
if node.any == nil {
|
||||
node.any = newTrieNodeImpl()
|
||||
}
|
||||
return node.any.insertArray(arr[1:])
|
||||
return node.any.insertArray(arr.Slice(1, -1))
|
||||
case Null, Boolean, Number, String:
|
||||
child, ok := node.scalars[head]
|
||||
if !ok {
|
||||
child = newTrieNodeImpl()
|
||||
node.scalars[head] = child
|
||||
}
|
||||
return child.insertArray(arr[1:])
|
||||
return child.insertArray(arr.Slice(1, -1))
|
||||
}
|
||||
|
||||
panic("illegal value")
|
||||
@@ -553,7 +622,10 @@ func (node *trieNode) traverse(resolver ValueResolver, tr *trieTraversalResult)
|
||||
}
|
||||
|
||||
if node.undefined != nil {
|
||||
node.undefined.Traverse(resolver, tr)
|
||||
err = node.undefined.Traverse(resolver, tr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if v == nil {
|
||||
@@ -561,20 +633,29 @@ func (node *trieNode) traverse(resolver ValueResolver, tr *trieTraversalResult)
|
||||
}
|
||||
|
||||
if node.any != nil {
|
||||
node.any.Traverse(resolver, tr)
|
||||
err = node.any.Traverse(resolver, tr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if node.mapper != nil {
|
||||
v = node.mapper(v)
|
||||
if err := node.traverseValue(resolver, tr, v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return node.traverseValue(resolver, tr, v)
|
||||
for i := range node.mappers {
|
||||
if err := node.traverseValue(resolver, tr, node.mappers[i].MapValue(v)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (node *trieNode) traverseValue(resolver ValueResolver, tr *trieTraversalResult, value Value) error {
|
||||
|
||||
switch value := value.(type) {
|
||||
case Array:
|
||||
case *Array:
|
||||
if node.array == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -591,20 +672,23 @@ func (node *trieNode) traverseValue(resolver ValueResolver, tr *trieTraversalRes
|
||||
return nil
|
||||
}
|
||||
|
||||
func (node *trieNode) traverseArray(resolver ValueResolver, tr *trieTraversalResult, arr Array) error {
|
||||
func (node *trieNode) traverseArray(resolver ValueResolver, tr *trieTraversalResult, arr *Array) error {
|
||||
|
||||
if len(arr) == 0 {
|
||||
if arr.Len() == 0 {
|
||||
return node.Traverse(resolver, tr)
|
||||
}
|
||||
|
||||
head := arr[0].Value
|
||||
head := arr.Elem(0).Value
|
||||
|
||||
if !IsScalar(head) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if node.any != nil {
|
||||
node.any.traverseArray(resolver, tr, arr[1:])
|
||||
err := node.any.traverseArray(resolver, tr, arr.Slice(1, -1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
child, ok := node.scalars[head]
|
||||
@@ -612,7 +696,7 @@ func (node *trieNode) traverseArray(resolver ValueResolver, tr *trieTraversalRes
|
||||
return nil
|
||||
}
|
||||
|
||||
return child.traverseArray(resolver, tr, arr[1:])
|
||||
return child.traverseArray(resolver, tr, arr.Slice(1, -1))
|
||||
}
|
||||
|
||||
func (node *trieNode) traverseUnknown(resolver ValueResolver, tr *trieTraversalResult) error {
|
||||
@@ -646,41 +730,42 @@ func (node *trieNode) traverseUnknown(resolver ValueResolver, tr *trieTraversalR
|
||||
return nil
|
||||
}
|
||||
|
||||
type triePrinter struct {
|
||||
depth int
|
||||
w io.Writer
|
||||
// If term `a` is one of the function's operands, we store a Ref: `args[0]`
|
||||
// for the argument number. So for `f(x, y) { x = 10; y = 12 }`, we'll
|
||||
// bind `args[0]` and `args[1]` to this rule when called for (x=10) and
|
||||
// (y=12) respectively.
|
||||
func eqOperandsToRefAndValue(isVirtual func(Ref) bool, args []*Term, a, b *Term) (*refindex, bool) {
|
||||
switch v := a.Value.(type) {
|
||||
case Var:
|
||||
for i, arg := range args {
|
||||
if arg.Value.Compare(v) == 0 {
|
||||
if bval, ok := indexValue(b); ok {
|
||||
return &refindex{Ref: Ref{FunctionArgRootDocument, IntNumberTerm(i)}, Value: bval}, true
|
||||
}
|
||||
}
|
||||
}
|
||||
case Ref:
|
||||
if !RootDocumentNames.Contains(v[0]) {
|
||||
return nil, false
|
||||
}
|
||||
if isVirtual(v) {
|
||||
return nil, false
|
||||
}
|
||||
if v.IsNested() || !v.IsGround() {
|
||||
return nil, false
|
||||
}
|
||||
if bval, ok := indexValue(b); ok {
|
||||
return &refindex{Ref: v, Value: bval}, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (p triePrinter) Do(x interface{}) trieWalker {
|
||||
padding := strings.Repeat(" ", p.depth)
|
||||
fmt.Fprintf(p.w, "%v%v\n", padding, x)
|
||||
p.depth++
|
||||
return p
|
||||
}
|
||||
|
||||
func eqOperandsToRefAndValue(isVirtual func(Ref) bool, a, b *Term) (Ref, Value, bool) {
|
||||
|
||||
ref, ok := a.Value.(Ref)
|
||||
if !ok {
|
||||
return nil, nil, false
|
||||
}
|
||||
|
||||
if !RootDocumentNames.Contains(ref[0]) {
|
||||
return nil, nil, false
|
||||
}
|
||||
|
||||
if isVirtual(ref) {
|
||||
return nil, nil, false
|
||||
}
|
||||
|
||||
if ref.IsNested() || !ref.IsGround() {
|
||||
return nil, nil, false
|
||||
}
|
||||
|
||||
func indexValue(b *Term) (Value, bool) {
|
||||
switch b := b.Value.(type) {
|
||||
case Null, Boolean, Number, String, Var:
|
||||
return ref, b, true
|
||||
case Array:
|
||||
return b, true
|
||||
case *Array:
|
||||
stop := false
|
||||
first := true
|
||||
vis := NewGenericVisitor(func(x interface{}) bool {
|
||||
@@ -690,33 +775,34 @@ func eqOperandsToRefAndValue(isVirtual func(Ref) bool, a, b *Term) (Ref, Value,
|
||||
}
|
||||
switch x.(type) {
|
||||
// No nested structures or values that require evaluation (other than var).
|
||||
case Array, Object, Set, *ArrayComprehension, *ObjectComprehension, *SetComprehension, Ref:
|
||||
case *Array, Object, Set, *ArrayComprehension, *ObjectComprehension, *SetComprehension, Ref:
|
||||
stop = true
|
||||
}
|
||||
return stop
|
||||
})
|
||||
vis.Walk(b)
|
||||
if !stop {
|
||||
return ref, b, true
|
||||
return b, true
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil, false
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func globDelimiterToString(delim *Term) (string, bool) {
|
||||
|
||||
arr, ok := delim.Value.(Array)
|
||||
arr, ok := delim.Value.(*Array)
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
|
||||
var result string
|
||||
|
||||
if len(arr) == 0 {
|
||||
if arr.Len() == 0 {
|
||||
result = "."
|
||||
} else {
|
||||
for _, term := range arr {
|
||||
for i := 0; i < arr.Len(); i++ {
|
||||
term := arr.Elem(i)
|
||||
s, ok := term.Value.(String)
|
||||
if !ok {
|
||||
return "", false
|
||||
@@ -736,11 +822,11 @@ func globPatternToArray(pattern *Term, delim string) *Term {
|
||||
}
|
||||
|
||||
parts := splitStringEscaped(string(s), delim)
|
||||
result := make(Array, len(parts))
|
||||
arr := make([]*Term, len(parts))
|
||||
|
||||
for i := range parts {
|
||||
if parts[i] == "*" {
|
||||
result[i] = VarTerm("$globwildcard")
|
||||
arr[i] = VarTerm("$globwildcard")
|
||||
} else {
|
||||
var escaped bool
|
||||
for _, c := range parts[i] {
|
||||
@@ -758,11 +844,11 @@ func globPatternToArray(pattern *Term, delim string) *Term {
|
||||
}
|
||||
escaped = false
|
||||
}
|
||||
result[i] = StringTerm(parts[i])
|
||||
arr[i] = StringTerm(parts[i])
|
||||
}
|
||||
}
|
||||
|
||||
return NewTerm(result)
|
||||
return NewTerm(NewArray(arr...))
|
||||
}
|
||||
|
||||
// splits s on characters in delim except if delim characters have been escaped
|
||||
@@ -789,10 +875,10 @@ func splitStringEscaped(s string, delim string) []string {
|
||||
return result
|
||||
}
|
||||
|
||||
func stringSliceToArray(s []string) (result Array) {
|
||||
result = make(Array, len(s))
|
||||
for i := range s {
|
||||
result[i] = StringTerm(s[i])
|
||||
func stringSliceToArray(s []string) *Array {
|
||||
arr := make([]*Term, len(s))
|
||||
for i, v := range s {
|
||||
arr[i] = StringTerm(v)
|
||||
}
|
||||
return
|
||||
return NewArray(arr...)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user