Пример #1
0
        internal void ReadNullCheckedTail(Type type, IProtoSerializer tail, Local valueFrom)
        {
            Type type2;

            if (type.IsValueType && ((type2 = Helpers.GetUnderlyingType(type)) != null))
            {
                if (tail.RequiresOldValue)
                {
                    using (Local local = this.GetLocalWithValue(type, valueFrom))
                    {
                        this.LoadAddress(local, type);
                        this.EmitCall(type.GetMethod("GetValueOrDefault", Helpers.EmptyTypes));
                    }
                }
                tail.EmitRead(this, null);
                if (tail.ReturnsValue)
                {
                    this.EmitCtor(type, new Type[] { type2 });
                }
            }
            else
            {
                tail.EmitRead(this, valueFrom);
            }
        }
Пример #2
0
        private void WriteFieldHandler(
            Compiler.CompilerContext ctx, Compiler.Local loc,
            Compiler.CodeLabel handler, Compiler.CodeLabel @continue, IProtoSerializer serializer)
        {
            ctx.MarkLabel(handler);
            Type serType = serializer.ExpectedType;

            if (serType == ExpectedType)
            {
                // emit create if null
                Helpers.DebugAssert(!loc.IsNullRef());
                if (!ExpectedType.IsValueType && CanCreateInstance)
                {
                    Compiler.CodeLabel afterIf   = ctx.DefineLabel();
                    Compiler.CodeLabel ifContent = ctx.DefineLabel();

                    // if != null && of correct type
                    ctx.LoadValue(loc);
                    ctx.BranchIfFalse(ifContent, false);
                    ctx.LoadValue(loc);
                    ctx.TryCast(ExpectedType);
                    ctx.BranchIfFalse(ifContent, false);
                    ctx.Branch(afterIf, false);
                    {
                        ctx.MarkLabel(ifContent);

                        ((IProtoTypeSerializer)this).EmitCreateInstance(ctx);

                        if (_callbacks != null)
                        {
                            EmitInvokeCallback(ctx, _callbacks.BeforeDeserialize, true, null, ExpectedType);
                        }
                        ctx.StoreValue(loc);
                    }
                    ctx.MarkLabel(afterIf);
                }

                serializer.EmitRead(ctx, loc);
            }
            else
            {
                ctx.LoadValue(loc);
                if (ExpectedType.IsValueType || !serializer.EmitReadReturnsValue)
                {
                    ctx.Cast(serType);
                }
                else
                {
                    ctx.TryCast(serType); // default value can be another inheritance branch
                }
                serializer.EmitRead(ctx, null);
            }

            if (serializer.EmitReadReturnsValue)
            {   // update the variable
                ctx.StoreValue(loc);
            }
            ctx.Branch(@continue, false); // "continue"
        }
Пример #3
0
        private void WriteFieldHandler(
            Compiler.CompilerContext ctx, Type expected, Compiler.Local loc,
            Compiler.CodeLabel handler, Compiler.CodeLabel @continue, IProtoSerializer serializer)
        {
            ctx.MarkLabel(handler);
            Type serType = serializer.ExpectedType;

            if (serType == forType)
            {
                EmitCreateIfNull(ctx, loc);
                serializer.EmitRead(ctx, loc);
            }
            else
            {
                //RuntimeTypeModel rtm = (RuntimeTypeModel)ctx.Model;
                if (((IProtoTypeSerializer)serializer).CanCreateInstance())
                {
                    Compiler.CodeLabel allDone = ctx.DefineLabel();

                    ctx.LoadValue(loc);
                    ctx.BranchIfFalse(allDone, false); // null is always ok

                    ctx.LoadValue(loc);
                    ctx.TryCast(serType);
                    ctx.BranchIfTrue(allDone, false); // not null, but of the correct type

                    // otherwise, need to convert it
                    ctx.LoadReaderWriter();
                    ctx.LoadValue(loc);
                    ((IProtoTypeSerializer)serializer).EmitCreateInstance(ctx);
                    ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("Merge"));
                    ctx.Cast(expected);
                    ctx.StoreValue(loc); // Merge always returns a value

                    // nothing needs doing
                    ctx.MarkLabel(allDone);
                }
                ctx.LoadValue(loc);
                ctx.Cast(serType);
                serializer.EmitRead(ctx, null);
            }

            if (serializer.ReturnsValue)
            {   // update the variable
                ctx.StoreValue(loc);
            }
            ctx.Branch(@continue, false); // "continue"
        }
