Reorder logic to be consistent (#107)

Reorder logic to consistently handle steps in the order of:
	StructField, SliceIndex, MapIndex, Indirect, TypeAssertion
diff --git a/cmp/compare.go b/cmp/compare.go
index 30196a4..7d172ba 100644
--- a/cmp/compare.go
+++ b/cmp/compare.go
@@ -240,6 +240,21 @@
 	case reflect.Func:
 		s.report(vx.IsNil() && vy.IsNil(), vx, vy)
 		return
+	case reflect.Struct:
+		s.compareStruct(vx, vy, t)
+		return
+	case reflect.Slice:
+		if vx.IsNil() || vy.IsNil() {
+			s.report(vx.IsNil() && vy.IsNil(), vx, vy)
+			return
+		}
+		fallthrough
+	case reflect.Array:
+		s.compareSlice(vx, vy, t)
+		return
+	case reflect.Map:
+		s.compareMap(vx, vy, t)
+		return
 	case reflect.Ptr:
 		if vx.IsNil() || vy.IsNil() {
 			s.report(vx.IsNil() && vy.IsNil(), vx, vy)
@@ -262,21 +277,6 @@
 		defer s.curPath.pop()
 		s.compareAny(vx.Elem(), vy.Elem())
 		return
-	case reflect.Slice:
-		if vx.IsNil() || vy.IsNil() {
-			s.report(vx.IsNil() && vy.IsNil(), vx, vy)
-			return
-		}
-		fallthrough
-	case reflect.Array:
-		s.compareArray(vx, vy, t)
-		return
-	case reflect.Map:
-		s.compareMap(vx, vy, t)
-		return
-	case reflect.Struct:
-		s.compareStruct(vx, vy, t)
-		return
 	default:
 		panic(fmt.Sprintf("%v kind not handled", t.Kind()))
 	}
@@ -393,7 +393,42 @@
 	return v
 }
 
-func (s *state) compareArray(vx, vy reflect.Value, t reflect.Type) {
+func (s *state) compareStruct(vx, vy reflect.Value, t reflect.Type) {
+	var vax, vay reflect.Value // Addressable versions of vx and vy
+
+	step := &structField{}
+	s.curPath.push(step)
+	defer s.curPath.pop()
+	for i := 0; i < t.NumField(); i++ {
+		vvx := vx.Field(i)
+		vvy := vy.Field(i)
+		step.typ = t.Field(i).Type
+		step.name = t.Field(i).Name
+		step.idx = i
+		step.unexported = !isExported(step.name)
+		if step.unexported {
+			if step.name == "_" {
+				continue
+			}
+			// Defer checking of unexported fields until later to give an
+			// Ignore a chance to ignore the field.
+			if !vax.IsValid() || !vay.IsValid() {
+				// For unsafeRetrieveField to work, the parent struct must
+				// be addressable. Create a new copy of the values if
+				// necessary to make them addressable.
+				vax = makeAddressable(vx)
+				vay = makeAddressable(vy)
+			}
+			step.force = s.exporters[t]
+			step.pvx = vax
+			step.pvy = vay
+			step.field = t.Field(i)
+		}
+		s.compareAny(vvx, vvy)
+	}
+}
+
+func (s *state) compareSlice(vx, vy reflect.Value, t reflect.Type) {
 	step := &sliceIndex{pathStep{t.Elem()}, 0, 0}
 	s.curPath.push(step)
 
@@ -477,41 +512,6 @@
 	}
 }
 
-func (s *state) compareStruct(vx, vy reflect.Value, t reflect.Type) {
-	var vax, vay reflect.Value // Addressable versions of vx and vy
-
-	step := &structField{}
-	s.curPath.push(step)
-	defer s.curPath.pop()
-	for i := 0; i < t.NumField(); i++ {
-		vvx := vx.Field(i)
-		vvy := vy.Field(i)
-		step.typ = t.Field(i).Type
-		step.name = t.Field(i).Name
-		step.idx = i
-		step.unexported = !isExported(step.name)
-		if step.unexported {
-			if step.name == "_" {
-				continue
-			}
-			// Defer checking of unexported fields until later to give an
-			// Ignore a chance to ignore the field.
-			if !vax.IsValid() || !vay.IsValid() {
-				// For unsafeRetrieveField to work, the parent struct must
-				// be addressable. Create a new copy of the values if
-				// necessary to make them addressable.
-				vax = makeAddressable(vx)
-				vay = makeAddressable(vy)
-			}
-			step.force = s.exporters[t]
-			step.pvx = vax
-			step.pvy = vay
-			step.field = t.Field(i)
-		}
-		s.compareAny(vvx, vvy)
-	}
-}
-
 // report records the result of a single comparison.
 // It also calls Report if any reporter is registered.
 func (s *state) report(eq bool, vx, vy reflect.Value) {
diff --git a/cmp/path.go b/cmp/path.go
index 24a5657..49b622b 100644
--- a/cmp/path.go
+++ b/cmp/path.go
@@ -33,6 +33,13 @@
 		isPathStep()
 	}
 
+	// StructField represents a struct field access on a field called Name.
+	StructField interface {
+		PathStep
+		Name() string
+		Index() int
+		isStructField()
+	}
 	// SliceIndex is an index operation on a slice or array at some index Key.
 	SliceIndex interface {
 		PathStep
@@ -57,23 +64,16 @@
 		Key() reflect.Value
 		isMapIndex()
 	}
