You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
3.0 KiB

  1. // Copyright 2013 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. package ssa
  5. // This file defines a number of miscellaneous utility functions.
  6. import (
  7. "fmt"
  8. "go/ast"
  9. "go/token"
  10. "go/types"
  11. "io"
  12. "os"
  13. "golang.org/x/tools/go/ast/astutil"
  14. )
  15. //// AST utilities
  16. func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }
  17. // isBlankIdent returns true iff e is an Ident with name "_".
  18. // They have no associated types.Object, and thus no type.
  19. //
  20. func isBlankIdent(e ast.Expr) bool {
  21. id, ok := e.(*ast.Ident)
  22. return ok && id.Name == "_"
  23. }
  24. //// Type utilities. Some of these belong in go/types.
  25. // isPointer returns true for types whose underlying type is a pointer.
  26. func isPointer(typ types.Type) bool {
  27. _, ok := typ.Underlying().(*types.Pointer)
  28. return ok
  29. }
  30. func isInterface(T types.Type) bool { return types.IsInterface(T) }
  31. // deref returns a pointer's element type; otherwise it returns typ.
  32. func deref(typ types.Type) types.Type {
  33. if p, ok := typ.Underlying().(*types.Pointer); ok {
  34. return p.Elem()
  35. }
  36. return typ
  37. }
  38. // recvType returns the receiver type of method obj.
  39. func recvType(obj *types.Func) types.Type {
  40. return obj.Type().(*types.Signature).Recv().Type()
  41. }
  42. // DefaultType returns the default "typed" type for an "untyped" type;
  43. // it returns the incoming type for all other types. The default type
  44. // for untyped nil is untyped nil.
  45. //
  46. // Exported to ssa/interp.
  47. //
  48. // TODO(adonovan): use go/types.DefaultType after 1.8.
  49. //
  50. func DefaultType(typ types.Type) types.Type {
  51. if t, ok := typ.(*types.Basic); ok {
  52. k := t.Kind()
  53. switch k {
  54. case types.UntypedBool:
  55. k = types.Bool
  56. case types.UntypedInt:
  57. k = types.Int
  58. case types.UntypedRune:
  59. k = types.Rune
  60. case types.UntypedFloat:
  61. k = types.Float64
  62. case types.UntypedComplex:
  63. k = types.Complex128
  64. case types.UntypedString:
  65. k = types.String
  66. }
  67. typ = types.Typ[k]
  68. }
  69. return typ
  70. }
  71. // logStack prints the formatted "start" message to stderr and
  72. // returns a closure that prints the corresponding "end" message.
  73. // Call using 'defer logStack(...)()' to show builder stack on panic.
  74. // Don't forget trailing parens!
  75. //
  76. func logStack(format string, args ...interface{}) func() {
  77. msg := fmt.Sprintf(format, args...)
  78. io.WriteString(os.Stderr, msg)
  79. io.WriteString(os.Stderr, "\n")
  80. return func() {
  81. io.WriteString(os.Stderr, msg)
  82. io.WriteString(os.Stderr, " end\n")
  83. }
  84. }
  85. // newVar creates a 'var' for use in a types.Tuple.
  86. func newVar(name string, typ types.Type) *types.Var {
  87. return types.NewParam(token.NoPos, nil, name, typ)
  88. }
  89. // anonVar creates an anonymous 'var' for use in a types.Tuple.
  90. func anonVar(typ types.Type) *types.Var {
  91. return newVar("", typ)
  92. }
  93. var lenResults = types.NewTuple(anonVar(tInt))
  94. // makeLen returns the len builtin specialized to type func(T)int.
  95. func makeLen(T types.Type) *Builtin {
  96. lenParams := types.NewTuple(anonVar(T))
  97. return &Builtin{
  98. name: "len",
  99. sig: types.NewSignature(nil, lenParams, lenResults, false),
  100. }
  101. }