Пример #4
0
        private void WriteFieldHandler(CompilerContext ctx, Type expected, Local loc, CodeLabel handler, CodeLabel @continue, IProtoSerializer serializer)
        {
            ctx.MarkLabel(handler);
            Type expectedType = serializer.ExpectedType;

            if (expectedType == this.forType)
            {
                this.EmitCreateIfNull(ctx, loc);
                serializer.EmitRead(ctx, loc);
            }
            else
            {
                RuntimeTypeModel model = (RuntimeTypeModel)ctx.Model;
                if (((IProtoTypeSerializer)serializer).CanCreateInstance())
                {
                    CodeLabel label = ctx.DefineLabel();
                    ctx.LoadValue(loc);
                    ctx.BranchIfFalse(label, false);
                    ctx.LoadValue(loc);
                    ctx.TryCast(expectedType);
                    ctx.BranchIfTrue(label, false);
                    ctx.LoadReaderWriter();
                    ctx.LoadValue(loc);
                    ((IProtoTypeSerializer)serializer).EmitCreateInstance(ctx);
                    ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("Merge"));
                    ctx.Cast(expected);
                    ctx.StoreValue(loc);
                    ctx.MarkLabel(label);
                }
                ctx.LoadValue(loc);
                ctx.Cast(expectedType);
                serializer.EmitRead(ctx, null);
            }
            if (serializer.ReturnsValue)
            {
                ctx.StoreValue(loc);
            }
            ctx.Branch(@continue, false);
        }
Пример #5
0
        private void WriteFieldHandler(
            Compiler.CompilerContext ctx, Type expected, Compiler.Local loc,
            Compiler.CodeLabel handler, Compiler.CodeLabel @continue, IProtoSerializer serializer)
        {
            ctx.MarkLabel(handler);
            if (serializer.ExpectedType == forType)
            {
                EmitCreateIfNull(ctx, expected, loc);
                serializer.EmitRead(ctx, loc);
            }
            else
            {
                ctx.LoadValue(loc);
                ctx.Cast(serializer.ExpectedType);
                serializer.EmitRead(ctx, null);
            }

            if (serializer.ReturnsValue)
            {   // update the variable
                ctx.StoreValue(loc);
            }
            ctx.Branch(@continue, false); // "continue"
        }
