+++ /dev/null
-// UNREVIEWED
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This file implements printing of expressions.
-
-package types2
-
-import (
- "bytes"
- "cmd/compile/internal/syntax"
-)
-
-// ExprString returns the (possibly shortened) string representation for x.
-// Shortened representations are suitable for user interfaces but may not
-// necessarily follow Go syntax.
-func ExprString(x syntax.Expr) string {
- var buf bytes.Buffer
- WriteExpr(&buf, x)
- return buf.String()
-}
-
-// WriteExpr writes the (possibly shortened) string representation for x to buf.
-// Shortened representations are suitable for user interfaces but may not
-// necessarily follow Go syntax.
-func WriteExpr(buf *bytes.Buffer, x syntax.Expr) {
- // The AST preserves source-level parentheses so there is
- // no need to introduce them here to correct for different
- // operator precedences. (This assumes that the AST was
- // generated by a Go parser.)
-
- // TODO(gri): This assumption is not correct - we need to recreate
- // parentheses in expressions.
-
- switch x := x.(type) {
- default:
- buf.WriteString("(ast: bad expr)") // nil, syntax.BadExpr, syntax.KeyValueExpr
-
- case *syntax.Name:
- buf.WriteString(x.Value)
-
- case *syntax.DotsType:
- buf.WriteString("...")
- if x.Elem != nil {
- WriteExpr(buf, x.Elem)
- }
-
- case *syntax.BasicLit:
- buf.WriteString(x.Value)
-
- case *syntax.FuncLit:
- WriteExpr(buf, x.Type)
- if x.Body != nil && len(x.Body.List) > 0 {
- buf.WriteString(" {…}") // shortened
- } else {
- buf.WriteString(" {}")
- }
-
- case *syntax.CompositeLit:
- WriteExpr(buf, x.Type)
- if len(x.ElemList) > 0 {
- buf.WriteString("{…}") // shortened
- } else {
- buf.WriteString("{}")
- }
-
- case *syntax.ParenExpr:
- buf.WriteByte('(')
- WriteExpr(buf, x.X)
- buf.WriteByte(')')
-
- case *syntax.SelectorExpr:
- WriteExpr(buf, x.X)
- buf.WriteByte('.')
- buf.WriteString(x.Sel.Value)
-
- case *syntax.IndexExpr:
- WriteExpr(buf, x.X)
- buf.WriteByte('[')
- WriteExpr(buf, x.Index) // x.Index may be a *ListExpr
- buf.WriteByte(']')
-
- case *syntax.SliceExpr:
- WriteExpr(buf, x.X)
- buf.WriteByte('[')
- if x.Index[0] != nil {
- WriteExpr(buf, x.Index[0])
- }
- buf.WriteByte(':')
- if x.Index[1] != nil {
- WriteExpr(buf, x.Index[1])
- }
- if x.Full {
- buf.WriteByte(':')
- if x.Index[2] != nil {
- WriteExpr(buf, x.Index[2])
- }
- }
- buf.WriteByte(']')
-
- case *syntax.AssertExpr:
- WriteExpr(buf, x.X)
- buf.WriteString(".(")
- WriteExpr(buf, x.Type)
- buf.WriteByte(')')
-
- case *syntax.CallExpr:
- WriteExpr(buf, x.Fun)
- buf.WriteByte('(')
- writeExprList(buf, x.ArgList)
- if x.HasDots {
- buf.WriteString("...")
- }
- buf.WriteByte(')')
-
- case *syntax.ListExpr:
- writeExprList(buf, x.ElemList)
-
- case *syntax.Operation:
- // TODO(gri) This would be simpler if x.X == nil meant unary expression.
- if x.Y == nil {
- // unary expression
- buf.WriteString(x.Op.String())
- WriteExpr(buf, x.X)
- } else {
- // binary expression
- WriteExpr(buf, x.X)
- buf.WriteByte(' ')
- buf.WriteString(x.Op.String())
- buf.WriteByte(' ')
- WriteExpr(buf, x.Y)
- }
-
- // case *ast.StarExpr:
- // buf.WriteByte('*')
- // WriteExpr(buf, x.X)
-
- // case *ast.UnaryExpr:
- // buf.WriteString(x.Op.String())
- // WriteExpr(buf, x.X)
-
- // case *ast.BinaryExpr:
- // WriteExpr(buf, x.X)
- // buf.WriteByte(' ')
- // buf.WriteString(x.Op.String())
- // buf.WriteByte(' ')
- // WriteExpr(buf, x.Y)
-
- case *syntax.ArrayType:
- if x.Len == nil {
- buf.WriteString("[...]")
- } else {
- buf.WriteByte('[')
- WriteExpr(buf, x.Len)
- buf.WriteByte(']')
- }
- WriteExpr(buf, x.Elem)
-
- case *syntax.SliceType:
- buf.WriteString("[]")
- WriteExpr(buf, x.Elem)
-
- case *syntax.StructType:
- buf.WriteString("struct{")
- writeFieldList(buf, x.FieldList, "; ", false)
- buf.WriteByte('}')
-
- case *syntax.FuncType:
- buf.WriteString("func")
- writeSigExpr(buf, x)
-
- case *syntax.InterfaceType:
- // separate type list types from method list
- // TODO(gri) we can get rid of this extra code if writeExprList does the separation
- var types []syntax.Expr
- var methods []*syntax.Field
- for _, f := range x.MethodList {
- if f.Name != nil && f.Name.Value == "type" {
- // type list type
- types = append(types, f.Type)
- } else {
- // method or embedded interface
- methods = append(methods, f)
- }
- }
-
- buf.WriteString("interface{")
- writeFieldList(buf, methods, "; ", true)
- if len(types) > 0 {
- if len(methods) > 0 {
- buf.WriteString("; ")
- }
- buf.WriteString("type ")
- writeExprList(buf, types)
- }
- buf.WriteByte('}')
-
- case *syntax.MapType:
- buf.WriteString("map[")
- WriteExpr(buf, x.Key)
- buf.WriteByte(']')
- WriteExpr(buf, x.Value)
-
- case *syntax.ChanType:
- var s string
- switch x.Dir {
- case syntax.SendOnly:
- s = "chan<- "
- case syntax.RecvOnly:
- s = "<-chan "
- default:
- s = "chan "
- }
- buf.WriteString(s)
- if e, _ := x.Elem.(*syntax.ChanType); x.Dir != syntax.SendOnly && e != nil && e.Dir == syntax.RecvOnly {
- // don't print chan (<-chan T) as chan <-chan T (but chan<- <-chan T is ok)
- buf.WriteByte('(')
- WriteExpr(buf, x.Elem)
- buf.WriteByte(')')
- } else {
- WriteExpr(buf, x.Elem)
- }
- }
-}
-
-func writeSigExpr(buf *bytes.Buffer, sig *syntax.FuncType) {
- buf.WriteByte('(')
- writeFieldList(buf, sig.ParamList, ", ", false)
- buf.WriteByte(')')
-
- res := sig.ResultList
- n := len(res)
- if n == 0 {
- // no result
- return
- }
-
- buf.WriteByte(' ')
- if n == 1 && res[0].Name == nil {
- // single unnamed result
- WriteExpr(buf, res[0].Type)
- return
- }
-
- // multiple or named result(s)
- buf.WriteByte('(')
- writeFieldList(buf, res, ", ", false)
- buf.WriteByte(')')
-}
-
-func writeFieldList(buf *bytes.Buffer, list []*syntax.Field, sep string, iface bool) {
- for i := 0; i < len(list); {
- f := list[i]
- if i > 0 {
- buf.WriteString(sep)
- }
-
- // if we don't have a name, we have an embedded type
- if f.Name == nil {
- WriteExpr(buf, f.Type)
- i++
- continue
- }
-
- // types of interface methods consist of signatures only
- if sig, _ := f.Type.(*syntax.FuncType); sig != nil && iface {
- buf.WriteString(f.Name.Value)
- writeSigExpr(buf, sig)
- i++
- continue
- }
-
- // write the type only once for a sequence of fields with the same type
- t := f.Type
- buf.WriteString(f.Name.Value)
- for i++; i < len(list) && list[i].Type == t; i++ {
- buf.WriteString(", ")
- buf.WriteString(list[i].Name.Value)
- }
- buf.WriteByte(' ')
- WriteExpr(buf, t)
- }
-}
-
-func writeExprList(buf *bytes.Buffer, list []syntax.Expr) {
- for i, x := range list {
- if i > 0 {
- buf.WriteString(", ")
- }
- WriteExpr(buf, x)
- }
-}