Exemplo n.º 1
0
        public override void visit(statement_list stmtList)
        {
            var stl = new statements_list(_visitor.get_location(stmtList),
                                          _visitor.get_location_with_check(stmtList.left_logical_bracket),
                                          _visitor.get_location_with_check(stmtList.right_logical_bracket));

            _visitor.convertion_data_and_alghoritms.statement_list_stack_push(stl);

            var newTreeNode = new CapturedVariablesTreeNodeBlockScope(_currentTreeNode, stl.Scope.ScopeNum, stmtList);

            if (_rootNode == null)
            {
                _rootNode = newTreeNode;
            }
            if (_currentTreeNode != null)
            {
                _currentTreeNode.ChildNodes.Add(newTreeNode);
            }
            _currentTreeNode = newTreeNode;

            _scopesCapturedVarsNodesDictionary.Add(stl.Scope.ScopeNum, _currentTreeNode);

            if (stmtList.subnodes != null)
            {
                foreach (var stmt in stmtList.subnodes)
                {
                    ProcessNode(stmt);
                }
            }

            _visitor.convertion_data_and_alghoritms.statement_list_stack.pop();

            _currentTreeNode = _currentTreeNode.ParentNode;
        }
        public override void visit(statement_list stmtList)
        {
            var stl = new statements_list(syntaxTreeVisitor.get_location(stmtList),
                                          syntaxTreeVisitor.get_location_with_check(stmtList.left_logical_bracket),
                                          syntaxTreeVisitor.get_location_with_check(stmtList.right_logical_bracket));

            syntaxTreeVisitor.convertion_data_and_alghoritms.statement_list_stack_push(stl);
            if (stmtList.subnodes != null)
            {
                foreach (var stmt in stmtList.subnodes)
                {
                    ProcessNode(stmt);
                }
            }
            syntaxTreeVisitor.convertion_data_and_alghoritms.statement_list_stack.pop();
        }
        public override void visit(statement_list stmtList)
        {
            if (stmtList.IsInternal) // просто обойти как продолжение объемлющего statement_list
            {
                foreach (var stmt in stmtList.subnodes)
                {
                    ProcessNode(stmt);
                }
                return;
            }

            var stl = new statements_list(_visitor.get_location(stmtList),
                                          _visitor.get_location_with_check(stmtList.left_logical_bracket),
                                          _visitor.get_location_with_check(stmtList.right_logical_bracket));

            _visitor.convertion_data_and_alghoritms.statement_list_stack_push(stl);

            var newTreeNode = new CapturedVariablesTreeNodeBlockScope(_currentTreeNode, stl.Scope.ScopeNum, stmtList);

            if (_rootNode == null)
            {
                _rootNode = newTreeNode;
            }
            if (_currentTreeNode != null)
            {
                _currentTreeNode.ChildNodes.Add(newTreeNode);
            }
            _currentTreeNode = newTreeNode;

            _scopesCapturedVarsNodesDictionary.Add(stl.Scope.ScopeNum, _currentTreeNode);
            foreach (var csi in _pendingCapturedSymbols)
            {
                _currentTreeNode.VariablesDefinedInScope.Add(csi);
            }
            _pendingCapturedSymbols.Clear();
            if (stmtList.subnodes != null)
            {
                foreach (var stmt in stmtList.subnodes)
                {
                    ProcessNode(stmt);
                }
            }

            _visitor.convertion_data_and_alghoritms.statement_list_stack.pop();

            _currentTreeNode = _currentTreeNode.ParentNode;
        }
