diff --git a/Directory.Build.props b/Directory.Build.props
index fce83db7..7d3cfde5 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -7,5 +7,4 @@
-
-
+
\ No newline at end of file
diff --git a/src/XamlX.IL.Cecil/CecilEmitter.cs b/src/XamlX.IL.Cecil/CecilEmitter.cs
index 870c413e..f3e1064e 100644
--- a/src/XamlX.IL.Cecil/CecilEmitter.cs
+++ b/src/XamlX.IL.Cecil/CecilEmitter.cs
@@ -132,6 +132,12 @@ public IXamlILEmitter Emit(SreOpCode code, int arg)
public IXamlILEmitter Emit(SreOpCode code, long arg)
=> Emit(Instruction.Create(Dic[code], arg));
+
+ public IXamlILEmitter Emit(SreOpCode code, sbyte arg)
+ => Emit(Instruction.Create(Dic[code], arg));
+
+ public IXamlILEmitter Emit(SreOpCode code, byte arg)
+ => Emit(Instruction.Create(Dic[code], arg));
public IXamlILEmitter Emit(SreOpCode code, IXamlType type)
=> Emit(Instruction.Create(Dic[code], Import(((ITypeReference) type).Reference)));
@@ -143,9 +149,11 @@ public IXamlILEmitter Emit(SreOpCode code, double arg)
=> Emit(Instruction.Create(Dic[code], arg));
- class CecilLocal : IXamlLocal
+ class CecilLocal : IXamlILLocal
{
public VariableDefinition Variable { get; set; }
+
+ public int Index => Variable.Index;
}
class CecilLabel : IXamlLabel
diff --git a/src/XamlX.IL.Cecil/CecilField.cs b/src/XamlX.IL.Cecil/CecilField.cs
index ec03d907..63c91384 100644
--- a/src/XamlX.IL.Cecil/CecilField.cs
+++ b/src/XamlX.IL.Cecil/CecilField.cs
@@ -19,7 +19,9 @@ public CecilField(CecilTypeSystem typeSystem, FieldDefinition def, TypeReference
Field = new FieldReference(def.Name, def.FieldType, declaringType);
}
- public bool Equals(IXamlField other) => other is CecilField cf && cf.Field == Field;
+ public bool Equals(IXamlField other) => other is CecilField cf && cf.Field.FullName == Field.FullName;
+
+ public override int GetHashCode() => Field.FullName.GetHashCode();
public string Name => Field.Name;
private IXamlType _type;
@@ -41,4 +43,4 @@ public object GetLiteralValue()
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/XamlX.IL.Cecil/CecilMethod.cs b/src/XamlX.IL.Cecil/CecilMethod.cs
index 416403ff..62e76e20 100644
--- a/src/XamlX.IL.Cecil/CecilMethod.cs
+++ b/src/XamlX.IL.Cecil/CecilMethod.cs
@@ -102,6 +102,9 @@ other is CecilMethod cm
&& DeclaringType.Equals(cm.DeclaringType)
&& Reference.FullName == cm.Reference.FullName;
+ public override int GetHashCode()
+ => (DeclaringType.GetHashCode() * 397) ^ Reference.FullName.GetHashCode();
+
public IXamlMethod MakeGenericMethod(IReadOnlyList typeArguments)
{
GenericInstanceMethod instantiation = new GenericInstanceMethod(Reference);
diff --git a/src/XamlX.IL.Cecil/CecilType.cs b/src/XamlX.IL.Cecil/CecilType.cs
index c358813e..2605e04c 100644
--- a/src/XamlX.IL.Cecil/CecilType.cs
+++ b/src/XamlX.IL.Cecil/CecilType.cs
@@ -112,10 +112,9 @@ public bool IsAssignableFrom(IXamlType type)
}
bool IsAssignableFromCore(IXamlType type)
{
- if (!type.IsValueType
- && type == XamlPseudoType.Null)
- return true;
-
+ if (type == XamlPseudoType.Null)
+ return !IsValueType || GenericTypeDefinition?.FullName == "System.Nullable`1";
+
if (type.IsValueType
&& GenericTypeDefinition?.FullName == "System.Nullable`1"
&& GenericArguments[0].Equals(type))
diff --git a/src/XamlX/Ast/Clr.cs b/src/XamlX/Ast/Clr.cs
index 3d8a9c87..489ca730 100644
--- a/src/XamlX/Ast/Clr.cs
+++ b/src/XamlX/Ast/Clr.cs
@@ -87,15 +87,36 @@ public XamlAstClrProperty(IXamlLineInfo lineInfo, string name, IXamlType declari
public override string ToString() => DeclaringType.GetFqn() + "." + Name;
}
- class XamlDirectCallPropertySetter : IXamlPropertySetter, IXamlEmitablePropertySetter
+#if !XAMLX_INTERNAL
+ public
+#endif
+ interface IXamlILOptimizedEmitablePropertySetter : IXamlEmitablePropertySetter
+ {
+ void EmitWithArguments(
+ XamlEmitContextWithLocals context,
+ IXamlILEmitter emitter,
+ IReadOnlyList arguments);
+ }
+
+ class XamlDirectCallPropertySetter : IXamlILOptimizedEmitablePropertySetter, IEquatable
{
private readonly IXamlMethod _method;
public IXamlType TargetType { get; }
public PropertySetterBinderParameters BinderParameters { get; } = new PropertySetterBinderParameters();
public IReadOnlyList Parameters { get; }
- public void Emit(IXamlILEmitter codegen)
+
+ public void Emit(IXamlILEmitter emitter)
+ => emitter.EmitCall(_method, true);
+
+ public void EmitWithArguments(
+ XamlEmitContextWithLocals context,
+ IXamlILEmitter emitter,
+ IReadOnlyList arguments)
{
- codegen.EmitCall(_method, true);
+ for (var i = 0; i < arguments.Count; ++i)
+ context.Emit(arguments[i], emitter, Parameters[i]);
+
+ emitter.EmitCall(_method, true);
}
public XamlDirectCallPropertySetter(IXamlMethod method)
@@ -103,17 +124,64 @@ public XamlDirectCallPropertySetter(IXamlMethod method)
_method = method;
Parameters = method.ParametersWithThis().Skip(1).ToList();
TargetType = method.ThisOrFirstParameter();
+
+ bool allowNull = Parameters.Last().AcceptsNull();
+ BinderParameters = new PropertySetterBinderParameters
+ {
+ AllowMultiple = false,
+ AllowXNull = allowNull,
+ AllowRuntimeNull = allowNull
+ };
+ }
+
+ public bool Equals(XamlDirectCallPropertySetter other)
+ {
+ if (ReferenceEquals(null, other))
+ return false;
+ if (ReferenceEquals(this, other))
+ return true;
+
+ return _method.Equals(other._method) && BinderParameters.Equals(other.BinderParameters);
}
+
+ public override bool Equals(object obj)
+ => Equals(obj as XamlDirectCallPropertySetter);
+
+ public override int GetHashCode()
+ => (_method.GetHashCode() * 397) ^ BinderParameters.GetHashCode();
}
#if !XAMLX_INTERNAL
public
#endif
- class PropertySetterBinderParameters
+ class PropertySetterBinderParameters : IEquatable
{
public bool AllowMultiple { get; set; }
public bool AllowXNull { get; set; } = true;
public bool AllowRuntimeNull { get; set; } = true;
+
+ public bool Equals(PropertySetterBinderParameters other)
+ {
+ if (ReferenceEquals(null, other))
+ return false;
+ if (ReferenceEquals(this, other))
+ return true;
+
+ return AllowMultiple == other.AllowMultiple
+ && AllowXNull == other.AllowXNull
+ && AllowRuntimeNull == other.AllowRuntimeNull;
+ }
+
+ public override bool Equals(object obj)
+ => Equals(obj as PropertySetterBinderParameters);
+
+ public override int GetHashCode()
+ {
+ int hashCode = AllowMultiple.GetHashCode();
+ hashCode = (hashCode * 397) ^ AllowXNull.GetHashCode();
+ hashCode = (hashCode * 397) ^ AllowRuntimeNull.GetHashCode();
+ return hashCode;
+ }
}
#if !XAMLX_INTERNAL
@@ -637,6 +705,8 @@ void CompileBuilder(ILEmitContext context)
context.Emit(Value, context.Emitter, context.Configuration.WellKnownTypes.Object);
il.Ret();
+
+ context.ExecuteAfterEmitCallbacks();
}
public XamlILNodeEmitResult Emit(XamlEmitContext context, IXamlILEmitter codeGen)
@@ -652,7 +722,7 @@ public XamlILNodeEmitResult Emit(XamlEmitContext subType.DefineSubType(type, s, false),
- defineDelegateSubType: (s, returnType, parameters) => subType.DefineDelegateSubType(s, false, returnType, parameters),
+ defineDelegateSubType: (s, returnType, parameters) => subType.DefineDelegateSubType(s, false, returnType, parameters),
file: context.File,
emitters: context.Emitters));
@@ -662,11 +732,11 @@ public XamlILNodeEmitResult Emit(XamlEmitContext
ct.Parameters.Count == 2 && ct.Parameters[0].Equals(context.Configuration.WellKnownTypes.Object)));
-
+
// Allow to save values from the parent context, pass own service provider, etc, etc
if (context.Configuration.TypeMappings.DeferredContentExecutorCustomization != null)
{
-
+
var customization = context.Configuration.TypeMappings.DeferredContentExecutorCustomization;
if (_deferredContentCustomizationTypeParameter != null)
customization =
diff --git a/src/XamlX/Ast/Intrinsics.cs b/src/XamlX/Ast/Intrinsics.cs
index 7b42cc59..5a855e48 100644
--- a/src/XamlX/Ast/Intrinsics.cs
+++ b/src/XamlX/Ast/Intrinsics.cs
@@ -25,7 +25,7 @@ public XamlILNodeEmitResult Emit(XamlEmitContext : XamlContextBase
public IFileSource File { get; }
public List