aboutsummaryrefslogtreecommitdiffstatsci
path: root/src/CompilerServices
diff options
context:
space:
mode:
authorjpbruyere <jp.bruyere@hotmail.com>2016-12-22 12:29:10 +0100
committerjpbruyere <jp.bruyere@hotmail.com>2016-12-22 12:29:10 +0100
commit366e3e09cd941a4bb80afcba87157764b007770c (patch)
tree9ecc8c044825ae06323641c2d2658f8b00900548 /src/CompilerServices
parentb21a20ca16bd342dfc609a5b25fb0fe63f992715 (diff)
Add in tree handler at end of parsing just after name resolution
Move several static func for emit in CompilerService class modifié : src/CompilerServices/CompilerServices.cs modifié : src/IML/BindingDefinition.cs modifié : src/IML/Context.cs modifié : src/Instantiator.cs
Diffstat (limited to 'src/CompilerServices')
-rw-r--r--src/CompilerServices/CompilerServices.cs130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/CompilerServices/CompilerServices.cs b/src/CompilerServices/CompilerServices.cs
index 16ad5d8e..de49d32d 100644
--- a/src/CompilerServices/CompilerServices.cs
+++ b/src/CompilerServices/CompilerServices.cs
@@ -6,6 +6,7 @@ using System.Linq;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Xml;
+using Crow.IML;
namespace Crow
@@ -665,6 +666,135 @@ namespace Crow
return Activator.CreateInstance (dstType);
return null;
}
+ public static void emitGetInstance (ILGenerator il, NodeAddress orig, NodeAddress dest){
+ if (orig.Count < dest.Count) {
+ for (int i = orig.Count - 1; i < dest.Count - 1; i++)
+ emitGetChild (il, dest [i].CrowType, dest [i + 1].Index);
+ } else {
+ for (int j = dest.Count; j < orig.Count; j++)
+ il.Emit (OpCodes.Callvirt, typeof(ILayoutable).GetProperty ("Parent").GetGetMethod ());
+ }
+ }
+ public static void emitGetInstance (ILGenerator il, NodeAddress dest){
+ for (int i = 0; i < dest.Count - 1; i++)
+ emitGetChild (il, dest [i].CrowType, dest [i + 1].Index);
+ }
+ public static void emitGetChild(ILGenerator il, Type parentType, int index){
+ if (typeof (Group).IsAssignableFrom (parentType)) {
+ 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 (parentType) || index < 0) {
+ il.Emit (OpCodes.Ldfld, typeof(PrivateContainer).GetField ("child", BindingFlags.Instance | BindingFlags.NonPublic));
+ return;
+ }
+ if (typeof(TemplatedContainer).IsAssignableFrom (parentType)) {
+ il.Emit (OpCodes.Callvirt, typeof(TemplatedContainer).GetProperty ("Content").GetGetMethod ());
+ return;
+ }
+ if (typeof(TemplatedGroup).IsAssignableFrom (parentType)) {
+ 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;
+ }
+ }
+ /// <summary>
+ /// Emit conversion from orig type to dest type
+ /// </summary>
+ public static void emitConvert(ILGenerator il, Type origType, Type destType){
+ if (destType == typeof(string))
+ il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);
+ else if (origType.IsValueType) {
+ if (destType != origType) {
+ il.Emit (OpCodes.Callvirt, CompilerServices.GetConvertMethod (destType));
+ }else
+ il.Emit (OpCodes.Unbox_Any, destType);//TODO:double check this
+ } else {
+ if (origType.IsAssignableFrom(destType))
+ il.Emit (OpCodes.Castclass, destType);
+ else {
+ MethodInfo miIO = getImplicitOp (origType, destType);
+ if (miIO != null)
+ il.Emit (OpCodes.Callvirt, miIO);
+ }
+ }
+ }
+ /// <summary>
+ /// check type of current object on the stack and convert to dest type,
+ /// use loc_0 so store it as object!!!
+ /// </summary>
+ public static void emitConvert(ILGenerator il, Type dstType){
+ System.Reflection.Emit.Label endConvert = il.DefineLabel ();
+ System.Reflection.Emit.Label convert = il.DefineLabel ();
+
+ il.Emit (OpCodes.Dup);
+ il.Emit (OpCodes.Isinst, dstType);
+ il.Emit (OpCodes.Brfalse, convert);
+
+ if (dstType.IsValueType)
+ il.Emit (OpCodes.Unbox_Any, dstType);
+ else
+ il.Emit (OpCodes.Isinst, dstType);
+ il.Emit (OpCodes.Br, endConvert);
+
+ il.MarkLabel (convert);
+
+ if (dstType == typeof(string)) {
+ il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);
+ } else if (dstType.IsPrimitive) {
+ //il.Emit (OpCodes.Unbox_Any, dstType);
+ il.Emit (OpCodes.Callvirt, CompilerServices.GetConvertMethod (dstType));
+ } else if (dstType.IsValueType) {
+ il.Emit (OpCodes.Unbox_Any, dstType);
+ } else{
+ il.Emit (OpCodes.Stloc_0); //save orig value in loc0
+ il.Emit (OpCodes.Ldloc_0);
+ il.Emit (OpCodes.Callvirt, typeof(object).GetMethod ("GetType"));
+ il.Emit (OpCodes.Ldtoken, dstType);//push destination property type for testing
+ il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle);
+ il.Emit (OpCodes.Call, typeof(CompilerServices).GetMethod ("getImplicitOp", BindingFlags.Static | BindingFlags.Public));
+ il.Emit (OpCodes.Dup);
+ convert = il.DefineLabel ();
+ il.Emit (OpCodes.Brtrue, convert);
+ il.Emit (OpCodes.Pop);
+ il.Emit (OpCodes.Ldloc_0);
+ il.Emit (OpCodes.Isinst, dstType);
+ il.Emit (OpCodes.Br, endConvert);
+
+ il.MarkLabel (convert);
+ il.Emit (OpCodes.Ldnull);//null instance for invoke
+ il.Emit (OpCodes.Ldc_I4_1);
+ il.Emit(OpCodes.Newarr, typeof(object));
+ il.Emit (OpCodes.Dup);//duplicate the array ref
+ il.Emit (OpCodes.Ldc_I4_0);//push the index 0
+ il.Emit (OpCodes.Ldloc_0);//push the orig value to convert
+ il.Emit (OpCodes.Stelem, typeof(object));//set the array element at index 0
+ il.Emit (OpCodes.Callvirt, typeof(MethodInfo).GetMethod("Invoke", new Type[] { typeof(object), typeof (object[])}));
+ }
+
+ il.MarkLabel (endConvert);
+ }
+ /// <summary>
+ /// search for an implicit conversion method in origine or destination classes
+ /// </summary>
+ public static MethodInfo getImplicitOp(Type origType, Type dstType){
+ foreach(MethodInfo mi in origType.GetMethods(BindingFlags.Public|BindingFlags.Static)){
+ if (mi.Name == "op_Implicit") {
+ if (mi.ReturnType == dstType && mi.GetParameters ().FirstOrDefault ().ParameterType == origType)
+ return mi;
+ }
+ }
+ foreach(MethodInfo mi in dstType.GetMethods(BindingFlags.Public|BindingFlags.Static)){
+ if (mi.Name == "op_Implicit") {
+ if (mi.ReturnType == dstType && mi.GetParameters ().FirstOrDefault ().ParameterType == origType)
+ return mi;
+ }
+ }
+ return null;
+ }
}
}