예제 #1
0
파일: IfStatement.cs 프로젝트: dotted/csly
        public Emit <Func <int> > EmitByteCode(CompilerContext context, Emit <Func <int> > emiter)
        {
            var thenLabel = emiter.DefineLabel();
            var elseLabel = emiter.DefineLabel();
            var endLabel  = emiter.DefineLabel();

            Condition.EmitByteCode(context, emiter);
            emiter.BranchIfTrue(thenLabel);
            emiter.Branch(elseLabel);
            emiter.MarkLabel(thenLabel);
            ThenStmt.EmitByteCode(context, emiter);
            emiter.Branch(endLabel);
            emiter.MarkLabel(elseLabel);
            ElseStmt.EmitByteCode(context, emiter);
            emiter.Branch(endLabel);
            emiter.MarkLabel(endLabel);
            return(emiter);
        }
        public void EmitSerialize(Emit emiter, Local value)
        {
            var elementType = value.LocalType.GetElementType();

            using (var length = emiter.DeclareLocal <int>("length"))
            {
                // length = value.Length
                emiter.LoadLocal(value);
                emiter.Call(value.LocalType.GetProperty(nameof(Array.Length)).GetMethod);
                emiter.StoreLocal(length);

                emiter.CallSerializerForType(length.LocalType, length);

                var loop      = emiter.DefineLabel();
                var loopCheck = emiter.DefineLabel();

                using (var element = emiter.DeclareLocal(elementType, "element"))
                    using (var i = emiter.DeclareLocal <int>("i"))
                    {
                        emiter.Branch(loopCheck);
                        emiter.MarkLabel(loop);

                        // element = value[i]
                        emiter.LoadLocal(value);
                        emiter.LoadLocal(i);
                        emiter.LoadElement(elementType);
                        emiter.StoreLocal(element);

                        if (_compiler != null)
                        {
                            _compiler.EmitSerialize(emiter, element);
                        }
                        else if (_serializer != null)
                        {
                            emiter.CallSerializer(_serializer, element);
                        }
                        else
                        {
                            emiter.CallSerializerForType(elementType, element);
                        }

                        // ++i
                        emiter.LoadLocal(i);
                        emiter.LoadConstant(1);
                        emiter.Add();
                        emiter.StoreLocal(i);

                        // i < length
                        emiter.MarkLabel(loopCheck);
                        emiter.LoadLocal(i);
                        emiter.LoadLocal(length);
                        emiter.BranchIfLess(loop);
                    }
            }
        }
예제 #3
0
        public Emit <Func <int> > EmitByteCode(CompilerContext context, Emit <Func <int> > emiter)
        {
            var loopLabel = emiter.DefineLabel();
            var outLabel  = emiter.DefineLabel();

            emiter.MarkLabel(loopLabel);
            Condition.EmitByteCode(context, emiter);
            emiter.BranchIfFalse(outLabel);
            BlockStmt.EmitByteCode(context, emiter);
            emiter.Branch(loopLabel);
            emiter.MarkLabel(outLabel);
            return(emiter);
        }
