github.com/goplus/gop@v1.2.6/x/typesutil/exprstring.go (about) 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 5 // This file implements printing of expressions. 6 7 package typesutil 8 9 import ( 10 "bytes" 11 "fmt" 12 13 "github.com/goplus/gop/ast" 14 "github.com/goplus/gop/x/typesutil/typeparams" 15 ) 16 17 // ExprString returns the (possibly shortened) string representation for x. 18 // Shortened representations are suitable for user interfaces but may not 19 // necessarily follow Go syntax. 20 func ExprString(x ast.Expr) string { 21 var buf bytes.Buffer 22 WriteExpr(&buf, x) 23 return buf.String() 24 } 25 26 // WriteExpr writes the (possibly shortened) string representation for x to buf. 27 // Shortened representations are suitable for user interfaces but may not 28 // necessarily follow Go syntax. 29 func WriteExpr(buf *bytes.Buffer, x ast.Expr) { 30 // The AST preserves source-level parentheses so there is 31 // no need to introduce them here to correct for different 32 // operator precedences. (This assumes that the AST was 33 // generated by a Go parser.) 34 35 switch x := x.(type) { 36 default: 37 fmt.Fprintf(buf, "(ast: %T)", x) // nil, ast.BadExpr, ast.KeyValueExpr 38 39 case *ast.Ident: 40 buf.WriteString(x.Name) 41 42 case *ast.Ellipsis: 43 buf.WriteString("...") 44 if x.Elt != nil { 45 WriteExpr(buf, x.Elt) 46 } 47 48 case *ast.BasicLit: 49 buf.WriteString(x.Value) 50 51 case *ast.FuncLit: 52 buf.WriteByte('(') 53 WriteExpr(buf, x.Type) 54 buf.WriteString(" literal)") // shortened 55 56 case *ast.CompositeLit: 57 WriteExpr(buf, x.Type) 58 buf.WriteByte('{') 59 if len(x.Elts) > 0 { 60 buf.WriteString("…") 61 } 62 buf.WriteByte('}') 63 64 case *ast.ParenExpr: 65 buf.WriteByte('(') 66 WriteExpr(buf, x.X) 67 buf.WriteByte(')') 68 69 case *ast.SelectorExpr: 70 WriteExpr(buf, x.X) 71 buf.WriteByte('.') 72 buf.WriteString(x.Sel.Name) 73 74 case *ast.IndexExpr, *ast.IndexListExpr: 75 ix := typeparams.UnpackIndexExpr(x) 76 WriteExpr(buf, ix.X) 77 buf.WriteByte('[') 78 writeExprList(buf, ix.Indices) 79 buf.WriteByte(']') 80 81 case *ast.SliceExpr: 82 WriteExpr(buf, x.X) 83 buf.WriteByte('[') 84 if x.Low != nil { 85 WriteExpr(buf, x.Low) 86 } 87 buf.WriteByte(':') 88 if x.High != nil { 89 WriteExpr(buf, x.High) 90 } 91 if x.Slice3 { 92 buf.WriteByte(':') 93 if x.Max != nil { 94 WriteExpr(buf, x.Max) 95 } 96 } 97 buf.WriteByte(']') 98 99 case *ast.TypeAssertExpr: 100 WriteExpr(buf, x.X) 101 buf.WriteString(".(") 102 WriteExpr(buf, x.Type) 103 buf.WriteByte(')') 104 105 case *ast.CallExpr: 106 WriteExpr(buf, x.Fun) 107 buf.WriteByte('(') 108 writeExprList(buf, x.Args) 109 if x.Ellipsis.IsValid() { 110 buf.WriteString("...") 111 } 112 buf.WriteByte(')') 113 114 case *ast.StarExpr: 115 buf.WriteByte('*') 116 WriteExpr(buf, x.X) 117 118 case *ast.UnaryExpr: 119 buf.WriteString(x.Op.String()) 120 WriteExpr(buf, x.X) 121 122 case *ast.BinaryExpr: 123 WriteExpr(buf, x.X) 124 buf.WriteByte(' ') 125 buf.WriteString(x.Op.String()) 126 buf.WriteByte(' ') 127 WriteExpr(buf, x.Y) 128 129 case *ast.ArrayType: 130 buf.WriteByte('[') 131 if x.Len != nil { 132 WriteExpr(buf, x.Len) 133 } 134 buf.WriteByte(']') 135 WriteExpr(buf, x.Elt) 136 137 case *ast.StructType: 138 buf.WriteString("struct{") 139 writeFieldList(buf, x.Fields.List, "; ", false) 140 buf.WriteByte('}') 141 142 case *ast.FuncType: 143 buf.WriteString("func") 144 writeSigExpr(buf, x) 145 146 case *ast.InterfaceType: 147 buf.WriteString("interface{") 148 writeFieldList(buf, x.Methods.List, "; ", true) 149 buf.WriteByte('}') 150 151 case *ast.MapType: 152 buf.WriteString("map[") 153 WriteExpr(buf, x.Key) 154 buf.WriteByte(']') 155 WriteExpr(buf, x.Value) 156 157 case *ast.ChanType: 158 var s string 159 switch x.Dir { 160 case ast.SEND: 161 s = "chan<- " 162 case ast.RECV: 163 s = "<-chan " 164 default: 165 s = "chan " 166 } 167 buf.WriteString(s) 168 WriteExpr(buf, x.Value) 169 } 170 } 171 172 func writeSigExpr(buf *bytes.Buffer, sig *ast.FuncType) { 173 buf.WriteByte('(') 174 writeFieldList(buf, sig.Params.List, ", ", false) 175 buf.WriteByte(')') 176 177 res := sig.Results 178 n := res.NumFields() 179 if n == 0 { 180 // no result 181 return 182 } 183 184 buf.WriteByte(' ') 185 if n == 1 && len(res.List[0].Names) == 0 { 186 // single unnamed result 187 WriteExpr(buf, res.List[0].Type) 188 return 189 } 190 191 // multiple or named result(s) 192 buf.WriteByte('(') 193 writeFieldList(buf, res.List, ", ", false) 194 buf.WriteByte(')') 195 } 196 197 func writeFieldList(buf *bytes.Buffer, list []*ast.Field, sep string, iface bool) { 198 for i, f := range list { 199 if i > 0 { 200 buf.WriteString(sep) 201 } 202 203 // field list names 204 writeIdentList(buf, f.Names) 205 206 // types of interface methods consist of signatures only 207 if sig, _ := f.Type.(*ast.FuncType); sig != nil && iface { 208 writeSigExpr(buf, sig) 209 continue 210 } 211 212 // named fields are separated with a blank from the field type 213 if len(f.Names) > 0 { 214 buf.WriteByte(' ') 215 } 216 217 WriteExpr(buf, f.Type) 218 219 // ignore tag 220 } 221 } 222 223 func writeIdentList(buf *bytes.Buffer, list []*ast.Ident) { 224 for i, x := range list { 225 if i > 0 { 226 buf.WriteString(", ") 227 } 228 buf.WriteString(x.Name) 229 } 230 } 231 232 func writeExprList(buf *bytes.Buffer, list []ast.Expr) { 233 for i, x := range list { 234 if i > 0 { 235 buf.WriteString(", ") 236 } 237 WriteExpr(buf, x) 238 } 239 }