public Delegate Generate(RootNode root)
        {
            var ctx = new DeserializerTypeContext
              {
            Type = root.Type
              };

              InitializeVars(ctx);

              var @switch = GetSwitchStatement(ctx, root.Children);

              ctx.BlockInsideLoop = GetInnerLoopTemplate(ctx, @switch);

              var lambda = GetTemplate(ctx);

              var del = CompileExpression(root.Type, lambda);

              _treeBuilder.AddKnownType(root.Type, del);

              return del;
        }
 private SwitchCase ProcessNode(DeserializerTypeContext ctx, IntCollectionNode node)
 {
     return ProcessCollectionNode(ctx, node, _extractIntCollection);
 }
        private SwitchCase ProcessNode(DeserializerTypeContext ctx, DoubleNode node)
        {
            var bodyExpressions = new List<Expression>();

              var callExtractInt = Expression.Call(null, _extractDouble, ctx.IteratorVar, ctx.StringParam);

              var accessMember = Expression.MakeMemberAccess(ctx.InstanceVar, node.Member);

              var assignMember = Expression.Assign(accessMember, callExtractInt);

              bodyExpressions.Add(assignMember);
              bodyExpressions.Add(Expression.Empty());

              var body = Expression.Block(bodyExpressions);

              var @case = Expression.SwitchCase(body, GetSwitchConstant(ctx, node));

              return @case;
        }
        private SwitchCase ProcessNode(DeserializerTypeContext ctx, RecursionNode node)
        {
            var accessFunction = Expression.MakeMemberAccess(null, typeof(DeserializerStore<>)
            .MakeGenericType(node.Type).GetField("Function"));

              var invokeReturnValue = Expression.Invoke(accessFunction, ctx.IteratorVar, ctx.StringParam);

              var accessMember = Expression.MakeMemberAccess(ctx.InstanceVar, node.Member);

              var assignMember = Expression.Assign(accessMember, invokeReturnValue);
              var bodyExpressions = new List<Expression>();

              bodyExpressions.Add(assignMember);
              bodyExpressions.Add(Expression.Empty());

              var body = Expression.Block(bodyExpressions);

              var @case = Expression.SwitchCase(body, GetSwitchConstant(ctx, node));

              return @case;
        }
        private SwitchCase ProcessNode(DeserializerTypeContext parentCtx, UnknownTypeNode node)
        {
            var ctx = new DeserializerTypeContext
              {
            Type = node.Member.PropertyOrFieldType
              };

              InitializeVars(ctx);

              var @switch = GetSwitchStatement(ctx, node.Children);

              ctx.BlockInsideLoop = GetInnerLoopTemplate(ctx, @switch);

              var lambda = GetTemplate(ctx);

              var del = CompileExpression(node.Type, lambda);

              _treeBuilder.AddKnownType(node.Type, del);

              return GetKnownTypeSwitchCase(parentCtx, del.Method, node);
        }
        private SwitchCase ProcessCollectionNode(DeserializerTypeContext ctx, MemberNode node, MethodInfo method)
        {
            var bodyExpressions = new List<Expression>();

              var collectionType = GetNewCollectionType(node.Member.PropertyOrFieldType);

              method = method.MakeGenericMethod(collectionType);

              var createNewCollection = Expression.New(collectionType);

              var callExtractItems = Expression.Call(null, method, ctx.IteratorVar, ctx.StringParam, createNewCollection);

              var accessMember = Expression.MakeMemberAccess(ctx.InstanceVar, node.Member);

              if (node.Member.PropertyOrFieldType.IsArray)
              {
            var callToArray = Expression.Call(null, _toArray.MakeGenericMethod(node.Member.PropertyOrFieldType.GetElementType()), callExtractItems);
            callExtractItems = callToArray;
              }

              var assignMember = Expression.Assign(accessMember, callExtractItems);

              bodyExpressions.Add(assignMember);
              bodyExpressions.Add(Expression.Empty());

              var body = Expression.Block(bodyExpressions);

              var @case = Expression.SwitchCase(body, GetSwitchConstant(ctx, node));

              return @case;
        }
 private SwitchCase ProcessNode(DeserializerTypeContext ctx, KnownTypeNode node)
 {
     return GetKnownTypeSwitchCase(ctx, node.Method, node);
 }
        private LambdaExpression GetTemplate(DeserializerTypeContext ctx)
        {
            var newInstance = Expression.New(ctx.Type);

              var assignInstance = Expression.Assign(ctx.InstanceVar, newInstance);

              var terminationCondition = Expression.LessThan(ctx.IteratorVar, ctx.StringLengthVar);

              var initializeIterationVar = Expression.Assign(ctx.IteratorVar, ctx.StartParam);

              var assignLen = Expression.Assign(ctx.StringLengthVar, Expression.Property(ctx.StringParam, "Length"));

              var @for = Expression.Loop(
                        Expression.IfThenElse(
                        terminationCondition,
                            ctx.BlockInsideLoop
                        , Expression.Break(ctx.BreakLabel)), ctx.BreakLabel);

              var bodyExpressions = new List<Expression>();

              bodyExpressions.Add(assignInstance);
              bodyExpressions.Add(initializeIterationVar);
              bodyExpressions.Add(assignLen);
              bodyExpressions.Add(@for);
              bodyExpressions.Add(Expression.Label(ctx.ReturnLabel));
              bodyExpressions.Add(ctx.InstanceVar);

              var body = Expression.Block(new[] // the variables
              {
            ctx.InstanceVar,
            ctx.EndVar,
            ctx.IteratorVar,
            ctx.StringLengthVar,
            ctx.CharVar,
            ctx.WhiteSpaceCounter,
            ctx.PropertyHashValue ?? ctx.SubStringVar
              },
            // the body
              bodyExpressions);

              var lambdaType = typeof(DeserializeHandler<>).MakeGenericType(ctx.Type);

              var lambda = Expression.Lambda(lambdaType, body, ctx.StartParam, ctx.StringParam);

              return lambda;
        }
        private void InitializeVars(DeserializerTypeContext ctx)
        {
            ctx.InstanceVar = Expression.Variable(ctx.Type, "new" + ctx.Type.Name);

              ctx.EndVar = Expression.Variable(typeof(int), "end");

              ctx.StartParam = Expression.Parameter(typeof(int).MakeByRefType(), "start");

              ctx.IteratorVar = Expression.Variable(typeof(int), "i");

              ctx.StringParam = Expression.Parameter(typeof(string), "str");

              ctx.StringLengthVar = Expression.Variable(typeof(int), "len");

              ctx.CharVar = Expression.Variable(typeof(char), "c");

              ctx.BreakLabel = Expression.Label("break");
              ctx.ContinueLabel = Expression.Label("continue");
              ctx.ReturnLabel = Expression.Label("return");

              ctx.WhiteSpaceCounter = Expression.Variable(typeof(int), "whitespace");

              ctx.SubStringVar = Expression.Variable(typeof(string), "subStr");
        }
