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

View as plain text