示例#1
0
 public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
 {
     // Discard the stack value we are "supposed" to manipulate
     codeGen.Pop();
     context.Emit(Imperative, codeGen, null);
     return(XamlIlNodeEmitResult.Void(1));
 }
        protected override void DoEmit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (_selectors.Count == 0)
            {
                throw new XamlIlLoadException("Invalid selector count", this);
            }
            if (_selectors.Count == 1)
            {
                _selectors[0].Emit(context, codeGen);
                return;
            }
            var listType = context.Configuration.TypeSystem.FindType("System.Collections.Generic.List`1")
                           .MakeGenericType(base.Type.GetClrType());
            var add = listType.FindMethod("Add", context.Configuration.WellKnownTypes.Void, false, Type.GetClrType());

            codeGen
            .Newobj(listType.FindConstructor());
            foreach (var s in _selectors)
            {
                codeGen.Dup();
                context.Emit(s, codeGen, Type.GetClrType());
                codeGen.EmitCall(add, true);
            }

            EmitCall(context, codeGen,
                     m => m.Name == "Or" && m.Parameters.Count == 1 && m.Parameters[0].Name.StartsWith("IReadOnlyList"));
        }
示例#3
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlCodeGen codeGen)
        {
            if (!(node is XamlIlInstanceMethodCallBaseNode mc))
            {
                return(null);
            }
            for (var c = 0; c < mc.Arguments.Count; c++)
            {
                context.Emit(mc.Arguments[c], codeGen, mc.Method.Parameters[c]);
            }
            codeGen.Generator.Emit(mc.Method.IsStatic ? OpCodes.Call : OpCodes.Callvirt, mc.Method);

            var isVoid = mc.Method.ReturnType.Equals(context.Configuration.WellKnownTypes.Void);

            if (mc is XamlIlInstanceNoReturnMethodCallNode && !isVoid)
            {
                codeGen.Generator.Emit(OpCodes.Pop);
            }
            if (mc is XamlIlStaticReturnMethodCallNode && isVoid)
            {
                throw new XamlIlLoadException(
                          $"XamlIlStaticReturnMethodCallNode expects a value while {mc.Method.Name} returns void", node);
            }

            return(isVoid ? XamlIlNodeEmitResult.Void : XamlIlNodeEmitResult.Type(mc.Method.ReturnType));
        }
示例#4
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlCodeGen codeGen)
        {
            if (!(node is XamlIlAstNewClrObjectNode n))
            {
                return(null);
            }
            var type = n.Type.GetClrType();

            var argTypes = n.Arguments.Select(a => a.Type.GetClrType()).ToList();
            var ctor     = type.FindConstructor(argTypes);

            if (ctor == null)
            {
                throw new XamlIlLoadException(
                          $"Unable to find public constructor for type {type.GetFqn()}({string.Join(", ", argTypes.Select(at => at.GetFqn()))})",
                          n);
            }

            for (var c = 0; c < n.Arguments.Count; c++)
            {
                var ctorArg = n.Arguments[c];
                context.Emit(ctorArg, codeGen, ctor.Parameters[c]);
            }

            var gen = codeGen.Generator
                      .Emit(OpCodes.Newobj, ctor);


            return(XamlIlNodeEmitResult.Type(type));
        }
示例#5
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlValueWithManipulationNode vwm))
            {
                return(null);
            }
            var created = context.Emit(vwm.Value, codeGen, vwm.Type.GetClrType());

            if (vwm.Manipulation != null &&
                !(vwm.Manipulation is XamlIlManipulationGroupNode grp && grp.Children.Count == 0))
            {
                codeGen.Emit(OpCodes.Dup);
                context.Emit(vwm.Manipulation, codeGen, null);
            }
            return(XamlIlNodeEmitResult.Type(0, created.ReturnType));
        }
