Example #1
0
 public override void visit(foreach_stmt _foreach_stmt)
 {
     prepare_node(_foreach_stmt.identifier, "identifier");
     prepare_node(_foreach_stmt.type_name, "type_name");
     prepare_node(_foreach_stmt.in_what, "in_what");
     prepare_node(_foreach_stmt.stmt, "stmt");
 }
Example #2
0
        private void ForeachCheckAndConvert(foreach_stmt _foreach_stmt, out expression_node foreachCollection,
                                            out var_definition_node foreachVariable)
        {
            var lambdaSearcher = new LambdaSearcher(_foreach_stmt.in_what);

            if (lambdaSearcher.CheckIfContainsLambdas())
            {
                AddError(new LambdasNotAllowedInForeachInWhatSatetement(get_location(lambdaSearcher.FoundLambda)));
            }

            foreachCollection = convert_strong(_foreach_stmt.in_what);

            expression_node tmp = convert_if_typed_expression_to_function_call(foreachCollection);

            if (tmp.type != null)
            {
                foreachCollection = tmp;
            }

            bool      sys_coll_ienum; // true означает, что мы нашли тип object у интерфейса System.Collections.IEnumerable
            type_node elem_type = null;

            if (!FindIEnumerableElementType(foreachCollection.type, ref elem_type, out sys_coll_ienum))
            {
                AddError(foreachCollection.location, "CAN_NOT_EXECUTE_FOREACH_BY_EXPR_OF_TYPE_{0}", foreachCollection.type.name);
            }

            CheckToEmbeddedStatementCannotBeADeclaration(_foreach_stmt.stmt);

            foreachVariable = FindForeachVariable(_foreach_stmt, elem_type, sys_coll_ienum);
        }
 public override void visit(foreach_stmt frch)
 {
     if (frch.type_name != null)
     {
         CheckVariableAlreadyDefined(frch.identifier);
     }
     base.visit(frch);
 }
        public override void visit(yield_sequence_node yn)
        {
            var id = NewVarName();

            id.source_context = yn.source_context;
            var fe = new foreach_stmt(id, new no_type_foreach(), yn.ex, new yield_node(id, yn.source_context), yn.source_context);

            ReplaceStatement(yn, fe);
        }
Example #5
0
 public override void visit(foreach_stmt _foreach_stmt)
 {
     AddPossibleComments(_foreach_stmt, true, false);
     _foreach_stmt.identifier.visit(this);
     if (_foreach_stmt.type_name != null)
     {
         _foreach_stmt.type_name.visit(this);
     }
     _foreach_stmt.in_what.visit(this);
     _foreach_stmt.stmt.visit(this);
 }
Example #6
0
        private var_definition_node FindForeachVariable(foreach_stmt _foreach_stmt, type_node elem_type, bool sys_coll_ienum)
        {
            var_definition_node foreachVariable = null;

            if (_foreach_stmt.type_name == null) // значит, переменная определена в другом месте
            {
                location        loc1 = get_location(_foreach_stmt.identifier);
                definition_node dn   = context.check_name_node_type(_foreach_stmt.identifier.name, loc1,
                                                                    general_node_type.variable_node);
                foreachVariable = (var_definition_node)dn;
                if (!check_name_in_current_scope(_foreach_stmt.identifier.name))
                {
                    AddError(loc1, "FOREACH_LOOP_CONTROL_MUST_BE_SIMPLE_LOCAL_VARIABLE");
                }
            }
            else
            {
                foreachVariable = context.add_var_definition(_foreach_stmt.identifier.name,
                                                             get_location(_foreach_stmt.identifier));

                type_node tn;
                if (_foreach_stmt.type_name is no_type_foreach) // значит, это for var x in a
                {
                    tn = elem_type;
                }
                else // значит, это for var x: T in a
                {
                    tn = convert_strong(_foreach_stmt.type_name);
                    check_for_type_allowed(tn, get_location(_foreach_stmt.type_name));
                    check_using_static_class(tn, get_location(_foreach_stmt.type_name));
                }
                if (tn.is_value_type && !tn.is_standard_type)
                {
                    context.close_var_definition_list(tn, new default_operator_node(tn, foreachVariable.location));
                }
                else
                {
                    context.close_var_definition_list(tn, null);
                }
            }

            if (/*!(foreachVariable.type is compiled_generic_instance_type_node) &&*/ !sys_coll_ienum) // SSM 16.09.18 - закомментировал это ограничение для фиксации бага #1184
            {
                convertion_data_and_alghoritms.check_convert_type_with_inheritance(elem_type, foreachVariable.type,
                                                                                   get_location(_foreach_stmt.identifier));
            }
            return(foreachVariable);
        }
