public override void visit(assign _assign) { var loc = get_location(_assign); addressed_expression to; expression_node from; AssignCheckAndConvert(_assign, out to, out from); InferLambdaResultTypeFromAssignment(_assign, from, to); if (ProcessAssignToPropertyIfPossible(_assign, to, loc, from)) { return; } if (ProcessAssignmentToEventIfPossible(_assign, to, from, loc)) { return; } if (ProcessAssignmentToShortStringIfPossible(_assign, to, from, loc)) { return; } assign_is_converting = true; statement_node en = find_operator(_assign.operator_type, to, from, get_location(_assign)); assign_is_converting = false; return_value(en); }
private void VisitStatement(statement_node sn) { if (sn == null) { return; } if (!(sn is statements_list) && is_break_stmt) { warns.Add(new UnreachableCodeDetected(sn.location)); is_break_stmt = false; } if (sn is expression_node) { VisitExpression((expression_node)sn); return; } switch (sn.semantic_node_type) { case semantic_node_type.if_node: VisitIf((if_node)sn); break; case semantic_node_type.while_node: VisitWhile((while_node)sn); break; case semantic_node_type.repeat_node: VisitRepeat((repeat_node)sn); break; case semantic_node_type.for_node: VisitFor((for_node)sn); break; case semantic_node_type.statements_list: VisitStatementList((statements_list)sn); break; case semantic_node_type.empty_statement: VisitEmpty((empty_statement)sn); break; case semantic_node_type.return_node: VisitReturnNode((return_node)sn); break; case semantic_node_type.switch_node: VisitSwitchNode((switch_node)sn); break; case semantic_node_type.external_statement_node: VisitExternalStatementNode((external_statement)sn); break; case semantic_node_type.pinvoke_node: VisitPInvokeStatementNode((pinvoke_statement)sn); break; case semantic_node_type.throw_statement: VisitThrow((throw_statement_node)sn); break; case semantic_node_type.runtime_statement: VisitRuntimeStatement((runtime_statement)sn); break; case semantic_node_type.try_block: VisitTryBlock((try_block)sn); break; case semantic_node_type.labeled_statement: VisitLabeledStatement((labeled_statement)sn); break; case semantic_node_type.goto_statement: VisitGoto((goto_statement)sn); break; case semantic_node_type.foreach_node: VisitForeach((foreach_node)sn); break; case semantic_node_type.lock_statement: VisitLockStatement((lock_statement)sn); break; } }
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 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(assign _assign) { var loc = get_location(_assign); addressed_expression to; expression_node from; AssignCheckAndConvert(_assign, out to, out from); InferLambdaResultTypeFromAssignment(_assign, from, to); if (ProcessAssignToPropertyIfPossible(_assign, to, loc, from)) { return; } if (ProcessAssignmentToEventIfPossible(_assign, to, from, loc)) { return; } if (ProcessAssignmentToShortStringIfPossible(_assign, to, from, loc)) { return; } assign_is_converting = true; if (to.type.type_special_kind == type_special_kind.set_type && from.type.type_special_kind == type_special_kind.set_type && // SSM 12/07/19 fix #1795 convertion_data_and_alghoritms.is_value_int_type(to.type.element_type) && convertion_data_and_alghoritms.is_value_real_type(from.type.element_type)) { AddError(new CanNotConvertTypes(from, from.type, to.type, from.location)); } statement_node en = find_operator(_assign.operator_type, to, from, get_location(_assign)); assign_is_converting = false; return_value(en); }
/// <summary> /// Обрабатывает случай, когда левая часть присваивания short string. /// </summary> /// <returns>True - обработка прошла, иначе False.</returns> private bool ProcessAssignmentToShortStringIfPossible(assign _assign, addressed_expression to, expression_node from, location loc) { if (_assign.operator_type == Operators.Assignment) { if (to is simple_array_indexing && (to as simple_array_indexing).simple_arr_expr.type.type_special_kind == type_special_kind.short_string) { expression_node expr = (to as simple_array_indexing).simple_arr_expr; expression_node ind_expr = (to as simple_array_indexing).ind_expr; from = convertion_data_and_alghoritms.convert_type(from, SystemLibrary.SystemLibrary.char_type); ind_expr = convertion_data_and_alghoritms.create_simple_function_call( SystemLibInitializer.SetCharInShortStringProcedure.sym_info as function_node, loc, expr, ind_expr, new int_const_node((expr.type as short_string_type_node).Length, null), from); return_value(find_operator(compiler_string_consts.assign_name, expr, ind_expr, get_location(_assign))); return(true); } if (to.type.type_special_kind == type_special_kind.short_string) { if (from.type is null_type_node) { AddError(get_location(_assign), "NIL_WITH_VALUE_TYPES_NOT_ALLOWED"); } expression_node clip_expr = convertion_data_and_alghoritms.create_simple_function_call( SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node, loc, convertion_data_and_alghoritms.convert_type(from, SystemLibrary.SystemLibrary.string_type), new int_const_node((to.type as short_string_type_node).Length, null)); statement_node en = find_operator(compiler_string_consts.assign_name, to, clip_expr, get_location(_assign)); return_value(en); return(true); } } return(false); }
/// <summary> /// Обрабатывает случай, когда левая часть присваивания имеет тип event. /// </summary> /// <returns>True - обработка прошла, иначе False.</returns> private bool ProcessAssignmentToEventIfPossible(assign _assign, addressed_expression to, expression_node from, location loc) { if ((to.semantic_node_type == semantic_node_type.static_event_reference) || (to.semantic_node_type == semantic_node_type.nonstatic_event_reference)) { statement_node event_assign = null; static_event_reference ser = (static_event_reference)to; expression_node right_del = convertion_data_and_alghoritms.convert_type(from, ser.en.delegate_type); switch (_assign.operator_type) { case Operators.AssignmentAddition: { if (to.semantic_node_type == semantic_node_type.static_event_reference) { event_assign = convertion_data_and_alghoritms.create_simple_function_call( ser.en.add_method, loc, right_del); } else { if (ser.en.semantic_node_type == semantic_node_type.compiled_event) { nonstatic_event_reference nser = (nonstatic_event_reference)ser; compiled_function_node cfn = (compiled_function_node)ser.en.add_method; compiled_function_call tmp_event_assign = new compiled_function_call(cfn, nser.obj, loc); tmp_event_assign.parameters.AddElement(right_del); event_assign = tmp_event_assign; } else if (ser.en.semantic_node_type == semantic_node_type.common_event) { nonstatic_event_reference nser = (nonstatic_event_reference)ser; common_method_node cfn = (common_method_node)ser.en.add_method; common_method_call tmp_event_assign = new common_method_call(cfn, nser.obj, loc); tmp_event_assign.parameters.AddElement(right_del); event_assign = tmp_event_assign; } } break; } case Operators.AssignmentSubtraction: { if (to.semantic_node_type == semantic_node_type.static_event_reference) { event_assign = convertion_data_and_alghoritms.create_simple_function_call( ser.en.remove_method, loc, right_del); } else { if (ser.en.semantic_node_type == semantic_node_type.compiled_event) { nonstatic_event_reference nser = (nonstatic_event_reference)ser; compiled_function_node cfn = (compiled_function_node)ser.en.remove_method; compiled_function_call tmp_event_assign = new compiled_function_call(cfn, nser.obj, loc); tmp_event_assign.parameters.AddElement(right_del); event_assign = tmp_event_assign; } else if (ser.en.semantic_node_type == semantic_node_type.common_event) { nonstatic_event_reference nser = (nonstatic_event_reference)ser; common_method_node cfn = (common_method_node)ser.en.remove_method; common_method_call tmp_event_assign = new common_method_call(cfn, nser.obj, loc); tmp_event_assign.parameters.AddElement(right_del); event_assign = tmp_event_assign; } } break; } default: { AddError(loc, "ASSIGN_TO_EVENT"); //throw new CanNotApplyThisOperationToEvent break; } } return_value(event_assign); return(true); } return(false); }
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); }
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); }