示例#6
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlAstNewClrObjectNode n))
            {
                return(null);
            }

            var type = n.Type.GetClrType();
            var ctor = n.Constructor ?? type.FindConstructor();

            if (ctor == null)
            {
                throw new XamlIlLoadException("Unable to find default constructor and no non-default one is specified",
                                              n);
            }

            for (var c = 0; c < n.Arguments.Count; c++)
            {
                context.Emit(n.Arguments[c], codeGen, ctor.Parameters[c]);
            }

            var gen = codeGen
                      .Emit(OpCodes.Newobj, ctor);


            return(XamlIlNodeEmitResult.Type(0, type));
        }
            public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
            {
                var exts           = context.Configuration.TypeSystem.GetType("Avalonia.Controls.NameScopeExtensions");
                var findNameScope  = exts.FindMethod(m => m.Name == "FindNameScope");
                var registerMethod = findNameScope.ReturnType.FindMethod(m => m.Name == "Register");

                using (var targetLoc = context.GetLocal(context.Configuration.WellKnownTypes.Object))
                    using (var nameScopeLoc = context.GetLocal(findNameScope.ReturnType))
                    {
                        var exit = codeGen.DefineLabel();
                        codeGen
                        // var target = {pop}
                        .Stloc(targetLoc.Local)
                        // var scope = target.FindNameScope()
                        .Ldloc(targetLoc.Local)
                        .Castclass(findNameScope.Parameters[0])
                        .EmitCall(findNameScope)
                        .Stloc(nameScopeLoc.Local)
                        // if({scope} != null) goto call;
                        .Ldloc(nameScopeLoc.Local)
                        .Brfalse(exit)
                        .Ldloc(nameScopeLoc.Local);
                        context.Emit(Value, codeGen, Value.Type.GetClrType());
                        codeGen
                        .Ldloc(targetLoc.Local)
                        .EmitCall(registerMethod)
                        .MarkLabel(exit);
                    }
                return(XamlIlNodeEmitResult.Void(1));
            }
示例#8
0
        public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            var rv = context.Emit(Value, codeGen, Local.Type);

            codeGen.Emit(OpCodes.Dup);
            context.StLocal(Local, codeGen);
            return(XamlIlNodeEmitResult.Type(0, rv.ReturnType));
        }
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlObjectInitializationNode init))
            {
                return(null);
            }
            var supportInitType    = context.Configuration.TypeMappings.SupportInitialize;
            var supportsInitialize = supportInitType != null &&
                                     context.Configuration.TypeMappings.SupportInitialize
                                     .IsAssignableFrom(init.Type);

            if (supportsInitialize)
            {
                codeGen
                // We need a copy for/EndInit
                .Emit(OpCodes.Dup);
                if (!init.SkipBeginInit)
                {
                    codeGen
                    .Emit(OpCodes.Dup)
                    .EmitCall(supportInitType.FindMethod(m => m.Name == "BeginInit"));
                }
            }


            var addToParentStack = context.RuntimeContext.ParentListField != null &&
                                   !init.Type.IsValueType &&
                                   context.GetOrCreateItem <XamlIlNeedsParentStackCache>().NeedsParentStack(node);

            if (addToParentStack)
            {
                using (var local = context.GetLocal(init.Type))
                    codeGen
                    .Stloc(local.Local)
                    .Ldloc(context.ContextLocal)
                    .Ldloc(local.Local)
                    .EmitCall(context.RuntimeContext.PushParentMethod)
                    .Ldloc(local.Local);
            }

            context.Emit(init.Manipulation, codeGen, null);

            if (addToParentStack)
            {
                codeGen
                .Ldloc(context.ContextLocal)
                .EmitCall(context.RuntimeContext.PopParentMethod, true);
            }

            if (supportsInitialize)
            {
                codeGen
                .EmitCall(supportInitType.FindMethod(m => m.Name == "EndInit"));
            }


            return(XamlIlNodeEmitResult.Void(1));
        }
示例#10
0
 public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
 {
     context.Emit(Value, codeGen, Method.DeclaringType);
     codeGen
     .Ldftn(Method)
     .Newobj(DelegateType.Constructors.FirstOrDefault(ct =>
                                                      ct.Parameters.Count == 2 && ct.Parameters[0].Equals(context.Configuration.WellKnownTypes.Object)));
     return(XamlIlNodeEmitResult.Type(0, DelegateType));
 }
 public virtual XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
 {
     if (Previous != null)
     {
         context.Emit(Previous, codeGen, Type.GetClrType());
     }
     DoEmit(context, codeGen);
     return(XamlIlNodeEmitResult.Type(0, Type.GetClrType()));
 }
示例#12
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlPropertyAssignmentNode an))
                return null;
            var callOp = an.Property.Setter.IsStatic ? OpCodes.Call : OpCodes.Callvirt;
            context.Emit(an.Value, codeGen, an.Property.Setter.Parameters.Last());
            codeGen.Emit(callOp, an.Property.Setter);

            return XamlIlNodeEmitResult.Void(1);
        }
