Source file src/cmd/compile/internal/midway/deepcopy.go

     1  // Copyright 2026 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package midway
     6  
     7  import (
     8  	"fmt"
     9  	"strings"
    10  
    11  	"cmd/compile/internal/syntax"
    12  	"cmd/compile/internal/types2"
    13  )
    14  
    15  // DeepCopier clones syntax nodes and maintains types2.Info mappings.
    16  type DeepCopier struct {
    17  	VecLen   int
    18  	info     *types2.Info
    19  	pkg      *types2.Package
    20  	analyzer *Analyzer
    21  	suffix   string
    22  
    23  	vars map[*types2.Var]*types2.Var
    24  }
    25  
    26  func NewDeepCopier(pkg *types2.Package, info *types2.Info, vecLen int, analyzer *Analyzer, suffix string) *DeepCopier {
    27  	return &DeepCopier{
    28  		VecLen:   vecLen,
    29  		info:     info,
    30  		pkg:      pkg,
    31  		analyzer: analyzer,
    32  		suffix:   suffix,
    33  		vars:     make(map[*types2.Var]*types2.Var),
    34  	}
    35  }
    36  
    37  func (c *DeepCopier) registerDef(newName *syntax.Name, oldName *syntax.Name) {
    38  	if oldName == nil || newName == nil {
    39  		return
    40  	}
    41  	if oldObj := c.info.Defs[oldName]; oldObj != nil {
    42  		if val, isVar := oldObj.(*types2.Var); isVar {
    43  			newObj := types2.NewVar(newName.Pos(), c.pkg, newName.Value, val.Type())
    44  			c.vars[val] = newObj
    45  			c.info.Defs[newName] = newObj
    46  		} else {
    47  			c.info.Defs[newName] = oldObj
    48  		}
    49  	}
    50  }
    51  
    52  func (c *DeepCopier) mapUse(newName *syntax.Name, oldName *syntax.Name) {
    53  	if oldName == nil || newName == nil {
    54  		return
    55  	}
    56  	if oldObj := c.info.Uses[oldName]; oldObj != nil {
    57  		if val, isVar := oldObj.(*types2.Var); isVar && c.vars[val] != nil {
    58  			c.info.Uses[newName] = c.vars[val]
    59  		} else {
    60  			c.info.Uses[newName] = oldObj
    61  		}
    62  	}
    63  }
    64  
    65  // OnName rewrites "dependent" and SIMD names to their architecture-specific version.
    66  func (c *DeepCopier) OnName(id *syntax.Name) *syntax.Name {
    67  	obj := c.info.Uses[id]
    68  	if obj == nil {
    69  		obj = c.info.Defs[id]
    70  	}
    71  	if obj == nil {
    72  		return nil
    73  	}
    74  
    75  	if c.analyzer.dependentObj[obj] || isBaseSimdTypeObj(obj) {
    76  		newId := syntax.NewName(id.Pos(), id.Value+c.suffix)
    77  		// Object link will be handled manually in deepcopier Use/Def mapper
    78  		return newId
    79  	}
    80  	return nil
    81  }
    82  
    83  // OnNameExpr rewrites references to simd.<simd type> into
    84  // <bridge package>.<size-dependent-type>.
    85  func (c *DeepCopier) OnNameExpr(id *syntax.Name) syntax.Expr {
    86  	obj := c.info.Uses[id]
    87  	if obj == nil {
    88  		obj = c.info.Defs[id]
    89  	}
    90  	if obj == nil {
    91  		return nil
    92  	}
    93  
    94  	if isBaseSimdTypeObj(obj) {
    95  		// if it is a name, that means that this is in the simd package,
    96  		// and the name must be replaced with a selector referencing
    97  		// the architecture-dependent packages..
    98  		name := id.Value
    99  		width := nameToElemBitWidth(name)
   100  		if width > 0 {
   101  			archsimdId := syntax.NewName(id.Pos(), archPkg)
   102  			if c.VecLen == 0 {
   103  				// special case for emulation
   104  				newSel := &syntax.SelectorExpr{
   105  					X:   archsimdId,
   106  					Sel: id, // name is unchanged for emulation
   107  				}
   108  				newSel.SetPos(id.Pos())
   109  				return newSel
   110  			}
   111  
   112  			count := c.VecLen / width
   113  			base := name[:len(name)-1]
   114  			newName := fmt.Sprintf("%sx%d", base, count)
   115  			newSelId := syntax.NewName(id.Pos(), newName)
   116  			newSel := &syntax.SelectorExpr{
   117  				X:   archsimdId,
   118  				Sel: newSelId,
   119  			}
   120  			newSel.SetPos(id.Pos())
   121  			return newSel
   122  		}
   123  	}
   124  
   125  	if c.analyzer.dependentObj[obj] {
   126  		newId := syntax.NewName(id.Pos(), id.Value+c.suffix)
   127  		// Object link will be handled manually in deepcopier Use/Def mapper
   128  		return newId
   129  	}
   130  	return nil
   131  }
   132  
   133  // OnSelector is looking for simd.Something, to be rewritten into
   134  // appropriately.  Note that this will not work properly within the simd
   135  // package because there is no "simd." selection there.
   136  func (c *DeepCopier) OnSelector(se *syntax.SelectorExpr) syntax.Expr {
   137  	if x, ok := se.X.(*syntax.Name); ok {
   138  		obj := c.info.Uses[x]
   139  		if pkgName, isPkg := obj.(*types2.PkgName); isPkg && pkgName.Imported().Path() == simdPkg {
   140  			// This first little bit detects name = Load-Type-Width-s-{,Part}
   141  			// and converts the name to Type-Width-s (for nameToWidth), sets isLoad,
   142  			// and initializes the suffix appropriately.
   143  			prefix := ""
   144  			nameSuffix := ""
   145  			name := se.Sel.Value
   146  			end := len(name)
   147  			if strings.HasPrefix(name, "Load") {
   148  				prefix = "Load"
   149  				if strings.HasSuffix(name, "Part") {
   150  					end = strings.Index(name, "Part")
   151  					nameSuffix = "Part"
   152  				}
   153  				name = name[len("Load"):end]
   154  			}
   155  			if strings.HasPrefix(name, "Broadcast") {
   156  				prefix = "Broadcast"
   157  				name = name[len("Broadcast"):end]
   158  			}
   159  
   160  			width := nameToElemBitWidth(name)
   161  			if width > 0 {
   162  				archsimdId := syntax.NewName(se.Pos(), archPkg)
   163  				if c.VecLen == 0 {
   164  					// emulated instead, name is unchanged
   165  					newSel := &syntax.SelectorExpr{
   166  						X:   archsimdId,
   167  						Sel: se.Sel,
   168  					}
   169  					newSel.SetPos(se.Pos())
   170  					return newSel
   171  				}
   172  
   173  				count := c.VecLen / width
   174  				base := name[:len(name)-1]
   175  				newName := fmt.Sprintf("%sx%d", base, count)
   176  				newName = prefix + newName + nameSuffix
   177  
   178  				newSelId := syntax.NewName(se.Sel.Pos(), newName)
   179  
   180  				newSel := &syntax.SelectorExpr{
   181  					X:   archsimdId,
   182  					Sel: newSelId,
   183  				}
   184  				newSel.SetPos(se.Pos())
   185  				return newSel
   186  			}
   187  		}
   188  	}
   189  	return nil
   190  }
   191  
   192  func (c *DeepCopier) CopyDecl(d syntax.Decl) syntax.Decl {
   193  	if d == nil {
   194  		return nil
   195  	}
   196  	switch d := d.(type) {
   197  	case *syntax.FuncDecl:
   198  		return c.CopyFuncDecl(d)
   199  	case *syntax.VarDecl:
   200  		return c.CopyVarDecl(d)
   201  	case *syntax.TypeDecl:
   202  		return c.CopyTypeDecl(d)
   203  	case *syntax.ConstDecl:
   204  		return c.CopyConstDecl(d)
   205  	case *syntax.ImportDecl:
   206  		newD := &syntax.ImportDecl{
   207  			Group:        d.Group,
   208  			Pragma:       d.Pragma,
   209  			LocalPkgName: c.CopyName(d.LocalPkgName, false),
   210  			Path:         c.CopyExpr(d.Path).(*syntax.BasicLit),
   211  		}
   212  		newD.SetPos(d.Pos())
   213  		return newD
   214  	default:
   215  		return d
   216  	}
   217  }
   218  
   219  func (c *DeepCopier) CopyVarDecl(d *syntax.VarDecl) *syntax.VarDecl {
   220  	newD := &syntax.VarDecl{
   221  		Group:  d.Group,
   222  		Pragma: d.Pragma,
   223  		Type:   c.CopyExpr(d.Type),
   224  		Values: c.CopyExpr(d.Values),
   225  	}
   226  	newD.SetPos(d.Pos())
   227  	for _, n := range d.NameList {
   228  		newN := c.CopyName(n, true)
   229  		newD.NameList = append(newD.NameList, newN)
   230  	}
   231  	return newD
   232  }
   233  
   234  func (c *DeepCopier) CopyTypeDecl(d *syntax.TypeDecl) *syntax.TypeDecl {
   235  	newD := &syntax.TypeDecl{
   236  		Group:      d.Group,
   237  		Pragma:     d.Pragma,
   238  		Name:       c.CopyName(d.Name, true),
   239  		TParamList: c.CopyFieldList(d.TParamList),
   240  		Alias:      d.Alias,
   241  		Type:       c.CopyExpr(d.Type),
   242  	}
   243  	newD.SetPos(d.Pos())
   244  	return newD
   245  }
   246  
   247  func (c *DeepCopier) CopyConstDecl(d *syntax.ConstDecl) *syntax.ConstDecl {
   248  	newD := &syntax.ConstDecl{
   249  		Group:  d.Group,
   250  		Pragma: d.Pragma,
   251  		Type:   c.CopyExpr(d.Type),
   252  		Values: c.CopyExpr(d.Values),
   253  	}
   254  	newD.SetPos(d.Pos())
   255  	for _, n := range d.NameList {
   256  		newD.NameList = append(newD.NameList, c.CopyName(n, true))
   257  	}
   258  	return newD
   259  }
   260  
   261  func (c *DeepCopier) CopyFuncDecl(d *syntax.FuncDecl) *syntax.FuncDecl {
   262  	newD := &syntax.FuncDecl{
   263  		Pragma:     d.Pragma,
   264  		Recv:       c.CopyField(d.Recv),
   265  		Name:       c.CopyName(d.Name, true),
   266  		TParamList: c.CopyFieldList(d.TParamList),
   267  		Type:       c.CopyExpr(d.Type).(*syntax.FuncType),
   268  	}
   269  	newD.SetPos(d.Pos())
   270  
   271  	// Create and register new types2.Func
   272  	if oldFuncObj, ok := c.info.Defs[d.Name].(*types2.Func); ok {
   273  		newFuncObj := types2.NewFunc(newD.Name.Pos(), c.pkg, newD.Name.Value, oldFuncObj.Type().(*types2.Signature))
   274  		c.info.Defs[newD.Name] = newFuncObj
   275  	}
   276  
   277  	newD.Body = c.CopyBlockStmt(d.Body)
   278  	return newD
   279  }
   280  
   281  func (c *DeepCopier) CopyName(id *syntax.Name, isDef bool) *syntax.Name {
   282  	if id == nil {
   283  		return nil
   284  	}
   285  	if match := c.OnName(id); match != nil {
   286  		match.SetPos(id.Pos())
   287  		if isDef {
   288  			c.registerDef(match, id)
   289  		} else {
   290  			c.mapUse(match, id)
   291  		}
   292  		return match
   293  	}
   294  	newId := syntax.NewName(id.Pos(), id.Value)
   295  	if isDef {
   296  		c.registerDef(newId, id)
   297  	} else {
   298  		c.mapUse(newId, id)
   299  	}
   300  	return newId
   301  }
   302  
   303  func (c *DeepCopier) CopyNameExpr(id *syntax.Name) syntax.Expr {
   304  	if !c.analyzer.inSimd {
   305  		return c.CopyName(id, false)
   306  	}
   307  	if id == nil {
   308  		return nil
   309  	}
   310  
   311  	if match := c.OnNameExpr(id); match != nil {
   312  		match.SetPos(id.Pos())
   313  		if n, ok := match.(*syntax.Name); ok {
   314  			c.mapUse(n, id)
   315  		}
   316  		return match
   317  	}
   318  
   319  	newId := syntax.NewName(id.Pos(), id.Value)
   320  	c.mapUse(newId, id)
   321  	return newId
   322  }
   323  
   324  func (c *DeepCopier) CopyExpr(e syntax.Expr) syntax.Expr {
   325  	if e == nil {
   326  		return nil
   327  	}
   328  	var newE syntax.Expr
   329  	switch e := e.(type) {
   330  	case *syntax.Name:
   331  		return c.CopyNameExpr(e)
   332  	case *syntax.BasicLit:
   333  		newLit := &syntax.BasicLit{Value: e.Value, Kind: e.Kind, Bad: e.Bad}
   334  		newE = newLit
   335  	case *syntax.CompositeLit:
   336  		newLit := &syntax.CompositeLit{
   337  			Type:   c.CopyExpr(e.Type),
   338  			NKeys:  e.NKeys,
   339  			Rbrace: e.Rbrace,
   340  		}
   341  		for _, el := range e.ElemList {
   342  			newLit.ElemList = append(newLit.ElemList, c.CopyExpr(el))
   343  		}
   344  		newE = newLit
   345  	case *syntax.KeyValueExpr:
   346  		newE = &syntax.KeyValueExpr{Key: c.CopyExpr(e.Key), Value: c.CopyExpr(e.Value)}
   347  	case *syntax.FuncLit:
   348  		newE = &syntax.FuncLit{Type: c.CopyExpr(e.Type).(*syntax.FuncType), Body: c.CopyBlockStmt(e.Body)}
   349  	case *syntax.ParenExpr:
   350  		newE = &syntax.ParenExpr{X: c.CopyExpr(e.X)}
   351  	case *syntax.SelectorExpr:
   352  		if sub := c.OnSelector(e); sub != nil {
   353  			sub.SetPos(e.Pos())
   354  			if sel := c.info.Selections[e]; sel != nil {
   355  				c.info.Selections[sub.(*syntax.SelectorExpr)] = sel
   356  			}
   357  			return sub
   358  		}
   359  		newSel := &syntax.SelectorExpr{X: c.CopyExpr(e.X), Sel: c.CopyName(e.Sel, false)}
   360  		if sel := c.info.Selections[e]; sel != nil {
   361  			c.info.Selections[newSel] = sel
   362  		}
   363  		newE = newSel
   364  	case *syntax.IndexExpr:
   365  		newE = &syntax.IndexExpr{X: c.CopyExpr(e.X), Index: c.CopyExpr(e.Index)}
   366  	case *syntax.SliceExpr:
   367  		newE = &syntax.SliceExpr{
   368  			X:     c.CopyExpr(e.X),
   369  			Index: [3]syntax.Expr{c.CopyExpr(e.Index[0]), c.CopyExpr(e.Index[1]), c.CopyExpr(e.Index[2])},
   370  			Full:  e.Full,
   371  		}
   372  	case *syntax.AssertExpr:
   373  		newE = &syntax.AssertExpr{X: c.CopyExpr(e.X), Type: c.CopyExpr(e.Type)}
   374  	case *syntax.TypeSwitchGuard:
   375  		newE = &syntax.TypeSwitchGuard{Lhs: c.CopyName(e.Lhs, true), X: c.CopyExpr(e.X)}
   376  	case *syntax.Operation:
   377  		newE = &syntax.Operation{Op: e.Op, X: c.CopyExpr(e.X), Y: c.CopyExpr(e.Y)}
   378  	case *syntax.CallExpr:
   379  		newCall := &syntax.CallExpr{
   380  			Fun:     c.CopyExpr(e.Fun),
   381  			HasDots: e.HasDots,
   382  		}
   383  		for _, a := range e.ArgList {
   384  			newCall.ArgList = append(newCall.ArgList, c.CopyExpr(a))
   385  		}
   386  		newE = newCall
   387  	case *syntax.ListExpr:
   388  		newList := &syntax.ListExpr{}
   389  		for _, el := range e.ElemList {
   390  			newList.ElemList = append(newList.ElemList, c.CopyExpr(el))
   391  		}
   392  		newE = newList
   393  	case *syntax.ArrayType:
   394  		newE = &syntax.ArrayType{Len: c.CopyExpr(e.Len), Elem: c.CopyExpr(e.Elem)}
   395  	case *syntax.SliceType:
   396  		newE = &syntax.SliceType{Elem: c.CopyExpr(e.Elem)}
   397  	case *syntax.DotsType:
   398  		newE = &syntax.DotsType{Elem: c.CopyExpr(e.Elem)}
   399  	case *syntax.StructType:
   400  		newE = &syntax.StructType{
   401  			FieldList: c.CopyFieldList(e.FieldList),
   402  			TagList:   e.TagList, // Shallow copy for tags is fine usually
   403  		}
   404  	case *syntax.InterfaceType:
   405  		newE = &syntax.InterfaceType{MethodList: c.CopyFieldList(e.MethodList)}
   406  	case *syntax.FuncType:
   407  		newE = &syntax.FuncType{
   408  			ParamList:  c.CopyFieldList(e.ParamList),
   409  			ResultList: c.CopyFieldList(e.ResultList),
   410  		}
   411  	case *syntax.MapType:
   412  		newE = &syntax.MapType{Key: c.CopyExpr(e.Key), Value: c.CopyExpr(e.Value)}
   413  	case *syntax.ChanType:
   414  		newE = &syntax.ChanType{Dir: e.Dir, Elem: c.CopyExpr(e.Elem)}
   415  	case *syntax.BadExpr:
   416  		newE = &syntax.BadExpr{}
   417  	default:
   418  		newE = e
   419  	}
   420  	newE.SetPos(e.Pos())
   421  	return newE
   422  }
   423  
   424  func (c *DeepCopier) CopyStmt(s syntax.Stmt) syntax.Stmt {
   425  	if s == nil {
   426  		return nil
   427  	}
   428  	var newS syntax.Stmt
   429  	switch s := s.(type) {
   430  	case *syntax.DeclStmt:
   431  		newDeclList := make([]syntax.Decl, len(s.DeclList))
   432  		for i, v := range s.DeclList {
   433  			newDeclList[i] = c.CopyDecl(v)
   434  		}
   435  		newS = &syntax.DeclStmt{DeclList: newDeclList}
   436  	case *syntax.ExprStmt:
   437  		newS = &syntax.ExprStmt{X: c.CopyExpr(s.X)}
   438  	case *syntax.SendStmt:
   439  		newS = &syntax.SendStmt{Chan: c.CopyExpr(s.Chan), Value: c.CopyExpr(s.Value)}
   440  	case *syntax.AssignStmt:
   441  		newS = &syntax.AssignStmt{Op: s.Op, Lhs: c.CopyExpr(s.Lhs), Rhs: c.CopyExpr(s.Rhs)}
   442  	case *syntax.ReturnStmt:
   443  		newS = &syntax.ReturnStmt{Results: c.CopyExpr(s.Results)}
   444  	case *syntax.BranchStmt:
   445  		// TODO this is broken
   446  		newS = &syntax.BranchStmt{Tok: s.Tok, Label: c.CopyName(s.Label, false), Target: nil} // Targets need fix-up
   447  	case *syntax.CallStmt:
   448  		newS = &syntax.CallStmt{Tok: s.Tok, Call: c.CopyExpr(s.Call), DeferAt: c.CopyExpr(s.DeferAt)}
   449  	case *syntax.IfStmt:
   450  		newS = &syntax.IfStmt{
   451  			Init: c.CopySimpleStmt(s.Init),
   452  			Cond: c.CopyExpr(s.Cond),
   453  			Then: c.CopyBlockStmt(s.Then),
   454  			Else: c.CopyStmt(s.Else),
   455  		}
   456  	case *syntax.ForStmt:
   457  		newS = &syntax.ForStmt{
   458  			Init: c.CopySimpleStmt(s.Init),
   459  			Cond: c.CopyExpr(s.Cond),
   460  			Post: c.CopySimpleStmt(s.Post),
   461  			Body: c.CopyBlockStmt(s.Body),
   462  		}
   463  	case *syntax.SwitchStmt:
   464  		newS = &syntax.SwitchStmt{
   465  			Init:   c.CopySimpleStmt(s.Init),
   466  			Tag:    c.CopyExpr(s.Tag),
   467  			Body:   c.CopyCaseClauses(s.Body),
   468  			Rbrace: s.Rbrace,
   469  		}
   470  	case *syntax.SelectStmt:
   471  		newS = &syntax.SelectStmt{
   472  			Body:   c.CopyCommClauses(s.Body),
   473  			Rbrace: s.Rbrace,
   474  		}
   475  	case *syntax.EmptyStmt:
   476  		newS = &syntax.EmptyStmt{}
   477  	case *syntax.LabeledStmt:
   478  		newS = &syntax.LabeledStmt{Label: c.CopyName(s.Label, true), Stmt: c.CopyStmt(s.Stmt)} // Labels are defs
   479  	case *syntax.BlockStmt:
   480  		return c.CopyBlockStmt(s)
   481  	default:
   482  		newS = s
   483  	}
   484  	newS.SetPos(s.Pos())
   485  	return newS
   486  }
   487  
   488  func (c *DeepCopier) CopySimpleStmt(s syntax.SimpleStmt) syntax.SimpleStmt {
   489  	if s == nil {
   490  		return nil
   491  	}
   492  	switch s := s.(type) {
   493  	case *syntax.RangeClause:
   494  		newS := &syntax.RangeClause{
   495  			Def: s.Def,
   496  			X:   c.CopyExpr(s.X),
   497  		}
   498  		// In a range clause, Lhs may contain definitions if Def is true.
   499  		if list, ok := s.Lhs.(*syntax.ListExpr); ok && s.Def {
   500  			newList := &syntax.ListExpr{}
   501  			for _, el := range list.ElemList {
   502  				if id, ok := el.(*syntax.Name); ok {
   503  					newList.ElemList = append(newList.ElemList, c.CopyName(id, true))
   504  				} else {
   505  					newList.ElemList = append(newList.ElemList, c.CopyExpr(el))
   506  				}
   507  			}
   508  			newS.Lhs = newList
   509  		} else if id, ok := s.Lhs.(*syntax.Name); ok && s.Def {
   510  			newS.Lhs = c.CopyName(id, true)
   511  		} else {
   512  			newS.Lhs = c.CopyExpr(s.Lhs)
   513  		}
   514  		newS.Lhs.SetPos(s.Lhs.Pos())
   515  		newS.SetPos(s.Pos())
   516  		return newS
   517  	case *syntax.AssignStmt:
   518  		// Check for :=
   519  		isDef := false
   520  		if list, ok := s.Lhs.(*syntax.ListExpr); ok {
   521  			for _, el := range list.ElemList {
   522  				if id, ok := el.(*syntax.Name); ok && c.info.Defs[id] != nil {
   523  					isDef = true
   524  					break
   525  				}
   526  			}
   527  		} else if id, ok := s.Lhs.(*syntax.Name); ok && c.info.Defs[id] != nil {
   528  			isDef = true
   529  		}
   530  
   531  		newS := &syntax.AssignStmt{Op: s.Op, Rhs: c.CopyExpr(s.Rhs)}
   532  		if isDef {
   533  			if list, ok := s.Lhs.(*syntax.ListExpr); ok {
   534  				newList := &syntax.ListExpr{}
   535  				for _, el := range list.ElemList {
   536  					if id, ok := el.(*syntax.Name); ok && c.info.Defs[id] != nil {
   537  						newList.ElemList = append(newList.ElemList, c.CopyName(id, true))
   538  					} else {
   539  						newList.ElemList = append(newList.ElemList, c.CopyExpr(el))
   540  					}
   541  				}
   542  				newS.Lhs = newList
   543  			} else if id, ok := s.Lhs.(*syntax.Name); ok {
   544  				newS.Lhs = c.CopyName(id, true)
   545  			}
   546  		} else {
   547  			newS.Lhs = c.CopyExpr(s.Lhs)
   548  		}
   549  		newS.Lhs.SetPos(s.Lhs.Pos())
   550  		newS.SetPos(s.Pos())
   551  		return newS
   552  	default:
   553  		return c.CopyStmt(s).(syntax.SimpleStmt)
   554  	}
   555  }
   556  
   557  func (c *DeepCopier) CopyCaseClauses(list []*syntax.CaseClause) []*syntax.CaseClause {
   558  	var newList []*syntax.CaseClause
   559  	for _, cc := range list {
   560  		newC := &syntax.CaseClause{Cases: c.CopyExpr(cc.Cases), Colon: cc.Colon}
   561  		for _, b := range cc.Body {
   562  			newC.Body = append(newC.Body, c.CopyStmt(b))
   563  		}
   564  		newC.SetPos(cc.Pos())
   565  		newList = append(newList, newC)
   566  	}
   567  	return newList
   568  }
   569  
   570  func (c *DeepCopier) CopyCommClauses(list []*syntax.CommClause) []*syntax.CommClause {
   571  	var newList []*syntax.CommClause
   572  	for _, cc := range list {
   573  		newC := &syntax.CommClause{Comm: c.CopySimpleStmt(cc.Comm), Colon: cc.Colon}
   574  		for _, b := range cc.Body {
   575  			newC.Body = append(newC.Body, c.CopyStmt(b))
   576  		}
   577  		newC.SetPos(cc.Pos())
   578  		newList = append(newList, newC)
   579  	}
   580  	return newList
   581  }
   582  
   583  func (c *DeepCopier) CopyBlockStmt(b *syntax.BlockStmt) *syntax.BlockStmt {
   584  	if b == nil {
   585  		return nil
   586  	}
   587  	newB := &syntax.BlockStmt{Rbrace: b.Rbrace}
   588  	for _, s := range b.List {
   589  		newB.List = append(newB.List, c.CopyStmt(s))
   590  	}
   591  	newB.SetPos(b.Pos())
   592  	return newB
   593  }
   594  
   595  func (c *DeepCopier) CopyFieldList(f []*syntax.Field) []*syntax.Field {
   596  	if f == nil {
   597  		return nil
   598  	}
   599  	var newF []*syntax.Field
   600  	for _, field := range f {
   601  		newF = append(newF, c.CopyField(field))
   602  	}
   603  	return newF
   604  }
   605  
   606  func (c *DeepCopier) CopyField(f *syntax.Field) *syntax.Field {
   607  	if f == nil {
   608  		return nil
   609  	}
   610  	newF := &syntax.Field{
   611  		Name: c.CopyName(f.Name, true),
   612  		Type: c.CopyExpr(f.Type),
   613  	}
   614  	newF.SetPos(f.Pos())
   615  	return newF
   616  }
   617  

View as plain text