Пример #6
0
        /*public static ProtoCallback BuildCallback(IProtoTypeSerializer head)
         * {
         *  Type type = head.ExpectedType;
         *  CompilerContext ctx = new CompilerContext(type, true, true);
         *  using (Local typedVal = new Local(ctx, type))
         *  {
         *      ctx.LoadValue(Local.InputValue);
         *      ctx.CastFromObject(type);
         *      ctx.StoreValue(typedVal);
         *      CodeLabel[] jumpTable = new CodeLabel[4];
         *      for(int i = 0 ; i < jumpTable.Length ; i++) {
         *          jumpTable[i] = ctx.DefineLabel();
         *      }
         *      ctx.LoadReaderWriter();
         *      ctx.Switch(jumpTable);
         *      ctx.Return();
         *      for(int i = 0 ; i < jumpTable.Length ; i++) {
         *          ctx.MarkLabel(jumpTable[i]);
         *          if (head.HasCallbacks((TypeModel.CallbackType)i))
         *          {
         *              head.EmitCallback(ctx, typedVal, (TypeModel.CallbackType)i);
         *          }
         *          ctx.Return();
         *      }
         *  }
         *
         *  ctx.Emit(OpCodes.Ret);
         *  return (ProtoCallback)ctx.method.CreateDelegate(
         *      typeof(ProtoCallback));
         * }*/
        public static ProtoDeserializer BuildDeserializer(IProtoSerializer head, TypeModel model)
        {
            Type            type = head.ExpectedType;
            CompilerContext ctx  = new CompilerContext(type, false, true, model);

            using (Local typedVal = new Local(ctx, type))
            {
                if (!type.IsValueType)
                {
                    ctx.LoadValue(Local.InputValue);
                    ctx.CastFromObject(type);
                    ctx.StoreValue(typedVal);
                }
                else
                {
                    ctx.LoadValue(Local.InputValue);
                    CodeLabel notNull = ctx.DefineLabel(), endNull = ctx.DefineLabel();
                    ctx.BranchIfTrue(notNull, true);

                    ctx.LoadAddress(typedVal, type);
                    ctx.EmitCtor(type);
                    ctx.Branch(endNull, true);

                    ctx.MarkLabel(notNull);
                    ctx.LoadValue(Local.InputValue);
                    ctx.CastFromObject(type);
                    ctx.StoreValue(typedVal);

                    ctx.MarkLabel(endNull);
                }
                head.EmitRead(ctx, typedVal);

                if (head.ReturnsValue)
                {
                    ctx.StoreValue(typedVal);
                }

                ctx.LoadValue(typedVal);
                ctx.CastToObject(type);
            }
            ctx.Emit(OpCodes.Ret);
            return((ProtoDeserializer)ctx.method.CreateDelegate(
                       typeof(ProtoDeserializer)));
        }
Пример #7
0
        public static ProtoDeserializer BuildDeserializer(IProtoSerializer head, TypeModel model)
        {
            Type            expectedType    = head.ExpectedType;
            CompilerContext compilerContext = new CompilerContext(expectedType, false, true, model, typeof(object));

            using (Local local = new Local(compilerContext, expectedType))
            {
                if (expectedType.IsValueType)
                {
                    compilerContext.LoadValue(compilerContext.InputValue);
                    CodeLabel codeLabel  = compilerContext.DefineLabel();
                    CodeLabel codeLabel1 = compilerContext.DefineLabel();
                    compilerContext.BranchIfTrue(codeLabel, true);
                    compilerContext.LoadAddress(local, expectedType);
                    compilerContext.EmitCtor(expectedType);
                    compilerContext.Branch(codeLabel1, true);
                    compilerContext.MarkLabel(codeLabel);
                    compilerContext.LoadValue(compilerContext.InputValue);
                    compilerContext.CastFromObject(expectedType);
                    compilerContext.StoreValue(local);
                    compilerContext.MarkLabel(codeLabel1);
                }
                else
                {
                    compilerContext.LoadValue(compilerContext.InputValue);
                    compilerContext.CastFromObject(expectedType);
                    compilerContext.StoreValue(local);
                }
                head.EmitRead(compilerContext, local);
                if (head.ReturnsValue)
                {
                    compilerContext.StoreValue(local);
                }
                compilerContext.LoadValue(local);
                compilerContext.CastToObject(expectedType);
            }
            compilerContext.Emit(OpCodes.Ret);
            return((ProtoDeserializer)compilerContext.method.CreateDelegate(typeof(ProtoDeserializer)));
        }