예제 #4
0
        public void EmitSerialize(Emit emiter, Local value)
        {
            var elementType = value.LocalType.GetElementType();

            using (var length = emiter.DeclareLocal <int>("length"))
            {
                // length = value.Length
                emiter.LoadLocal(value);
                emiter.Call(value.LocalType.GetProperty(nameof(Array.Length)).GetMethod);
                emiter.StoreLocal(length);

                emiter.CallSerializerForType(length.LocalType, length);

                var loop      = emiter.DefineLabel();
                var loopCheck = emiter.DefineLabel();

                using (var element = emiter.DeclareLocal(elementType, "element"))
                    using (var i = emiter.DeclareLocal <int>("i"))
                    {
                        emiter.Branch(loopCheck);
                        emiter.MarkLabel(loop);

                        // element = value[i]
                        emiter.LoadLocal(value);
                        emiter.LoadLocal(i);
                        emiter.LoadElement(elementType);
                        emiter.StoreLocal(element);

                        // writer.Write((byte)i)
                        emiter.LoadArgument(1);
                        emiter.LoadLocal(i);
                        emiter.Convert <byte>();
                        emiter.CallVirtual(typeof(BinaryWriter).GetMethod(nameof(BinaryWriter.Write),
                                                                          new[] { typeof(byte) }));

                        emiter.CallSerializerForType(elementType, element);

                        // ++i
                        emiter.LoadLocal(i);
                        emiter.LoadConstant(1);
                        emiter.Add();
                        emiter.StoreLocal(i);

                        // i < length
                        emiter.MarkLabel(loopCheck);
                        emiter.LoadLocal(i);
                        emiter.LoadLocal(length);
                        emiter.BranchIfLess(loop);
                    }
            }
        }
        public void EmitSerialize(Emit emiter, Local value)
        {
            // ToDo check for null

            var elementType = value.LocalType.GetElementType();

            using (var length = emiter.DeclareLocal <int>("length"))
            {
                // length = value.Length
                emiter.LoadLocal(value);
                emiter.Call(value.LocalType.GetProperty(nameof(Array.Length)).GetMethod);
                emiter.StoreLocal(length);

                // ProudNetBinaryWriterExtensions.WriteScalar(writer, length)
                emiter.LoadArgument(1);
                emiter.LoadLocal(length);
                emiter.Call(ReflectionHelper.GetMethod((BinaryWriter x) => x.WriteScalar(default(int))));

                var loop      = emiter.DefineLabel();
                var loopCheck = emiter.DefineLabel();

                using (var element = emiter.DeclareLocal(elementType, "element"))
                    using (var i = emiter.DeclareLocal <int>("i"))
                    {
                        emiter.Branch(loopCheck);
                        emiter.MarkLabel(loop);

                        // element = value[i]
                        emiter.LoadLocal(value);
                        emiter.LoadLocal(i);
                        emiter.LoadElement(elementType);
                        emiter.StoreLocal(element);

                        emiter.CallSerializerForType(elementType, element);

                        // ++i
                        emiter.LoadLocal(i);
                        emiter.LoadConstant(1);
                        emiter.Add();
                        emiter.StoreLocal(i);

                        // i < length
                        emiter.MarkLabel(loopCheck);
                        emiter.LoadLocal(i);
                        emiter.LoadLocal(length);
                        emiter.BranchIfLess(loop);
                    }
            }
        }
        public void EmitSerialize(Emit emiter, Local value)
        {
            using (var address = emiter.DeclareLocal <string>("str"))
                using (var port = emiter.DeclareLocal <ushort>("port"))
                {
                    var isNull = emiter.DefineLabel();
                    var write  = emiter.DefineLabel();

                    // if (value == null) goto isNull
                    emiter.LoadLocal(value);
                    emiter.LoadNull();
                    emiter.BranchIfEqual(isNull);

                    // address = value.Address.ToString()
                    emiter.LoadLocal(value);
                    emiter.Call(typeof(IPEndPoint).GetProperty(nameof(IPEndPoint.Address)).GetMethod);
                    emiter.CallVirtual(typeof(IPAddress).GetMethod(nameof(IPAddress.ToString)));
                    emiter.StoreLocal(address);

                    // port = (ushort)value.Port
                    emiter.LoadLocal(value);
                    emiter.Call(typeof(IPEndPoint).GetProperty(nameof(IPEndPoint.Port)).GetMethod);
                    emiter.Convert <ushort>();
                    emiter.StoreLocal(port);
                    emiter.Branch(write);

                    emiter.MarkLabel(isNull);

                    // address = "255.255.255.255"
                    emiter.LoadConstant("255.255.255.255");
                    emiter.StoreLocal(address);

                    emiter.MarkLabel(write);

                    // ProudNetSrcBinaryWriterExtensions.WriteProudString(writer, address, false)
                    emiter.LoadArgument(1);
                    emiter.LoadLocal(address);
                    emiter.LoadConstant(false);
                    emiter.Call(ReflectionHelper.GetMethod((BinaryWriter x) =>
                                                           x.WriteProudString(default(string), default(bool))));

                    // writer.Write(port)
                    emiter.CallSerializerForType(typeof(ushort), port);
                }
        }
        public void EmitSerialize(Emit emiter, Local value)
        {
            var elementType = value.LocalType.GetElementType();

            using (var length = emiter.DeclareLocal <short>("length"))
            {
                // length = value.Length
                emiter.LoadLocal(value);
                emiter.Call(value.LocalType.GetProperty(nameof(Array.Length)).GetMethod);
                emiter.StoreLocal(length);

                emiter.CallSerializerForType(length.LocalType, length);

                var loop      = emiter.DefineLabel(nameof(ArrayWithScalarSerializer) + "Loop" + Guid.NewGuid());
                var loopCheck = emiter.DefineLabel(nameof(ArrayWithScalarSerializer) + "LoopCheck" + Guid.NewGuid());

                using (var element = emiter.DeclareLocal(elementType, "element"))
                    using (var i = emiter.DeclareLocal <int>("i"))
                    {
                        emiter.Branch(loopCheck);
                        emiter.MarkLabel(loop);

                        // element = value[i]
                        emiter.LoadLocal(value);
                        emiter.LoadLocal(i);
                        emiter.LoadElement(elementType);
                        emiter.StoreLocal(element);

                        emiter.CallSerializerForType(elementType, element);

                        // ++i
                        emiter.LoadLocal(i);
                        emiter.LoadConstant(1);
                        emiter.Add();
                        emiter.StoreLocal(i);

                        // i < length
                        emiter.MarkLabel(loopCheck);
                        emiter.LoadLocal(i);
                        emiter.LoadLocal(length);
                        emiter.BranchIfLess(loop);
                    }
            }
        }