Example #7
0
    public override void visit(foreach_stmt fe)
    {
        if (fe.in_what.DescendantNodes().OfType <function_lambda_definition>().Count() > 0)
        {
            var id = GenIdentName();
            id.Parent = fe;
            var ass = new var_statement(id, fe.in_what, fe.in_what.source_context);
            fe.in_what = id;
            var l = new List <statement> {
                ass, fe
            };
            ReplaceStatement(fe, l);
        }

        base.visit(fe);
    }
Example #8
0
        public override void visit(foreach_stmt fe)
        {
            //if (fe.DescendantNodes().OfType<function_lambda_definition>().Count() > 0) // из-за #1984 убрал вообще условие. Пусть будет всегда
            {
                var id = GenIdentName();
                id.Parent = fe;
                var ass = new var_statement(id, fe.in_what, fe.in_what.source_context);
                id.source_context = fe.in_what.source_context;
                fe.in_what        = id;
                var l = new List <statement> {
                    ass, fe
                };
                //ReplaceStatement(fe, l);
                ReplaceStatementUsingParent(fe, l);
            }

            base.visit(fe);
        }
Example #9
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);
        }
Example #10
0
        private var_definition_node FindForeachVariable(foreach_stmt _foreach_stmt, type_node elem_type, bool sys_coll_ienum)
        {
            var_definition_node foreachVariable = null;

            if (_foreach_stmt.type_name == null) // значит, переменная определена в другом месте
            {
                location        loc1 = get_location(_foreach_stmt.identifier);
                definition_node dn   = context.check_name_node_type(_foreach_stmt.identifier.name, loc1,
                                                                    general_node_type.variable_node);
                foreachVariable = (var_definition_node)dn;
                if (!check_name_in_current_scope(_foreach_stmt.identifier.name))
                {
                    AddError(loc1, "FOREACH_LOOP_CONTROL_MUST_BE_SIMPLE_LOCAL_VARIABLE");
                }
            }
            else
            {
                foreachVariable = context.add_var_definition(_foreach_stmt.identifier.name,
                                                             get_location(_foreach_stmt.identifier));

                type_node tn;
                if (_foreach_stmt.type_name is no_type_foreach) // значит, это for var x in a
                {
                    tn = elem_type;
                }
                else // значит, это for var x: T in a
                {
                    tn = convert_strong(_foreach_stmt.type_name);
                    check_for_type_allowed(tn, get_location(_foreach_stmt.type_name));
                }

                context.close_var_definition_list(tn, null);
            }

            if (!(foreachVariable.type is compiled_generic_instance_type_node) && !sys_coll_ienum)
            {
                convertion_data_and_alghoritms.check_convert_type_with_inheritance(elem_type, foreachVariable.type,
                                                                                   get_location(_foreach_stmt.identifier));
            }
            return(foreachVariable);
        }
Example #11
0
		public override void visit(foreach_stmt _foreach_stmt)
		{
			executer.visit(_foreach_stmt);
			if (_foreach_stmt.identifier != null)
				this.visit((dynamic)_foreach_stmt.identifier);
			if (_foreach_stmt.type_name != null)
				this.visit((dynamic)_foreach_stmt.type_name);
			if (_foreach_stmt.in_what != null)
				this.visit((dynamic)_foreach_stmt.in_what);
			if (_foreach_stmt.stmt != null)
				this.visit((dynamic)_foreach_stmt.stmt);
			if (_foreach_stmt.attributes != null)
				this.visit((dynamic)_foreach_stmt.attributes);
		}