示例#10
0
        private Expression GetSwitchConstant(DeserializerTypeContext ctx, MemberNode node)
        {
            if (ctx.HashingMethod == null) return Expression.Constant(node.Member.Name);

              var hash = ctx.HashingMethod.Values.FirstOrDefault(kv => kv.Value == node.Member.Name);

              if (hash.Value == null) throw new InvalidOperationException("Unknown hash for member " + node.Member);

              return Expression.Constant(hash.Key);
        }
示例#11
0
        private Expression GetSwitchStatement(DeserializerTypeContext ctx, IList<Node> members)
        {
            var switchCases = new List<SwitchCase>();

              ctx.HashingMethod = MemberHashHelper.CanUseHashLookup(members.Cast<MemberNode>().Select(m => m.Member.Name));

              foreach (var c in members)
              {
            var caseStatement = ProcessNode(ctx, c as dynamic) as SwitchCase;

            if (caseStatement != null)
            {
              switchCases.Add(caseStatement);
            }
              }

              if (!switchCases.Any())
              {
            return Expression.Empty();
              }

              Expression switchValue;

              if (ctx.HashingMethod == null)
              {
            switchValue = ctx.SubStringVar;
              }
              else
              {
            ctx.PropertyHashValue = Expression.Variable(typeof(int), "hashValue");

            switchValue = ctx.PropertyHashValue;
              }

              var @switch = Expression.Switch(switchValue, GetDefaultCase(ctx), switchCases.ToArray());
              return @switch;
        }
示例#12
0
        private Expression GetPropertyFinderLoop(DeserializerTypeContext ctx)
        {
            var outerLoopExpressions = new List<Expression>();

              var jParam = Expression.Variable(typeof(int), "j");

              var terminationCondition = Expression.LessThan(jParam, ctx.StringLengthVar);

              var @break = Expression.Label();

              var assignItoJ = Expression.Assign(jParam, ctx.IteratorVar);

              var increment = Expression.PostIncrementAssign(jParam);

              var accessStringIndex = Expression.MakeIndex(ctx.StringParam, _stringIndexMethod, new[] { jParam });

              var assignToChar = Expression.Assign(ctx.CharVar, accessStringIndex);

              var invokeIgnoreFunc = Expression.Call(null, _ignoreFunc, ctx.CharVar);

              var assignJtoEnd = Expression.Assign(ctx.EndVar, jParam);

              var exitLoopBlock = Expression.Block(assignJtoEnd, Expression.Break(@break));

              var ifWhiteSpace = Expression.IfThenElse(invokeIgnoreFunc,
            Expression.PostIncrementAssign(ctx.WhiteSpaceCounter),

            Expression.IfThen(Expression.Equal(ctx.CharVar, Expression.Constant(':')),

            exitLoopBlock));

              var innerLoopExpressions = new List<Expression>();

              innerLoopExpressions.Add(assignToChar);
              innerLoopExpressions.Add(ifWhiteSpace);
              innerLoopExpressions.Add(increment);

              var innerLoopBlock = Expression.Block(innerLoopExpressions);

              var @for = Expression.Loop(
                        Expression.IfThenElse(
                        terminationCondition,
                            innerLoopBlock
                        , Expression.Break(@break)), @break);

              outerLoopExpressions.Add(assignItoJ);
              outerLoopExpressions.Add(@for);

              var outerLoopBlock = Expression.Block(new[] { jParam }, outerLoopExpressions);

              return outerLoopBlock;
        }
