physical-lock: Change vdl go codegen to emit __VDLInit funcs.

Fixes a subtle init-ordering issue in vdl-generated go code.  The
basic problem looks something like this; there are many variants
to this problem, this is just one simple example:

// User's file a.go
package foo
import "v.io/v23/vdl"
var myType := vdl.TypeOf(FooType{})

// Generated file foo.vdl.go
package foo
import "v.io/v23/vdl"
func init() {
vdl.RegisterNative(FooToNative, FooFromNative)
}

The problem is that the vdl.RegisterNative call must occur before
the vdl.TypeOf call, so that the vdl package knows about native
types, and can analyze the type correctly.  But init funcs are
always processed after all package-level variables have been
initialized, so we get the wrong order above.

We fix that by moving all initialization into a generated
__VDLInit func, with a trick to turn it into a var
initialization.  Note that we still haven't fixed the above
example, since the package-level vars in a.go are typically
processed before foo.vdl.go.  In the rare case where this
happens, the user can add a call to __VDLInit in a var
initializer early in their a.go file.

Similar problems existed with vom.RawBytesOf, and the
manually-generated types we were storing in package-level vars.

The new strategy is to put all ordering-dependent init logic in
__VDLInit, and to ensure that the order that we call things
within the function is correct.  We also sort types, consts and
interfaces in the compiler as best we can.  Note that sorting
types isn't strictly required (or meaningful), since we allow
cyclic types.  But it still might be nice for some generated
languages.

There are further cleanups possible; we can probably add
error-checking more methodically for cases like above where the
user needs to add a call to __VDLInit, and we should replace the
long hex hash for generated type names to a simple counter.  But
that'll occur in a separate CL; this is the more important one.

MultiPart: 5/6

Change-Id: I8c649c9f6f7cdc54d72d5096348d3f6c4452ae58
diff --git a/go/src/v.io/x/lock/lock.vdl.go b/go/src/v.io/x/lock/lock.vdl.go
index f80667a..f5c77e0 100644
--- a/go/src/v.io/x/lock/lock.vdl.go
+++ b/go/src/v.io/x/lock/lock.vdl.go
@@ -28,6 +28,11 @@
 	"v.io/v23/vdl/vdlconv"
 )
 
+var _ = __VDLInit() // Must be first; see __VDLInit comments for details.
+
+//////////////////////////////////////////////////
+// Type definitions
+
 // LockStatus  indicates the status (locked or unlocked) of a lock.
 type LockStatus int32
 
@@ -37,7 +42,7 @@
 }
 
 func (m *LockStatus) FillVDLTarget(t vdl.Target, tt *vdl.Type) error {
-	if err := t.FromInt(int64((*m)), __VDLType_v_io_x_lock_LockStatus); err != nil {
+	if err := t.FromInt(int64((*m)), tt); err != nil {
 		return err
 	}
 	return nil
@@ -93,19 +98,15 @@
 	return nil
 }
 
-func init() {
-	vdl.Register((*LockStatus)(nil))
-}
-
-var __VDLType_v_io_x_lock_LockStatus *vdl.Type = vdl.TypeOf(LockStatus(0))
-
-func __VDLEnsureNativeBuilt() {
-}
+//////////////////////////////////////////////////
+// Const definitions
 
 const Locked = LockStatus(0)
-
 const Unlocked = LockStatus(1)
 
+//////////////////////////////////////////////////
+// Interface definitions
+
 // UnclaimedLockClientMethods is the client interface
 // containing UnclaimedLock methods.
 //
@@ -382,3 +383,29 @@
 		},
 	},
 }
+
+var __VDLInitCalled bool
+
+// __VDLInit performs vdl initialization.  It is safe to call multiple times.
+// If you have an init ordering issue, just insert the following line verbatim
+// into your source files in this package, right after the "package foo" clause:
+//
+//    var _ = __VDLInit()
+//
+// The purpose of this function is to ensure that vdl initialization occurs in
+// the right order, and very early in the init sequence.  In particular, vdl
+// registration and package variable initialization needs to occur before
+// functions like vdl.TypeOf will work properly.
+//
+// This function returns a dummy value, so that it can be used to initialize the
+// first var in the file, to take advantage of Go's defined init order.
+func __VDLInit() struct{} {
+	if __VDLInitCalled {
+		return struct{}{}
+	}
+
+	// Register types.
+	vdl.Register((*LockStatus)(nil))
+
+	return struct{}{}
+}
diff --git a/go/src/v.io/x/lock/lock/main.vdl.go b/go/src/v.io/x/lock/lock/main.vdl.go
index bd17b5d..b529770 100644
--- a/go/src/v.io/x/lock/lock/main.vdl.go
+++ b/go/src/v.io/x/lock/lock/main.vdl.go
@@ -13,18 +13,41 @@
 	"v.io/v23/verror"
 )
 
