// Copyright 2019, 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 cmp

import 

// valueNode represents a single node within a report, which is a
// structured representation of the value tree, containing information
// regarding which nodes are equal or not.
type valueNode struct {
	parent *valueNode

	Type   reflect.Type
	ValueX reflect.Value
	ValueY reflect.Value

	// NumSame is the number of leaf nodes that are equal.
	// All descendants are equal only if NumDiff is 0.
	NumSame int
	// NumDiff is the number of leaf nodes that are not equal.
	NumDiff int
	// NumIgnored is the number of leaf nodes that are ignored.
	NumIgnored int
	// NumCompared is the number of leaf nodes that were compared
	// using an Equal method or Comparer function.
	NumCompared int
	// NumTransformed is the number of non-leaf nodes that were transformed.
	NumTransformed int
	// NumChildren is the number of transitive descendants of this node.
	// This counts from zero; thus, leaf nodes have no descendants.
	NumChildren int
	// MaxDepth is the maximum depth of the tree. This counts from zero;
	// thus, leaf nodes have a depth of zero.
	MaxDepth int

	// Records is a list of struct fields, slice elements, or map entries.
	Records []reportRecord // If populated, implies Value is not populated

	// Value is the result of a transformation, pointer indirect, of
	// type assertion.
	Value *valueNode // If populated, implies Records is not populated

	// TransformerName is the name of the transformer.
	TransformerName string // If non-empty, implies Value is populated
}
type reportRecord struct {
	Key   reflect.Value // Invalid for slice element
	Value *valueNode
}

func ( *valueNode) ( PathStep) ( *valueNode) {
	,  := .Values()
	 = &valueNode{parent: , Type: .Type(), ValueX: , ValueY: }
	switch s := .(type) {
	case StructField:
		assert(.Value == nil)
		.Records = append(.Records, reportRecord{Key: reflect.ValueOf(.Name()), Value: })
	case SliceIndex:
		assert(.Value == nil)
		.Records = append(.Records, reportRecord{Value: })
	case MapIndex:
		assert(.Value == nil)
		.Records = append(.Records, reportRecord{Key: .Key(), Value: })
	case Indirect:
		assert(.Value == nil && .Records == nil)
		.Value = 
	case TypeAssertion:
		assert(.Value == nil && .Records == nil)
		.Value = 
	case Transform:
		assert(.Value == nil && .Records == nil)
		.Value = 
		.TransformerName = .Name()
		.NumTransformed++
	default:
		assert( == nil) // Must be the root step
	}
	return 
}

func ( *valueNode) ( Result) {
	assert(.MaxDepth == 0) // May only be called on leaf nodes

	if .ByIgnore() {
		.NumIgnored++
	} else {
		if .Equal() {
			.NumSame++
		} else {
			.NumDiff++
		}
	}
	assert(.NumSame+.NumDiff+.NumIgnored == 1)

	if .ByMethod() {
		.NumCompared++
	}
	if .ByFunc() {
		.NumCompared++
	}
	assert(.NumCompared <= 1)
}

func ( *valueNode) () ( *valueNode) {
	if .parent == nil {
		return nil
	}
	 = .parent
	.NumSame += .NumSame
	.NumDiff += .NumDiff
	.NumIgnored += .NumIgnored
	.NumCompared += .NumCompared
	.NumTransformed += .NumTransformed
	.NumChildren += .NumChildren + 1
	if .MaxDepth < .MaxDepth+1 {
		.MaxDepth = .MaxDepth + 1
	}
	return 
}