function walkAST(node, parent) {
			if (!node)
				return;
			for (var key in node) {
				if (key === 'range')
					continue;
				var value = node[key];
				if (Array.isArray(value)) {
					for (var i = 0, l = value.length; i < l; i++)
						walkAST(value[i], node);
				} else if (value && typeof value === 'object') {
					// We cannot use Base.isPlainObject() for these since
					// Acorn.js uses its own internal prototypes now.
					walkAST(value, node);
				}
			}
			switch (node && node.type) {
			case 'UnaryExpression': // -a
				if (node.operator in unaryOperators
						&& node.argument.type !== 'Literal') {
					var arg = getCode(node.argument);
					replaceCode(node, '$_("' + node.operator + '", '
							+ arg + ')');
				}
				break;
			case 'BinaryExpression': // a + b, a - b, a / b, a * b, a == b, ...				
				if (node.operator in binaryOperators
						&& node.left.type !== 'Literal') {
					var left = getCode(node.left),
						right = getCode(node.right);
					replaceCode(node, '_$_(' + left + ', "' + node.operator
							+ '", ' + right + ')');
				}
				break;
			case 'UpdateExpression': // a++, a--
			case 'AssignmentExpression': /// a += b, a -= b
				if (!(parent && (
						// Filter out for statements to allow loop increments
						// to perform well
						parent.type === 'ForStatement'
						// We need to filter out parents that are comparison
						// operators, e.g. for situations like if (++i < 1),
						// as we can't replace that with if (_$_(i, "+", 1) < 1)
						// Match any operator beginning with =, !, < and >.
						|| parent.type === 'BinaryExpression'
							&& /^[=!<>]/.test(parent.operator)
						// array[i++] is a MemberExpression with computed = true
						// We can't replace that with array[_$_(i, "+", 1)].
						|| parent.type === 'MemberExpression'
							&& parent.computed))) {
					if (node.type === 'UpdateExpression') {
						if (!node.prefix) {
							var arg = getCode(node.argument);
							replaceCode(node, arg + ' = _$_(' + arg + ', "'
									+ node.operator[0] + '", 1)');
						}
					} else { // AssignmentExpression
						if (/^.=$/.test(node.operator)
								&& node.left.type !== 'Literal') {
							var left = getCode(node.left),
								right = getCode(node.right);
							replaceCode(node, left + ' = _$_(' + left + ', "'
									+ node.operator[0] + '", ' + right + ')');
						}
					}
				}
				break;
			}
		}
// Recursively walks the AST and replaces the code of certain nodes
Recursively walks the AST and replaces the code of certain nodes
Recursively walks the AST and replaces the code of certain nodes
function walkAST(node, parent) {
			if (!node)
				return;
			for (var key in node) {
				if (key === 'range')
					continue;
				var value = node[key];
				if (Array.isArray(value)) {
					for (var i = 0, l = value.length; i < l; i++)
						walkAST(value[i], node);
				} else if (value && typeof value === 'object') {
					walkAST(value, node);
				}
			}
			switch (node && node.type) {
			case 'UnaryExpression': 
				if (node.operator in unaryOperators
						&& node.argument.type !== 'Literal') {
					var arg = getCode(node.argument);
					replaceCode(node, '$_("' + node.operator + '", '
							+ arg + ')');
				}
				break;
			case 'BinaryExpression': 
				if (node.operator in binaryOperators
						&& node.left.type !== 'Literal') {
					var left = getCode(node.left),
						right = getCode(node.right);
					replaceCode(node, '_$_(' + left + ', "' + node.operator
							+ '", ' + right + ')');
				}
				break;
			case 'UpdateExpression': 
			case 'AssignmentExpression': 
				if (!(parent && (
						parent.type === 'ForStatement'
						|| parent.type === 'BinaryExpression'
							&& /^[=!<>]/.test(parent.operator)
						|| parent.type === 'MemberExpression'
							&& parent.computed))) {
					if (node.type === 'UpdateExpression') {
						if (!node.prefix) {
							var arg = getCode(node.argument);
							replaceCode(node, arg + ' = _$_(' + arg + ', "'
									+ node.operator[0] + '", 1)');
						}
					} else { 
						if (/^.=$/.test(node.operator)
								&& node.left.type !== 'Literal') {
							var left = getCode(node.left),
								right = getCode(node.right);
							replaceCode(node, left + ' = _$_(' + left + ', "'
									+ node.operator[0] + '", ' + right + ')');
						}
					}
				}
				break;
			}
		}
function walkAST ( node , parent ) { if ( ! node ) return ; for ( var key in node ) { if ( key === 'range' ) continue ; var value = node [ key ] ; if ( Array . isArray ( value ) ) { for ( var i = 0 , l = value . length ; i < l ; i ++ ) walkAST ( value [ i ] , node ) ; } else if ( value && typeof value === 'object' ) { walkAST ( value , node ) ; } } switch ( node && node . type ) { case 'UnaryExpression' : if ( node . operator in unaryOperators && node . argument . type !== 'Literal' ) { var arg = getCode ( node . argument ) ; replaceCode ( node , '$_("' + node . operator + '", ' + arg + ')' ) ; } break ; case 'BinaryExpression' : if ( node . operator in binaryOperators && node . left . type !== 'Literal' ) { var left = getCode ( node . left ) , right = getCode ( node . right ) ; replaceCode ( node , '_$_(' + left + ', "' + node . operator + '", ' + right + ')' ) ; } break ; case 'UpdateExpression' : case 'AssignmentExpression' : if ( ! ( parent && ( parent . type === 'ForStatement' || parent . type === 'BinaryExpression' && / ^[=!<>] / . test ( parent . operator ) || parent . type === 'MemberExpression' && parent . computed ) ) ) { if ( node . type === 'UpdateExpression' ) { if ( ! node . prefix ) { var arg = getCode ( node . argument ) ; replaceCode ( node , arg + ' = _$_(' + arg + ', "' + node . operator [ 0 ] + '", 1)' ) ; } } else { if ( / ^.=$ / . test ( node . operator ) && node . left . type !== 'Literal' ) { var left = getCode ( node . left ) , right = getCode ( node . right ) ; replaceCode ( node , left + ' = _$_(' + left + ', "' + node . operator [ 0 ] + '", ' + right + ')' ) ; } } } break ; } }
Recursively walks the AST and replaces the code of certain nodes
Recursively walks the AST and replaces the code of certain nodes
// We cannot use Base.isPlainObject() for these since // Acorn.js uses its own internal prototypes now. // -a // a + b, a - b, a / b, a * b, a == b, ...				 // a++, a-- /// a += b, a -= b // Filter out for statements to allow loop increments // to perform well // We need to filter out parents that are comparison // operators, e.g. for situations like if (++i < 1), // as we can't replace that with if (_$_(i, "+", 1) < 1) // Match any operator beginning with =, !, < and >. // array[i++] is a MemberExpression with computed = true // We can't replace that with array[_$_(i, "+", 1)]. // AssignmentExpression