-func __VDLEnsureNativeBuilt() {
-}
+var _ = __VDLInit() // Must be first; see __VDLInit comments for details.
 
+//////////////////////////////////////////////////
+// Error definitions
 var (
 	ErrKeyRejected = verror.Register("v.io/x/lock/lock.KeyRejected", verror.NoRetry, "{1:}{2:} receiver rejected key {3} for lock {4}")
 )
 
-func init() {
-	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrKeyRejected.ID), "{1:}{2:} receiver rejected key {3} for lock {4}")
-}
-
 // NewErrKeyRejected returns an error with the ErrKeyRejected ID.
 func NewErrKeyRejected(ctx *context.T, key string, lock string) error {
 	return verror.New(ErrKeyRejected, ctx, key, lock)
 }
+
+var __VDLInitCalled bool
+
+// __VDLInit performs vdl initialization.  It is safe to call multiple times.
+// If you have an init ordering issue, just insert the following line verbatim
+// into your source files in this package, right after the "package foo" clause:
+//
+//    var _ = __VDLInit()
+//
+// The purpose of this function is to ensure that vdl initialization occurs in
+// the right order, and very early in the init sequence.  In particular, vdl
+// registration and package variable initialization needs to occur before
+// functions like vdl.TypeOf will work properly.
+//
+// This function returns a dummy value, so that it can be used to initialize the
+// first var in the file, to take advantage of Go's defined init order.
+func __VDLInit() struct{} {
+	if __VDLInitCalled {
+		return struct{}{}
+	}
+
+	// Set error format strings.
+	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrKeyRejected.ID), "{1:}{2:} receiver rejected key {3} for lock {4}")
+
+	return struct{}{}
+}
diff --git a/go/src/v.io/x/lock/lockd/main.vdl.go b/go/src/v.io/x/lock/lockd/main.vdl.go
index 030de5b..04f63ec 100644
--- a/go/src/v.io/x/lock/lockd/main.vdl.go
+++ b/go/src/v.io/x/lock/lockd/main.vdl.go
@@ -13,19 +13,15 @@
 	"v.io/v23/verror"
 )
 
-func __VDLEnsureNativeBuilt() {
-}
+var _ = __VDLInit() // Must be first; see __VDLInit comments for details.
 
+//////////////////////////////////////////////////
+// Error definitions
 var (
 	ErrLockAlreadyClaimed = verror.Register("v.io/x/lock/lockd.LockAlreadyClaimed", verror.NoRetry, "{1:}{2:} lock has already been claimed")
 	ErrInvalidLockName    = verror.Register("v.io/x/lock/lockd.InvalidLockName", verror.NoRetry, "{1:}{2:} invalid lock name ({3}: cannot contain {4})")
 )
 
-func init() {
-	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrLockAlreadyClaimed.ID), "{1:}{2:} lock has already been claimed")
-	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrInvalidLockName.ID), "{1:}{2:} invalid lock name ({3}: cannot contain {4})")
-}
-
 // NewErrLockAlreadyClaimed returns an error with the ErrLockAlreadyClaimed ID.
 func NewErrLockAlreadyClaimed(ctx *context.T) error {
 	return verror.New(ErrLockAlreadyClaimed, ctx)
@@ -35,3 +31,30 @@
 func NewErrInvalidLockName(ctx *context.T, name string, reason string) error {
 	return verror.New(ErrInvalidLockName, ctx, name, reason)
 }
+
+var __VDLInitCalled bool
+
+// __VDLInit performs vdl initialization.  It is safe to call multiple times.
+// If you have an init ordering issue, just insert the following line verbatim
+// into your source files in this package, right after the "package foo" clause:
+//
+//    var _ = __VDLInit()
+//
+// The purpose of this function is to ensure that vdl initialization occurs in
+// the right order, and very early in the init sequence.  In particular, vdl
+// registration and package variable initialization needs to occur before
+// functions like vdl.TypeOf will work properly.
+//
+// This function returns a dummy value, so that it can be used to initialize the
+// first var in the file, to take advantage of Go's defined init order.
+func __VDLInit() struct{} {
+	if __VDLInitCalled {
+		return struct{}{}
+	}
+
+	// Set error format strings.
+	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrLockAlreadyClaimed.ID), "{1:}{2:} lock has already been claimed")
+	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrInvalidLockName.ID), "{1:}{2:} invalid lock name ({3}: cannot contain {4})")
+
+	return struct{}{}
+}