private bool TryGenKnownType(NodeTree node, bool requireBoxing, out object prototype)
            {
                // Try Primitive Type
                Type type;

                if (PrimitiveTypeDic.TryGetValue(node.Type, out type))
                {
                    // reader.Read<T>()
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Call, PrimitiveReaderDic[type]);
                    if (requireBoxing)
                    {
                        il.Emit(OpCodes.Box, type);
                    }

                    prototype = Activator.CreateInstance(type);

                    return(true);
                }
                // Try String
                else if (node.Type == "string")
                {
                    GenReadString();

                    prototype = "";

                    return(true);
                }
                else
                {
                    prototype = null;
                    return(false);
                }
            }
Esempio n. 2
0
            private bool TryGenKnownType(NodeTree node, bool requireUnboxing, Action <ILGenerator> loader)
            {
                // Try Primitive Type
                Type type;

                if (PrimitiveTypeDic.TryGetValue(node.Type, out type))
                {
                    // writer.Write<T>((type)value)
                    il.Emit(OpCodes.Ldarg_0);
                    loader(il);
                    if (requireUnboxing)
                    {
                        il.Emit(OpCodes.Unbox_Any, type);
                    }
                    il.Emit(OpCodes.Call, PrimitiveWriterDic[type]);

                    return(true);
                }
                // Try String
                else if (node.Type == "string")
                {
                    il.Emit(OpCodes.Ldarg_0);
                    loader(il);
                    if (requireUnboxing)
                    {
                        il.Emit(OpCodes.Castclass, typeof(string));
                    }
                    il.Emit(OpCodes.Call, WriteAlignedString);

                    return(true);
                }
                else
                {
                    return(false);
                }
            }
Esempio n. 3
0
            private void GenWriteDic(NodeTree node, Action <ILGenerator> loader)
            {
                Type keytype, valuetype;

                NodeTree pair = node.Children[0].Children[1];

                // Determine Key/Value Type
                if (PrimitiveTypeDic.TryGetValue(pair.Children[0].Type, out keytype))
                {
                }
                else if (pair.Children[0].Type == "string")
                {
                    keytype = typeof(string);
                }
                else
                {
                    keytype = typeof(object);
                }

                if (PrimitiveTypeDic.TryGetValue(pair.Children[1].Type, out valuetype))
                {
                }
                else if (pair.Children[1].Type == "string")
                {
                    valuetype = typeof(string);
                }
                else
                {
                    valuetype = typeof(object);
                }

                // Load Dictionary<keytype, valuetype>
                Type       dictype = typeof(DynamicAssetDictionary <,>).MakeGenericType(keytype, valuetype);
                MethodInfo getter  = dictype.GetMethod("Item", new Type[] { keytype, valuetype });
                MethodInfo Count   = dictype.GetProperty("Count").GetMethod;
                int        dic     = locman.AllocLocal(dictype);

                loader(il);
                il.Emit(OpCodes.Castclass, dictype);
                il.EmitStloc(dic);

                // Write Count
                il.Emit(OpCodes.Ldarg_0);
                il.EmitLdloc(dic);
                il.Emit(OpCodes.Callvirt, Count);
                il.Emit(OpCodes.Call, WriteInt);

                // Write KeyValuePairs

                // foreach(var kv in dic)
                Type       enumtype      = typeof(Dictionary <,> .Enumerator).MakeGenericType(keytype, valuetype);
                int        enumerator    = locman.AllocLocal(enumtype);
                Type       kvtype        = typeof(KeyValuePair <,>).MakeGenericType(keytype, valuetype);
                int        kv            = locman.AllocLocal(kvtype);
                MethodInfo getenumerator = dictype.GetMethod("GetEnumerator");
                MethodInfo movenext      = enumtype.GetMethod("MoveNext");
                MethodInfo getcurrent    = enumtype.GetProperty("Current").GetMethod;
                MethodInfo getkey        = kvtype.GetProperty("Key").GetMethod;
                MethodInfo getvalue      = kvtype.GetProperty("Value").GetMethod;


                var l_foreachstart = il.DefineLabel();
                var l_movenext     = il.DefineLabel();

                // Get Enumerator
                loader(il);
                il.Emit(OpCodes.Castclass, dictype);
                il.Emit(OpCodes.Callvirt, getenumerator);
                il.EmitStloc(enumerator);
                il.BeginExceptionBlock();
                il.Emit(OpCodes.Br, l_movenext);

                // Main
                il.MarkLabel(l_foreachstart);
                il.EmitLdloca(enumerator);
                il.Emit(OpCodes.Call, getcurrent);
                il.EmitStloc(kv);

                // Key
                GenWriteUnknownType(pair.Children[0], requireUnboxing: false, loader: (cil) => {
                    cil.EmitLdloca(kv);
                    cil.Emit(OpCodes.Call, getkey);
                });

                // Value
                GenWriteUnknownType(pair.Children[1], requireUnboxing: false, loader: (cil) => {
                    cil.EmitLdloca(kv);
                    cil.Emit(OpCodes.Call, getvalue);
                });

                // MoveNext
                il.MarkLabel(l_movenext);
                il.EmitLdloca(enumerator);
                il.Emit(OpCodes.Call, movenext);
                il.Emit(OpCodes.Brtrue, l_foreachstart);

                // Finally(Dispose)
                il.BeginFinallyBlock();
                il.EmitLdloca(enumerator);
                il.Emit(OpCodes.Constrained, enumtype);
                il.Emit(OpCodes.Callvirt, Dispose);
                il.EndExceptionBlock();


                if (node.Children[0].IsAligned)
                {
                    GenAlign();
                }

                locman.ReleaseLocal(enumtype);
                locman.ReleaseLocal(kvtype);
                locman.ReleaseLocal(dictype);
            }