Exemplo n.º 4
0
        public override void visit(foreach_stmt _foreach_stmt)
        {
            statements_list sl2 = new statements_list(get_location(_foreach_stmt));

            convertion_data_and_alghoritms.statement_list_stack_push(sl2);

            expression_node     foreachCollection;
            var_definition_node foreachVariable;

            ForeachCheckAndConvert(_foreach_stmt, out foreachCollection, out foreachVariable);

            // SSM 29.07.16 - если in_what - одномерный массив, то заменить код foreach на for
            // if (OptimizeForeachInCase1DArray(_foreach_stmt, foreachCollection)) return;

            statements_list sl = new statements_list(get_location(_foreach_stmt.stmt));

            convertion_data_and_alghoritms.statement_list_stack_push(sl);

            foreach_node foreachNode = new foreach_node(foreachVariable, foreachCollection, null, get_location(_foreach_stmt));

            context.cycle_stack.push(foreachNode);
            context.loop_var_stack.Push(foreachVariable);
            context.enter_code_block_with_bind();
            statement_node body = convert_strong(_foreach_stmt.stmt);

            context.leave_code_block();
            context.loop_var_stack.Pop();
            context.cycle_stack.pop();

            sl = convertion_data_and_alghoritms.statement_list_stack.pop();

            if (sl.statements.Count > 0 || sl.local_variables.Count > 0)
            {
                sl.statements.AddElement(body);
                body = sl;
            }

            foreachNode.what_do = body;

            convertion_data_and_alghoritms.statement_list_stack.pop();
            sl2.statements.AddElement(foreachNode);

            return_value(sl2);
        }
Exemplo n.º 5
0
        private void VisitStatementList(statements_list stmt)
        {
            statement_node sn = null;

            foreach (local_block_variable lbv in stmt.local_variables)
            {
                helper.AddVariable(lbv);
                if (lbv.inital_value != null)
                {
                    VisitExpression(lbv.inital_value);
                }
                CheckType(lbv.type, lbv.inital_value, lbv.loc);
            }
            for (int i = 0; i < stmt.statements.Count; i++)
            {
                if (is_break_stmt && stmt.statements[i].semantic_node_type != semantic_node_type.empty_statement)
                {
                    warns.Add(new UnreachableCodeDetected(stmt.statements[i].location));
                }
                is_break_stmt = false;
                sn            = stmt.statements[i];
                VisitStatement(sn);
                if (is_break_stmt && i < stmt.statements.Count - 1 && stmt.statements[i + 1].semantic_node_type != semantic_node_type.empty_statement)
                {
                    warns.Add(new UnreachableCodeDetected(stmt.statements[i + 1].location));
                }
                is_break_stmt = false;
            }
            foreach (local_block_variable vdn in stmt.local_variables)
            {
                VarInfo vi = helper.GetVariable(vdn);
                if (vi.num_use == 0 && !vdn.is_special_name)
                {
                    warns.Add(new UnusedVariable(vdn.name, vdn.loc));
                }

                if (vi.num_ass > 0 && vi.act_num_use == 0 && !vdn.is_special_name)
                {
                    warns.Add(new AssignWithoutUsing(vdn.name, vi.last_ass_loc));
                }
            }
        }
        /*public override void visit(exception_handler eh)
         * {
         *  _visitor.visit(eh);
         *  SymbolInfo si = _visitor.context.find_first(eh.variable.name);
         *  _currentTreeNode.VariablesDefinedInScope.Add(new CapturedVariablesTreeNode.CapturedSymbolInfo(eh, si));
         *  ProcessNode(eh.statements);
         * }*/

        public override void visit(exception_handler eh)
        {
            // Отдельным визитором переменные в on присвою локальным переменным и переименую везде внутри блока
            statements_list sl = new statements_list(_visitor.get_location(eh.statements));

            _visitor.convertion_data_and_alghoritms.statement_list_stack_push(sl);

            _visitor.context.enter_code_block_without_bind();

            if (eh.variable != null)
            {
                _visitor.context.add_var_definition(eh.variable.name, _visitor.get_location(eh.variable), _visitor.convert_strong(eh.type_name), PascalABCCompiler.SemanticTree.polymorphic_state.ps_common, true);
            }
            //SymbolInfo si = _visitor.context.find_first(eh.variable.name);
            //var csi = new CapturedVariablesTreeNode.CapturedSymbolInfo(eh, si);
            //_currentTreeNode.VariablesDefinedInScope.Add(new CapturedVariablesTreeNode.CapturedSymbolInfo(eh, si));
            //_pendingCapturedSymbols.Add(csi);
            ProcessNode(eh.variable);

            ProcessNode(eh.statements);
            _visitor.context.leave_code_block();
            _visitor.convertion_data_and_alghoritms.statement_list_stack_pop();
            //_pendingCapturedSymbols.Remove(csi);
        }
