예제 #1
0
 public SafeCast(Operand op, Type t)
 {
     _op = op;
     _t = t;
     if (t.IsValueType)
         _conditional = _op.Is(_t).Conditional(_op.Cast(_t), new DefaultValue(_t));
 }
예제 #2
0
 public SafeCast(Operand op, Type t)
 {
     _op = op;
     _t  = t;
     if (t.IsValueType)
     {
         _conditional = _op.Is(_t).Conditional(_op.Cast(_t), new DefaultValue(_t));
     }
 }
예제 #3
0
        // example based on the MSDN Versioning Sample (versioning.cs)
        public static void GenVersioning(AssemblyGen ag)
        {
            TypeGen MyBase = ag.Public.Class("MyBase");
            {
                MyBase.Public.Virtual.Method <string>("Meth1").GetCode()
                .Return("MyBase-Meth1");

                MyBase.Public.Virtual.Method <string>("Meth2").GetCode()
                .Return("MyBase-Meth2");

                MyBase.Public.Virtual.Method <string>("Meth3").GetCode()
                .Return("MyBase-Meth3");
            }

            TypeGen MyDerived = ag.Class("MyDerived", MyBase);
            {
                // Overrides the virtual method Meth1 using the override keyword:
                MyDerived.Public.Override.Method <string>("Meth1").GetCode()
                .Return("MyDerived-Meth1");

                // Explicitly hide the virtual method Meth2 using the new
                // keyword:
                // remark: new is not supported/required in RunSharp
                MyDerived.Public.Method <string>("Meth2").GetCode()
                .Return("MyDerived-Meth2");

                // Because no keyword is specified in the following declaration
                // a warning will be issued to alert the programmer that
                // the method hides the inherited member MyBase.Meth3():
                // remark: this warning is not supported in RunSharp
                MyDerived.Public.Method <string>("Meth3").GetCode()
                .Return("MyDerived-Meth3");

                CodeGen g = MyDerived.Public.Static.Void("Main");
                {
                    Operand mD = g.Local(Exp.New(MyDerived));
                    Operand mB = g.Local(mD.Cast(MyBase));

                    g.WriteLine(mB.Invoke("Meth1"));
                    g.WriteLine(mB.Invoke("Meth2"));
                    g.WriteLine(mB.Invoke("Meth3"));
                }
            }
        }
예제 #4
0
        public void CreateAssembly(string p1, string p2)
        {
            AssemblyGen ag = new AssemblyGen(_path + @"\DemoHost.exe");

            Assembly asm = Assembly.LoadFrom(_path + @"\WaveTech.Scutex.Licensing.dll");

            ag.Attribute(asm.GetType("WaveTech.Scutex.Model.LicenseAttribute"), p1, p2);

            TypeGen DemoHost = ag.Public.Class("DemoHost");

            {
                CodeGen g = DemoHost.Public.Static.Method(typeof(void), "Main");
                {
                    g.WriteLine("====================================================");
                    g.WriteLine("|                      SCUTEX                      |");
                    g.WriteLine("|         DEMO HOST FOR TRIAL DIALOG TESTING       |");
                    g.WriteLine("====================================================");
                    g.WriteLine("");
                    g.WriteLine("");
                    g.WriteLine("Your trial dialog or form should display in a few seconds...");

                    Operand licensingManager = g.Local(Exp.New(asm.GetType("WaveTech.Scutex.Licensing.LicensingManager")));

                    Operand value = g.Local(asm.GetType("WaveTech.Scutex.Model.InteractionModes"));

                    Operand value2 = g.Local(typeof(System.Int32));
                    g.Assign(value2, 1);

                    g.Assign(value, value2.Cast(asm.GetType("WaveTech.Scutex.Model.InteractionModes")));

                    Operand scutexLicensing = g.Local(asm.GetType("WaveTech.Scutex.Model.ScutexLicense"));

                    g.Assign(scutexLicensing, licensingManager.Invoke("Validate", value));

                    g.Return();
                }
            }

            ag.Save();
            asm = null;
        }