Esempio n. 4
0
            private void GenWriteArray(NodeTree node, Action <ILGenerator> loader)
            {
                NodeTree elem = node.Children[1];

                // Try Primitive Type
                Type elemtype;

                if (PrimitiveTypeDic.TryGetValue(elem.Type, out elemtype))
                {
                    // reader.ReadValueArray<T>()
                    var writefunc = WriteValueArray.MakeGenericMethod(elemtype);
                    il.Emit(OpCodes.Ldarg_0);
                    loader(il);
                    il.Emit(OpCodes.Castclass, elemtype.MakeArrayType());
                    il.Emit(OpCodes.Call, writefunc);
                }
                // Try String
                else if (elem.Type == "string")
                {
                    Type arytype = typeof(string).MakeArrayType();
                    int  ary     = locman.AllocLocal(arytype);
                    loader(il);
                    il.Emit(OpCodes.Castclass, arytype);
                    il.EmitStloc(ary);

                    // Write length
                    // writer.WriteInt(ary.Length);
                    il.Emit(OpCodes.Ldarg_0);
                    il.EmitLdloc(ary);
                    il.Emit(OpCodes.Ldlen);
                    il.Emit(OpCodes.Conv_I4);
                    il.Emit(OpCodes.Call, WriteInt);

                    int i = locman.AllocLocal(typeof(int));
                    // for(int i = 0; i < ary.Length; i++)
                    il.EmitFor(i,
                               cond: (cil) => {
                        il.EmitLdloc(ary);
                        il.Emit(OpCodes.Ldlen);
                        il.Emit(OpCodes.Conv_I4);
                        il.EmitLdloc(i);
                        return(OpCodes.Ble_S);
                    },
                               block: (cil) => {
                        // w.WriteAlignedString(ary[i]);
                        il.Emit(OpCodes.Ldarg_0);
                        il.EmitLdloc(ary);
                        il.EmitLdloc(i);
                        il.Emit(OpCodes.Ldelem_Ref);
                        il.Emit(OpCodes.Call, WriteAlignedString);
                    }
                               );
                    locman.ReleaseLocal(typeof(int));
                    locman.ReleaseLocal(arytype);
                }
                else if (elem.Type == "map")
                {
                    throw new NotImplementedException("Array of map is not supported");
                }
                // Object
                else
                {
                    // Load DynamicAssetArray.elems
                    Type arytype = typeof(IDynamicAssetBase).MakeArrayType();
                    int  ary     = locman.AllocLocal(arytype);
                    loader(il);
                    il.Emit(OpCodes.Castclass, typeof(DynamicAssetArray));
                    il.Emit(OpCodes.Ldfld, DynamicAssetArrayelems);
                    il.EmitStloc(ary);

                    // Write length
                    // writer.WriteInt(ary.Length);
                    il.Emit(OpCodes.Ldarg_0);
                    il.EmitLdloc(ary);
                    il.Emit(OpCodes.Ldlen);
                    il.Emit(OpCodes.Conv_I4);
                    il.Emit(OpCodes.Call, WriteInt);

                    // for(int i = 0; i < ary.Length; i++)
                    int i = locman.AllocLocal(typeof(int));
                    il.EmitFor(i,
                               (cil) => {
                        il.EmitLdloc(ary);
                        il.Emit(OpCodes.Ldlen);
                        il.Emit(OpCodes.Conv_I4);
                        il.EmitLdloc(i);
                        return(OpCodes.Ble);
                    },
                               (cil) => {
                        // GenWriteUnknownType(ary[i]);
                        GenWriteUnknownType(elem, requireUnboxing: false, loader: (ccil) => {
                            ccil.EmitLdloc(ary);
                            ccil.EmitLdloc(i);
                            ccil.Emit(OpCodes.Ldelem_Ref);
                        });
                    }
                               );

                    locman.ReleaseLocal(typeof(int));
                    locman.ReleaseLocal(arytype);
                }
                if (node.IsAligned)
                {
                    GenAlign();
                }
            }
            private object GenReadDic(NodeTree node)
            {
                Type keytype, valuetype;

                NodeTree pair = node.Children[0].Children[1];

                // Determine Key/Value Type
                if (PrimitiveTypeDic.TryGetValue(pair.Children[0].Type, out keytype))
                {
                }
                else if (pair.Children[0].Type == "string")
                {
                    keytype = typeof(string);
                }
                else
                {
                    keytype = typeof(object);
                }

                if (PrimitiveTypeDic.TryGetValue(pair.Children[1].Type, out valuetype))
                {
                }
                else if (pair.Children[1].Type == "string")
                {
                    valuetype = typeof(string);
                }
                else
                {
                    valuetype = typeof(object);
                }

                string keyFQN   = (keytype == typeof(object)) ? protoman.GetFQN(pair.Children[0].Type) : keytype.GetCSharpName();
                string valueFQN = (valuetype == typeof(object)) ? protoman.GetFQN(pair.Children[1].Type) : valuetype.GetCSharpName();

                // int cnt = reader.ReadInt();
                int cnt = locman.AllocLocal(typeof(int));

                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Call, ReadInt);
                il.EmitStloc(cnt);

                // Create Dictionary<keytype, valuetype>
                Type       dictype = typeof(DynamicAssetDictionary <,>).MakeGenericType(keytype, valuetype);
                MethodInfo add     = dictype.GetMethod("Add", new Type[] { keytype, valuetype });

                il.EmitLdloc(cnt);
                il.Emit(OpCodes.Ldstr, keyFQN);
                il.Emit(OpCodes.Ldstr, valueFQN);
                il.Emit(OpCodes.Newobj, dictype.GetConstructor(BindingFlags.InvokeMethod | BindingFlags.Instance |
#if DEBUG
                                                               BindingFlags.Public
#else
                                                               BindingFlags.NonPublic
#endif
                                                               , null, new Type[] { typeof(int), typeof(string), typeof(string) }, null));

                // Read KeyValuePairs

                // for(int i = 0; i < cnt; i++)
                int i = locman.AllocLocal(typeof(int));
                il.EmitFor(i,
                           (cil) => {
                    il.EmitLdloc(i);
                    il.EmitLdloc(cnt);
                    return(OpCodes.Bge);
                },
                           (cil) => {
                    // dic.Add(
                    il.Emit(OpCodes.Dup);

                    // Read Key
                    GenReadUnknownType(pair.Children[0], requireBoxing: false);

                    // Read Value
                    GenReadUnknownType(pair.Children[1], requireBoxing: false);

                    // Add KeyValuePair
                    il.Emit(OpCodes.Callvirt, add);
                }
                           );
                locman.ReleaseLocal(typeof(int));
                locman.ReleaseLocal(typeof(int));

                if (node.Children[0].IsAligned)
                {
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldc_I4_4);
                    il.Emit(OpCodes.Call, AlignReader);
                }

                // Make prototype
                return(Activator.CreateInstance(dictype, BindingFlags.Instance |
#if DEBUG
                                                BindingFlags.Public
#else
                                                BindingFlags.NonPublic
#endif
                                                , null, new object[] { 0, keyFQN, valueFQN }, null));
            }
            private object GenReadArray(NodeTree node)
            {
                NodeTree elem = node.Children[1];
                object   proto;

                // Try Primitive Type
                Type elemtype;

                if (PrimitiveTypeDic.TryGetValue(elem.Type, out elemtype))
                {
                    // reader.ReadValueArray<T>()
                    var readfunc = ReadValueArray.MakeGenericMethod(elemtype);
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Call, readfunc);

                    proto = Activator.CreateInstance(elemtype.MakeArrayType(), new object[] { 0 });
                }
                // Try String
                else if (elem.Type == "string")
                {
                    // var ary = new string[reader.ReadInt()];
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Call, ReadInt);
                    il.Emit(OpCodes.Newarr, typeof(string));

                    int i = locman.AllocLocal(typeof(int));
                    // for(int i = 0; i < ary.Length; i++)
                    il.EmitFor(i,
                               cond: (cil) => {
                        il.Emit(OpCodes.Dup);
                        il.Emit(OpCodes.Ldlen);
                        il.Emit(OpCodes.Conv_I4);
                        il.EmitLdloc(i);
                        return(OpCodes.Ble_S);
                    },
                               block: (cil) => {
                        // ary[i] = r.ReadAlignedString();
                        il.Emit(OpCodes.Dup);
                        il.EmitLdloc(i);
                        GenReadString();
                        il.Emit(OpCodes.Stelem, typeof(string));
                    }
                               );
                    locman.ReleaseLocal(typeof(int));

                    proto = new string[0];
                }
                else if (elem.Type == "map")
                {
                    throw new NotImplementedException("Array of map is not supported");
                }
                // Object
                else
                {
                    string FQN = protoman.GetFQN(elem.Type);

                    // vec = new DynamicAssetArray(reader.ReadInt(), protoname)
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Call, ReadInt);

                    il.Emit(OpCodes.Ldstr, FQN);

                    il.Emit(OpCodes.Newobj, DynamicAssetArrayCtor);

                    // ary = vec.elems;
                    il.Emit(OpCodes.Dup);
                    il.Emit(OpCodes.Ldfld, DynamicAssetArrayelems);

                    // for(int i = 0; i < ary.Length; i++)
                    int i = locman.AllocLocal(typeof(int));
                    il.EmitFor(i,
                               (cil) => {
                        il.Emit(OpCodes.Dup);
                        il.Emit(OpCodes.Ldlen);
                        il.Emit(OpCodes.Conv_I4);
                        il.EmitLdloc(i);
                        return(OpCodes.Ble);
                    },
                               (cil) => {
                        // ary[i] = new DynamicAsset(GenReadUnkownType());
                        il.Emit(OpCodes.Dup);
                        il.EmitLdloc(i);

                        // Fallback
                        GenReadUnknownType(elem, requireBoxing: false);

                        il.Emit(OpCodes.Stelem_Ref);
                    }
                               );

                    il.Emit(OpCodes.Pop);

                    proto = new DynamicAssetArray(0, FQN);
                }
                if (node.IsAligned)
                {
                    GenAlign();
                }

                return(proto);
            }