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