Convert a function to a node or a group of nodes
184151
def set_nodes(self, func):
        """"""
        op_type = self.nnabla_function_type_to_onnx_optype.get(func.type)
        if op_type is None:
            raise ValueError(
                "function {} is currently not supported for ONNX conversion".format(func.type))
        if callable(op_type):
            return op_type(func)

        variables = self._net.variable
        input_types = self._input_types
        output_types = self._output_types
        broadcast_target = self._broadcast_target

        n = onnx.helper.make_node(
            op_type,
            func.input,
            func.output,
            name=func.name)
        nl = []
        if func.type == "Convolution":
            cp = func.convolution_param
            # Calculate the kernel_shape from input weight data.
            # Weight data should be the second input for convolution
            if len(func.input) < 2:
                raise ValueError(
                    "Weight input is missing for convolution {}"
                    .format(func.name))
            weight = func.input[1]
            weight_var = [v for v in variables if v.name == weight]
            if len(weight_var) != 1:
                raise ValueError(
                    "No weight input was found, or multiple weight inputs were found"
                    " for convolution {} where there should be only one."
                    .format(func.name))
            weight_shape = weight_var[0].shape
            # The base axis for weights is the next axis from the data's base axis
            weight_base = cp.base_axis + 1
            k = onnx.helper.make_attribute("kernel_shape",
                                           weight_shape.dim[weight_base:])
            d = onnx.helper.make_attribute("dilations", cp.dilation.dim)
            s = onnx.helper.make_attribute("strides", cp.stride.dim)
            p = onnx.helper.make_attribute("pads", cp.pad.dim[:] * 2)
            g = onnx.helper.make_attribute("group", cp.group)
            n.attribute.extend([k, d, s, p, g])
            nl.append(n)
        elif func.type == "GlobalAveragePooling":
            # We wipeout the node name to avoid a bug?
            # that occurs when we use a GlobalAveragePooling node with a name
            # "Conv" or "Pool" contained.
            # Caffe2 issue is here:
            # https://github.com/caffe2/caffe2/issues/1971
            # Because a GlobalAveragePooling operator does not contain a kernel, we get an error at the
            # following code if we have a specific name.
            # https://github.com/caffe2/caffe2/blob/master/caffe2/operators/conv_pool_op_base.h#L167
            # The above caffe2 code should be checking the node's operator name and not the node's name.
            n.name = ""
            nl.append(n)
        elif func.type == "Softmax":
            # Softmax on NNabla does softmax ONLY along the specified axis.
            # ONNX first squashes the input dimensions to 2D based on the specified axis,
            # and then calculates the Softmax.
            # Since these two slightly differ, we show a warning here.
            logger.warning(SOFTMAX_WARNING)
            attr = onnx.helper.make_attribute("axis", func.softmax_param.axis)
            n.attribute.extend([attr])
            nl.append(n)
        elif func.type == "Reshape":
            # Convert Reshape size to a constant
            rp = func.reshape_param
            x = func.input[0]
            c_out = x + "_shape"
            c = generate_constant(c_out, func.name + "_shape",
                                  TensorProto.INT32, [len(rp.shape.dim)],
                                  rp.shape.dim)
            nl.append(c)
            # Add resize target shape as the second input
            del n.input[:]
            n.input.extend([x, c_out])
            nl.append(n)
        elif func.type == "Transpose":
            tp = func.transpose_param
            p = onnx.helper.make_attribute("perm", tp.axes)
            n.attribute.extend([p])
            nl.append(n)
        elif func.type == "BatchMatmul":
            bmp = func.batch_matmul_param
            if bmp.transpose_a or bmp.transpose_b:
                raise ValueError(
                    "{} with transpose is not supported yet".format(func.type))
            nl.append(n)
        elif func.type == "LeakyReLU":
            lrp = func.leaky_relu_param
            a = onnx.helper.make_attribute("alpha", lrp.alpha)
            n.attribute.extend([a])
            nl.append(n)
        elif func.type == "ELU":
            ep = func.elu_param
            a = onnx.helper.make_attribute("alpha", ep.alpha)
            n.attribute.extend([a])
            nl.append(n)
        elif func.type == "LogicalNot":
            # Store the input/output tensor's name and convert it to boolean
            input_types[n.input[0]] = TensorProto.BOOL
            output_types[n.output[0]] = TensorProto.BOOL
            nl.append(n)
        elif func.type == "SELU":
            sp = func.selu_param
            a = onnx.helper.make_attribute("alpha", sp.alpha)
            g = onnx.helper.make_attribute("gamma", sp.scale)
            n.attribute.extend([a, g])
            nl.append(n)
        elif func.type == "Sum":
            sp = func.sum_param
            set_reduction_attrs(n, sp)
            nl.append(n)
        elif func.type == "Mean":
            mp = func.mean_param
            set_reduction_attrs(n, mp)
            nl.append(n)
        elif func.type == "Max":
            mp = func.max_param
            set_reduction_attrs(n, mp)
            nl.append(n)
        elif func.type == "Min":
            mp = func.min_param
            set_reduction_attrs(n, mp)
            nl.append(n)
        elif func.type == "Prod":
            pp = func.prod_param
            set_reduction_attrs(n, pp)
            nl.append(n)
        elif func.type == "BroadcastTo":
            # BroadcastTo conversion only works when the
            # broadcasted buffer is used as second input for the following:
            # Add, And, Div, Equal, Greater,
            # Less, Mul, Or, Pow, Sub, Xor
            bp = func.broadcast_to_param
            broadcast_target[func.output[0]] = (func.input[1], bp.axis)
            # we do not append node here because BroadcastTo should disappear
        elif func.type == "MinimumScalar":
            msp = func.minimum_scalar_param
            m = onnx.helper.make_attribute("max", msp.val)
            n.attribute.extend([m])
            nl.append(n)
        elif func.type == "MaximumScalar":
            msp = func.maximum_scalar_param
            m = onnx.helper.make_attribute("min", msp.val)
            n.attribute.extend([m])
            nl.append(n)
        elif func.type == "Pad":
            pp = func.pad_param
            mode_conv = {
                "constant": "constant",
                "replicate": "edge",
                "reflect": "reflect"
            }
            # separate pad values to match ONNX format
            # (S0,E0,S1,E1) => (S0,S1,E0,E1)
            dim = len(pp.pad_width) // 2
            # If we can get the dimension of the input buffer,
            # we get it here. If we cannot, we are assuming 4D input
            in_name = func.input[0]
            in_var = [v for v in variables if v.name == in_name]
            in_dim = 4
            if len(in_var) == 1 and len(in_var[0].shape.dim) > 0:
                # Found variable with valid shape.
                # If the shape dimension is zero, it means
                # that is an intermediate buffer so we can't get
                # the exact dimension at this point
                # (thus assuming 4D input).
                in_dim = len(in_var[0].shape.dim)
            elif len(in_var) > 1:
                raise ValueError("More than one buffer with"
                                 " the same buffer name found.")
            zero_dim_num = in_dim - dim
            it = iter(pp.pad_width)
            # We need to fill empty dimensions with zero padding
            # (at least this is what Caffe2 expects)
            starts = [0] * zero_dim_num
            ends = [0] * zero_dim_num
            for x in it:
                starts.append(x)
                ends.append(next(it))
            starts.extend(ends)
            pad = onnx.helper.make_attribute("pads", starts)
            m = onnx.helper.make_attribute("mode", mode_conv[pp.mode])
            v = onnx.helper.make_attribute("value", pp.constant_value)
            n.attribute.extend([pad, m, v])
            nl.append(n)
        else:
            # Simply append node to list
            nl.append(n)
        return nl
