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"); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
/// <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); }
public override void visit(foreach_stmt _foreach_stmt) { }
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; }
public virtual void visit(foreach_stmt _foreach_stmt) { DefaultVisit(_foreach_stmt); }
public virtual void visit(foreach_stmt _foreach_stmt) { }
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); }
public virtual void post_do_visit(foreach_stmt _foreach_stmt) { }
public override void visit(foreach_stmt fn) { ForeachCount++; base.visit(fn); }
// 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 }
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); }