예제 #8
0
        public void EmitSerialize(Emit <Action <BinaryWriter, object> > emiter, Local value)
        {
            var elementType = value.LocalType.GetElementType();

            if (_length <= 0)
            {
                return;
            }

            var loop      = emiter.DefineLabel(nameof(ArrayWithScalarSerializer) + "Loop" + Guid.NewGuid());
            var loopCheck = emiter.DefineLabel(nameof(ArrayWithScalarSerializer) + "LoopCheck" + Guid.NewGuid());

            using (var element = emiter.DeclareLocal(elementType, "element"))
                using (var i = emiter.DeclareLocal <int>("i"))
                {
                    emiter.Branch(loopCheck);
                    emiter.MarkLabel(loop);

                    // element = value[i]
                    emiter.LoadLocal(value);
                    emiter.LoadLocal(i);
                    emiter.LoadElement(elementType);
                    emiter.StoreLocal(element);

                    emiter.CallSerializerForType(elementType, element);

                    // ++i
                    emiter.LoadLocal(i);
                    emiter.LoadConstant(1);
                    emiter.Add();
                    emiter.StoreLocal(i);

                    // i < length
                    emiter.MarkLabel(loopCheck);
                    emiter.LoadLocal(i);
                    emiter.LoadConstant(_length);
                    emiter.BranchIfLess(loop);
                }
        }
        public void EmitDeserialize(Emit <Func <BinaryReader, object> > emiter, Local value)
        {
            var elementType = value.LocalType.GetElementType();
            var emptyArray  = emiter.DefineLabel(nameof(ArrayWithIntPrefixAndIndexSerializer) + "EmptyArray" + Guid.NewGuid());
            var end         = emiter.DefineLabel(nameof(ArrayWithIntPrefixAndIndexSerializer) + "End" + Guid.NewGuid());

            using (var length = emiter.DeclareLocal <int>("length"))
            {
                emiter.CallDeserializerForType(length.LocalType, length);

                // if(length < 1) {
                //  value = Array.Empty<>()
                //  return
                // }
                emiter.LoadLocal(length);
                emiter.LoadConstant(1);
                emiter.BranchIfLess(emptyArray);

                // value = new [length]
                emiter.LoadLocal(length);
                emiter.NewArray(elementType);
                emiter.StoreLocal(value);

                var loop      = emiter.DefineLabel(nameof(ArrayWithIntPrefixAndIndexSerializer) + "Loop" + Guid.NewGuid());
                var loopCheck = emiter.DefineLabel(nameof(ArrayWithIntPrefixAndIndexSerializer) + "LoopCheck" + Guid.NewGuid());

                using (var element = emiter.DeclareLocal(elementType, "element"))
                    using (var i = emiter.DeclareLocal <int>("i"))
                    {
                        emiter.MarkLabel(loop);

                        // reader.ReadByte() -> index
                        emiter.LoadArgument(1);
                        emiter.CallVirtual(typeof(BinaryReader).GetMethod(nameof(BinaryReader.ReadByte)));
                        emiter.Pop();

                        emiter.CallDeserializerForType(elementType, element);

                        // value[i] = element
                        emiter.LoadLocal(value);
                        emiter.LoadLocal(i);
                        emiter.LoadLocal(element);
                        emiter.StoreElement(elementType);

                        // ++i
                        emiter.LoadLocal(i);
                        emiter.LoadConstant(1);
                        emiter.Add();
                        emiter.StoreLocal(i);

                        // i < length
                        emiter.MarkLabel(loopCheck);
                        emiter.LoadLocal(i);
                        emiter.LoadLocal(length);
                        emiter.BranchIfLess(loop);
                    }
                emiter.Branch(end);
            }

            // value = Array.Empty<>()
            emiter.MarkLabel(emptyArray);
            emiter.Call(typeof(Array)
                        .GetMethod(nameof(Array.Empty))
                        .GetGenericMethodDefinition()
                        .MakeGenericMethod(elementType));
            emiter.StoreLocal(value);
            emiter.MarkLabel(end);
        }
        public void EmitDeserialize(Emit emiter, Local value)
        {
            var elementType = value.LocalType.GetElementType();
            var emptyArray  = emiter.DefineLabel();
            var end         = emiter.DefineLabel();

            using (var length = emiter.DeclareLocal <short>("length"))
            {
                emiter.CallDeserializerForType(length.LocalType, length);

                // if(length < 1) {
                //  value = Array.Empty<>()
                //  return
                // }
                emiter.LoadLocal(length);
                emiter.LoadConstant(1);
                emiter.BranchIfLess(emptyArray);

                // value = new [length]
                emiter.LoadLocal(length);
                emiter.NewArray(elementType);
                emiter.StoreLocal(value);

                var loop      = emiter.DefineLabel();
                var loopCheck = emiter.DefineLabel();

                // Little optimization for byte arrays
                if (elementType == typeof(byte))
                {
                    // value = reader.ReadBytes(length);
                    emiter.LoadArgument(1);
                    emiter.LoadLocal(length);
                    emiter.CallVirtual(typeof(BinaryReader).GetMethod(nameof(BinaryReader.ReadBytes)));
                    emiter.StoreLocal(value);
                    emiter.Branch(end);
                }
                else
                {
                    using (var element = emiter.DeclareLocal(elementType, "element"))
                        using (var i = emiter.DeclareLocal <int>("i"))
                        {
                            emiter.MarkLabel(loop);
                            emiter.CallDeserializerForType(elementType, element);

                            // value[i] = element
                            emiter.LoadLocal(value);
                            emiter.LoadLocal(i);
                            emiter.LoadLocal(element);
                            emiter.StoreElement(elementType);

                            // ++i
                            emiter.LoadLocal(i);
                            emiter.LoadConstant(1);
                            emiter.Add();
                            emiter.StoreLocal(i);

                            // i < length
                            emiter.MarkLabel(loopCheck);
                            emiter.LoadLocal(i);
                            emiter.LoadLocal(length);
                            emiter.BranchIfLess(loop);
                        }
                }

                emiter.Branch(end);
            }

            // value = Array.Empty<>()
            emiter.MarkLabel(emptyArray);
            emiter.Call(typeof(Array)
                        .GetMethod(nameof(Array.Empty))
                        .GetGenericMethodDefinition()
                        .MakeGenericMethod(elementType));
            emiter.StoreLocal(value);
            emiter.MarkLabel(end);
        }
