Esempio n. 1
0
        static Action <string, string> MakeNewProjectDialogMethod()
        {
            var newProjInfoType = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypesOrNone()).FirstOrDefault(t => t.Name == "VSNEWPROJECTDLGINFO");

            var sDialogService   = Microsoft.VisualStudio.Shell.ServiceProvider.GlobalProvider.GetService(typeof(SVsDialogService));
            var rawDialogService = (SVsDialogService)sDialogService;

            var hierarchyArg = Expression.Parameter(typeof(string), "hierarchy");
            var nameArg      = Expression.Parameter(typeof(string), "name");

            var newProjInfoVar = Expression.Variable(newProjInfoType, "newProjInfo");
            var locVar         = Expression.Variable(typeof(string), "locVar");
            var expr           = Expression.Lambda <Action <string, string> >(
                Expression.Block(
                    new[] { newProjInfoVar, locVar },
                    Expression.Assign(newProjInfoVar, Expression.New(newProjInfoType)),
                    Expression.Assign(Expression.Field(newProjInfoVar, newProjInfoType.GetField("pwzExpand")), hierarchyArg),
                    Expression.Assign(Expression.Field(newProjInfoVar, newProjInfoType.GetField("pwzSelect")), nameArg),
                    Expression.Call(Expression.Constant(rawDialogService, typeof(SVsDialogService)), rawDialogService.GetType().GetMethod("InvokeDialog"), newProjInfoVar, locVar)
                    ),
                new[] { hierarchyArg, nameArg }
                );

            var compiledExpr = expr.Compile();

            return(compiledExpr);
        }
        Expr Logical(DynamicMetaObject left, DynamicMetaObject right)
        {
            // Assign left operand to a temp variable for single evaluation
            var tempLeft = Expr.Variable(left.LimitType);

            var  compareExpr = (Expr)tempLeft;
            Expr ifExpr      = null;

            switch (Operation)
            {
            case ExprType.AndAlso:
                if (left.LimitType != typeof(bool))
                {
                    compareExpr = Expr.Equal(tempLeft, Expr.Constant(null));
                }

                ifExpr = Expr.IfThenElse(compareExpr, right.Expression, tempLeft);
                break;

            case ExprType.OrElse:
                if (left.LimitType != typeof(bool))
                {
                    compareExpr = Expr.NotEqual(tempLeft, Expr.Constant(null));
                }

                ifExpr = Expr.IfThenElse(compareExpr, tempLeft, right.Expression);
                break;
            }

            return
                (Expr.Block(
                     new[] { tempLeft },
                     Expr.Assign(tempLeft, left.Expression),
                     ifExpr));
        }
Esempio n. 3
0
        private static Action <Popup, int, bool> CreatePopupCacheValidSetter()
        {
            var cacheValidField =
                typeof(Popup).GetField("_cacheValid", BindingFlags.Instance | BindingFlags.NonPublic);

            if (cacheValidField == null || cacheValidField.FieldType != typeof(BitVector32))
            {
                return (_, _, _) => { }
            }
            ;

            var popup         = Expression.Parameter(typeof(Popup));
            var flagParameter = Expression.Parameter(typeof(int));
            var value         = Expression.Parameter(typeof(bool));
            var indexer       = typeof(BitVector32).GetProperty("Item", new[] { typeof(int) });

            var lambda = Expression.Lambda <Action <Popup, int, bool> >(
                Expression.Assign(
                    Expression.MakeIndex(
                        Expression.Field(popup, cacheValidField),
                        indexer,
                        new[] { flagParameter }),
                    value),
                popup, flagParameter, value);

            return(lambda.Compile());
        }
    }
