aboutsummaryrefslogtreecommitdiffstatsci
diff options
context:
space:
mode:
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>2025-07-29 10:12:19 +0200
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>2025-07-29 10:12:19 +0200
commit3f16c00248623bac4c883d3c6cd43afeaaa0d630 (patch)
treea54ee57f0e07636b0e0d69fd9c07e1cecac6cab1
parent60e0e7d19c884fc8204be45c244a065e9085f98a (diff)
debug binding object->value type
-rw-r--r--Crow/Crow.csproj2
-rw-r--r--Crow/src/IML/CompilerServices.cs55
-rw-r--r--Crow/src/IML/Instantiator.cs22
-rw-r--r--Crow/src/Widgets/Widget.cs2
4 files changed, 48 insertions, 33 deletions
diff --git a/Crow/Crow.csproj b/Crow/Crow.csproj
index 316345cf..61b83e98 100644
--- a/Crow/Crow.csproj
+++ b/Crow/Crow.csproj
@@ -30,7 +30,7 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType>
- <DefineConstants>$(DefineConstants);DEBUG;TRACE;_DEBUG_BINDING;_DEBUG_CLIP_RECTANGLE</DefineConstants>
+ <DefineConstants>$(DefineConstants);DEBUG;TRACE;_DEBUG_BINDING;_DEBUG_BINDING_FUNC_CALLS;_DEBUG_CLIP_RECTANGLE</DefineConstants>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
</PropertyGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('netstandard'))">
diff --git a/Crow/src/IML/CompilerServices.cs b/Crow/src/IML/CompilerServices.cs
index 2cea823d..c288e07a 100644
--- a/Crow/src/IML/CompilerServices.cs
+++ b/Crow/src/IML/CompilerServices.cs
@@ -548,11 +548,30 @@ namespace Crow.IML
return;
}
}
-
+ static bool emitParse(ILGenerator il, Type destType) {
+ //search dest type for parse method
+ MethodInfo miParse = destType.GetMethod
+ ("Parse", BindingFlags.Static | BindingFlags.Public,
+ Type.DefaultBinder, new Type [] { typeof (string) }, null);
+ if (miParse == null) {
+ //TODO:find parse for enums destTypes
+ if (destType.IsEnum) {
+ il.Emit (OpCodes.Ldtoken, destType);//push destination property type for testing
+ il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle);
+ il.Emit (OpCodes.Call, CompilerServices.miParseEnumInversedParams);
+ il.Emit (OpCodes.Unbox_Any, destType);
+ } else
+ return false;
+ }else
+ il.Emit (OpCodes.Call, miParse);
+ return true;
+ }
/// <summary>
/// Emit MSIL for conversion from orig type to dest type
/// </summary>
internal static void emitConvert(ILGenerator il, Type origType, Type destType){
+ //Console.WriteLine ($"emitConvert: {origType.FullName} -> {destType.FullName}");
+ //il.EmitWriteLine ($"convert: {origType.FullName} -> {destType.FullName}");
if (destType == typeof(object))
return;
if (destType == typeof (string)) {
@@ -596,32 +615,30 @@ namespace Crow.IML
}
} else
il.Emit (OpCodes.Unbox_Any, destType);//TODO:double check this
+ } else if (destType.IsValueType && origType == typeof(object)){
+ System.Reflection.Emit.Label labContinue = il.DefineLabel ();
+ System.Reflection.Emit.Label emitFinish = il.DefineLabel ();
+ il.Emit (OpCodes.Dup);
+ il.Emit (OpCodes.Isinst, typeof(string));
+ il.Emit (OpCodes.Brfalse, labContinue);
+ emitParse (il, destType);
+ il.Emit (OpCodes.Br, emitFinish);
+ il.MarkLabel (labContinue);
+ il.Emit (OpCodes.Unbox_Any, destType);//TODO:double check this
+ il.MarkLabel (emitFinish);
} else {
if (destType.IsAssignableFrom (origType))
il.Emit (OpCodes.Castclass, destType);
else {
if (origType == typeof (string)) {
- //search dest type for parse method
- MethodInfo miParse = destType.GetMethod
- ("Parse", BindingFlags.Static | BindingFlags.Public,
- Type.DefaultBinder, new Type [] { typeof (string) }, null);
- if (miParse == null) {
- //TODO:find parse for enums destTypes
- if (destType.IsEnum) {
- il.Emit (OpCodes.Ldtoken, destType);//push destination property type for testing
- il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle);
- il.Emit (OpCodes.Call, CompilerServices.miParseEnumInversedParams);
- il.Emit (OpCodes.Unbox_Any, destType);
- } else
- throw new Exception ("no Parse method found for: " + destType.FullName);
- }else
- il.Emit (OpCodes.Call, miParse);
+ if (!emitParse (il, destType))
+ throw new Exception ("no Parse method found for: " + destType.FullName);
}
//implicit conversion can't be defined from or to object base class,
//so we will check if object underlying type is one of the implicit converter of destType
else if (origType == typeof (object)) {//test all implicit converter to destType on obj
+ System.Reflection.Emit.Label emitFinish = il.DefineLabel ();
System.Reflection.Emit.Label emitTestNextImpOp;
- System.Reflection.Emit.Label emitImpOpFound = il.DefineLabel ();
foreach (MethodInfo mi in destType.GetMethods (BindingFlags.Public | BindingFlags.Static)) {
if (mi.Name == "op_Implicit") {
if (mi.GetParameters () [0].ParameterType == destType)
@@ -636,13 +653,13 @@ namespace Crow.IML
il.Emit (OpCodes.Isinst, mi.GetParameters () [0].ParameterType);
il.Emit (OpCodes.Call, mi);
- il.Emit (OpCodes.Br, emitImpOpFound);
+ il.Emit (OpCodes.Br, emitFinish);
il.MarkLabel (emitTestNextImpOp);
}
}
//il.Emit (OpCodes.Br, emitImpOpNotFound);
- il.MarkLabel (emitImpOpFound);
+ il.MarkLabel (emitFinish);
} else {//search both orig and dest types for implicit operators
MethodInfo miIO = getImplicitOp (origType, destType);
if (miIO != null)
diff --git a/Crow/src/IML/Instantiator.cs b/Crow/src/IML/Instantiator.cs
index dc3e77da..c0492e41 100644
--- a/Crow/src/IML/Instantiator.cs
+++ b/Crow/src/IML/Instantiator.cs
@@ -1208,7 +1208,7 @@ namespace Crow.IML {
dm = new DynamicMethod (dschangeddelname,
typeof (void),
CompilerServices.argsBoundDSChange, true);
-
+
il = dm.GetILGenerator (64);
il.DeclareLocal (typeof (object));//used for checking propery less bindings
@@ -1216,7 +1216,7 @@ namespace Crow.IML {
il.DeclareLocal (typeof (object));//new datasource store, save one field access
Label cancel = il.DefineLabel ();
Label newDSIsNull = il.DefineLabel ();
- Label cancelInit = il.DefineLabel ();
+ //Label cancelInit = il.DefineLabel ();
#if DEBUG_BINDING
il.EmitWriteLine ($"DYN Called => {dschangeddelname}");
#endif
@@ -1236,8 +1236,6 @@ namespace Crow.IML {
//test if new ds is of expected type
il.Emit (OpCodes.Ldloc_2);
il.Emit (OpCodes.Isinst, dsType);
- //il.Emit (OpCodes.Call, CompilerServices.miGetMDToken);
- //il.Emit (OpCodes.Ldc_I4, dsType.MetadataToken);
il.Emit (OpCodes.Brfalse, newDSIsNull);
#if DEBUG_BINDING
il.EmitWriteLine ($"\tNew ds is of expected type: {dsType}");
@@ -1263,7 +1261,7 @@ namespace Crow.IML {
#endregion
if (!string.IsNullOrEmpty (bindingDef.TargetMember)) {
- il.MarkLabel (cancelInit);
+ //il.MarkLabel (cancelInit);
//check if new dataSource implement IValueChange
il.Emit (OpCodes.Ldloc_2);//load new datasource
il.Emit (OpCodes.Isinst, typeof (IValueChange));
@@ -1296,18 +1294,18 @@ namespace Crow.IML {
//store dschange delegate in instatiator instance for access while instancing graphic object
int delDSIndex = cachedDelegates.Count;
- //Int32 fiLength = (Int32)il.GetType ().GetField ("code_len", BindingFlags.Instance | BindingFlags.NonPublic).GetValue (il);
- //byte [] bytes = (byte[])il.GetType ().GetField ("code", BindingFlags.Instance | BindingFlags.NonPublic).GetValue (il);
-
- cachedDelegates.Add (dm.CreateDelegate (CompilerServices.ehTypeDSChange, this));
- #endregion
-
- ctx.emitCachedDelegateHandlerAddition (delDSIndex, CompilerServices.eiDSChange);
+ //Int32 fiLength = (Int32)Type.GetType("System.Reflection.Emit.ILGenerator").GetField("m_length", BindingFlags.Instance | BindingFlags.NonPublic).GetValue (il);
+ //byte [] bytes = (byte[])Type.GetType("System.Reflection.Emit.ILGenerator").GetField ("m_ILStream", BindingFlags.Instance | BindingFlags.NonPublic).GetValue (il);
#if DEBUG_BINDING
Console.WriteLine("\tDataSource ValueChanged: " + delName);
Console.WriteLine("\tDataSource Changed: " + dm.Name);
#endif
+
+ cachedDelegates.Add (dm.CreateDelegate (CompilerServices.ehTypeDSChange, this));
+ #endregion
+
+ ctx.emitCachedDelegateHandlerAddition (delDSIndex, CompilerServices.eiDSChange);
}
/// <summary>
diff --git a/Crow/src/Widgets/Widget.cs b/Crow/src/Widgets/Widget.cs
index 6f20a54b..1a7f1e7b 100644
--- a/Crow/src/Widgets/Widget.cs
+++ b/Crow/src/Widgets/Widget.cs
@@ -552,7 +552,7 @@ namespace Crow
/// If enabled, resulting bitmap of graphic object is cached
/// speeding up rendering of complex object. Default is enabled.
/// </summary>
- [DesignCategory ("Behavior")][DefaultValue(false)]
+ [DesignCategory ("Behaviour")][DefaultValue(false)]
public virtual bool CacheEnabled {
get => cacheEnabled;
set {