From: jpbruyere Date: Tue, 22 Nov 2016 16:49:16 +0000 (+0100) Subject: debug X-Git-Tag: v0.5.1~63^2~34 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=f416267010e2d44badae89ceb76df3b27dd69a67;p=jp%2Fcrow.git debug --- diff --git a/Crow.csproj b/Crow.csproj index 6e43e8dd..6cae0a7e 100644 --- a/Crow.csproj +++ b/Crow.csproj @@ -147,6 +147,7 @@ + diff --git a/src/IML/Context.cs b/src/IML/Context.cs index e5d33374..965d0062 100644 --- a/src/IML/Context.cs +++ b/src/IML/Context.cs @@ -38,11 +38,12 @@ namespace Crow.IML { public XmlTextReader reader = null; public Type RootType = null; - public Node CurrentNode = null; + public int CurrentIndex = 0; + public DynamicMethod dm = null; public ILGenerator il = null; //public SubNodeType curSubNodeType; - public Stack nodesStack = new Stack (); + public NodeStack nodesStack = new NodeStack (); public Dictionary> Names = new Dictionary>(); public Dictionary> PropertyBindings = new Dictionary> (); @@ -64,13 +65,31 @@ namespace Crow.IML } public NodeAddress CurrentNodeAddress { - get { - NodeAddress tmp = new NodeAddress(nodesStack.ToArray ()); - tmp.Add (CurrentNode); - return tmp; + get { + Node[] n = nodesStack.ToArray (); + Array.Reverse (n); + return new NodeAddress(n); } } + public Type CurrentNodeType { + get { return nodesStack.Peek().CrowType; } + } + public MethodInfo CurrentAddMethod { + get { + if (typeof (Group).IsAssignableFrom (CurrentNodeType)) + return CompilerServices.miAddChild; + if (typeof (Container).IsAssignableFrom (CurrentNodeType)) + return CompilerServices.miSetChild; + if (typeof (TemplatedContainer).IsAssignableFrom (CurrentNodeType)) + return CurrentIndex < 0 ? CompilerServices.miLoadTmp : CompilerServices.miSetContent; + if (typeof (TemplatedGroup).IsAssignableFrom (CurrentNodeType)) + return CurrentIndex < 0 ? CompilerServices.miLoadTmp : CompilerServices.miAddItem; + if (typeof (TemplatedControl).IsAssignableFrom (CurrentNodeType)) + return CompilerServices.miLoadTmp; + return null; + } + } void initILGen () { il.DeclareLocal (typeof (GraphicObject)); diff --git a/src/IML/Node.cs b/src/IML/Node.cs index a503a3bb..14cffdb2 100644 --- a/src/IML/Node.cs +++ b/src/IML/Node.cs @@ -28,7 +28,7 @@ namespace Crow.IML /// /// IML Node are the elements of the interface XML, /// - public class Node + public struct Node { public Type CrowType; /// @@ -59,43 +59,6 @@ namespace Crow.IML public bool HasTemplate { get { return typeof (TemplatedControl).IsAssignableFrom (CrowType);} } - public MethodInfo AddMethod { - get { - if (typeof (Group).IsAssignableFrom (CrowType)) - return CompilerServices.miAddChild; - if (typeof (Container).IsAssignableFrom (CrowType)) - return CompilerServices.miSetChild; - if (typeof (TemplatedContainer).IsAssignableFrom (CrowType)) - return Index < 0 ? CompilerServices.miLoadTmp : CompilerServices.miSetContent; - if (typeof (TemplatedGroup).IsAssignableFrom (CrowType)) - return Index < 0 ? CompilerServices.miLoadTmp : CompilerServices.miAddItem; - if (typeof (TemplatedControl).IsAssignableFrom (CrowType)) - return CompilerServices.miLoadTmp; - return null; - } - } - public void EmitGetInstance (ILGenerator il){ - if (typeof (Group).IsAssignableFrom (CrowType)) { - il.Emit (OpCodes.Ldfld, typeof(Group).GetField ("children", BindingFlags.Instance | BindingFlags.NonPublic)); - il.Emit(OpCodes.Ldc_I4, Index); - il.Emit (OpCodes.Callvirt, typeof(List).GetMethod("get_Item", new Type[] { typeof(Int32) })); - return; - } - if (typeof(Container).IsAssignableFrom (CrowType) || Index < 0) { - il.Emit (OpCodes.Ldfld, typeof(PrivateContainer).GetField ("child", BindingFlags.Instance | BindingFlags.NonPublic)); - return; - } - if (typeof(TemplatedContainer).IsAssignableFrom (CrowType)) { - il.Emit (OpCodes.Callvirt, typeof(TemplatedContainer).GetProperty ("Content").GetGetMethod ()); - return; - } - if (typeof(TemplatedGroup).IsAssignableFrom (CrowType)) { - il.Emit (OpCodes.Callvirt, typeof(TemplatedGroup).GetProperty ("Items").GetGetMethod ()); - il.Emit(OpCodes.Ldc_I4, Index); - il.Emit (OpCodes.Callvirt, typeof(List).GetMethod("get_Item", new Type[] { typeof(Int32) })); - return; - } - } public static implicit operator string (Node sn) { diff --git a/src/IML/NodeAddress.cs b/src/IML/NodeAddress.cs index b7517b1f..1c907ec1 100644 --- a/src/IML/NodeAddress.cs +++ b/src/IML/NodeAddress.cs @@ -21,6 +21,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; +using System.Reflection.Emit; namespace Crow.IML { diff --git a/src/IML/NodeStack.cs b/src/IML/NodeStack.cs new file mode 100644 index 00000000..bec45e26 --- /dev/null +++ b/src/IML/NodeStack.cs @@ -0,0 +1,44 @@ +// +// NodeStack.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2016 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using System.Collections.Generic; + +namespace Crow.IML +{ + public class NodeStack : Stack + { + public NodeStack () : base() + { + } + public void IncrementCurrentNodeIndex(){ + Node n = this.Pop(); + this.Push (new Node (n.CrowType, n.Index + 1)); + } + public void DecrementCurrentNodeIndex(){ + Node n = this.Pop(); + this.Push (new Node (n.CrowType, n.Index - 1)); + } + public void ResetCurrentNodeIndex(){ + this.Push (new Node (this.Pop().CrowType)); + } + } +} + diff --git a/src/Instantiator.cs b/src/Instantiator.cs index 0af50a85..b5ffbe83 100644 --- a/src/Instantiator.cs +++ b/src/Instantiator.cs @@ -95,8 +95,7 @@ namespace Crow void parseIML (XmlTextReader reader) { Context ctx = new Context (findRootType (reader)); - ctx.CurrentNode = new Node (ctx.RootType); - emitLoader (reader, ctx); + emitLoader (reader, ctx, ctx.RootType); emitBindingDelegates (ctx); @@ -130,17 +129,21 @@ namespace Crow } return t; } - void emitLoader (XmlTextReader reader, Context ctx) + void emitLoader (XmlTextReader reader, Context ctx, Type newType) { + ctx.nodesStack.Push(new Node (newType, ctx.CurrentIndex)); string tmpXml = reader.ReadOuterXml (); - if (ctx.CurrentNode.HasTemplate) + if (ctx.nodesStack.Peek().HasTemplate) emitTemplateLoad (ctx, tmpXml); emitGOLoad (ctx, tmpXml); + + emitCheckAndBindValueChanged (ctx); + + ctx.nodesStack.Pop (); } - void emitTemplateLoad (Context ctx, string tmpXml) { - ctx.CurrentNode.Index--;//template indexing use -1 + void emitTemplateLoad (Context ctx, string tmpXml) { //if its a template, first read template elements using (XmlTextReader reader = new XmlTextReader (tmpXml, XmlNodeType.Element, null)) { List itemTemplateIds = new List (); @@ -156,9 +159,8 @@ namespace Crow if (reader.Name == "Template") { inlineTemplate = true; reader.Read (); - ctx.nodesStack.Push (ctx.CurrentNode); + ctx.CurrentIndex = -1; readChildren (reader, ctx); - ctx.nodesStack.Pop (); } else if (reader.Name == "ItemTemplate") { string dataType = "default", datas = "", path = ""; while (reader.MoveToNextAttribute ()) { @@ -221,7 +223,7 @@ namespace Crow } } } - ctx.CurrentNode.Index++; + ctx.nodesStack.IncrementCurrentNodeIndex (); } void emitGOLoad (Context ctx, string tmpXml) { @@ -245,16 +247,16 @@ namespace Crow if (reader.Name == "Style") continue; - MemberInfo mi = ctx.CurrentNode.CrowType.GetMember (reader.Name).FirstOrDefault (); + MemberInfo mi = ctx.CurrentNodeType.GetMember (reader.Name).FirstOrDefault (); if (mi == null) - throw new Exception ("Member '" + reader.Name + "' not found in " + ctx.CurrentNode.CrowType.Name); + throw new Exception ("Member '" + reader.Name + "' not found in " + ctx.CurrentNodeType.Name); if (mi.MemberType == MemberTypes.Event) { //CompilerServices.emitBindingCreation (ctx.il, reader.Name, reader.Value); continue; } PropertyInfo pi = mi as PropertyInfo; if (pi == null) - throw new Exception ("Member '" + reader.Name + "' not found in " + ctx.CurrentNode.CrowType.Name); + throw new Exception ("Member '" + reader.Name + "' not found in " + ctx.CurrentNodeType.Name); if (pi.Name == "Name"){ if (!ctx.Names.ContainsKey(reader.Value)) @@ -273,12 +275,9 @@ namespace Crow #endregion if (!reader.IsEmptyElement) { - ctx.nodesStack.Push (ctx.CurrentNode); + ctx.CurrentIndex = 0; readChildren (reader, ctx); - ctx.nodesStack.Pop (); } - - emitCheckAndBindValueChanged (ctx); } } /// @@ -295,7 +294,7 @@ namespace Crow case XmlNodeType.Element: //skip Templates if (reader.Name == "Template" || - reader.Name == "ItemTemplate") { + reader.Name == "ItemTemplate") { reader.Skip (); continue; } @@ -320,14 +319,13 @@ namespace Crow ctx.il.Emit (OpCodes.Stloc_0);//child is now loc_0 CompilerServices.emitSetCurInterface (ctx.il); - ctx.CurrentNode = new Node (t); - emitLoader (reader, ctx); + emitLoader (reader, ctx, t); ctx.il.Emit (OpCodes.Ldloc_0);//load child on stack for parenting - ctx.il.Emit (OpCodes.Callvirt, ctx.nodesStack.Peek ().AddMethod); + ctx.il.Emit (OpCodes.Callvirt, ctx.CurrentAddMethod); ctx.il.Emit (OpCodes.Stloc_0); //reset local to current go - ctx.nodesStack.Peek ().Index++; + ctx.CurrentIndex++; break; } @@ -421,7 +419,7 @@ namespace Crow Array.Copy (currentNode.ToArray (), targetNode, ptr + 1); NodeAddress targetNA = new NodeAddress (targetNode); - string [] bindTrg = bindingExp [currentNode.Count - 1 - ptr].Split ('.'); + string [] bindTrg = bindingExp.Last().Split ('.'); if (bindTrg.Length == 1) memberName = bindTrg [0]; @@ -504,7 +502,7 @@ namespace Crow //by default, source value type is deducted from target member type to allow //memberless binding, if targetMember exists, it will be used to determine target //value type for conversion - PropertyInfo piSource = ctx.CurrentNode.CrowType.GetProperty(sourceMember); + PropertyInfo piSource = ctx.CurrentNodeType.GetProperty(sourceMember); Type sourceValueType = piSource.PropertyType; //il.Emit (OpCodes.Call, typeof(object).GetMethod("GetType")); @@ -642,17 +640,9 @@ namespace Crow NodeAddress origine = bindings.Key; NodeAddress destination = ma.Address; - if (origine.Count < destination.Count){ - for (int j = origine.Count-1; j < destination.Count-1; j++){ - destination[j].EmitGetInstance(ilInit); - destination[j].EmitGetInstance(il); - } - }else{ - for (int j = destination.Count; j < origine.Count; j++){ - ilInit.Emit(OpCodes.Callvirt, typeof(ILayoutable).GetProperty("Parent").GetGetMethod()); - il.Emit(OpCodes.Callvirt, typeof(ILayoutable).GetProperty("Parent").GetGetMethod()); - } - } + emitGetInstance(il,origine,destination); + emitGetInstance(ilInit,origine,destination); + //init dynmeth: load actual value ilInit.Emit (OpCodes.Ldarg_0); ilInit.Emit (OpCodes.Callvirt, origineNodeType.GetProperty (bindingCase.Key).GetGetMethod()); @@ -681,8 +671,38 @@ namespace Crow il.Emit (OpCodes.Ret); bindingDelegates [bindings.Key.ToString()] = dm.CreateDelegate (typeof(EventHandler)); - bindingDelegates [bindings.Key.ToString()] = dmInit.CreateDelegate (typeof(Action)); + bindingInitializer [bindings.Key.ToString()] = dmInit.CreateDelegate (typeof(Action)); + } + } + void emitGetInstance (ILGenerator il, NodeAddress orig, NodeAddress dest){ + if (orig.Count < dest.Count){ + for (int i = orig.Count-1; i < dest.Count-1; i++){ + if (typeof (Group).IsAssignableFrom (dest[i].CrowType)) { + il.Emit (OpCodes.Ldfld, typeof(Group).GetField ("children", BindingFlags.Instance | BindingFlags.NonPublic)); + il.Emit(OpCodes.Ldc_I4, dest[i+1].Index); + il.Emit (OpCodes.Callvirt, typeof(List).GetMethod("get_Item", new Type[] { typeof(Int32) })); + continue; + } + if (typeof(Container).IsAssignableFrom (dest[i].CrowType) || dest[i+1].Index < 0) { + il.Emit (OpCodes.Ldfld, typeof(PrivateContainer).GetField ("child", BindingFlags.Instance | BindingFlags.NonPublic)); + continue; + } + if (typeof(TemplatedContainer).IsAssignableFrom (dest[i].CrowType)) { + il.Emit (OpCodes.Callvirt, typeof(TemplatedContainer).GetProperty ("Content").GetGetMethod ()); + continue; + } + if (typeof(TemplatedGroup).IsAssignableFrom (dest[i].CrowType)) { + il.Emit (OpCodes.Callvirt, typeof(TemplatedGroup).GetProperty ("Items").GetGetMethod ()); + il.Emit(OpCodes.Ldc_I4, dest[i+1].Index); + il.Emit (OpCodes.Callvirt, typeof(List).GetMethod("get_Item", new Type[] { typeof(Int32) })); + continue; + } + } + return; } + + for (int j = dest.Count; j < orig.Count; j++) + il.Emit(OpCodes.Callvirt, typeof(ILayoutable).GetProperty("Parent").GetGetMethod()); } void emitConvert(ILGenerator il, Type origType, Type destType){ if (destType == typeof (string))