예제 #11
0
 public override void Emit <T>(Emit <T> emitter)
 {
     emitter.Branch(_label);
 }
예제 #12
0
        private static void SerializeValueArray(PropertyInfo propInfo,
                                                Emit <Action <T, StringBuilder, StringBuilder> > serializationEmitter)
        {
            var loopBodyLabel      = serializationEmitter.DefineLabel();
            var loopConditionLabel = serializationEmitter.DefineLabel();

            var elementType = propInfo.PropertyType.GetElementType();
            var isString    = elementType == typeof(string);

            using (var stringLocal = serializationEmitter.DeclareLocal <string>())
                using (var iterationLocal = serializationEmitter.DeclareLocal <int>())
                {
                    serializationEmitter.LoadConstant(0);
                    serializationEmitter.StoreLocal(iterationLocal);
                    serializationEmitter.Branch(loopConditionLabel);
                    serializationEmitter.MarkLabel(loopBodyLabel);

                    serializationEmitter.LoadConstant(isString ? @"'{0}', " : "{0}, ");
                    serializationEmitter.LoadArgument(0); // instance
                    serializationEmitter.CallVirtual(propInfo.GetGetMethod());
                    serializationEmitter.LoadLocal(iterationLocal);
                    serializationEmitter.LoadElement(elementType);
                    if (isString)
                    {
                        serializationEmitter.Call(stringEscape);
                        serializationEmitter.LoadConstant(Environment.NewLine);
                        serializationEmitter.LoadConstant(@"\n");
                        serializationEmitter.CallVirtual(stringReplace);
                    }
                    else
                    {
                        serializationEmitter.Box(elementType);
                    }
                    serializationEmitter.Call(stringFormat);
                    serializationEmitter.StoreLocal(stringLocal);

                    // Append to hotfix builder
                    serializationEmitter.LoadArgument(1); // hotfixBuilder
                    serializationEmitter.LoadLocal(stringLocal);
                    serializationEmitter.Call(stringBuilderAppend);
                    serializationEmitter.Pop();

                    if (isString)
                    {
                        // Append to locale builder if (localeBuilder != null)
                        var localeBuilderMarker = serializationEmitter.DefineLabel();
                        serializationEmitter.LoadArgument(2); // instanceBuilder
                        serializationEmitter.LoadNull();
                        serializationEmitter.CompareEqual();
                        serializationEmitter.BranchIfTrue(localeBuilderMarker);
                        serializationEmitter.LoadArgument(2); // instanceBuilder
                        serializationEmitter.LoadLocal(stringLocal);
                        serializationEmitter.Call(stringBuilderAppend);
                        serializationEmitter.Pop();
                        serializationEmitter.MarkLabel(localeBuilderMarker);
                    }

                    serializationEmitter.LoadLocal(iterationLocal);
                    serializationEmitter.LoadConstant(1);
                    serializationEmitter.Add();
                    serializationEmitter.StoreLocal(iterationLocal);

                    serializationEmitter.MarkLabel(loopConditionLabel);
                    serializationEmitter.LoadLocal(iterationLocal);
                    serializationEmitter.LoadArgument(0); // instance
                    serializationEmitter.CallVirtual(propInfo.GetGetMethod());
                    serializationEmitter.LoadLength(elementType);
                    serializationEmitter.Convert <int>();
                    serializationEmitter.CompareLessThan();
                    serializationEmitter.BranchIfTrue(loopBodyLabel);
                }
        }