示例#13
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter ilgen)
        {
            if (!(node is XamlIlMarkupExtensionNode me))
            {
                return(null);
            }
            XamlIlNeedsParentStackCache.Verify(context, node);

            var prop = context.ParentNodes().OfType <XamlIlPropertyAssignmentNode>().FirstOrDefault();

            var needProvideValueTarget = me.ProvideValue.Parameters.Count != 0 &&
                                         context.RuntimeContext.PropertyTargetObject != null &&
                                         prop != null;

            void EmitPropertyDescriptor()
            {
                if (context.Configuration.TypeMappings.ProvideValueTargetPropertyEmitter
                    ?.Invoke(context, ilgen, prop.Property) == true)
                {
                    return;
                }
                ilgen.Ldstr(prop.Property.Name);
            }

            context.Emit(me.Value, ilgen, me.Value.Type.GetClrType());

            if (me.ProvideValue.Parameters.Count > 0)
            {
                ilgen
                .Emit(OpCodes.Ldloc, context.ContextLocal);
            }

            if (needProvideValueTarget)
            {
                ilgen
                .Ldloc(context.ContextLocal);
                EmitPropertyDescriptor();
                ilgen
                .Stfld(context.RuntimeContext.PropertyTargetProperty);
            }

            ilgen.EmitCall(me.ProvideValue);

            if (needProvideValueTarget)
            {
                ilgen
                .Ldloc(context.ContextLocal)
                .Ldnull()
                .Stfld(context.RuntimeContext.PropertyTargetProperty);
            }



            return(XamlIlNodeEmitResult.Type(0, me.ProvideValue.ReturnType));
        }
示例#14
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlPropertyValueManipulationNode pvm))
            {
                return(null);
            }
            codeGen.EmitCall(pvm.Property.Getter);
            context.Emit(pvm.Manipulation, codeGen, null);

            return(XamlIlNodeEmitResult.Void(1));
        }
示例#15
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlCodeGen codeGen)
        {
            if (!(node is XamlIlPropertyValueManipulationNode pvm))
            {
                return(null);
            }
            codeGen.Generator.Emit(pvm.Property.Getter.IsStatic ? OpCodes.Call : OpCodes.Callvirt,
                                   pvm.Property.Getter);
            context.Emit(pvm.Manipulation, codeGen, null);

            return(XamlIlNodeEmitResult.Void);
        }
示例#16
0
        public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            context.Emit(Value, codeGen, context.Configuration.WellKnownTypes.Object);
            var t = Type.GetClrType();

            if (t.IsValueType)
            {
                codeGen.Unbox_Any(t);
            }
            else
            {
                codeGen.Castclass(t);
            }
            return(XamlIlNodeEmitResult.Type(0, t));
        }
 protected override void DoEmit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
 {
     if (!XamlIlAvaloniaPropertyHelper.Emit(context, codeGen, Property))
     {
         throw new XamlIlLoadException(
                   $"{Property.Name} of {(Property.Setter ?? Property.Getter).DeclaringType.GetFqn()} doesn't seem to be an AvaloniaProperty",
                   this);
     }
     context.Emit(Value, codeGen, context.Configuration.WellKnownTypes.Object);
     EmitCall(context, codeGen,
              m => m.Name == "PropertyEquals" &&
              m.Parameters.Count == 3 &&
              m.Parameters[1].FullName == "Avalonia.AvaloniaProperty" &&
              m.Parameters[2].Equals(context.Configuration.WellKnownTypes.Object));
 }
