function traverse( node ) {
	var properties;
	var fname;
	var i;
	if ( !node ) {
		return false;
	}
	if ( node.type === 'Literal' || node.type === 'Identifier' || ( node.type === 'UnaryExpression' && node.operator !== 'delete' ) ) {
		return true;
	}
	if ( node.type === 'BinaryExpression' ) {
		if ( traverse( node.left ) && traverse( node.right ) ) {
			return true;
		}
	} else if ( node.type === 'MemberExpression' ) {
		if ( traverse( node.object ) ) {
			return true;
		}
	} else if ( node.type === 'ExpressionStatement' ) {
		if ( traverse( node.expression ) ) {
			return true;
		}
	} else if ( node.type === 'CallExpression' ) {
		fname = getFunctionName( node.callee );
		if ( tempDB[fname] && tempDB[fname].isPure ) {
			// Examine each function argument for potential side-effects...
			for ( i = 0; i < node.arguments.length; i++ ) {
				if ( !traverse( node.arguments[ i ] ) ) {
					return false;
				}
			}
			return true;
		}
	} else if ( node.type === 'ArrayExpression' ) {
		for ( i = 0; i < node.elements.length; i++ ) {
			if ( !traverse( node.elements[ i ] ) ) {
				return false;
			}
		}
		return true;
	} else if ( node.type === 'ObjectExpression' ) {
		for ( i = 0; i < node.properties.length; i++ ) {
			properties = node.properties;
			if ( !traverse( properties[ i ].key ) || !traverse( properties[ i ].value ) ) {
				return false;
			}
		}
		return true;
	}
	return false;
}
Recursively traverses the node to determine whether the node is side-effect-free.

@private
@param {Object} node - ast node
@returns {boolean} boolean indicating whether the node is side-effect-free