Пример #8
0
        private static void EmitReadAndAddItem(Compiler.CompilerContext ctx, Compiler.Local list, IProtoSerializer tail, MethodInfo add, bool castListForAdd)
        {
            ctx.LoadAddress(list, list.Type); // needs to be the reference in case the list is value-type (static-call)
            if (castListForAdd)
            {
                ctx.Cast(add.DeclaringType);
            }
            Type itemType         = tail.ExpectedType;
            bool tailReturnsValue = tail.ReturnsValue;

            if (tail.RequiresOldValue)
            {
                if (itemType.IsValueType || !tailReturnsValue)
                {
                    // going to need a variable
                    using (Compiler.Local item = new Compiler.Local(ctx, itemType))
                    {
                        if (itemType.IsValueType)
                        {   // initialise the struct
                            ctx.LoadAddress(item, itemType);
                            ctx.EmitCtor(itemType);
                        }
                        else
                        {   // assign null
                            ctx.LoadNullRef();
                            ctx.StoreValue(item);
                        }
                        tail.EmitRead(ctx, item);
                        if (!tailReturnsValue)
                        {
                            ctx.LoadValue(item);
                        }
                    }
                }
                else
                {    // no variable; pass the null on the stack and take the value *off* the stack
                    ctx.LoadNullRef();
                    tail.EmitRead(ctx, null);
                }
            }
            else
            {
                if (tailReturnsValue)
                {   // out only (on the stack); just emit it
                    tail.EmitRead(ctx, null);
                }
                else
                {   // doesn't take anything in nor return anything! WTF?
                    throw new InvalidOperationException();
                }
            }
            // our "Add" is chosen either to take the correct type, or to take "object";
            // we may need to box the value

            Type addParamType = add.GetParameters()[0].ParameterType;

            if (addParamType != itemType)
            {
                if (addParamType == ctx.MapType(typeof(object)))
                {
                    ctx.CastToObject(itemType);
                }
                else if (Helpers.GetUnderlyingType(addParamType) == itemType)
                {                       // list is nullable
                    ConstructorInfo ctor = Helpers.GetConstructor(addParamType, new Type[] { itemType }, false);
                    ctx.EmitCtor(ctor); // the itemType on the stack is now a Nullable<ItemType>
                }
                else
                {
                    throw new InvalidOperationException("Conflicting item/add type");
                }
            }
            ctx.EmitCall(add);
            if (add.ReturnType != ctx.MapType(typeof(void)))
            {
                ctx.DiscardValue();
            }
        }
Пример #9
0
        private void WriteFieldHandler(
            Compiler.CompilerContext ctx, Type expected, Compiler.Local loc,
            Compiler.CodeLabel handler, Compiler.CodeLabel @continue, IProtoSerializer serializer)
        {
            ctx.MarkLabel(handler);
            Type serType = serializer.ExpectedType;

            if (serType == ExpectedType)
            {
                EmitCreateIfNull(ctx, loc);
                serializer.EmitRead(ctx, loc);
            }
            else
            {
                //RuntimeTypeModel rtm = (RuntimeTypeModel)ctx.Model;
                if (((IProtoTypeSerializer)serializer).CanCreateInstance())
                {
                    Compiler.CodeLabel allDone = ctx.DefineLabel();

                    ctx.LoadValue(loc);
                    ctx.BranchIfFalse(allDone, false); // null is always ok

                    ctx.LoadValue(loc);
                    ctx.TryCast(serType);
                    ctx.BranchIfTrue(allDone, false); // not null, but of the correct type

                    // otherwise, need to convert it
                    ctx.LoadReader(false);
                    ctx.LoadValue(loc);
                    ((IProtoTypeSerializer)serializer).EmitCreateInstance(ctx);

                    ctx.EmitCall(typeof(ProtoReader).GetMethod("Merge",
                                                               new[] { typeof(ProtoReader), typeof(object), typeof(object) }));
                    ctx.Cast(expected);
                    ctx.StoreValue(loc); // Merge always returns a value

                    // nothing needs doing
                    ctx.MarkLabel(allDone);
                }

                if (Helpers.IsValueType(serType))
                {
                    Compiler.CodeLabel initValue = ctx.DefineLabel();
                    Compiler.CodeLabel hasValue  = ctx.DefineLabel();
                    using (Compiler.Local emptyValue = new Compiler.Local(ctx, serType))
                    {
                        ctx.LoadValue(loc);
                        ctx.BranchIfFalse(initValue, false);

                        ctx.LoadValue(loc);
                        ctx.CastFromObject(serType);
                        ctx.Branch(hasValue, false);

                        ctx.MarkLabel(initValue);
                        ctx.InitLocal(serType, emptyValue);
                        ctx.LoadValue(emptyValue);

                        ctx.MarkLabel(hasValue);
                    }
                }
                else
                {
                    ctx.LoadValue(loc);
                    ctx.Cast(serType);
                }

                serializer.EmitRead(ctx, null);
            }

            if (serializer.ReturnsValue)
            {   // update the variable
                if (Helpers.IsValueType(serType))
                {
                    // but box it first in case of value type
                    ctx.CastToObject(serType);
                }
                ctx.StoreValue(loc);
            }
            ctx.Branch(@continue, false); // "continue"
        }
