| 
					
				 | 
			
			
				@@ -0,0 +1,147 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+using System; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+using System.Collections.Generic; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+using System.Linq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+using XamlIl.Ast; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+using XamlIl.Transform; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+using XamlIl.TypeSystem; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    class XamlIlClrPropertyInfoHelper 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        class ClrPropertyInfoNode : XamlIlAstNode, IXamlIlAstValueNode 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            public ClrPropertyInfoNode(AvaloniaXamlIlWellKnownTypes types, IXamlIlLineInfo lineInfo) : 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                base(lineInfo) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                Type = new XamlIlAstClrTypeReference(this, types.XamlIlTypes.Object, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            public IXamlIlAstTypeReference Type { get; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    class XamlIlClrPropertyInfoEmitter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        private readonly IXamlIlTypeBuilder _builder; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        private Dictionary<string, List<(IXamlIlProperty prop, IXamlIlMethod get)>> _fields 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            = new Dictionary<string, List<(IXamlIlProperty prop, IXamlIlMethod get)>>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        public XamlIlClrPropertyInfoEmitter(IXamlIlTypeBuilder builder) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            _builder = builder; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        static string GetKey(IXamlIlProperty property)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            => property.Getter.DeclaringType.GetFullName() + "." + property.Name; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        public IXamlIlType Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen, IXamlIlProperty property) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var types = context.GetAvaloniaTypes(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            IXamlIlMethod Get() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var key = GetKey(property); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!_fields.TryGetValue(key, out var lst)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    _fields[key] = lst = new List<(IXamlIlProperty prop, IXamlIlMethod get)>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                foreach (var cached in lst) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        ((cached.prop.Getter == null && property.Getter == null) || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                         cached.prop.Getter?.Equals(property.Getter) == true) && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        ((cached.prop.Setter == null && property.Setter == null) || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                         cached.prop.Setter?.Equals(property.Setter) == true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return cached.get; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var name = lst.Count == 0 ? key : key + "_" + Guid.NewGuid().ToString("N"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var field = _builder.DefineField(types.IPropertyInfo, name + "!Field", false, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var getter = property.Getter == null ? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    null : 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    _builder.DefineMethod(types.XamlIlTypes.Object, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        new[] {types.XamlIlTypes.Object}, name + "!Getter", false, true, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (getter != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    getter.Generator 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .Ldarg_0() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .Castclass(property.Getter.DeclaringType) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .EmitCall(property.Getter); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (property.Getter.ReturnType.IsValueType) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        getter.Generator.Box(property.Getter.ReturnType); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    getter.Generator.Ret(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var setter = property.Setter == null ? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    null : 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    _builder.DefineMethod(types.XamlIlTypes.Void, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        new[] {types.XamlIlTypes.Object, types.XamlIlTypes.Object}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        name + "!Setter", false, true, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (setter != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    setter.Generator 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .Ldarg_0() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .Castclass(property.Setter.DeclaringType) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .Ldarg(1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (property.Setter.Parameters[0].IsValueType) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        setter.Generator.Unbox_Any(property.Setter.Parameters[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        setter.Generator.Castclass(property.Setter.Parameters[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    setter.Generator 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .EmitCall(property.Setter, true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .Ret(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var get = _builder.DefineMethod(types.IPropertyInfo, Array.Empty<IXamlIlType>(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    name + "!Property", true, true, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var ctor = types.ClrPropertyInfo.Constructors.First(c => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    c.Parameters.Count == 3 && c.IsStatic == false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var cacheMiss = get.Generator.DefineLabel(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                get.Generator 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .Ldsfld(field) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .Brfalse(cacheMiss) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .Ldsfld(field) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .Ret() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .MarkLabel(cacheMiss) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .Ldstr(property.Name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                void EmitFunc(IXamlIlEmitter emitter, IXamlIlMethod method, IXamlIlType del) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (method == null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        emitter.Ldnull(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        emitter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            .Ldnull() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            .Ldftn(method) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            .Newobj(del.Constructors.First(c => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                c.Parameters.Count == 2 && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                c.Parameters[0].Equals(context.Configuration.WellKnownTypes.Object))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                EmitFunc(get.Generator, getter, ctor.Parameters[1]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                EmitFunc(get.Generator, setter, ctor.Parameters[2]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                get.Generator 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .Newobj(ctor) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .Stsfld(field) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .Ldsfld(field) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .Ret(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lst.Add((property, get)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return get; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            codeGen.EmitCall(Get()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return types.IPropertyInfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |