]> O.S.I.I.S - jp/crow.git/commitdiff
debug
authorjpbruyere <jp.bruyere@hotmail.com>
Tue, 22 Nov 2016 16:49:16 +0000 (17:49 +0100)
committerjpbruyere <jp.bruyere@hotmail.com>
Tue, 22 Nov 2016 16:49:16 +0000 (17:49 +0100)
Crow.csproj
src/IML/Context.cs
src/IML/Node.cs
src/IML/NodeAddress.cs
src/IML/NodeStack.cs [new file with mode: 0644]
src/Instantiator.cs

index 6e43e8ddb462581f0bcf9831a34d6d2f032684d8..6cae0a7ec30833edc33a2909565abeeb8a6a9403 100644 (file)
     <Compile Include="src\IML\NodeAddress.cs" />
     <Compile Include="src\IML\Node.cs" />
     <Compile Include="src\IML\MemberAddress.cs" />
+    <Compile Include="src\IML\NodeStack.cs" />
   </ItemGroup>
   <ItemGroup>
     <Reference Include="System" />
index e5d333742dbd96372b87ae38321ac90a2fe94c4a..965d0062edf6cd5ebc10d49b07ab230d0f1adb2e 100644 (file)
@@ -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<Node> nodesStack = new Stack<Node> ();
+               public NodeStack nodesStack = new NodeStack ();
 
                public Dictionary<string, List<NodeAddress>> Names  = new Dictionary<string, List<NodeAddress>>();
                public Dictionary<string, Dictionary<string, MemberAddress>> PropertyBindings = new Dictionary<string, Dictionary<string, MemberAddress>> ();
@@ -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));
index a503a3bb8c165b6008bba1e9dd2f20e2b672e92c..14cffdb29f5b071b606e75ac5f53b53bfcb8e900 100644 (file)
@@ -28,7 +28,7 @@ namespace Crow.IML
        /// <summary>
        /// IML Node are the elements of the interface XML,
        /// </summary>
-       public class Node
+       public struct Node
        {
                public Type CrowType;
                /// <summary>
@@ -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<GraphicObject>).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<GraphicObject>).GetMethod("get_Item", new Type[] { typeof(Int32) }));
-                               return;
-                       }
-               }
 
                public static implicit operator string (Node sn)
                {
index b7517b1f5c15ae7a814b56c67ef7ce47dff9a1f4..1c907ec1cdbfb0a85b408c7354c09b2aaa68e23b 100644 (file)
@@ -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 (file)
index 0000000..bec45e2
--- /dev/null
@@ -0,0 +1,44 @@
+//
+//  NodeStack.cs
+//
+//  Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+//  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 <http://www.gnu.org/licenses/>.
+using System;
+using System.Collections.Generic;
+
+namespace Crow.IML
+{
+       public class NodeStack : Stack<Node>
+       {
+               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));
+               }
+       }
+}
+
index 0af50a857d639dc1a88d22decb08419146d6fe59..b5ffbe832ae6b726091f1311313b5c4418c1d565 100644 (file)
@@ -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<string []> itemTemplateIds = new List<string []> ();
@@ -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);
                        }
                }
                /// <summary>
@@ -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<ValueChangeEventArgs>));
-                               bindingDelegates [bindings.Key.ToString()] = dmInit.CreateDelegate (typeof(Action<object>));
+                               bindingInitializer [bindings.Key.ToString()] = dmInit.CreateDelegate (typeof(Action<object>));
+                       }
+               }
+               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<GraphicObject>).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<GraphicObject>).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))