Пример #10
0
        internal void ReadNullCheckedTail(Type type, IProtoSerializer tail, Compiler.Local valueFrom)
        {
            #if !FX11
            Type underlyingType;

            if (type.IsValueType && (underlyingType = Helpers.GetUnderlyingType(type)) != null)
            {
                if(tail.RequiresOldValue)
                {
                    // we expect the input value to be in valueFrom; need to unpack it from T?
                    using (Local loc = GetLocalWithValue(type, valueFrom))
                    {
                        LoadAddress(loc, type);
                        EmitCall(type.GetMethod("GetValueOrDefault", Helpers.EmptyTypes));
                    }
                }
                else
                {
                    Helpers.DebugAssert(valueFrom == null); // not expecting a valueFrom in this case
                }
                tail.EmitRead(this, null); // either unwrapped on the stack or not provided
                if (tail.ReturnsValue)
                {
                    // now re-wrap the value
                    EmitCtor(type, underlyingType);
                }
                return;
            }
            #endif
            // either a ref-type of a non-nullable struct; treat "as is", even if null
            // (the type-serializer will handle the null case; it needs to allow null
            // inputs to perform the correct type of subclass creation)
            tail.EmitRead(this, valueFrom);
        }
Пример #11
0
        /*public static ProtoCallback BuildCallback(IProtoTypeSerializer head)
        {
            Type type = head.ExpectedType;
            CompilerContext ctx = new CompilerContext(type, true, true);
            using (Local typedVal = new Local(ctx, type))
            {
                ctx.LoadValue(Local.InputValue);
                ctx.CastFromObject(type);
                ctx.StoreValue(typedVal);
                CodeLabel[] jumpTable = new CodeLabel[4];
                for(int i = 0 ; i < jumpTable.Length ; i++) {
                    jumpTable[i] = ctx.DefineLabel();
                }
                ctx.LoadReaderWriter();
                ctx.Switch(jumpTable);
                ctx.Return();
                for(int i = 0 ; i < jumpTable.Length ; i++) {
                    ctx.MarkLabel(jumpTable[i]);
                    if (head.HasCallbacks((TypeModel.CallbackType)i))
                    {
                        head.EmitCallback(ctx, typedVal, (TypeModel.CallbackType)i);
                    }
                    ctx.Return();
                }
            }

            ctx.Emit(OpCodes.Ret);
            return (ProtoCallback)ctx.method.CreateDelegate(
                typeof(ProtoCallback));
        }*/
        public static ProtoDeserializer BuildDeserializer(IProtoSerializer head, TypeModel model)
        {
            Type type = head.ExpectedType;
            CompilerContext ctx = new CompilerContext(type, false, true, model, typeof(object));

            using (Local typedVal = new Local(ctx, type))
            {
                if (!type.IsValueType)
                {
                    ctx.LoadValue(ctx.InputValue);
                    ctx.CastFromObject(type);
                    ctx.StoreValue(typedVal);
                }
                else
                {
                    ctx.LoadValue(ctx.InputValue);
                    CodeLabel notNull = ctx.DefineLabel(), endNull = ctx.DefineLabel();
                    ctx.BranchIfTrue(notNull, true);

                    ctx.LoadAddress(typedVal, type);
                    ctx.EmitCtor(type);
                    ctx.Branch(endNull, true);

                    ctx.MarkLabel(notNull);
                    ctx.LoadValue(ctx.InputValue);
                    ctx.CastFromObject(type);
                    ctx.StoreValue(typedVal);

                    ctx.MarkLabel(endNull);
                }
                head.EmitRead(ctx, typedVal);

                if (head.ReturnsValue) {
                    ctx.StoreValue(typedVal);
                }

                ctx.LoadValue(typedVal);
                ctx.CastToObject(type);
            }
            ctx.Emit(OpCodes.Ret);
            return (ProtoDeserializer)ctx.method.CreateDelegate(
                typeof(ProtoDeserializer));
        }