Esempio n. 4
0
            public Updater(Type type)
            {
                var props = from p in type.GetProperties()
                            let bas                 = p.GetCustomAttributes(typeof(BrowsableAttribute), true)
                                              let b = bas.FirstOrDefault() as BrowsableAttribute
                                                      where p.CanWrite && (b == null || b.Browsable)
                                                      select p;

                var convert = typeof(Updater).GetMethod("FromString", BindingFlags.Static | BindingFlags.NonPublic);

                foreach (var p in props)
                {
                    var instance = X.Parameter(typeof(object));
                    var value    = X.Parameter(typeof(string));

                    var lambda = X.Lambda <Action <object, string> >(
                        X.Assign(
                            X.Property(
                                X.Convert(instance, type),
                                p
                                ),
                            X.Convert(
                                X.Call(convert, value, X.Constant(p.PropertyType)),
                                p.PropertyType
                                )
                            ),
                        instance, value);

                    cache[p.Name] = lambda.Compile();
                }
            }
Esempio n. 5
0
        protected override LinqExpression BuildLinqExpression()
        {
            var leftOperandExpression  = LeftNode.GetEvaluationLinqExpression();
            var rightOperandExpression = RightNode.GetEvaluationLinqExpression();

            var variableLeft            = LinqExpression.Variable(typeof(object));
            var variableEvaluatedResult = LinqExpression.Variable(typeof(object));

            return(LinqExpression.Block(
                       typeof(object),
                       new[] { variableLeft, variableEvaluatedResult },
                       LinqExpressionHelper.ExpressionCallThrowIfCancellationRequested,
                       LinqExpression.Assign(variableLeft, leftOperandExpression),
                       LinqExpression.IfThen(
                           LinqExpression.Not(
                               LinqExpression.Call(
                                   LinqExpression.Constant(Operator),
                                   LinqExpressionHelper.MethodInfoBinaryOperatorEvaluateLhs,
                                   LinqExpressionHelper.ExpressionParameterContext,
                                   variableLeft,
                                   variableEvaluatedResult)),
                           LinqExpression.Assign(
                               variableEvaluatedResult,
                               LinqExpression.Call(
                                   LinqExpression.Constant(Operator),
                                   LinqExpressionHelper.MethodInfoBinaryOperatorEvaluate,
                                   LinqExpressionHelper.ExpressionParameterContext,
                                   variableLeft,
                                   rightOperandExpression))),
                       variableEvaluatedResult));
        }
Esempio n. 6
0
 static void mapField(string typeName, FieldInfo field, Data data)
 {
     if (!field.IsStatic)
     {
         return;
     }
     if (mapType == ExpressionMode)
     {
         var get = Dlr.Lambda(Dlr.Field(null, field)).Compile();
         data.set(typeName + '.' + field.Name, get);
         if (!field.IsInitOnly)
         {
             var par = Dlr.Parameter(field.FieldType);
             var set = Dlr.Lambda(Dlr.Assign(Dlr.Field(null, field), par), par).Compile();
             data.set(typeName + '.' + field.Name + ".set", set);
         }
     }
     else if (mapType == ReflectionMode)
     {
         var get = (Func <dynamic>)(() => field.GetValue(null));
         var set = (Action <dynamic>)((n) => field.SetValue(null, n));
         data.set(typeName + '.' + field.Name, get);
         data.set(typeName + '.' + field.Name + ".set", set);
     }
 }
Esempio n. 7
0
        /// <summary>
        ///   returns the assignation expression that should be executed before this variable is used
        /// </summary>
        /// <returns></returns>
        protected internal override MAst Transform()
        {
            // return an assignment expression to the parameter that should be called
            // before any uses of the variable

            MAst valueExpression = Value.Transform();

            return(MAst.Assign(Pointer, valueExpression));
        }
Esempio n. 8
0
        public static tfloat PowSub(tfloat bas, tfloat exp)
        {
            var val = VFloat();

            return(Ex.Block(new[] { val },
                            Ex.Assign(val, bas),
                            Pow(val, exp).Sub(val)
                            ));
        }
Esempio n. 9
0
            static Expr GenerateAddFlagsGuts(ExprParam paramV, ExprParam paramF)
            {
                var param_v_member = Expr.PropertyOrField(paramV, EnumUtils.kMemberName);               // value.value__
                var param_f_member = Expr.PropertyOrField(paramF, EnumUtils.kMemberName);               // flags.value__

                var or = Expr.Or(param_v_member, param_f_member);

                return(Expr.Assign(param_v_member, or));
                //return Expr.OrAssign(param_v_member, param_f_member);					// value.value__ |= flags.value__
            }