示例#18
0
        void CompileBuilder(XamlIlEmitContext context)
        {
            var il = context.Emitter;

            // Initialize the context
            il
            .Ldarg_0();
            context.RuntimeContext.Factory(il);
            il.Stloc(context.ContextLocal);

            // It might be better to save this in a closure
            if (context.Configuration.TypeMappings.RootObjectProvider != null)
            {
                // Attempt to get the root object from parent service provider
                var noRoot = il.DefineLabel();
                using (var loc = context.GetLocal(context.Configuration.WellKnownTypes.Object))
                    il
                    // if(arg == null) goto noRoot;
                    .Ldarg_0()
                    .Brfalse(noRoot)
                    // var loc = arg.GetService(typeof(IRootObjectProvider))
                    .Ldarg_0()
                    .Ldtype(context.Configuration.TypeMappings.RootObjectProvider)
                    .EmitCall(context.Configuration.TypeMappings.ServiceProvider
                              .FindMethod(m => m.Name == "GetService"))
                    .Stloc(loc.Local)
                    // if(loc == null) goto noRoot;
                    .Ldloc(loc.Local)
                    .Brfalse(noRoot)
                    // loc = ((IRootObjectProvider)loc).RootObject
                    .Ldloc(loc.Local)
                    .Castclass(context.Configuration.TypeMappings.RootObjectProvider)
                    .EmitCall(context.Configuration.TypeMappings.RootObjectProvider
                              .FindMethod(m => m.Name == "get_RootObject"))
                    .Stloc(loc.Local)
                    // contextLocal.RootObject = loc;
                    .Ldloc(context.ContextLocal)
                    .Ldloc(loc.Local)
                    .Castclass(context.RuntimeContext.ContextType.GenericArguments[0])
                    .Stfld(context.RuntimeContext.RootObjectField)
                    .MarkLabel(noRoot);
            }

            context.Emit(Value, context.Emitter, context.Configuration.WellKnownTypes.Object);
            il.Ret();
        }
示例#19
0
        public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            var res                = context.Emit(Value, codeGen, Value.Type.GetClrType());
            var supportInitType    = context.Configuration.TypeMappings.SupportInitialize;
            var supportsInitialize = supportInitType != null &&
                                     context.Configuration.TypeMappings.SupportInitialize
                                     .IsAssignableFrom(Value.Type.GetClrType());

            if (supportsInitialize)
            {
                codeGen
                .Dup()
                .EmitCall(supportInitType.FindMethod(m => m.Name == "BeginInit"));
            }

            return(res);
        }
示例#20
0
        public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            var scopeField = context.RuntimeContext.ContextType.Fields.First(f =>
                                                                             f.Name == AvaloniaXamlIlLanguage.ContextNameScopeFieldName);

            using (var targetLoc = context.GetLocal(context.Configuration.WellKnownTypes.Object))
            {
                codeGen
                // var target = {pop}
                .Stloc(targetLoc.Local)
                // _context.NameScope.Register(Name, target)
                .Ldloc(context.ContextLocal)
                .Ldfld(scopeField);

                context.Emit(Name, codeGen, Name.Type.GetClrType());

                codeGen
                .Ldloc(targetLoc.Local)
                .EmitCall(_types.INameScopeRegister, true);
            }

            return(XamlIlNodeEmitResult.Void(1));
        }
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlCodeGen codeGen)
        {
            if (!(node is XamlIlManipulationGroupNode group))
            {
                return(null);
            }
            if (group.Children.Count == 0)
            {
                codeGen.Generator.Emit(OpCodes.Pop);
            }
            else
            {
                for (var c = 0; c < group.Children.Count; c++)
                {
                    if (c != group.Children.Count - 1)
                    {
                        codeGen.Generator.Emit(OpCodes.Dup);
                    }
                    context.Emit(group.Children[c], codeGen, null);
                }
            }

            return(XamlIlNodeEmitResult.Void);
        }
