2024-06-23 00:02:30 +03:00
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
2019-06-16 23:44:32 +03:00
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
//Здесь описана реализация generic-типов
//Файлом владеет ssyy.
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Linq ;
using System.Reflection ;
using PascalABCCompiler.SyntaxTree ;
using PascalABCCompiler.TreeConverter ;
namespace PascalABCCompiler.TreeRealization
{
//Вспомогательный класс для реализации generic-типов
public class generic_type_instance_info
{
public List < type_node > param_types ;
public generic_instance_type_node pseudo_instance ;
public generic_type_instance_info ( List < type_node > _param_types , generic_instance_type_node _pseudo_instance )
{
param_types = _param_types ;
pseudo_instance = _pseudo_instance ;
}
}
public class generic_function_instance_info
{
public List < type_node > param_types ;
public function_node pseudo_instance ;
public generic_function_instance_info ( List < type_node > _param_types , function_node _pseudo_instance )
{
param_types = _param_types ;
pseudo_instance = _pseudo_instance ;
}
}
public class generic_parameter_eliminations
{
public bool is_class = false ;
public bool is_value = false ;
public bool has_default_ctor = false ;
2021-01-31 14:08:33 +03:00
public bool has_explicit_default_ctor = false ;
2019-06-16 23:44:32 +03:00
public type_node base_class = null ;
public List < type_node > implementing_interfaces = null ;
public static void add_default_ctor ( common_type_node param )
{
common_method_node cnode = new common_method_node (
2024-05-04 20:21:50 +03:00
StringConstants . default_constructor_name , param , null ,
2019-06-16 23:44:32 +03:00
param , SemanticTree . polymorphic_state . ps_common ,
SemanticTree . field_access_level . fal_public , null ) ;
cnode . is_constructor = true ;
param . methods . AddElement ( cnode ) ;
2024-05-04 20:21:50 +03:00
param . add_name ( StringConstants . default_constructor_name , new SymbolInfo ( cnode ) ) ;
2019-06-16 23:44:32 +03:00
param . has_default_constructor = true ;
2021-01-31 14:08:33 +03:00
param . has_explicit_default_constructor = true ;
2019-06-16 23:44:32 +03:00
}
public static List < generic_parameter_eliminations > make_eliminations_common ( List < SemanticTree . ICommonTypeNode > generic_params )
{
List < generic_parameter_eliminations > _parameters_eliminations = new List < generic_parameter_eliminations > ( ) ;
foreach ( type_node t in generic_params )
{
generic_parameter_eliminations gpe = new generic_parameter_eliminations ( ) ;
2023-05-14 12:36:08 +03:00
2019-06-16 23:44:32 +03:00
gpe . has_default_ctor = generic_convertions . type_has_default_ctor ( t , false ) ;
2021-01-31 14:08:33 +03:00
if ( t is common_type_node & & ( t as common_type_node ) . has_explicit_default_constructor )
gpe . has_explicit_default_ctor = true ;
2019-06-16 23:44:32 +03:00
gpe . is_class = t . is_class ;
gpe . is_value = t . is_value ;
gpe . base_class = t . base_type ;
gpe . implementing_interfaces = new List < type_node > ( t . ImplementingInterfaces . Count ) ;
foreach ( type_node interf in t . ImplementingInterfaces )
{
gpe . implementing_interfaces . Add ( interf ) ;
}
_parameters_eliminations . Add ( gpe ) ;
}
return _parameters_eliminations ;
}
public static List < generic_parameter_eliminations > make_eliminations_compiled ( Type [ ] pars )
{
2022-09-26 14:25:15 +03:00
List < generic_parameter_eliminations > _parameters_eliminations = new List < generic_parameter_eliminations > ( pars . Length ) ;
2019-06-16 23:44:32 +03:00
foreach ( Type t in pars )
{
generic_parameter_eliminations gpe = new generic_parameter_eliminations ( ) ;
2022-09-26 14:25:15 +03:00
2019-06-16 23:44:32 +03:00
gpe . has_default_ctor =
( ( t . GenericParameterAttributes &
GenericParameterAttributes . DefaultConstructorConstraint ) ! = 0 ) ;
2021-01-31 14:08:33 +03:00
if ( gpe . has_default_ctor )
gpe . has_explicit_default_ctor = true ;
2022-09-26 14:25:15 +03:00
2019-06-16 23:44:32 +03:00
gpe . is_class =
( ( t . GenericParameterAttributes &
GenericParameterAttributes . ReferenceTypeConstraint ) ! = 0 ) ;
gpe . is_value =
( ( t . GenericParameterAttributes &
GenericParameterAttributes . NotNullableValueTypeConstraint ) ! = 0 ) ;
2022-09-26 14:25:15 +03:00
2019-06-16 23:44:32 +03:00
gpe . base_class = compiled_type_node . get_type_node ( t . BaseType ) ;
2022-09-26 14:25:15 +03:00
if ( gpe . is_value & & gpe . base_class = = SystemLibrary . SystemLibrary . value_type )
gpe . base_class = SystemLibrary . SystemLibrary . object_type ;
2019-06-16 23:44:32 +03:00
Type [ ] net_interf = t . GetInterfaces ( ) ;
gpe . implementing_interfaces = new List < type_node > ( net_interf . Length ) ;
foreach ( Type net_t in net_interf )
{
gpe . implementing_interfaces . Add ( compiled_type_node . get_type_node ( net_t ) ) ;
}
2022-09-26 14:25:15 +03:00
2019-06-16 23:44:32 +03:00
_parameters_eliminations . Add ( gpe ) ;
}
return _parameters_eliminations ;
}
public static CompilationErrorWithLocation check_type_generic_useful ( type_node tn , location loc )
{
if ( tn = = null )
{
return new SimpleSemanticError ( loc , "TYPE_NAME_EXPECTED" ) ;
}
if ( tn . IsPointer )
{
return new SimpleSemanticError ( loc , "CANNOT_USE_POINTER_AS_GENERIC_ARGUMENT" ) ;
}
switch ( tn . type_special_kind )
{
case PascalABCCompiler . SemanticTree . type_special_kind . diap_type :
return new SimpleSemanticError ( loc , "CANNOT_USE_DIAPASON_AS_GENERIC_ARGUMENT" ) ;
case PascalABCCompiler . SemanticTree . type_special_kind . typed_file :
return new SimpleSemanticError ( loc , "CANNOT_USE_TYPED_FILE_AS_GENERIC_ARGUMENT" ) ;
case PascalABCCompiler . SemanticTree . type_special_kind . short_string :
return new SimpleSemanticError ( loc , "CANNOT_USE_SHORT_STRING_AS_GENERIC_ARGUMENT" ) ;
}
/ * if ( tn = = SystemLibrary . SystemLibrary . void_type )
{
return new VoidNotValid ( loc ) ;
} * /
SystemLibrary . SystemLibrary . syn_visitor . check_for_type_allowed ( tn , loc ) ;
SystemLibrary . SystemLibrary . syn_visitor . check_using_static_class ( tn , loc ) ;
internal_interface ii = tn . get_internal_interface ( internal_interface_kind . bounded_array_interface ) ;
if ( ii ! = null )
{
return new SimpleSemanticError ( loc , "CANNOT_USE_BOUNDED_ARRAY_AS_GENERIC_ARGUMENT" ) ;
}
return null ;
}
public static CompilationErrorWithLocation check_type_list ( List < type_node > tparams , List < generic_parameter_eliminations > gpe_list , bool method_param_types , out int i )
{
int count = tparams . Count ;
2019-10-04 14:37:47 +03:00
2019-06-16 23:44:32 +03:00
for ( i = 0 ; i < count ; i + + )
{
generic_parameter_eliminations gpe = gpe_list [ i ] ;
type_node tn = tparams [ i ] ;
2019-10-04 14:37:47 +03:00
2022-09-26 14:25:15 +03:00
if ( gpe . base_class ! = null & & gpe . base_class ! = SystemLibrary . SystemLibrary . object_type )
2019-06-16 23:44:32 +03:00
{
type_node base_type = generic_convertions . determine_type ( gpe . base_class , tparams , method_param_types ) ;
2020-06-18 23:17:13 +03:00
// Если tn не соврадает с о своим базовым типом и
// tn не наследуется от base_type и
// tn - не generic параметр - закомментировал
if ( base_type ! = tn & & ! type_table . is_derived ( base_type , tn ) /*&& !tn.is_generic_parameter*/ )
2019-06-16 23:44:32 +03:00
{
2022-09-27 18:29:49 +03:00
return new SimpleSemanticError ( null , "PARAMETER_{0}_MUST_BE_DERIVED_FROM_{1}" , tn . PrintableName , base_type . PrintableName ) ;
2019-06-16 23:44:32 +03:00
}
}
2022-03-20 19:01:03 +03:00
if ( gpe . is_class & & ! tn . is_class )
2022-03-20 00:08:57 +03:00
{
return new SimpleSemanticError ( null , "PARAMETER_{0}_MUST_BE_REFERENCE_TYPE" , tn . PrintableName ) ;
}
if ( gpe . is_value & & ( ! tn . is_value | | tn . BaseFullName ! = null & & tn . BaseFullName . StartsWith ( "System.Nullable" ) ) /*&& !tn.is_generic_parameter*/ )
{
return new SimpleSemanticError ( null , "PARAMETER_{0}_MUST_BE_VALUE_TYPE" , tn . PrintableName ) ;
}
2019-06-16 23:44:32 +03:00
foreach ( type_node interf in gpe . implementing_interfaces )
{
type_node di = generic_convertions . determine_type ( interf , tparams , method_param_types ) ;
if ( di ! = tn & &
( tn . ImplementingInterfaces = = null | |
! type_table . is_derived ( di , tn ) ) )
{
2022-09-27 18:29:49 +03:00
return new SimpleSemanticError ( null , "PARAMETER_{0}_MUST_IMPLEMENT_INTERFACE_{1}" , tn . PrintableName , di . PrintableName ) ;
2019-06-16 23:44:32 +03:00
}
}
if ( tn . IsStatic )
return new SimpleSemanticError ( null , "USING_STATIC_CLASS_NOT_VALID" ) ;
if ( gpe . has_default_ctor )
{
2020-07-09 21:36:29 +03:00
if ( tn . IsAbstract )
{
return new SimpleSemanticError ( null , "PARAMETER_{0}_MUST_NOT_BE_ABSTRACT" , tn . PrintableName ) ;
}
if ( tn . IsStatic | | ! tn . is_value & & ! generic_convertions . type_has_default_ctor ( tn , false ) )
2019-06-16 23:44:32 +03:00
{
return new SimpleSemanticError ( null , "PARAMETER_{0}_MUST_HAVE_DEFAULT_CONSTRUCTOR" , tn . PrintableName ) ;
}
}
}
return null ;
}
}
public class type_instance_and_location
{
public generic_instance_type_node instance ;
public location loc ;
public type_instance_and_location ( generic_instance_type_node _instance , location _loc )
{
instance = _instance ;
loc = _loc ;
}
}
//Вспомогательный класс для создания псевдо-инстанций generic-типов.
//TODO: sdelat singletonom. staticheskie klassy eto gadost
public static class generic_convertions
{
//Список, хранящий все псевдо-инстанции generic-типов, нужен для NetGenerator.
public static List < SemanticTree . IGenericTypeInstance > all_type_instances =
new List < SemanticTree . IGenericTypeInstance > ( ) ;
public static List < SemanticTree . IGenericFunctionInstance > all_function_instances =
new List < SemanticTree . IGenericFunctionInstance > ( ) ;
public static Hashtable generic_instances = new Hashtable ( ) ;
public static syntax_tree_visitor visitor ;
public static List < generic_type_instance_info > get_type_instances ( type_node original_generic_type )
{
List < generic_type_instance_info > instances = generic_instances [ original_generic_type ] as List < generic_type_instance_info > ;
if ( instances = = null )
{
instances = new List < generic_type_instance_info > ( ) ;
generic_instances . Add ( original_generic_type , instances ) ;
}
return instances ;
}
2021-11-07 12:14:35 +03:00
public static void remove_type_instances ( type_node original_generic_type )
{
if ( generic_instances [ original_generic_type ] ! = null )
generic_instances . Remove ( original_generic_type ) ;
}
2019-06-16 23:44:32 +03:00
public static List < generic_function_instance_info > get_function_instances ( function_node original_generic_function )
{
List < generic_function_instance_info > instances = generic_instances [ original_generic_function ] as List < generic_function_instance_info > ;
if ( instances = = null )
{
instances = new List < generic_function_instance_info > ( ) ;
generic_instances . Add ( original_generic_function , instances ) ;
}
return instances ;
}
public static type_node find_type_instance ( List < generic_type_instance_info > _generic_instances , List < type_node > param_types )
{
int count = param_types . Count ;
foreach ( generic_type_instance_info gii in _generic_instances )
{
bool equals = true ;
for ( int i = 0 ; equals & & i < count ; + + i )
{
equals = ( param_types [ i ] = = gii . param_types [ i ] ) ;
}
if ( equals )
{
//Такая инстанция уже есть
return gii . pseudo_instance ;
}
}
return null ;
}
public static void check_instances_are_correct ( List < type_instance_and_location > insts )
{
int num ;
foreach ( type_instance_and_location tia in insts )
{
List < generic_parameter_eliminations > gpes = tia . instance . original_generic . parameters_eliminations ;
CompilationErrorWithLocation err = generic_parameter_eliminations . check_type_list ( tia . instance . instance_params , gpes , false , out num ) ;
if ( err ! = null )
{
err . loc = tia . loc ;
throw err ;
}
}
}
public static function_node find_function_instance ( List < generic_function_instance_info > _generic_instances , List < type_node > param_types )
{
int count = param_types . Count ;
foreach ( generic_function_instance_info gii in _generic_instances )
{
bool equals = true ;
for ( int i = 0 ; equals & & i < count ; + + i )
{
equals = ( param_types [ i ] = = gii . param_types [ i ] ) ;
}
if ( equals )
{
//Такая инстанция уже есть
return gii . pseudo_instance ;
}
}
return null ;
}
2023-07-02 22:22:49 +03:00
public static void instance_default_property ( generic_instance_type_node instance )
{
var original = instance . original_generic ;
property_node orig_pn = original . default_property_node ;
if ( orig_pn ! = null )
{
if ( orig_pn . comprehensive_type = = original )
{
//Свойство по умолчанию описано в оригинальном коде generic-a;
//конвертируем е г о
instance . default_property = instance . ConvertMember ( orig_pn ) as common_property_node ;
}
else
{
//Свойство по умолчанию описано в каком-то предке оригинального generic-a
if ( orig_pn . comprehensive_type . is_generic_type_definition )
{
instance . default_property = instance . find_instance_type_from ( orig_pn . comprehensive_type ) . default_property ;
}
}
}
}
2022-10-06 11:06:27 +03:00
public static void init_generic_instance ( generic_instance_type_node instance /*, SymbolTable.ClassScope instance_scope*/ )
2019-06-16 23:44:32 +03:00
{
2022-10-06 11:06:27 +03:00
var original = instance . original_generic ;
var param_types = instance . instance_params ;
2019-06-16 23:44:32 +03:00
instance . IsInterface = original . IsInterface ;
instance . is_class = original . is_class ;
instance . internal_is_value = original . is_value ;
instance . SetIsSealed ( original . IsSealed ) ;
instance . IsDelegate = original . IsDelegate ;
instance . type_special_kind = original . type_special_kind ;
//Определяем базовый тип
type_node btype = determine_type (
original . base_type , param_types , false ) ;
2021-01-02 15:22:21 +03:00
if ( btype = = null )
btype = SystemLibrary . SystemLibrary . object_type ;
2019-06-16 23:44:32 +03:00
instance . SetBaseTypeIgnoringScope ( btype ) ;
//instance._scope = new SymbolTable.GenericTypeInstanceScope(instance, instance.original_generic.Scope, btype.Scope);
2022-10-06 11:06:27 +03:00
// Создаются лениво
/ * *
2019-06-16 23:44:32 +03:00
foreach ( type_node interf in original . ImplementingInterfaces )
{
instance . ImplementingInterfaces . Add (
determine_type ( interf , param_types , false )
) ;
}
2022-10-06 11:06:27 +03:00
/**/
2019-06-16 23:44:32 +03:00
SystemLibrary . SystemLibrary . init_reference_type ( instance ) ;
instance . conform_basic_functions ( ) ;
//(ssyy) Нужно, чтобы добавились конструкторы
2024-05-04 20:21:50 +03:00
//ctnode.find_in_type(StringConstants.default_constructor_name);
2019-06-16 23:44:32 +03:00
instance . instance_params = param_types ;
property_node orig_pn = original . default_property_node ;
if ( orig_pn ! = null )
{
if ( orig_pn . comprehensive_type = = original )
{
//Свойство по умолчанию описано в оригинальном коде generic-a;
//конвертируем е г о
instance . default_property = instance . ConvertMember ( orig_pn ) as common_property_node ;
}
else
{
//Свойство по умолчанию описано в каком-то предке оригинального generic-a
if ( orig_pn . comprehensive_type . is_generic_type_definition )
{
instance . default_property = instance . find_instance_type_from ( orig_pn . comprehensive_type ) . default_property ;
}
}
}
var shouldAddToAllTypeInstances = true ;
if ( LambdaHelper . processingLambdaParametersForTypeInference ! = 0 )
{
foreach ( var par in instance . generic_parameters )
{
if ( par is lambda_any_type_node )
{
shouldAddToAllTypeInstances = false ;
break ;
}
}
}
if ( shouldAddToAllTypeInstances ) //lroman// Если зашли сюда при выведении типов параметров лямбды, то тип инстанцироваться может с типом lambda_any_type_node. Поэтому, если выводим типы. Т о данную инстанцию не добавляем
{
if ( instance . instance_params [ 0 ] is ienumerable_auto_type ) // SSM 10.07.16 (yields) в эту таблицу не включаются типы IEnumerable<ienumerable_auto_type>, т.к. потом они всё равно автовыводятся
{
//instance = instance;
}
else
{
generic_convertions . all_type_instances . Add ( instance ) ;
}
}
internal_interface ii = original . get_internal_interface ( internal_interface_kind . delegate_interface ) ;
if ( ii ! = null )
{
delegate_internal_interface dii = ii as delegate_internal_interface ;
common_method_node inv = instance . ConvertMember ( dii . invoke_method ) as common_method_node ;
common_method_node constr = instance . ConvertMember ( dii . constructor ) as common_method_node ;
constr . function_code = new runtime_statement ( SemanticTree . runtime_statement_type . ctor_delegate , null ) ;
delegate_internal_interface converted_dii = new delegate_internal_interface ( inv . return_value_type ,
inv , constr ) ;
converted_dii . parameters . AddRange ( inv . parameters ) ;
instance . add_internal_interface ( converted_dii ) ;
}
}
public static void reset_generics ( )
{
generic_instances . Clear ( ) ;
all_type_instances . Clear ( ) ;
all_function_instances . Clear ( ) ;
}
//Определяет, как должен выглядеть тип в семантическом дереве.
//Возвращает этот тип.
2020-06-12 16:38:46 +03:00
public static type_node determine_type ( Type t , List < type_node > param_types , bool method_param_types , List < type_node > generic_param_types = null )
2019-06-16 23:44:32 +03:00
{
if ( t = = null ) return null ;
if ( t . IsGenericParameter )
{
//Если мы определяем тип-параметры метода, нет необходимости рассматривать
//тип-параметры типа, и наоборот. Это для поддержки generic-методов в
//generic-типе.
if ( method_param_types = = ( t . DeclaringMethod ! = null ) )
{
2020-02-07 09:31:40 +03:00
try
{
return param_types [ t . GenericParameterPosition ] ;
}
catch ( Exception e )
{
2022-01-28 11:55:37 +03:00
// e = e; // PVS 01/2022
2020-02-07 09:31:40 +03:00
}
2019-06-16 23:44:32 +03:00
}
else
{
return compiled_type_node . get_type_node ( t ) ;
}
}
if ( t . IsGenericType )
{
//Формируем список типов-параметров
Type [ ] args = t . GetGenericArguments ( ) ;
List < type_node > semantic_args = new List < type_node > ( ) ;
foreach ( Type arg in args )
{
semantic_args . Add ( determine_type ( arg , param_types , method_param_types ) ) ;
}
//Получаем описание generic-класса
Type def = t . GetGenericTypeDefinition ( ) ;
compiled_type_node ct_def = compiled_type_node . get_type_node ( def ) ;
//Создаём псевдо-инстанцию
return ct_def . get_instance ( semantic_args ) ;
}
//Для типов, не имеющих отношения к generic-типам.
return compiled_type_node . get_type_node ( t ) ;
}
2020-06-12 16:38:46 +03:00
public static type_node determine_type ( type_node tn , List < type_node > param_types , bool method_param_types , List < type_node > generic_param_types = null )
2019-06-16 23:44:32 +03:00
{
if ( tn = = null ) return null ;
ref_type_node rtn = tn as ref_type_node ;
if ( rtn ! = null )
{
2020-06-12 16:38:46 +03:00
type_node ptype = generic_convertions . determine_type ( rtn . pointed_type , param_types , method_param_types , generic_param_types ) ;
2019-06-16 23:44:32 +03:00
if ( ptype = = rtn . pointed_type ) return tn ;
ref_type_node rez_ref = ptype . ref_type ;
rez_ref . loc = rtn . loc ;
return rez_ref ;
}
array_internal_interface ii = tn . get_internal_interface ( internal_interface_kind . unsized_array_interface ) as array_internal_interface ;
if ( ii ! = null )
{
2020-06-12 16:38:46 +03:00
type_node elem_tp = determine_type ( ii . element_type , param_types , method_param_types , generic_param_types ) ;
2019-06-16 23:44:32 +03:00
if ( elem_tp ! = ii . element_type )
{
2024-06-23 00:02:30 +03:00
return SystemLibrary . SystemLibrary . syn_visitor . convertion_data_and_alghoritms . type_constructor . create_unsized_array ( elem_tp , ii . rank , null ) ;
2019-06-16 23:44:32 +03:00
}
return tn ;
}
common_type_node comm_type = tn as common_type_node ;
if ( comm_type ! = null )
{
if ( comm_type . is_generic_parameter )
{
2020-06-12 12:29:52 +03:00
if ( method_param_types & & comm_type . generic_function_container ! = null )
2019-06-16 23:44:32 +03:00
{
2020-06-12 16:38:46 +03:00
if ( generic_param_types = = null )
return param_types [ comm_type . generic_param_index ] ;
else
{
// Мы устанавливаем, содержится ли comm_type среди generic_param_types, и если да, то меняем е г о по этому же алгоритму, а если нет, то ничего не делаем
var found = generic_param_types . Contains ( comm_type ) ;
if ( found )
return param_types [ comm_type . generic_param_index ] ;
}
2019-06-16 23:44:32 +03:00
}
else if ( ! method_param_types & & comm_type . generic_type_container ! = null )
{
return param_types [ comm_type . generic_param_index ] ;
}
return tn ;
}
generic_instance_type_node gitn = tn as generic_instance_type_node ;
if ( gitn ! = null )
{
List < type_node > semantic_args = new List < type_node > ( ) ;
List < type_node > gitn_inst_parameters = gitn . instance_params ;
foreach ( type_node arg in gitn_inst_parameters )
{
2020-06-12 16:38:46 +03:00
semantic_args . Add ( determine_type ( arg , param_types , method_param_types , generic_param_types ) ) ;
2019-06-16 23:44:32 +03:00
}
return gitn . original_generic . get_instance ( semantic_args ) ;
}
if ( comm_type . is_generic_type_definition )
{
return comm_type . get_instance ( param_types ) ;
}
if ( comm_type . type_special_kind = = SemanticTree . type_special_kind . array_kind )
{
2020-06-12 16:38:46 +03:00
type_node elem_tp = determine_type ( comm_type . element_type , param_types , method_param_types , generic_param_types ) ;
2019-06-16 23:44:32 +03:00
if ( elem_tp ! = comm_type . element_type )
{
2024-06-23 00:02:30 +03:00
return SystemLibrary . SystemLibrary . syn_visitor . convertion_data_and_alghoritms . type_constructor . create_unsized_array ( elem_tp , 1 , comm_type . loc ) ;
2019-06-16 23:44:32 +03:00
}
return tn ;
}
if ( comm_type . type_special_kind = = SemanticTree . type_special_kind . set_type )
{
2020-06-12 16:38:46 +03:00
type_node elem_tp = determine_type ( comm_type . element_type , param_types , method_param_types , generic_param_types ) ;
2019-06-16 23:44:32 +03:00
if ( elem_tp ! = comm_type . element_type )
{
return SystemLibrary . SystemLibrary . syn_visitor . context . create_set_type ( elem_tp , comm_type . loc ) ;
}
return tn ;
}
if ( comm_type . type_special_kind = = PascalABCCompiler . SemanticTree . type_special_kind . typed_file )
{
2020-06-12 16:38:46 +03:00
type_node elem_tp = determine_type ( comm_type . element_type , param_types , method_param_types , generic_param_types ) ;
2019-06-16 23:44:32 +03:00
if ( elem_tp ! = comm_type . element_type )
{
return SystemLibrary . SystemLibrary . syn_visitor . context . create_typed_file_type ( elem_tp , comm_type . loc ) ;
}
return tn ;
}
return tn ;
}
compiled_type_node ctn = tn as compiled_type_node ;
if ( ctn = = null | | ( ! ctn . compiled_type . IsGenericType & & ! ctn . compiled_type . IsGenericParameter ) )
{
return tn ;
}
return determine_type ( ctn . compiled_type , param_types , method_param_types ) ;
}
private static bool CheckIfTypeDependsOnUndeducedGenericParameters ( type_node formalType , type_node [ ] deduced ) //lroman
{
2024-01-14 14:28:36 +03:00
if ( formalType = = null )
return false ;
2019-06-16 23:44:32 +03:00
if ( formalType . generic_function_container ! = null )
{
var par_num = formalType . generic_param_index ;
return deduced [ par_num ] = = null ;
}
var formalRef = formalType as ref_type_node ;
if ( formalRef ! = null )
{
return CheckIfTypeDependsOnUndeducedGenericParameters ( formalRef . pointed_type , deduced ) ;
}
var formalIi = formalType . get_internal_interface ( internal_interface_kind . unsized_array_interface ) as array_internal_interface ;
if ( formalIi ! = null )
{
return CheckIfTypeDependsOnUndeducedGenericParameters ( formalIi . element_type , deduced ) ;
}
if ( formalType . type_special_kind = = PascalABCCompiler . SemanticTree . type_special_kind . set_type )
{
return CheckIfTypeDependsOnUndeducedGenericParameters ( formalType . element_type , deduced ) ;
}
if ( formalType . IsDelegate )
{
var dii = formalType . get_internal_interface ( internal_interface_kind . delegate_interface ) as delegate_internal_interface ;
var paramCount = dii . parameters . Count ;
for ( var i = 0 ; i < paramCount ; i + + )
{
if ( ! CheckIfTypeDependsOnUndeducedGenericParameters ( dii . parameters [ i ] . type , deduced ) )
{
return false ;
}
}
return CheckIfTypeDependsOnUndeducedGenericParameters ( dii . return_value_type , deduced ) ;
}
if ( formalType . is_generic_type_instance )
{
var pcount = formalType . instance_params . Count ;
for ( var k = 0 ; k < pcount ; + + k )
{
if ( ! CheckIfTypeDependsOnUndeducedGenericParameters ( formalType . instance_params [ k ] , deduced ) )
{
return false ;
}
}
return true ;
}
return false ;
}
//Сохранить типы параметров и тип возвращаемого значения лямбд перед попыткой вычисления реального типа возвращаемого знаяения лямбд
private static Dictionary < string , Tuple < List < type_node > , type_node > > SaveLambdasStates ( IEnumerable < function_lambda_definition > lambdaParametersList )
{
var savedLambdasStates = new Dictionary < string , Tuple < List < type_node > , type_node > > ( ) ;
foreach ( var lambda in lambdaParametersList )
{
var parsTypes = new List < type_node > ( ) ;
if ( lambda . formal_parameters ! = null & & lambda . formal_parameters . params_list ! = null & &
lambda . formal_parameters . params_list . Count > 0 )
{
parsTypes . AddRange ( lambda
. formal_parameters
. params_list
. Select ( t = >
{
var lambdaNode = t . vars_type as lambda_inferred_type ;
if ( lambdaNode = = null )
{
return null ;
}
return lambdaNode . real_type is lambda_any_type_node
? ( lambda_any_type_node ) lambdaNode . real_type
: null ;
} ) ) ;
}
type_node retType ;
var lambdaResNode = lambda . return_type as lambda_inferred_type ;
if ( lambdaResNode = = null )
{
retType = null ;
}
else
{
retType = lambdaResNode . real_type is lambda_any_type_node
? ( lambda_any_type_node ) lambdaResNode . real_type
: null ;
}
savedLambdasStates . Add ( lambda . lambda_name ,
new Tuple < List < type_node > , type_node > ( parsTypes , retType ) ) ;
}
return savedLambdasStates ;
}
//Восстановление типов в исходное состояние на случай подстановки других типов
private static void RestoreLambdasStates ( List < function_lambda_definition > lambdaParametersList ,
Dictionary < string , Tuple < List < type_node > , type_node > > savedLambdasStates )
{
for ( var i = 0 ; i < lambdaParametersList . Count ; i + + )
{
var state = savedLambdasStates [ lambdaParametersList [ i ] . lambda_name ] ;
var lambdaPar = lambdaParametersList [ i ] ;
for ( var k = 0 ; k < state . Item1 . Count ; k + + )
{
var lambdaNode = lambdaPar . formal_parameters . params_list [ k ] . vars_type as lambda_inferred_type ;
if ( lambdaNode ! = null
& & state . Item1 [ k ] ! = null )
{
lambdaNode . real_type = state . Item1 [ k ] ;
}
}
var resLambdaNode = lambdaPar . return_type as lambda_inferred_type ;
if ( resLambdaNode ! = null
& & state . Item2 ! = null )
{
resLambdaNode . real_type = state . Item2 ;
}
}
}
//Попытка вычислить типы после подстановки типов формальных параметров
public static bool TryToDeduceTypesInLambda ( function_lambda_definition lambda_syntax_node ,
delegate_internal_interface formal_delegate ,
type_node [ ] deduced , List < int > nils ,
2020-06-13 15:35:47 +03:00
out Exception exception_on_body_compilation , List < type_node > generic_params )
2019-06-16 23:44:32 +03:00
{
var there_are_undeduced_params = false ;
var param_counter = 0 ;
var visitor = SystemLibrary . SystemLibrary . syn_visitor ;
var result = true ;
exception_on_body_compilation = null ;
2021-01-14 23:04:51 +03:00
int errors_count = visitor . ErrorsList . Count ;
2019-06-16 23:44:32 +03:00
/ * if ( lambda_syntax_node . formal_parameters = = null
| | lambda_syntax_node . formal_parameters . params_list = = null
| | lambda_syntax_node . formal_parameters . params_list . Count = = 0 )
{
return false ;
} * /
if ( lambda_syntax_node . formal_parameters ! = null )
foreach ( var t in lambda_syntax_node . formal_parameters . params_list )
{
var lambdaInfType = t . vars_type as lambda_inferred_type ;
if ( lambdaInfType ! = null
& & lambdaInfType . real_type is lambda_any_type_node )
{
if ( formal_delegate = = null ) // SSM 5.12.15
{
return false ;
}
if ( ! CheckIfTypeDependsOnUndeducedGenericParameters ( formal_delegate . parameters [ param_counter ] . type , deduced ) ) //Если тип параметра не зависит от невыведенных дженерик-параметров, то можем вычислить этот тип явно
{
lambdaInfType . real_type = generic_convertions . determine_type ( formal_delegate . parameters [ param_counter ] . type ,
deduced . ToList ( ) ,
true ) ; //инстанцируем и записываем вычесленный тип
}
else
{
2021-01-14 22:28:51 +03:00
there_are_undeduced_params = true ; //иначе мы не сможем вывести тип возвращаемого значения
2019-06-16 23:44:32 +03:00
break ;
}
}
param_counter + = t . idents . idents . Count ;
}
2021-01-14 22:28:51 +03:00
if ( / * ! there_are_undeduced_params
& & * / lambda_syntax_node . return_type is lambda_inferred_type
2019-06-16 23:44:32 +03:00
& & ( ( lambda_inferred_type ) lambda_syntax_node . return_type ) . real_type is lambda_any_type_node )
{
var lambdaName = lambda_syntax_node . lambda_name ;
var fl = lambda_syntax_node . lambda_visit_mode ;
lambda_syntax_node . lambda_visit_mode = LambdaVisitMode . VisitForAdvancedMethodCallProcessing ;
2026-03-08 18:30:33 +03:00
var aux_name = LambdaHelper . GetAuxiliaryLambdaName ( lambda_syntax_node . lambda_name , visitor . GeneratedNamesManager ) ;
2019-06-16 23:44:32 +03:00
lambda_syntax_node . lambda_name = aux_name ;
try
{
visitor . visit ( lambda_syntax_node ) ; //пробуем скомпилировать тело лямбды, вычислим тип возвращаемого значения
}
catch ( Exception exc )
{
2021-01-14 22:28:51 +03:00
if ( ! there_are_undeduced_params )
{
exception_on_body_compilation = exc ; // Если произошло исключение то запишем е г о в выходной параметр, оно потом будет обработано вызывающим методом
result = false ;
}
2019-06-16 23:44:32 +03:00
}
finally
{
var context = visitor . context ;
//Далее надо удалить ненужный узел из списка функций
LambdaHelper . RemoveLambdaInfoFromCompilationContext ( context , lambda_syntax_node ) ;
lambda_syntax_node . lambda_name = lambdaName ;
lambda_syntax_node . lambda_visit_mode = fl ;
if ( result )
{
2021-01-14 23:04:51 +03:00
if ( there_are_undeduced_params & & visitor . ErrorsList . Count > errors_count )
2019-06-16 23:44:32 +03:00
{
2021-01-14 23:04:51 +03:00
visitor . ErrorsList . RemoveAt ( visitor . ErrorsList . Count - 1 ) ;
2019-06-16 23:44:32 +03:00
}
else
2021-01-14 23:04:51 +03:00
{
if ( formal_delegate = = null ) // SSM 5.12.15
2019-06-16 23:44:32 +03:00
{
result = false ;
}
2021-01-14 23:04:51 +03:00
else
2019-06-16 23:44:32 +03:00
{
2021-01-14 23:04:51 +03:00
if ( formal_delegate . return_value_type = = null ) // SSM 19/04/16 - эта проверка в связи с падением при передаче функции вместо процедуры в качестве функционального параметра: a.Foreach(x->1)
{
result = false ;
}
else if ( ! DeduceInstanceTypes ( formal_delegate . return_value_type ,
( type_node ) ( ( lambda_inferred_type ) lambda_syntax_node . return_type ) . real_type ,
deduced , nils , generic_params ) ) //Выводим дженерик-параметры после того как вычислили тип возвращаемого значения
{
result = false ;
}
2019-06-16 23:44:32 +03:00
}
}
2021-01-14 23:04:51 +03:00
2019-06-16 23:44:32 +03:00
}
}
}
return result ;
}
public static function_node DeduceFunction ( function_node func , expressions_list fact , bool alone , compilation_context context , location loc , List < SyntaxTree . expression > syntax_nodes_parameters = null )
{
parameter_list formal = func . parameters ;
int formal_count = formal . Count ;
int fact_count = fact . Count ;
int generic_type_params_count = func . generic_parameters_count ;
2020-06-13 15:35:47 +03:00
List < type_node > generic_params = func . get_generic_params_list ( ) ;
2019-06-16 23:44:32 +03:00
type_node [ ] deduced = new type_node [ generic_type_params_count ] ;
List < int > nils = new List < int > ( ) ;
int count_params_to_see = fact_count ;
var lambda_syntax_nodes = new Dictionary < string , function_lambda_definition > ( ) ; //lroman Получим список фактических параметров-лямбд текущей вызываемой подпрограммы
if ( syntax_nodes_parameters ! = null
& & syntax_nodes_parameters . Count > 0 ) //lroman
{
lambda_syntax_nodes = syntax_nodes_parameters
. OfType < function_lambda_definition > ( )
. ToDictionary ( f = > f . lambda_name , f = > f ) ;
}
var lambda_in_parameters = lambda_syntax_nodes . Count > 0 ;
var saved_lambdas_states = SaveLambdasStates ( lambda_syntax_nodes . Select ( ld = > ld . Value ) ) ; // Сохраним типы лямбды перед вычислениями
if ( fact_count < formal_count )
{
//Сравниваем количества параметров
parameter par = formal [ fact_count ] ;
if ( par . default_value = = null & & ! par . is_params )
{
if ( alone )
throw new NoFunctionWithSameParametresNum ( loc , alone , func ) ;
return null ;
}
}
else
{
type_node last_params_type = null ;
bool last_is_params = false ;
parameter par = null ;
if ( formal_count > 0 )
{
par = formal [ formal_count - 1 ] ;
last_is_params = par . is_params ;
}
if ( last_is_params )
{
array_internal_interface aii = par . type . get_internal_interface ( internal_interface_kind . unsized_array_interface ) as array_internal_interface ;
last_params_type = aii . element_type ;
}
if ( fact_count > formal_count )
{
//Фактических больше, чем формальных. Последний формальный должен быть params...
if ( last_is_params )
{
for ( int i = formal_count - 1 ; i < fact_count ; + + i )
{
//Проверяем фактические, попадающие под params...
2020-06-13 15:35:47 +03:00
if ( ! DeduceInstanceTypes ( last_params_type , fact [ i ] . type , deduced , nils , generic_params ) )
2019-06-16 23:44:32 +03:00
{
if ( alone & & fact [ i ] . type is delegated_methods & & ( fact [ i ] . type as delegated_methods ) . empty_param_method ! = null )
{
2020-06-13 15:35:47 +03:00
if ( DeduceInstanceTypes ( last_params_type , ( fact [ i ] . type as delegated_methods ) . empty_param_method . type , deduced , nils , generic_params ) )
2019-06-16 23:44:32 +03:00
continue ;
}
else if ( alone )
throw new SimpleSemanticError ( loc , "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS" , func . name ) ;
return null ;
}
}
count_params_to_see = formal_count - 1 ;
}
else
{
if ( alone )
throw new NoFunctionWithSameParametresNum ( loc , alone , func ) ;
return null ;
}
}
else if ( last_is_params )
{
for ( int i = formal_count - 1 ; i < fact_count ; + + i )
{
//Проверяем фактические, попадающие под params...
type_node tn = fact [ i ] . type ;
2021-12-14 22:42:39 +03:00
bool deduce_empty_func_call = false ;
if ( tn is delegated_methods & & ( tn as delegated_methods ) . empty_param_method ! = null & & last_params_type . is_generic_parameter )
{
tn = ( tn as delegated_methods ) . empty_param_method . ret_type ;
deduce_empty_func_call = true ;
}
2019-06-16 23:44:32 +03:00
if ( tn . element_type ! = null & & tn . type_special_kind ! = SemanticTree . type_special_kind . array_wrapper )
tn = tn . element_type ;
2021-12-14 22:42:39 +03:00
2020-06-13 15:35:47 +03:00
if ( ! DeduceInstanceTypes ( last_params_type , tn , deduced , nils , generic_params ) )
2019-06-16 23:44:32 +03:00
{
2021-12-14 22:42:39 +03:00
if ( deduce_empty_func_call & & DeduceInstanceTypes ( last_params_type , fact [ i ] . type , deduced , nils , generic_params ) )
continue ;
2019-06-16 23:44:32 +03:00
if ( alone )
throw new SimpleSemanticError ( loc , "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS" , func . name ) ;
return null ;
}
}
count_params_to_see = formal_count - 1 ;
}
}
bool need_params_work = ( count_params_to_see > 0 & & formal [ count_params_to_see - 1 ] . is_params ) ;
if ( need_params_work )
{
count_params_to_see - = 1 ;
}
var continue_trying_to_infer_types = true ;
Dictionary < string , delegate_internal_interface > formal_delegates = null ;
while ( continue_trying_to_infer_types ) //Продолжаем пытаться вычислить типы до тех пор пока состояние о выведенных типах не будет отличаться от состояния на предыдущей итерации
{
var previous_deduce_state = deduced // Текущее состояние выведенных на данный момент типов. Простой список индексов с уже выведенными типами из массива deduced
. Select ( ( t , i ) = > new { Type = t , Index = i } )
. Where ( t = > t . Type ! = null )
. Select ( t = > t . Index )
. ToArray ( ) ;
2021-07-10 10:45:02 +03:00
// SSM 08/07/21 попытаться вывести нефункциональные параметры первыми
/ * for ( int i = 0 ; i < count_params_to_see ; + + i )
if ( ! ( fact [ i ] . type is delegated_methods ) )
{
bool b = DeduceInstanceTypes ( formal [ i ] . type , fact [ i ] . type , deduced , nils , generic_params ) ;
b = b ;
} * /
2019-06-16 23:44:32 +03:00
for ( int i = 0 ; i < count_params_to_see ; + + i )
{
2020-06-13 15:35:47 +03:00
if ( alone & & fact [ i ] . type is delegated_methods & & ( fact [ i ] . type as delegated_methods ) . empty_param_method ! = null & & DeduceInstanceTypes ( formal [ i ] . type , ( fact [ i ] . type as delegated_methods ) . empty_param_method . type , deduced , nils , generic_params ) )
2019-06-16 23:44:32 +03:00
continue ;
else
2020-06-13 15:35:47 +03:00
if ( ! DeduceInstanceTypes ( formal [ i ] . type , fact [ i ] . type , deduced , nils , generic_params ) )
2019-06-16 23:44:32 +03:00
{
if ( alone & & fact [ i ] . type is delegated_methods & & ( fact [ i ] . type as delegated_methods ) . empty_param_method ! = null )
{
2020-06-13 15:35:47 +03:00
if ( DeduceInstanceTypes ( formal [ i ] . type , ( fact [ i ] . type as delegated_methods ) . empty_param_method . type , deduced , nils , generic_params ) )
2019-06-16 23:44:32 +03:00
continue ;
}
if ( alone )
throw new SimpleSemanticError ( loc , "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS" , func . name ) ;
RestoreLambdasStates ( lambda_syntax_nodes . Values . ToList ( ) , saved_lambdas_states ) ;
return null ;
}
}
if ( lambda_in_parameters )
{
if ( formal_delegates = = null )
{
formal_delegates = new Dictionary < string , delegate_internal_interface > ( ) ;
for ( int i = 0 ; i < count_params_to_see ; + + i )
//Выделим из формальных параметров те, которые соотвтествуют фактическим параметрам-лямбдам
{
var lambda_func = fact [ i ] . type as delegated_methods ;
if ( lambda_func ! = null
& & lambda_func . proper_methods . Count = = 1
& & LambdaHelper . IsLambdaName ( lambda_func . proper_methods [ 0 ] . simple_function_node . name ) )
{
formal_delegates . Add ( LambdaHelper . GetLambdaNamePartWithoutGenerics ( lambda_func . proper_methods [ 0 ] . simple_function_node . name ) ,
formal [ i ] . type . get_internal_interface (
internal_interface_kind . delegate_interface ) as
delegate_internal_interface ) ;
}
}
}
foreach ( var formal_delegate in formal_delegates )
// Перебираем все полученные формальные параметры, соответствующие фактическим лямбдам
{
var lambda_syntax_node = lambda_syntax_nodes [ formal_delegate . Key ] ;
Exception on_lambda_body_compile_exception ;
// Исключение которое может возникнуть в результате компиляции тела лямбды если мы выберем неправильные типы параметров
var b = TryToDeduceTypesInLambda ( lambda_syntax_node , formal_delegate . Value , deduced , nils ,
2020-06-13 15:35:47 +03:00
out on_lambda_body_compile_exception , generic_params ) ;
2019-06-16 23:44:32 +03:00
if ( ! b )
// Пробуем вычислить типы из лямбд
{
RestoreLambdasStates ( lambda_syntax_nodes . Values . ToList ( ) , saved_lambdas_states ) ;
if ( on_lambda_body_compile_exception ! = null )
{
if ( alone )
{
throw on_lambda_body_compile_exception ;
}
throw new FailedWhileTryingToCompileLambdaBodyWithGivenParametersException (
on_lambda_body_compile_exception ) ;
}
if ( alone )
{
throw new SimpleSemanticError ( loc , "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS" , func . name ) ;
}
return null ;
}
}
}
var current_deduce_state = deduced //текущее состояние выведенных типов
. Select ( ( t , ii ) = > new { Type = t , Index = ii } )
. Where ( t = > t . Type ! = null )
. Select ( t = > t . Index )
. ToArray ( ) ;
if ( previous_deduce_state . SequenceEqual ( current_deduce_state ) ) // Если ничего с прошлой итерации не изменилось, то дальше нет смысла пробовать выводить. Выходим из цикла
{
continue_trying_to_infer_types = false ;
}
}
RestoreLambdasStates ( lambda_syntax_nodes . Values . ToList ( ) , saved_lambdas_states ) ;
if ( need_params_work )
{
type_node [ ] tmp_deduced = ( type_node [ ] ) deduced . Clone ( ) ;
List < int > tmp_nils = new List < int > ( ) ;
tmp_nils . AddRange ( nils ) ;
2020-06-13 15:35:47 +03:00
if ( ! DeduceInstanceTypes ( formal [ count_params_to_see ] . type , fact [ count_params_to_see ] . type , deduced , nils , generic_params ) )
2019-06-16 23:44:32 +03:00
{
//Второй шанс. Учитываем слово params.
deduced = tmp_deduced ;
nils = tmp_nils ;
2020-06-13 15:35:47 +03:00
if ( ! DeduceInstanceTypes ( formal [ count_params_to_see ] . type . element_type , fact [ count_params_to_see ] . type , deduced , nils , generic_params ) )
2019-06-16 23:44:32 +03:00
{
if ( alone )
throw new SimpleSemanticError ( loc , "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS" , func . name ) ;
return null ;
}
}
}
//Вывели всё, что могли. Теперь проверяем.
for ( int i = 0 ; i < generic_type_params_count ; + + i )
{
if ( deduced [ i ] = = null )
{
if ( alone )
throw new SimpleSemanticError ( loc , "CAN_NOT_DEDUCE_TYPE_PARAMS_FROM_CALL_{0}" , func . name ) ;
return null ;
}
}
foreach ( int num in nils )
{
if ( ! type_table . is_with_nil_allowed ( deduced [ num ] ) )
{
if ( alone )
throw new SimpleSemanticError ( loc , "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS" , func . name ) ;
return null ;
}
}
foreach ( type_node tt in deduced )
{
CompilationErrorWithLocation check_err = generic_parameter_eliminations . check_type_generic_useful ( tt , loc ) ;
if ( check_err ! = null )
{
if ( alone )
throw check_err ;
return null ;
}
}
//Итак, вывели все параметры. Теперь инстанцируем.
List < type_node > deduced_list = new List < type_node > ( generic_type_params_count ) ;
deduced_list . AddRange ( deduced ) ;
return func . get_instance ( deduced_list , alone , loc ) ;
}
//Выведение типов
2020-06-13 15:35:47 +03:00
public static bool DeduceInstanceTypes ( type_node formal_type , type_node fact_type , type_node [ ] deduced , List < int > nils , List < type_node > generic_params )
2019-06-16 23:44:32 +03:00
{
if ( fact_type = = null ) //issue #347
return false ;
2022-04-03 14:41:13 +03:00
if ( formal_type = = null )
return false ;
2019-06-16 23:44:32 +03:00
if ( formal_type . generic_function_container = = null & & fact_type . generic_function_container ! = null )
{
//swap
type_node tmp = formal_type ;
formal_type = fact_type ;
fact_type = tmp ;
}
//Формальный тип - generic-параметр функции. Выводим.
if ( formal_type . generic_function_container ! = null )
{
2020-06-13 15:35:47 +03:00
// SSM 13/06/20 Если formal_type не входит в generic_params, то вернуть false
if ( ! generic_params . Contains ( formal_type ) ) // SSM 13.06.20 #2067
{
return true ; // т.е . вывод закончен - нечего выводить
}
2019-06-16 23:44:32 +03:00
int par_num = formal_type . generic_param_index ;
if ( fact_type . semantic_node_type = = semantic_node_type . null_type_node )
{
nils . Add ( par_num ) ;
return true ;
}
if ( deduced [ par_num ] = = null )
{
//Этот тип-параметр ещё не был выведен.
if ( fact_type is delegated_methods & & ( fact_type as delegated_methods ) . empty_param_method ! = null & & ( fact_type as delegated_methods ) . empty_param_method . ret_type ! = null )
fact_type = ( fact_type as delegated_methods ) . empty_param_method . ret_type ;
//if (fact_type is delegated_methods)
// fact_type = visitor.CreateDelegate((fact_type as delegated_methods).proper_methods[0].simple_function_node);
deduced [ par_num ] = fact_type ;
return true ;
}
//Этот тип-параметр уже был выведен. Сравниваем с выведенным.
if ( ! convertion_data_and_alghoritms . eq_type_nodes ( fact_type , deduced [ par_num ] , true ) )
{
if ( fact_type is delegated_methods & & deduced [ par_num ] . IsDelegate )
{
delegate_internal_interface d1 = deduced [ par_num ] . get_internal_interface ( internal_interface_kind . delegate_interface ) as delegate_internal_interface ;
return convertion_data_and_alghoritms . function_eq_params_and_result ( ( fact_type as delegated_methods ) . proper_methods [ 0 ] . simple_function_node , d1 . invoke_method ) ;
}
else if ( fact_type is delegated_methods & & deduced [ par_num ] is delegated_methods )
{
return convertion_data_and_alghoritms . function_eq_params_and_result ( ( fact_type as delegated_methods ) . proper_methods [ 0 ] . simple_function_node , ( deduced [ par_num ] as delegated_methods ) . proper_methods [ 0 ] . simple_function_node ) ;
}
return false ;
}
return true ;
}
//Указатели
ref_type_node formal_ref = formal_type as ref_type_node ;
if ( formal_ref ! = null )
{
ref_type_node fact_ref = fact_type as ref_type_node ;
if ( fact_ref = = null )
{
goto eq_cmp ;
}
2020-06-13 15:35:47 +03:00
return DeduceInstanceTypes ( formal_ref . pointed_type , fact_ref . pointed_type , deduced , nils , generic_params ) ;
2019-06-16 23:44:32 +03:00
}
//безразмерные массивы
array_internal_interface formal_ii = formal_type . get_internal_interface ( internal_interface_kind . unsized_array_interface ) as array_internal_interface ;
if ( formal_ii ! = null )
{
array_internal_interface fact_ii = fact_type . get_internal_interface ( internal_interface_kind . unsized_array_interface ) as array_internal_interface ;
if ( fact_ii = = null )
{
goto eq_cmp ;
}
2020-06-13 15:35:47 +03:00
return DeduceInstanceTypes ( formal_ii . element_type , fact_ii . element_type , deduced , nils , generic_params ) ;
2019-06-16 23:44:32 +03:00
}
2020-06-13 15:35:47 +03:00
//Множества
2019-06-16 23:44:32 +03:00
if ( formal_type . type_special_kind = = PascalABCCompiler . SemanticTree . type_special_kind . set_type )
{
if ( fact_type . type_special_kind ! = PascalABCCompiler . SemanticTree . type_special_kind . set_type )
{
goto eq_cmp ;
}
2020-06-13 15:35:47 +03:00
return DeduceInstanceTypes ( formal_type . element_type , fact_type . element_type , deduced , nils , generic_params ) ;
2019-06-16 23:44:32 +03:00
}
2020-06-13 15:35:47 +03:00
//Типизированные файлы
2019-06-16 23:44:32 +03:00
if ( formal_type . type_special_kind = = PascalABCCompiler . SemanticTree . type_special_kind . typed_file )
{
if ( fact_type . type_special_kind ! = PascalABCCompiler . SemanticTree . type_special_kind . typed_file )
{
goto eq_cmp ;
}
2020-06-13 15:35:47 +03:00
return DeduceInstanceTypes ( formal_type . element_type , fact_type . element_type , deduced , nils , generic_params ) ;
2019-06-16 23:44:32 +03:00
}
//Делегаты
if ( formal_type . IsDelegate )
{
//Если текущий параметр - лямбда, то просто выводим дженерик-параметры из типов, которые уже известны. Н е трогаем lambda_any_type_node. Остальное выведется в цикле выше
2021-07-06 16:28:02 +03:00
var lambda_func = fact_type as delegated_methods ; // Возвр true не только если fact_type - лямбда, но и если это имя функции
2021-03-21 13:24:27 +03:00
if ( lambda_func ! = null
& & lambda_func . proper_methods . Count = = 1
2019-06-16 23:44:32 +03:00
& & LambdaHelper . IsLambdaName ( lambda_func . proper_methods [ 0 ] . simple_function_node . name ) )
{
var dii = formal_type . get_internal_interface ( internal_interface_kind . delegate_interface ) as delegate_internal_interface ;
var fact_func = lambda_func . proper_methods [ 0 ] . simple_function_node ;
if ( fact_func . parameters . Count ! = dii . parameters . Count )
{
goto eq_cmp ;
}
var param_count = fact_func . parameters . Count ;
for ( var i = 0 ; i < param_count ; i + + )
{
if ( fact_func . parameters [ i ] . parameter_type ! = dii . parameters [ i ] . parameter_type | |
fact_func . parameters [ i ] . is_params ! = dii . parameters [ i ] . is_params )
goto eq_cmp ;
}
for ( var i = 0 ; i < param_count ; i + + )
{
if ( fact_func . parameters [ i ] . type is lambda_any_type_node )
{
continue ;
}
// 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка
2020-06-13 15:35:47 +03:00
if ( ! DeduceInstanceTypes ( dii . parameters [ i ] . type , fact_func . parameters [ i ] . type , deduced , nils , generic_params ) )
2019-06-16 23:44:32 +03:00
//if (!DeduceInstanceTypes(fact_func.parameters[i].type, dii.parameters[i].type, deduced, nils))
{
goto eq_cmp ;
}
}
if ( fact_func . return_value_type = = null & & dii . return_value_type = = null )
{
//ok
}
else if ( fact_func . return_value_type is lambda_any_type_node ) //lroman//
{
if ( dii . return_value_type = = null )
{
goto eq_cmp ;
}
return true ;
}
// 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка
2020-06-13 15:35:47 +03:00
else if ( fact_func . return_value_type = = null | | ! DeduceInstanceTypes ( dii . return_value_type , fact_func . return_value_type , deduced , nils , generic_params ) ) // SSM 29.05.14 - не выводится если IEnumerable<TResult>
2021-03-21 13:24:27 +03:00
// else if (fact_func.return_value_type == null || !DeduceInstanceTypes(fact_func.return_value_type, dii.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable<TResult>
2019-06-16 23:44:32 +03:00
{
goto eq_cmp ;
}
return true ;
}
if ( ! convertion_data_and_alghoritms . eq_type_nodes ( formal_type , fact_type , true ) )
{
delegate_internal_interface dii = formal_type . get_internal_interface ( internal_interface_kind . delegate_interface ) as delegate_internal_interface ;
delegated_methods dm = fact_type as delegated_methods ;
function_node fact_func = null ;
2021-03-21 13:24:27 +03:00
List < function_node > fact_funcs = new List < function_node > ( ) ;
2019-06-16 23:44:32 +03:00
if ( dm ! = null & & dm . proper_methods . Count = = 1 )
2021-03-21 13:24:27 +03:00
{
fact_funcs . Add ( dm . proper_methods [ 0 ] . simple_function_node ) ;
}
2019-06-16 23:44:32 +03:00
else if ( fact_type . IsDelegate )
{
var sil = fact_type . find_in_type ( "Invoke" ) ;
if ( sil ! = null & & sil . Count > 0 )
2021-03-21 13:24:27 +03:00
{
fact_funcs . Add ( sil [ 0 ] . sym_info as function_node ) ;
}
2019-06-16 23:44:32 +03:00
}
2021-07-10 10:45:02 +03:00
// SSM 09.07 - My(f: T->T1) при наличии двух f - следующие 2 else дают пропуск этой ошибки!! Она внесена 10.01 в 20:54 при исправлении 1093
// Видимо, это улучшило ситуацию - просто надо точнее отбрасывать часть fact_funcs
2021-01-10 20:54:40 +03:00
else if ( dm ! = null & & dm . proper_methods . Count > 1 & & formal_type . original_generic is compiled_type_node & & ( formal_type . original_generic as compiled_type_node ) . compiled_type . FullName . StartsWith ( "System.Func`" ) )
{
var ctn = formal_type . original_generic as compiled_type_node ;
foreach ( var fc in dm . proper_methods )
{
if ( fc . simple_function_node . parameters . Count = = formal_type . instance_params . Count - 1 )
{
2021-03-21 13:24:27 +03:00
fact_funcs . Add ( fc . simple_function_node ) ;
2021-01-10 20:54:40 +03:00
}
}
}
2021-03-21 13:24:27 +03:00
else if ( dm ! = null & & dm . proper_methods . Count > 1 & & formal_type . original_generic is compiled_type_node & & ( formal_type . original_generic as compiled_type_node ) . compiled_type . FullName . StartsWith ( "System.Action`" ) )
{
var ctn = formal_type . original_generic as compiled_type_node ;
foreach ( var fc in dm . proper_methods )
{
if ( fc . simple_function_node . parameters . Count = = formal_type . instance_params . Count )
{
fact_funcs . Add ( fc . simple_function_node ) ;
}
}
2021-07-10 10:45:02 +03:00
}
// end SSM 09.07 - конец кода, который был написан раньше IB. Здесь поясняется е г о влияние на ошибки
2021-03-21 13:24:27 +03:00
for ( int j = 0 ; j < fact_funcs . Count ; j + + )
2019-06-16 23:44:32 +03:00
{
2021-03-21 13:24:27 +03:00
fact_func = fact_funcs [ j ] ;
2019-06-16 23:44:32 +03:00
if ( fact_func . parameters . Count ! = dii . parameters . Count )
{
2021-03-21 13:24:27 +03:00
if ( j < fact_funcs . Count - 1 )
continue ;
2019-06-16 23:44:32 +03:00
goto eq_cmp ;
}
int param_count = fact_func . parameters . Count ;
for ( int i = 0 ; i < param_count ; i + + )
{
if ( fact_func . parameters [ i ] . parameter_type ! = dii . parameters [ i ] . parameter_type | |
fact_func . parameters [ i ] . is_params ! = dii . parameters [ i ] . is_params )
2021-03-21 13:24:27 +03:00
{
if ( j < fact_funcs . Count - 1 )
continue ;
2019-06-16 23:44:32 +03:00
goto eq_cmp ;
2021-03-21 13:24:27 +03:00
}
2019-06-16 23:44:32 +03:00
}
2021-07-06 16:28:02 +03:00
bool skip_j = false ; // SSM 06/07/21
2019-06-16 23:44:32 +03:00
for ( int i = 0 ; i < param_count ; i + + )
{
2020-06-13 15:35:47 +03:00
if ( ! DeduceInstanceTypes ( dii . parameters [ i ] . type , fact_func . parameters [ i ] . type , deduced , nils , generic_params ) ) // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка
2019-06-16 23:44:32 +03:00
{
2021-03-21 13:24:27 +03:00
if ( j < fact_funcs . Count - 1 )
2021-07-06 16:28:02 +03:00
{
skip_j = true ; // SSM 06/07/21
break ;
//continue; // тут надо завершать итерацию по j, а не по i !!!
}
2019-06-16 23:44:32 +03:00
goto eq_cmp ;
}
}
2021-07-06 16:28:02 +03:00
if ( skip_j ) // // SSM 06/07/21 пропустить текущую итерацию по j !!
continue ;
2019-06-16 23:44:32 +03:00
if ( fact_func . return_value_type = = null & & dii . return_value_type = = null )
{
//ok
}
else if ( fact_func . return_value_type is lambda_any_type_node & & dii . return_value_type = = null ) //lroman//
{
2021-03-21 13:24:27 +03:00
if ( j < fact_funcs . Count - 1 )
continue ;
2019-06-16 23:44:32 +03:00
goto eq_cmp ;
}
// 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка
2020-06-13 15:35:47 +03:00
else if ( fact_func . return_value_type = = null | | ! DeduceInstanceTypes ( dii . return_value_type , fact_func . return_value_type , deduced , nils , generic_params ) ) // SSM 29.05.14 - не выводится если IEnumerable<TResult>
2021-03-21 13:24:27 +03:00
// else if (fact_func.return_value_type == null || !DeduceInstanceTypes(fact_func.return_value_type, dii.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable<TResult>
2019-06-16 23:44:32 +03:00
{
2021-03-21 13:24:27 +03:00
if ( j < fact_funcs . Count - 1 )
continue ;
2019-06-16 23:44:32 +03:00
goto eq_cmp ;
}
2021-07-06 16:28:02 +03:00
return true ; // SSM 06/07/21 тут сбита логика. Мы рассматриваем получается только первую fact_func[0] и выходим
2019-06-16 23:44:32 +03:00
}
}
if ( fact_type . IsDelegate & & fact_type . semantic_node_type = = semantic_node_type . delegated_method )
return true ;
//goto eq_cmp;
}
//Инстанции дженериков
if ( formal_type . is_generic_type_instance )
{
//if () goto eq_cmp;
type_node fact_type_converted ; //Сюда будет записан фактический тип или интерфейс, к которому он приводится
if ( ! fact_type . is_generic_type_instance | | formal_type . original_generic ! = fact_type . original_generic )
{
//if (!formal_type.IsInterface) goto eq_cmp;
fact_type_converted = null ;
type_node base_type = fact_type . base_type ;
while ( base_type ! = null )
{
if ( base_type . original_generic = = formal_type . original_generic )
{
fact_type_converted = base_type ;
break ;
}
base_type = base_type . base_type ;
}
if ( fact_type . ImplementingInterfaces ! = null & & fact_type_converted = = null )
{
2021-03-16 22:29:26 +03:00
foreach ( type_node ti in fact_type . ImplementingInterfaces )
2019-06-16 23:44:32 +03:00
{
2021-03-16 22:29:26 +03:00
if ( ti . original_generic = = formal_type . original_generic )
{
fact_type_converted = ti ;
break ;
}
}
if ( fact_type_converted = = null )
{
base_type = fact_type . base_type ;
while ( base_type ! = null )
{
if ( base_type . ImplementingInterfaces ! = null )
foreach ( type_node ti in base_type . ImplementingInterfaces )
{
if ( ti . original_generic = = formal_type . original_generic )
{
fact_type_converted = ti ;
break ;
}
}
if ( fact_type_converted ! = null )
break ;
base_type = base_type . base_type ;
}
2019-06-16 23:44:32 +03:00
}
}
2021-03-16 22:29:26 +03:00
2019-06-16 23:44:32 +03:00
if ( fact_type_converted = = null ) goto eq_cmp ;
}
else
{
fact_type_converted = fact_type ;
}
int pcount = formal_type . instance_params . Count ;
for ( int k = 0 ; k < pcount ; + + k )
{
2020-06-13 15:35:47 +03:00
if ( ! DeduceInstanceTypes ( formal_type . instance_params [ k ] , fact_type_converted . instance_params [ k ] , deduced , nils , generic_params ) )
2019-06-16 23:44:32 +03:00
{
goto eq_cmp ;
}
}
return true ;
}
//Если совпадают - всё хорошо.
eq_cmp :
if ( convertion_data_and_alghoritms . eq_type_nodes ( formal_type , fact_type , true ) )
{
return true ;
}
possible_type_convertions ptc = type_table . get_convertions ( fact_type , formal_type ) ;
if ( ptc . first ! = null )
{
return true ;
}
return false ;
}
public static string MakePseudoInstanceName ( string name , List < type_node > param_types , bool type_name )
{
string rez ;
if ( type_name )
{
2024-05-04 20:21:50 +03:00
int last = name . LastIndexOf ( StringConstants . generic_params_infix ) ;
2019-06-16 23:44:32 +03:00
if ( last < 0 )
{
rez = name ;
}
else
{
rez = name . Substring ( 0 , last ) ;
}
}
else
{
rez = name ;
}
bool first = true ;
foreach ( type_node tnode in param_types )
{
rez + = ( ( first ) ? "<" : "," ) + tnode . PrintableName ;
first = false ;
}
rez + = ">" ;
return rez ;
}
public static bool type_has_default_ctor ( type_node tn , bool find_protected_ctors )
{
2021-01-26 22:41:42 +03:00
if ( tn . is_generic_parameter & & tn . base_type ! = null & & tn . base_type . IsAbstract & & ! ( tn is common_type_node & & ( tn as common_type_node ) . has_default_constructor ) )
2019-06-16 23:44:32 +03:00
return false ;
2024-05-04 20:21:50 +03:00
List < SymbolInfo > sil = tn . find_in_type ( StringConstants . default_constructor_name , tn . Scope ) ;
2019-06-16 23:44:32 +03:00
if ( sil ! = null )
{
foreach ( SymbolInfo si in sil )
{
function_node fn = si . sym_info as function_node ;
if ( find_protected_ctors | |
fn . field_access_level = = PascalABCCompiler . SemanticTree . field_access_level . fal_public )
{
compiled_constructor_node pconstr = fn as compiled_constructor_node ;
common_method_node mconstr = fn as common_method_node ;
if ( ( pconstr ! = null | |
mconstr ! = null & & mconstr . is_constructor ) & &
( fn . parameters . Count = = 0 | | fn . parameters [ 0 ] . default_value ! = null )
)
{
//Нашли конструктор по умолчанию у предка
return true ;
}
}
}
}
2020-06-28 16:01:06 +03:00
2019-06-16 23:44:32 +03:00
return false ;
}
public static function_node get_function_instance ( function_node orig , List < type_node > param_types )
{
List < generic_function_instance_info > _generic_instances = get_function_instances ( orig ) ;
function_node founded_inst = find_function_instance ( _generic_instances , param_types ) ;
if ( founded_inst ! = null ) return founded_inst ;
for ( int i = 0 ; i < param_types . Count ; i + + )
{
if ( param_types [ i ] is delegated_methods )
{
base_function_call bfc = ( param_types [ i ] as delegated_methods ) . proper_methods [ 0 ] ;
var context = SystemLibrary . SystemLibrary . syn_visitor . context ;
common_type_node del =
type_constructor . instance . 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 ) ;
param_types [ i ] = del ;
}
}
//Создаём новую псевдо-инстанцию
common_function_node new_func = null ;
SemanticTree . IGenericFunctionInstance new_inst = null ;
if ( orig . semantic_node_type = = semantic_node_type . common_namespace_function_node )
{
generic_namespace_function_instance_node nnode = new generic_namespace_function_instance_node ( orig as common_namespace_function_node , param_types ) ;
nnode . ConnectedToType = ( orig as common_namespace_function_node ) . ConnectedToType ;
new_func = nnode ;
new_inst = nnode ;
}
else
{
generic_method_instance_node ctnode = new generic_method_instance_node ( orig , param_types ) ;
new_func = ctnode ;
new_inst = ctnode ;
}
common_function_node common_orig = orig as common_function_node ;
if ( common_orig ! = null )
{
new_func . num_of_default_variables = common_orig . num_of_default_variables ;
}
var shouldAddToAllTypeInstances = true ;
if ( LambdaHelper . processingLambdaParametersForTypeInference ! = 0 )
{
foreach ( var par in param_types )
{
if ( par is lambda_any_type_node )
{
shouldAddToAllTypeInstances = false ;
break ;
}
}
}
if ( shouldAddToAllTypeInstances ) //lroman// Если зашли сюда при выведении типов параметров лямбды, то функция инстанцироваться может с типом lambda_any_type_node. Поэтому, если выводим типы. Т о данную инстанцию не добавляем
{
_generic_instances . Add ( new generic_function_instance_info ( param_types , new_func ) ) ;
all_function_instances . Add ( new_inst ) ;
}
return new_func ;
}
}
public class generic_instance_type_node : common_type_node , SemanticTree . IGenericTypeInstance
{
protected Hashtable _members = new Hashtable ( ) ;
protected Hashtable _member_definitions = new Hashtable ( ) ;
protected type_node _original_generic ;
public override SymbolTable . Scope Scope
{
get
{
return _original_generic . Scope ;
}
}
SemanticTree . ITypeNode SemanticTree . IGenericTypeInstance . original_generic
{
get { return _original_generic ; }
}
public override type_node original_generic
{
get { return _original_generic ; }
}
public Hashtable used_members
{
get
{
return _members ;
}
}
protected List < SemanticTree . ITypeNode > _generic_parameters = null ;
protected List < type_node > _instance_params ;
public generic_instance_type_node ( type_node original_generic_type ,
List < type_node > param_types ,
type_node base_type , string name , SemanticTree . type_access_level type_access_level ,
common_namespace_node comprehensive_namespace , location loc )
:
base ( base_type , name , type_access_level , comprehensive_namespace ,
null , loc )
{
_original_generic = original_generic_type ;
_instance_params = param_types ;
2022-10-06 11:06:27 +03:00
SetImplementingInterfaces ( null ) ;
2019-06-16 23:44:32 +03:00
}
public List < SemanticTree . ITypeNode > generic_parameters
{
get
{
if ( _generic_parameters = = null )
{
_generic_parameters = new List < SemanticTree . ITypeNode > ( _instance_params . Count ) ;
foreach ( type_node tn in _instance_params )
{
_generic_parameters . Add ( tn ) ;
}
}
return _generic_parameters ;
}
}
2022-10-06 11:06:27 +03:00
public override List < SemanticTree . ITypeNode > ImplementingInterfaces
{
get
{
var res = base . ImplementingInterfaces ;
if ( res = = null )
{
res = new List < SemanticTree . ITypeNode > ( ) ;
foreach ( type_node interf in original_generic . ImplementingInterfaces )
res . Add ( generic_convertions . determine_type ( interf , this . instance_params , false ) ) ;
SetImplementingInterfaces ( res ) ;
}
return res ;
}
}
public override List < SemanticTree . ITypeNode > ImplementingInterfacesOrEmpty
{
get
{
return base . ImplementingInterfaces ? ? new List < SemanticTree . ITypeNode > ( ) ;
}
}
2019-06-16 23:44:32 +03:00
2023-07-02 22:22:49 +03:00
/ * public override property_node default_property_node
2023-07-02 21:48:21 +03:00
{
get
{
if ( default_property ! = null )
return default_property ;
if ( original_generic . default_property_node ! = null )
default_property = ConvertMember ( original_generic . default_property_node ) as common_property_node ;
return default_property ;
}
2023-07-02 22:22:49 +03:00
} * /
2023-07-02 21:48:21 +03:00
2019-06-16 23:44:32 +03:00
private List < SymbolInfo > temp_names = new List < SymbolInfo > ( 3 ) ;
public override void add_name ( string name , SymbolInfo si )
{
temp_names . Add ( si ) ;
}
protected void AddMember ( object original , object converted )
{
var cf = original as class_field ;
#if DEBUG
/ * if ( cf ! = null & & cf . name = = "XYZW" )
{
cf = cf ;
} * /
#endif
// Этот код дает перекрестные ошибки далее поэтому эта идея неправильна. Комментирую
/ * if ( cf ! = null ) // значит это поле и заменять original на соответствующее поле оригинального класса
{
var or = this . original_generic as common_type_node ;
original = or . fields . First ( f = > f . name = = cf . name ) ;
if ( original = = null )
{
original = original ;
}
} * /
if ( ! _members . ContainsValue ( original ) ) // SSM 30.12.18 bug fix #907
{
// Если это поле и T1->Anything, то как-то надо находить оригинальный класс Base и заменять на T->Anything
// Вторая версия - делать это в GetMember - там доступны все _members
// Закомментировал всё кроме того что было - изменение вместо добавления срабатывает только если мы в предыдущем коде меняли original, а именно эта идея признана ошибочной
//if (!_members.ContainsKey(original))
//{
_members . Add ( original , converted ) ;
_member_definitions . Add ( converted , original ) ;
//}
/ * else
{
_members [ original ] = converted ;
_member_definitions [ original ] = converted ;
} * /
}
else // SSM 30.12.18 bug fix #907
{
object kk = null ;
foreach ( System . Collections . DictionaryEntry x in _members )
{
if ( x . Value = = original )
kk = x . Key ;
}
_members [ kk ] = converted ;
_member_definitions . Remove ( original ) ;
_member_definitions [ converted ] = kk ;
}
}
protected parameter_list make_parameters ( parameter_list orig_pl , common_function_node fn )
{
parameter_list pl = new parameter_list ( ) ;
//TODO: разобраться с concrete_parameter_type
foreach ( parameter p in orig_pl )
{
common_parameter cp = new common_parameter (
p . name , generic_convertions . determine_type ( p . type , _instance_params , false ) ,
p . parameter_type ,
fn , concrete_parameter_type . cpt_none , p . inital_value , null ) ;
cp . intrenal_is_params = p . is_params ;
cp . is_special_name = p . is_special_name ;
cp . is_ret_value = p . is_ret_value ;
cp . default_value = p . default_value ;
pl . AddElement ( cp ) ;
}
return pl ;
}
//(ssyy) Создаёт метод псевдо-инстанции generic-типа.
protected common_method_node make_method ( function_node orig_fn , location loc )
{
if ( orig_fn = = null )
{
return null ;
}
List < type_node > meth_inst_pars = null ;
2020-06-12 16:38:46 +03:00
List < type_node > orig_tpars = null ;
2019-06-16 23:44:32 +03:00
SemanticTree . IClassMemberNode orig_member = orig_fn as SemanticTree . IClassMemberNode ;
common_method_node cmn = new common_method_node (
orig_fn . name ,
//generic_convertions.determine_type(orig_fn.return_value_type, _instance_params, false),
null ,
loc , this , orig_member . polymorphic_state , orig_member . field_access_level ,
null ) ;
if ( orig_fn . is_generic_function )
{
2020-06-12 16:38:46 +03:00
orig_tpars = orig_fn . get_generic_params_list ( ) ;
2019-06-16 23:44:32 +03:00
int type_count = orig_tpars . Count ;
cmn . generic_params = new List < PascalABCCompiler . SemanticTree . ICommonTypeNode > ( orig_tpars . Count ) ;
foreach ( type_node t in orig_tpars )
{
common_type_node par = new common_type_node ( t . name , PascalABCCompiler . SemanticTree . type_access_level . tal_public ,
null , SystemLibrary . SystemLibrary . syn_visitor . convertion_data_and_alghoritms . symbol_table . CreateInterfaceScope ( null , SystemLibrary . SystemLibrary . object_type . Scope , null ) , null ) ;
SystemLibrary . SystemLibrary . init_reference_type ( par ) ;
par . SetBaseType ( SystemLibrary . SystemLibrary . object_type ) ;
cmn . generic_params . Add ( par ) ;
par . generic_function_container = cmn ;
}
meth_inst_pars = cmn . get_generic_params_list ( ) ;
List < generic_parameter_eliminations > gpes = orig_fn . parameters_eliminations ;
for ( int i = 0 ; i < type_count ; + + i )
{
common_type_node p = ( common_type_node ) ( meth_inst_pars [ i ] ) ;
generic_parameter_eliminations gpe = gpes [ i ] ;
p . SetBaseType ( generic_convertions . determine_type (
generic_convertions . determine_type ( gpe . base_class , _instance_params , false ) ,
meth_inst_pars , true ) ) ;
p . is_class = gpe . is_class ;
p . internal_is_value = gpe . is_value ;
foreach ( type_node interf in gpe . implementing_interfaces )
{
type_table . AddInterface ( p , generic_convertions . determine_type (
generic_convertions . determine_type ( interf , _instance_params , false ) ,
meth_inst_pars , true ) , null ) ;
}
if ( gpe . has_default_ctor )
{
generic_parameter_eliminations . add_default_ctor ( p ) ;
}
}
}
cmn . parameters . AddRange ( make_parameters ( orig_fn . parameters , cmn ) ) ;
2020-06-12 12:29:52 +03:00
if ( orig_fn . is_generic_function ) // orig_fn м.б . generic-методом, но и класс м.б .generic!!! Смешение параметров! А у нас либо класс, либо функция
2019-06-16 23:44:32 +03:00
{
foreach ( common_parameter cp in cmn . parameters )
{
2020-06-12 12:29:52 +03:00
//if (cp.type.PrintableName == "Action<TSource>" || cp.type.PrintableName == "TSource") { } // ничего не надо делать, поскольку
//cp.type = generic_convertions.determine_type(cp.type, _instance_params, false);
//else
// Action<T,T2> - T м.б . от класса, а T2 - от метода! И надо передавать о б а : meth_inst_pars и _instance_params
// И индексом м.б . не обойдёшься
2020-06-12 16:38:46 +03:00
cp . type = generic_convertions . determine_type ( cp . type , meth_inst_pars , true , orig_tpars ) ;
2019-06-16 23:44:32 +03:00
}
}
common_method_node common_orig = orig_fn as common_method_node ;
if ( common_orig ! = null )
{
cmn . num_of_default_variables = common_orig . num_of_default_variables ;
}
compiled_constructor_node compiled_orig = orig_fn as compiled_constructor_node ;
cmn . is_constructor = ( compiled_orig ! = null | |
( common_orig ! = null & & common_orig . is_constructor ) ) ;
cmn . return_value_type = generic_convertions . determine_type ( orig_fn . return_value_type , _instance_params , false ) ;
if ( common_orig ! = null )
cmn . overrided_method = common_orig . overrided_method ;
if ( orig_fn . is_generic_function )
{
2021-12-29 17:02:15 +03:00
cmn . return_value_type = generic_convertions . determine_type ( cmn . return_value_type , meth_inst_pars , true , orig_tpars ) ;
2019-06-16 23:44:32 +03:00
}
if ( orig_fn is common_function_node )
{
cmn . return_variable = ( orig_fn as common_function_node ) ? . return_variable ;
}
2020-08-01 16:04:54 +03:00
cmn . IsOperator = orig_fn . IsOperator ;
2024-01-04 19:44:29 +03:00
if ( orig_fn is compiled_function_node )
{
compiled_function_node fn_orig = orig_fn as compiled_function_node ;
if ( fn_orig . method_info . GetBaseDefinition ( ) ! = null )
cmn . overrided_method = compiled_function_node . get_compiled_method ( fn_orig . method_info . GetBaseDefinition ( ) ) ;
}
2019-06-16 23:44:32 +03:00
return cmn ;
}
2023-05-14 12:36:08 +03:00
public override bool IsAbstract
{
get
{
return original_generic . IsAbstract ;
}
}
2019-06-16 23:44:32 +03:00
public override List < type_node > instance_params
{
get
{
return _instance_params ;
}
set
{
_instance_params = value ;
}
}
public override bool is_generic_type_instance
{
get
{
return true ;
}
}
protected void AddPropertyAccessors ( property_node pn )
{
if ( pn . get_function ! = null )
{
if ( _members [ pn . get_function ] = = null )
{
ConvertMember ( pn . get_function ) ;
}
}
if ( pn . set_function ! = null )
{
if ( _members [ pn . set_function ] = = null )
{
ConvertMember ( pn . set_function ) ;
}
}
}
protected common_event make_event ( event_node orig_event , location loc )
{
common_event cme = orig_event as common_event ;
compiled_event ce = orig_event as compiled_event ;
if ( _members [ orig_event . add_method ] = = null )
ConvertMember ( orig_event . add_method ) ;
if ( _members [ orig_event . remove_method ] = = null )
ConvertMember ( orig_event . remove_method ) ;
if ( orig_event . raise_method ! = null & & _members [ orig_event . raise_method ] = = null )
ConvertMember ( orig_event . raise_method ) ;
common_event evnt = new common_event ( orig_event . name , generic_convertions . determine_type (
orig_event . delegate_type , _instance_params , false ) , this ,
_members [ orig_event . add_method ] as common_method_node ,
_members [ orig_event . remove_method ] as common_method_node ,
orig_event . raise_method ! = null ? _members [ orig_event . raise_method ] as common_method_node : null ,
cme ! = null ? cme . field_access_level : SemanticTree . field_access_level . fal_public ,
orig_event . is_static ? SemanticTree . polymorphic_state . ps_static : SemanticTree . polymorphic_state . ps_common ,
loc
) ;
return evnt ;
}
protected common_property_node make_property ( property_node orig_pn , location loc )
{
AddPropertyAccessors ( orig_pn ) ;
common_property_node cpn = new common_property_node (
orig_pn . name , this , generic_convertions . determine_type (
orig_pn . property_type , _instance_params , false ) ,
( orig_pn . get_function = = null ) ? null : _members [ orig_pn . get_function ] as common_method_node ,
( orig_pn . set_function = = null ) ? null : _members [ orig_pn . set_function ] as common_method_node ,
loc , orig_pn . field_access_level , orig_pn . polymorphic_state ) ;
cpn . parameters . AddRange ( make_parameters ( orig_pn . parameters , null ) ) ;
return cpn ;
}
public definition_node get_member_definition ( definition_node instance_member )
{
return _member_definitions [ instance_member ] as definition_node ;
}
public generic_instance_type_node find_instance_type_from ( type_node orig_type )
{
generic_instance_type_node bt = null ; //this;
/ * while ( bt ! = null )
{
if ( bt . _original_generic = = orig_type )
{
return bt ;
}
bt = bt . base_type as generic_instance_type_node ;
} * /
type_node curt = this ;
while ( curt ! = null )
{
bt = curt as generic_instance_type_node ;
if ( bt ! = null & & bt . original_generic = = orig_type )
{
return bt ;
}
curt = curt . base_type ;
}
foreach ( type_node tn in ImplementingInterfaces )
{
bt = tn as generic_instance_type_node ;
if ( bt ! = null & & bt . _original_generic = = orig_type )
{
return bt ;
}
}
return null ;
}
public definition_node ConvertMember ( definition_node orig_node )
{
definition_node rez_node = _members [ orig_node ] as definition_node ;
2024-11-19 13:56:47 +03:00
/ * if ( ( rez_node ! = null ) & & this . BaseFullName = = "PABCSystem.NewSet`1" & & orig_node is compiled_function_node cfn2
& & cfn2 . name = = "op_Equality" )
{
rez_node = null ;
_members . Remove ( orig_node ) ; // ну так с е б е метод - сколько операций = столько и будет удаляться и повторно создаваться :)
} * /
2019-06-16 23:44:32 +03:00
if ( rez_node = = null )
{
//Преобразуем найденный член класса.
SemanticTree . IClassMemberNode orig_member = orig_node as SemanticTree . IClassMemberNode ;
if ( orig_member = = null )
{
//Для basic_function
generic_instance_type_node gitn = base_type as generic_instance_type_node ;
if ( gitn = = null )
return orig_node ;
else
return gitn . ConvertMember ( orig_node ) ;
}
type_node tn = orig_member . comperehensive_type as type_node ;
if ( orig_member . comperehensive_type . is_generic_type_instance )
tn = tn . original_generic ;
if ( tn ! = _original_generic )
{
if ( orig_member . comperehensive_type . is_generic_type_definition )
{
generic_instance_type_node compr_type = find_instance_type_from ( orig_member . comperehensive_type as type_node ) ;
if ( compr_type = = null )
{
compiled_function_node cfn = orig_node as compiled_function_node ;
if ( cfn = = null )
{
return orig_node ;
}
compiled_type_node cct = orig_member . comperehensive_type as compiled_type_node ;
type_node inst_type = this ;
do
{
inst_type = inst_type . base_type ;
}
while ( inst_type . semantic_node_type ! = semantic_node_type . compiled_type_node | |
( inst_type ! = cct & & inst_type . original_generic ! = cct ) ) ;
/ * MethodInfo [ ] meths = cct . _compiled_type . GetMethods ( BindingFlags . Public | BindingFlags . NonPublic |
BindingFlags . Static | BindingFlags . Instance ) ;
int num = System . Array . IndexOf ( meths , cfn . method_info ) ;
//!!! прикольно, но индексы в meths и instmeths не совпадают!!!
MethodInfo [ ] instmeths = ( ( compiled_type_node ) inst_type ) . _compiled_type . GetMethods ( BindingFlags . Public | BindingFlags . NonPublic |
BindingFlags . Static | BindingFlags . Instance ) ;
//var mt1 = meths.Select(m => m.MetadataToken).OrderBy(x => x);
//var mt2 = instmeths.Select(m => m.MetadataToken).OrderBy(x => x);
MethodInfo mi = instmeths [ num ] ; * /
// SSM 2018.05.05 bug fix #664
var mdtok = cfn . method_info . MetadataToken ;
MethodInfo [ ] instmeths = ( ( compiled_type_node ) inst_type ) . _compiled_type . GetMethods ( BindingFlags . Public | BindingFlags . NonPublic |
BindingFlags . Static | BindingFlags . Instance ) ;
MethodInfo mi = System . Array . Find ( instmeths , m = > m . MetadataToken = = mdtok ) ;
// SSM 2018.05.05 end bug fix #664
return compiled_function_node . get_compiled_method ( mi ) ;
}
else
return compr_type . ConvertMember ( orig_node ) ;
}
else if ( orig_member . comperehensive_type . is_generic_type_instance )
{
/ *
// SSM 29/04/18 - проба - как достать IndexOf из MyList<integer> - наследника List<integer>
// Это поздно - надо как-то раньше
if ( tn is compiled_type_node )
tn = generic_convertions . determine_type ( ( tn as compiled_type_node ) . compiled_type , instance_params , false ) ;
var tn1 = tn as compiled_type_node ;
var ff = tn1 . find_in_type ( "IndexOf" ) ; * /
2020-06-15 10:38:41 +03:00
generic_instance_type_node compr_type = find_instance_type_from ( tn ) ; // #1647 tn = IEnumerable<T>
2019-06-16 23:44:32 +03:00
if ( compr_type = = null )
{
2020-06-15 10:38:41 +03:00
compiled_type_node bbt = null ; // SSM 14/06/20 - это для #1647 IGrouping<t1, byte>: IEnumerable<byte>
foreach ( type_node tn1 in ImplementingInterfaces )
{
var bt = tn1 as compiled_type_node ;
if ( bt ! = null & & bt . original_generic = = tn )
{
bbt = bt ; // #1647 bbt = IEnumerable<byte>
break ;
}
}
compiled_function_node cfn = orig_node as compiled_function_node ; // #1647 orig_node = cfn = IEnumerator<TElement> GetEnumerator()
2019-06-16 23:44:32 +03:00
if ( cfn = = null )
{
return orig_node ;
}
2020-06-15 10:38:41 +03:00
compiled_type_node cct = tn as compiled_type_node ; // cct = IEnumerable<T>
if ( bbt ! = null ) // #1647
cct = orig_member . comperehensive_type as compiled_type_node ;
2019-06-16 23:44:32 +03:00
type_node inst_type = this ;
2020-06-15 10:38:41 +03:00
// До этого цикла проверить bbt - если оно не null, то в роли inst_type как раз и надо брать bbt!!!
if ( bbt = = null )
do
{
inst_type = inst_type . base_type ;
}
while ( inst_type . semantic_node_type ! = semantic_node_type . compiled_type_node | |
( inst_type ! = cct & & inst_type . original_generic ! = cct ) ) ;
else inst_type = bbt ; // #1647
2019-06-16 23:44:32 +03:00
2020-06-15 10:38:41 +03:00
MethodInfo [ ] meths = cct . _compiled_type . GetMethods ( BindingFlags . Public | BindingFlags . NonPublic |
2019-06-16 23:44:32 +03:00
BindingFlags . Static | BindingFlags . Instance ) ;
2020-06-15 10:38:41 +03:00
int num = System . Array . IndexOf ( meths , cfn . method_info ) ;
2019-06-16 23:44:32 +03:00
MethodInfo mi = ( ( compiled_type_node ) inst_type ) . _compiled_type . GetMethods ( BindingFlags . Public | BindingFlags . NonPublic |
2020-06-15 10:38:41 +03:00
BindingFlags . Static | BindingFlags . Instance ) [ num ] ;
2019-06-16 23:44:32 +03:00
return compiled_function_node . get_compiled_method ( mi ) ;
}
else
return compr_type . ConvertMember ( orig_node ) ;
}
else
return orig_node ;
}
2020-06-15 10:38:41 +03:00
2019-06-16 23:44:32 +03:00
SemanticTree . ILocated orig_loc = orig_node as SemanticTree . ILocated ;
location loc = ( orig_loc = = null ) ? null : ( orig_loc . Location as location ) ;
switch ( orig_node . general_node_type )
{
case general_node_type . constant_definition :
constant_definition_node orig_cdn = orig_node as constant_definition_node ;
rez_node = new class_constant_definition (
orig_cdn . name , orig_cdn . const_value ,
loc , this , orig_member . field_access_level ) ;
break ;
case general_node_type . variable_node :
var_definition_node orig_cf = ( var_definition_node ) ( orig_node ) ;
rez_node = new class_field ( orig_cf . name ,
generic_convertions . determine_type ( orig_cf . type , _instance_params , false ) ,
this , orig_member . polymorphic_state ,
orig_member . field_access_level , loc ) ;
break ;
case general_node_type . property_node :
property_node orig_pn = ( property_node ) ( orig_node ) ;
rez_node = make_property ( orig_pn , loc ) ;
break ;
case general_node_type . function_node :
function_node orig_fn = ( function_node ) ( orig_node ) ;
rez_node = make_method ( orig_fn , loc ) ;
break ;
case general_node_type . event_node :
//(ssyy) Н е знаю, что тут делать
event_node orig_event = ( event_node ) orig_node ;
rez_node = make_event ( orig_event , loc ) ;
break ;
default :
throw new CompilerInternalError ( "Unexpected definition_node." ) ;
}
/ * if ( orig_node is class_field cf )
{
if ( cf . type . name = = "T1" )
orig_node = orig_node ;
else AddMember ( orig_node , rez_node ) ;
}
else * /
AddMember ( orig_node , rez_node ) ;
}
return rez_node ;
}
public List < SymbolInfo > ConvertSymbolInfo ( List < SymbolInfo > start )
{
List < SymbolInfo > rez_start = null ;
SymbolInfo rez_si = null ;
if ( start ! = null )
{
foreach ( SymbolInfo si in start )
{
2020-05-24 21:23:46 +03:00
if ( si . sym_info = = null )
{
if ( rez_start = = null )
rez_start = new List < SymbolInfo > ( ) ;
rez_start . Add ( si ) ;
continue ;
}
2019-06-21 08:24:10 +03:00
// Бурмистров Артем 13.06.19 begin
2019-06-16 23:44:32 +03:00
// Поправил странное поведение для локальных переменных, у которых не generic тип
// Исправление для #1993
2019-06-21 08:24:10 +03:00
if ( si . sym_info is /*var_definition_node*/ local_block_variable vdn & & ! vdn . type . is_generic_parameter )
2019-06-16 23:44:32 +03:00
{
2019-06-13 23:43:54 +03:00
rez_si = si ;
2019-06-16 23:44:32 +03:00
}
2019-06-13 23:43:54 +03:00
else
{
definition_node dnode = ConvertMember ( si . sym_info ) ;
rez_si = new SymbolInfo ( dnode , si . access_level , si . symbol_kind ) ;
rez_si . scope = si . scope ;
2019-06-16 23:44:32 +03:00
}
// aab 13.06.19 end
//Дополняем список SymbolInfo преобразованным значением
if ( rez_start = = null )
{
rez_start = new List < SymbolInfo > ( ) ;
rez_start . Add ( rez_si ) ;
}
else
{
rez_start . Add ( rez_si ) ;
}
}
}
return rez_start ;
}
public override List < SymbolInfo > find ( string name , bool no_search_in_extension_methods = false )
{
List < SymbolInfo > si = _original_generic . find ( name ) ;
return ConvertSymbolInfo ( si ) ; //delete
}
public override List < SymbolInfo > find_in_type ( string name , bool no_search_in_extension_methods = false )
{
List < SymbolInfo > sil = _original_generic . find_in_type ( name ) ;
sil = ConvertSymbolInfo ( sil ) ;
return sil ;
}
public override List < SymbolInfo > find_in_type ( string name , SymbolTable . Scope CurrentScope , type_node orig_generic_or_null = null , bool no_search_in_extension_methods = false )
{
//var or = generic_convertions.determine_type(_original_generic,this.instance_params,false); // циклится
List < SymbolInfo > sil = null ;
/ * var ctn = base_type as compiled_type_node ;
if ( ctn ! = null & & ctn . is_generic_type_instance )
{
sil = ctn . find_in_type ( name , CurrentScope , no_search_in_extension_methods ) ;
var sil1 = _original_generic . find_in_type ( name , CurrentScope ) ;
sil1 = ConvertSymbolInfo ( sil1 ) ;
if ( sil ! = null )
sil1 . InsertRange ( 0 , sil ) ;
return sil1 ;
} * /
#if DEBUG
/ * if ( name = = "XYZW" )
{
var y = name ;
} * /
#endif
sil = _original_generic . find_in_type ( name , CurrentScope , _original_generic ) ; // передача _original_generic - это костыль для устранения б а г а #1674.
// параметр _original_generic - фиктивный: если он не null (это только здесь), то в common_type_node выполнение в одном месте идет по другой ветке
sil = ConvertSymbolInfo ( sil ) ;
return sil ;
}
private void conform_basic_function ( string name , int base_func_num )
{
2021-04-05 16:33:16 +03:00
SymbolInfo si1 = null ;
List < SymbolInfo > sil = _original_generic . find_in_type ( name , true ) ;
foreach ( SymbolInfo si in sil )
if ( si . sym_info is function_node & & ! ( si . sym_info as function_node ) . is_extension_method )
{
si1 = si ;
break ;
}
2019-06-16 23:44:32 +03:00
AddMember ( si1 . sym_info , temp_names [ base_func_num ] . sym_info ) ;
}
public void conform_basic_functions ( )
{
2024-11-19 13:56:47 +03:00
// Вообще говоря, надо эти операции добавлять только если пользовательские не определены
if ( BaseFullName ! = "PABCSystem.NewSet`1" ) // SSM 19/11/24 - для типа встроенных множеств где эти операции переопределены
{
conform_basic_function ( StringConstants . assign_name , 0 ) ;
conform_basic_function ( StringConstants . eq_name , 1 ) ;
conform_basic_function ( StringConstants . noteq_name , 2 ) ;
}
2019-06-16 23:44:32 +03:00
temp_names = null ;
}
public virtual List < function_node > all_methods
{
get
{
return null ;
}
}
public virtual List < type_node > all_field_types
{
get
{
return null ;
}
}
public override generic_instance_type_node base_generic_instance
{
get
{
return this ;
}
}
public override bool depended_from_indefinite
{
get
{
if ( _instance_params = = null )
{
return false ;
}
foreach ( type_node tn in _instance_params )
{
if ( tn . depended_from_indefinite )
{
return true ;
}
}
return false ;
}
}
}
//Класс, характеризующий одну псевдоинстанцию generic-типа
public class compiled_generic_instance_type_node : generic_instance_type_node , SemanticTree . ICompiledGenericTypeInstance
{
public compiled_type_node compiled_original_generic
{
get
{
return _original_generic as compiled_type_node ;
}
}
public override string BaseFullName
{
get
{
return compiled_original_generic . BaseFullName ;
}
}
public compiled_generic_instance_type_node ( compiled_type_node generic_definition ,
List < type_node > param_types ,
type_node base_type , string name ,
SemanticTree . type_access_level type_access_level ,
common_namespace_node comprehensive_namespace ,
location loc )
:
base ( generic_definition , param_types , base_type , name , type_access_level , comprehensive_namespace ,
loc )
{
}
private List < function_node > _all_methods = null ;
public override List < function_node > all_methods
{
get
{
if ( _all_methods ! = null ) return _all_methods ;
_all_methods = new List < function_node > ( ) ;
System . Reflection . MemberInfo [ ] orig_members = compiled_original_generic . compiled_type . GetMembers ( ) ;
foreach ( System . Reflection . MemberInfo mi in orig_members )
{
if ( mi . MemberType = = System . Reflection . MemberTypes . Method )
{
compiled_function_node cmeth = compiled_function_node . get_compiled_method ( ( System . Reflection . MethodInfo ) mi ) ;
_all_methods . Add ( ConvertMember ( cmeth ) as function_node ) ;
}
}
return _all_methods ;
}
}
private List < type_node > _all_field_types = null ;
public override List < type_node > all_field_types
{
get
{
if ( _all_field_types ! = null ) return _all_field_types ;
System . Reflection . FieldInfo [ ] fields = compiled_original_generic . compiled_type . GetFields ( ) ;
_all_field_types = new List < type_node > ( ) ;
foreach ( System . Reflection . FieldInfo fi in fields )
{
if ( ! fi . IsStatic )
{
_all_field_types . Add ( generic_convertions . determine_type ( compiled_type_node . get_type_node ( fi . FieldType ) , instance_params , false ) ) ;
}
}
return _all_field_types ;
}
}
}
//Класс, характеризующий одну псевдоинстанцию generic-типа
public class common_generic_instance_type_node : generic_instance_type_node , SemanticTree . ICommonGenericTypeInstance
{
public common_type_node common_original_generic
{
get
{
return _original_generic as common_type_node ;
}
}
public common_generic_instance_type_node ( common_type_node generic_definition ,
List < type_node > param_types ,
type_node base_type , string name ,
SemanticTree . type_access_level type_access_level ,
common_namespace_node comprehensive_namespace ,
location loc )
:
base ( generic_definition , param_types , base_type , name , type_access_level , comprehensive_namespace ,
loc )
{
}
private List < function_node > _all_methods = null ;
public override List < function_node > all_methods
{
get
{
if ( _all_methods ! = null ) return _all_methods ;
common_method_node_list orig_meths = common_original_generic . methods ;
_all_methods = new List < function_node > ( orig_meths . Count ) ;
foreach ( common_method_node cnode in orig_meths )
{
_all_methods . Add ( ConvertMember ( cnode ) as function_node ) ;
}
return _all_methods ;
}
}
private List < type_node > _all_field_types = null ;
public override List < type_node > all_field_types
{
get
{
if ( _all_field_types ! = null ) return _all_field_types ;
class_field_list orig_fields = common_original_generic . fields ;
_all_field_types = new List < type_node > ( orig_fields . Count ) ;
foreach ( class_field cf in orig_fields )
{
_all_field_types . Add ( generic_convertions . determine_type ( cf . type , this . instance_params , false ) ) ;
}
return _all_field_types ;
}
}
}
//Класс для запрещения создания в одной области видимости generic-классов с одинаковым именем.
public class generic_indicator : definition_node , SemanticTree . ILocated
{
private common_type_node _generic ;
public common_type_node generic
{
get
{
return _generic ;
}
}
public generic_indicator ( common_type_node generic_type )
{
_generic = generic_type ;
}
public SemanticTree . ILocation Location
{
get
{
return _generic . Location ;
}
}
public location loc
{
get
{
return _generic . loc ;
}
}
public override general_node_type general_node_type
{
get
{
return TreeRealization . general_node_type . generic_indicator ;
}
}
public override semantic_node_type semantic_node_type
{
get
{
return semantic_node_type . generic_indicator ;
}
}
}
public class GenericParameterAbilities
{
public bool useful_for_pointers = false ;
public bool useful_for_binary_files = false ;
public bool useful_for_typed_files = false ;
}
public class generic_method_instance_node : common_method_node , SemanticTree . IGenericFunctionInstance
{
protected List < type_node > _instance_params ;
public List < type_node > instance_params
{
get
{
return _instance_params ;
}
}
protected List < SemanticTree . ITypeNode > _generic_parameters = null ;
public List < SemanticTree . ITypeNode > generic_parameters
{
get
{
if ( _generic_parameters = = null )
{
_generic_parameters = new List < SemanticTree . ITypeNode > ( ) ;
foreach ( type_node t in _instance_params )
{
_generic_parameters . Add ( t ) ;
}
}
return _generic_parameters ;
}
}
protected function_node _original_function ;
SemanticTree . IFunctionNode SemanticTree . IGenericFunctionInstance . original_function
{
get
{
return _original_function ;
}
}
public override function_node original_function
{
get
{
return _original_function ;
}
}
2021-11-21 16:37:34 +03:00
public override bool is_extension_method
{
get
{
return _original_function . is_extension_method ;
}
}
2019-06-16 23:44:32 +03:00
public override bool is_generic_function_instance
{
get
{
return true ;
}
}
public override SemanticTree . ITypeNode comperehensive_type
{
get
{
return ( _original_function as SemanticTree . IClassMemberNode ) . comperehensive_type ;
}
}
public generic_method_instance_node ( function_node original_generic_function , List < type_node > instance_parameters )
: base (
generic_convertions . MakePseudoInstanceName ( original_generic_function . name , instance_parameters , false ) ,
null , null )
{
_original_function = original_generic_function ;
_instance_params = instance_parameters ;
2020-06-12 16:38:46 +03:00
List < type_node > orig_gen_params =
original_generic_function . get_generic_params_list ( ) ; // #2068 попытка
2019-06-16 23:44:32 +03:00
this . field_access_level = original_generic_function . field_access_level ;
this . is_final = original_generic_function . is_final ;
this . is_overload = true ;
this . polymorphic_state = original_generic_function . polymorphic_state ;
2020-06-12 16:38:46 +03:00
this . return_value_type = generic_convertions . determine_type ( original_generic_function . return_value_type , instance_parameters , true , orig_gen_params ) ;
2019-06-16 23:44:32 +03:00
foreach ( parameter par in original_generic_function . parameters )
{
common_parameter cpar = new common_parameter ( par . name ,
2020-06-12 16:38:46 +03:00
generic_convertions . determine_type ( par . type , _instance_params , true , orig_gen_params ) ,
2019-06-16 23:44:32 +03:00
par . parameter_type , this ,
( par . parameter_type = = SemanticTree . parameter_type . var ) ? concrete_parameter_type . cpt_var : concrete_parameter_type . cpt_none ,
par . default_value , null ) ;
cpar . inital_value = par . inital_value ;
cpar . default_value = par . default_value ;
cpar . intrenal_is_params = par . is_params ;
cpar . is_ret_value = par . is_ret_value ;
cpar . is_special_name = par . is_special_name ;
parameters . AddElement ( cpar ) ;
}
}
public override List < type_node > get_generic_params_list ( )
{
return instance_params ;
}
}
public class generic_namespace_function_instance_node : common_namespace_function_node , SemanticTree . IGenericFunctionInstance
{
protected List < type_node > _instance_params ;
public List < type_node > instance_params
{
get
{
return _instance_params ;
}
}
protected List < SemanticTree . ITypeNode > _generic_parameters = null ;
public List < SemanticTree . ITypeNode > generic_parameters
{
get
{
if ( _generic_parameters = = null )
{
_generic_parameters = new List < SemanticTree . ITypeNode > ( ) ;
foreach ( type_node t in _instance_params )
{
_generic_parameters . Add ( t ) ;
}
}
return _generic_parameters ;
}
}
protected common_namespace_function_node _original_function ;
SemanticTree . IFunctionNode SemanticTree . IGenericFunctionInstance . original_function
{
get
{
return _original_function ;
}
}
public override function_node original_function
{
get
{
return _original_function ;
}
}
public override bool is_generic_function_instance
{
get
{
return true ;
}
}
public generic_namespace_function_instance_node ( common_namespace_function_node original_generic_function , List < type_node > instance_parameters )
: base (
generic_convertions . MakePseudoInstanceName ( original_generic_function . name , instance_parameters , false ) ,
null , original_generic_function . namespace_node , null )
{
_original_function = original_generic_function ;
_instance_params = instance_parameters ;
2020-06-12 16:38:46 +03:00
List < type_node > orig_gen_params =
original_generic_function . generic_params . Select ( p = > p as type_node ) . ToList ( ) ; // #2068 попытка
2019-06-16 23:44:32 +03:00
this . field_access_level = original_generic_function . field_access_level ;
this . is_final = original_generic_function . is_final ;
this . is_overload = true ;
this . polymorphic_state = original_generic_function . polymorphic_state ;
2020-06-12 16:38:46 +03:00
this . return_value_type = generic_convertions . determine_type ( original_generic_function . return_value_type , instance_parameters , true , orig_gen_params ) ;
2019-06-16 23:44:32 +03:00
foreach ( parameter par in original_generic_function . parameters )
{
common_parameter cpar = new common_parameter ( par . name ,
2020-06-12 16:38:46 +03:00
generic_convertions . determine_type ( par . type , _instance_params , true , orig_gen_params ) ,
2019-06-16 23:44:32 +03:00
par . parameter_type , this ,
( par . parameter_type = = SemanticTree . parameter_type . var ) ? concrete_parameter_type . cpt_var : concrete_parameter_type . cpt_none ,
par . default_value , null ) ;
cpar . inital_value = par . inital_value ;
cpar . default_value = par . default_value ;
2023-11-01 15:48:08 +03:00
if ( cpar . default_value is default_operator_node )
( cpar . default_value as default_operator_node ) . type = generic_convertions . determine_type ( cpar . default_value . type , _instance_params , true , orig_gen_params ) ;
else if ( cpar . default_value is default_operator_node_as_constant )
{
( cpar . default_value as default_operator_node_as_constant ) . type = generic_convertions . determine_type ( cpar . default_value . type , _instance_params , true , orig_gen_params ) ;
( cpar . default_value as default_operator_node_as_constant ) . default_operator . type = ( cpar . default_value as default_operator_node_as_constant ) . type ;
}
2019-06-16 23:44:32 +03:00
cpar . intrenal_is_params = par . is_params ;
cpar . is_ret_value = par . is_ret_value ;
cpar . is_special_name = par . is_special_name ;
parameters . AddElement ( cpar ) ;
}
}
public override List < type_node > get_generic_params_list ( )
{
return instance_params ;
}
}
public class default_operator_node : expression_node , SemanticTree . IDefaultOperatorNode
{
public default_operator_node ( type_node tn , location loc )
: base ( tn , loc )
{
}
public override semantic_node_type semantic_node_type
{
get
{
return semantic_node_type . default_operator ;
}
}
/// <summary>
/// Метод для обхода дерева посетителем.
/// </summary>
/// <param name="visitor">Класс - посетитель дерева.</param>
public override void visit ( SemanticTree . ISemanticVisitor visitor )
{
visitor . visit ( this ) ;
}
}
}