Esempio n. 10
0
        /// <summary>
        /// Return true iff the first argument is strictly between the second and third.
        /// </summary>
        /// <param name="b">First BPY function</param>
        /// <param name="br1">Lower bound BPY function</param>
        /// <param name="br2">Upper bound BPY function</param>
        /// <returns></returns>
        public static tbool In(tfloat b, tfloat br1, tfloat br2)
        {
            var f = ExUtils.VFloat();

            return(Ex.Block(new[] { f },
                            Ex.Assign(f, b),
                            Ex.AndAlso(
                                Ex.GreaterThan(f, br1),
                                Ex.LessThan(f, br2)
                                )
                            ));
        }
Esempio n. 11
0
            static Expr GenerateRemoveFlagsGuts(ExprParam paramV, ExprParam paramF)
            {
                var param_v_member = Expr.PropertyOrField(paramV, EnumUtils.kMemberName);               // value.value__
                var param_f_member = Expr.PropertyOrField(paramF, EnumUtils.kMemberName);               // flags.value__

                var f_complement = Expr.Not(param_f_member);                                            // ~flags.value__

                var and = Expr.And(param_v_member, f_complement);

                return(Expr.Assign(param_v_member, and));
                //return Expr.AndAssign(param_v_member, f_complement);					// value.value__ &= ~flags.value__
            }
Esempio n. 12
0
        Function ParseFunc(Expression def, bool has_self = false)
        {
            string name = def[0].Value;
            var    ps   = ParseParameters(def[1].Subset, omitFirstParameter: has_self);

            /* write IL */
            LocalBuilder loc = Local;

            Local = new LocalBuilder();

            var IL = new List <Exp>();

            ret.Push(Exp.Label(typeof(Object)));

            // load parameters

            var arg = Exp.Parameter(typeof(Args), "arg");

            if (has_self)
            {
                var self = Exp.Variable(typeof(Object), "self");
                Local.Add(self);
                IL.Add(Exp.Assign(self, Exp.Field(arg, "self")));
            }

            ParamInfo pi;

            for (int i = 0; i < ps.Info.Length; i++)
            {
                pi = ps.Info[i];
                var p = Exp.Variable(typeof(Object), pi.Name.str);
                Local.Add(p);
                IL.Add(Exp.Assign(p, Exp.Property(arg, "Item", Exp.Constant(i))));
            }

            PushBlock(def.Body, IL);

            // add the return label target
            IL.Add(Exp.Label(ret.Pop(), NoneExp));

            var body = Exp.Block(Local.Variables, IL);

            Local = loc;
            var func = Exp.Lambda <Func <Args, Object> >(body, arg).Compile();

            return(new Function
            {
                Name = name,
                Parameters = ps,
                handler = func
            });
        }
Esempio n. 13
0
        private static NodeVisitFunction BuildMethodVisitor(MethodInfo method, out Type parameterType)
        {
            var declaringtype = method.DeclaringType;

            if (declaringtype == null)
            {
                throw new InvalidOperationException(string.Format("No declaring type for method [{0}]", method.Name));
            }

            // Throws an exception if parammeters.Count != 1
            if (method.GetParameters().Length != 1)
            {
                throw new InvalidOperationException(
                          string.Format("Invalid number of parameters [{0}] for visit method [{1}] for type [{2}]. One parameter is expected", method.GetParameters().Length, method.Name, declaringtype.FullName));
            }

            parameterType = method.GetParameters()[0].ParameterType;
            if (!parameterType.IsInterface && !typeof(Node).IsAssignableFrom(parameterType))
            {
                throw new InvalidOperationException(
                          string.Format("Invalid type parameter [{0}] for visit method [{1}] for type [{2}]. Parameter must inherit from Node", parameterType, method.Name, declaringtype.FullName));
            }

            var thisParameter    = LinqExpression.Parameter(typeof(VisitorBase), "this");
            var nodeParameter    = LinqExpression.Parameter(typeof(object), "node");
            var thisCastVariable = LinqExpression.Variable(declaringtype, "thisCast");

            var statements = new List <LinqExpression>
            {
                LinqExpression.Assign(thisCastVariable, LinqExpression.Convert(thisParameter, declaringtype))
            };

            var callVisitMethod = LinqExpression.Call(thisCastVariable, method, LinqExpression.Convert(nodeParameter, parameterType));

            if (typeof(void) == method.ReturnType)
            {
                statements.Add(callVisitMethod);
                statements.Add(nodeParameter);
            }
            else
            {
                statements.Add(callVisitMethod);
            }

            var block = LinqExpression.Block(new[] { thisCastVariable }, statements);

            var lambda = LinqExpression.Lambda <NodeVisitFunction>(block, thisParameter, nodeParameter);

            return(lambda.Compile());
        }