Exemplo n.º 7
0
        public override void visit(PascalABCCompiler.SyntaxTree.for_node _for_node)
        {
            var loc1           = _visitor.get_location(_for_node.loop_variable);
            var loopIdentName  = _for_node.loop_variable.name.ToLower();
            var nodesToProcess = new List <syntax_tree_node>();

            var_definition_node vdn;
            var initv = _visitor.convert_strong(_for_node.initial_value);
            var tmp   = initv;

            if (initv is typed_expression)
            {
                initv = _visitor.convert_typed_expression_to_function_call(initv as typed_expression);
            }

            if (initv.type == null)
            {
                initv = tmp;
            }

            var headStmts = new statements_list(loc1);

            _visitor.convertion_data_and_alghoritms.statement_list_stack_push(headStmts);

            var newTreeNode = new CapturedVariablesTreeNodeForScope(_currentTreeNode, headStmts.Scope.ScopeNum, _for_node);

            if (_currentTreeNode != null)
            {
                _currentTreeNode.ChildNodes.Add(newTreeNode);
            }
            _currentTreeNode = newTreeNode;

            _scopesCapturedVarsNodesDictionary.Add(headStmts.Scope.ScopeNum, _currentTreeNode);


            if (_for_node.type_name == null && !_for_node.create_loop_variable)
            {
                var dn = _visitor.context.check_name_node_type(loopIdentName, loc1, general_node_type.variable_node);
                vdn = (var_definition_node)dn;
                nodesToProcess.Add(_for_node.loop_variable);
            }
            else
            {
                var tn = _for_node.type_name != null?_visitor.convert_strong(_for_node.type_name) : initv.type;

                vdn = _visitor.context.add_var_definition(loopIdentName,
                                                          _visitor.get_location(_for_node.loop_variable), tn,
                                                          polymorphic_state.ps_common);

                _currentTreeNode.VariablesDefinedInScope.Add(new CapturedVariablesTreeNode.CapturedSymbolInfo(_for_node, _visitor.context.find(loopIdentName)));
            }


            newTreeNode.SymbolInfoLoopVar = _visitor.context.find(loopIdentName);

            var fn = new PascalABCCompiler.TreeRealization.for_node(null, null, null, null, null, _visitor.get_location(_for_node));

            if (vdn.type == SystemLibrary.bool_type)
            {
                fn.bool_cycle = true;
            }
            _visitor.context.cycle_stack.push(fn);
            _visitor.context.loop_var_stack.Push(vdn);

            nodesToProcess.Add(_for_node.initial_value);
            nodesToProcess.Add(_for_node.finish_value);
            nodesToProcess.Add(_for_node.increment_value);

            foreach (var n in nodesToProcess)
            {
                ProcessNode(n);
            }

            if (!(_for_node.statements is statement_list))
            {
                var stmtList = new statement_list(_for_node.statements, _for_node.statements.source_context);
                _for_node.statements = stmtList;
            }
            ProcessNode(_for_node.statements);

            _visitor.context.cycle_stack.pop();
            _visitor.context.loop_var_stack.Pop();
            _visitor.convertion_data_and_alghoritms.statement_list_stack.pop();

            _currentTreeNode = _currentTreeNode.ParentNode;
        }