示例#13
0
 private SwitchCase GetKnownTypeSwitchCaseForRecursion(DeserializerTypeContext ctx, RecursionNode node)
 {
     //var
       return null;
 }
示例#14
0
        private SwitchCase GetKnownTypeSwitchCase(DeserializerTypeContext ctx, MethodInfo method, MemberNode node)
        {
            var bodyExpressions = new List<Expression>();

              var callExtractString = Expression.Call(null, method, ctx.IteratorVar, ctx.StringParam);

              var accessMember = Expression.MakeMemberAccess(ctx.InstanceVar, node.Member);

              var assignMember = Expression.Assign(accessMember, callExtractString);

              bodyExpressions.Add(assignMember);
              bodyExpressions.Add(Expression.Empty());

              var body = Expression.Block(bodyExpressions);

              var @case = Expression.SwitchCase(body, GetSwitchConstant(ctx, node));

              return @case;
        }
示例#15
0
        private Expression GetInnerLoopTemplate(DeserializerTypeContext ctx, Expression propertySwitch)
        {
            var accessStringIndex = Expression.MakeIndex(ctx.StringParam, _stringIndexMethod, new[] { ctx.IteratorVar });

              var assignToChar = Expression.Assign(ctx.CharVar, accessStringIndex);

              var invokeIgnoreFunc = Expression.Call(null, _ignoreFunc, ctx.CharVar);

              var increment = Expression.PreIncrementAssign(ctx.IteratorVar);

              var ifIgnore = Expression.IfThen(invokeIgnoreFunc, Expression.Block(increment, Expression.Continue(ctx.ContinueLabel)));

              var bodyExpressions = new List<Expression>();

              var ifCommaOrBrace = Expression.SwitchCase(Expression.Block(increment, Expression.Continue(ctx.ContinueLabel)), Expression.Constant(','), Expression.Constant('{'));

              var ifClosingBrace = Expression.SwitchCase(Expression.Block(Expression.Assign(ctx.StartParam, increment), Expression.Return(ctx.ReturnLabel)), Expression.Constant('}'));

              var @switch = Expression.Switch(ctx.CharVar, ifCommaOrBrace, ifClosingBrace);

              var resetEndVar = Expression.Assign(ctx.EndVar, Expression.Constant(-1));
              var resetWhiteSpaceVar = Expression.Assign(ctx.WhiteSpaceCounter, Expression.Constant(0));

              var throwIfEndIsNegative = Expression.IfThen(Expression.LessThan(ctx.EndVar, Expression.Constant(0)),
            Expression.Throw(Expression.New(typeof(InvalidOperationException).GetConstructor(new[] { typeof(string) })
            , Expression.Constant("Expected a property, but encountered none."))));

              Expression assignToSwitchValue;

              if (ctx.HashingMethod == null)
              {
            var callSubString = Expression.Call(ctx.StringParam, _subStringMethod, ctx.IteratorVar,
              Expression.Subtract(Expression.Subtract(ctx.EndVar, ctx.IteratorVar), ctx.WhiteSpaceCounter));

            assignToSwitchValue = Expression.Assign(ctx.SubStringVar, callSubString);
              }
              else
              {
            var callHash = Expression.Call(null, ctx.HashingMethod.Method.Method, ctx.StringParam, ctx.IteratorVar,
              Expression.Subtract(ctx.EndVar, ctx.WhiteSpaceCounter));

            assignToSwitchValue = Expression.Assign(ctx.PropertyHashValue, callHash);
              }

              var assignI = Expression.Assign(ctx.IteratorVar, Expression.Add(ctx.EndVar, Expression.Constant(1)));

              bodyExpressions.Add(assignToChar);
              bodyExpressions.Add(ifIgnore);
              bodyExpressions.Add(@switch);
              bodyExpressions.Add(resetEndVar);
              bodyExpressions.Add(resetWhiteSpaceVar);

              bodyExpressions.Add(GetPropertyFinderLoop(ctx));

              bodyExpressions.Add(throwIfEndIsNegative);
              bodyExpressions.Add(assignToSwitchValue);

              bodyExpressions.Add(assignI);
              bodyExpressions.Add(propertySwitch);

              bodyExpressions.Add(Expression.Label(ctx.ContinueLabel));

              return Expression.Block(bodyExpressions);
        }
示例#16
0
        private Expression GetDefaultCase(DeserializerTypeContext ctx)
        {
            var skipMethod = typeof(StandardFunctions).GetMethod("Skip");

              var callSkip = Expression.Call(null, skipMethod, ctx.IteratorVar, ctx.StringParam);

              return callSkip;
        }