示例#22
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlMethodCallBaseNode mc))
            {
                return(null);
            }

            bool thisArgFromArgs = node is XamlIlStaticOrTargetedReturnMethodCallNode;
            bool expectsVoid     = node is XamlIlNoReturnMethodCallNode;


            for (var c = 0; c < mc.Arguments.Count; c++)
            {
                var off          = thisArgFromArgs ? 0 : 1;
                var expectedType = mc.Method.ParametersWithThis[c + off];
                context.Emit(mc.Arguments[c], codeGen, expectedType);
            }



            mc.Method.Emit(context, codeGen, expectsVoid);

            var isVoid = mc.Method.ReturnType.Equals(context.Configuration.WellKnownTypes.Void);

            if (!expectsVoid && isVoid)
            {
                throw new XamlIlLoadException(
                          $"XamlIlStaticReturnMethodCallNode expects a value while {mc.Method.Name} returns void", node);
            }

            var consumed = thisArgFromArgs ? 0 : 1;

            return(isVoid || expectsVoid
                ? XamlIlNodeEmitResult.Void(consumed)
                : XamlIlNodeEmitResult.Type(consumed, mc.Method.ReturnType));
        }
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlCodeGen codeGen)
        {
            if (!(node is XamlIlMarkupExtensionNode me))
            {
                return(null);
            }


            var ptype = me.Manipulation?.Parameters[0] ?? me.Property.PropertyType;
            var rtype = me.ProvideValue.ReturnType;

            context.Emit(me.Value, codeGen, me.Value.Type.GetClrType());
            if (me.ProvideValue.Parameters.Count != 0)
            {
                //TODO: IProvideValueTarget
                codeGen.Generator
                .Emit(OpCodes.Ldloc, context.ContextLocal);
            }

            var resultLocal = codeGen.Generator.DefineLocal(rtype);

            codeGen.Generator
            .Emit(OpCodes.Call, me.ProvideValue)
            .Emit(OpCodes.Stloc, resultLocal);

            IXamlIlEmitter CallSetter()
            {
                if (me.Manipulation != null)
                {
                    // {target}.{Property}.{Method)(res)
                    var res = codeGen.Generator.DefineLocal(ptype);
                    if (me.Property != null)
                    {
                        codeGen.Generator
                        .Emit(OpCodes.Stloc, res)
                        .EmitCall(me.Property.Getter)
                        .Emit(OpCodes.Ldloc, res);
                    }
                    codeGen.Generator
                    .EmitCall(me.Manipulation, true);
                    return(codeGen.Generator);
                }

                return(codeGen.Generator.EmitCall(me.Property.Setter));
            }

            // Now we have the value returned by markup extension in resultLocal


            //Simplest case: exact type match
            if (ptype.Equals(rtype))
            {
                codeGen.Generator
                .Emit(OpCodes.Ldloc, resultLocal);
                CallSetter();
                return(XamlIlNodeEmitResult.Void);
            }
            var exit = codeGen.Generator.DefineLabel();


            if (ptype.IsValueType && rtype.IsValueType)
            {
                // If both are value types, try convert non-nullable to nullable
                if (ptype.IsNullableOf(rtype))
                {
                    codeGen.Generator
                    .Emit(OpCodes.Ldloc, resultLocal)
                    .Emit(OpCodes.Newobj,
                          ptype.Constructors.First(c =>
                                                   c.Parameters.Count == 1 && c.Parameters[0].Equals(rtype)));
                    CallSetter();
                    return(XamlIlNodeEmitResult.Void);
                }
            }
            else if (rtype.IsValueType && !ptype.IsValueType)
            {
                // If target is object, simply box
                if (ptype.Equals(context.Configuration.WellKnownTypes.Object))
                {
                    codeGen.Generator
                    .Emit(OpCodes.Ldloc, resultLocal)
                    .Emit(OpCodes.Box, rtype);
                    CallSetter();
                    return(XamlIlNodeEmitResult.Void);
                }
            }
            else if (ptype.IsValueType)
            {
                // Cast attempt only makes sense if it's an object
                if (rtype.Equals(context.Configuration.WellKnownTypes.Object))
                {
                    var notMatchedType = codeGen.Generator.DefineLabel();
                    codeGen.Generator
                    .Emit(OpCodes.Ldloc, resultLocal)
                    .Emit(OpCodes.Isinst, ptype)
                    .Emit(OpCodes.Brfalse, notMatchedType)
                    .Emit(OpCodes.Ldloc, resultLocal)
                    .Emit(OpCodes.Unbox_Any, ptype);
                    CallSetter()
                    .Emit(OpCodes.Br, exit)
                    .MarkLabel(notMatchedType);
                }
            }
            else
            {
                // if(res==null) target.Property = null;
                var notNull = codeGen.Generator.DefineLabel();
                codeGen.Generator
                .Emit(OpCodes.Ldloc, resultLocal)
                .Emit(OpCodes.Brtrue, notNull)
                .Emit(OpCodes.Ldloc, resultLocal);
                CallSetter()
                .Emit(OpCodes.Br, exit)
                .MarkLabel(notNull);

                // if (res is T matched)  target.Property = matched;
                var nonMatchedType = codeGen.Generator.DefineLabel();
                codeGen.Generator
                .Emit(OpCodes.Ldloc, resultLocal)
                .Emit(OpCodes.Isinst, ptype)
                .Emit(OpCodes.Dup)
                .Emit(OpCodes.Brfalse, nonMatchedType);
                CallSetter();
                codeGen.Generator.Emit(OpCodes.Br, exit)
                .MarkLabel(nonMatchedType)
                .Emit(OpCodes.Pop);
            }

            // Cast attempts have failed, call external method
            codeGen.Generator
            .Emit(OpCodes.Ldstr, me.Property?.Name)
            .Emit(OpCodes.Ldloc, context.ContextLocal)
            .Emit(OpCodes.Ldloc, resultLocal);
            if (rtype.IsValueType)
            {
                codeGen.Generator.Emit(OpCodes.Box, rtype);
            }
            codeGen.Generator
            .Emit(OpCodes.Call, context.Configuration.TypeMappings.ApplyNonMatchingMarkupExtension)
            .Emit(OpCodes.Br, exit);


            codeGen.Generator.MarkLabel(exit);
            return(XamlIlNodeEmitResult.Void);
        }
 protected override void DoEmit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
 {
     context.Emit(Argument, codeGen, Type.GetClrType());
     EmitCall(context, codeGen,
              m => m.Name == "Not" && m.Parameters.Count == 2 && m.Parameters[1].Equals(Type.GetClrType()));
 }
