2017-08-11 04:05:25 +03:00
|
|
|
|
using PascalABCCompiler.SemanticTree;
|
2017-08-04 13:29:53 +03:00
|
|
|
|
using PascalABCCompiler.SyntaxTree;
|
2017-08-11 04:05:25 +03:00
|
|
|
|
using PascalABCCompiler.SystemLibrary;
|
2017-08-04 13:29:53 +03:00
|
|
|
|
using PascalABCCompiler.TreeRealization;
|
|
|
|
|
|
using SymTable = SymbolTable;
|
|
|
|
|
|
|
|
|
|
|
|
namespace PascalABCCompiler.TreeConverter
|
|
|
|
|
|
{
|
|
|
|
|
|
public partial class syntax_tree_visitor
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-11 04:05:25 +03:00
|
|
|
|
public bool internal_is_assign;
|
2017-08-04 13:29:53 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-11 04:05:25 +03:00
|
|
|
|
public override void visit(assign _assign)
|
2017-08-04 13:29:53 +03:00
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
var loc = get_location(_assign);
|
|
|
|
|
|
|
2017-08-04 13:29:53 +03:00
|
|
|
|
|
2017-08-11 04:05:25 +03:00
|
|
|
|
addressed_expression to;
|
|
|
|
|
|
expression_node from;
|
|
|
|
|
|
AssignCheckAndConvert(_assign, out to, out from);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
InferLambdaResultTypeFromAssignment(_assign, from, to);
|
2017-08-04 13:29:53 +03:00
|
|
|
|
|
2017-08-11 04:05:25 +03:00
|
|
|
|
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;
|
2019-07-12 00:16:19 +03:00
|
|
|
|
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));
|
2017-08-11 04:05:25 +03:00
|
|
|
|
statement_node en = find_operator(_assign.operator_type, to, from, get_location(_assign));
|
|
|
|
|
|
assign_is_converting = false;
|
|
|
|
|
|
return_value(en);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Выводит тип результата лямбды по первому присваиванию переменной Result.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void InferLambdaResultTypeFromAssignment(assign _assign, expression_node from, addressed_expression to)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (stflambda.Count > 0) // мы находимся внутри лямбды - возможно, вложенной
|
2017-08-04 13:29:53 +03:00
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2017-08-04 13:29:53 +03:00
|
|
|
|
}
|
2017-08-11 04:05:25 +03:00
|
|
|
|
}
|
2017-08-04 13:29:53 +03:00
|
|
|
|
|
2017-08-11 04:05:25 +03:00
|
|
|
|
/// <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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-04 13:29:53 +03:00
|
|
|
|
|
|
|
|
|
|
|
2017-08-11 04:05:25 +03:00
|
|
|
|
/// <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");
|
|
|
|
|
|
|
2017-08-04 13:29:53 +03:00
|
|
|
|
//(ssyy) Вставляю проверки прямо сюда, т.к. запарился вылавливать другие случаи.
|
2017-08-11 04:05:25 +03:00
|
|
|
|
bool flag;
|
|
|
|
|
|
general_node_type node_type;
|
2017-08-04 13:29:53 +03:00
|
|
|
|
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)
|
|
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
#region Вывод параметров лямбда-выражения
|
|
|
|
|
|
|
2021-01-06 14:11:41 +03:00
|
|
|
|
LambdaHelper.InferTypesFromVarStmt(to.type, fromAsLambda, this, _assign.operator_type); //lroman//
|
2017-08-11 04:05:25 +03:00
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2017-08-04 13:29:53 +03:00
|
|
|
|
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);
|
2017-08-11 04:05:25 +03:00
|
|
|
|
ProcessAssigntToAutoType(to, ref from);
|
2017-08-04 13:29:53 +03:00
|
|
|
|
}
|
|
|
|
|
|
// 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)
|
|
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
var classFieldRef = to as class_field_reference;
|
|
|
|
|
|
if (classFieldRef.obj.type.type_special_kind == type_special_kind.record &&
|
|
|
|
|
|
classFieldRef.obj is base_function_call)
|
2017-08-04 13:29:53 +03:00
|
|
|
|
{
|
|
|
|
|
|
//исключим ситуацию обращения к массиву
|
2017-08-11 04:05:25 +03:00
|
|
|
|
if (!(classFieldRef.obj is common_method_call &&
|
|
|
|
|
|
(classFieldRef.obj as common_method_call).obj.type.type_special_kind ==
|
|
|
|
|
|
type_special_kind.array_wrapper))
|
2017-08-04 13:29:53 +03:00
|
|
|
|
AddError(loc, "LEFT_SIDE_CANNOT_BE_ASSIGNED_TO");
|
|
|
|
|
|
}
|
|
|
|
|
|
//else check_field_reference_for_assign(to as class_field_reference,loc);
|
|
|
|
|
|
}
|
2017-08-11 04:05:25 +03:00
|
|
|
|
if (context.is_in_cycle() && !SemanticRules.AllowChangeLoopVariable)
|
2017-08-04 13:29:53 +03:00
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
var_definition_node toAsVariable = GetLocalVariableFromAdressExpressionIfPossible(to);
|
|
|
|
|
|
if (toAsVariable != null && context.is_loop_variable(toAsVariable))
|
2017-08-04 13:29:53 +03:00
|
|
|
|
AddError(to.location, "CANNOT_ASSIGN_TO_LOOP_VARIABLE");
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
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");
|
2017-08-04 13:29:53 +03:00
|
|
|
|
}
|
2017-08-11 04:05:25 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <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)
|
2017-08-04 13:29:53 +03:00
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
try_convert_typed_expression_to_function_call(ref from);
|
|
|
|
|
|
if (to is class_field_reference)
|
|
|
|
|
|
{
|
|
|
|
|
|
var cfr = to as class_field_reference;
|
2018-12-22 12:56:57 +03:00
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-11 04:05:25 +03:00
|
|
|
|
cfr.field.type = from.type;
|
2018-11-01 19:57:55 +03:00
|
|
|
|
cfr.type = from.type; // Это неверно работает когда yieldится процедура #1439
|
2018-12-22 12:56:57 +03:00
|
|
|
|
// 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;
|
|
|
|
|
|
|
2018-11-01 19:57:55 +03:00
|
|
|
|
|
2018-01-29 18:12:31 +03:00
|
|
|
|
cfr.field.inital_value = context.GetInitalValueForVariable(cfr.field, cfr.field.inital_value);
|
2017-08-11 04:05:25 +03:00
|
|
|
|
}
|
|
|
|
|
|
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;
|
2018-01-29 18:12:31 +03:00
|
|
|
|
lvr.var.inital_value = context.GetInitalValueForVariable(lvr.var, lvr.var.inital_value);
|
2017-08-11 04:05:25 +03:00
|
|
|
|
}
|
|
|
|
|
|
else AddError(to.location, "Не могу вывести тип при наличии yield: " + to.type.full_name);
|
|
|
|
|
|
//to.type = from.type; // и без всякого real_type!
|
2017-08-04 13:29:53 +03:00
|
|
|
|
}
|
2017-08-11 04:05:25 +03:00
|
|
|
|
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; // замена типа у переменной
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-08-04 13:29:53 +03:00
|
|
|
|
|
|
|
|
|
|
|
2017-08-11 04:05:25 +03:00
|
|
|
|
|
|
|
|
|
|
/// <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)
|
2017-08-04 13:29:53 +03:00
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
property_node pn;
|
2017-08-04 13:29:53 +03:00
|
|
|
|
if (to.semantic_node_type == semantic_node_type.static_property_reference)
|
2017-08-11 04:05:25 +03:00
|
|
|
|
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)
|
2017-08-04 13:29:53 +03:00
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
if (oper_ass_in_prop)
|
2017-08-04 13:29:53 +03:00
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
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);
|
2017-08-04 13:29:53 +03:00
|
|
|
|
}
|
2017-08-11 04:05:25 +03:00
|
|
|
|
|
|
|
|
|
|
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)
|
2017-08-04 13:29:53 +03:00
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
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)
|
2017-08-04 13:29:53 +03:00
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
if (nspr.property == SystemLibrary.SystemLibrary.string_type.default_property_node)
|
2017-08-04 13:29:53 +03:00
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2017-08-04 13:29:53 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-11 04:05:25 +03:00
|
|
|
|
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);
|
2017-08-04 13:29:53 +03:00
|
|
|
|
}
|
2017-08-11 04:05:25 +03:00
|
|
|
|
return true;
|
2017-08-04 13:29:53 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-08-11 04:05:25 +03:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Если addressedExpression это ссылка на переменную, то возвращает узел этой переменной.
|
|
|
|
|
|
/// Например, для namespace_variable_reference вернёт (addressedExpression as namespace_variable_reference).var
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>Возвращает узел этой переменной, иначе null</returns>
|
|
|
|
|
|
private static var_definition_node GetLocalVariableFromAdressExpressionIfPossible(addressed_expression addressedExpression)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (addressedExpression.semantic_node_type)
|
2017-08-04 13:29:53 +03:00
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
case semantic_node_type.namespace_variable_reference:
|
|
|
|
|
|
return (addressedExpression as namespace_variable_reference).var;
|
|
|
|
|
|
case semantic_node_type.local_variable_reference:
|
|
|
|
|
|
return (addressedExpression as local_variable_reference).var;
|
|
|
|
|
|
case semantic_node_type.local_block_variable_reference:
|
|
|
|
|
|
return (addressedExpression as local_block_variable_reference).var;
|
|
|
|
|
|
default:
|
|
|
|
|
|
return null;
|
2017-08-04 13:29:53 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-09 02:23:26 +03:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Сопоставляет составному присваиванию его аналог.
|
|
|
|
|
|
/// Оператору '+=' возвращает '+', для '-=' возвращает '-', и т.д.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>Возвращает оператор. Если было передано не присваивание возвращает Operators.Undefined</returns>
|
|
|
|
|
|
private static Operators MapCompositeAssignmentOperatorToSameBinaryOperator(assign _assign)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (_assign.operator_type)
|
|
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
case Operators.AssignmentAddition:
|
|
|
|
|
|
return Operators.Plus;
|
|
|
|
|
|
case Operators.AssignmentBitwiseAND:
|
|
|
|
|
|
return Operators.BitwiseAND;
|
|
|
|
|
|
case Operators.AssignmentBitwiseLeftShift:
|
|
|
|
|
|
return Operators.BitwiseLeftShift;
|
|
|
|
|
|
case Operators.AssignmentBitwiseOR:
|
|
|
|
|
|
return Operators.BitwiseOR;
|
|
|
|
|
|
case Operators.AssignmentBitwiseRightShift:
|
|
|
|
|
|
return Operators.BitwiseRightShift;
|
|
|
|
|
|
case Operators.AssignmentBitwiseXOR:
|
|
|
|
|
|
return Operators.BitwiseXOR;
|
|
|
|
|
|
case Operators.AssignmentDivision:
|
|
|
|
|
|
return Operators.Division;
|
|
|
|
|
|
case Operators.AssignmentModulus:
|
|
|
|
|
|
return Operators.ModulusRemainder;
|
|
|
|
|
|
case Operators.AssignmentMultiplication:
|
|
|
|
|
|
return Operators.Multiplication;
|
|
|
|
|
|
case Operators.AssignmentSubtraction:
|
|
|
|
|
|
return Operators.Minus;
|
|
|
|
|
|
default:
|
|
|
|
|
|
return Operators.Undefined;
|
2017-08-09 02:23:26 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Обрабатывает случай, когда левая часть присваивания имеет тип event.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>True - обработка прошла, иначе False.</returns>
|
2017-08-11 04:05:25 +03:00
|
|
|
|
private bool ProcessAssignmentToEventIfPossible(assign _assign, addressed_expression to, expression_node from,
|
2017-08-09 02:23:26 +03:00
|
|
|
|
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;
|
2017-08-11 04:05:25 +03:00
|
|
|
|
expression_node right_del = convertion_data_and_alghoritms.convert_type(from, ser.en.delegate_type);
|
2017-08-09 02:23:26 +03:00
|
|
|
|
switch (_assign.operator_type)
|
|
|
|
|
|
{
|
2017-08-11 04:05:25 +03:00
|
|
|
|
case Operators.AssignmentAddition:
|
2017-08-09 02:23:26 +03:00
|
|
|
|
{
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
2017-08-11 04:05:25 +03:00
|
|
|
|
case Operators.AssignmentSubtraction:
|
2017-08-09 02:23:26 +03:00
|
|
|
|
{
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
2017-08-04 13:29:53 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|