1285239
function templateNodeTransformation( $functionName, &$node,
                                         $tpl, &$parameters, $privateData )
    {
        // {while <condition> [sequence <sequence_array> as $<sequence_var>]}

        $tpl->WhileCounter++;
        $newNodes      = array();
        $nodePlacement = eZTemplateNodeTool::extractFunctionNodePlacement( $node );
        $uniqid        =  md5( $nodePlacement[2] ) . "_" . $tpl->WhileCounter;

        $loop = new eZTemplateCompiledLoop( eZTemplateWhileFunction::FUNCTION_NAME,
                                            $newNodes, $parameters, $nodePlacement, $uniqid,
                                            $node, $tpl, $privateData );


        $loop->initVars();

        // loop header
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "while ( 1 ) // while\n{" );
        $newNodes[] = eZTemplateNodeTool::createSpacingIncreaseNode();
        $newNodes[] = eZTemplateNodeTool::createVariableNode( false, $parameters['condition'], $nodePlacement, array( 'treat-value-as-non-object' => true ),
                                                              "while_cond" );
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "if ( ! \$while_cond ) break;\n" );

        $loop->processBody();

        // loop footer
        $newNodes[] = eZTemplateNodeTool::createSpacingDecreaseNode();
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "} // end of while\n" );
        $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( 'while_cond' );
        $loop->cleanup();

        return $newNodes;
    }