예제 #13
0
        void ExpectRawCharOrNull(char c, Action ifChar, Action ifNull)
        {
            var gotQuote = Emit.DefineLabel();
            var gotN     = Emit.DefineLabel();
            var done     = Emit.DefineLabel();

            RawReadChar(() => ThrowExpected("\"", "null")); // int
            Emit.Duplicate();                               // int int
            Emit.LoadConstant((int)c);                      // int int int
            Emit.BranchIfEqual(gotQuote);                   // int
            Emit.LoadConstant((int)'n');                    // int n
            Emit.BranchIfEqual(gotN);                       // --empty--
            ThrowExpected("\"", "null");                    // --empty--

            Emit.MarkLabel(gotQuote);                       // int
            Emit.Pop();                                     // --empty--
            ifChar();                                       // ???
            Emit.Branch(done);                              // ???

            Emit.MarkLabel(gotN);                           // --empty--
            ExpectChar('u');                                // --empty--
            ExpectChar('l');                                // --empty--
            ExpectChar('l');                                // --empty--
            ifNull();                                       // ???

            Emit.MarkLabel(done);                           // --empty--
        }
예제 #14
0
        private void GenerateFunctionInner(Emit<MuftecFunction> funcDef, Queue<MuftecStackItem> execStack, Local runtimeStack, MuftecStackItem lastItem = default(MuftecStackItem))
        {
            DebugMsg("- Call stack -> {0}", String.Join(", ", execStack.ToArray()));

            var stackPush = typeof (Stack<MuftecStackItem>).GetMethod("Push");

            while (execStack.Count > 0)
            {
                var currStackItem = execStack.Dequeue();
                DebugMsg("- Popping stack item: " + currStackItem.ToDebugString());

                switch (currStackItem.Type)
                {
                    // Run a user defined function
                    case MuftecType.Function:
                        // Find the function and create an IL call
                        var funcName = currStackItem.Item.ToString();
                        DebugMsg(" -- Call function {0}", funcName);
                        var func = _funcCache[funcName];
                        funcDef.LoadArgument(0); // Load OpCodeData into stack
                        funcDef.Call(func);
                        break;

                    // Execute a library opcode
                    case MuftecType.OpCode:
                        // Translate opcode into direct call
                        var opCodeName = currStackItem.Item.ToString();
                        DebugMsg(" >> Call opcode {0}", opCodeName);
                        var opCode = _system.FindOpCode(opCodeName);

                        // If this is an internal opcode, we need to handle it at this level
                        if (opCode.Attribute.Extern)
                        {
                            switch (opCode.Attribute.OpCodeName)
                            {
                                case "!":
                                case "@":
                                    throw new MuftecCompilerException("Variables not supported in the fabricator at line " + currStackItem.LineNumber);
                                case "loadlibdll":
                                    funcDef.LoadLocal(runtimeStack);
                                    funcDef.Call(typeof (Shared).GetMethod("PopStr"));
                                    _system.AddLibrary(lastItem.ToString());
                                    break;
                            }
                        }
                        else
                        {
                            funcDef.LoadArgument(0); // Load OpCodeData into the stack
                            funcDef.Call(opCode.Pointer.Method); // Call OpCode function
                        }

                        // Handle post-execution magic
                        var magic = opCode.Attribute.Magic;
                        switch (magic)
                        {
                            case MagicOpcodes.Abort:
                                // End exeuction
                                DebugMsg(" ---- Abort");
                                funcDef.LoadConstant(0);
                                funcDef.Call(typeof (Environment).GetMethod("Exit"));
                                return;
                            case MagicOpcodes.Exit:
                                DebugMsg(" ---- Exit");
                                // Exit out of this loop
                                return;
                        }
                        break;

                    // Handle a conditional container
                    case MuftecType.Conditional:
                        var container = currStackItem.Item as ConditionalContainer;
                        if (container == null)
                            throw new MuftecCompilerException("Unable to process conditional statement at line " + currStackItem.LineNumber);

                        DebugMsg(" -- Container");
                        var ltLabel = funcDef.DefineLabel();
                        var endLabel = funcDef.DefineLabel();
                        funcDef.LoadLocal(runtimeStack); // Get the RuntimeStack
                        funcDef.Call(typeof (Shared).GetMethod("PopInt")); // Call PopInt on RuntimeStack
                        funcDef.BranchIfFalse(ltLabel);

                        // GT operations
                        DebugMsg(" -- Starting true condition");
                        GenerateFunctionInner(funcDef, container.TrueQueue, runtimeStack, lastItem);
                        funcDef.Branch(endLabel);

                        // LT operations
                        funcDef.MarkLabel(ltLabel);
                        DebugMsg(" -- Starting false condition");
                        GenerateFunctionInner(funcDef, container.FalseQueue, runtimeStack, lastItem);

                        funcDef.MarkLabel(endLabel);
                        DebugMsg(" -- Conditions done");
                        break;

                    // Add item to the runtime stack
                    case MuftecType.Integer:
                        DebugMsg(" -- Pushing int {0} to RS", currStackItem.ToString());
                        funcDef.LoadLocal(runtimeStack); // Get the RuntimeStack
                        funcDef.LoadConstant((int)currStackItem.Item);
                        funcDef.LoadConstant(currStackItem.LineNumber);
                        funcDef.NewObject<MuftecStackItem, int, int>();
                        funcDef.Call(stackPush);
                        break;
                    case MuftecType.Float:
                        DebugMsg(" -- Pushing float {0} to RS", currStackItem.ToString());
                        funcDef.LoadLocal(runtimeStack); // Get the RuntimeStack
                        funcDef.LoadConstant((double)currStackItem.Item);
                        funcDef.LoadConstant(currStackItem.LineNumber);
                        funcDef.NewObject<MuftecStackItem, double, int>();
                        funcDef.Call(stackPush);
                        break;
                    case MuftecType.String:
                        DebugMsg(" -- Pushing string {0} to RS", currStackItem.ToString());
                        funcDef.LoadLocal(runtimeStack); // Get the RuntimeStackp =
                        funcDef.LoadConstant((string)currStackItem.Item);
                        funcDef.LoadConstant(currStackItem.LineNumber);
                        funcDef.NewObject<MuftecStackItem, string, int>();
                        funcDef.Call(stackPush);
                        break;
                    case MuftecType.ArrayMarker:
                        DebugMsg(" -- Pushing array marker to RS");
                        funcDef.LoadLocal(runtimeStack); // Get the RuntimeStack
                        funcDef.LoadConstant((int)currStackItem.Item);
                        funcDef.Call(typeof(MuftecStackItem).GetMethod("CreateArrayMarker"));
                        funcDef.Call(stackPush);
                        break;
                }

                lastItem = currStackItem;
            }
        }
