Пример #1
0
func IncDecStmt(stmt ast.Stmt, info *analysis.Info) ast.Stmt {
	if s, ok := stmt.(*ast.IncDecStmt); ok {
		t := info.TypeOf(s.X)
		if iExpr, isIExpr := s.X.(*ast.IndexExpr); isIExpr {
			switch u := info.TypeOf(iExpr.X).Underlying().(type) {
			case *types.Array:
				t = u.Elem()
			case *types.Slice:
				t = u.Elem()
			case *types.Map:
				t = u.Elem()
			}
		}

		tok := token.ADD_ASSIGN
		if s.Tok == token.DEC {
			tok = token.SUB_ASSIGN
		}

		one := &ast.BasicLit{Kind: token.INT}
		info.Types[one] = types.TypeAndValue{Type: t, Value: exact.MakeInt64(1)}

		return &ast.AssignStmt{
			Lhs: []ast.Expr{s.X},
			Tok: tok,
			Rhs: []ast.Expr{one},
		}
	}
	return stmt
}
Пример #2
0
func Assign(stmt ast.Stmt, info *analysis.Info) ast.Stmt {
	if s, ok := stmt.(*ast.AssignStmt); ok && s.Tok != token.ASSIGN && s.Tok != token.DEFINE {
		var op token.Token
		switch s.Tok {
		case token.ADD_ASSIGN:
			op = token.ADD
		case token.SUB_ASSIGN:
			op = token.SUB
		case token.MUL_ASSIGN:
			op = token.MUL
		case token.QUO_ASSIGN:
			op = token.QUO
		case token.REM_ASSIGN:
			op = token.REM
		case token.AND_ASSIGN:
			op = token.AND
		case token.OR_ASSIGN:
			op = token.OR
		case token.XOR_ASSIGN:
			op = token.XOR
		case token.SHL_ASSIGN:
			op = token.SHL
		case token.SHR_ASSIGN:
			op = token.SHR
		case token.AND_NOT_ASSIGN:
			op = token.AND_NOT
		default:
			panic(s.Tok)
		}

		var list []ast.Stmt

		var viaTmpVars func(expr ast.Expr, name string) ast.Expr
		viaTmpVars = func(expr ast.Expr, name string) ast.Expr {
			switch e := astutil.RemoveParens(expr).(type) {
			case *ast.IndexExpr:
				return astutil.SetType(info.Info, info.TypeOf(e), &ast.IndexExpr{
					X:     viaTmpVars(e.X, "_slice"),
					Index: viaTmpVars(e.Index, "_index"),
				})

			case *ast.SelectorExpr:
				sel, ok := info.Selections[e]
				if !ok {
					// qualified identifier
					return e
				}
				newSel := &ast.SelectorExpr{
					X:   viaTmpVars(e.X, "_struct"),
					Sel: e.Sel,
				}
				info.Selections[newSel] = sel
				return astutil.SetType(info.Info, info.TypeOf(e), newSel)

			case *ast.StarExpr:
				return astutil.SetType(info.Info, info.TypeOf(e), &ast.StarExpr{
					X: viaTmpVars(e.X, "_ptr"),
				})

			case *ast.Ident, *ast.BasicLit:
				return e

			default:
				tmpVar := astutil.NewIdent(name, info.TypeOf(e), info.Info, info.Pkg)
				list = append(list, &ast.AssignStmt{
					Lhs: []ast.Expr{tmpVar},
					Tok: token.DEFINE,
					Rhs: []ast.Expr{e},
				})
				return tmpVar

			}
		}

		lhs := viaTmpVars(s.Lhs[0], "_val")

		list = append(list, &ast.AssignStmt{
			Lhs: []ast.Expr{lhs},
			Tok: token.ASSIGN,
			Rhs: []ast.Expr{
				astutil.SetType(info.Info, info.TypeOf(s.Lhs[0]), &ast.BinaryExpr{
					X:  lhs,
					Op: op,
					Y: astutil.SetType(info.Info, info.TypeOf(s.Rhs[0]), &ast.ParenExpr{
						X: s.Rhs[0],
					}),
				}),
			},
		})

		return &ast.BlockStmt{
			List: list,
		}
	}
	return stmt
}