Пример #12
0
 private static void EmitReadAndAddItem(Compiler.CompilerContext ctx, Compiler.Local list, IProtoSerializer tail, MethodInfo add)
 {
     ctx.LoadValue(list);
     Type itemType = tail.ExpectedType;
     if (tail.RequiresOldValue)
     {
         if (itemType.IsValueType || !tail.ReturnsValue)
         {
             // going to need a variable
             using (Compiler.Local item = new Compiler.Local(ctx, itemType))
             {
                 if (itemType.IsValueType)
                 {   // initialise the struct
                     ctx.LoadAddress(item, itemType);
                     ctx.EmitCtor(itemType);
                 }
                 else
                 {   // assign null
                     ctx.LoadNullRef();
                     ctx.StoreValue(item);
                 }
                 tail.EmitRead(ctx, item);
                 if (!tail.ReturnsValue) { ctx.LoadValue(item); }
             }
         }
         else
         {    // no variable; pass the null on the stack and take the value *off* the stack
             ctx.LoadNullRef();
             tail.EmitRead(ctx, null);
         }
     }
     else
     {
         if (tail.ReturnsValue)
         {   // out only (on the stack); just emit it
             tail.EmitRead(ctx, null);
         }
         else
         {   // doesn't take anything in nor return anything! WTF?
             throw new InvalidOperationException();
         }
     }
     // our "Add" is chosen either to take the correct type, or to take "object";
     // we may need to box the value
         
     Type addParamType = add.GetParameters()[0].ParameterType;
     if(addParamType != itemType) {
         if (addParamType == typeof(object))
         {
             ctx.CastToObject(itemType);
         }
         else
         {
             throw new InvalidOperationException("Conflicting item/add type");
         }
     }
     ctx.EmitCall(add);
     if (add.ReturnType != typeof(void))
     {
         ctx.DiscardValue();
     }
 }