예제 #15
0
        public static Emit <Func <IEnumerable <object>, IEnumerable <T> > > GenerateMapper <T>()
        {
            Type type = typeof(T);
            Emit <Func <IEnumerable <object>, IEnumerable <T> > > emit = null;

            if (_mappers.ContainsKey(type.FullName))
            {
                emit = (Emit <Func <IEnumerable <object>, IEnumerable <T> > >)_mappers[type.FullName];
            }
            else
            {
                ConstructorInfo listConstructor = typeof(List <T>).GetConstructor(new Type[] { });
                MethodInfo      listAdd         = typeof(List <T>).GetMethod("Add", new Type[] { typeof(T) });

                Emit <Func <IEnumerable <object>, IEnumerable <T> > > emiter = Emit <Func <IEnumerable <object>, IEnumerable <T> > > .NewDynamicMethod(type.Name + "Mapper");


                var enumeratorLocal = emiter.DeclareLocal <IEnumerator <object> >("enumerator");
                var listLocal       = emiter.DeclareLocal <List <T> >("list");
                var cacheLocal      = emiter.DeclareLocal <IDictionary <object, object> >("cache");


                var loopFinishedLabel    = emiter.DefineLabel("loopFinished");
                var loopCheckLabel       = emiter.DefineLabel("loopCheck");
                var loopBeginLabel       = emiter.DefineLabel("loopBegin");
                var finallyFinishedLabel = emiter.DefineLabel("finallyFinished");
                var isNullLabel          = emiter.DefineLabel("isNull");


                emiter.NewObject(listConstructor);
                emiter.StoreLocal(listLocal);
                emiter.NewObject(DictionaryConstructor_Object_Object);
                emiter.StoreLocal(cacheLocal);

                emiter.LoadArgument(0);
                emiter.CallVirtual(IEnumerable_Object_GetEnumerator);
                emiter.StoreLocal(enumeratorLocal);

                //try {
                var exceptionBlock = emiter.BeginExceptionBlock();
                emiter.Branch(loopCheckLabel);

                emiter.MarkLabel(loopBeginLabel);

                emiter.LoadLocal(listLocal);
                emiter.LoadLocal(enumeratorLocal);
                emiter.CallVirtual(IEnumerator_Object_GetCurrent);
                emiter.CastClass <IDictionary <string, object> >();
                emiter.LoadLocal(cacheLocal);
                emiter.LoadConstant("");
                emiter.Call(GenerateRowMapper(type)); // var rowResult = rowMapper ( row, cache, depthString = "" );
                emiter.Duplicate();
                emiter.LoadNull();
                emiter.BranchIfEqual(isNullLabel);


                emiter.CastClass(typeof(T));
                emiter.Call(listAdd); // listLocal.Add((T)rowResult);
                emiter.Branch(loopCheckLabel);

                emiter.MarkLabel(isNullLabel);
                emiter.Pop();
                emiter.Pop();


                emiter.MarkLabel(loopCheckLabel);
                emiter.LoadLocal(enumeratorLocal);
                emiter.CallVirtual(IEnumerator_MoveNext);
                emiter.BranchIfTrue(loopBeginLabel);
                emiter.Leave(loopFinishedLabel);
                //}
                //finallY {
                var finallyBlock = emiter.BeginFinallyBlock(exceptionBlock);
                emiter.LoadNull();
                emiter.LoadLocal(enumeratorLocal);
                emiter.CompareEqual();
                emiter.BranchIfTrue(finallyFinishedLabel);
                emiter.LoadLocal(enumeratorLocal);
                emiter.CallVirtual(IEnumerator_Dispose);
                emiter.MarkLabel(finallyFinishedLabel);
                emiter.EndFinallyBlock(finallyBlock);
                emiter.EndExceptionBlock(exceptionBlock);
                //}

                emiter.MarkLabel(loopFinishedLabel);
                emiter.LoadLocal(listLocal);
                emiter.Return(); // return listLocal;
                _mapperDelegates.Add(type.FullName, emiter.CreateDelegate());
                _mappers.Add(type.FullName, emiter);
                emit = emiter;
            }
            return(emit);
        }
