github.com/goplusjs/gopherjs@v1.2.6-0.20211206034512-f187917453b8/compiler/filter/assign.go (about)

     1  package filter
     2  
     3  import (
     4  	"go/ast"
     5  	"go/token"
     6  	"go/types"
     7  
     8  	"github.com/goplusjs/gopherjs/compiler/astutil"
     9  )
    10  
    11  func Assign(stmt ast.Stmt, info *types.Info, pkg *types.Package) ast.Stmt {
    12  	if s, ok := stmt.(*ast.AssignStmt); ok && s.Tok != token.ASSIGN && s.Tok != token.DEFINE {
    13  		var op token.Token
    14  		switch s.Tok {
    15  		case token.ADD_ASSIGN:
    16  			op = token.ADD
    17  		case token.SUB_ASSIGN:
    18  			op = token.SUB
    19  		case token.MUL_ASSIGN:
    20  			op = token.MUL
    21  		case token.QUO_ASSIGN:
    22  			op = token.QUO
    23  		case token.REM_ASSIGN:
    24  			op = token.REM
    25  		case token.AND_ASSIGN:
    26  			op = token.AND
    27  		case token.OR_ASSIGN:
    28  			op = token.OR
    29  		case token.XOR_ASSIGN:
    30  			op = token.XOR
    31  		case token.SHL_ASSIGN:
    32  			op = token.SHL
    33  		case token.SHR_ASSIGN:
    34  			op = token.SHR
    35  		case token.AND_NOT_ASSIGN:
    36  			op = token.AND_NOT
    37  		default:
    38  			panic(s.Tok)
    39  		}
    40  
    41  		var list []ast.Stmt
    42  
    43  		var viaTmpVars func(expr ast.Expr, name string) ast.Expr
    44  		viaTmpVars = func(expr ast.Expr, name string) ast.Expr {
    45  			switch e := astutil.RemoveParens(expr).(type) {
    46  			case *ast.IndexExpr:
    47  				return astutil.SetType(info, info.TypeOf(e), &ast.IndexExpr{
    48  					X:     viaTmpVars(e.X, "_slice"),
    49  					Index: viaTmpVars(e.Index, "_index"),
    50  				})
    51  
    52  			case *ast.SelectorExpr:
    53  				sel, ok := info.Selections[e]
    54  				if !ok {
    55  					// qualified identifier
    56  					return e
    57  				}
    58  				newSel := &ast.SelectorExpr{
    59  					X:   viaTmpVars(e.X, "_struct"),
    60  					Sel: e.Sel,
    61  				}
    62  				info.Selections[newSel] = sel
    63  				return astutil.SetType(info, info.TypeOf(e), newSel)
    64  
    65  			case *ast.StarExpr:
    66  				return astutil.SetType(info, info.TypeOf(e), &ast.StarExpr{
    67  					X: viaTmpVars(e.X, "_ptr"),
    68  				})
    69  
    70  			case *ast.Ident, *ast.BasicLit:
    71  				return e
    72  
    73  			default:
    74  				tmpVar := astutil.NewIdent(name, info.TypeOf(e), info, pkg)
    75  				list = append(list, &ast.AssignStmt{
    76  					Lhs: []ast.Expr{tmpVar},
    77  					Tok: token.DEFINE,
    78  					Rhs: []ast.Expr{e},
    79  				})
    80  				return tmpVar
    81  
    82  			}
    83  		}
    84  
    85  		lhs := viaTmpVars(s.Lhs[0], "_val")
    86  
    87  		list = append(list, &ast.AssignStmt{
    88  			Lhs: []ast.Expr{lhs},
    89  			Tok: token.ASSIGN,
    90  			Rhs: []ast.Expr{
    91  				astutil.SetType(info, info.TypeOf(s.Lhs[0]), &ast.BinaryExpr{
    92  					X:  lhs,
    93  					Op: op,
    94  					Y: astutil.SetType(info, info.TypeOf(s.Rhs[0]), &ast.ParenExpr{
    95  						X: s.Rhs[0],
    96  					}),
    97  				}),
    98  			},
    99  		})
   100  
   101  		return &ast.BlockStmt{
   102  			List: list,
   103  		}
   104  	}
   105  	return stmt
   106  }