...

Source file src/cuelang.org/go/internal/core/export/expr.go

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

     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 export
    16  
    17  import (
    18  	"fmt"
    19  	"sort"
    20  
    21  	"cuelang.org/go/cue/ast"
    22  	"cuelang.org/go/cue/token"
    23  	"cuelang.org/go/internal"
    24  	"cuelang.org/go/internal/core/adt"
    25  )
    26  
    27  // Modes:
    28  //   raw: as is
    29  //   def: merge structs, print reset as is.
    30  //
    31  // Possible simplifications in def mode:
    32  //    - merge contents of multiple _literal_ structs.
    33  //      - this is not possible if some of the elements are bulk optional
    34  //        (or is it?).
    35  //    - still do not ever resolve references.
    36  //    - to do this, fields must be pre-linked to their destinations.
    37  //    - use astutil.Sanitize to resolve shadowing and imports.
    38  //
    39  //
    40  // Categories of printing:
    41  //   - concrete
    42  //   - optionals
    43  //   - references
    44  //   - constraints
    45  //
    46  // Mixed mode is also not supported in the old implementation (at least not
    47  // correctly). It requires references to resolve properly, backtracking to
    48  // a common root and prefixing that to the reference. This is now possible
    49  // with the Environment construct and could be done later.
    50  
    51  var empty *adt.Vertex
    52  
    53  func init() {
    54  	// TODO: Consider setting a non-nil BaseValue.
    55  	empty = &adt.Vertex{}
    56  	empty.ForceDone()
    57  }
    58  
    59  // innerExpr is like expr, but prohibits inlining in certain cases.
    60  func (e *exporter) innerExpr(env *adt.Environment, v adt.Elem) (result ast.Expr) {
    61  	e.inExpression++
    62  	r := e.expr(env, v)
    63  	e.inExpression--
    64  	return r
    65  }
    66  
    67  // expr converts an ADT expression to an AST expression.
    68  // The env is used for resolution and does not need to be given if v is known
    69  // to not contain any references.
    70  func (e *exporter) expr(env *adt.Environment, v adt.Elem) (result ast.Expr) {
    71  	switch x := v.(type) {
    72  	case nil:
    73  		return nil
    74  
    75  	case *adt.Vertex:
    76  		if len(x.Conjuncts) == 0 || x.IsData() {
    77  			// Treat as literal value.
    78  			return e.value(x)
    79  		} // Should this be the arcs label?
    80  
    81  		a := []conjunct{}
    82  		for _, c := range x.Conjuncts {
    83  			if c, ok := c.Elem().(*adt.Comprehension); ok && !c.DidResolve() {
    84  				continue
    85  			}
    86  			a = append(a, conjunct{c, 0})
    87  		}
    88  
    89  		return e.mergeValues(adt.InvalidLabel, x, a, x.Conjuncts...)
    90  
    91  	case *adt.StructLit:
    92  		c := adt.MakeRootConjunct(env, x)
    93  		return e.mergeValues(adt.InvalidLabel, nil, []conjunct{{c: c, up: 0}}, c)
    94  
    95  	case adt.Value:
    96  		return e.value(x) // Use conjuncts.
    97  
    98  	default:
    99  		return e.adt(env, v)
   100  	}
   101  }
   102  
   103  // Piece out values:
   104  
   105  // For a struct, piece out conjuncts that are already values. Those can be
   106  // unified. All other conjuncts are added verbatim.
   107  
   108  func (x *exporter) mergeValues(label adt.Feature, src *adt.Vertex, a []conjunct, orig ...adt.Conjunct) (expr ast.Expr) {
   109  
   110  	e := conjuncts{
   111  		exporter: x,
   112  		values:   &adt.Vertex{},
   113  		fields:   map[adt.Feature]field{},
   114  		attrs:    []*ast.Attribute{},
   115  	}
   116  
   117  	s, saved := e.pushFrame(src, orig)
   118  	defer e.popFrame(saved)
   119  
   120  	// Handle value aliases and lets
   121  	var valueAlias *ast.Alias
   122  	for _, c := range a {
   123  		if f, ok := c.c.Field().Source().(*ast.Field); ok {
   124  			if a, ok := f.Value.(*ast.Alias); ok {
   125  				if valueAlias == nil {
   126  					if e.valueAlias == nil {
   127  						e.valueAlias = map[*ast.Alias]*ast.Alias{}
   128  					}
   129  					name := a.Ident.Name
   130  					name = e.uniqueAlias(name)
   131  					valueAlias = &ast.Alias{Ident: ast.NewIdent(name)}
   132  				}
   133  				e.valueAlias[a] = valueAlias
   134  			}
   135  		}
   136  		x.markLets(c.c.Expr().Source(), s)
   137  	}
   138  
   139  	defer filterUnusedLets(s)
   140  
   141  	defer func() {
   142  		if valueAlias != nil {
   143  			valueAlias.Expr = expr
   144  			expr = valueAlias
   145  		}
   146  	}()
   147  
   148  	hasAlias := len(s.Elts) > 0
   149  
   150  	for _, c := range a {
   151  		e.top().upCount = c.up
   152  		x := c.c.Elem()
   153  		e.addExpr(c.c.Env, src, x, false)
   154  	}
   155  
   156  	if src != nil {
   157  		for _, a := range src.Arcs {
   158  			if x, ok := e.fields[a.Label]; ok {
   159  				x.arc = a
   160  				x.arcType = a.ArcType
   161  				e.fields[a.Label] = x
   162  			}
   163  		}
   164  	}
   165  
   166  	for _, a := range e.attrs {
   167  		s.Elts = append(s.Elts, a)
   168  	}
   169  
   170  	// Unify values only for one level.
   171  	if a := e.values.Conjuncts; len(a) > 0 {
   172  		e.values.Finalize(e.ctx)
   173  		e.embed = append(e.embed, e.value(e.values, a...))
   174  	}
   175  
   176  	// Collect and order set of fields.
   177  
   178  	fields := []adt.Feature{}
   179  	for f := range e.fields {
   180  		fields = append(fields, f)
   181  	}
   182  
   183  	// Sort fields in case features lists are missing to ensure
   184  	// predictability. Also sort in reverse order, so that bugs
   185  	// are more likely exposed.
   186  	sort.Slice(fields, func(i, j int) bool {
   187  		return fields[i] > fields[j]
   188  	})
   189  
   190  	if adt.DebugSort == 0 {
   191  		m := sortArcs(extractFeatures(e.structs))
   192  		sort.SliceStable(fields, func(i, j int) bool {
   193  			if m[fields[j]] == 0 {
   194  				return m[fields[i]] != 0
   195  			}
   196  			return m[fields[i]] > m[fields[j]]
   197  		})
   198  	} else {
   199  		adt.DebugSortFields(e.ctx, fields)
   200  	}
   201  
   202  	if len(e.fields) == 0 && !e.hasEllipsis {
   203  		switch len(e.embed) + len(e.conjuncts) {
   204  		case 0:
   205  			if len(e.attrs) > 0 {
   206  				break
   207  			}
   208  			if len(e.structs) > 0 || e.isData {
   209  				return e.wrapCloseIfNecessary(s, src)
   210  			}
   211  			return ast.NewIdent("_")
   212  		case 1:
   213  			var x ast.Expr
   214  			if len(e.conjuncts) == 1 {
   215  				x = e.conjuncts[0]
   216  			} else {
   217  				x = e.embed[0]
   218  			}
   219  			if len(e.attrs) == 0 && !hasAlias {
   220  				return x
   221  			}
   222  			if st, ok := x.(*ast.StructLit); ok {
   223  				s.Elts = append(s.Elts, st.Elts...)
   224  				return e.wrapCloseIfNecessary(s, src)
   225  			}
   226  		}
   227  	}
   228  
   229  	for _, x := range e.embed {
   230  		s.Elts = append(s.Elts, &ast.EmbedDecl{Expr: x})
   231  	}
   232  
   233  	for _, f := range fields {
   234  		if f.IsLet() {
   235  			continue
   236  		}
   237  		field := e.getField(f)
   238  		c := field.conjuncts
   239  
   240  		label := e.stringLabel(f)
   241  
   242  		if f.IsDef() {
   243  			x.inDefinition++
   244  		}
   245  
   246  		a := []adt.Conjunct{}
   247  		for _, cc := range c {
   248  			a = append(a, cc.c)
   249  		}
   250  
   251  		d := &ast.Field{Label: label}
   252  
   253  		top := e.frame(0)
   254  		if fr, ok := top.fields[f]; ok && fr.alias != "" {
   255  			setFieldAlias(d, fr.alias)
   256  			fr.node = d
   257  			top.fields[f] = fr
   258  		}
   259  
   260  		d.Value = e.mergeValues(f, field.arc, c, a...)
   261  
   262  		e.linkField(field.arc, d)
   263  
   264  		if f.IsDef() {
   265  			x.inDefinition--
   266  		}
   267  
   268  		internal.SetConstraint(d, field.arcType.Token())
   269  		if x.cfg.ShowDocs {
   270  			docs := extractDocs(src, a)
   271  			ast.SetComments(d, docs)
   272  		}
   273  		if x.cfg.ShowAttributes {
   274  			for _, c := range a {
   275  				d.Attrs = extractFieldAttrs(d.Attrs, c.Field())
   276  			}
   277  		}
   278  		s.Elts = append(s.Elts, d)
   279  	}
   280  	if e.hasEllipsis {
   281  		s.Elts = append(s.Elts, &ast.Ellipsis{})
   282  	}
   283  
   284  	ws := e.wrapCloseIfNecessary(s, src)
   285  	switch {
   286  	case len(e.conjuncts) == 0:
   287  		return ws
   288  
   289  	case len(e.structs) > 0, len(s.Elts) > 0:
   290  		e.conjuncts = append(e.conjuncts, ws)
   291  	}
   292  
   293  	return ast.NewBinExpr(token.AND, e.conjuncts...)
   294  }
   295  
   296  func (e *conjuncts) wrapCloseIfNecessary(s *ast.StructLit, v *adt.Vertex) ast.Expr {
   297  	if !e.hasEllipsis && v != nil {
   298  		if st, ok := v.BaseValue.(*adt.StructMarker); ok && st.NeedClose {
   299  			return ast.NewCall(ast.NewIdent("close"), s)
   300  		}
   301  	}
   302  	return s
   303  }
   304  
   305  // Conjuncts if for collecting values of a single vertex.
   306  type conjuncts struct {
   307  	*exporter
   308  	// Values is used to collect non-struct values.
   309  	values      *adt.Vertex
   310  	embed       []ast.Expr
   311  	conjuncts   []ast.Expr
   312  	structs     []*adt.StructInfo
   313  	fields      map[adt.Feature]field
   314  	attrs       []*ast.Attribute
   315  	hasEllipsis bool
   316  
   317  	// A value is a struct if it has a non-zero structs slice or if isData is
   318  	// set to true. Data vertices may not have conjuncts associated with them.
   319  	isData bool
   320  }
   321  
   322  func (c *conjuncts) getField(label adt.Feature) field {
   323  	f, ok := c.fields[label]
   324  	if !ok {
   325  		f.arcType = adt.ArcNotPresent
   326  	}
   327  	return f
   328  }
   329  
   330  func (c *conjuncts) addValueConjunct(src *adt.Vertex, env *adt.Environment, x adt.Elem) {
   331  	switch b, ok := x.(adt.BaseValue); {
   332  	case ok && src != nil && isTop(b) && !isTop(src.BaseValue):
   333  		// drop top
   334  	default:
   335  		c.values.AddConjunct(adt.MakeRootConjunct(env, x))
   336  	}
   337  }
   338  
   339  func (c *conjuncts) addConjunct(f adt.Feature, t adt.ArcType, env *adt.Environment, n adt.Node) {
   340  	x := c.getField(f)
   341  	if t < x.arcType {
   342  		x.arcType = t
   343  	}
   344  
   345  	v := adt.MakeRootConjunct(env, n)
   346  	x.conjuncts = append(x.conjuncts, conjunct{
   347  		c:  v,
   348  		up: c.top().upCount,
   349  	})
   350  	// x.upCounts = append(x.upCounts, c.top().upCount)
   351  	c.fields[f] = x
   352  }
   353  
   354  type field struct {
   355  	arcType   adt.ArcType
   356  	arc       *adt.Vertex
   357  	conjuncts []conjunct
   358  }
   359  
   360  type conjunct struct {
   361  	c  adt.Conjunct
   362  	up int32
   363  }
   364  
   365  func (e *conjuncts) addExpr(env *adt.Environment, src *adt.Vertex, x adt.Elem, isEmbed bool) {
   366  	switch x := x.(type) {
   367  	case *adt.StructLit:
   368  		e.top().upCount++
   369  
   370  		if e.cfg.ShowAttributes {
   371  			e.attrs = extractDeclAttrs(e.attrs, x.Src)
   372  		}
   373  
   374  		// Only add if it only has no bulk fields or ellipsis.
   375  		if isComplexStruct(x) {
   376  			_, saved := e.pushFrame(src, nil)
   377  			e.embed = append(e.embed, e.adt(env, x))
   378  			e.top().upCount-- // not necessary, but for proper form
   379  			e.popFrame(saved)
   380  			return
   381  		}
   382  		// Used for sorting.
   383  		e.structs = append(e.structs, &adt.StructInfo{StructLit: x, Env: env})
   384  
   385  		env = &adt.Environment{Up: env, Vertex: e.node()}
   386  
   387  		for _, d := range x.Decls {
   388  			var label adt.Feature
   389  			t := adt.ArcNotPresent
   390  			switch f := d.(type) {
   391  			case *adt.Field:
   392  				label = f.Label
   393  				t = f.ArcType
   394  				// TODO: mark optional here, if needed.
   395  			case *adt.LetField:
   396  				continue
   397  			case *adt.Ellipsis:
   398  				e.hasEllipsis = true
   399  				continue
   400  			case adt.Expr:
   401  				e.addExpr(env, nil, f, true)
   402  				continue
   403  
   404  				// TODO: also handle dynamic fields
   405  			default:
   406  				panic(fmt.Sprintf("Unexpected type %T", d))
   407  			}
   408  			e.addConjunct(label, t, env, d)
   409  		}
   410  		e.top().upCount--
   411  
   412  	case adt.Value: // other values.
   413  		switch v := x.(type) {
   414  		case nil:
   415  		default:
   416  			e.addValueConjunct(src, env, x)
   417  
   418  		case *adt.Vertex:
   419  			if b, ok := v.BaseValue.(*adt.Bottom); ok {
   420  				if !b.IsIncomplete() || e.cfg.Final {
   421  					e.addExpr(env, v, b, false)
   422  					return
   423  				}
   424  			}
   425  
   426  			switch {
   427  			default:
   428  				for _, c := range v.Conjuncts {
   429  					e.addExpr(c.Env, v, c.Elem(), false)
   430  				}
   431  
   432  			case v.IsData():
   433  				e.structs = append(e.structs, v.Structs...)
   434  				e.isData = true
   435  
   436  				if y, ok := v.BaseValue.(adt.Value); ok {
   437  					e.addValueConjunct(src, env, y)
   438  				}
   439  
   440  				for _, a := range v.Arcs {
   441  					a.Finalize(e.ctx) // TODO: should we do this?
   442  
   443  					if !a.IsDefined(e.ctx) {
   444  						continue
   445  					}
   446  
   447  					e.addConjunct(a.Label, a.ArcType, env, a)
   448  				}
   449  			}
   450  		}
   451  
   452  	case *adt.BinaryExpr:
   453  		switch {
   454  		case x.Op == adt.AndOp && !isEmbed:
   455  			e.addExpr(env, src, x.X, false)
   456  			e.addExpr(env, src, x.Y, false)
   457  		case isSelfContained(x):
   458  			e.addValueConjunct(src, env, x)
   459  		default:
   460  			if isEmbed {
   461  				e.embed = append(e.embed, e.expr(env, x))
   462  			} else {
   463  				e.conjuncts = append(e.conjuncts, e.expr(env, x))
   464  			}
   465  		}
   466  
   467  	default:
   468  		switch {
   469  		case isSelfContained(x):
   470  			e.addValueConjunct(src, env, x)
   471  		case isEmbed:
   472  			e.embed = append(e.embed, e.expr(env, x))
   473  		default:
   474  			if x := e.expr(env, x); x != dummyTop {
   475  				e.conjuncts = append(e.conjuncts, x)
   476  			}
   477  		}
   478  	}
   479  }
   480  
   481  func isTop(x adt.BaseValue) bool {
   482  	switch v := x.(type) {
   483  	case *adt.Top:
   484  		return true
   485  	case *adt.BasicType:
   486  		return v.K == adt.TopKind
   487  	default:
   488  		return false
   489  	}
   490  }
   491  
   492  func isComplexStruct(s *adt.StructLit) bool {
   493  	for _, d := range s.Decls {
   494  		switch x := d.(type) {
   495  		case *adt.Field:
   496  			// TODO: remove this and also handle field annotation in expr().
   497  			// This allows structs to be merged. Ditto below.
   498  			if x.Src != nil {
   499  				if _, ok := x.Src.Label.(*ast.Alias); ok {
   500  					return ok
   501  				}
   502  			}
   503  
   504  		case *adt.LetField:
   505  
   506  		case adt.Expr:
   507  
   508  		case *adt.Ellipsis:
   509  			if x.Value != nil {
   510  				return true
   511  			}
   512  
   513  		default:
   514  			return true
   515  		}
   516  	}
   517  	return false
   518  }
   519  
   520  func isSelfContained(expr adt.Elem) bool {
   521  	switch x := expr.(type) {
   522  	case *adt.BinaryExpr:
   523  		return isSelfContained(x.X) && isSelfContained(x.Y)
   524  	case *adt.UnaryExpr:
   525  		return isSelfContained(x.X)
   526  	case *adt.BoundExpr:
   527  		return isSelfContained(x.Expr)
   528  	case adt.Value:
   529  		return true
   530  	}
   531  	return false
   532  }
   533  

View as plain text