// Copyright 2009 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. package Printer import Globals "globals" import Object "object" import Type "type" import Universe "universe" type Printer struct { comp *Globals.Compilation; print_all bool; level int; }; func (P *Printer) PrintObjectStruct(obj *Globals.Object); func (P *Printer) PrintObject(obj *Globals.Object); func (P *Printer) PrintTypeStruct(typ *Globals.Type); func (P *Printer) PrintType(typ *Globals.Type); func (P *Printer) Init(comp *Globals.Compilation, print_all bool) { P.comp = comp; P.print_all = print_all; P.level = 0; } func IsAnonymous(name string) bool { return len(name) == 0 || name[0] == '.'; } func (P *Printer) PrintSigRange(typ *Globals.Type, a, b int) { scope := typ.scope; if a + 1 == b && IsAnonymous(scope.entries.ObjAt(a).ident) { P.PrintType(scope.entries.TypAt(a)); // result type only } else { print("("); for i := a; i < b; i++ { par := scope.entries.ObjAt(i); if i > a { print(", "); } print(par.ident, " "); P.PrintType(par.typ); } print(")"); } } func (P *Printer) PrintSignature(typ *Globals.Type, fun *Globals.Object) { if typ.form != Type.FUNCTION { panic("typ.form != Type.FUNCTION"); } p0 := 0; if typ.flags & Type.RECV != 0 { p0 = 1; } r0 := p0 + typ.len_; l0 := typ.scope.entries.len_; if P.level == 0 { print("func "); if 0 < p0 { P.PrintSigRange(typ, 0, p0); print(" "); } } if fun != nil { P.PrintObject(fun); //print(" "); } else if p0 > 0 { print(". "); } P.PrintSigRange(typ, p0, r0); if r0 < l0 { print(" "); P.PrintSigRange(typ, r0, l0); } } func (P *Printer) PrintIndent() { print("\n"); for i := P.level; i > 0; i-- { print("\t"); } } func (P *Printer) PrintScope(scope *Globals.Scope, delta int) { // determine the number of scope entries to print var n int; if P.print_all { n = scope.entries.len_; } else { n = 0; for p := scope.entries.first; p != nil; p = p.next { if p.obj.exported && !IsAnonymous(p.obj.ident) { n++; } } } // print the scope const scale = 2; if n > 0 { P.level += delta; for p := scope.entries.first; p != nil; p = p.next { if P.print_all || p.obj.exported && !IsAnonymous(p.obj.ident) { P.PrintIndent(); P.PrintObjectStruct(p.obj); } } P.level -= delta; P.PrintIndent(); } } func (P *Printer) PrintObjectStruct(obj *Globals.Object) { switch obj.kind { case Object.BAD: print("bad "); P.PrintObject(obj); case Object.CONST: print("const "); P.PrintObject(obj); print(" "); P.PrintType(obj.typ); case Object.TYPE: print("type "); P.PrintObject(obj); print(" "); P.PrintTypeStruct(obj.typ); case Object.VAR, Object.FIELD: if P.level == 0 { print("var "); } P.PrintObject(obj); print(" "); P.PrintType(obj.typ); case Object.FUNC: P.PrintSignature(obj.typ, obj); case Object.PACKAGE: print("package "); P.PrintObject(obj); print(" "); P.PrintScope(P.comp.pkg_list[obj.pnolev].scope, 0); default: panic("UNREACHABLE"); } if P.level > 0 { print(";"); } } func (P *Printer) PrintObject(obj *Globals.Object) { if obj.pnolev > 0 { pkg := P.comp.pkg_list[obj.pnolev]; if pkg.key == "" { // forward-declared package print(`"`, pkg.file_name, `"`); } else { // imported package print(pkg.obj.ident); } print("."); } print(obj.ident); } func (P *Printer) PrintTypeStruct(typ *Globals.Type) { switch typ.form { case Type.VOID: print("void"); case Type.FORWARD: print(""); case Type.BAD: print(""); case Type.NIL, Type.BOOL, Type.UINT, Type.INT, Type.FLOAT, Type.STRING, Type.ANY: if typ.obj == nil { panic("typ.obj == nil"); } P.PrintType(typ); case Type.ALIAS: P.PrintType(typ.elt); if typ.aux != typ.elt { print(" /* "); P.PrintType(typ.aux); print(" */"); } case Type.ARRAY: print("[]"); P.PrintType(typ.elt); case Type.STRUCT: print("struct {"); P.PrintScope(typ.scope, 1); print("}"); case Type.INTERFACE: print("interface {"); P.PrintScope(typ.scope, 1); print("}"); case Type.MAP: print("map ["); P.PrintType(typ.aux); print("] "); P.PrintType(typ.elt); case Type.CHANNEL: print("chan"); switch typ.flags { case Type.SEND: print(" -<"); case Type.RECV: print(" <-"); case Type.SEND + Type.RECV: // nothing to print default: panic("UNREACHABLE"); } print(" "); P.PrintType(typ.elt); case Type.FUNCTION: P.PrintSignature(typ, nil); case Type.POINTER: print("*"); P.PrintType(typ.elt); case Type.REFERENCE: print("&"); P.PrintType(typ.elt); default: panic("UNREACHABLE"); } } func (P *Printer) PrintType(typ *Globals.Type) { if typ.obj != nil { P.PrintObject(typ.obj); } else { P.PrintTypeStruct(typ); } } export func PrintObject(comp *Globals.Compilation, obj *Globals.Object, print_all bool) { var P Printer; (&P).Init(comp, print_all); (&P).PrintObjectStruct(obj); print("\n"); }