1// Copyright 2018 The OPA Authors. All rights reserved. 2// Use of this source code is governed by an Apache2 3// license that can be found in the LICENSE file. 4 5package ast 6 7import ( 8 "fmt" 9 "io" 10 "strings" 11) 12 13// Pretty writes a pretty representation of the AST rooted at x to w. 14// 15// This is function is intended for debug purposes when inspecting ASTs. 16func Pretty(w io.Writer, x interface{}) { 17 pp := &prettyPrinter{ 18 depth: -1, 19 w: w, 20 } 21 NewBeforeAfterVisitor(pp.Before, pp.After).Walk(x) 22} 23 24type prettyPrinter struct { 25 depth int 26 w io.Writer 27} 28 29func (pp *prettyPrinter) Before(x interface{}) bool { 30 switch x.(type) { 31 case *Term: 32 default: 33 pp.depth++ 34 } 35 36 switch x := x.(type) { 37 case *Term: 38 return false 39 case Args: 40 if len(x) == 0 { 41 return false 42 } 43 pp.writeType(x) 44 case *Expr: 45 extras := []string{} 46 if x.Negated { 47 extras = append(extras, "negated") 48 } 49 extras = append(extras, fmt.Sprintf("index=%d", x.Index)) 50 pp.writeIndent("%v %v", TypeName(x), strings.Join(extras, " ")) 51 case Null, Boolean, Number, String, Var: 52 pp.writeValue(x) 53 default: 54 pp.writeType(x) 55 } 56 return false 57} 58 59func (pp *prettyPrinter) After(x interface{}) { 60 switch x.(type) { 61 case *Term: 62 default: 63 pp.depth-- 64 } 65} 66 67func (pp *prettyPrinter) writeValue(x interface{}) { 68 pp.writeIndent(fmt.Sprint(x)) 69} 70 71func (pp *prettyPrinter) writeType(x interface{}) { 72 pp.writeIndent(TypeName(x)) 73} 74 75func (pp *prettyPrinter) writeIndent(f string, a ...interface{}) { 76 pad := strings.Repeat(" ", pp.depth) 77 pp.write(pad+f, a...) 78} 79 80func (pp *prettyPrinter) write(f string, a ...interface{}) { 81 fmt.Fprintf(pp.w, f+"\n", a...) 82} 83