Exemplo n.º 8
0
        public override void visit(foreach_stmt _foreach_stmt)
        {
            var loopIdentName = _foreach_stmt.identifier.name.ToLower();

            definition_node     dn  = null;
            var_definition_node vdn = null;

            var sl2 = new statements_list(_visitor.get_location(_foreach_stmt));

            _visitor.convertion_data_and_alghoritms.statement_list_stack_push(sl2);

            var newTreeNode = new CapturedVariablesTreeNodeForEachScope(_currentTreeNode, sl2.Scope.ScopeNum, _foreach_stmt);

            if (_currentTreeNode != null)
            {
                _currentTreeNode.ChildNodes.Add(newTreeNode);
            }
            _currentTreeNode = newTreeNode;

            _scopesCapturedVarsNodesDictionary.Add(sl2.Scope.ScopeNum, _currentTreeNode);

            var inWhat = _visitor.convert_strong(_foreach_stmt.in_what);
            var tmp    = inWhat;

            if (inWhat is typed_expression)
            {
                inWhat = _visitor.convert_typed_expression_to_function_call(inWhat as typed_expression);
            }

            type_node elemType = null;

            if (inWhat.type == null)
            {
                inWhat = tmp;
            }

            _visitor.FindIEnumerableElementType(/*_foreach_stmt, */ inWhat.type, ref elemType);

            if (_foreach_stmt.type_name == null)
            {
                var loc1 = _visitor.get_location(_foreach_stmt.identifier);
                dn  = _visitor.context.check_name_node_type(loopIdentName, loc1, general_node_type.variable_node);
                vdn = (var_definition_node)dn;
            }
            else
            {
                vdn = _visitor.context.add_var_definition(loopIdentName, _visitor.get_location(_foreach_stmt.identifier));

                type_node tn;
                if (_foreach_stmt.type_name is no_type_foreach)
                {
                    tn = elemType;
                }
                else
                {
                    tn = _visitor.convert_strong(_foreach_stmt.type_name);
                    _visitor.check_for_type_allowed(tn, _visitor.get_location(_foreach_stmt.type_name));
                }


                _visitor.context.close_var_definition_list(tn, null);

                _currentTreeNode.VariablesDefinedInScope.Add(new CapturedVariablesTreeNode.CapturedSymbolInfo(_foreach_stmt, _visitor.context.find(loopIdentName)));
            }

            newTreeNode.SymbolInfoLoopVar = _visitor.context.find(loopIdentName);

            if (!(vdn.type is compiled_generic_instance_type_node))
            {
                _visitor.convertion_data_and_alghoritms.check_convert_type_with_inheritance(vdn.type, elemType, _visitor.get_location(_foreach_stmt.identifier));
            }

            var fn = new foreach_node(vdn, inWhat, null, _visitor.get_location(_foreach_stmt));

            _visitor.context.cycle_stack.push(fn);
            _visitor.context.loop_var_stack.Push(vdn);

            ProcessNode(_foreach_stmt.in_what);

            if (!(_foreach_stmt.stmt is statement_list))
            {
                var stmtList = new statement_list(_foreach_stmt.stmt, _foreach_stmt.stmt.source_context);
                _foreach_stmt.stmt = stmtList;
            }

            ProcessNode(_foreach_stmt.stmt);

            _visitor.context.loop_var_stack.Pop();
            _visitor.convertion_data_and_alghoritms.statement_list_stack.pop();
            _visitor.context.cycle_stack.pop();

            _currentTreeNode = _currentTreeNode.ParentNode;
        }
