Исправление вызовов методов без скобочек для языков с отличающихся от PascalABC.NET этим поведением (#3289)

* Fix method calls without parentheses in SPython

* Move condition above loop to make code cleaner
This commit is contained in:
AlexanderZemlyak 2025-06-22 17:32:22 +03:00 committed by GitHub
parent 239be2d202
commit 6298fdb655
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 118 additions and 108 deletions

View file

@ -48,6 +48,7 @@ namespace Languages.Pascal
SemanticRulesConstants.StrongPointersTypeCheckForDotNet = true; SemanticRulesConstants.StrongPointersTypeCheckForDotNet = true;
SemanticRulesConstants.AllowChangeLoopVariable = false; SemanticRulesConstants.AllowChangeLoopVariable = false;
SemanticRulesConstants.AllowGlobalVisibilityForPABCDll = true; SemanticRulesConstants.AllowGlobalVisibilityForPABCDll = true;
SemanticRulesConstants.AllowMethodCallsWithoutParentheses = true;
} }
public override void SetSyntaxTreeToSemanticTreeConverter() public override void SetSyntaxTreeToSemanticTreeConverter()

View file

@ -135,6 +135,11 @@ namespace PascalABCCompiler.TreeConverter
public static bool AddressOfOperatorNonOverloaded = true; public static bool AddressOfOperatorNonOverloaded = true;
public static bool GenerateNativeCode = false; public static bool GenerateNativeCode = false;
/// <summary>
/// Разрешить вызов методов, не имеющих параметров (или со всеми параметрами по умолчанию) без скобок
/// </summary>
public static bool AllowMethodCallsWithoutParentheses = true;
} }
} }

View file