Esempio n. 14
0
        public static Expr ConvertToNumberAndCheck(Context context, Expr expression, string format, params object[] args)
        {
            var numberVar    = Expr.Variable(typeof(double));
            var assignNumber = Expr.Assign(numberVar, ConvertToNumber(context, expression));

            return(Expr.Block(
                       new[] { numberVar },
                       assignNumber,
                       Expr.Condition(
                           Expr.Invoke(
                               Expr.Constant((Func <double, bool>)Double.IsNaN), numberVar),
                           Expr.Block(
                               Expr.Throw(Expr.New(MemberInfos.NewRuntimeException, Expr.Constant(format), Expr.Constant(args))),
                               Expr.Constant(Double.NaN)),
                           numberVar)));
        }
Esempio n. 15
0
            static ModifyByRefDelegate GenerateAddFlagsMethodByRef()
            {
                //////////////////////////////////////////////////////////////////////////
                // Define the generated method's parameters
                var param_v = GenerateParamValue(true);
                var param_f = GenerateParamFlags();

                //////////////////////////////////////////////////////////////////////////
                // value = value | flags
                var assign = Expr.Assign(param_v, GenerateAddFlagsGuts(param_v, param_f));

                //////////////////////////////////////////////////////////////////////////
                // Generate a method based on the expression tree we've built
                var lambda = Expr.Lambda <ModifyByRefDelegate>(assign, param_v, param_f);

                return(lambda.Compile());
            }
Esempio n. 16
0
            public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes)
            {
                var valueVar = Expr.Variable(typeof(object));

                var getValue = Expr.Call(
                    Expr.Convert(Expression, typeof(LuaTable)),
                    MemberInfos.LuaTableGetValue,
                    Expr.Convert(indexes[0].Expression, typeof(object)));
                var valueAssign = Expr.Assign(valueVar, getValue);

                var expression = Expr.Block(
                    valueVar,
                    Expr.Condition(
                        Expr.Equal(valueVar, Expr.Constant(null)),
                        MetamethodFallbacks.Index(null, this, indexes),
                        valueVar));

                return(new DynamicMetaObject(expression, RuntimeHelpers.MergeTypeRestrictions(this)));
            }
        Expr FallbackIfNumberIsNan(Expr numExpr)
        {
            // If we have performed a string to number conversion check that conversion went well by checking
            // number for NaN. If conversion failed do metatable fallback. Also assign to temp variable for single evaluation.

            var numVar = Expr.Variable(typeof(double));

            var expr = Expr.IfThenElse(
                Expr.Invoke(Expr.Constant((Func <double, bool>)Double.IsNaN), numVar),
                Expr.Invoke(
                    Expr.Constant((Func <Context, object, object>)LuaOps.UnaryMinusMetamethod),
                    Expr.Constant(context),
                    Expr.Constant(Operation),
                    Expr.Convert(numExpr, typeof(object))),
                numVar);

            return(Expr.Block(
                       new[] { numVar },
                       Expr.Assign(numVar, numExpr),
                       expr));
        }
        Expr FallbackIfNumberIsNan(Expr conversionResult, DynamicMetaObject left, DynamicMetaObject right)
        {
            // If we have performed a string to number conversion check that conversion went well by checking
            // number for NaN. If conversion failed do metatable fallback. Also assign to temp variable for single evaluation.

            var conversionVar = Expr.Variable(typeof(double));

            var expr = Expr.Condition(
                Expr.Invoke(Expr.Constant((Func <double, bool>)Double.IsNaN), conversionVar),
                Expr.Invoke(
                    Expr.Constant((Func <Context, ExprType, object, object, object>)LuaOps.NumericMetamethod),
                    Expr.Constant(context),
                    Expr.Constant(Operation),
                    Expr.Convert(left.Expression, typeof(object)),
                    Expr.Convert(right.Expression, typeof(object))),
                Expr.Convert(conversionVar, typeof(object)));

            return(Expr.Block(
                       new[] { conversionVar },
                       Expr.Assign(conversionVar, conversionResult),
                       expr));
        }