Example #12
0
        /// <summary>
        /// Преобразует foreach в for, если коллекция это одномерный массив.
        /// </summary>
        /// <param name="_foreach_stmt"></param>
        /// <param name="in_what"></param>
        /// <returns>True - если преобразование удалось, иначе False</returns>
        private bool OptimizeForeachInCase1DArray(foreach_stmt _foreach_stmt, expression_node in_what)
        {
            var is1dimdynarr = false;
            var comptn       = in_what.type as compiled_type_node;

            if (comptn != null && comptn.type_special_kind == type_special_kind.array_kind && comptn.rank == 1)
            {
                is1dimdynarr = true;
            }
            if (!is1dimdynarr)
            {
                var comtn = in_what.type as common_type_node;
                if (comtn != null && comtn.internal_type_special_kind == type_special_kind.array_kind &&
                    comtn.rank == 1)
                {
                    is1dimdynarr = true;
                }
            }


            // SSM 23.08.16 Закомментировал оптимизацию. Не работает с лямбдами. Лямбды обходят старое дерево. А заменить foreach на for на этом этапе пока не получается - не развита инфраструктура

            if (is1dimdynarr) // Замена foreach на for для массива
            {
                // сгенерировать код для for и вызвать соответствующий visit
                var arrid = GenIdentName();
                //var vdarr = new var_statement(arrid, new semantic_addr_value(in_what)); // semantic_addr_value - перевод в синтаксис для мгновенного вычисления семантического выражения, которое уже вычислено в in_what
                var vdarr = new var_statement(arrid, _foreach_stmt.in_what);

                var i = GenIdentName();
                var x = _foreach_stmt.identifier;

                // Возможны 3 случая:
                // 1. _foreach_stmt.type_name = null - значит, переменная определена в другом месте
                // 2. _foreach_stmt.type_name = no_type_foreach - значит, это for var x in a
                // 3. _foreach_stmt.type_name = T - значит, это for var x: T in a

                statement vd;
                if (_foreach_stmt.type_name == null) // 1.
                {
                    vd = new assign(x, arrid.indexer(i));
                }
                else if (_foreach_stmt.type_name is no_type_foreach) // 2.
                {
                    vd = new var_statement(x, arrid.indexer(i));
                }
                else // 3.
                {
                    vd = new var_statement(x, _foreach_stmt.type_name, arrid.indexer(i));
                }

                // Превратить старое тело в statement_list и добавить к нему в начало x := a[i] или var x := a[i]
                var newbody = _foreach_stmt.stmt.ToStatementList();
                newbody.AddFirst(vd);

                var high = arrid.dot_node("Length").Minus(1);

                var fornode = new for_node(i, 0, high, newbody, for_cycle_type.to, null, null, true);

                var stl = new statement_list(vdarr, fornode);
                // Замена 1 оператора на 1 оператор. Всё хорошо даже если оператор помечен меткой
                ReplaceUsingParent(_foreach_stmt, stl);

                visit(stl);
                //visit(vdarr);
                //visit(fornode);

                return(true);
            }
            /// SSM 29.07.16
            return(false);
        }
Example #13
0
 public override void visit(foreach_stmt _foreach_stmt)
 {
 }
Example #14
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;
        }
Example #15
0
 public virtual void visit(foreach_stmt _foreach_stmt)
 {
     DefaultVisit(_foreach_stmt);
 }
		public virtual void visit(foreach_stmt _foreach_stmt)
		{
			DefaultVisit(_foreach_stmt);
		}
Example #17
0
		public virtual void visit(foreach_stmt _foreach_stmt)
		{
		}