@ -10243,7 +10243,8 @@ namespace PascalABCCompiler.TreeConverter
only_extension_methods = false; only_extension_methods = false;
else else
{ {
if (tmp_fn.parameters.Count == 1 || tmp_fn.parameters.Count == 2 && (tmp_fn.parameters[1].is_params || tmp_fn.parameters[1].default_value != null)) if (SemanticRulesConstants.AllowMethodCallsWithoutParentheses &&
(tmp_fn.parameters.Count == 1 || tmp_fn.parameters.Count == 2 && (tmp_fn.parameters[1].is_params || tmp_fn.parameters[1].default_value != null)))
has_empty_methods = true; has_empty_methods = true;
} }
} }
@ -10590,7 +10591,7 @@ namespace PascalABCCompiler.TreeConverter
} }
foreach (SymbolInfo tmp_si in tmp_list) foreach (SymbolInfo tmp_si in tmp_list)
{ {
if (tmp_si.sym_info is function_node && (tmp_si.sym_info as function_node).is_extension_method && !has_property(ref sil) if (SemanticRulesConstants.AllowMethodCallsWithoutParentheses && tmp_si.sym_info is function_node && (tmp_si.sym_info as function_node).is_extension_method && !has_property(ref sil)
|| tmp_si.sym_info is common_method_node && (tmp_si.sym_info as common_method_node).is_constructor || tmp_si.sym_info is common_method_node && (tmp_si.sym_info as common_method_node).is_constructor
|| tmp_si.sym_info is compiled_constructor_node) || tmp_si.sym_info is compiled_constructor_node)
return true; return true;

View file

@ -1160,7 +1160,7 @@ namespace PascalABCCompiler.TreeRealization
} }
} }
if (dii.parameters.Count == 0) if (dii.parameters.Count == 0 && TreeConverter.SemanticRulesConstants.AllowMethodCallsWithoutParentheses)
{ {
if (dii.return_value_type == to) if (dii.return_value_type == to)
{ {

View file

@ -4631,126 +4631,129 @@ namespace PascalABCCompiler.TreeRealization
public override function_node get_implicit_conversion_to(type_node ctn) public override function_node get_implicit_conversion_to(type_node ctn)
{ {
foreach (base_function_call fn in _proper_methods) if (SemanticRulesConstants.AllowMethodCallsWithoutParentheses)
{ {
if (fn.simple_function_node.parameters.Count == 0 foreach (base_function_call fn in _proper_methods)
|| (fn.simple_function_node is common_namespace_function_node && (fn.simple_function_node as common_namespace_function_node).ConnectedToType != null
|| fn.simple_function_node is compiled_function_node && (fn.simple_function_node as compiled_function_node).ConnectedToType != null)
&& fn.simple_function_node.parameters.Count == 1 && !fn.simple_function_node.parameters[0].is_params)
{ {
if (fn.simple_function_node.return_value_type == ctn) if (fn.simple_function_node.parameters.Count == 0
|| (fn.simple_function_node is common_namespace_function_node && (fn.simple_function_node as common_namespace_function_node).ConnectedToType != null
|| fn.simple_function_node is compiled_function_node && (fn.simple_function_node as compiled_function_node).ConnectedToType != null)
&& fn.simple_function_node.parameters.Count == 1 && !fn.simple_function_node.parameters[0].is_params)
{ {
convert_function_to_function_call cftfc = new convert_function_to_function_call(fn); if (fn.simple_function_node.return_value_type == ctn)
return (new convert_types_function_node(cftfc.compile_time_executor, true)); {
convert_function_to_function_call cftfc = new convert_function_to_function_call(fn);
return (new convert_types_function_node(cftfc.compile_time_executor, true));
}
if (fn.simple_function_node.return_value_type == null)
{
continue;
}
//TODO: Очень внимательно рассмотреть. Если преобразование типов должно идти через compile_time_executor.
possible_type_convertions ptc = type_table.get_convertions(fn.simple_function_node.return_value_type, ctn);
if ((ptc.first == null) || (ptc.first.convertion_method == null))
{
continue;
}
expression_node ennew = type_table.type_table_function_call_maker(ptc.first.convertion_method, null, fn);
convert_function_to_function_call cftfc2 = new convert_function_to_function_call(ennew);
return (new convert_types_function_node(cftfc2.compile_time_executor, false));
} }
if (fn.simple_function_node.return_value_type == null) else if (fn.simple_function_node.parameters.Count == 1 && fn.simple_function_node.parameters[0].is_params ||
(fn.simple_function_node is common_namespace_function_node && (fn.simple_function_node as common_namespace_function_node).ConnectedToType != null || fn.simple_function_node is compiled_function_node && (fn.simple_function_node as compiled_function_node).ConnectedToType != null)
&& fn.simple_function_node.parameters.Count == 2 && fn.simple_function_node.parameters[1].is_params)
{ {
continue; base_function_call copy_fn = get_function_call_copy(fn);
} int param_num = (fn.simple_function_node is common_namespace_function_node && (fn.simple_function_node as common_namespace_function_node).ConnectedToType != null || fn.simple_function_node is compiled_function_node && (fn.simple_function_node as compiled_function_node).ConnectedToType != null) ? 1 : 0;
//TODO: Очень внимательно рассмотреть. Если преобразование типов должно идти через compile_time_executor. if (fn.simple_function_node.return_value_type == ctn)
possible_type_convertions ptc=type_table.get_convertions(fn.simple_function_node.return_value_type, ctn); {
if ((ptc.first == null) || (ptc.first.convertion_method == null)) common_namespace_function_call cnfc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.NewArrayProcedureDecl, null);
{ cnfc.parameters.AddElement(new typeof_operator(fn.simple_function_node.parameters[param_num].type, null));
continue; cnfc.parameters.AddElement(new int_const_node(0, null));
} if (copy_fn.parameters.Count < fn.simple_function_node.parameters.Count)
expression_node ennew=type_table.type_table_function_call_maker(ptc.first.convertion_method, null, fn); copy_fn.parameters.AddElement(cnfc);
convert_function_to_function_call cftfc2 = new convert_function_to_function_call(ennew); convert_function_to_function_call cftfc = new convert_function_to_function_call(copy_fn);
return (new convert_types_function_node(cftfc2.compile_time_executor, false)); return (new convert_types_function_node(cftfc.compile_time_executor, true));
}
else if (fn.simple_function_node.parameters.Count == 1 && fn.simple_function_node.parameters[0].is_params || }
(fn.simple_function_node is common_namespace_function_node && (fn.simple_function_node as common_namespace_function_node).ConnectedToType != null || fn.simple_function_node is compiled_function_node && (fn.simple_function_node as compiled_function_node).ConnectedToType != null) if (fn.simple_function_node.return_value_type == null)
&& fn.simple_function_node.parameters.Count == 2 && fn.simple_function_node.parameters[1].is_params) {
{ continue;
base_function_call copy_fn = get_function_call_copy(fn); }
int param_num = (fn.simple_function_node is common_namespace_function_node && (fn.simple_function_node as common_namespace_function_node).ConnectedToType != null || fn.simple_function_node is compiled_function_node && (fn.simple_function_node as compiled_function_node).ConnectedToType != null) ? 1 : 0; //TODO: Очень внимательно рассмотреть. Если преобразование типов должно идти через compile_time_executor.
if (fn.simple_function_node.return_value_type == ctn) possible_type_convertions ptc = type_table.get_convertions(fn.simple_function_node.return_value_type, ctn);
{ if ((ptc.first == null) || (ptc.first.convertion_method == null))
common_namespace_function_call cnfc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.NewArrayProcedureDecl,null); {
cnfc.parameters.AddElement(new typeof_operator(fn.simple_function_node.parameters[param_num].type, null)); continue;
cnfc.parameters.AddElement(new int_const_node(0,null)); }
common_namespace_function_call cnfc2 = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.NewArrayProcedureDecl, null);
cnfc2.parameters.AddElement(new typeof_operator(fn.simple_function_node.parameters[param_num].type, null));
cnfc2.parameters.AddElement(new int_const_node(0, null));
if (copy_fn.parameters.Count < fn.simple_function_node.parameters.Count) if (copy_fn.parameters.Count < fn.simple_function_node.parameters.Count)
copy_fn.parameters.AddElement(cnfc); copy_fn.parameters.AddElement(cnfc2);
convert_function_to_function_call cftfc = new convert_function_to_function_call(copy_fn); expression_node ennew = type_table.type_table_function_call_maker(ptc.first.convertion_method, null, copy_fn);
return (new convert_types_function_node(cftfc.compile_time_executor, true)); convert_function_to_function_call cftfc2 = new convert_function_to_function_call(ennew);
return (new convert_types_function_node(cftfc2.compile_time_executor, false));
} }
if (fn.simple_function_node.return_value_type == null) else if (fn.simple_function_node.parameters.Count == 1 && fn.simple_function_node.parameters[0].default_value != null ||
{ (fn.simple_function_node is common_namespace_function_node && (fn.simple_function_node as common_namespace_function_node).ConnectedToType != null
continue; || fn.simple_function_node is compiled_function_node && (fn.simple_function_node as compiled_function_node).ConnectedToType != null)
} && fn.simple_function_node.parameters.Count == 2 && fn.simple_function_node.parameters[1].default_value != null)
//TODO: Очень внимательно рассмотреть. Если преобразование типов должно идти через compile_time_executor.
possible_type_convertions ptc=type_table.get_convertions(fn.simple_function_node.return_value_type, ctn);
if ((ptc.first == null) || (ptc.first.convertion_method == null))
{
continue;
}
common_namespace_function_call cnfc2 = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.NewArrayProcedureDecl,null);
cnfc2.parameters.AddElement(new typeof_operator(fn.simple_function_node.parameters[param_num].type, null));
cnfc2.parameters.AddElement(new int_const_node(0,null));
if (copy_fn.parameters.Count < fn.simple_function_node.parameters.Count)
copy_fn.parameters.AddElement(cnfc2);
expression_node ennew=type_table.type_table_function_call_maker(ptc.first.convertion_method, null, copy_fn);
convert_function_to_function_call cftfc2 = new convert_function_to_function_call(ennew);
return (new convert_types_function_node(cftfc2.compile_time_executor, false));
}
else if (fn.simple_function_node.parameters.Count == 1 && fn.simple_function_node.parameters[0].default_value != null ||
(fn.simple_function_node is common_namespace_function_node && (fn.simple_function_node as common_namespace_function_node).ConnectedToType != null
|| fn.simple_function_node is compiled_function_node && (fn.simple_function_node as compiled_function_node).ConnectedToType != null)
&& fn.simple_function_node.parameters.Count == 2 && fn.simple_function_node.parameters[1].default_value != null)
{
int param_num = (fn.simple_function_node is common_namespace_function_node && (fn.simple_function_node as common_namespace_function_node).ConnectedToType != null || fn.simple_function_node is compiled_function_node && (fn.simple_function_node as compiled_function_node).ConnectedToType != null) ? 1 : 0;
base_function_call copy_fn = null;
if (fn.simple_function_node.return_value_type == ctn)
{ {
int param_num = (fn.simple_function_node is common_namespace_function_node && (fn.simple_function_node as common_namespace_function_node).ConnectedToType != null || fn.simple_function_node is compiled_function_node && (fn.simple_function_node as compiled_function_node).ConnectedToType != null) ? 1 : 0;
base_function_call copy_fn = null;
if (fn.simple_function_node.return_value_type == ctn)
{
copy_fn = get_function_call_copy(fn);
copy_fn.parameters.AddElement(fn.simple_function_node.parameters[param_num].default_value);
convert_function_to_function_call cftfc = new convert_function_to_function_call(copy_fn);
return (new convert_types_function_node(cftfc.compile_time_executor, true));
}
if (fn.simple_function_node.return_value_type == null)
{
continue;
}
//TODO: Очень внимательно рассмотреть. Если преобразование типов должно идти через compile_time_executor.
possible_type_convertions ptc = type_table.get_convertions(fn.simple_function_node.return_value_type, ctn);
if ((ptc.first == null) || (ptc.first.convertion_method == null))
{
continue;
}
copy_fn = get_function_call_copy(fn); copy_fn = get_function_call_copy(fn);
copy_fn.parameters.AddElement(fn.simple_function_node.parameters[param_num].default_value); copy_fn.parameters.AddElement(fn.simple_function_node.parameters[param_num].default_value);
convert_function_to_function_call cftfc = new convert_function_to_function_call(copy_fn); expression_node ennew = type_table.type_table_function_call_maker(ptc.first.convertion_method, null, copy_fn);
return (new convert_types_function_node(cftfc.compile_time_executor, true)); convert_function_to_function_call cftfc2 = new convert_function_to_function_call(ennew);
return (new convert_types_function_node(cftfc2.compile_time_executor, false));
} }
if (fn.simple_function_node.return_value_type == null) else if (fn.simple_function_node.parameters.Count == fn.simple_function_node.num_of_default_parameters)
{
continue;
}
//TODO: Очень внимательно рассмотреть. Если преобразование типов должно идти через compile_time_executor.
possible_type_convertions ptc = type_table.get_convertions(fn.simple_function_node.return_value_type, ctn);
if ((ptc.first == null) || (ptc.first.convertion_method == null))
{
continue;
}
copy_fn = get_function_call_copy(fn);
copy_fn.parameters.AddElement(fn.simple_function_node.parameters[param_num].default_value);
expression_node ennew = type_table.type_table_function_call_maker(ptc.first.convertion_method, null, copy_fn);
convert_function_to_function_call cftfc2 = new convert_function_to_function_call(ennew);
return (new convert_types_function_node(cftfc2.compile_time_executor, false));
}
else if (fn.simple_function_node.parameters.Count == fn.simple_function_node.num_of_default_parameters)
{
base_function_call copy_fn = get_function_call_copy(fn);
if (fn.simple_function_node.return_value_type == ctn)
{ {
base_function_call copy_fn = get_function_call_copy(fn);
if (fn.simple_function_node.return_value_type == ctn)
{
foreach (parameter p in fn.simple_function_node.parameters)
copy_fn.parameters.AddElement(p.default_value);
convert_function_to_function_call cftfc = new convert_function_to_function_call(copy_fn);
return (new convert_types_function_node(cftfc.compile_time_executor, true));
}
if (fn.simple_function_node.return_value_type == null)
{
continue;
}
//TODO: Очень внимательно рассмотреть. Если преобразование типов должно идти через compile_time_executor.
possible_type_convertions ptc = type_table.get_convertions(fn.simple_function_node.return_value_type, ctn);
if ((ptc.first == null) || (ptc.first.convertion_method == null))
{
continue;
}
foreach (parameter p in fn.simple_function_node.parameters) foreach (parameter p in fn.simple_function_node.parameters)
copy_fn.parameters.AddElement(p.default_value); copy_fn.parameters.AddElement(p.default_value);
convert_function_to_function_call cftfc = new convert_function_to_function_call(copy_fn); expression_node ennew = type_table.type_table_function_call_maker(ptc.first.convertion_method, null, copy_fn);
return (new convert_types_function_node(cftfc.compile_time_executor, true)); convert_function_to_function_call cftfc2 = new convert_function_to_function_call(ennew);
return (new convert_types_function_node(cftfc2.compile_time_executor, false));
} }
if (fn.simple_function_node.return_value_type == null)
{
continue;
}
//TODO: Очень внимательно рассмотреть. Если преобразование типов должно идти через compile_time_executor.
possible_type_convertions ptc = type_table.get_convertions(fn.simple_function_node.return_value_type, ctn);
if ((ptc.first == null) || (ptc.first.convertion_method == null))
{
continue;
}
foreach (parameter p in fn.simple_function_node.parameters)
copy_fn.parameters.AddElement(p.default_value);
expression_node ennew = type_table.type_table_function_call_maker(ptc.first.convertion_method, null, copy_fn);
convert_function_to_function_call cftfc2 = new convert_function_to_function_call(ennew);
return (new convert_types_function_node(cftfc2.compile_time_executor, false));
} }
} }