cuelang.org/go@v0.13.0/internal/core/debug/compact.go (about)

     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  // Package debug prints a given ADT node.
    16  //
    17  // Note that the result is not valid CUE, but instead prints the internals
    18  // of an ADT node in human-readable form. It uses a simple indentation algorithm
    19  // for improved readability and diffing.
    20  package debug
    21  
    22  import (
    23  	"fmt"
    24  	"strconv"
    25  
    26  	"cuelang.org/go/cue/literal"
    27  	"cuelang.org/go/internal/core/adt"
    28  )
    29  
    30  type compactPrinter struct {
    31  	printer
    32  }
    33  
    34  func (w *compactPrinter) string(s string) {
    35  	w.dst = append(w.dst, s...)
    36  }
    37  
    38  func (w *compactPrinter) node(n adt.Node) {
    39  	switch x := n.(type) {
    40  	case *adt.Vertex:
    41  		if x.BaseValue == nil || (w.cfg.Raw && !x.IsData()) {
    42  			i := 0
    43  			x.VisitLeafConjuncts(func(c adt.Conjunct) bool {
    44  				if i > 0 {
    45  					w.string(" & ")
    46  				}
    47  				i++
    48  				w.node(c.Elem())
    49  				return true
    50  			})
    51  			return
    52  		}
    53  
    54  		switch v := x.BaseValue.(type) {
    55  		case *adt.StructMarker:
    56  			w.string("{")
    57  			for i, a := range x.Arcs {
    58  				if i > 0 {
    59  					w.string(",")
    60  				}
    61  				if a.Label.IsLet() {
    62  					w.string("let ")
    63  					w.label(a.Label)
    64  					if a.MultiLet {
    65  						w.string("m")
    66  					}
    67  					w.string("=")
    68  					if c := a.ConjunctAt(0); a.MultiLet {
    69  						w.node(c.Expr())
    70  						continue
    71  					}
    72  					w.node(a)
    73  				} else {
    74  					w.label(a.Label)
    75  					w.string(a.ArcType.Suffix())
    76  					w.string(":")
    77  					w.node(a)
    78  				}
    79  			}
    80  			w.string("}")
    81  
    82  		case *adt.ListMarker:
    83  			w.string("[")
    84  			for i, a := range x.Arcs {
    85  				if i > 0 {
    86  					w.string(",")
    87  				}
    88  				w.node(a)
    89  			}
    90  			w.string("]")
    91  
    92  		case *adt.Vertex:
    93  			if v, ok := w.printShared(x); !ok {
    94  				w.node(v)
    95  				w.popVertex()
    96  			}
    97  
    98  		case adt.Value:
    99  			w.node(v)
   100  		}
   101  
   102  	case *adt.StructMarker:
   103  		w.string("struct")
   104  
   105  	case *adt.ListMarker:
   106  		w.string("list")
   107  
   108  	case *adt.StructLit:
   109  		w.string("{")
   110  		for i, d := range x.Decls {
   111  			if i > 0 {
   112  				w.string(",")
   113  			}
   114  			w.node(d)
   115  		}
   116  		w.string("}")
   117  
   118  	case *adt.ListLit:
   119  		w.string("[")
   120  		for i, d := range x.Elems {
   121  			if i > 0 {
   122  				w.string(",")
   123  			}
   124  			w.node(d)
   125  		}
   126  		w.string("]")
   127  
   128  	case *adt.Field:
   129  		w.label(x.Label)
   130  		w.string(x.ArcType.Suffix())
   131  		w.string(":")
   132  		w.node(x.Value)
   133  
   134  	case *adt.LetField:
   135  		w.string("let ")
   136  		w.label(x.Label)
   137  		if x.IsMulti {
   138  			w.string("m")
   139  		}
   140  		w.string("=")
   141  		w.node(x.Value)
   142  
   143  	case *adt.BulkOptionalField:
   144  		w.string("[")
   145  		w.node(x.Filter)
   146  		w.string("]:")
   147  		w.node(x.Value)
   148  
   149  	case *adt.DynamicField:
   150  		w.node(x.Key)
   151  		w.string(x.ArcType.Suffix())
   152  		w.string(":")
   153  		w.node(x.Value)
   154  
   155  	case *adt.Ellipsis:
   156  		w.string("...")
   157  		if x.Value != nil {
   158  			w.node(x.Value)
   159  		}
   160  
   161  	case *adt.Bottom:
   162  		w.string(`_|_`)
   163  		if x.Err != nil {
   164  			w.string("(")
   165  			w.string(x.Err.Error())
   166  			w.string(")")
   167  		}
   168  
   169  	case *adt.Null:
   170  		w.string("null")
   171  
   172  	case *adt.Bool:
   173  		w.dst = strconv.AppendBool(w.dst, x.B)
   174  
   175  	case *adt.Num:
   176  		w.string(x.X.String())
   177  
   178  	case *adt.String:
   179  		w.dst = literal.String.Append(w.dst, x.Str)
   180  
   181  	case *adt.Bytes:
   182  		w.dst = literal.Bytes.Append(w.dst, string(x.B))
   183  
   184  	case *adt.Top:
   185  		w.string("_")
   186  
   187  	case *adt.BasicType:
   188  		w.string(x.K.String())
   189  
   190  	case *adt.BoundExpr:
   191  		w.string(x.Op.String())
   192  		w.node(x.Expr)
   193  
   194  	case *adt.BoundValue:
   195  		w.string(x.Op.String())
   196  		w.node(x.Value)
   197  
   198  	case *adt.NodeLink:
   199  		w.string(openTuple)
   200  		for i, f := range x.Node.Path() {
   201  			if i > 0 {
   202  				w.string(".")
   203  			}
   204  			w.label(f)
   205  		}
   206  		w.string(closeTuple)
   207  
   208  	case *adt.FieldReference:
   209  		w.label(x.Label)
   210  
   211  	case *adt.ValueReference:
   212  		w.label(x.Label)
   213  
   214  	case *adt.LabelReference:
   215  		if x.Src == nil {
   216  			w.string("LABEL")
   217  		} else {
   218  			w.string(x.Src.Name)
   219  		}
   220  
   221  	case *adt.DynamicReference:
   222  		w.node(x.Label)
   223  
   224  	case *adt.ImportReference:
   225  		w.label(x.ImportPath)
   226  
   227  	case *adt.LetReference:
   228  		w.ident(x.Label)
   229  
   230  	case *adt.SelectorExpr:
   231  		w.node(x.X)
   232  		w.string(".")
   233  		w.label(x.Sel)
   234  
   235  	case *adt.IndexExpr:
   236  		w.node(x.X)
   237  		w.string("[")
   238  		w.node(x.Index)
   239  		w.string("]")
   240  
   241  	case *adt.SliceExpr:
   242  		w.node(x.X)
   243  		w.string("[")
   244  		if x.Lo != nil {
   245  			w.node(x.Lo)
   246  		}
   247  		w.string(":")
   248  		if x.Hi != nil {
   249  			w.node(x.Hi)
   250  		}
   251  		if x.Stride != nil {
   252  			w.string(":")
   253  			w.node(x.Stride)
   254  		}
   255  		w.string("]")
   256  
   257  	case *adt.Interpolation:
   258  		w.interpolation(x)
   259  
   260  	case *adt.UnaryExpr:
   261  		w.string(x.Op.String())
   262  		w.node(x.X)
   263  
   264  	case *adt.BinaryExpr:
   265  		w.string("(")
   266  		w.node(x.X)
   267  		w.string(" ")
   268  		w.string(x.Op.String())
   269  		w.string(" ")
   270  		w.node(x.Y)
   271  		w.string(")")
   272  
   273  	case *adt.CallExpr:
   274  		w.node(x.Fun)
   275  		w.string("(")
   276  		for i, a := range x.Args {
   277  			if i > 0 {
   278  				w.string(", ")
   279  			}
   280  			w.arg(a)
   281  		}
   282  		w.string(")")
   283  
   284  	case *adt.Builtin:
   285  		if x.Package != 0 {
   286  			w.label(x.Package)
   287  			w.string(".")
   288  		}
   289  		w.string(x.Name)
   290  
   291  	case *adt.BuiltinValidator:
   292  		w.node(x.Builtin)
   293  		w.string("(")
   294  		for i, a := range x.Args {
   295  			if i > 0 {
   296  				w.string(", ")
   297  			}
   298  			w.arg(a)
   299  		}
   300  		w.string(")")
   301  
   302  	case *adt.DisjunctionExpr:
   303  		w.string("(")
   304  		for i, a := range x.Values {
   305  			if i > 0 {
   306  				w.string("|")
   307  			}
   308  			// Disjunct
   309  			if a.Default {
   310  				w.string("*")
   311  			}
   312  			w.node(a.Val)
   313  		}
   314  		w.string(")")
   315  
   316  	case *adt.Conjunction:
   317  		for i, c := range x.Values {
   318  			if i > 0 {
   319  				w.string(" & ")
   320  			}
   321  			w.node(c)
   322  		}
   323  
   324  	case *adt.ConjunctGroup:
   325  		for i, c := range *x {
   326  			if i > 0 {
   327  				w.string(" & ")
   328  			}
   329  			w.node(c.Expr())
   330  		}
   331  
   332  	case *adt.Disjunction:
   333  		for i, c := range x.Values {
   334  			if i > 0 {
   335  				w.string(" | ")
   336  			}
   337  			if i < x.NumDefaults {
   338  				w.string("*")
   339  			}
   340  			w.node(c)
   341  		}
   342  
   343  	case *adt.Comprehension:
   344  		for _, c := range x.Clauses {
   345  			w.node(c)
   346  		}
   347  		w.node(adt.ToExpr(x.Value))
   348  
   349  	case *adt.ForClause:
   350  		w.string("for ")
   351  		w.ident(x.Key)
   352  		w.string(", ")
   353  		w.ident(x.Value)
   354  		w.string(" in ")
   355  		w.node(x.Src)
   356  		w.string(" ")
   357  
   358  	case *adt.IfClause:
   359  		w.string("if ")
   360  		w.node(x.Condition)
   361  		w.string(" ")
   362  
   363  	case *adt.LetClause:
   364  		w.string("let ")
   365  		w.ident(x.Label)
   366  		w.string(" = ")
   367  		w.node(x.Expr)
   368  		w.string(" ")
   369  
   370  	case *adt.ValueClause:
   371  
   372  	default:
   373  		panic(fmt.Sprintf("unknown type %T", x))
   374  	}
   375  }