예제 #5
0
        // example based on the MSDN User-Defined Conversions Sample (structconversion.cs)
        public static void GenStructConversion(AssemblyGen ag)
        {
            TypeGen BinaryNumeral = ag.Struct("BinaryNumeral");
            {
                FieldGen value = BinaryNumeral.Private.Field <int>("value");

                CodeGen g = BinaryNumeral.Public.Constructor().Parameter <int>("value");
                {
                    g.Assign(value, g.Arg("value"));
                }

                g = BinaryNumeral.Public.ImplicitConversionFrom <int>();
                {
                    g.Return(Exp.New(BinaryNumeral, g.Arg("value")));
                }

                g = BinaryNumeral.Public.ImplicitConversionTo <string>();
                {
                    g.Return("Conversion not yet implemented");
                }

                g = BinaryNumeral.Public.ExplicitConversionTo <int>("binary");
                {
                    g.Return(g.Arg("binary").Field("value"));
                }
            }

            TypeGen RomanNumeral = ag.Struct("RomanNumeral");
            {
                FieldGen value = RomanNumeral.Private.Field <int>("value");

                CodeGen g = RomanNumeral.Public.Constructor().Parameter <int>("value");
                {
                    g.Assign(value, g.Arg("value"));
                }

                g = RomanNumeral.Public.ImplicitConversionFrom <int>();
                {
                    g.Return(Exp.New(RomanNumeral, g.Arg("value")));
                }

                g = RomanNumeral.Public.ImplicitConversionFrom(BinaryNumeral, "binary");
                {
                    g.Return(Exp.New(RomanNumeral, g.Arg("binary").Cast <int>()));
                }

                g = RomanNumeral.Public.ExplicitConversionTo <int>("roman");
                {
                    g.Return(g.Arg("roman").Field("value"));
                }

                g = RomanNumeral.Public.ImplicitConversionTo <string>();
                {
                    g.Return("Conversion not yet implemented");
                }
            }

            TypeGen Test = ag.Class("Test");
            {
                CodeGen g = Test.Public.Static.Void("Main");
                {
                    Operand roman = g.Local(RomanNumeral);
                    g.Assign(roman, 10);
                    Operand binary = g.Local(BinaryNumeral);
                    // Perform a conversion from a RomanNumeral to a
                    // BinaryNumeral:
                    g.Assign(binary, roman.Cast <int>().Cast(BinaryNumeral));
                    // Performs a conversion from a BinaryNumeral to a RomanNumeral.
                    // No cast is required:
                    g.Assign(roman, binary);
                    g.WriteLine(binary.Cast <int>());
                    g.WriteLine(binary);
                }
            }
        }
예제 #6
0
        // example based on the MSDN User-Defined Conversions Sample (conversion.cs)
        public static void GenConversion(AssemblyGen ag)
        {
            TypeGen RomanNumeral = ag.Struct("RomanNumeral");
            {
                FieldGen value = RomanNumeral.Private.Field <int>("value");

                CodeGen g = RomanNumeral.Public.Constructor().Parameter <int>("value");
                {
                    g.Assign(value, g.Arg("value"));
                }

                // Declare a conversion from an int to a RomanNumeral. Note the
                // the use of the operator keyword. This is a conversion
                // operator named RomanNumeral:
                g = RomanNumeral.Public.ImplicitConversionFrom <int>();
                {
                    // Note that because RomanNumeral is declared as a struct,
                    // calling new on the struct merely calls the constructor
                    // rather than allocating an object on the heap:
                    g.Return(Exp.New(RomanNumeral, g.Arg("value")));
                }

                // Declare an explicit conversion from a RomanNumeral to an int:
                g = RomanNumeral.Public.ExplicitConversionTo <int>("roman");
                {
                    g.Return(g.Arg("roman").Field("value"));
                }

                // Declare an implicit conversion from a RomanNumeral to
                // a string:
                g = RomanNumeral.Public.ImplicitConversionTo <string>();
                {
                    g.Return("Conversion not yet implemented");
                }
            }

            TypeGen Test = ag.Class("Test");
            {
                CodeGen g = Test.Public.Static.Void("Main");
                {
                    Operand numeral = g.Local(RomanNumeral);

                    g.Assign(numeral, 10);

                    // Call the explicit conversion from numeral to int. Because it is
                    // an explicit conversion, a cast must be used:
                    g.WriteLine(numeral.Cast <int>());

                    // Call the implicit conversion to string. Because there is no
                    // cast, the implicit conversion to string is the only
                    // conversion that is considered:
                    g.WriteLine(numeral);

                    // Call the explicit conversion from numeral to int and
                    // then the explicit conversion from int to short:
                    Operand s = g.Local(numeral.Cast <short>());

                    g.WriteLine(s);
                }
            }
        }
