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