949864
def _get_func_nodes():
    """"""
    return [definition for definition in project_definitions.values()
            if isinstance(definition.node, ast.FunctionDef)]
1267516
def _group(tlist, cls, match,
           valid_prev=lambda t: True,
           valid_next=lambda t: True,
           post=None,
           extend=True,
           recurse=True
           ):
    """"""

    tidx_offset = 0
    pidx, prev_ = None, None
    for idx, token in enumerate(list(tlist)):
        tidx = idx - tidx_offset

        if token.is_whitespace:
            continue

        if recurse and token.is_group and not isinstance(token, cls):
            _group(token, cls, match, valid_prev, valid_next, post, extend)

        if match(token):
            nidx, next_ = tlist.token_next(tidx)
            if prev_ and valid_prev(prev_) and valid_next(next_):
                from_idx, to_idx = post(tlist, pidx, tidx, nidx)
                grp = tlist.group_tokens(cls, from_idx, to_idx, extend=extend)

                tidx_offset += to_idx - from_idx
                pidx, prev_ = from_idx, grp
                continue

        pidx, prev_ = tidx, token
1348856
def dfs_do_func_on_graph(node, func, *args, **kwargs):
    '''
    
    '''
    for _node in node.tree_iterator():
        func(_node, *args, **kwargs)
