function update( state, engine, summary ) {
	var parts;
	var path;
	var skey;
	var dkey;
	var acc;
	var oe;
	var os;
	var v;
	var t;
	var i;
	var j;

	// Walk the field paths to update accumulator state...
	for ( i = 0; i < fields.length; i++ ) {
		oe = engine;
		os = state;

		// Get the state path:
		path = fields[ i ][ 0 ].split( '.' );

		// Get the accumulator and its corresponding state leaf:
		for ( j = 0; j < path.length-1; j++ ) {
			skey = path[ j ];
			oe = oe[ skey ];
			os = os[ skey ];
		}
		skey = path[ j ];
		acc = oe[ skey ];

		// Get the data path:
		path = fields[ i ][ 1 ].split( '.' );

		// Walk the data path while performing any accumulations in order to resolve the update value:
		v = summary;
		for ( j = 0; j < path.length-1; j++ ) {
			dkey = path[ j ];

			// Check if we need to "pluck" values from an array:
			if ( isArray( v ) ) {
				parts = RE_ARRAY.exec( dkey );
				if ( parts ) {
					// E.g., key path: function.[data].variable.[data].name.length
					j += 1;
					v = pluck( v, parts[ 1 ], popts );

					// We assume that, at this point, we have an array of arrays. In order to get the next property value, we need to flatten the array.
					v = flattenArray( v, fopts );
				}
				v = pluck( v, path[ j ], popts );
			} else {
				parts = RE_ARRAY.exec( dkey );
				if ( parts ) {
					if ( RE_CONDITIONAL_VALUE.test( path[ j+1 ] ) ) {
						// E.g., key path: comments.[data].{length,type='block'}
						v = v[ parts[ 1 ] ];
					} else {
						// E.g., key path: function.[data].count
						j += 1;
						v = pluck( v[ parts[1] ], path[ j ], popts );
					}
				} else {
					// E.g., key path: function.count
					v = v[ dkey ];
				}
			}
		}
		dkey = path[ j ];

		// Check if we need to perform a reduction:
		if ( isArray( v ) ) {
			if ( v.length === 0 ) {
				// If the array is empty, no data to provide to the accumulator...
				continue;
			}
			if ( dkey === void 0 ) {
				// Update the accumulator for each array value (e.g., key path: function.[data].length):
				for ( j = 0; j < v.length; j++ ) {
					acc( v[ j ] );
				}
			} else {
				parts = RE_VALUE.exec( dkey );
				if ( parts ) {
					// Track the frequency of some observation; e.g., a particular key value (e.g., key path: function.[data].type.<'declaration'>):
					t = evil( parts[ 1 ] );
					for ( j = 0; j < v.length; j++ ) {
						if ( v[ j ] === t ) {
							acc( 1 );
						} else {
							acc( 0 );
						}
					}
				} else {
					parts = RE_CONDITIONAL_VALUE.exec( dkey );
					if ( parts ) {
						// Subject to a particular key-value realization, extract a property value from each array element and update the accumulator (e.g., comments.[data].{length,jsdoc=true}):
						t = evil( parts[ 3 ] );
						for ( j = 0; j < v.length; j++ ) {
							if ( v[j][ parts[2] ] === t ) {
								acc( v[j][ parts[1] ] );
							}
						}
					} else {
						// Update the accumulator by extracting a property value from each array element (e.g., function.[data].name.length):
						for ( j = 0; j < v.length; j++ ) {
							acc( v[ j ][ dkey ] );
						}
					}
				}
			}
		} else {
			// This is a "program-wide" value, and, thus, suitable to provide to the accumulator, even if zero (e.g., key path: function.count):
			acc( v[ dkey ] );
		}
		// Update the state:
		os[ skey ] = acc();
	}
	return state;
}
Updates accumulator state.

## Notes

-   Summary field paths are assumed to obey the following conventions:

    -   `a.b.c`: walk an object path defined by the keys `a`, `b`, and `c`. This convention is oriented toward program-wide measures, such as total line count, SLOC, LLOC, etc.
    -   `a.[b].c`: walk an object path where the value assigned at location `a.b` is an object array, over which we should "pluck" the values at key `c`. The plucked values should then be individually fed into an accumulator. This convention is oriented toward individual construct instances within a program, such as the SLOC for each `for` loop or the number of parameters for each function declaration.
    -   `a.[b].c.d`: walk an object path where the value assigned at location `a.b` is an object array, over which we should "pluck" the values at key `c`. For each plucked value, individually feed the value at key `d` into an accumulator. This convention is oriented toward individual construct instances within a program, such as variable name lengths within individual function declarations.
    -   `a.[b].c.<v>`: walk an object path where the value assigned at location `a.b` is an object array, over which we should "pluck" the values at key `c`. For each plucked value, if the value equals `v`, feed `1` to the accumulator and `0` otherwise. This convention is oriented toward individual construct instances within a program, such as determining relative frequencies for particular function types (declaration or expression).
    -   `a.[b].{c,d=v}`: walk an object path where the value assigned at location `a.b` is an object array, over which we should "pluck" the values at key `c` subject to the value at key `d` equaling `v`. For each plucked value, individually feed the value into an accumulator. This convention is oriented toward individual construct instances within a program, such as accumulating the character length of individual block comments, conditioned on the block comment being a JSDoc comment.
    -   `a.[b].c.[d].e`: walk an object path where the value assigned at a location `a.b` is an object array, over which we should "pluck" the values at key `c`. The plucked values are objects having a property `d` which is also an object array. This leaves an array of arrays, which must be flattened in order to extract the desired values at key `e`. Hence, the sequence of operations is to pluck, flatten, pluck, and extract. The extracted values are then fed separately into an accumulator. This convention is oriented toward accessing individual construct instances nested within a particular context. For example, variable name lengths within individual function instances.

-   Needless to say, the articulation of field paths makes considerable assumptions regarding program summary structure. As such, this algorithm should not be considered sufficiently general purpose and most likely would need to be refashioned should upstream changes be made in terms of result layout.

@private
@param {Object} state - accumulator state
@param {Object} engine - accumulator engine
@param {Object} summary - program summary
@returns {Object} accumulator state