1056 lines
29 KiB
C#
1056 lines
29 KiB
C#
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||
using PascalABCCompiler.SemanticTree;
|
||
using System;
|
||
using System.Reflection;
|
||
using System.Reflection.Emit;
|
||
using System.Collections;
|
||
using System.Linq;
|
||
using System.Collections.Generic;
|
||
|
||
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()
|
||
{
|
||
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";
|
||
|
||
//op_Implicit
|
||
//op_Explicit
|
||
|
||
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";
|
||
//op_LeftShiftAssignment
|
||
//op_ModulusAssignment
|
||
names[StringConstants.plusassign_name]="op_AdditionAssignment";
|
||
//op_BitwiseAndAssignment
|
||
//op_BitwiseOrAssignment
|
||
//op_Comma
|
||
names[StringConstants.divassign_name]="op_DivisionAssignment";
|
||
//op_Decrement
|
||
//op_Increment
|
||
//names[StringConstants.minus_name] ="op_UnaryNegation";
|
||
//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;
|
||
public FieldInfo prev_fi; // передаю чтобы на третьем этапе в NegGenerator.cs (примерно 1586) можно было сконструировать правильный тип. Костыль для #1632
|
||
|
||
public override Type field_type
|
||
{
|
||
get
|
||
{
|
||
return _field_type;
|
||
}
|
||
}
|
||
|
||
public GenericFldInfo(FieldInfo fi, Type field_type, FieldInfo prev_fi)
|
||
: base(fi)
|
||
{
|
||
_field_type = field_type;
|
||
this.prev_fi = prev_fi;
|
||
}
|
||
}
|
||
|
||
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 {
|
||
public Hashtable defs=new Hashtable();
|
||
private HashSet<ICommonTypeNode> processing_types = new HashSet<ICommonTypeNode>();
|
||
private MethodInfo arr_mi=null;
|
||
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>();
|
||
|
||
public Helper() {}
|
||
|
||
public void AddDummyMethod(TypeBuilder tb, MethodBuilder mb)
|
||
{
|
||
dummy_methods[tb] = mb;
|
||
}
|
||
|
||
public MethodBuilder GetDummyMethod(TypeBuilder tb)
|
||
{
|
||
return dummy_methods[tb];
|
||
}
|
||
|
||
public void AddPascalTypeReference(ITypeNode tn, Type t)
|
||
{
|
||
pas_defs[tn] = t;
|
||
}
|
||
|
||
public Type GetPascalTypeReference(ITypeNode tn)
|
||
{
|
||
pas_defs.TryGetValue(tn, out var result);
|
||
return result;
|
||
}
|
||
|
||
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)
|
||
{
|
||
if (expr is PascalABCCompiler.TreeRealization.null_const_node) // SSM 20/04/21
|
||
return expr;
|
||
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);
|
||
#if DEBUG
|
||
/*if (f.name == "XYZW")
|
||
{
|
||
var y = f.GetHashCode();
|
||
} */
|
||
#endif
|
||
defs[f] = fi;
|
||
return fi;
|
||
}
|
||
|
||
public FldInfo AddGenericField(ICommonClassFieldNode f, FieldInfo fb, Type field_type, FieldInfo prev_fi)
|
||
{
|
||
FldInfo fi = new GenericFldInfo(fb, field_type, prev_fi); // prev_fi - чтобы сконструировать на последнем этапе fi
|
||
#if DEBUG
|
||
/*if (f.name == "XYZW")
|
||
{
|
||
var y = f.GetHashCode();
|
||
}*/
|
||
#endif
|
||
defs[f] = fi;
|
||
return fi;
|
||
}
|
||
|
||
//получение поля
|
||
public FldInfo GetField(ICommonClassFieldNode f)
|
||
{
|
||
var r = (FldInfo)defs[f];
|
||
#if DEBUG
|
||
/*if (f.name == "XYZW")
|
||
{
|
||
var y = f.GetHashCode();
|
||
} */
|
||
#endif
|
||
#if DEBUG
|
||
/*if (r == null && f.name == "XYZW")
|
||
{
|
||
foreach (var k in defs.Keys)
|
||
{
|
||
if ((k is ICommonClassFieldNode) && (k as ICommonClassFieldNode).name == "XYZW")
|
||
return (FldInfo)defs[k];
|
||
}
|
||
} */
|
||
#endif
|
||
return r;
|
||
}
|
||
|
||
//добавление типа
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// До вызова <c>.CreateType()</c> позволяет определить, был ли тип объявлен в коде, а не в готовой сборке.
|
||
/// Generic типы инстанцированные Pascal типами также считаются Pascal типами (пример: <c>IEnumerable<PascalType></c>)
|
||
/// </summary>
|
||
public bool IsPascalType(Type t)
|
||
{
|
||
if (t is TypeBuilder || t is GenericTypeParameterBuilder || t is EnumBuilder || t.GetType().FullName == "System.Reflection.Emit.TypeBuilderInstantiation")
|
||
return true;
|
||
|
||
if ( t.IsGenericType && t.GetGenericArguments().Any(IsPascalType) )
|
||
return true;
|
||
|
||
if (t.IsArray)
|
||
return IsPascalType(t.GetElementType());
|
||
|
||
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;
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
public void SetAsProcessing(ICommonTypeNode type)
|
||
{
|
||
processing_types.Add(type);
|
||
}
|
||
|
||
public bool IsProcessing(ICommonTypeNode type)
|
||
{
|
||
return processing_types.Contains(type);
|
||
}
|
||
|
||
public void LinkExpressionToLocalBuilder(IExpressionNode expr, LocalBuilder lb)
|
||
{
|
||
memoized_exprs[expr] = lb;
|
||
}
|
||
|
||
public LocalBuilder GetLocalBuilderForExpression(IExpressionNode expr)
|
||
{
|
||
memoized_exprs.TryGetValue(expr, out var result);
|
||
return result;
|
||
}
|
||
|
||
//получение типа
|
||
public TypeInfo GetTypeReference(ITypeNode type)
|
||
{
|
||
TypeInfo ti = defs[type] as TypeInfo;
|
||
if (ti != null)
|
||
{
|
||
if (type.type_special_kind == type_special_kind.text_file)
|
||
ti.is_text_file = true;
|
||
if (!ti.is_set && !ti.is_typed_file && !ti.is_text_file)
|
||
return ti;
|
||
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:
|
||
return new TypeInfo(TypeFactory.StringType);
|
||
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;
|
||
}
|
||
}
|
||
} |