1309415
function findStmtNodes(nodeBody) {
  const nodes = [];
  const fnExpressions = utils.findNodes(nodeBody, 'ExpressionStatement');
  const returnStatement = utils.findNodes(nodeBody, 'ReturnStatement');

  if (fnExpressions.length !== 0) {
    fnExpressions.forEach((item) => {
      nodes.push(item);
    });
  }

  if (returnStatement.length !== 0) {
    returnStatement.forEach((item) => {
      nodes.push(item);
    });
  }

  return nodes;
}
878123
function traverse (node, options) {
  if (!node) {
    return ''
  }

  switch (node.type) {
    case 'unary_expr':
    case 'binary_expr':
      return handleExpr(node, options)
    case 'function':
      return handleFunction(node, options)
    case 'expr_list':
      return handleExprList(node, options)
    case 'column_ref':
      return handleColumn(node, options)
    case 'string':
    case 'number':
    case 'null':
    case 'bool':
      return handleValue(node, options)
    case 'timestamp':
      return handleTimestampValue(node, options)
    default:
      throw new Error('Unrecognized AST node: \n' + JSON.stringify(node, null, 2))
  }
}
527786
function _groupWith (makeValue) {
    return function (arrayLike, iteratee) {
        var result = {};
        var len = arrayLike.length;

        for (var i = 0, element, key; i < len; i++) {
            element = arrayLike[i];
            key = iteratee(element, i, arrayLike);
            result[key] = makeValue(result[key], element);
        }

        return result;
    };
}
567747
def make_function3_annotate(self, node, is_lambda, nested=1,
                            code_node=None, annotate_last=-1):
    

    def build_param(ast, name, default):
        """build parameters:
            - handle defaults
            - handle format tuple parameters
        """
        if default:
            value = self.traverse(default, indent='')
            maybe_show_tree_param_default(self, name, value)
            result = '%s=%s' % (name,  value)
            if result[-2:] == '= ':	# default was 'LOAD_CONST None'
                result += 'None'
            return result
        else:
            return name

    # MAKE_FUNCTION_... or MAKE_CLOSURE_...
    assert node[-1].kind.startswith('MAKE_')

    annotate_tuple = None
    for annotate_last in range(len(node)-1, -1, -1):
        if node[annotate_last] == 'annotate_tuple':
            annotate_tuple = node[annotate_last]
            break
    annotate_args = {}

    if (annotate_tuple == 'annotate_tuple'
        and annotate_tuple[0] in ('LOAD_CONST', 'LOAD_NAME')
        and isinstance(annotate_tuple[0].attr, tuple)):
        annotate_tup = annotate_tuple[0].attr
        i = -1
        j = annotate_last-1
        l = -len(node)
        while j >= l and node[j].kind in ('annotate_arg' 'annotate_tuple'):
            annotate_args[annotate_tup[i]] = node[j][0]
            i -= 1
            j -= 1

    args_node = node[-1]
    if isinstance(args_node.attr, tuple):
        # positional args are before kwargs
        defparams = node[:args_node.attr[0]]
        pos_args, kw_args, annotate_argc  = args_node.attr
        if 'return' in annotate_args.keys():
            annotate_argc = len(annotate_args) - 1
    else:
        defparams = node[:args_node.attr]
        kw_args  = 0
        annotate_argc = 0
        pass

    if 3.0 <= self.version <= 3.2:
        lambda_index = -2
    elif 3.03 <= self.version:
        lambda_index = -3
    else:
        lambda_index = None

    if lambda_index and is_lambda and iscode(node[lambda_index].attr):
        assert node[lambda_index].kind == 'LOAD_LAMBDA'
        code = node[lambda_index].attr
    else:
        code = code_node.attr

    assert iscode(code)
    code = Code(code, self.scanner, self.currentclass)

    # add defaults values to parameter names
    argc = code.co_argcount
    paramnames = list(code.co_varnames[:argc])

    try:
        ast = self.build_ast(code._tokens,
                             code._customize,
                             is_lambda = is_lambda,
                             noneInNames = ('None' in code.co_names))
    except (ParserError, ParserError2) as p:
        self.write(str(p))
        if not self.tolerate_errors:
            self.ERROR = p
        return

    kw_pairs = args_node.attr[1]
    indent = self.indent

    if is_lambda:
        self.write("lambda ")
    else:
        self.write("(")

    last_line = self.f.getvalue().split("\n")[-1]
    l = len(last_line)
    indent = ' ' * l
    line_number = self.line_number

    if code_has_star_arg(code):
        self.write('*%s' % code.co_varnames[argc + kw_pairs])
        argc += 1

    i = len(paramnames) - len(defparams)
    suffix = ''

    no_paramnames = len(paramnames[:i]) == 0

    for param in paramnames[:i]:
        self.write(suffix, param)
        suffix = ', '
        if param in annotate_tuple[0].attr:
            p = annotate_tuple[0].attr.index(param)
            self.write(': ')
            self.preorder(node[p])
            if (line_number != self.line_number):
                suffix = ",\n" + indent
                line_number = self.line_number
            # value, string = annotate_args[param]
            # if string:
            #     self.write(': "%s"' % value)
            # else:
            #     self.write(': %s' % value)


    suffix = ', ' if i > 0 else ''
    for n in node:
        if n == 'pos_arg':
            no_paramnames = False
            self.write(suffix)
            param = paramnames[i]
            self.write(param)
            if param in annotate_args:
                aa = annotate_args[param]
                if isinstance(aa, tuple):
                    aa = aa[0]
                    self.write(': "%s"' % aa)
                elif isinstance(aa, SyntaxTree):
                    self.write(': ')
                    self.preorder(aa)

            self.write('=')
            i += 1
            self.preorder(n)
            if (line_number != self.line_number):
                suffix = ",\n" + indent
                line_number = self.line_number
            else:
                suffix = ', '


    # self.println(indent, '#flags:\t', int(code.co_flags))
    if kw_args + annotate_argc > 0:
        if no_paramnames:
            if not code_has_star_arg(code):
                if argc > 0:
                    self.write(", *, ")
                else:
                    self.write("*, ")
                pass
            else:
                self.write(", ")

            kwargs = node[0]
            last = len(kwargs)-1
            i = 0
            for n in node[0]:
                if n == 'kwarg':
                    if (line_number != self.line_number):
                        self.write("\n" + indent)
                        line_number = self.line_number
                    self.write('%s=' % n[0].pattr)
                    self.preorder(n[1])
                    if i < last:
                        self.write(', ')
                    i += 1
                    pass
                pass
            annotate_args = []
            for n in node:
                if n == 'annotate_arg':
                    annotate_args.append(n[0])
                elif n == 'annotate_tuple':
                    t = n[0].attr
                    if t[-1] == 'return':
                        t = t[0:-1]
                        annotate_args = annotate_args[:-1]
                        pass
                    last = len(annotate_args) - 1
                    for i in range(len(annotate_args)):
                        self.write("%s: " % (t[i]))
                        self.preorder(annotate_args[i])
                        if i < last:
                            self.write(', ')
                            pass
                        pass
                    break
                pass
            pass


        if code_has_star_star_arg(code):
            if argc > 0:
                self.write(', ')
            self.write('**%s' % code.co_varnames[argc + kw_pairs])

    if is_lambda:
        self.write(": ")
    else:
        self.write(')')
        if 'return' in annotate_tuple[0].attr:
            if (line_number != self.line_number) and not no_paramnames:
                self.write("\n" + indent)
                line_number = self.line_number
            self.write(' -> ')
            # value, string = annotate_args['return']
            # if string:
            #     self.write(' -> "%s"' % value)
            # else:
            #     self.write(' -> %s' % value)
            self.preorder(node[annotate_last-1])

        self.println(":")

    if (len(code.co_consts) > 0 and
        code.co_consts[0] is not None and not is_lambda): # ugly
        # docstring exists, dump it
        print_docstring(self, self.indent, code.co_consts[0])

    code._tokens = None # save memory
    assert ast == 'stmts'

    all_globals = find_all_globals(ast, set())
    globals, nonlocals = find_globals_and_nonlocals(ast, set(), set(),
                                                    code, self.version)
    for g in sorted((all_globals & self.mod_globs) | globals):
        self.println(self.indent, 'global ', g)
    for nl in sorted(nonlocals):
        self.println(self.indent, 'nonlocal ', nl)
    self.mod_globs -= all_globals
    has_none = 'None' in code.co_names
    rn = has_none and not find_none(ast)
    self.gen_source(ast, code.co_name, code._customize, is_lambda=is_lambda,
                    returnNone=rn)
    code._tokens = code._customize = None
