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

View as plain text