示例#25
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlObjectInitializationNode init))
            {
                return(null);
            }
            var supportInitType    = context.Configuration.TypeMappings.SupportInitialize;
            var supportsInitialize = supportInitType != null &&
                                     context.Configuration.TypeMappings.SupportInitialize
                                     .IsAssignableFrom(init.Type);

            if (supportsInitialize)
            {
                codeGen
                // We need a copy for/EndInit
                .Emit(OpCodes.Dup);
                if (!init.SkipBeginInit)
                {
                    codeGen
                    .Emit(OpCodes.Dup)
                    .EmitCall(supportInitType.FindMethod(m => m.Name == "BeginInit"));
                }
            }

            IXamlIlType objectListType   = null;
            var         addToParentStack = context.RuntimeContext.ParentListField != null &&
                                           !init.Type.IsValueType &&
                                           context.GetOrCreateItem <XamlIlNeedsParentStackCache>().NeedsParentStack(node);

            if (addToParentStack)
            {
                objectListType = context.Configuration.TypeSystem.GetType("System.Collections.Generic.List`1")
                                 .MakeGenericType(new[] { context.Configuration.WellKnownTypes.Object });

                using (var local = context.GetLocal(init.Type))
                    codeGen
                    .Stloc(local.Local)
                    .Ldloc(context.ContextLocal).Ldfld(context.RuntimeContext.ParentListField)
                    .Ldloc(local.Local)
                    .EmitCall(objectListType.FindMethod("Add", context.Configuration.WellKnownTypes.Void,
                                                        false, context.Configuration.WellKnownTypes.Object))
                    .Ldloc(local.Local);
            }

            context.Emit(init.Manipulation, codeGen, null);

            if (addToParentStack)
            {
                codeGen
                .Ldloc(context.ContextLocal).Ldfld(context.RuntimeContext.ParentListField)
                .Ldloc(context.ContextLocal).Ldfld(context.RuntimeContext.ParentListField)
                .EmitCall(objectListType.FindMethod(m => m.Name == "get_Count"))
                .Ldc_I4(1).Emit(OpCodes.Sub)
                .EmitCall(objectListType.FindMethod(m => m.Name == "RemoveAt"));
            }

            if (supportsInitialize)
            {
                codeGen
                .EmitCall(supportInitType.FindMethod(m => m.Name == "EndInit"));
            }


            return(XamlIlNodeEmitResult.Void(1));
        }
