Example #1
0
File: exports.go Project: pcc/llgo
func (x *exporter) exportObject(obj types.Object) {
	switch t := obj.(type) {
	case *types.Var:
		if !obj.IsExported() {
			return
		}
		x.write("\tvar @\"\".%s ", obj.Name())
		x.exportName(obj.Type())
		x.write("\n")
	case *types.Func:
		sig := t.Type().(*types.Signature)
		recv := sig.Recv()
		if recv == nil && !t.IsExported() {
			return
			// The package "go/ast" has an interface "Decl" (http://golang.org/pkg/go/ast/#Decl)
			// containing "filtered or unexported methods", specifically a method named "declNode".
			//
			// No implementation of that method actually does anything, but it forces type
			// correctness and also disallows other packages from defining new types that
			// satisfies that interface.
			//
			// As the interface is exported and the types implementing the interface are too,
			// "declNode" must be exported to be able to properly type check any code that type
			// casts from and to that interface.
			//
			// To be clear; exporting *all* receiver methods is a superset of the methods
			// that must be exported.
		}
		x.write("\tfunc ")

		if recv != nil {
			x.write("(")
			x.exportName(recv)
			x.write(") ")
		}
		x.write(`@"".%s`, t.Name())
		x.writeFunc = false
		x.exportName(sig)
		x.write("\n")
	case *types.Const:
		if !t.IsExported() {
			return
		}
		x.write("\tconst @\"\".%s ", t.Name())
		x.exportName(t.Type())
		x.write(" = ")
		x.exportName(t.Val())
		x.write("\n")
	case *types.TypeName:
		// Some types that are not exported outside of the package actually
		// need to be exported for the compiler.
		//
		// An example would be a package having an exported struct type
		// that has a member variable of some unexported type:
		//
		// As declaring variables of the exported struct type is allowed
		// outside of the package, the compiler needs to know the size
		// of the struct.
		//
		// To be clear; exporting *all* types is a superset of the types
		// that must be exported.
		x.write("\ttype @\"\".%s ", obj.Name())
		x.exportName(obj.Type().Underlying())
		x.write("\n")
		if u, ok := obj.Type().(*types.Named); ok {
			for i := 0; i < u.NumMethods(); i++ {
				m := u.Method(i)
				x.exportObject(m)
			}
		}
	default:
		panic(fmt.Sprintf("UNHANDLED %T", t))
	}
}