Beispiel #1
0
        public Emit <Func <int> > EmitByteCode(CompilerContext context, Emit <Func <int> > emiter)
        {
            if (Operator == BinaryOperator.CONCAT)
            {
                return(EmitConcat(context, emiter));
            }
            emiter = Left.EmitByteCode(context, emiter);
            emiter = Right.EmitByteCode(context, emiter);
            switch (Operator)
            {
            case BinaryOperator.ADD:
            {
                emiter = emiter.Add();
                break;
            }

            case BinaryOperator.SUB:
            {
                emiter = emiter.Subtract();
                break;
            }

            case BinaryOperator.MULTIPLY:
            {
                emiter = emiter.Multiply();
                break;
            }

            case BinaryOperator.DIVIDE:
            {
                emiter = emiter.Divide();
                break;
            }

            case BinaryOperator.EQUALS:
            {
                emiter = emiter.CompareEqual();
                break;
            }

            case BinaryOperator.DIFFERENT:
            {
                emiter = emiter.CompareEqual();
                emiter = emiter.Not();
                break;
            }

            case BinaryOperator.OR:
            {
                emiter = emiter.Or();
                break;
            }

            case BinaryOperator.AND:
            {
                emiter = emiter.And();
                break;
            }

            case BinaryOperator.LESSER:
            {
                emiter = emiter.CompareLessThan();
                break;
            }

            case BinaryOperator.GREATER:
            {
                emiter = emiter.CompareGreaterThan();
                break;
            }
            }

            return(emiter);
        }
        public void EmitDeserialize(Emit emiter, Local value)
        {
            var elementType = value.LocalType.GetElementType();
            var emptyArray  = emiter.DefineLabel(nameof(ArrayWithScalarSerializer) + "EmptyArray" + Guid.NewGuid());
            var end         = emiter.DefineLabel(nameof(ArrayWithScalarSerializer) + "End" + Guid.NewGuid());

            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(nameof(ArrayWithScalarSerializer) + "Loop" + Guid.NewGuid());
                var loopCheck = emiter.DefineLabel(nameof(ArrayWithScalarSerializer) + "LoopCheck" + Guid.NewGuid());

                // 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);
        }
Beispiel #3
0
        public void EmitSerialize(Emit emiter, Local value)
        {
            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);

                var elementType = value.LocalType.GetElementType();

                var loop          = emiter.DefineLabel();
                var loopCheck     = emiter.DefineLabel();
                var loopFill      = emiter.DefineLabel();
                var loopFillCheck = 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);

                        emiter.Branch(loopFillCheck);
                        emiter.MarkLabel(loopFill);
                        // element = 0
                        emiter.LoadConstant(0);
                        emiter.StoreLocal(element);

                        emiter.CallSerializerForType(elementType, element);
                        // ++i
                        emiter.LoadLocal(i);
                        emiter.LoadConstant(1);
                        emiter.Add();
                        emiter.StoreLocal(i);

                        emiter.MarkLabel(loopFillCheck);
                        emiter.LoadLocal(i);
                        emiter.LoadConstant(_size);
                        emiter.BranchIfLess(loopFill);
                    }
            }
        }
        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);
                }
        }
Beispiel #5
0
 public static Emit <TDelegate> Increment <TDelegate>(this Emit <TDelegate> emiter, Type valueType)
 {
     emiter.LoadConstantOne(valueType);
     emiter.Add();
     return(emiter);
 }
Beispiel #6
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);
        }
Beispiel #7
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 <int>("length"))
            {
                // length = ProudNetBinaryReaderExtensions.ReadScalar(reader)
                emiter.LoadArgument(1);
                emiter.Call(ReflectionHelper.GetMethod((BinaryReader x) => x.ReadScalar()));
                emiter.StoreLocal(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);

                // Little optimization for byte arrays
                if (elementType == typeof(byte))
                {
                    // value = reader.ReadBytes(length);
                    emiter.LoadArgument(1);
                    emiter.LoadLocal(length);
                    emiter.Call(ReflectionHelper.GetMethod((BinaryReader x) => x.ReadBytes(default(int))));
                    emiter.StoreLocal(value);
                }
                else
                {
                    var loop      = emiter.DefineLabel();
                    var loopCheck = emiter.DefineLabel();

                    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);
        }
Beispiel #8
0
 [Fact] public void TestAdd() => TestRoundTrip("x += 3", Emit.Add(Emit.Name("x"), Emit.Const(3)), ScriptParser.Expression);
Beispiel #9
0
 [Fact] public void OrderTest06() => TestRoundTrip(
     "x.y += 10",
     Emit.Add(
         Emit.Member(Emit.Name("x"), Emit.Name("y")),
         Emit.Const(10)
         ), ScriptParser.Expression);