2019-07-28 23:53:15 +03:00
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
2015-06-01 22:15:17 +03:00
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
2015-05-14 22:35:07 +03:00
using PascalABCCompiler.SemanticTree ;
using System ;
using System.Reflection ;
using System.Reflection.Emit ;
using System.Collections ;
2025-07-03 20:39:09 +03:00
using System.Linq ;
2025-10-09 18:40:11 +03:00
using System.Collections.Generic ;
2015-05-14 22:35:07 +03:00
namespace PascalABCCompiler.NETGenerator {
public class HandlerFactory
{
public static ConstructorInfo ci ;
public static Type [ ] parameters ;
public static Type eventHandler ;
static HandlerFactory ( )
{
eventHandler = typeof ( System . EventHandler ) ;
parameters = new Type [ 2 ] { typeof ( object ) , typeof ( IntPtr ) } ;
ci = eventHandler . GetConstructor ( parameters ) ;
}
}
public abstract class NodeInfo
{
}
public static class OperatorsNameConvertor
{
private static System . Collections . Generic . Dictionary < string , string > names =
new System . Collections . Generic . Dictionary < string , string > ( 32 ) ;
static OperatorsNameConvertor ( )
{
2024-05-04 20:21:50 +03:00
names [ StringConstants . plus_name ] = "op_Addition" ;
names [ StringConstants . minus_name ] = "op_Subtraction" ;
names [ StringConstants . mul_name ] = "op_Multiply" ;
names [ StringConstants . div_name ] = "op_Division" ;
names [ StringConstants . and_name ] = "op_BitwiseAnd" ;
names [ StringConstants . or_name ] = "op_BitwiseOr" ;
names [ StringConstants . eq_name ] = "op_Equality" ;
names [ StringConstants . gr_name ] = "op_GreaterThan" ;
names [ StringConstants . greq_name ] = "op_GreaterThanOrEqual" ;
names [ StringConstants . sm_name ] = "op_LessThan" ;
names [ StringConstants . smeq_name ] = "op_LessThanOrEqual" ;
names [ StringConstants . mod_name ] = "op_Modulus" ;
names [ StringConstants . not_name ] = "op_LogicalNot" ;
names [ StringConstants . noteq_name ] = "op_Inequality" ;
2015-05-14 22:35:07 +03:00
//op_Implicit
//op_Explicit
2024-05-04 20:21:50 +03:00
names [ StringConstants . xor_name ] = "op_ExclusiveOr" ;
names [ StringConstants . and_name ] = "op_LogicalAnd" ;
names [ StringConstants . or_name ] = "op_LogicalOr" ;
names [ StringConstants . assign_name ] = "op_Assign" ;
names [ StringConstants . shl_name ] = "op_LeftShift" ;
names [ StringConstants . shr_name ] = "op_RightShift" ;
//names["op_SignedRightShift"]=StringConstants.shr_name;
names [ StringConstants . shr_name ] = "op_UnsignedRightShift" ;
names [ StringConstants . eq_name ] = "op_Equality" ;
names [ StringConstants . multassign_name ] = "op_MultiplicationAssignment" ;
names [ StringConstants . minusassign_name ] = "op_SubtractionAssignment" ;
//names[StringConstants.minusassign_name]="op_ExclusiveOrAssignment";
2015-05-14 22:35:07 +03:00
//op_LeftShiftAssignment
//op_ModulusAssignment
2024-05-04 20:21:50 +03:00
names [ StringConstants . plusassign_name ] = "op_AdditionAssignment" ;
2015-05-14 22:35:07 +03:00
//op_BitwiseAndAssignment
//op_BitwiseOrAssignment
//op_Comma
2024-05-04 20:21:50 +03:00
names [ StringConstants . divassign_name ] = "op_DivisionAssignment" ;
2015-05-14 22:35:07 +03:00
//op_Decrement
//op_Increment
2024-05-04 20:21:50 +03:00
//names[StringConstants.minus_name] ="op_UnaryNegation";
2015-05-14 22:35:07 +03:00
//op_UnaryPlus
//op_OnesComplement
}
public static string convert_name ( string name )
{
string ret ;
if ( names . TryGetValue ( name , out ret ) )
{
return ret ;
}
return null ;
}
}
public class TypeInfo : NodeInfo
{
private Type _tp ;
private bool _is_arr = false ; //флаг массив ли это
public bool is_set = false ;
public bool is_typed_file = false ;
public bool is_text_file = false ;
public int arr_len ;
public ConstructorInfo def_cnstr ; //конструктор по умолчанию типа (если он есть)
public FieldInfo arr_fld ; //ссылка на поле массива в оболочке над массивом
public MethodInfo clone_meth ; //метод копирования в массиве
public MethodInfo init_meth ; //метод инициализации
public MethodInfo assign_meth ; //метод присваивания значений размерных типов
public ConstructorBuilder static_cnstr ;
public MethodBuilder fix_meth ;
//временно для событий
public MethodBuilder handl_meth ;
public bool has_events = false ; //есть ли в типе события
//public Hashtable fields=new Hashtable();//временно
public MethodInfo enumerator_meth ;
public TypeInfo ( ) { }
public TypeInfo ( Type tp )
{
_tp = tp ;
}
public Type tp {
get {
return _tp ;
}
set {
_tp = value ;
}
}
public bool is_arr {
get
{
return _is_arr ;
}
set
{
_is_arr = value ;
}
}
}
public class EvntInfo : NodeInfo
{
private EventBuilder _ei ;
public EvntInfo ( EventBuilder ei )
{
_ei = ei ;
}
public EventBuilder ei
{
get {
return _ei ;
}
set {
_ei = value ;
}
}
}
public class FldInfo : NodeInfo {
private FieldInfo _fi ;
public FldInfo ( ) { }
public FldInfo ( FieldInfo fi )
{
_fi = fi ;
}
public FieldInfo fi
{
get {
return _fi ;
}
set {
_fi = value ;
}
}
public virtual Type field_type
{
get
{
return fi . FieldType ;
}
}
}
public class GenericFldInfo : FldInfo
{
private Type _field_type ;
2019-01-26 11:43:27 +03:00
public FieldInfo prev_fi ; // передаю чтобы на третьем этапе в NegGenerator.cs (примерно 1586) можно было сконструировать правильный тип. Костыль для #1632
2015-05-14 22:35:07 +03:00
public override Type field_type
{
get
{
return _field_type ;
}
}
2019-01-26 11:43:27 +03:00
public GenericFldInfo ( FieldInfo fi , Type field_type , FieldInfo prev_fi )
2015-05-14 22:35:07 +03:00
: base ( fi )
{
_field_type = field_type ;
2019-01-26 11:43:27 +03:00
this . prev_fi = prev_fi ;
2015-05-14 22:35:07 +03:00
}
}
public class PropInfo : NodeInfo {
private PropertyInfo _prop ;
public PropInfo ( PropertyInfo _prop )
{
this . _prop = _prop ;
}
public PropertyInfo prop
{
get
{
return _prop ;
}
}
}
public class ConstrInfo : NodeInfo {
private ConstructorInfo _ci ;
public ConstrInfo ( ) { }
public ConstrInfo ( ConstructorInfo ci )
{
_ci = ci ;
}
public ConstructorInfo ci {
get {
return _ci ;
}
set {
_ci = value ;
}
}
}
public class MethInfo : NodeInfo {
private MethodInfo _mi ;
//private LocalBuilder _ret_val;//переменная для возвр. значения //(ssyy) Нет пользы
private LocalBuilder _frame ; //перем, хранящая запись активации
private MethInfo _up_meth ; //ссылка на верхний метод
private Frame _disp ; //запись активации
private bool _nested = false ; //является ли вложенной или содержащей вложенные
private int _num_scope ; //номер области видимости
private ConstructorInfo _cnstr ;
private bool _stand = false ; //для станд. процедур, у которого нет тела в семант. дереве ("New","Dispose")
private bool _is_in_class = false ; //является ли он процедурой, влож. в метод
private bool _is_ptr_ret_type = false ;
public MethInfo ( ) { }
public MethInfo ( MethodInfo mi )
{
_mi = mi ;
}
public bool is_ptr_ret_type
{
get
{
return _is_ptr_ret_type ;
}
set
{
_is_ptr_ret_type = value ;
}
}
public bool is_in_class
{
get
{
return _is_in_class ;
}
set
{
_is_in_class = value ;
}
}
public bool stand
{
get
{
return _stand ;
}
set
{
_stand = value ;
}
}
public MethodInfo mi {
get {
return _mi ;
}
set {
_mi = value ;
}
}
public MethInfo up_meth {
get {
return _up_meth ;
}
set {
_up_meth = value ;
}
}
public ConstructorInfo cnstr {
get {
return _cnstr ;
}
set {
_cnstr = value ;
}
}
public int num_scope {
get {
return _num_scope ;
}
set {
_num_scope = value ;
}
}
public Frame disp {
get {
return _disp ;
}
set {
_disp = value ;
}
}
public bool nested {
get {
return _nested ;
}
set {
_nested = value ;
}
}
public LocalBuilder frame {
get {
return _frame ;
}
set {
_frame = value ;
}
}
//(ssyy) Нет пользы
/ * public LocalBuilder ret_val {
get {
return _ret_val ;
}
set {
_ret_val = value ;
}
} * /
}
public enum VarKind
{
vkLocal , //локальная
vkNonLocal , //нелокальная(содержится в процедуре)
vkGlobal //глобальная переменная (основная программа)
}
public class VarInfo : NodeInfo {
private LocalBuilder _lb ; //билдер для переменной
private FieldBuilder _fb ; //а вдруг переменная нелокальная
private VarKind _kind ; //тип переменной
private MethInfo _meth ; //метод, в котором определена переменная
public VarInfo ( ) { }
public VarInfo ( LocalBuilder lb )
{
_lb = lb ;
_kind = VarKind . vkLocal ;
}
public MethInfo meth {
get {
return _meth ;
}
set {
_meth = value ;
}
}
public FieldBuilder fb {
get {
return _fb ;
}
set {
_fb = value ;
}
}
public VarKind kind {
get {
return _kind ;
}
set {
_kind = value ;
}
}
public LocalBuilder lb {
get {
return _lb ;
}
set {
_lb = value ;
}
}
}
public enum ParamKind {
pkNone ,
pkGlobal
}
public class ParamInfo : NodeInfo {
private ParameterBuilder _pb ; //билдер для параметра
private FieldBuilder _fb ; //вдруг параметр нелокальный
private ParamKind _kind = ParamKind . pkNone ;
private MethInfo _meth ; //метод, в котор. описан параметр
public ParamInfo ( ) { }
public ParamInfo ( ParameterBuilder pb )
{
_pb = pb ;
}
public MethInfo meth {
get {
return _meth ;
}
set {
_meth = value ;
}
}
public ParamKind kind {
get {
return _kind ;
}
set {
_kind = value ;
}
}
public FieldBuilder fb {
get {
return _fb ;
}
set {
_fb = value ;
}
}
public ParameterBuilder pb {
get {
return _pb ;
}
set {
_pb = value ;
}
}
}
public class ConstInfo : NodeInfo {
public FieldBuilder fb ;
public ConstInfo ( FieldBuilder fb )
{
this . fb = fb ;
}
}
//Структура для записи активации процедуры
public class Frame {
public TypeBuilder tb ; //класс - запись активации
public FieldBuilder parent ; //поле-ссылка на род. запись активации
public ConstructorBuilder cb ; //конструктор записи активации
public MethodBuilder mb ;
public Frame ( ) { }
}
public class Helper {
2019-02-01 15:04:07 +03:00
public Hashtable defs = new Hashtable ( ) ;
2025-10-09 18:40:11 +03:00
private HashSet < ICommonTypeNode > processing_types = new HashSet < ICommonTypeNode > ( ) ;
2015-05-14 22:35:07 +03:00
private MethodInfo arr_mi = null ;
2025-10-09 18:40:11 +03:00
private Dictionary < ITypeNode , Type > pas_defs = new Dictionary < ITypeNode , Type > ( ) ;
private Dictionary < IExpressionNode , LocalBuilder > memoized_exprs = new Dictionary < IExpressionNode , LocalBuilder > ( ) ;
private Dictionary < TypeBuilder , MethodBuilder > dummy_methods = new Dictionary < TypeBuilder , MethodBuilder > ( ) ;
2018-10-02 23:11:07 +03:00
2015-05-14 22:35:07 +03:00
public Helper ( ) { }
2021-11-07 13:39:36 +03:00
public void AddDummyMethod ( TypeBuilder tb , MethodBuilder mb )
{
dummy_methods [ tb ] = mb ;
}
2025-10-09 18:40:11 +03:00
public MethodBuilder GetDummyMethod ( TypeBuilder tb )
2021-11-07 13:39:36 +03:00
{
2025-10-09 18:40:11 +03:00
return dummy_methods [ tb ] ;
2021-11-07 13:39:36 +03:00
}
2015-05-14 22:35:07 +03:00
public void AddPascalTypeReference ( ITypeNode tn , Type t )
{
pas_defs [ tn ] = t ;
}
public Type GetPascalTypeReference ( ITypeNode tn )
{
2025-10-09 18:40:11 +03:00
pas_defs . TryGetValue ( tn , out var result ) ;
return result ;
2015-05-14 22:35:07 +03:00
}
public ConstInfo AddConstant ( IConstantDefinitionNode cnst , FieldBuilder fb )
{
ConstInfo ci = new ConstInfo ( fb ) ;
defs [ cnst ] = ci ;
return ci ;
}
//добавление локальной переменной
public VarInfo AddVariable ( IVAriableDefinitionNode var , LocalBuilder lb )
{
VarInfo vi = new VarInfo ( lb ) ;
defs [ var ] = vi ;
return vi ;
}
//ssyy
public Label GetLabel ( ILabelNode label , ILGenerator il )
{
if ( defs . ContainsKey ( label ) )
{
return ( Label ) ( defs [ label ] ) ;
}
Label lab = il . DefineLabel ( ) ;
defs . Add ( label , lab ) ;
return lab ;
}
//\ssyy
//получение локальной переменной
public VarInfo GetVariable ( IVAriableDefinitionNode var )
{
return ( VarInfo ) defs [ var ] ;
}
//добавление глоб. переменной
public VarInfo AddGlobalVariable ( IVAriableDefinitionNode var , FieldBuilder fb )
{
VarInfo vi = new VarInfo ( ) ;
defs [ var ] = vi ;
vi . fb = fb ;
vi . kind = VarKind . vkGlobal ;
return vi ;
}
public EvntInfo AddEvent ( IEventNode ev , EventBuilder eb )
{
EvntInfo ei = new EvntInfo ( eb ) ;
defs [ ev ] = ei ;
return ei ;
}
public EvntInfo GetEvent ( IEventNode ev )
{
return ( EvntInfo ) defs [ ev ] ;
}
//добавление нелок. переменной
public VarInfo AddNonLocalVariable ( IVAriableDefinitionNode var , FieldBuilder fb )
{
VarInfo vi = new VarInfo ( ) ;
defs [ var ] = vi ;
vi . fb = fb ;
vi . kind = VarKind . vkNonLocal ;
return vi ;
}
//добавление функции (метода)
public MethInfo AddMethod ( IFunctionNode func , MethodInfo mi )
{
MethInfo m = new MethInfo ( mi ) ;
defs [ func ] = m ;
return m ;
}
//добавление функции, вложенной в функцию
public MethInfo AddMethod ( IFunctionNode func , MethodInfo mi , MethInfo up )
{
MethInfo m = new MethInfo ( mi ) ;
m . up_meth = up ;
defs [ func ] = m ;
return m ;
}
//получение метода
public MethInfo GetMethod ( IFunctionNode func )
{
return ( MethInfo ) defs [ func ] ;
}
//добавление конструктора
public MethInfo AddConstructor ( IFunctionNode func , ConstructorInfo ci )
{
//ConstrInfo m = new ConstrInfo(ci);
MethInfo mi = new MethInfo ( ) ;
mi . cnstr = ci ;
defs [ func ] = mi ;
return mi ;
}
public PropInfo AddProperty ( IPropertyNode prop , PropertyInfo pi )
{
PropInfo pi2 = new PropInfo ( pi ) ;
defs [ prop ] = pi2 ;
return pi2 ;
}
public PropInfo GetProperty ( IPropertyNode prop )
{
return ( PropInfo ) defs [ prop ] ;
}
//получение конструктора
public MethInfo GetConstructor ( IFunctionNode func )
{
MethInfo mi = ( MethInfo ) defs [ func ] ;
return mi ;
}
public ConstInfo GetConstant ( IConstantDefinitionNode cnst )
{
ConstInfo ci = ( ConstInfo ) defs [ cnst ] ;
return ci ;
}
public object GetConstantForExpression ( IExpressionNode expr )
{
2021-04-20 08:04:33 +03:00
if ( expr is PascalABCCompiler . TreeRealization . null_const_node ) // SSM 20/04/21
return expr ;
2015-05-14 22:35:07 +03:00
if ( expr is IConstantNode )
return ( expr as IConstantNode ) . value ;
return null ;
}
//добавление параметра
public ParamInfo AddParameter ( IParameterNode p , ParameterBuilder pb )
{
ParamInfo pi = new ParamInfo ( pb ) ;
defs [ p ] = pi ;
return pi ;
}
//добавление нелок. параметра
public ParamInfo AddGlobalParameter ( IParameterNode p , FieldBuilder fb )
{
ParamInfo pi = new ParamInfo ( ) ;
pi . kind = ParamKind . pkGlobal ;
pi . fb = fb ;
defs [ p ] = pi ;
return pi ;
}
//получение параметра
public ParamInfo GetParameter ( IParameterNode p )
{
return ( ParamInfo ) defs [ p ] ;
}
//добавление поля
public FldInfo AddField ( ICommonClassFieldNode f , FieldInfo fb )
{
FldInfo fi = new FldInfo ( fb ) ;
2019-01-23 20:14:45 +03:00
#if DEBUG
2019-02-12 10:19:33 +03:00
/ * if ( f . name = = "XYZW" )
2019-01-11 08:32:45 +03:00
{
var y = f . GetHashCode ( ) ;
2019-02-12 10:19:33 +03:00
} * /
2019-01-23 20:14:45 +03:00
#endif
defs [ f ] = fi ;
return fi ;
2015-05-14 22:35:07 +03:00
}
2019-01-26 11:43:27 +03:00
public FldInfo AddGenericField ( ICommonClassFieldNode f , FieldInfo fb , Type field_type , FieldInfo prev_fi )
2015-05-14 22:35:07 +03:00
{
2019-01-26 11:43:27 +03:00
FldInfo fi = new GenericFldInfo ( fb , field_type , prev_fi ) ; // prev_fi - чтобы сконструировать на последнем этапе fi
2019-01-23 20:14:45 +03:00
#if DEBUG
2019-02-13 20:52:38 +03:00
/ * if ( f . name = = "XYZW" )
2019-01-11 08:32:45 +03:00
{
var y = f . GetHashCode ( ) ;
2019-02-13 20:52:38 +03:00
} * /
2019-01-23 20:14:45 +03:00
#endif
2015-05-14 22:35:07 +03:00
defs [ f ] = fi ;
return fi ;
}
//получение поля
public FldInfo GetField ( ICommonClassFieldNode f )
{
2019-01-23 20:14:45 +03:00
var r = ( FldInfo ) defs [ f ] ;
#if DEBUG
2019-02-12 10:19:33 +03:00
/ * if ( f . name = = "XYZW" )
2019-01-11 08:32:45 +03:00
{
var y = f . GetHashCode ( ) ;
2019-02-12 10:19:33 +03:00
} * /
2019-02-01 15:04:07 +03:00
#endif
#if DEBUG
/ * if ( r = = null & & f . name = = "XYZW" )
2019-01-23 20:14:45 +03:00
{
foreach ( var k in defs . Keys )
{
if ( ( k is ICommonClassFieldNode ) & & ( k as ICommonClassFieldNode ) . name = = "XYZW" )
return ( FldInfo ) defs [ k ] ;
}
2019-01-26 11:43:27 +03:00
} * /
2019-01-23 20:14:45 +03:00
#endif
return r ;
2015-05-14 22:35:07 +03:00
}
//добавление типа
public TypeInfo AddType ( ITypeNode type , TypeBuilder tb )
{
TypeInfo ti = new TypeInfo ( tb ) ;
defs [ type ] = ti ;
return ti ;
}
public TypeInfo AddEnum ( ITypeNode type , EnumBuilder emb )
{
TypeInfo ti = new TypeInfo ( emb ) ;
defs [ type ] = ti ;
return ti ;
}
public TypeInfo AddExistingType ( ITypeNode type , Type t )
{
TypeInfo ti = new TypeInfo ( t ) ;
defs [ type ] = ti ;
return ti ;
}
private IFunctionNode find_method ( ICommonTypeNode tn , string name )
{
foreach ( ICommonMethodNode cmn in tn . methods )
{
if ( string . Compare ( cmn . name , name , true ) = = 0 ) return cmn ;
}
return null ;
}
private IFunctionNode find_constructor ( ICommonTypeNode tn )
{
foreach ( ICommonMethodNode cmn in tn . methods )
{
if ( cmn . is_constructor ) return cmn ;
}
return null ;
}
private ConstructorInfo find_constructor ( Type tn )
{
foreach ( ConstructorInfo cmn in tn . GetConstructors ( ) )
{
return cmn ;
}
return null ;
}
private IFunctionNode find_constructor_with_params ( ICommonTypeNode tn )
{
foreach ( ICommonMethodNode cmn in tn . methods )
{
if ( cmn . is_constructor & & cmn . parameters . Length = = 2 ) return cmn ;
}
return null ;
}
private ConstructorInfo find_constructor_with_params ( Type t )
{
foreach ( ConstructorInfo ci in t . GetConstructors ( ) )
{
if ( ci . GetParameters ( ) . Length = = 2 )
return ci ;
}
return null ;
}
private IFunctionNode find_constructor_with_one_param ( ICommonTypeNode tn )
{
foreach ( ICommonMethodNode cmn in tn . methods )
{
if ( cmn . is_constructor & & cmn . parameters . Length = = 1 ) return cmn ;
}
return null ;
}
private ConstructorInfo find_constructor_with_one_param ( Type t )
{
foreach ( ConstructorInfo ci in t . GetConstructors ( ) )
{
if ( ci . GetParameters ( ) . Length = = 1 )
return ci ;
}
return null ;
}
2025-07-03 20:39:09 +03:00
/// <summary>
/// До вызова <c>.CreateType()</c> позволяет определить, был ли тип объявлен в коде, а не в готовой сборке.
/// Generic типы инстанцированные Pascal типами также считаются Pascal типами (пример: <c>IEnumerable<PascalType></c>)
/// </summary>
public bool IsPascalType ( Type t )
2015-05-14 22:35:07 +03:00
{
2023-01-22 12:37:37 +03:00
if ( t is TypeBuilder | | t is GenericTypeParameterBuilder | | t is EnumBuilder | | t . GetType ( ) . FullName = = "System.Reflection.Emit.TypeBuilderInstantiation" )
2015-05-14 22:35:07 +03:00
return true ;
2025-07-03 20:39:09 +03:00
if ( t . IsGenericType & & t . GetGenericArguments ( ) . Any ( IsPascalType ) )
return true ;
2019-01-31 23:27:18 +03:00
if ( t . IsArray )
2025-07-03 20:39:09 +03:00
return IsPascalType ( t . GetElementType ( ) ) ;
2015-05-14 22:35:07 +03:00
return false ;
}
public bool IsNumericType ( Type t )
{
return t = = TypeFactory . ByteType | | t = = TypeFactory . SByteType | | t = = TypeFactory . Int16Type | | t = = TypeFactory . UInt16Type
| | t = = TypeFactory . Int32Type | | t = = TypeFactory . UInt32Type | | t = = TypeFactory . Int64Type | | t = = TypeFactory . UInt64Type
| | t = = TypeFactory . SingleType | | t = = TypeFactory . DoubleType ;
}
2018-09-09 13:11:42 +03:00
public ICommonTypeNode GetTypeNodeByTypeBuilder ( TypeBuilder tb )
{
foreach ( object o in defs . Keys )
{
if ( o is ICommonTypeNode & & this . GetTypeReference ( o as ICommonTypeNode ) . tp = = tb )
return o as ICommonTypeNode ;
}
return null ;
}
2025-10-09 18:40:11 +03:00
public void SetAsProcessing ( ICommonTypeNode type )
2018-03-11 19:47:53 +03:00
{
2025-10-09 18:40:11 +03:00
processing_types . Add ( type ) ;
2018-03-11 19:47:53 +03:00
}
public bool IsProcessing ( ICommonTypeNode type )
{
2025-10-09 18:40:11 +03:00
return processing_types . Contains ( type ) ;
2018-03-11 19:47:53 +03:00
}
2018-10-02 23:11:07 +03:00
public void LinkExpressionToLocalBuilder ( IExpressionNode expr , LocalBuilder lb )
{
memoized_exprs [ expr ] = lb ;
}
public LocalBuilder GetLocalBuilderForExpression ( IExpressionNode expr )
{
2025-10-09 18:40:11 +03:00
memoized_exprs . TryGetValue ( expr , out var result ) ;
return result ;
2018-10-02 23:11:07 +03:00
}
2015-05-14 22:35:07 +03:00
//получение типа
2018-10-02 23:11:07 +03:00
public TypeInfo GetTypeReference ( ITypeNode type )
2015-05-14 22:35:07 +03:00
{
TypeInfo ti = defs [ type ] as TypeInfo ;
if ( ti ! = null )
{
if ( type . type_special_kind = = type_special_kind . text_file )
ti . is_text_file = true ;
2019-01-26 11:43:27 +03:00
if ( ! ti . is_set & & ! ti . is_typed_file & & ! ti . is_text_file )
return ti ;
2015-05-14 22:35:07 +03:00
if ( ti . clone_meth = = null & & ! ti . is_typed_file & & ! ti . is_text_file )
{
if ( type is ICommonTypeNode )
ti . clone_meth = this . GetMethodBuilder ( find_method ( type as ICommonTypeNode , "CloneSet" ) ) ; //ti.tp.GetMethod("Clone");
else
ti . clone_meth = ti . tp . GetMethod ( "CloneSet" ) ;
}
if ( ti . def_cnstr = = null )
{
//if (type.type_special_kind == type_special_kind.text_file) ti.is_text_file = true;
if ( ti . is_set )
{
if ( type is ICommonTypeNode )
ti . def_cnstr = this . GetConstructorBuilder ( find_constructor_with_params ( type as ICommonTypeNode ) ) ;
else
ti . def_cnstr = find_constructor_with_params ( ti . tp ) ;
}
else if ( ti . is_typed_file )
{
if ( type is ICommonTypeNode )
ti . def_cnstr = this . GetConstructorBuilder ( find_constructor_with_one_param ( type as ICommonTypeNode ) ) ;
else
ti . def_cnstr = find_constructor_with_one_param ( ti . tp ) ;
}
else
{
if ( type is ICommonTypeNode )
ti . def_cnstr = this . GetConstructorBuilder ( find_constructor ( type as ICommonTypeNode ) ) ;
else
ti . def_cnstr = find_constructor ( ti . tp ) ;
}
}
if ( ti . assign_meth = = null & & ! ti . is_typed_file & & ! ti . is_text_file )
{
if ( type is ICommonTypeNode )
ti . assign_meth = this . GetMethodBuilder ( find_method ( type as ICommonTypeNode , "AssignSetFrom" ) ) ;
else
ti . assign_meth = ti . tp . GetMethod ( "AssignSetFrom" ) ;
}
return ti ;
}
if ( type is ICompiledTypeNode ) {
ti = new TypeInfo ( ( ( ICompiledTypeNode ) type ) . compiled_type ) ;
defs [ type ] = ti ;
return ti ;
}
//(ssyy) Ускорил, вставив switch
switch ( type . type_special_kind )
{
case type_special_kind . typed_file :
ti = GetTypeReference ( type . base_type ) ;
if ( ti = = null ) return null ;
ti . is_typed_file = true ;
if ( ti . def_cnstr = = null )
{
if ( type . base_type is ICommonTypeNode )
ti . def_cnstr = this . GetConstructorBuilder ( find_constructor_with_one_param ( type . base_type as ICommonTypeNode ) ) ;
else
ti . def_cnstr = find_constructor_with_one_param ( ti . tp ) ;
}
return ti ;
case type_special_kind . set_type :
ti = GetTypeReference ( type . base_type ) ;
if ( ti = = null ) return null ;
ti . is_set = true ;
if ( ti . clone_meth = = null )
{
if ( type . base_type is ICommonTypeNode )
ti . clone_meth = this . GetMethodBuilder ( find_method ( type . base_type as ICommonTypeNode , "CloneSet" ) ) ; //ti.tp.GetMethod("Clone");
else
ti . clone_meth = ti . tp . GetMethod ( "CloneSet" ) ;
}
if ( ti . assign_meth = = null )
{
if ( type . base_type is ICommonTypeNode )
ti . assign_meth = this . GetMethodBuilder ( find_method ( type . base_type as ICommonTypeNode , "AssignSetFrom" ) ) ;
else
ti . assign_meth = ti . tp . GetMethod ( "AssignSetFrom" ) ;
}
if ( ti . def_cnstr = = null )
{
if ( type . base_type is ICommonTypeNode )
ti . def_cnstr = this . GetConstructorBuilder ( find_constructor_with_params ( type . base_type as ICommonTypeNode ) ) ;
else
ti . def_cnstr = find_constructor_with_params ( ti . tp ) ;
}
return ti ;
case type_special_kind . diap_type :
return GetTypeReference ( type . base_type ) ;
case type_special_kind . short_string :
2025-10-11 22:36:05 +03:00
return new TypeInfo ( TypeFactory . StringType ) ;
2015-05-14 22:35:07 +03:00
case type_special_kind . array_kind :
TypeInfo tmp = GetTypeReference ( type . element_type ) ;
if ( tmp = = null ) return null ;
int rank = ( type as ICommonTypeNode ) . rank ;
if ( rank = = 1 )
ti = new TypeInfo ( tmp . tp . MakeArrayType ( ) ) ;
else
ti = new TypeInfo ( tmp . tp . MakeArrayType ( rank ) ) ;
//ti.is_arr = true;
defs [ type ] = ti ;
return ti ;
}
if ( type is IRefTypeNode ) {
TypeInfo ref_ti = GetTypeReference ( ( ( IRefTypeNode ) type ) . pointed_type ) ;
if ( ref_ti = = null ) return null ;
//(ssyy) Лучше использовать MakePointerType
ti = new TypeInfo ( ref_ti . tp . MakePointerType ( ) ) ;
defs [ type ] = ti ;
return ti ;
}
return null ;
}
public MethodBuilder GetMethodBuilder ( IFunctionNode meth )
{
MethInfo mi = defs [ meth ] as MethInfo ;
if ( mi ! = null )
return mi . mi as MethodBuilder ;
return null ;
}
public ConstructorBuilder GetConstructorBuilder ( IFunctionNode meth )
{
MethInfo ci = defs [ meth ] as MethInfo ;
if ( ci ! = null )
return ci . cnstr as ConstructorBuilder ;
return null ;
}
//получение метода создания массива
public MethodInfo GetArrayInstance ( )
{
if ( arr_mi ! = null ) return arr_mi ;
arr_mi = typeof ( System . Array ) . GetMethod ( "CreateInstance" , new Type [ 2 ] { typeof ( System . Type ) , typeof ( int ) } ) ;
return arr_mi ;
}
//добавление фиктивного метода (если метод содерж. вложенные, создается заглушка)
//т. е . метод не добавл. в таблицу
public MethInfo AddFictiveMethod ( IFunctionNode func , MethodBuilder mi )
{
MethInfo m = new MethInfo ( mi ) ;
//defs[func] = m;
return m ;
}
}
2025-10-09 18:40:11 +03:00
}