示例#26
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlPropertyAssignmentNode an))
            {
                return(null);
            }

            var setters = ValidateAndGetSetters(an);

            for (var c = 0; c < an.Values.Count - 1; c++)
            {
                context.Emit(an.Values[c], codeGen, an.Values[c].Type.GetClrType());
            }

            var value = an.Values.Last();

            var isValueType = value.Type.GetClrType().IsValueType;

            // If there is only one available setter or if value is a value type, always use the first one
            if (setters.Count == 1 || isValueType)
            {
                var setter = an.PossibleSetters.First();
                context.Emit(value, codeGen, setter.Parameters.Last());
                setter.Emit(codeGen);
            }
            else
            {
                var          checkedTypes = new List <IXamlIlType>();
                IXamlIlLabel exit         = codeGen.DefineLabel();
                IXamlIlLabel next         = null;
                var          hadJumps     = false;
                context.Emit(value, codeGen, value.Type.GetClrType());

                foreach (var setter in setters)
                {
                    var type = setter.Parameters.Last();

                    // We have already checked this type or its base type
                    if (checkedTypes.Any(ch => ch.IsAssignableFrom(type)))
                    {
                        continue;
                    }

                    if (next != null)
                    {
                        codeGen.MarkLabel(next);
                        next = null;
                    }

                    IXamlIlLabel Next() => next ?? (next = codeGen.DefineLabel());

                    var checkNext = false;
                    if (setter.BinderParameters.AllowRuntimeNull)
                    {
                        checkedTypes.Add(type);
                    }
                    else
                    {
                        // Check for null; Also don't add this type to the list of checked ones because of the null check
                        codeGen
                        .Dup()
                        .Brfalse(Next());
                        checkNext = true;
                    }

                    // Only do dynamic checks if we know that type is not assignable by downcast
                    if (!type.IsAssignableFrom(value.Type.GetClrType()))
                    {
                        codeGen
                        .Dup()
                        .Isinst(type)
                        .Brfalse(Next());
                        checkNext = true;
                    }

                    if (checkNext)
                    {
                        hadJumps = true;
                    }

                    TypeSystemHelpers.EmitConvert(context, codeGen, value, value.Type.GetClrType(), type);
                    setter.Emit(codeGen);
                    if (hadJumps)
                    {
                        codeGen.Br(exit);
                    }

                    if (!checkNext)
                    {
                        break;
                    }
                }

                if (next != null)
                {
                    codeGen.MarkLabel(next);

                    if (setters.Any(x => !x.BinderParameters.AllowRuntimeNull))
                    {
                        next = codeGen.DefineLabel();
                        codeGen
                        .Dup()
                        .Brtrue(next)
                        .Newobj(context.Configuration.TypeSystem.GetType("System.NullReferenceException")
                                .FindConstructor())
                        .Throw();
                        codeGen.MarkLabel(next);
                    }

                    codeGen
                    .Newobj(context.Configuration.TypeSystem.GetType("System.InvalidCastException")
                            .FindConstructor())
                    .Throw();
                }

                codeGen.MarkLabel(exit);
            }

            return(XamlIlNodeEmitResult.Void(1));
        }