Exemplo n.º 9
0
        public override void visit(for_node _for_node)
        {
            #region MikhailoMMX, обработка omp parallel for
            bool isGenerateParallel   = false;
            bool isGenerateSequential = true;
            if (OpenMP.ForsFound)
            {
                OpenMP.LoopVariables.Push(_for_node.loop_variable.name.ToLower());
                //если в программе есть хоть одна директива parallel for - проверяем:
                if (DirectivesToNodesLinks.ContainsKey(_for_node) && OpenMP.IsParallelForDirective(DirectivesToNodesLinks[_for_node]))
                {
                    //перед этим узлом есть директива parallel for
                    if (CurrentParallelPosition == ParallelPosition.Outside)            //входим в самый внешний параллельный for
                    {
                        if (_for_node.create_loop_variable || (_for_node.type_name != null))
                        {
                            //сгенерировать сначала последовательную ветку, затем параллельную
                            //устанавливаем флаг и продолжаем конвертирование, считая, что конвертируем последовательную ветку
                            isGenerateParallel      = true;
                            CurrentParallelPosition = ParallelPosition.InsideSequential;
                            //в конце за счет флага вернем состояние обратно и сгенерируем и параллельную ветку тоже
                        }
                        else
                        {
                            WarningsList.Add(new OMP_BuildigError(new Exception("Переменная параллельного цикла должна быть определена в заголовке цикла"), new location(_for_node.source_context.begin_position.line_num, _for_node.source_context.begin_position.column_num, _for_node.source_context.end_position.line_num, _for_node.source_context.end_position.column_num, new document(_for_node.source_context.FileName))));
                        }
                    }
                    else //уже генерируем одну из веток
                         //если это параллельная ветка - последовательную генерировать не будем
                    if (CurrentParallelPosition == ParallelPosition.InsideParallel)
                    {
                        isGenerateParallel   = true;
                        isGenerateSequential = false;
                    }
                    //else
                    //а если последовательная - то флаг isGenerateParallel не установлен, сгенерируется только последовательная
                }
            }
            #endregion


            location            loopVariableLocation = get_location(_for_node.loop_variable);
            var_definition_node vdn = null;
            expression_node     left, right, res;
            expression_node     initialValue = convert_strong(_for_node.initial_value);
            expression_node     tmp          = initialValue;
            if (initialValue is typed_expression)
            {
                initialValue = convert_typed_expression_to_function_call(initialValue as typed_expression);
            }
            if (initialValue.type == null)
            {
                initialValue = tmp;
            }
            statements_list head_stmts = new statements_list(loopVariableLocation);
            convertion_data_and_alghoritms.statement_list_stack_push(head_stmts);

            var early_init_loop_variable = false; // SSM 25/05/16
            if (_for_node.type_name == null && !_for_node.create_loop_variable)
            {
                definition_node dn = context.check_name_node_type(_for_node.loop_variable.name, loopVariableLocation,
                                                                  general_node_type.variable_node);
                vdn = (var_definition_node)dn;
                if (context.is_loop_variable(vdn))
                {
                    AddError(get_location(_for_node.loop_variable), "CANNOT_ASSIGN_TO_LOOP_VARIABLE");
                }
                if (!check_name_in_current_scope(_for_node.loop_variable.name))
                {
                    AddError(new ForLoopControlMustBeSimpleLocalVariable(loopVariableLocation));
                }
            }
            else
            {
                //В разработке DS
                //throw new NotSupportedError(get_location(_for_node.type_name));
                type_node tn;
                if (_for_node.type_name != null)
                {
                    tn = convert_strong(_for_node.type_name);
                }
                else
                {
                    tn = initialValue.type;
                }
                //if (tn == SystemLibrary.SystemLibrary.void_type && _for_node.type_name != null)
                //	AddError(new VoidNotValid(get_location(_for_node.type_name)))
                if (_for_node.type_name != null)
                {
                    check_for_type_allowed(tn, get_location(_for_node.type_name));
                }
                vdn = context.add_var_definition(_for_node.loop_variable.name, get_location(_for_node.loop_variable), tn, initialValue /*, polymorphic_state.ps_common*/);
                vdn.polymorphic_state    = polymorphic_state.ps_common;
                early_init_loop_variable = true; // SSM 25/05/16
            }
            internal_interface ii = vdn.type.get_internal_interface(internal_interface_kind.ordinal_interface);
            if (ii == null)
            {
                AddError(new OrdinalTypeExpected(loopVariableLocation));
            }
            ordinal_type_interface oti = (ordinal_type_interface)ii;


            location            finishValueLocation = get_location(_for_node.finish_value);
            var_definition_node vdn_finish          = context.create_for_temp_variable(vdn.type, finishValueLocation);
            //Это должно стоять раньше!!
            left = create_variable_reference(vdn_finish, loopVariableLocation);
            expression_node finishValue = convert_strong(_for_node.finish_value);
            right = finishValue;
            if (right is typed_expression)
            {
                right = convert_typed_expression_to_function_call(right as typed_expression);
            }
            res = find_operator(compiler_string_consts.assign_name, left, right, finishValueLocation);
            head_stmts.statements.AddElement(res);

            if (!early_init_loop_variable) // SSM 25/05/16 - for var i := f1() to f2() do без этой правки дважды вызывал f1()
            {
                left  = create_variable_reference(vdn, loopVariableLocation);
                right = initialValue;
                res   = find_operator(compiler_string_consts.assign_name, left, right, loopVariableLocation);
                head_stmts.statements.AddElement(res);
            }


            location initialValueLocation = get_location(_for_node.initial_value);

            statement_node  sn_inc        = null;
            expression_node sn_while      = null;
            expression_node sn_init_while = null;
            left  = create_variable_reference(vdn, initialValueLocation);
            right = create_variable_reference(vdn, finishValueLocation);
            expression_node right_border = create_variable_reference(vdn_finish, finishValueLocation);
            switch (_for_node.cycle_type)
            {
            case for_cycle_type.to:
            {
                sn_inc =
                    convertion_data_and_alghoritms.create_simple_function_call(oti.inc_method, loopVariableLocation,
                                                                               left);
                sn_while = convertion_data_and_alghoritms.create_simple_function_call(oti.lower_method,
                                                                                      finishValueLocation, right, right_border);
                sn_init_while = convertion_data_and_alghoritms.create_simple_function_call(oti.lower_eq_method,
                                                                                           finishValueLocation, right, right_border);
                break;
            }

            case for_cycle_type.downto:
            {
                sn_inc =
                    convertion_data_and_alghoritms.create_simple_function_call(oti.dec_method, loopVariableLocation,
                                                                               left);
                sn_while = convertion_data_and_alghoritms.create_simple_function_call(oti.greater_method,
                                                                                      finishValueLocation, right, right_border);
                sn_init_while = convertion_data_and_alghoritms.create_simple_function_call(oti.greater_eq_method,
                                                                                           finishValueLocation, right, right_border);
                break;
            }
            }

            CheckToEmbeddedStatementCannotBeADeclaration(_for_node.statements);

            //DarkStar Modifed
            //исправил ошибку:  не работали break в циклах
            TreeRealization.for_node forNode = new TreeRealization.for_node(null, sn_while, sn_init_while, sn_inc, null, get_location(_for_node));
            if (vdn.type == SystemLibrary.SystemLibrary.bool_type)
            {
                forNode.bool_cycle = true;
            }
            context.cycle_stack.push(forNode);
            context.loop_var_stack.Push(vdn);
            statements_list slst = new statements_list(get_location(_for_node.statements));
            convertion_data_and_alghoritms.statement_list_stack_push(slst);

            context.enter_code_block_with_bind();
            forNode.body = convert_strong(_for_node.statements);
            context.leave_code_block();

            slst = convertion_data_and_alghoritms.statement_list_stack.pop();
            if (slst.statements.Count > 0 || slst.local_variables.Count > 0)
            {
                slst.statements.AddElement(forNode.body);
                forNode.body = slst;
            }

            context.cycle_stack.pop();
            context.loop_var_stack.Pop();
            head_stmts = convertion_data_and_alghoritms.statement_list_stack.pop();
            head_stmts.statements.AddElement(forNode);

            #region MikhailoMMX, обработка omp parallel for
            //флаг был установлен только если это самый внешний parallel for и нужно сгенерировать обе ветки
            //или если это вложенный parallel for, нужно сгенерировать обе ветки, но без проверки на OMP_Available
            //Последовательная ветка только что сгенерирована, теперь меняем состояние и генерируем параллельную
            if (isGenerateParallel)
            {
                CurrentParallelPosition = ParallelPosition.InsideParallel;
                statements_list stl = OpenMP.TryConvertFor(head_stmts, _for_node, forNode, vdn, initialValue, finishValue, this);
                CurrentParallelPosition = ParallelPosition.Outside;
                if (stl != null)
                {
                    var f = _for_node.DescendantNodes().OfType <function_lambda_definition>().FirstOrDefault();
                    if (f != null)
                    {
                        AddError(get_location(f), "OPENMP_CONTROLLED_CONSTRUCTIONS_CANNOT_CONTAIN_LAMBDAS");
                    }

                    OpenMP.LoopVariables.Pop();
                    return_value(stl);
                    return;
                }
            }
            if (OpenMP.ForsFound)
            {
                OpenMP.LoopVariables.Pop();
            }
            #endregion

            return_value(head_stmts);
        }