Пример #13
0
        protected override void EmitRead(CompilerContext ctx, Local valueFrom)
        {
            using (Compiler.Local list = AppendToCollection ? ctx.GetLocalWithValue(ExpectedType, valueFrom)
                : new Compiler.Local(ctx, typeof(TDictionary)))
                using (Compiler.Local token = new Compiler.Local(ctx, typeof(SubItemToken)))
                    using (Compiler.Local key = new Compiler.Local(ctx, typeof(TKey)))
                        using (Compiler.Local @value = new Compiler.Local(ctx, typeof(TValue)))
                            using (Compiler.Local fieldNumber = new Compiler.Local(ctx, typeof(int)))
                            {
                                if (!AppendToCollection)
                                { // always new
                                    ctx.LoadNullRef();
                                    ctx.StoreValue(list);
                                }
                                if (concreteType != null)
                                {
                                    ctx.LoadValue(list);
                                    Compiler.CodeLabel notNull = ctx.DefineLabel();
                                    ctx.BranchIfTrue(notNull, true);
                                    ctx.EmitCtor(concreteType);
                                    ctx.StoreValue(list);
                                    ctx.MarkLabel(notNull);
                                }

                                var redoFromStart = ctx.DefineLabel();
                                ctx.MarkLabel(redoFromStart);

                                // key = default(TKey); value = default(TValue);
                                if (typeof(TKey) == typeof(string))
                                {
                                    ctx.LoadValue("");
                                    ctx.StoreValue(key);
                                }
                                else
                                {
                                    ctx.InitLocal(typeof(TKey), key);
                                }
                                if (typeof(TValue) == typeof(string))
                                {
                                    ctx.LoadValue("");
                                    ctx.StoreValue(value);
                                }
                                else
                                {
                                    ctx.InitLocal(typeof(TValue), @value);
                                }

                                // token = ProtoReader.StartSubItem(reader);
                                ctx.LoadReader(true);
                                ctx.EmitCall(typeof(ProtoReader).GetMethod("StartSubItem", ProtoReader.State.ReaderStateTypeArray));
                                ctx.StoreValue(token);

                                Compiler.CodeLabel @continue = ctx.DefineLabel(), processField = ctx.DefineLabel();
                                // while ...
                                ctx.Branch(@continue, false);

                                // switch(fieldNumber)
                                ctx.MarkLabel(processField);
                                ctx.LoadValue(fieldNumber);
                                CodeLabel @default = ctx.DefineLabel(), one = ctx.DefineLabel(), two = ctx.DefineLabel();
                                ctx.Switch(new[] { @default, one, two }); // zero based, hence explicit 0

                                // case 0: default: reader.SkipField();
                                ctx.MarkLabel(@default);
                                ctx.LoadReader(true);
                                ctx.EmitCall(typeof(ProtoReader).GetMethod("SkipField", ProtoReader.State.StateTypeArray));
                                ctx.Branch(@continue, false);

                                // case 1: key = ...
                                ctx.MarkLabel(one);
                                keyTail.EmitRead(ctx, null);
                                ctx.StoreValue(key);
                                ctx.Branch(@continue, false);

                                // case 2: value = ...
                                ctx.MarkLabel(two);
                                Tail.EmitRead(ctx, Tail.RequiresOldValue ? @value : null);
                                ctx.StoreValue(value);

                                // (fieldNumber = reader.ReadFieldHeader()) > 0
                                ctx.MarkLabel(@continue);
                                ctx.EmitBasicRead("ReadFieldHeader", typeof(int));
                                ctx.CopyValue();
                                ctx.StoreValue(fieldNumber);
                                ctx.LoadValue(0);
                                ctx.BranchIfGreater(processField, false);

                                // ProtoReader.EndSubItem(token, reader);
                                ctx.LoadValue(token);
                                ctx.LoadReader(true);
                                ctx.EmitCall(typeof(ProtoReader).GetMethod("EndSubItem",
                                                                           new[] { typeof(SubItemToken), typeof(ProtoReader), ProtoReader.State.ByRefStateType }));

                                // list[key] = value;
                                ctx.LoadAddress(list, ExpectedType);
                                ctx.LoadValue(key);
                                ctx.LoadValue(@value);
                                ctx.EmitCall(indexerSet);

                                // while reader.TryReadFieldReader(fieldNumber)
                                ctx.LoadReader(true);
                                ctx.LoadValue(this.fieldNumber);
                                ctx.EmitCall(typeof(ProtoReader).GetMethod("TryReadFieldHeader",
                                                                           new[] { ProtoReader.State.ByRefStateType, typeof(int) }));
                                ctx.BranchIfTrue(redoFromStart, false);

                                if (ReturnsValue)
                                {
                                    ctx.LoadValue(list);
                                }
                            }
        }
Пример #14
0
        private void WriteFieldHandler(
            Compiler.CompilerContext ctx, Type expected, Compiler.Local loc,
            Compiler.CodeLabel handler, Compiler.CodeLabel @continue, IProtoSerializer serializer)
        {
            ctx.MarkLabel(handler);
            if (serializer.ExpectedType == forType) {
                EmitCreateIfNull(ctx, expected, loc);
                serializer.EmitRead(ctx, loc);
            }
            else {
                ctx.LoadValue(loc);
                ctx.Cast(serializer.ExpectedType);
                serializer.EmitRead(ctx, null);
            }

            if (serializer.ReturnsValue)
            {   // update the variable
                ctx.StoreValue(loc);
            }
            ctx.Branch(@continue, false); // "continue"
        }
