...

Source file src/cuelang.org/go/internal/core/walk/walk.go

Documentation: cuelang.org/go/internal/core/walk

     1  // Copyright 2020 CUE Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // walk provides functions for visiting the nodes of an ADT tree.
    16  package walk
    17  
    18  import (
    19  	"fmt"
    20  
    21  	"cuelang.org/go/internal/core/adt"
    22  )
    23  
    24  // Features calls f for all features used in x and indicates whether the
    25  // feature is used as a reference or not.
    26  func Features(x adt.Expr, f func(label adt.Feature, src adt.Node)) {
    27  	w := Visitor{
    28  		Feature: f,
    29  	}
    30  	w.Elem(x)
    31  }
    32  
    33  // A Visitor walks over all elements in an ADT, recursively.
    34  type Visitor struct {
    35  	// Feature is invoked for all field names.
    36  	Feature func(f adt.Feature, src adt.Node)
    37  
    38  	// Before is invoked for all invoked for all nodes in pre-order traversal.
    39  	// Return false prevents the visitor from visiting the nodes descendant
    40  	// elements.
    41  	Before func(adt.Node) bool
    42  }
    43  
    44  func (w *Visitor) Elem(x adt.Elem) {
    45  	w.node(x)
    46  }
    47  
    48  func (w *Visitor) feature(x adt.Feature, src adt.Node) {
    49  	if w.Feature != nil {
    50  		w.Feature(x, src)
    51  	}
    52  }
    53  
    54  func (w *Visitor) node(n adt.Node) {
    55  	if w.Before != nil && !w.Before(n) {
    56  		return
    57  	}
    58  
    59  	switch x := n.(type) {
    60  	case nil:
    61  
    62  	// TODO: special-case Vertex?
    63  	case adt.Value:
    64  
    65  	case *adt.ConjunctGroup:
    66  		for _, x := range *x {
    67  			w.Elem(x.Elem())
    68  		}
    69  
    70  	case *adt.ListLit:
    71  		for _, x := range x.Elems {
    72  			w.node(x)
    73  		}
    74  
    75  	case *adt.StructLit:
    76  		for _, x := range x.Decls {
    77  			w.node(x)
    78  		}
    79  
    80  	case *adt.FieldReference:
    81  		w.feature(x.Label, x)
    82  
    83  	case *adt.ValueReference:
    84  		w.feature(x.Label, x)
    85  
    86  	case *adt.LabelReference:
    87  
    88  	case *adt.DynamicReference:
    89  
    90  	case *adt.ImportReference:
    91  		w.feature(x.ImportPath, x)
    92  		w.feature(x.Label, x)
    93  
    94  	case *adt.LetReference:
    95  		w.feature(x.Label, x)
    96  
    97  	case *adt.SelectorExpr:
    98  		w.node(x.X)
    99  		w.feature(x.Sel, x)
   100  
   101  	case *adt.IndexExpr:
   102  		w.node(x.X)
   103  		w.node(x.Index)
   104  
   105  	case *adt.SliceExpr:
   106  		w.node(x.X)
   107  		w.node(x.Lo)
   108  		w.node(x.Hi)
   109  		w.node(x.Stride)
   110  
   111  	case *adt.Interpolation:
   112  		for _, x := range x.Parts {
   113  			w.node(x)
   114  		}
   115  
   116  	case *adt.BoundExpr:
   117  		w.node(x.Expr)
   118  
   119  	case *adt.UnaryExpr:
   120  		w.node(x.X)
   121  
   122  	case *adt.BinaryExpr:
   123  		w.node(x.X)
   124  		w.node(x.Y)
   125  
   126  	case *adt.CallExpr:
   127  		w.node(x.Fun)
   128  		for _, arg := range x.Args {
   129  			w.node(arg)
   130  		}
   131  
   132  	case *adt.DisjunctionExpr:
   133  		for _, d := range x.Values {
   134  			w.node(d.Val)
   135  		}
   136  
   137  	// Fields
   138  
   139  	case *adt.Ellipsis:
   140  		if x.Value != nil {
   141  			w.node(x.Value)
   142  		}
   143  
   144  	case *adt.Field:
   145  		w.feature(x.Label, x)
   146  		w.node(x.Value)
   147  
   148  	case *adt.LetField:
   149  		w.feature(x.Label, x)
   150  		w.node(x.Value)
   151  
   152  	case *adt.BulkOptionalField:
   153  		w.node(x.Filter)
   154  		w.node(x.Value)
   155  
   156  	case *adt.DynamicField:
   157  		w.node(x.Key)
   158  		w.node(x.Value)
   159  
   160  	// Yielders
   161  
   162  	case *adt.Comprehension:
   163  		for _, c := range x.Clauses {
   164  			w.node(c)
   165  		}
   166  		w.node(adt.ToExpr(x.Value))
   167  
   168  	case *adt.ForClause:
   169  		w.feature(x.Key, x)
   170  		w.feature(x.Value, x)
   171  
   172  	case *adt.IfClause:
   173  		w.node(x.Condition)
   174  
   175  	case *adt.LetClause:
   176  		w.feature(x.Label, x)
   177  		w.node(x.Expr)
   178  
   179  	case *adt.ValueClause:
   180  
   181  	default:
   182  		panic(fmt.Sprintf("unknown field %T", x))
   183  	}
   184  }
   185  

View as plain text