예제 #7
0
        // example based on the MSDN Explicit Interface Implementation Sample (explicit.cs)
        public static void GenExplicit2(AssemblyGen ag)
        {
            // Declare the English units interface:
            TypeGen IEnglishDimensions = ag.Interface("IEnglishDimensions");
            {
                IEnglishDimensions.Method(typeof(float), "Length");
                IEnglishDimensions.Method(typeof(float), "Width");
            }

            // Declare the metric units interface:
            TypeGen IMetricDimensions = ag.Interface("IMetricDimensions");
            {
                IMetricDimensions.Method(typeof(float), "Length");
                IMetricDimensions.Method(typeof(float), "Width");
            }

            // Declare the "Box" class that implements the two interfaces:
            // IEnglishDimensions and IMetricDimensions:
            TypeGen Box = ag.Class("Box", typeof(object), IEnglishDimensions, IMetricDimensions);
            {
                FieldGen lengthInches = Box.Field(typeof(float), "lengthInches");
                FieldGen widthInches  = Box.Field(typeof(float), "widthInches");

                CodeGen g = Box.Public.Constructor()
                            .Parameter(typeof(float), "length")
                            .Parameter(typeof(float), "width")
                ;
                {
                    g.Assign(lengthInches, g.Arg("length"));
                    g.Assign(widthInches, g.Arg("width"));
                }
                // Explicitly implement the members of IEnglishDimensions:
                g = Box.MethodImplementation(IEnglishDimensions, typeof(float), "Length");
                {
                    g.Return(lengthInches);
                }
                g = Box.MethodImplementation(IEnglishDimensions, typeof(float), "Width");
                {
                    g.Return(widthInches);
                }
                // Explicitly implement the members of IMetricDimensions:
                g = Box.MethodImplementation(IMetricDimensions, typeof(float), "Length");
                {
                    g.Return(lengthInches * 2.54f);
                }
                g = Box.MethodImplementation(IMetricDimensions, typeof(float), "Width");
                {
                    g.Return(widthInches * 2.54f);
                }
                g = Box.Public.Static.Method(typeof(void), "Main");
                {
                    // Declare a class instance "myBox":
                    Operand myBox = g.Local(Exp.New(Box, 30.0f, 20.0f));
                    // Declare an instance of the English units interface:
                    Operand eDimensions = g.Local(myBox.Cast(IEnglishDimensions));
                    // Declare an instance of the metric units interface:
                    Operand mDimensions = g.Local(myBox.Cast(IMetricDimensions));
                    // Print dimensions in English units:
                    g.WriteLine("Length(in): {0}", eDimensions.Invoke("Length"));
                    g.WriteLine("Width (in): {0}", eDimensions.Invoke("Width"));
                    // Print dimensions in metric units:
                    g.WriteLine("Length(cm): {0}", mDimensions.Invoke("Length"));
                    g.WriteLine("Width (cm): {0}", mDimensions.Invoke("Width"));
                }
            }
        }
        /// <summary>
        ///   Create a wrapper class for a generic interface with more general type parameters than the wrapped interface.
        ///   Downcasts to the correct more specific type are generated where necessary.
        ///   This of course breaks type safety, and only calls to the class with the correct orginal types will work.
        ///   Incorrect calls will throw <see cref = "InvalidCastException" />.
        /// </summary>
        /// <remarks>
        ///   This is useful during reflection, when you don't want to know about specific types, but you can guarantee
        ///   that a certain call will always be done with objects of the correct type.
        ///   TODO: This non-generic method is only needed since RunSharp can't call generic methods, needed to generate wrappers recursively.
        ///   TODO: Possibly Castle DynamicProxy could replace this if it allows creating 'non-matching' proxies and thus support the downcasting.
        /// </remarks>
        /// <param name = "typeToCreate">The less-specific generic type of the wrapper which will be generated.</param>
        /// <param name = "o">The object to wrap, which should implement the desired interface, with arbitrary type parameters.</param>
        /// <returns>An instance of the specified type which wraps the given object.</returns>
        public static object CreateGenericInterfaceWrapper(Type typeToCreate, object o)
        {
            Contract.Requires(o.GetType().IsOfGenericType(typeToCreate.GetGenericTypeDefinition()));
            Contract.Requires(typeToCreate.IsInterface);

            Type typeToCreateGeneric = typeToCreate.GetGenericTypeDefinition();
            Type innerType           = o.GetType();
            Type innerMatchingType   = innerType.GetMatchingGenericType(typeToCreateGeneric);

            // Implement passed type and redirect all public calls to inner instance.
            var     assembly = new AssemblyGen("Whathecode.System.RunSharp");
            TypeGen type     = assembly.Public.Class("Wrapped" + typeToCreate.Name, typeof(object), typeToCreate);
            {
                const string inner = "inner";

                FieldGen innerInstance  = type.Private.Field(innerType, "_innerInstance");
                FieldGen returnCached   = type.Private.Field(typeof(Dictionary <int, object>), "_returnCached");
                FieldGen returnWrappers = type.Private.Field(typeof(Dictionary <int, object>), "_returnWrappers");

                // Create constructor which takes the wrapped instance as an argument.
                ConstructorGen constructor = type.Public.Constructor();
                {
                    constructor.Parameter(innerType, inner);

                    CodeGen code = constructor.GetCode();
                    {
                        code.Assign(innerInstance, code.Arg(inner));
                        code.Assign(returnCached, Exp.New(typeof(Dictionary <int, object>)));
                        code.Assign(returnWrappers, Exp.New(typeof(Dictionary <int, object>)));
                    }
                }

                // Create methods.
                int          methodCount     = 0;
                MethodInfo[] innerMethods    = innerMatchingType.GetFlattenedInterfaceMethods(ReflectionHelper.FlattenedInstanceMembers).ToArray();
                MethodInfo[] toCreateMethods = typeToCreate.GetFlattenedInterfaceMethods(ReflectionHelper.FlattenedInstanceMembers).ToArray();
                MethodInfo[] genericMethods  = typeToCreateGeneric.GetFlattenedInterfaceMethods(ReflectionHelper.FlattenedInstanceMembers).ToArray();
                foreach (var method in innerMethods
                         .Zip(toCreateMethods, genericMethods,
                              (matching, toCreate, generic) => new
                {
                    Id = methodCount++,
                    Matching = matching,
                    ToCreate = toCreate,
                    Generic = generic
                })
                         .Where(z => z.Matching.IsPublic || z.Matching.IsFamily))
                {
                    // TODO: Not quite certain why override is required for extended interfaces (DeclaringType != typeTocreate),
                    //       but this seems to work.
                    MethodInfo toCreate  = method.ToCreate;
                    MethodGen  methodGen = toCreate.DeclaringType == typeToCreate
                                                ? type.MethodImplementation(typeToCreate, toCreate.ReturnType, toCreate.Name)
                                                : type.Public.Override.Method(toCreate.ReturnType, toCreate.Name);

                    {
                        ParameterInfo[] toCreateParameters = toCreate.GetParameters();
                        var             parameters         = toCreateParameters
                                                             .Select(p =>
                        {
                            var info = methodGen.BeginParameter(p.ParameterType, p.Name);
                            info.End();
                            return(info);
                        }).ToArray();

                        CodeGen code = methodGen.GetCode();
                        {
                            // Cast arguments to the type of the inner instance.
                            Operand[] args     = parameters.Select(p => code.Arg(p.Name)).ToArray();
                            Operand[] castArgs = { };
                            if (args.Length > 0)
                            {
                                Type[] parameterTypes = method.Matching.GetParameters().Select(p => p.ParameterType).ToArray();
                                // TODO: When searching for generic methods, GetMethod returns null. http://stackoverflow.com/questions/4035719/getmethod-for-generic-method
                                //       Even when the correct method is found through custom filtering, RunSharp does not seem to be able to create generic methods yet.
                                MethodInfo methodToCall
                                         = innerType.GetMethod(toCreate.Name, ReflectionHelper.FlattenedInstanceMembers, parameterTypes);
                                castArgs = methodToCall.GetParameters()
                                           .Select((p, index) => args[index].Cast(typeof(object)).Cast(p.ParameterType)).ToArray();
                            }

                            // Call inner instance and return value when needed.
                            if (toCreate.ReturnType != typeof(void))
                            {
                                Operand result = innerInstance.Invoke(toCreate.Name, castArgs);

                                // Wrappers will recursively need to be created for generic return types.
                                Type genericReturnType = method.Generic.ReturnType;
                                if (genericReturnType.IsGenericType && genericReturnType.ContainsGenericParameters && genericReturnType.IsInterface)
                                {
                                    // Check whether a new result is returned.
                                    Operand innerCached = code.Local(typeof(object));
                                    code.If(returnCached.Invoke("TryGetValue", method.Id, innerCached.Ref()));
                                    {
                                        code.If((innerCached == result).LogicalNot());
                                        {
                                            code.Invoke(returnWrappers, "Remove", method.Id);
                                            code.Invoke(returnCached, "Remove", method.Id);
                                            code.Invoke(returnCached, "Add", method.Id, result);
                                        }
                                        code.End();
                                    }
                                    code.Else();
                                    {
                                        code.Invoke(returnCached, "Add", method.Id, result);
                                    }
                                    code.End();

                                    // Check whether a wrapper needs to be generated.
                                    Operand wrappedCached = code.Local(typeof(object));
                                    code.If(returnWrappers.Invoke("TryGetValue", method.Id, wrappedCached.Ref()).LogicalNot());
                                    {
                                        Operand proxied = Static.Invoke(typeof(Proxy), "CreateGenericInterfaceWrapper", toCreate.ReturnType, result);
                                        code.Assign(wrappedCached, proxied);
                                        code.Invoke(returnWrappers, "Add", method.Id, wrappedCached);
                                    }
                                    code.End();
                                    code.Return(wrappedCached.Cast(toCreate.ReturnType));
                                }
                                else
                                {
                                    // A simple cast will work.
                                    // TODO: Throw proper exception when this is known to fail. E.g. generic type which is not an interface?
                                    code.Return(result.Cast(toCreate.ReturnType));
                                }
                            }
                            else
                            {
                                code.Invoke(innerInstance, toCreate.Name, castArgs);
                            }
                        }
                    }
                }
            }
            Type wrapperType = type.GetCompletedType(true);

            return(Activator.CreateInstance(wrapperType, new[] { o }));
        }