示例#27
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlMarkupExtensionNode me))
            {
                return(null);
            }
            XamlIlNeedsParentStackCache.Verify(context, node);
            var ilgen = codeGen;
            var so    = context.Configuration.WellKnownTypes.Object;
            var ptype = me.Manipulation?.ParametersWithThis[1] ?? me.Property.PropertyType;
            var rtype = me.ProvideValue?.ReturnType ?? me.Value.Type.GetClrType();
            var needProvideValueTarget = me.ProvideValue != null &&
                                         me.ProvideValue.Parameters.Count != 0 &&
                                         context.RuntimeContext.PropertyTargetObject != null &&
                                         me.Property != null;

            void EmitPropertyDescriptor()
            {
                if (me.Property == null)
                {
                    ilgen.Ldnull();
                }
                else if (context.Configuration.TypeMappings.ProvideValueTargetPropertyEmitter
                         ?.Invoke(context, codeGen, me.Property) == true)
                {
                    return;
                }
                else if (me.Property is XamlIlAstAttachedProperty)
                {
                    ilgen.Ldtoken(me.Property.Getter ?? me.Property.Setter)
                    .Emit(OpCodes.Box, context.Configuration.TypeSystem.GetType("System.RuntimeMethodHandle"));
                }
                else
                {
                    ilgen.Ldstr(me.Property?.Name);
                }
            }

            using (var resultLocalContainer = context.GetLocal(rtype))
            {
                var resultLocal = resultLocalContainer.Local;
                using (var targetObjectLocal = needProvideValueTarget ? context.GetLocal(so) : null)
                {
                    if (needProvideValueTarget)
                    {
                        ilgen
                        .Dup().Stloc(targetObjectLocal.Local);
                    }

                    context.Emit(me.Value, codeGen, me.Value.Type.GetClrType());
                    if (me.ProvideValue?.Parameters.Count > 0)
                    {
                        ilgen
                        .Emit(OpCodes.Ldloc, context.ContextLocal);
                    }

                    if (needProvideValueTarget)
                    {
                        ilgen
                        .Ldloc(context.ContextLocal)
                        .Ldloc(targetObjectLocal.Local)
                        .Stfld(context.RuntimeContext.PropertyTargetObject)
                        .Ldloc(context.ContextLocal);
                        EmitPropertyDescriptor();
                        ilgen
                        .Stfld(context.RuntimeContext.PropertyTargetProperty);
                    }

                    if (me.ProvideValue != null)
                    {
                        ilgen
                        .Emit(OpCodes.Call, me.ProvideValue);
                    }
                    ilgen
                    .Emit(OpCodes.Stloc, resultLocal);

                    if (needProvideValueTarget)
                    {
                        ilgen
                        .Ldloc(context.ContextLocal)
                        .Ldnull()
                        .Stfld(context.RuntimeContext.PropertyTargetObject)
                        .Ldloc(context.ContextLocal)
                        .Ldnull()
                        .Stfld(context.RuntimeContext.PropertyTargetProperty);
                    }
                }

                // At this point we have the target object at the top of the stack and markup extension result in resultLocal

                var exit = ilgen.DefineLabel();

                // This is needed for custom conversions of Binding to object
                var customTypes = context.Configuration.TypeMappings.MarkupExtensionCustomResultTypes;
                // This is needed for properties that accept Binding
                if (
                    me.Property != null &&
                    context.Configuration.TypeMappings.ShouldIgnoreMarkupExtensionCustomResultForProperty !=
                    null)
                {
                    customTypes = customTypes.Where(ct =>
                                                    !context.Configuration.TypeMappings
                                                    .ShouldIgnoreMarkupExtensionCustomResultForProperty(me.Property, ct))
                                  .ToList();
                }


                if (customTypes.Any() && !rtype.IsValueType)
                {
                    void EmitCustomActionCall()
                    {
                        EmitPropertyDescriptor();
                        codeGen
                        .Emit(OpCodes.Ldloc, context.ContextLocal)
                        .Emit(OpCodes.Ldloc, resultLocal);
                        if (rtype.IsValueType)
                        {
                            codeGen.Emit(OpCodes.Box, rtype);
                        }
                        codeGen
                        .Emit(OpCodes.Call, context.Configuration.TypeMappings.MarkupExtensionCustomResultHandler)
                        .Emit(OpCodes.Br, exit);
                    }

                    // Skip conversion attempts and call custom conversion directly
                    if (customTypes.Any(ct => ct.IsAssignableFrom(rtype)))
                    {
                        EmitCustomActionCall();
                        ilgen.MarkLabel(exit);
                        return(XamlIlNodeEmitResult.Void(1));
                    }

                    var callCustomLabel  = ilgen.DefineLabel();
                    var afterCustomLabel = ilgen.DefineLabel();
                    foreach (var ct in customTypes)
                    {
                        codeGen
                        .Ldloc(resultLocal)
                        .Isinst(ct)
                        .Brtrue(callCustomLabel);
                    }
                    ilgen
                    .Br(afterCustomLabel)
                    .MarkLabel(callCustomLabel);
                    EmitCustomActionCall();
                    ilgen.MarkLabel(afterCustomLabel);
                }


                TypeSystemHelpers.EmitConvert(context, node, rtype, ptype,
                                              lda => ilgen.Emit(lda ? OpCodes.Ldloca : OpCodes.Ldloc, resultLocal));

                // Call some method either on the target or on target's property
                if (me.Manipulation != null)
                {
                    // {target}.{Property}.{Method)(res)
                    if (me.Property != null)
                    {
                        using (var res = context.GetLocal(ptype))
                            ilgen
                            .Emit(OpCodes.Stloc, res.Local)
                            .EmitCall(me.Property.Getter)
                            .Emit(OpCodes.Ldloc, res.Local);
                    }
                    me.Manipulation.Emit(context, ilgen, true);
                }
                // Call property setter on the target
                else
                {
                    ilgen.EmitCall(me.Property.Setter);
                }

                ilgen.MarkLabel(exit);
            }

            return(XamlIlNodeEmitResult.Void(1));
        }
示例#28
0
 public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
 {
     XamlIlNeedsParentStackCache.Verify(context, this);
     return(context.Emit(Value, codeGen, Value.Type.GetClrType()));
 }
示例#29
0
 public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
 {
     context.Emit(Value, codeGen, Value.Type.GetClrType());
     context.Emit(Manipulation, codeGen, null);
     return(XamlIlNodeEmitResult.Void(0));
 }