github.com/rajeev159/opa@v0.45.0/ast/index.go (about)

     1  // Copyright 2017 The OPA Authors.  All rights reserved.
     2  // Use of this source code is governed by an Apache2
     3  // license that can be found in the LICENSE file.
     4  
     5  package ast
     6  
     7  import (
     8  	"fmt"
     9  	"sort"
    10  	"strings"
    11  
    12  	"github.com/open-policy-agent/opa/util"
    13  )
    14  
    15  // RuleIndex defines the interface for rule indices.
    16  type RuleIndex interface {
    17  
    18  	// Build tries to construct an index for the given rules. If the index was
    19  	// constructed, it returns true, otherwise false.
    20  	Build(rules []*Rule) bool
    21  
    22  	// Lookup searches the index for rules that will match the provided
    23  	// resolver. If the resolver returns an error, it is returned via err.
    24  	Lookup(resolver ValueResolver) (*IndexResult, error)
    25  
    26  	// AllRules traverses the index and returns all rules that will match
    27  	// the provided resolver without any optimizations (effectively with
    28  	// indexing disabled). If the resolver returns an error, it is returned
    29  	// via err.
    30  	AllRules(resolver ValueResolver) (*IndexResult, error)
    31  }
    32  
    33  // IndexResult contains the result of an index lookup.
    34  type IndexResult struct {
    35  	Kind      DocKind
    36  	Rules     []*Rule
    37  	Else      map[*Rule][]*Rule
    38  	Default   *Rule
    39  	EarlyExit bool
    40  }
    41  
    42  // NewIndexResult returns a new IndexResult object.
    43  func NewIndexResult(kind DocKind) *IndexResult {
    44  	return &IndexResult{
    45  		Kind: kind,
    46  		Else: map[*Rule][]*Rule{},
    47  	}
    48  }
    49  
    50  // Empty returns true if there are no rules to evaluate.
    51  func (ir *IndexResult) Empty() bool {
    52  	return len(ir.Rules) == 0 && ir.Default == nil
    53  }
    54  
    55  type baseDocEqIndex struct {
    56  	skipIndexing Set
    57  	isVirtual    func(Ref) bool
    58  	root         *trieNode
    59  	defaultRule  *Rule
    60  	kind         DocKind
    61  }
    62  
    63  func newBaseDocEqIndex(isVirtual func(Ref) bool) *baseDocEqIndex {
    64  	return &baseDocEqIndex{
    65  		skipIndexing: NewSet(NewTerm(InternalPrint.Ref())),
    66  		isVirtual:    isVirtual,
    67  		root:         newTrieNodeImpl(),
    68  	}
    69  }
    70  
    71  func (i *baseDocEqIndex) Build(rules []*Rule) bool {
    72  	if len(rules) == 0 {
    73  		return false
    74  	}
    75  
    76  	i.kind = rules[0].Head.DocKind()
    77  	indices := newrefindices(i.isVirtual)
    78  
    79  	// build indices for each rule.
    80  	for idx := range rules {
    81  		WalkRules(rules[idx], func(rule *Rule) bool {
    82  			if rule.Default {
    83  				i.defaultRule = rule
    84  				return false
    85  			}
    86  			var skip bool
    87  			for _, expr := range rule.Body {
    88  				if op := expr.OperatorTerm(); op != nil && i.skipIndexing.Contains(op) {
    89  					skip = true
    90  					break
    91  				}
    92  			}
    93  			if !skip {
    94  				for _, expr := range rule.Body {
    95  					indices.Update(rule, expr)
    96  				}
    97  			}
    98  			return false
    99  		})
   100  	}
   101  
   102  	// build trie out of indices.
   103  	for idx := range rules {
   104  		var prio int
   105  		WalkRules(rules[idx], func(rule *Rule) bool {
   106  			if rule.Default {
   107  				return false
   108  			}
   109  			node := i.root
   110  			if indices.Indexed(rule) {
   111  				for _, ref := range indices.Sorted() {
   112  					node = node.Insert(ref, indices.Value(rule, ref), indices.Mapper(rule, ref))
   113  				}
   114  			}
   115  			// Insert rule into trie with (insertion order, priority order)
   116  			// tuple. Retaining the insertion order allows us to return rules
   117  			// in the order they were passed to this function.
   118  			node.append([...]int{idx, prio}, rule)
   119  			prio++
   120  			return false
   121  		})
   122  	}
   123  	return true
   124  }
   125  
   126  func (i *baseDocEqIndex) Lookup(resolver ValueResolver) (*IndexResult, error) {
   127  
   128  	tr := newTrieTraversalResult()
   129  
   130  	err := i.root.Traverse(resolver, tr)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  
   135  	result := NewIndexResult(i.kind)
   136  	result.Default = i.defaultRule
   137  	result.Rules = make([]*Rule, 0, len(tr.ordering))
   138  
   139  	for _, pos := range tr.ordering {
   140  		sort.Slice(tr.unordered[pos], func(i, j int) bool {
   141  			return tr.unordered[pos][i].prio[1] < tr.unordered[pos][j].prio[1]
   142  		})
   143  		nodes := tr.unordered[pos]
   144  		root := nodes[0].rule
   145  
   146  		result.Rules = append(result.Rules, root)
   147  		if len(nodes) > 1 {
   148  			result.Else[root] = make([]*Rule, len(nodes)-1)
   149  			for i := 1; i < len(nodes); i++ {
   150  				result.Else[root][i-1] = nodes[i].rule
   151  			}
   152  		}
   153  	}
   154  
   155  	result.EarlyExit = tr.values.Len() == 1 && tr.values.Slice()[0].IsGround()
   156  
   157  	return result, nil
   158  }
   159  
   160  func (i *baseDocEqIndex) AllRules(resolver ValueResolver) (*IndexResult, error) {
   161  	tr := newTrieTraversalResult()
   162  
   163  	// Walk over the rule trie and accumulate _all_ rules
   164  	rw := &ruleWalker{result: tr}
   165  	i.root.Do(rw)
   166  
   167  	result := NewIndexResult(i.kind)
   168  	result.Default = i.defaultRule
   169  	result.Rules = make([]*Rule, 0, len(tr.ordering))
   170  
   171  	for _, pos := range tr.ordering {
   172  		sort.Slice(tr.unordered[pos], func(i, j int) bool {
   173  			return tr.unordered[pos][i].prio[1] < tr.unordered[pos][j].prio[1]
   174  		})
   175  		nodes := tr.unordered[pos]
   176  		root := nodes[0].rule
   177  		result.Rules = append(result.Rules, root)
   178  		if len(nodes) > 1 {
   179  			result.Else[root] = make([]*Rule, len(nodes)-1)
   180  			for i := 1; i < len(nodes); i++ {
   181  				result.Else[root][i-1] = nodes[i].rule
   182  			}
   183  		}
   184  	}
   185  
   186  	result.EarlyExit = tr.values.Len() == 1 && tr.values.Slice()[0].IsGround()
   187  
   188  	return result, nil
   189  }
   190  
   191  type ruleWalker struct {
   192  	result *trieTraversalResult
   193  }
   194  
   195  func (r *ruleWalker) Do(x interface{}) trieWalker {
   196  	tn := x.(*trieNode)
   197  	r.result.Add(tn)
   198  	return r
   199  }
   200  
   201  type valueMapper struct {
   202  	Key      string
   203  	MapValue func(Value) Value
   204  }
   205  
   206  type refindex struct {
   207  	Ref    Ref
   208  	Value  Value
   209  	Mapper *valueMapper
   210  }
   211  
   212  type refindices struct {
   213  	isVirtual func(Ref) bool
   214  	rules     map[*Rule][]*refindex
   215  	frequency *util.HashMap
   216  	sorted    []Ref
   217  }
   218  
   219  func newrefindices(isVirtual func(Ref) bool) *refindices {
   220  	return &refindices{
   221  		isVirtual: isVirtual,
   222  		rules:     map[*Rule][]*refindex{},
   223  		frequency: util.NewHashMap(func(a, b util.T) bool {
   224  			r1, r2 := a.(Ref), b.(Ref)
   225  			return r1.Equal(r2)
   226  		}, func(x util.T) int {
   227  			return x.(Ref).Hash()
   228  		}),
   229  	}
   230  }
   231  
   232  // Update attempts to update the refindices for the given expression in the
   233  // given rule. If the expression cannot be indexed the update does not affect
   234  // the indices.
   235  func (i *refindices) Update(rule *Rule, expr *Expr) {
   236  
   237  	if expr.Negated {
   238  		return
   239  	}
   240  
   241  	if len(expr.With) > 0 {
   242  		// NOTE(tsandall): In the future, we may need to consider expressions
   243  		// that have with statements applied to them.
   244  		return
   245  	}
   246  
   247  	op := expr.Operator()
   248  
   249  	if op.Equal(Equality.Ref()) {
   250  		i.updateEq(rule, expr)
   251  	} else if op.Equal(Equal.Ref()) && len(expr.Operands()) == 2 {
   252  		// NOTE(tsandall): if equal() is called with more than two arguments the
   253  		// output value is being captured in which case the indexer cannot
   254  		// exclude the rule if the equal() call would return false (because the
   255  		// false value must still be produced.)
   256  		i.updateEq(rule, expr)
   257  	} else if op.Equal(GlobMatch.Ref()) {
   258  		i.updateGlobMatch(rule, expr)
   259  	}
   260  }
   261  
   262  // Sorted returns a sorted list of references that the indices were built from.
   263  // References that appear more frequently in the indexed rules are ordered
   264  // before less frequently appearing references.
   265  func (i *refindices) Sorted() []Ref {
   266  
   267  	if i.sorted == nil {
   268  		counts := make([]int, 0, i.frequency.Len())
   269  		i.sorted = make([]Ref, 0, i.frequency.Len())
   270  
   271  		i.frequency.Iter(func(k, v util.T) bool {
   272  			counts = append(counts, v.(int))
   273  			i.sorted = append(i.sorted, k.(Ref))
   274  			return false
   275  		})
   276  
   277  		sort.Slice(i.sorted, func(a, b int) bool {
   278  			if counts[a] > counts[b] {
   279  				return true
   280  			} else if counts[b] > counts[a] {
   281  				return false
   282  			}
   283  			return i.sorted[a][0].Loc().Compare(i.sorted[b][0].Loc()) < 0
   284  		})
   285  	}
   286  
   287  	return i.sorted
   288  }
   289  
   290  func (i *refindices) Indexed(rule *Rule) bool {
   291  	return len(i.rules[rule]) > 0
   292  }
   293  
   294  func (i *refindices) Value(rule *Rule, ref Ref) Value {
   295  	if index := i.index(rule, ref); index != nil {
   296  		return index.Value
   297  	}
   298  	return nil
   299  }
   300  
   301  func (i *refindices) Mapper(rule *Rule, ref Ref) *valueMapper {
   302  	if index := i.index(rule, ref); index != nil {
   303  		return index.Mapper
   304  	}
   305  	return nil
   306  }
   307  
   308  func (i *refindices) updateEq(rule *Rule, expr *Expr) {
   309  	a, b := expr.Operand(0), expr.Operand(1)
   310  	args := rule.Head.Args
   311  	if idx, ok := eqOperandsToRefAndValue(i.isVirtual, args, a, b); ok {
   312  		i.insert(rule, idx)
   313  		return
   314  	}
   315  	if idx, ok := eqOperandsToRefAndValue(i.isVirtual, args, b, a); ok {
   316  		i.insert(rule, idx)
   317  		return
   318  	}
   319  }
   320  
   321  func (i *refindices) updateGlobMatch(rule *Rule, expr *Expr) {
   322  	args := rule.Head.Args
   323  
   324  	delim, ok := globDelimiterToString(expr.Operand(1))
   325  	if !ok {
   326  		return
   327  	}
   328  
   329  	if arr := globPatternToArray(expr.Operand(0), delim); arr != nil {
   330  		// The 3rd operand of glob.match is the value to match. We assume the
   331  		// 3rd operand was a reference that has been rewritten and bound to a
   332  		// variable earlier in the query OR a function argument variable.
   333  		match := expr.Operand(2)
   334  		if _, ok := match.Value.(Var); ok {
   335  			var ref Ref
   336  			for _, other := range i.rules[rule] {
   337  				if _, ok := other.Value.(Var); ok && other.Value.Compare(match.Value) == 0 {
   338  					ref = other.Ref
   339  				}
   340  			}
   341  			if ref == nil {
   342  				for j, arg := range args {
   343  					if arg.Equal(match) {
   344  						ref = Ref{FunctionArgRootDocument, IntNumberTerm(j)}
   345  					}
   346  				}
   347  			}
   348  			if ref != nil {
   349  				i.insert(rule, &refindex{
   350  					Ref:   ref,
   351  					Value: arr.Value,
   352  					Mapper: &valueMapper{
   353  						Key: delim,
   354  						MapValue: func(v Value) Value {
   355  							if s, ok := v.(String); ok {
   356  								return stringSliceToArray(splitStringEscaped(string(s), delim))
   357  							}
   358  							return v
   359  						},
   360  					},
   361  				})
   362  			}
   363  		}
   364  	}
   365  }
   366  
   367  func (i *refindices) insert(rule *Rule, index *refindex) {
   368  
   369  	count, ok := i.frequency.Get(index.Ref)
   370  	if !ok {
   371  		count = 0
   372  	}
   373  
   374  	i.frequency.Put(index.Ref, count.(int)+1)
   375  
   376  	for pos, other := range i.rules[rule] {
   377  		if other.Ref.Equal(index.Ref) {
   378  			i.rules[rule][pos] = index
   379  			return
   380  		}
   381  	}
   382  
   383  	i.rules[rule] = append(i.rules[rule], index)
   384  }
   385  
   386  func (i *refindices) index(rule *Rule, ref Ref) *refindex {
   387  	for _, index := range i.rules[rule] {
   388  		if index.Ref.Equal(ref) {
   389  			return index
   390  		}
   391  	}
   392  	return nil
   393  }
   394  
   395  type trieWalker interface {
   396  	Do(x interface{}) trieWalker
   397  }
   398  
   399  type trieTraversalResult struct {
   400  	unordered map[int][]*ruleNode
   401  	ordering  []int
   402  	values    Set
   403  }
   404  
   405  func newTrieTraversalResult() *trieTraversalResult {
   406  	return &trieTraversalResult{
   407  		unordered: map[int][]*ruleNode{},
   408  		values:    NewSet(),
   409  	}
   410  }
   411  
   412  func (tr *trieTraversalResult) Add(t *trieNode) {
   413  	for _, node := range t.rules {
   414  		root := node.prio[0]
   415  		nodes, ok := tr.unordered[root]
   416  		if !ok {
   417  			tr.ordering = append(tr.ordering, root)
   418  		}
   419  		tr.unordered[root] = append(nodes, node)
   420  	}
   421  	if t.values != nil {
   422  		t.values.Foreach(func(v *Term) { tr.values.Add(v) })
   423  	}
   424  }
   425  
   426  type trieNode struct {
   427  	ref       Ref
   428  	values    Set
   429  	mappers   []*valueMapper
   430  	next      *trieNode
   431  	any       *trieNode
   432  	undefined *trieNode
   433  	scalars   map[Value]*trieNode
   434  	array     *trieNode
   435  	rules     []*ruleNode
   436  }
   437  
   438  func (node *trieNode) String() string {
   439  	var flags []string
   440  	flags = append(flags, fmt.Sprintf("self:%p", node))
   441  	if len(node.ref) > 0 {
   442  		flags = append(flags, node.ref.String())
   443  	}
   444  	if node.next != nil {
   445  		flags = append(flags, fmt.Sprintf("next:%p", node.next))
   446  	}
   447  	if node.any != nil {
   448  		flags = append(flags, fmt.Sprintf("any:%p", node.any))
   449  	}
   450  	if node.undefined != nil {
   451  		flags = append(flags, fmt.Sprintf("undefined:%p", node.undefined))
   452  	}
   453  	if node.array != nil {
   454  		flags = append(flags, fmt.Sprintf("array:%p", node.array))
   455  	}
   456  	if len(node.scalars) > 0 {
   457  		buf := make([]string, 0, len(node.scalars))
   458  		for k, v := range node.scalars {
   459  			buf = append(buf, fmt.Sprintf("scalar(%v):%p", k, v))
   460  		}
   461  		sort.Strings(buf)
   462  		flags = append(flags, strings.Join(buf, " "))
   463  	}
   464  	if len(node.rules) > 0 {
   465  		flags = append(flags, fmt.Sprintf("%d rule(s)", len(node.rules)))
   466  	}
   467  	if len(node.mappers) > 0 {
   468  		flags = append(flags, fmt.Sprintf("%d mapper(s)", len(node.mappers)))
   469  	}
   470  	if l := node.values.Len(); l > 0 {
   471  		flags = append(flags, fmt.Sprintf("%d value(s)", l))
   472  	}
   473  	return strings.Join(flags, " ")
   474  }
   475  
   476  func (node *trieNode) append(prio [2]int, rule *Rule) {
   477  	node.rules = append(node.rules, &ruleNode{prio, rule})
   478  
   479  	if node.values != nil {
   480  		node.values.Add(rule.Head.Value)
   481  		return
   482  	}
   483  
   484  	if node.values == nil && rule.Head.DocKind() == CompleteDoc {
   485  		node.values = NewSet(rule.Head.Value)
   486  	}
   487  }
   488  
   489  type ruleNode struct {
   490  	prio [2]int
   491  	rule *Rule
   492  }
   493  
   494  func newTrieNodeImpl() *trieNode {
   495  	return &trieNode{
   496  		scalars: map[Value]*trieNode{},
   497  	}
   498  }
   499  
   500  func (node *trieNode) Do(walker trieWalker) {
   501  	next := walker.Do(node)
   502  	if next == nil {
   503  		return
   504  	}
   505  	if node.any != nil {
   506  		node.any.Do(next)
   507  	}
   508  	if node.undefined != nil {
   509  		node.undefined.Do(next)
   510  	}
   511  	for _, child := range node.scalars {
   512  		child.Do(next)
   513  	}
   514  	if node.array != nil {
   515  		node.array.Do(next)
   516  	}
   517  	if node.next != nil {
   518  		node.next.Do(next)
   519  	}
   520  }
   521  
   522  func (node *trieNode) Insert(ref Ref, value Value, mapper *valueMapper) *trieNode {
   523  
   524  	if node.next == nil {
   525  		node.next = newTrieNodeImpl()
   526  		node.next.ref = ref
   527  	}
   528  
   529  	if mapper != nil {
   530  		node.next.addMapper(mapper)
   531  	}
   532  
   533  	return node.next.insertValue(value)
   534  }
   535  
   536  func (node *trieNode) Traverse(resolver ValueResolver, tr *trieTraversalResult) error {
   537  
   538  	if node == nil {
   539  		return nil
   540  	}
   541  
   542  	tr.Add(node)
   543  
   544  	return node.next.traverse(resolver, tr)
   545  }
   546  
   547  func (node *trieNode) addMapper(mapper *valueMapper) {
   548  	for i := range node.mappers {
   549  		if node.mappers[i].Key == mapper.Key {
   550  			return
   551  		}
   552  	}
   553  	node.mappers = append(node.mappers, mapper)
   554  }
   555  
   556  func (node *trieNode) insertValue(value Value) *trieNode {
   557  
   558  	switch value := value.(type) {
   559  	case nil:
   560  		if node.undefined == nil {
   561  			node.undefined = newTrieNodeImpl()
   562  		}
   563  		return node.undefined
   564  	case Var:
   565  		if node.any == nil {
   566  			node.any = newTrieNodeImpl()
   567  		}
   568  		return node.any
   569  	case Null, Boolean, Number, String:
   570  		child, ok := node.scalars[value]
   571  		if !ok {
   572  			child = newTrieNodeImpl()
   573  			node.scalars[value] = child
   574  		}
   575  		return child
   576  	case *Array:
   577  		if node.array == nil {
   578  			node.array = newTrieNodeImpl()
   579  		}
   580  		return node.array.insertArray(value)
   581  	}
   582  
   583  	panic("illegal value")
   584  }
   585  
   586  func (node *trieNode) insertArray(arr *Array) *trieNode {
   587  
   588  	if arr.Len() == 0 {
   589  		return node
   590  	}
   591  
   592  	switch head := arr.Elem(0).Value.(type) {
   593  	case Var:
   594  		if node.any == nil {
   595  			node.any = newTrieNodeImpl()
   596  		}
   597  		return node.any.insertArray(arr.Slice(1, -1))
   598  	case Null, Boolean, Number, String:
   599  		child, ok := node.scalars[head]
   600  		if !ok {
   601  			child = newTrieNodeImpl()
   602  			node.scalars[head] = child
   603  		}
   604  		return child.insertArray(arr.Slice(1, -1))
   605  	}
   606  
   607  	panic("illegal value")
   608  }
   609  
   610  func (node *trieNode) traverse(resolver ValueResolver, tr *trieTraversalResult) error {
   611  
   612  	if node == nil {
   613  		return nil
   614  	}
   615  
   616  	v, err := resolver.Resolve(node.ref)
   617  	if err != nil {
   618  		if IsUnknownValueErr(err) {
   619  			return node.traverseUnknown(resolver, tr)
   620  		}
   621  		return err
   622  	}
   623  
   624  	if node.undefined != nil {
   625  		err = node.undefined.Traverse(resolver, tr)
   626  		if err != nil {
   627  			return err
   628  		}
   629  	}
   630  
   631  	if v == nil {
   632  		return nil
   633  	}
   634  
   635  	if node.any != nil {
   636  		err = node.any.Traverse(resolver, tr)
   637  		if err != nil {
   638  			return err
   639  		}
   640  	}
   641  
   642  	if err := node.traverseValue(resolver, tr, v); err != nil {
   643  		return err
   644  	}
   645  
   646  	for i := range node.mappers {
   647  		if err := node.traverseValue(resolver, tr, node.mappers[i].MapValue(v)); err != nil {
   648  			return err
   649  		}
   650  	}
   651  
   652  	return nil
   653  }
   654  
   655  func (node *trieNode) traverseValue(resolver ValueResolver, tr *trieTraversalResult, value Value) error {
   656  
   657  	switch value := value.(type) {
   658  	case *Array:
   659  		if node.array == nil {
   660  			return nil
   661  		}
   662  		return node.array.traverseArray(resolver, tr, value)
   663  
   664  	case Null, Boolean, Number, String:
   665  		child, ok := node.scalars[value]
   666  		if !ok {
   667  			return nil
   668  		}
   669  		return child.Traverse(resolver, tr)
   670  	}
   671  
   672  	return nil
   673  }
   674  
   675  func (node *trieNode) traverseArray(resolver ValueResolver, tr *trieTraversalResult, arr *Array) error {
   676  
   677  	if arr.Len() == 0 {
   678  		return node.Traverse(resolver, tr)
   679  	}
   680  
   681  	head := arr.Elem(0).Value
   682  
   683  	if !IsScalar(head) {
   684  		return nil
   685  	}
   686  
   687  	if node.any != nil {
   688  		err := node.any.traverseArray(resolver, tr, arr.Slice(1, -1))
   689  		if err != nil {
   690  			return err
   691  		}
   692  	}
   693  
   694  	child, ok := node.scalars[head]
   695  	if !ok {
   696  		return nil
   697  	}
   698  
   699  	return child.traverseArray(resolver, tr, arr.Slice(1, -1))
   700  }
   701  
   702  func (node *trieNode) traverseUnknown(resolver ValueResolver, tr *trieTraversalResult) error {
   703  
   704  	if node == nil {
   705  		return nil
   706  	}
   707  
   708  	if err := node.Traverse(resolver, tr); err != nil {
   709  		return err
   710  	}
   711  
   712  	if err := node.undefined.traverseUnknown(resolver, tr); err != nil {
   713  		return err
   714  	}
   715  
   716  	if err := node.any.traverseUnknown(resolver, tr); err != nil {
   717  		return err
   718  	}
   719  
   720  	if err := node.array.traverseUnknown(resolver, tr); err != nil {
   721  		return err
   722  	}
   723  
   724  	for _, child := range node.scalars {
   725  		if err := child.traverseUnknown(resolver, tr); err != nil {
   726  			return err
   727  		}
   728  	}
   729  
   730  	return nil
   731  }
   732  
   733  // If term `a` is one of the function's operands, we store a Ref: `args[0]`
   734  // for the argument number. So for `f(x, y) { x = 10; y = 12 }`, we'll
   735  // bind `args[0]` and `args[1]` to this rule when called for (x=10) and
   736  // (y=12) respectively.
   737  func eqOperandsToRefAndValue(isVirtual func(Ref) bool, args []*Term, a, b *Term) (*refindex, bool) {
   738  	switch v := a.Value.(type) {
   739  	case Var:
   740  		for i, arg := range args {
   741  			if arg.Value.Compare(v) == 0 {
   742  				if bval, ok := indexValue(b); ok {
   743  					return &refindex{Ref: Ref{FunctionArgRootDocument, IntNumberTerm(i)}, Value: bval}, true
   744  				}
   745  			}
   746  		}
   747  	case Ref:
   748  		if !RootDocumentNames.Contains(v[0]) {
   749  			return nil, false
   750  		}
   751  		if isVirtual(v) {
   752  			return nil, false
   753  		}
   754  		if v.IsNested() || !v.IsGround() {
   755  			return nil, false
   756  		}
   757  		if bval, ok := indexValue(b); ok {
   758  			return &refindex{Ref: v, Value: bval}, true
   759  		}
   760  	}
   761  	return nil, false
   762  }
   763  
   764  func indexValue(b *Term) (Value, bool) {
   765  	switch b := b.Value.(type) {
   766  	case Null, Boolean, Number, String, Var:
   767  		return b, true
   768  	case *Array:
   769  		stop := false
   770  		first := true
   771  		vis := NewGenericVisitor(func(x interface{}) bool {
   772  			if first {
   773  				first = false
   774  				return false
   775  			}
   776  			switch x.(type) {
   777  			// No nested structures or values that require evaluation (other than var).
   778  			case *Array, Object, Set, *ArrayComprehension, *ObjectComprehension, *SetComprehension, Ref:
   779  				stop = true
   780  			}
   781  			return stop
   782  		})
   783  		vis.Walk(b)
   784  		if !stop {
   785  			return b, true
   786  		}
   787  	}
   788  
   789  	return nil, false
   790  }
   791  
   792  func globDelimiterToString(delim *Term) (string, bool) {
   793  
   794  	arr, ok := delim.Value.(*Array)
   795  	if !ok {
   796  		return "", false
   797  	}
   798  
   799  	var result string
   800  
   801  	if arr.Len() == 0 {
   802  		result = "."
   803  	} else {
   804  		for i := 0; i < arr.Len(); i++ {
   805  			term := arr.Elem(i)
   806  			s, ok := term.Value.(String)
   807  			if !ok {
   808  				return "", false
   809  			}
   810  			result += string(s)
   811  		}
   812  	}
   813  
   814  	return result, true
   815  }
   816  
   817  func globPatternToArray(pattern *Term, delim string) *Term {
   818  
   819  	s, ok := pattern.Value.(String)
   820  	if !ok {
   821  		return nil
   822  	}
   823  
   824  	parts := splitStringEscaped(string(s), delim)
   825  	arr := make([]*Term, len(parts))
   826  
   827  	for i := range parts {
   828  		if parts[i] == "*" {
   829  			arr[i] = VarTerm("$globwildcard")
   830  		} else {
   831  			var escaped bool
   832  			for _, c := range parts[i] {
   833  				if c == '\\' {
   834  					escaped = !escaped
   835  					continue
   836  				}
   837  				if !escaped {
   838  					switch c {
   839  					case '[', '?', '{', '*':
   840  						// TODO(tsandall): super glob and character pattern
   841  						// matching not supported yet.
   842  						return nil
   843  					}
   844  				}
   845  				escaped = false
   846  			}
   847  			arr[i] = StringTerm(parts[i])
   848  		}
   849  	}
   850  
   851  	return NewTerm(NewArray(arr...))
   852  }
   853  
   854  // splits s on characters in delim except if delim characters have been escaped
   855  // with reverse solidus.
   856  func splitStringEscaped(s string, delim string) []string {
   857  
   858  	var last, curr int
   859  	var escaped bool
   860  	var result []string
   861  
   862  	for ; curr < len(s); curr++ {
   863  		if s[curr] == '\\' || escaped {
   864  			escaped = !escaped
   865  			continue
   866  		}
   867  		if strings.ContainsRune(delim, rune(s[curr])) {
   868  			result = append(result, s[last:curr])
   869  			last = curr + 1
   870  		}
   871  	}
   872  
   873  	result = append(result, s[last:])
   874  
   875  	return result
   876  }
   877  
   878  func stringSliceToArray(s []string) *Array {
   879  	arr := make([]*Term, len(s))
   880  	for i, v := range s {
   881  		arr[i] = StringTerm(v)
   882  	}
   883  	return NewArray(arr...)
   884  }