Exemplo n.º 10
0
        public override void visit(foreach_stmt _foreach_stmt)
        {
            // SSM 24.12.19 lambda_capture_foreach_counter.pas не проходит если откомментировать эти 2 строки
            // Причина - лямбда уже начала разбираться
            // Пробую сделать так: если foreach в лямбде, то оптимизация не делается, а если нет, то делается
            // Пока не получилось - ошибка err0157.pas начинает быть правильной программой
            // Надо как-то переменную x в стек context.loop_var_stack.Push(foreachVariable); помещать !!! Но не сейчас... (SSM 12.01.20)

            /*syntax_tree_node p = _foreach_stmt;
             * do
             * {
             *  p = p.Parent;
             * } while (!(p == null || p is procedure_definition || p is function_lambda_definition));
             *
             * if (!(p is function_lambda_definition)) // тогда оптимизируем
             * {
             *  var feWhat = convert_strong(_foreach_stmt.in_what);
             *  if (OptimizeForeachInCase1DArray(_foreach_stmt, feWhat)) return;
             * }*/

            statements_list sl2 = new statements_list(get_location(_foreach_stmt));

            convertion_data_and_alghoritms.statement_list_stack_push(sl2);

            expression_node     foreachCollection;
            var_definition_node foreachVariable;

            ForeachCheckAndConvert(_foreach_stmt, out foreachCollection, out foreachVariable);

            // SSM 29.07.16 - если in_what - одномерный массив, то заменить код foreach на for
            // if (OptimizeForeachInCase1DArray(_foreach_stmt, foreachCollection)) return;

            statements_list sl = new statements_list(get_location(_foreach_stmt.stmt));

            convertion_data_and_alghoritms.statement_list_stack_push(sl);

            foreach_node foreachNode = new foreach_node(foreachVariable, foreachCollection, null, get_location(_foreach_stmt));

            context.cycle_stack.push(foreachNode);
            context.loop_var_stack.Push(foreachVariable);
            context.enter_code_block_with_bind();
            statement_node body = convert_strong(_foreach_stmt.stmt);

            context.leave_code_block();
            context.loop_var_stack.Pop();
            context.cycle_stack.pop();

            sl = convertion_data_and_alghoritms.statement_list_stack.pop();

            if (sl.statements.Count > 0 || sl.local_variables.Count > 0)
            {
                sl.statements.AddElement(body);
                body = sl;
            }

            foreachNode.what_do = body;

            convertion_data_and_alghoritms.statement_list_stack.pop();
            sl2.statements.AddElement(foreachNode);

            return_value(sl2);
        }