224684
function (functionName, arguments) {
                var self = this;
                var args = self._getArgs(arguments);
                var callback = self._getCallback(arguments);

                return self._generic(functionName, args)
                    .nodeify(callback);
            }
1194394
def call(node: Node, key: str, value: Any):
    """"""
    value = _to_list(value)
    if not value or not isinstance(value[-1], dict):
        value.append({})
    args = value[0:-1]
    kwargs = value[-1]
    node.__dict__[key](*args, **kwargs)
85812
def func(self, node):
        ''
        _, params, _, _, _, expr = node
        params = map(self.eval, params)
        def func(*args):
            env = dict(self.env.items() + zip(params, args))
            return Mini(env).eval(expr)
        return func
424036
def __convert(root, tag, values, func):
    
    elements = root.getElementsByTagName(tag)

    for element in elements:
        converted = func(element)

        # Append to the list
        __append_list(values, converted)
1204277
def group_by_impl(func, sequence):
    
    result = {}
    for element in sequence:
        if result.get(func(element)):
            result.get(func(element)).append(element)
        else:
            result[func(element)] = [element]
    return six.viewitems(result)
426838
def get_func_lno(self, funcname):
        """"""

        class FuncLineno(ast.NodeVisitor):
            def __init__(self):
                self.clss = []

            def generic_visit(self, node):
                for child in ast.iter_child_nodes(node):
                    for item in self.visit(child):
                        yield item

            def visit_ClassDef(self, node):
                self.clss.append(node.name)
                for item in self.generic_visit(node):
                    yield item
                self.clss.pop()

            def visit_FunctionDef(self, node):
                # Only allow non nested function definitions.
                name = '.'.join(itertools.chain(self.clss, [node.name]))
                yield name, node.lineno

        if self.functions_firstlno is None:
            self.functions_firstlno = {}
            for name, lineno in FuncLineno().visit(self.node):
                if (name not in self.functions_firstlno or
                        self.functions_firstlno[name] < lineno):
                    self.functions_firstlno[name] = lineno
        try:
            return self.functions_firstlno[funcname]
        except KeyError:
            raise BdbSourceError('{}: function "{}" not found.'.format(
                self.filename, funcname))
