func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exprListMode, next0 token.Pos) {
	if len(list) == 0 {
		return
	}
	prev := p.posFor(prev0)
	next := p.posFor(next0)
	line := p.lineFor(list[0].Pos())
	endLine := p.lineFor(list[len(list)-1].End())
	if prev.IsValid() && prev.Line == line && line == endLine {
		for i, x := range list {
			if i > 0 {
				p.print(x.Pos(), token.COMMA, blank)
			}
			p.expr0(x, depth)
		}
		return
	}
	ws := ignore
	if mode&noIndent == 0 {
		ws = indent
	}
	prevBreak := -1  
	if prev.IsValid() && prev.Line < line && p.linebreak(line, 0, ws, true) {
		ws = ignore
		prevBreak = 0
	}
	size := 0
	prevLine := prev.Line
	for i, x := range list {
		line = p.lineFor(x.Pos())
		useFF := true
		prevSize := size
		const infinity = 1e6  
		size = p.nodeSize(x, infinity)
		pair, isPair := x.(*ast.KeyValueExpr)
		if size <= infinity && prev.IsValid() && next.IsValid() {
			if isPair {
				size = p.nodeSize(pair.Key, infinity)  
			}
		} else {
			size = 0
		}
		if prevSize > 0 && size > 0 {
			const smallSize = 20
			if prevSize <= smallSize && size <= smallSize {
				useFF = false
			} else {
				const r = 4  
				ratio := float64(size) / float64(prevSize)
				useFF = ratio <= 1.0/r || r <= ratio
			}
		}
		needsLinebreak := 0 < prevLine && prevLine < line
		if i > 0 {
			if !needsLinebreak {
				p.print(x.Pos())
			}
			p.print(token.COMMA)
			needsBlank := true
			if needsLinebreak {
				if p.linebreak(line, 0, ws, useFF || prevBreak+1 < i) {
					ws = ignore
					prevBreak = i
					needsBlank = false  
				}
			}
			if needsBlank {
				p.print(blank)
			}
		}
		if len(list) > 1 && isPair && size > 0 && needsLinebreak {
			p.expr(pair.Key)
			p.print(pair.Colon, token.COLON, vtab)
			p.expr(pair.Value)
		} else {
			p.expr0(x, depth)
		}
		prevLine = line
	}
	if mode&commaTerm != 0 && next.IsValid() && p.pos.Line < next.Line {
		p.print(token.COMMA)
		if ws == ignore && mode&noIndent == 0 {
			p.print(unindent)
		}
		p.print(formfeed)  
		return
	}
	if ws == ignore && mode&noIndent == 0 {
		p.print(unindent)
	}
}
Print a list of expressions. If the list spans multiple
source lines, the original line breaks are respected between
expressions.

TODO(gri) Consider rewriting this to be independent of []ast.Expr
so that we can use the algorithm for any kind of list
(e.g., pass list via a channel over which to range).
package printer
import (
	"bytes"
	"strconv"
	"strings"
	"unicode"
	"unicode/utf8"
	"html"
	"github.com/8byt/gox/ast"
	"github.com/8byt/gox/token"
)
func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (printedBreak bool) {
	n := nlimit(line - p.pos.Line)
	if n < min {
		n = min
	}
	if n > 0 {
		p.print(ws)
		if newSection {
			p.print(formfeed)
			n--
		}
		for ; n > 0; n-- {
			p.print(newline)
		}
		printedBreak = true
	}
	return
}
func (p *printer) setComment(g *ast.CommentGroup) {
	if g == nil || !p.useNodeComments {
		return
	}
	if p.comments == nil {
		p.comments = make([]*ast.CommentGroup, 1)
	} else if p.cindex < len(p.comments) {
		p.flush(p.posFor(g.List[0].Pos()), token.ILLEGAL)
		p.comments = p.comments[0:1]
		p.internalError("setComment found pending comments")
	}
	p.comments[0] = g
	p.cindex = 0
	if p.commentOffset == infinity {
		p.nextComment()  
	}
}
type exprListMode uint
const (
	commaTerm exprListMode = 1 << iota  
	noIndent                            
)
func (p *printer) identList(list []*ast.Ident, indent bool) {
	xlist := make([]ast.Expr, len(list))
	for i, x := range list {
		xlist[i] = x
	}
	var mode exprListMode
	if !indent {
		mode = noIndent
	}
	p.exprList(token.NoPos, xlist, 1, mode, token.NoPos)
}