예제 #9
0
        protected override void EmitRead(AqlaSerializer.Compiler.CompilerContext ctx, AqlaSerializer.Compiler.Local valueFrom)
        {
            var g = ctx.G;

            using (ctx.StartDebugBlockAuto(this))
                using (Compiler.Local value = ctx.GetLocalWithValueForEmitRead(this, valueFrom))
                    using (Compiler.Local oldValueForSubTypeHelpers = ctx.Local(value.Type))
                        using (Compiler.Local createdNew = ctx.Local(typeof(bool), true))
                        {
                            bool asList = IsList && !SuppressIList;

                            // can't call clear? => create new!
                            bool forceNewInstance = !AppendToCollection && !asList;

                            ListHelpers.EmitRead(
                                ctx.G,
                                (onSuccess, onFail) =>
                            {
                                using (ctx.StartDebugBlockAuto(this, "readNextMeta"))
                                {
                                    if (_metaType != null)
                                    {
                                        g.If(g.ReaderFunc.TryReadFieldHeader_bool(ListHelpers.FieldSubtype));
                                        {
                                            using (ctx.StartDebugBlockAuto(this, "subtype handler"))
                                            {
                                                g.Assign(oldValueForSubTypeHelpers, forceNewInstance ? null : value.AsOperand);
                                                _subTypeHelpers.EmitTryRead(
                                                    g,
                                                    oldValueForSubTypeHelpers,
                                                    _metaType,
                                                    r =>
                                                {
                                                    using (ctx.StartDebugBlockAuto(this, "subtype handler - read"))
                                                    {
                                                        if (r != null)
                                                        {
                                                            ctx.MarkDebug("// creating list subtype");
                                                            r.Serializer.EmitCreateInstance(ctx);
                                                            ctx.StoreValue(value);
                                                            g.Assign(createdNew, true);
                                                        }
                                                    }
                                                });
                                            }
                                            onSuccess();
                                        }
                                        g.Else();
                                        {
                                            onFail();
                                        }
                                        g.End();
                                    }
                                    else
                                    {
                                        onFail();
                                    }
                                }
                            }
                                ,
                                () =>
                            {
                                using (ctx.StartDebugBlockAuto(this, "prepareInstance"))
                                {
                                    var createInstanceCondition = value.AsOperand == null;

                                    // also create new if should clear existing instance on not lists
                                    if (forceNewInstance)
                                    {
                                        createInstanceCondition = createInstanceCondition || !createdNew.AsOperand;
                                    }

                                    g.If(createInstanceCondition);
                                    {
                                        ctx.MarkDebug("// creating new list");
                                        EmitCreateInstance(ctx);
                                        ctx.StoreValue(value);
                                        g.Reader.NoteObject(value);
                                    }
                                    g.Else();
                                    {
                                        g.If(!createdNew.AsOperand);
                                        {
                                            g.Reader.NoteObject(value);

                                            if (asList && !AppendToCollection)
                                            {
                                                ctx.MarkDebug("// clearing existing list");
                                                // ReSharper disable once PossibleNullReferenceException
                                                g.Invoke(value, "Clear");
                                            }
                                        }
                                        g.End();
                                    }
                                    g.End();
                                }
                            },
                                v =>
                            {
                                // TODO do null checks without allowing user == operators!
                                using (ctx.StartDebugBlockAuto(this, "add"))
                                {
#if DEBUG_COMPILE_2
                                    g.If(v.AsOperand != null);
                                    {
                                        g.ctx.MarkDebug("adding " + v.AsOperand.InvokeToString());
                                    }
                                    g.End();
#endif
                                    if (asList)
                                    {
                                        ctx.MarkDebug("// using Add method");
                                        Operand instance = value;
                                        if (_add != null && !Helpers.IsAssignableFrom(_add.DeclaringType, ExpectedType))
                                        {
                                            instance = instance.Cast(_add.DeclaringType); // TODO optimize to local
                                        }
                                        g.Invoke(instance, "Add", v);
                                    }
                                    else
                                    {
                                        ctx.MarkDebug("// using add delegate");
                                        ctx.LoadAddress(value, ExpectedType);
                                        if (!Helpers.IsAssignableFrom(_add.DeclaringType, ExpectedType))
                                        {
                                            ctx.Cast(_add.DeclaringType);
                                        }
                                        ctx.LoadValue(v);
                                        ctx.EmitCall(this._add);
                                    }
                                }
                            }
                                );
                            if (EmitReadReturnsValue)
                            {
                                ctx.MarkDebug("returning list");
                                ctx.LoadValue(value);
                            }
                        }
        }