818125
function forEach(nodes, fn) {
  if (nodes && nodes.length) {
    Array.prototype.slice.call(nodes).forEach(fn);
  }
}
22610
function templateNodeTransformation( $functionName, &$node,
                                         $tpl, $parameters, $privateData )
    {
        /*
        {foreach <array> as [$keyVar =>] $itemVar
                 [sequence <array> as $sequenceVar]
                 [offset <offset>]
                 [max <max>]
                 [reverse]
        }
        */

        $tpl->ForeachCounter++;
        $newNodes            = array();
        $nodePlacement       = eZTemplateNodeTool::extractFunctionNodePlacement( $node );
        $uniqid              =  md5( $nodePlacement[2] ) . "_" . $tpl->ForeachCounter;

        $loop = new eZTemplateCompiledLoop( eZTemplateForeachFunction::FUNCTION_NAME,
                                            $newNodes, $parameters, $nodePlacement, $uniqid,
                                            $node, $tpl, $privateData );



        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "// foreach begins" );

        $loop->initVars();

        $array           = "fe_array_$uniqid";
        $arrayKeys       = "fe_array_keys_$uniqid";
        $nItems          = "fe_n_items_$uniqid";
        $nItemsProcessed = "fe_n_items_processed_$uniqid";
        $i               = "fe_i_$uniqid";
        $key             = "fe_key_$uniqid";
        $val             = "fe_val_$uniqid";
        $offset          = "fe_offset_$uniqid";
        $max             = "fe_max_$uniqid";
        $reverse         = "fe_reverse_$uniqid";
        $firstVal        = "fe_first_val_$uniqid";
        $lastVal         = "fe_last_val_$uniqid";

        $variableStack   = "fe_variable_stack_$uniqid";
        $namesArray = array( $array, $arrayKeys, $nItems, $nItemsProcessed, $i, $key, $val, $offset, $max, $reverse, $firstVal, $lastVal );

        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "if ( !isset( \$$variableStack ) ) \$$variableStack = array();" );
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "\$" . $variableStack ."[] = compact( '" . implode( "', '", $namesArray ) . "' );" );

        $newNodes[] = eZTemplateNodeTool::createVariableNode( false, $parameters['array'], $nodePlacement, array( 'text-result' => false ), $array );
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "\$$arrayKeys = is_array( \$$array ) ? array_keys( \$$array ) : array();" );
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "\$$nItems = count( \$$arrayKeys );" );
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "\$$nItemsProcessed = 0;" );


        // process offset, max and reverse parameters
        if ( isset( $parameters['offset'] ) )
            $newNodes[] = eZTemplateNodeTool::createVariableNode( false, $parameters['offset'], $nodePlacement, array( 'text-result' => false ), $offset );
        else
            $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "\$$offset = 0;" );

        if ( isset( $parameters['max'] ) )
            $newNodes[] = eZTemplateNodeTool::createVariableNode( false, $parameters['max'], $nodePlacement, array( 'text-result' => false ), $max );
        else
            $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "\$$max = \$$nItems - \$$offset;" );

        if ( isset( $parameters['reverse'] ) )
            $newNodes[] = eZTemplateNodeTool::createVariableNode( false, $parameters['reverse'], $nodePlacement, array( 'text-result' => false ), $reverse );
        else
            $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "\$$reverse = false;" );


        // fix definitely incorrect offset
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "if ( \$$offset < 0 || \$$offset >= \$$nItems )\n{\n".
                                                               "    \$$offset = ( \$$offset < 0 ) ? 0 : \$$nItems;\n".
                                                               "    if ( \$$nItems || \$$offset < 0 )\n {\n".
                                                               "        eZDebug::writeWarning(\"Invalid 'offset' parameter specified: '\$$offset'. Array count: \$$nItems\");   \n}\n}" );
        // fix definitely incorrect max
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "if ( \$$max < 0 || \$$offset + \$$max > \$$nItems )\n{\n".
                                                               "    if ( \$$max < 0 )\n eZDebug::writeWarning(\"Invalid 'max' parameter specified: \$$max\");\n".
                                                               "    \$$max = \$$nItems - \$$offset;\n}" );

        // initialize first and last indexes to iterate between them
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "if ( \$$reverse )\n" .
                                                               "{\n" .
                                                               "    \$$firstVal = \$$nItems - 1 - \$$offset;\n" .
                                                               "    \$$lastVal  = 0;\n" .
                                                               "}\n" .
                                                               "else\n" .
                                                               "{\n" .
                                                               "    \$$firstVal = \$$offset;\n" .
                                                               "    \$$lastVal  = \$$nItems - 1;\n" .
                                                               "}" );

        // generate loop header
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "// foreach" );
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "for ( \$$i = \$$firstVal; " .
                                                               "\$$nItemsProcessed < \$$max && ( \$$reverse ? \$$i >= \$$lastVal : \$$i <= \$$lastVal ); " .
                                                               "\$$reverse ? \$$i-- : \$$i++ )\n" .
                                                               "{" );
        $newNodes[] = eZTemplateNodeTool::createSpacingIncreaseNode();

        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "\$$key = \$${arrayKeys}[\$$i];" );
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "\$$val = \$${array}[\$$key];" );

        // export $itemVar
        $newNodes[] = eZTemplateNodeTool::createVariableNode( false, "$val", $nodePlacement, array(),
                                                              $parameters['item_var'][0][1],
                                                              false, true, true );

        // export $keyVar (if specified)
        if ( isset( $parameters['key_var'] ) )
        {
            $newNodes[] = eZTemplateNodeTool::createVariableNode( false, "$key", $nodePlacement, array(),
                                                                  $parameters['key_var'][0][1],
                                                                  false, true, true );
        }

        $loop->processBody();

        // generate loop footer
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "\$$nItemsProcessed++;" );
        $newNodes[] = eZTemplateNodeTool::createSpacingDecreaseNode();
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "} // foreach" );

        $loop->cleanup();

        // unset the loop variables
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "if ( count( \$$variableStack ) ) extract( array_pop( \$$variableStack ) );\n" );
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "else\n{\n" );
        $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( $array );
        $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( $arrayKeys );
        $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( $nItems );
        $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( $nItemsProcessed );
        $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( $i );
        $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( $key );
        $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( $val );
        $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( $offset );
        $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( $max );
        $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( $reverse );
        $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( $firstVal );
        $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( $lastVal );

        $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( $variableStack );
        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "}\n" );

        $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "// foreach ends" );

        return $newNodes;
    }