Esempio n. 19
0
        // Use homotopy method with newton's method to find a solution for F(x) = 0.
        private static List <Arrow> NSolve(List <Expression> F, List <Arrow> x0, double Epsilon, int MaxIterations)
        {
            int M = F.Count;
            int N = x0.Count;

            // Compute JxF, the Jacobian of F.
            List <Dictionary <Expression, Expression> > JxF = Jacobian(F, x0.Select(i => i.Left)).ToList();

            // Define a function to evaluate JxH(x), where H = F(x) - s*F(x0).
            CodeGen code = new CodeGen();

            ParamExpr _JxH = code.Decl <double[, ]>(Scope.Parameter, "JxH");
            ParamExpr _x0  = code.Decl <double[]>(Scope.Parameter, "x0");
            ParamExpr _s   = code.Decl <double>(Scope.Parameter, "s");

            // Load x_j from the input array and add them to the map.
            for (int j = 0; j < N; ++j)
            {
                code.DeclInit(x0[j].Left, LinqExpr.ArrayAccess(_x0, LinqExpr.Constant(j)));
            }

            LinqExpr error = code.Decl <double>("error");

            // Compile the expressions to assign JxH
            for (int i = 0; i < M; ++i)
            {
                LinqExpr _i = LinqExpr.Constant(i);
                for (int j = 0; j < N; ++j)
                {
                    code.Add(LinqExpr.Assign(
                                 LinqExpr.ArrayAccess(_JxH, _i, LinqExpr.Constant(j)),
                                 code.Compile(JxF[i][x0[j].Left])));
                }
                // e = F(x) - s*F(x0)
                LinqExpr e = code.DeclInit <double>("e", LinqExpr.Subtract(code.Compile(F[i]), LinqExpr.Multiply(LinqExpr.Constant((double)F[i].Evaluate(x0)), _s)));
                code.Add(LinqExpr.Assign(LinqExpr.ArrayAccess(_JxH, _i, LinqExpr.Constant(N)), e));
                // error += e * e
                code.Add(LinqExpr.AddAssign(error, LinqExpr.Multiply(e, e)));
            }

            // return error
            code.Return(error);

            Func <double[, ], double[], double, double> JxH = code.Build <Func <double[, ], double[], double, double> >().Compile();

            double[] x = new double[N];

            // Remember where we last succeeded/failed.
            double s0 = 0.0;
            double s1 = 1.0;

            do
            {
                try
                {
                    // H(F, s) = F - s*F0
                    NewtonsMethod(M, N, JxH, s0, x, Epsilon, MaxIterations);

                    // Success at this s!
                    s1 = s0;
                    for (int i = 0; i < N; ++i)
                    {
                        x0[i] = Arrow.New(x0[i].Left, x[i]);
                    }

                    // Go near the goal.
                    s0 = Lerp(s0, 0.0, 0.9);
                }
                catch (FailedToConvergeException)
                {
                    // Go near the last success.
                    s0 = Lerp(s0, s1, 0.9);

                    for (int i = 0; i < N; ++i)
                    {
                        x[i] = (double)x0[i].Right;
                    }
                }
            } while (s0 > 0.0 && s1 >= s0 + 1e-6);

            // Make sure the last solution is at F itself.
            if (s0 != 0.0)
            {
                NewtonsMethod(M, N, JxH, 0.0, x, Epsilon, MaxIterations);
                for (int i = 0; i < N; ++i)
                {
                    x0[i] = Arrow.New(x0[i].Left, x[i]);
                }
            }

            return(x0);
        }