-	// TypeAssertion represents a type assertion on an interface.
-	TypeAssertion interface {
-		PathStep
-		isTypeAssertion()
-	}
-	// StructField represents a struct field access on a field called Name.
-	StructField interface {
-		PathStep
-		Name() string
-		Index() int
-		isStructField()
-	}
 	// Indirect represents pointer indirection on the parent type.
 	Indirect interface {
 		PathStep
 		isIndirect()
 	}
+	// TypeAssertion represents a type assertion on an interface.
+	TypeAssertion interface {
+		PathStep
+		isTypeAssertion()
+	}
 	// Transform is a transformation from the parent type to the current type.
 	Transform interface {
 		PathStep
@@ -188,17 +188,6 @@
 		typ reflect.Type
 	}
 
-	sliceIndex struct {
-		pathStep
-		xkey, ykey int
-	}
-	mapIndex struct {
-		pathStep
-		key reflect.Value
-	}
-	typeAssertion struct {
-		pathStep
-	}
 	structField struct {
 		pathStep
 		name string
@@ -211,9 +200,20 @@
 		pvx, pvy   reflect.Value       // Parent values
 		field      reflect.StructField // Field information
 	}
+	sliceIndex struct {
+		pathStep
+		xkey, ykey int
+	}
+	mapIndex struct {
+		pathStep
+		key reflect.Value
+	}
 	indirect struct {
 		pathStep
 	}
+	typeAssertion struct {
+		pathStep
+	}
 	transform struct {
 		pathStep
 		trans *transformer
@@ -231,6 +231,12 @@
 	}
 	return fmt.Sprintf("{%s}", s)
 }
+func (ps pathStep) isPathStep() {}
+
+func (sf structField) String() string { return fmt.Sprintf(".%s", sf.name) }
+func (sf structField) Name() string   { return sf.name }
+func (sf structField) Index() int     { return sf.idx }
+func (sf structField) isStructField() {}
 
 func (si sliceIndex) String() string {
 	switch {
@@ -247,12 +253,6 @@
 		return fmt.Sprintf("[%d->%d]", si.xkey, si.ykey)
 	}
 }
-func (mi mapIndex) String() string      { return fmt.Sprintf("[%#v]", mi.key) }
-func (ta typeAssertion) String() string { return fmt.Sprintf(".(%v)", ta.typ) }
-func (sf structField) String() string   { return fmt.Sprintf(".%s", sf.name) }
-func (in indirect) String() string      { return "*" }
-func (tf transform) String() string     { return fmt.Sprintf("%s()", tf.trans.name) }
-
 func (si sliceIndex) Key() int {
 	if si.xkey != si.ykey {
 		return -1
@@ -260,35 +260,31 @@
 	return si.xkey
 }
 func (si sliceIndex) SplitKeys() (x, y int) { return si.xkey, si.ykey }
-func (mi mapIndex) Key() reflect.Value      { return mi.key }
-func (sf structField) Name() string         { return sf.name }
-func (sf structField) Index() int           { return sf.idx }
-func (tf transform) Name() string           { return tf.trans.name }
-func (tf transform) Func() reflect.Value    { return tf.trans.fnc }
-func (tf transform) Option() Option         { return tf.trans }
+func (si sliceIndex) isSliceIndex()         {}
 
-func (pathStep) isPathStep()           {}
-func (sliceIndex) isSliceIndex()       {}
-func (mapIndex) isMapIndex()           {}
-func (typeAssertion) isTypeAssertion() {}
-func (structField) isStructField()     {}
-func (indirect) isIndirect()           {}
-func (transform) isTransform()         {}
+func (mi mapIndex) String() string     { return fmt.Sprintf("[%#v]", mi.key) }
+func (mi mapIndex) Key() reflect.Value { return mi.key }
+func (mi mapIndex) isMapIndex()        {}
+
+func (in indirect) String() string { return "*" }
+func (in indirect) isIndirect()    {}
+
+func (ta typeAssertion) String() string   { return fmt.Sprintf(".(%v)", ta.typ) }
+func (ta typeAssertion) isTypeAssertion() {}
+
+func (tf transform) String() string      { return fmt.Sprintf("%s()", tf.trans.name) }
+func (tf transform) Name() string        { return tf.trans.name }
+func (tf transform) Func() reflect.Value { return tf.trans.fnc }
+func (tf transform) Option() Option      { return tf.trans }
+func (tf transform) isTransform()        {}
 
 var (
-	_ SliceIndex    = sliceIndex{}
-	_ MapIndex      = mapIndex{}
-	_ TypeAssertion = typeAssertion{}
-	_ StructField   = structField{}
-	_ Indirect      = indirect{}
-	_ Transform     = transform{}
-
-	_ PathStep = sliceIndex{}
-	_ PathStep = mapIndex{}
-	_ PathStep = typeAssertion{}
-	_ PathStep = structField{}
-	_ PathStep = indirect{}
-	_ PathStep = transform{}
+	_ PathStep = StructField(structField{})
+	_ PathStep = SliceIndex(sliceIndex{})
+	_ PathStep = MapIndex(mapIndex{})
+	_ PathStep = Indirect(indirect{})
+	_ PathStep = TypeAssertion(typeAssertion{})
+	_ PathStep = Transform(transform{})
 )
 
 // isExported reports whether the identifier is exported.