aboutsummaryrefslogtreecommitdiffstatsci
path: root/src/CompilerServices
diff options
context:
space:
mode:
authorj-p <jp.bruyere@live.be>2016-08-11 04:20:36 +0200
committerGitHub <noreply@github.com>2016-08-11 04:20:36 +0200
commit81eb8c7a75ffbe8b6740b2a84a9ebff75da9b393 (patch)
tree3225277358a2bba61c4496923ba39353c942098b /src/CompilerServices
parent4d4a9116ea5c68b27f0b7c43db9682ab57738ae7 (diff)
parent7560c0bb4a769210e289e2633ddf13d2617f8e6e (diff)
Merge pull request #18 from jpbruyere/BindingImprovement
Instantiator
Diffstat (limited to 'src/CompilerServices')
-rw-r--r--src/CompilerServices/Bindings.cs27
-rw-r--r--src/CompilerServices/CompilerServices.cs124
2 files changed, 144 insertions, 7 deletions
diff --git a/src/CompilerServices/Bindings.cs b/src/CompilerServices/Bindings.cs
index 8ece856c..64f412f6 100644
--- a/src/CompilerServices/Bindings.cs
+++ b/src/CompilerServices/Bindings.cs
@@ -41,6 +41,11 @@ namespace Crow
public string DynMethodId {
get { return dynMethodId; }
}
+ public Type SourceType {
+ get { return Source == null ? null
+ : Source.Instance == null ? null
+ : Source.Instance.GetType();}
+ }
public bool Resolved {
get { return resolved; }
@@ -123,10 +128,12 @@ namespace Crow
//datasource binding
object dataSource = (Source.Instance as GraphicObject).DataSource;
if (dataSource == null) {
+ #if DEBUG_BINDING
Debug.WriteLine ("\tDataSource is null => " + this.ToString());
+ #endif
return false;
}
-
+
Target = new MemberReference (dataSource);
memberName = bindingExp [0];
} else {
@@ -148,7 +155,7 @@ namespace Crow
while (ptr < bindingExp.Length - 1) {
if (tmpTarget == null) {
#if DEBUG_BINDING
- Debug.WriteLine ("\tERROR: target not found => " + this.ToString());
+ Debug.WriteLine ("\tTarget not found => " + this.ToString());
#endif
return false;
}
@@ -164,14 +171,12 @@ namespace Crow
}
if (tmpTarget == null) {
-#if DEBUG_BINDING
- Debug.WriteLine ("\tERROR: Binding Target not found => " + this.ToString());
-#endif
+ #if DEBUG_BINDING
+ Debug.WriteLine ("\tBinding Target not found => " + this.ToString());
+ #endif
return false;
}
- Target = new MemberReference (tmpTarget);
-
string [] bindTrg = bindingExp [ptr].Split ('.');
if (bindTrg.Length == 1)
@@ -182,6 +187,14 @@ namespace Crow
} else
throw new Exception ("Syntax error in binding, expected 'go dot member'");
+ if (tmpTarget == null) {
+ #if DEBUG_BINDING
+ Debug.WriteLine ("\tBinding Target not found => " + this.ToString());
+ #endif
+ return false;
+ }
+
+ Target = new MemberReference (tmpTarget);
}
if (Target.TryFindMember (memberName)) {
diff --git a/src/CompilerServices/CompilerServices.cs b/src/CompilerServices/CompilerServices.cs
index 0b69f970..d06cd29b 100644
--- a/src/CompilerServices/CompilerServices.cs
+++ b/src/CompilerServices/CompilerServices.cs
@@ -5,12 +5,136 @@ using System.Diagnostics;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
+using System.Xml;
namespace Crow
{
public static class CompilerServices
{
+ static MethodInfo miAddBinding = typeof(GraphicObject).GetMethod ("BindMember");
+
+
+ public static void emitBindingCreation(ILGenerator il, string memberName, string expression){
+ il.Emit (OpCodes.Ldloc_0);
+ il.Emit (OpCodes.Ldstr, memberName);
+ il.Emit (OpCodes.Ldstr, expression);
+ il.Emit (OpCodes.Callvirt, miAddBinding);
+ }
+
+ public static void EmitSetValue(ILGenerator il, PropertyInfo pi, object val){
+ il.Emit (OpCodes.Ldloc_0);
+
+ if (val == null) {
+ il.Emit (OpCodes.Ldnull);
+ il.Emit (OpCodes.Callvirt, pi.GetSetMethod ());
+ return;
+ }
+ Type dvType = val.GetType ();
+
+ if (dvType.IsValueType) {
+ if (pi.PropertyType.IsValueType) {
+ if (pi.PropertyType.IsEnum) {
+ if (pi.PropertyType != dvType)
+ throw new Exception ("Enum mismatch in default values: " + pi.PropertyType.FullName);
+ il.Emit (OpCodes.Ldc_I4, Convert.ToInt32 (val));
+ } else {
+ switch (Type.GetTypeCode (dvType)) {
+ case TypeCode.Boolean:
+ if ((bool)val == true)
+ il.Emit (OpCodes.Ldc_I4_1);
+ else
+ il.Emit (OpCodes.Ldc_I4_0);
+ break;
+ // case TypeCode.Empty:
+ // break;
+ // case TypeCode.Object:
+ // break;
+ // case TypeCode.DBNull:
+ // break;
+ // case TypeCode.SByte:
+ // break;
+ // case TypeCode.Decimal:
+ // break;
+ // case TypeCode.DateTime:
+ // break;
+ case TypeCode.Char:
+ il.Emit (OpCodes.Ldc_I4, Convert.ToChar (val));
+ break;
+ case TypeCode.Byte:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ il.Emit (OpCodes.Ldc_I4, Convert.ToInt32 (val));
+ break;
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ il.Emit (OpCodes.Ldc_I4, Convert.ToUInt32 (val));
+ break;
+ case TypeCode.Int64:
+ il.Emit (OpCodes.Ldc_I8, Convert.ToInt64 (val));
+ break;
+ case TypeCode.UInt64:
+ il.Emit (OpCodes.Ldc_I8, Convert.ToUInt64 (val));
+ break;
+ case TypeCode.Single:
+ il.Emit (OpCodes.Ldc_R4, Convert.ToSingle (val));
+ break;
+ case TypeCode.Double:
+ il.Emit (OpCodes.Ldc_R8, Convert.ToDouble (val));
+ break;
+ case TypeCode.String:
+ il.Emit (OpCodes.Ldstr, Convert.ToString (val));
+ break;
+ default:
+ il.Emit (OpCodes.Pop);
+ return;
+ }
+ }
+ } else
+ throw new Exception ("Expecting valuetype in default values for: " + pi.Name);
+ }else{
+ //surely a class or struct
+ if (dvType != typeof(string))
+ throw new Exception ("Expecting String in default values for: " + pi.Name);
+ if (pi.PropertyType == typeof(string))
+ il.Emit (OpCodes.Ldstr, Convert.ToString (val));
+ else if (pi.PropertyType.IsEnum) {
+ MethodInfo miParse = typeof(Enum).GetMethod
+ ("Parse", BindingFlags.Static | BindingFlags.Public,
+ Type.DefaultBinder, new Type [] {typeof (Type), typeof (string), typeof (bool)}, null);
+
+ if (miParse == null)
+ throw new Exception ("Enum Parse method not found");
+
+ //load type of enum
+ il.Emit(OpCodes.Ldtoken, pi.PropertyType);
+ il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new
+ Type[1]{typeof(RuntimeTypeHandle)}));
+ //load enum value name
+ il.Emit (OpCodes.Ldstr, Convert.ToString (val));//TODO:is this convert required?
+ //load false
+ il.Emit (OpCodes.Ldc_I4_0);
+ il.Emit (OpCodes.Callvirt, miParse);
+
+ if (miParse.ReturnType != pi.PropertyType)
+ il.Emit (OpCodes.Unbox_Any, pi.PropertyType);
+ } else {
+ MethodInfo miParse = pi.PropertyType.GetMethod
+ ("Parse", BindingFlags.Static | BindingFlags.Public,
+ Type.DefaultBinder, new Type [] {typeof (string)},null);
+ if (miParse == null)
+ throw new Exception ("no Parse method found for: " + pi.PropertyType.FullName);
+
+ il.Emit (OpCodes.Ldstr, Convert.ToString (val));//TODO:is this convert required?
+ il.Emit (OpCodes.Callvirt, miParse);
+
+ if (miParse.ReturnType != pi.PropertyType)
+ il.Emit (OpCodes.Unbox_Any, pi.PropertyType);
+ }
+ }
+ il.Emit (OpCodes.Callvirt, pi.GetSetMethod ());
+ }
+
public static void ResolveBindings (List<Binding> Bindings)
{
if (Bindings == null)