Esempio n. 20
0
        /// <summary>
        /// Def block parser
        /// </summary>
        void PushBlock(List <Expression> body, List <Exp> IL)
        {
            Expression expr;
            var        ifparts = new Stack <If>();

            for (int i = 0; i < body.Count; i++)
            {
                expr = body[i]; // cur expression

                switch (expr.Command)
                {
                case "class":
                {
                    Class type = ParseClass(expr);
                    Global.Add(type.Name, type);
                }
                break;

                case "def":
                {
                    Function func = ParseFunc(expr);
                    Global.Add(func.Name, func);
                }
                break;

                case "if":
                case "elif":
                    ifparts.Push(
                        new If
                    {
                        Test = AsBool(Parse(expr)),
                        Body = ParseBlock(expr.Body)
                    });
                    if (i + 1 == body.Count || body[i + 1].Command?.StartsWith("el") == false)
                    {
                        IL.Add(IfThenElse(ifparts));
                    }
                    break;

                case "else":
                    IL.Add(IfThenElse(ifparts, ParseBlock(expr.Body)));
                    break;

                case "for":
                {
                    var v = expr[0].Value;
                    expr.RemoveRange(0, 2);
                    if (expr.Count == 2 && expr[0].Value == "range")
                    {
                    }
                }
                break;

                case "while":
                    br.Push(Exp.Label());
                    con.Push(Exp.Label());

                    IL.Add(Exp.Loop(
                               Exp.IfThenElse(
                                   test: AsBool(Parse(expr)),
                                   ifTrue: ParseBlock(expr.Body),
                                   ifFalse: Exp.Goto(br.Peek())
                                   ),
                               br.Peek(),
                               con.Peek()));

                    br.Pop();
                    con.Pop();
                    break;

                case "try":

                    break;

                case "except":

                    break;

                case "finally":

                    break;

                case "import":

                    break;

                case "from":

                    break;

                case "return":
                    IL.Add(Exp.Goto(ret.Peek(), Parse(expr)));
                    break;

                case "break":
                    IL.Add(Exp.Goto(br.Peek()));
                    break;

                case "continue":
                    IL.Add(Exp.Goto(con.Peek()));
                    break;

                case "pass":
                    // nothing to do
                    break;

                case "global":
                {
                    var w = Split(expr, TokenType.Comma);
                    foreach (var v in w)
                    {
                        Local.Add(v[0].Value, GlobalAccess(v[0].Value));
                    }
                }
                break;

                case "nonlocal":

                    break;

                case "del":

                    break;

                case "raise":

                    break;

                case "assert":

                    break;

                case "yield":

                    break;

                case "print":
                    IL.Add(Exp.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(object) }), Parse(expr)));
                    break;

                case "emit":
                    Emit(expr[0].Value, IL);
                    break;

                case "assign":
                {
                    (var left, var right, var op) = SplitAssign(expr);

                    var vars   = Split(left, TokenType.Comma);
                    var values = Split(right, TokenType.Comma);

                    if (op != Op.None)         // augmented assignment
                    {
                        if (vars.Count == 1)
                        {
                            if (values.Count == 1)
                            {
                                Exp var = ParseUnit(vars[0]);
                                Exp val = Parse(values[0]);
                                IL.Add(Exp.Assign(var, Dynamic(op, var, val)));
                            }
                            else if (values.Count > 1)         // tuple
                            {
                                // pass
                            }
                        }
                        else
                        {
                            throw new Exception("illegal expression for augmented assignment");
                        }
                    }
                    else if (vars.Count == values.Count)
                    {
                        for (int j = 0; j < vars.Count; j++)
                        {
                            IL.Add(Assign(vars[j], Parse(values[j])));
                        }
                    }
                    else if (vars.Count > 1 && values.Count == 1)         // unpack
                    {
                        Exp iter = Cache("c_002");

                        var iterable = Parse(values[0]);
                        IL.Add(Exp.Assign(iter, iterable));

                        for (int j = 0; j < vars.Count; j++)
                        {
                            IL.Add(Assign(vars[j], Exp.Call(iter, typeof(Object).GetMethod("__getitem__"), Exp.Constant(new Int(j)))));
                        }
                    }
                    else if (vars.Count == 1 && values.Count > 1)         // tuple
                    {
                        var tpl = Exp.ListInit(Exp.New(typeof(Tuple)),
                                               values.Select(Parse));
                        IL.Add(Assign(vars[0], tpl));
                    }
                }
                break;

                case null:
                    IL.Add(Parse(expr));
                    break;
                }
            }
        }