Пример #15
0
        private static void EmitReadAndAddItem(CompilerContext ctx, Local list, IProtoSerializer tail, MethodInfo add, bool castListForAdd)
        {
            ctx.LoadAddress(list, list.Type);
            if (castListForAdd)
            {
                ctx.Cast(add.DeclaringType);
            }
            Type expectedType = tail.ExpectedType;
            bool returnsValue = tail.ReturnsValue;

            if (!tail.RequiresOldValue)
            {
                if (!returnsValue)
                {
                    throw new InvalidOperationException();
                }
                tail.EmitRead(ctx, null);
            }
            else if (expectedType.IsValueType || !returnsValue)
            {
                using (Local local = new Local(ctx, expectedType))
                {
                    if (!expectedType.IsValueType)
                    {
                        ctx.LoadNullRef();
                        ctx.StoreValue(local);
                    }
                    else
                    {
                        ctx.LoadAddress(local, expectedType);
                        ctx.EmitCtor(expectedType);
                    }
                    tail.EmitRead(ctx, local);
                    if (!returnsValue)
                    {
                        ctx.LoadValue(local);
                    }
                }
            }
            else
            {
                ctx.LoadNullRef();
                tail.EmitRead(ctx, null);
            }
            Type parameterType = add.GetParameters()[0].ParameterType;

            if (parameterType != expectedType)
            {
                if (parameterType != ctx.MapType(typeof(object)))
                {
                    if (Helpers.GetUnderlyingType(parameterType) != expectedType)
                    {
                        throw new InvalidOperationException("Conflicting item/add type");
                    }
                    Type[] typeArray = new Type[] { expectedType };
                    ctx.EmitCtor(Helpers.GetConstructor(parameterType, typeArray, false));
                }
                else
                {
                    ctx.CastToObject(expectedType);
                }
            }
            ctx.EmitCall(add);
            if (add.ReturnType != ctx.MapType(typeof(void)))
            {
                ctx.DiscardValue();
            }
        }
Пример #16
0
        private static void EmitReadAndAddItem(Compiler.CompilerContext ctx, Compiler.Local list, IProtoSerializer tail, MethodInfo add)
        {
            ctx.LoadValue(list);
            Type itemType = tail.ExpectedType;

            if (tail.RequiresOldValue)
            {
                if (itemType.IsValueType || !tail.ReturnsValue)
                {
                    // going to need a variable
                    using (Compiler.Local item = new Compiler.Local(ctx, itemType))
                    {
                        if (itemType.IsValueType)
                        {   // initialise the struct
                            ctx.LoadAddress(item, itemType);
                            ctx.EmitCtor(itemType);
                        }
                        else
                        {   // assign null
                            ctx.LoadNullRef();
                            ctx.StoreValue(item);
                        }
                        tail.EmitRead(ctx, item);
                        if (!tail.ReturnsValue)
                        {
                            ctx.LoadValue(item);
                        }
                    }
                }
                else
                {    // no variable; pass the null on the stack and take the value *off* the stack
                    ctx.LoadNullRef();
                    tail.EmitRead(ctx, null);
                }
            }
            else
            {
                if (tail.ReturnsValue)
                {   // out only (on the stack); just emit it
                    tail.EmitRead(ctx, null);
                }
                else
                {   // doesn't take anything in nor return anything! WTF?
                    throw new InvalidOperationException();
                }
            }
            // our "Add" is chosen either to take the correct type, or to take "object";
            // we may need to box the value

            Type addParamType = add.GetParameters()[0].ParameterType;

            if (addParamType != itemType)
            {
                if (addParamType == typeof(object))
                {
                    ctx.CastToObject(itemType);
                }
                else
                {
                    throw new InvalidOperationException("Conflicting item/add type");
                }
            }
            ctx.EmitCall(add);
            if (add.ReturnType != typeof(void))
            {
                ctx.DiscardValue();
            }
        }