예제 #16
0
        public void EmitDeserialize(Emit emiter, Local value)
        {
            var elementType = value.LocalType.GetElementType();
            var emptyArray  = emiter.DefineLabel();
            var end         = emiter.DefineLabel();

            using (var length = emiter.DeclareLocal <T>("length"))
            {
                emiter.CallDeserializerForType(length.LocalType, length);

                // if(length < 1) {
                //  value = Array.Empty<>()
                //  return
                // }
                emiter.LoadLocal(length);
                emiter.LoadConstant(1);
                emiter.BranchIfLess(emptyArray);

                // value = new [length]
                emiter.LoadLocal(length);
                emiter.NewArray(elementType);
                emiter.StoreLocal(value);

                var loop      = emiter.DefineLabel();
                var loopCheck = emiter.DefineLabel();

                using (var element = emiter.DeclareLocal(elementType, "element"))
                    using (var i = emiter.DeclareLocal <T>("i"))
                    {
                        emiter.MarkLabel(loop);

                        if (_compiler != null)
                        {
                            _compiler.EmitDeserialize(emiter, element);
                        }
                        else if (_serializer != null)
                        {
                            emiter.CallDeserializer(_serializer, element);
                        }
                        else
                        {
                            emiter.CallDeserializerForType(elementType, element);
                        }

                        // value[i] = element
                        emiter.LoadLocal(value);
                        emiter.LoadLocal(i);
                        emiter.LoadLocal(element);
                        emiter.StoreElement(elementType);

                        // ++i
                        emiter.LoadLocal(i);
                        emiter.LoadConstant(1);
                        emiter.Add();
                        emiter.StoreLocal(i);

                        // i < length
                        emiter.MarkLabel(loopCheck);
                        emiter.LoadLocal(i);
                        emiter.LoadLocal(length);
                        emiter.BranchIfLess(loop);
                    }
                emiter.Branch(end);
            }

            // value = Array.Empty<>()
            emiter.MarkLabel(emptyArray);
            emiter.Call(typeof(Array)
                        .GetMethod(nameof(Array.Empty))
                        .GetGenericMethodDefinition()
                        .MakeGenericMethod(elementType));
            emiter.StoreLocal(value);
            emiter.MarkLabel(end);
        }