Esempio n. 21
0
        /// <summary>Generates a method similar to this:
        /// <code>
        /// void Read(IO.BitStream s, out TEnum v, int bitCount)
        /// {
        ///     v = (UnderlyingType)s.Read[TStreamType](bitCount);
        /// }
        /// </code>
        /// </summary>
        /// <param name="args"></param>
        /// <param name="readMethodInfo"></param>
        /// <param name="bitSwapMethod"></param>
        /// <returns>The generated method.</returns>
        /// <remarks>
        /// If <see cref="args.UnderlyingType"/> is the same as <typeparamref name="TStreamType"/>, no conversion code is generated
        /// </remarks>
        static ReadDelegate GenerateReadMethod(MethodGenerationArgs args, MethodInfo readMethodInfo, MethodInfo bitSwapMethod)
        {
            // Get a "ref type" of the enum we're dealing with so we can define the enum value as an 'out' parameter
            var enum_ref = args.EnumType.MakeByRefType();

            //////////////////////////////////////////////////////////////////////////
            // Define the generated method's parameters
            var param_s  = Expr.Parameter(kBitStreamType, "s");                                                         // BitStream s
            var param_v  = Expr.Parameter(enum_ref, "v");                                                               // ref TEnum v
            var param_bc = Expr.Parameter(typeof(int), "bitCount");                                                     // int bitCount

            //////////////////////////////////////////////////////////////////////////
            // Define the Read call
            Expr call_read;

            if (args.StreamTypeIsSigned)
            {
                call_read = Expr.Call(param_s, readMethodInfo, param_bc, Expr.Constant(args.Options.SignExtend));
            }
            else
            {
                call_read = Expr.Call(param_s, readMethodInfo, param_bc);                                               // i.e., 's.Read<Type>(bitCount)'
            }
            if (args.Options.UseNoneSentinelEncoding)
            {
                call_read = Expr.Decrement(call_read);
            }

            #region options.BitSwap
            if (args.Options.BitSwap)
            {
                // i.e., Bits.BitSwap( Read(), bitCount-1 );
                var  start_bit_index = Expr.Decrement(param_bc);
                Expr swap_call       = Expr.Call(null, bitSwapMethod, call_read, start_bit_index);

                // i.e., bitCount-1 ? Bits.BitSwap( Read(), bitCount-1 ) : Read() ;
                if (args.Options.BitSwapGuardAgainstOneBit)
                {
                    var start_bit_index_is_not_zero = Expr.NotEqual(start_bit_index, Expr.Constant(0, typeof(int)));
                    swap_call = Expr.Condition(start_bit_index_is_not_zero,
                                               swap_call, call_read);
                }

                call_read = swap_call;
            }
            #endregion

            var read_result = args.UnderlyingTypeNeedsConversion ?                                                      // If the underlying type is different from the type we're reading,
                              Expr.Convert(call_read, args.UnderlyingType) :                                            // we need to cast the Read result from TStreamType to UnderlyingType
                              (Expr)call_read;

            //////////////////////////////////////////////////////////////////////////
            // Define the member assignment
            var param_v_member = Expr.PropertyOrField(param_v, EnumUtils.kMemberName);                  // i.e., 'v.value__'
            // i.e., 'v.value__ = s.Read<Type>()' or 'v.value__ = (UnderlyingType)s.Read<Type>()'
            var assign = Expr.Assign(param_v_member, read_result);

            //////////////////////////////////////////////////////////////////////////
            // Generate a method based on the expression tree we've built
            var lambda = Expr.Lambda <ReadDelegate>(assign, param_s, param_v, param_bc);
            return(lambda.Compile());
        }