Example #18
0
		public override void visit(foreach_stmt _foreach_stmt)
		{
			DefaultVisit(_foreach_stmt);
			pre_do_visit(_foreach_stmt);
			visit(foreach_stmt.identifier);
			visit(foreach_stmt.type_name);
			visit(foreach_stmt.in_what);
			visit(foreach_stmt.stmt);
			post_do_visit(_foreach_stmt);
		}
Example #19
0
		public virtual void post_do_visit(foreach_stmt _foreach_stmt)
		{
		}
 public override void visit(foreach_stmt fn)
 {
     ForeachCount++;
     base.visit(fn);
 }
Example #21
0
        // frninja 21/05/16
        public override void visit(foreach_stmt frch)
        {
            // Полный код Loweringа c yield_unknown_foreach_type = integer
            //  var a: System.Collections.Generic.IEnumerable<integer>;
            //  a := l;
            //  var en := a.GetEnumerator();
            //  while en.MoveNext do
            //  begin
            //    var curr := en.Current; // var не нужно ставить если curr была описана раньше
            //    Print(curr);
            //  end;
            ///

            // var a: System.Collections.Generic.IEnumerable<yield_unknown_foreach_type> := l;
            var foreachCollIdent = this.NewForeachCollectionName();
            var foreachCollType  = new template_type_reference(new named_type_reference("System.Collections.Generic.IEnumerable"),
                                                               new template_param_list(new yield_unknown_foreach_type(frch)));
            var foreachCollVarDef = new var_statement(foreachCollIdent, foreachCollType);

            var ass = new assign(foreachCollIdent, frch.in_what);

            //  var en := a.GetEnumerator();
            var enumeratorIdent  = this.NewEnumeratorName();
            var enumeratorVarDef = new var_statement(enumeratorIdent, new method_call(new dot_node(foreachCollIdent, new ident("GetEnumerator")), new expression_list()));

            //var curr := en.Current;
            // Переменная цикла foreach. Есть три варианта:
            // 1. foreach x in l do           ->    curr := en.Current;
            // 2. foreach var x in l do       ->    var curr := en.Current;
            // 3. foreach var x: T in l do    ->    var curr: T := en.Current;
            var       currentIdent = frch.identifier;
            statement st           = null;

            var curExpr = new dot_node(enumeratorIdent, "Current");

            // С типом
            if (frch.type_name == null) // 1. foreach x in l do   ->   curr := en.Current;
            {
                st = new assign(currentIdent, curExpr);
            }
            else if (frch.type_name is no_type_foreach) // 2. foreach var x in l do    ->    var curr := en.Current;
            {
                // Получаем служебное имя с $ и заменяем его в теле цикла
                currentIdent = this.NewVarNames(frch.identifier).VarName;
                var replacerVis = new ReplaceVariableNameVisitor(frch.identifier, currentIdent);
                frch.visit(replacerVis);

                st = new var_statement(currentIdent, curExpr);
            }
            else // 3. foreach var x: T in l do    ->    var curr: T := en.Current;
            {
                // Получаем служебное имя с $ и заменяем его в теле цикла
                currentIdent = this.NewVarNames(frch.identifier).VarName;
                var replacerVis = new ReplaceVariableNameVisitor(frch.identifier, currentIdent);
                frch.visit(replacerVis);

                st = new var_statement(currentIdent, frch.type_name, curExpr);
            }

            // Добавляем тело цикла в stl
            var stl = new statement_list(st);

            ProcessNode(frch.stmt); // для обработки вложенных конструкций
            stl.Add(frch.stmt);

            var whileNode = new while_node(new method_call(new dot_node(enumeratorIdent, "MoveNext"), new expression_list()),
                                           stl,
                                           WhileCycleType.While);

            var sq = SeqStatements(foreachCollVarDef, ass, enumeratorVarDef, whileNode);

            ReplaceStatement(frch, sq);

            visit(whileNode); // Lowering оставшегося whileNode
        }
Example #22
0
 public virtual void visit(foreach_stmt _foreach_stmt)
 {
 }
Example #23
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);
        }