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); }
private bool IsIList(expression_node en) { var ii = en.type.ImplementingInterfaces; if (ii != null) { foreach (var itn in ii) { System.Type tt = null; if (itn is compiled_type_node ctn) { tt = ctn.compiled_type; if (tt.IsGenericType) { tt = tt.GetGenericTypeDefinition(); } if (tt == typeof(System.Collections.Generic.IList <>)) { return(true); } } else if (itn is compiled_generic_instance_type_node itnc) { tt = (itnc.original_generic as compiled_type_node).compiled_type; if (tt == typeof(System.Collections.Generic.IList <>)) { return(true); } } } } return(false); }
private void VisitAssignment(base_function_call en) { for (int i = 1; i < en.parameters.Count; i++) { VisitExpression(en.parameters[i]); } expression_node p = en.parameters[0]; switch (p.semantic_node_type) { case semantic_node_type.local_variable_reference: IncreaseNumAssVar((local_variable_reference)p); break; case semantic_node_type.local_block_variable_reference: IncreaseNumAssVar((local_block_variable_reference)p); break; case semantic_node_type.namespace_variable_reference: IncreaseNumAssVar((namespace_variable_reference)p); break; case semantic_node_type.class_field_reference: VisitExpression((p as class_field_reference).obj); IncreaseNumAssField((class_field_reference)p); break; case semantic_node_type.static_class_field_reference: IncreaseNumAssField((static_class_field_reference)p); break; case semantic_node_type.common_parameter_reference: IncreaseNumAssParam((common_parameter_reference)p); break; case semantic_node_type.deref_node: CheckAssign(((dereference_node)p).deref_expr); break; case semantic_node_type.simple_array_indexing: VisitSimpleArrayIndexing((simple_array_indexing)p); break; } }
/// <summary> /// Проверяет, подходит ли фаункция для вызова с указанными параметрами /// </summary> /// <param name="candidate"></param> /// <param name="givenParameterTypes">Типы параметров, указанные пользователем</param> /// <returns></returns> private bool IsSuitableFunction( function_node candidate, type_node[] givenParameterTypes, expression_node patternInstance, location deconstructionLocation, out type_node[] parameterTypes) { parameterTypes = new type_node[givenParameterTypes.Length]; var selfParameter = candidate.is_extension_method ? candidate.parameters.First(IsSelfParameter) : null; Debug.Assert(!candidate.is_extension_method || selfParameter != null, "Couldn't find self parameter in extension method"); var candidateParameterTypes = candidate.is_extension_method ? candidate.parameters.Where(x => !IsSelfParameter(x)).ToArray() : candidate.parameters.ToArray(); if (candidateParameterTypes.Length != givenParameterTypes.Length) { return(false); } // Разрешаем только deconstruct текущего класса, родительские в расчет не берем if (candidate is common_method_node commonMethod && !AreTheSameType(patternInstance.type, commonMethod.cont_type)) { return(false); } var genericDeduceNeeded = candidate.is_extension_method && candidate.is_generic_function; type_node[] deducedGenerics = new type_node[candidate.generic_parameters_count]; if (genericDeduceNeeded) { // Выводим дженерики по self var nils = new List <int>(); var deduceSucceded = generic_convertions.DeduceInstanceTypes(selfParameter.type, patternInstance.type, deducedGenerics, nils); if (!deduceSucceded || deducedGenerics.Contains(null)) { return(false); } } for (int i = 0; i < givenParameterTypes.Length; i++) { var givenParameter = givenParameterTypes[i]; var candidateParameter = candidateParameterTypes[i].type; if (genericDeduceNeeded && (candidateParameter.is_generic_parameter || candidateParameter.is_generic_type_instance)) { candidateParameter = InstantiateParameter(candidateParameter, deducedGenerics); } if (givenParameter != null && !AreTheSameType(candidateParameter, givenParameter)) { return(false); } parameterTypes[i] = candidateParameter; } return(true); }
/// <summary> /// Автовыведение типов в yield'ax. /// </summary> private void ProcessAssigntToAutoType(addressed_expression to, ref expression_node from) { var sequence = to.type as compiled_generic_instance_type_node; // SSM 26.06.16 - правка в связи с автовыведением типов в yieldах if (to.type is auto_type) { try_convert_typed_expression_to_function_call(ref from); if (to is class_field_reference) { var cfr = to as class_field_reference; cfr.field.type = from.type; cfr.type = from.type; // Это неверно работает когда yieldится процедура #1439 // SSM 1.11.18 попытка правки возвращения процедуры в yield //if (from.type.semantic_node_type == semantic_node_type.delegated_method) cfr.field.inital_value = context.GetInitalValueForVariable(cfr.field, cfr.field.inital_value); } else if (to is local_block_variable_reference) { var lvr = to as local_block_variable_reference; lvr.var.type = from.type; lvr.type = from.type; lvr.var.inital_value = context.GetInitalValueForVariable(lvr.var, lvr.var.inital_value); } else { AddError(to.location, "Не могу вывести тип при наличии yield: " + to.type.full_name); } //to.type = from.type; // и без всякого real_type! } else if (sequence?.instance_params[0] is ienumerable_auto_type) { type_node elem_type = null; try_convert_typed_expression_to_function_call(ref from); bool bb; // здесь bb не нужно. Оно нужно в foreach var b = FindIEnumerableElementType(from.type, ref elem_type, out bb); if (!b) { AddError(from.location, "CAN_NOT_EXECUTE_FOREACH_BY_EXPR_OF_TYPE_{0}", from.type.full_name); } var IEnumType = new template_type_reference(new named_type_reference("System.Collections.Generic.IEnumerable"), new template_param_list(new semantic_type_node(elem_type))); if (to is class_field_reference) { var cfr = to as class_field_reference; cfr.field.type = convert_strong(IEnumType); cfr.type = cfr.field.type; } else if (to is local_block_variable_reference) { var lvr = to as local_block_variable_reference; lvr.var.type = convert_strong(IEnumType); // замена типа у описания переменной lvr.type = lvr.var.type; // замена типа у переменной } } }
public expression_node visit(SyntaxTree.expression expr) { expr.visit(syntax_tree_visitor); /*addressed_expression ad = ret_semantic as addressed_expression; * if (ad != null && ad.is_addressed) * { * if (convertion_data_and_alghoritms.check_for_constant(ad)) * ad.is_addressed = false; * }*/ //Надеюсь, это сильно не скажется на производительности, хотя в другом случае этот же код просто будет разбросан по всем метдам syntax_tree_visitor-а. base_function_call bfc = ret_semantic as base_function_call; if (bfc != null) { if (bfc.simple_function_node.compile_time_executor != null) { expression_node ex = bfc.simple_function_node.compile_time_executor(bfc.location, bfc.parameters.ToArray()); if (ex != null) { return(ex); } } } return(ret_semantic as expression_node); }
/// <summary> /// Проверяет, подходит ли фаункция для вызова с указанными параметрами /// </summary> /// <param name="candidate"></param> /// <param name="givenParameterTypes">Типы параметров, указанные пользователем</param> /// <returns></returns> private bool IsSuitableFunction( function_node candidate, type_node[] givenParameterTypes, expression_node patternInstance, location deconstructionLocation, out type_node[] parameterTypes) { parameterTypes = new type_node[givenParameterTypes.Length]; var selfParameter = candidate.is_extension_method ? candidate.parameters.First(IsSelfParameter) : null; Debug.Assert(!candidate.is_extension_method || selfParameter != null, "Couldn't find self parameter in extension method"); var candidateParameterTypes = candidate.is_extension_method ? candidate.parameters.Where(x => !IsSelfParameter(x)).ToArray() : candidate.parameters.ToArray(); if (candidateParameterTypes.Length != givenParameterTypes.Length) { return(false); } var genericDeduceNeeded = candidate.is_extension_method && candidate.is_generic_function; type_node[] deducedGenerics = new type_node[candidate.generic_parameters_count]; if (genericDeduceNeeded) { // Выводим дженерики по self var nils = new List <int>(); var deduceSucceded = generic_convertions.DeduceInstanceTypes(selfParameter.type, patternInstance.type, deducedGenerics, nils); if (!deduceSucceded || deducedGenerics.Contains(null)) { // Проверка на то, что в Deconstruct все дженерики выводятся по self делается в другом месте // TODO Patterns: сделать проверку из коммента выше // TODO Patterns: запретить дженерик методы в классах. Можно использовать только дженерик-типы самого класса в качестве параметров //AddError(deconstructionLocation, "COULDNT_DEDUCE_DECONSTRUCT_GENERIC_TYPE"); return(false); } } for (int i = 0; i < givenParameterTypes.Length; i++) { var givenParameter = givenParameterTypes[i]; var candidateParameter = candidateParameterTypes[i].type; if (genericDeduceNeeded && (candidateParameter.is_generic_parameter || candidateParameter.is_generic_type_instance)) { candidateParameter = InstantiateParameter(candidateParameter, deducedGenerics); } if (givenParameter != null && !AreTheSameType(candidateParameter, givenParameter)) { return(false); } parameterTypes[i] = candidateParameter; } return(true); }
public static bool IsCapturedSelf(expression_node ex) { if (ex is class_field_reference) { class_field fld = (ex as class_field_reference).field; if (fld.name.Contains("<>local_variables_class")) { return(true); } } return(false); }
/// <summary> /// Выводит тип результата лямбды по первому присваиванию переменной Result. /// </summary> private void InferLambdaResultTypeFromAssignment(assign _assign, expression_node from, addressed_expression to) { if (stflambda.Count > 0) // мы находимся внутри лямбды - возможно, вложенной { var fld = stflambda.Peek(); if (_assign.to is ident && (_assign.to as ident).name.ToLower() == "result" && fld.RealSemTypeOfResExpr == null) // если это - первое присваивание Result { fld.RealSemTypeOfResExpr = from.type; fld.RealSemTypeOfResult = to.type; } } }
private void CheckType(type_node type, expression_node initial_value, location loc) { /*if (type.IsPointer && type.element_type.is_value_type && type.element_type is common_type_node) * { * AddHint("DO_NOT_USE_POINTERS_TO_RECORDS", loc); * }*/ if (type.type_special_kind == SemanticTree.type_special_kind.short_string && !(current_type != null && current_type.is_value)) { AddHint("DO_NOT_USE_SHORT_STRINGS", loc); } else if (type.type_special_kind == SemanticTree.type_special_kind.array_kind || type.type_special_kind == SemanticTree.type_special_kind.array_wrapper) { CheckType(type.element_type, initial_value, loc); } }
private void CheckAssign(expression_node p) { switch (p.semantic_node_type) { case semantic_node_type.local_variable_reference: IncreaseNumAssVar((local_variable_reference)p); break; case semantic_node_type.namespace_variable_reference: IncreaseNumAssVar((namespace_variable_reference)p); break; case semantic_node_type.class_field_reference: VisitExpression((p as class_field_reference).obj); IncreaseNumAssField((class_field_reference)p); break; case semantic_node_type.static_class_field_reference: IncreaseNumAssField((static_class_field_reference)p); break; case semantic_node_type.common_parameter_reference: IncreaseNumAssParam((common_parameter_reference)p); break; case semantic_node_type.deref_node: CheckAssign(((dereference_node)p).deref_expr); break; } }
private RetVal GetConstantValue(expression_node en) { if (en is bool_const_node) { if ((en as bool_const_node).constant_value) { return(RetVal.True); } else { return(RetVal.False); } } else { return(RetVal.Undef); } }
private bool Is1DArray(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; } } return(is1dimdynarr); }
/// <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); }
private void VisitExpression(expression_node en) { if (en == null) { return; } //WriteDebugInfo(en.location); switch (en.semantic_node_type) { case semantic_node_type.exit_procedure: /*ничего писать не надо*/ break; case semantic_node_type.typeof_operator: //VisitTypeOfOperator((typeof_operator)en); break; case semantic_node_type.statement_expression_node: VisitStatementsExpressionNode((statements_expression_node)en); break; case semantic_node_type.question_colon_expression: VisitQuestionColonExpression((question_colon_expression)en); break; case semantic_node_type.sizeof_operator: VisitSizeOfOperator((sizeof_operator)en); break; case semantic_node_type.is_node: VisitIsNode((is_node)en); break; case semantic_node_type.as_node: VisitAsNode((as_node)en); break; case semantic_node_type.compiled_static_method_call_node_as_constant: //VisitCompiledStaticMethodCallNodeAsConstant((compiled_static_method_call_as_constant)en); break; case semantic_node_type.array_initializer: VisitArrayInitializer((array_initializer)en); break; case semantic_node_type.record_initializer: VisitRecordInitializer((record_initializer)en); break; case semantic_node_type.array_const: //VisitArrayConst((array_const)en); break; case semantic_node_type.record_const: //VisitRecordConst((record_constant)en); break; case semantic_node_type.float_const_node: //VisitFloatConst((float_const_node)en); break; case semantic_node_type.byte_const_node: //VisitByteConstNode((byte_const_node)en); break; case semantic_node_type.int_const_node: //VisitIntConstNode((int_const_node)en); break; case semantic_node_type.sbyte_const_node: //VisitSByteConstNode((sbyte_const_node)en); break; case semantic_node_type.short_const_node: //VisitShortConstNode((short_const_node)en); break; case semantic_node_type.ushort_const_node: //VisitUShortConstNode((ushort_const_node)en); break; case semantic_node_type.uint_const_node: //VisitUIntConstNode((uint_const_node)en); break; case semantic_node_type.ulong_const_node: //VisitULongConstNode((ulong_const_node)en); break; case semantic_node_type.long_const_node: //VisitLongConstNode((long_const_node)en); break; case semantic_node_type.double_const_node: //VisitDoubleConstNode((double_const_node)en); break; case semantic_node_type.char_const_node: //VisitCharConstNode((char_const_node)en); break; case semantic_node_type.bool_const_node: //VisitBoolConstNode((bool_const_node)en); break; case semantic_node_type.string_const_node: //VisitStringConstNode((string_const_node)en); break; case semantic_node_type.local_variable_reference: VisitLocalVariableReference((local_variable_reference)en); break; case semantic_node_type.namespace_variable_reference: VisitNamespaceVariableReference((namespace_variable_reference)en); break; case semantic_node_type.basic_function_call: VisitBasicFunctionCall((basic_function_call)en); break; case semantic_node_type.common_parameter_reference: VisitCommonParameterReference((common_parameter_reference)en); break; case semantic_node_type.common_namespace_function_call: VisitCommonNamespaceFunctionCall((common_namespace_function_call)en); break; case semantic_node_type.basic_function_call_node_as_constant: VisitBasicFunctionCall((en as basic_function_call_as_constant).method_call); break; case semantic_node_type.common_namespace_function_call_node_as_constant: VisitCommonNamespaceFunctionCallAsConstant((common_namespace_function_call_as_constant)en); break; case semantic_node_type.common_in_function_function_call: VisitCommonInFuncFuncCall((common_in_function_function_call)en); break; case semantic_node_type.while_break_node: //VisitWhileBreakNode((while_break_node)en); is_break_stmt = true; break; case semantic_node_type.while_continue_node: //VisitWhileContinueNode((while_continue_node)en); is_break_stmt = true; break; case semantic_node_type.for_break_node: //VisitForBreakNode((for_break_node)en); is_break_stmt = true; break; case semantic_node_type.for_continue_node: //VisitForContinueNode((for_continue_node)en); is_break_stmt = true; break; case semantic_node_type.repeat_break_node: //VisitRepeatBreakNode((repeat_break_node)en); is_break_stmt = true; break; case semantic_node_type.repeat_continue_node: //VisitRepeatContinueNode((repeat_continue_node)en); is_break_stmt = true; break; case semantic_node_type.foreach_break_node: is_break_stmt = true; break; case semantic_node_type.foreach_continue_node: is_break_stmt = true; break; case semantic_node_type.common_static_method_call: VisitCommonStaticMethodCall((common_static_method_call)en); break; case semantic_node_type.compiled_static_method_call: VisitCompiledStaticMethodCall((compiled_static_method_call)en); break; case semantic_node_type.class_field_reference: VisitClassFieldReference((class_field_reference)en); break; case semantic_node_type.deref_node: VisitDerefNode((dereference_node)en); break; case semantic_node_type.common_method_call: VisitCommonMethodCall((common_method_call)en); break; case semantic_node_type.compiled_function_call: VisitCompiledFunctionCall((compiled_function_call)en); break; case semantic_node_type.get_addr_node: VisitGetAddrNode((get_addr_node)en); break; case semantic_node_type.common_constructor_call: VisitCommonConstructorCall((common_constructor_call)en); break; case semantic_node_type.compiled_constructor_call: VisitCompiledConstructorCall((compiled_constructor_call)en); break; case semantic_node_type.compiled_variable_reference: VisitCompiledVariableReference((compiled_variable_reference)en); break; case semantic_node_type.local_block_variable_reference: VisitLocalBlockVariableReference((local_block_variable_reference)en); break; case semantic_node_type.static_compiled_variable_reference: //VisitStaticCompiledVariableReference((static_compiled_variable_reference)en); break; case semantic_node_type.static_class_field_reference: VisitStaticClassFieldReference((static_class_field_reference)en); break; case semantic_node_type.non_static_property_reference: VisitNonStaticPropertyReference((non_static_property_reference)en); break; case semantic_node_type.simple_array_indexing: VisitSimpleArrayIndexing((simple_array_indexing)en); break; case semantic_node_type.this_node: //VisitThisNode((this_node)en); break; case semantic_node_type.null_const_node: //VisitNullConstNode((null_const_node)en); break; //default: ;//Console.WriteLine(en.semantic_node_type); throw new Exception("Unknown expression"); } }
/// <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); }
/// <summary> /// Обрабатывает случай, когда левая часть присваивания свойство. /// </summary> /// <returns>True - обработка прошла, иначе False.</returns> private bool ProcessAssignToPropertyIfPossible(assign _assign, addressed_expression to, location loc, expression_node from) { //проверка на обращение к полю записи возвращенной из функции с целью присваивания //нужно чтобы пользователь не мог менять временный обьект if (to.semantic_node_type == semantic_node_type.static_property_reference || to.semantic_node_type == semantic_node_type.non_static_property_reference) { property_node pn; if (to.semantic_node_type == semantic_node_type.static_property_reference) { pn = (to as static_property_reference).property; } else { pn = (to as non_static_property_reference).property; } var ot = MapCompositeAssignmentOperatorToSameBinaryOperator(_assign); var oper_ass_in_prop = ot != Operators.Undefined; if (_assign.operator_type == Operators.Assignment || oper_ass_in_prop) { if (oper_ass_in_prop) { if (pn.get_function == null) { AddError(loc, "THIS_PROPERTY_{0}_CAN_NOT_BE_READED", pn.name); } base_function_call prop_expr; if (to.semantic_node_type == semantic_node_type.non_static_property_reference) { prop_expr = create_not_static_method_call(pn.get_function, (to as non_static_property_reference).expression, loc, false); prop_expr.parameters.AddRange((to as non_static_property_reference).fact_parametres); } else { prop_expr = create_static_method_call(pn.get_function, loc, pn.comprehensive_type, false); prop_expr.parameters.AddRange((to as static_property_reference).fact_parametres); } from = find_operator(ot, prop_expr, from, loc); } if (to.semantic_node_type == semantic_node_type.static_property_reference) { static_property_reference spr = (static_property_reference)to; if (spr.property.set_function == null) { AddError(loc, "THIS_PROPERTY_{0}_CAN_NOT_BE_WRITED", spr.property.name); } check_property_params(spr, loc); function_node set_func = spr.property.set_function; from = convertion_data_and_alghoritms.convert_type(from, spr.property.property_type); spr.fact_parametres.AddElement(from); base_function_call bfc = create_static_method_call(set_func, loc, spr.property.comprehensive_type, true); bfc.parameters.AddRange(spr.fact_parametres); return_value((statement_node)bfc); } else if (to.semantic_node_type == semantic_node_type.non_static_property_reference) { non_static_property_reference nspr = (non_static_property_reference)to; check_property_params(nspr, loc); from = convertion_data_and_alghoritms.convert_type(from, nspr.property.property_type); nspr.fact_parametres.AddElement(from); //Обработка s[i]:='c' if (SystemUnitAssigned) { if (nspr.property.comprehensive_type == SystemLibrary.SystemLibrary.string_type) { if (nspr.property == SystemLibrary.SystemLibrary.string_type.default_property_node) { if (SystemLibInitializer.StringDefaultPropertySetProcedure != null) { expressions_list exl = new expressions_list(); exl.AddElement(nspr.expression); exl.AddElement(nspr.fact_parametres[0]); exl.AddElement(from); function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibInitializer.StringDefaultPropertySetProcedure .SymbolInfo, loc); expression_node ret = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, exl.ToArray()); return_value((statement_node)ret); return(true); } } } } if (nspr.property.set_function == null) { AddError(loc, "THIS_PROPERTY_{0}_CAN_NOT_BE_WRITED", nspr.property.name); } function_node set_func = nspr.property.set_function; base_function_call bfc = create_not_static_method_call(set_func, nspr.expression, loc, true); bfc.parameters.AddRange(nspr.fact_parametres); return_value((statement_node)bfc); } return(true); } } return(false); }
/// <summary> /// Автовыведение типов в yield'ax. /// </summary> private void ProcessAssigntToAutoType(addressed_expression to, ref expression_node from) { var sequence = to.type as compiled_generic_instance_type_node; // SSM 26.06.16 - правка в связи с автовыведением типов в yieldах if (to.type is auto_type) { try_convert_typed_expression_to_function_call(ref from); if (to is class_field_reference) { var cfr = to as class_field_reference; if (from is typed_expression) // SSM 22.12.18 syntax_tree_visitor.cs 16066 - взял оттуда { base_function_call bfc = ((from as typed_expression).type as delegated_methods).proper_methods[0]; /*if (bfc.function.is_generic_function && _var_def_statement.vars_type == null) * { * AddError(inital_value.location, "CAN_NOT_DEDUCE_TYPE_{0}", null); * } * foreach (parameter p in bfc.simple_function_node.parameters) * { * if (p.type.is_generic_parameter) * AddError(inital_value.location, "USE_ANONYMOUS_FUNCTION_TYPE_WITH_GENERICS"); * } */ common_type_node del = convertion_data_and_alghoritms.type_constructor.create_delegate(context.get_delegate_type_name(), bfc.simple_function_node.return_value_type, bfc.simple_function_node.parameters, context.converted_namespace, null); context.converted_namespace.types.AddElement(del); //- сомневаюсь - контекст уже поменялся! //tn = del; from = convertion_data_and_alghoritms.explicit_convert_type(from, del); from.type = del; } cfr.field.type = from.type; cfr.type = from.type; // Это неверно работает когда yieldится процедура #1439 // SSM 1.11.18 попытка правки возвращения процедуры в yield //if (from.type.semantic_node_type == semantic_node_type.delegated_method) //cfr.type.semantic_node_type = semantic_node_type.delegated_method; cfr.field.inital_value = context.GetInitalValueForVariable(cfr.field, cfr.field.inital_value); } else if (to is local_block_variable_reference) { var lvr = to as local_block_variable_reference; lvr.var.type = from.type; lvr.type = from.type; lvr.var.inital_value = context.GetInitalValueForVariable(lvr.var, lvr.var.inital_value); } else { AddError(to.location, "Не могу вывести тип при наличии yield: " + to.type.full_name); } //to.type = from.type; // и без всякого real_type! } else if (sequence?.instance_params[0] is ienumerable_auto_type) { type_node elem_type = null; try_convert_typed_expression_to_function_call(ref from); bool bb; // здесь bb не нужно. Оно нужно в foreach var b = FindIEnumerableElementType(from.type, ref elem_type, out bb); if (!b) { AddError(from.location, "CAN_NOT_EXECUTE_FOREACH_BY_EXPR_OF_TYPE_{0}", from.type.full_name); } var IEnumType = new template_type_reference(new named_type_reference("System.Collections.Generic.IEnumerable"), new template_param_list(new semantic_type_node(elem_type))); if (to is class_field_reference) { var cfr = to as class_field_reference; cfr.field.type = convert_strong(IEnumType); cfr.type = cfr.field.type; } else if (to is local_block_variable_reference) { var lvr = to as local_block_variable_reference; lvr.var.type = convert_strong(IEnumType); // замена типа у описания переменной lvr.type = lvr.var.type; // замена типа у переменной } } }
/// <summary> /// Преобразует в семантическое представление поля to и from, проводя семантические проверки. /// </summary> private void AssignCheckAndConvert(assign _assign, out addressed_expression to, out expression_node from) { internal_is_assign = true; to = convert_address_strong(_assign.to); internal_is_assign = false; if (to == null) { AddError(get_location(_assign.to), "CAN_NOT_ASSIGN_TO_LEFT_PART"); } //(ssyy) Вставляю проверки прямо сюда, т.к. запарился вылавливать другие случаи. bool flag; general_node_type node_type; if (convertion_data_and_alghoritms.check_for_constant_or_readonly(to, out flag, out node_type)) { if (flag) { AddError(to.location, "CAN_NOT_ASSIGN_TO_CONSTANT_OBJECT"); } else { AddError(new CanNotAssignToReadOnlyElement(to.location, node_type)); } } // SSM исправление Саушкина 10.03.16 var fromAsLambda = _assign.from as function_lambda_definition; if (fromAsLambda != null) { #region Вывод параметров лямбда-выражения LambdaHelper.InferTypesFromVarStmt(to.type, fromAsLambda, this); //lroman// #endregion var lambdaVisitMode = fromAsLambda.lambda_visit_mode; fromAsLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; from = convert_strong(_assign.from); fromAsLambda.lambda_visit_mode = lambdaVisitMode; } else { from = convert_strong(_assign.from); ProcessAssigntToAutoType(to, ref from); } // end //SSM 4.04.16 if (to.type is undefined_type) { to.type = from.type; } location loc = get_location(_assign); if (to is class_field_reference) { var classFieldRef = to as class_field_reference; if (classFieldRef.obj.type.type_special_kind == type_special_kind.record && classFieldRef.obj is base_function_call) { //исключим ситуацию обращения к массиву if (!(classFieldRef.obj is common_method_call && (classFieldRef.obj as common_method_call).obj.type.type_special_kind == type_special_kind.array_wrapper)) { AddError(loc, "LEFT_SIDE_CANNOT_BE_ASSIGNED_TO"); } } //else check_field_reference_for_assign(to as class_field_reference,loc); } if (context.is_in_cycle() && !SemanticRules.AllowChangeLoopVariable) { var_definition_node toAsVariable = GetLocalVariableFromAdressExpressionIfPossible(to); if (toAsVariable != null && context.is_loop_variable(toAsVariable)) { AddError(to.location, "CANNOT_ASSIGN_TO_LOOP_VARIABLE"); } } { var classFieldRef = (to as simple_array_indexing)?.simple_arr_expr as class_field_reference; if (classFieldRef?.obj is constant_node) { AddError(loc, "LEFT_SIDE_CANNOT_BE_ASSIGNED_TO"); } } }
/// <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); }
private type_node[] InferAndCheckPatternVariableTypes(List <var_def_statement> variableDefinitions, expression_node patternInstance, desugared_deconstruction deconstruction) { var parameterTypes = variableDefinitions.Select(x => x.vars_type == null ? null : convert_strong(x.vars_type)).ToArray(); List <function_node> candidates = new List <function_node>(); List <type_node[]> deducedParametersList = new List <type_node[]>(); var allDeconstructs = patternInstance.type.find_in_type(compiler_string_consts.deconstruct_method_name, context.CurrentScope); foreach (var canditateSymbol in allDeconstructs) { var deducedParameters = new type_node[parameterTypes.Length]; var possibleCandidate = canditateSymbol.sym_info as function_node; if (!IsSuitableFunction(possibleCandidate, parameterTypes, patternInstance, get_location(deconstruction), out deducedParameters)) { continue; } deducedParametersList.Add(deducedParameters); candidates.Add(possibleCandidate); } if (candidates.Count == 0) { AddError(get_location(deconstruction), "NO_SUITABLE_DECONSTRUCT_FOUND"); return(null); } else if (candidates.Count > 1) { RemoveDefaultDeconstruct(candidates); if (candidates.Count > 1 && !CheckIfParameterListElementsAreTheSame(deducedParametersList)) { AddError(get_location(deconstruction), "DECONSTRUCTOR_METHOD_AMBIGUITY"); return(null); } } // Единственный подхдящий кандидат найден, либо их несколько, с одинаковыми выходными параметрами var chosenFunction = candidates.First(); if (chosenFunction.is_extension_method) { if (chosenFunction.is_generic_function) { chosenFunction = generic_convertions.get_function_instance(chosenFunction, deducedParametersList.First().ToList()); } return(chosenFunction.parameters.Where(x => !IsSelfParameter(x)).Select(x => x.type).ToArray()); } else { return(chosenFunction.parameters.Select(x => x.type).ToArray());//deducedParametersList[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); }