Browse Source

Bug fixes. Started implementing MSVC ABI. Small refactorings to support this.

git-svn-id: https://mono-soc-2010.googlecode.com/svn/trunk/cppinterop@71 a470b8cb-0e6f-1642-1b45-71e107334c4b
pull/1/head
alexander.corrado 15 years ago
parent
commit
49769f8f54
  1. 9
      Mono.VisualC.Interop/ABI/CppAbi.cs
  2. 21
      Mono.VisualC.Interop/ABI/Impl/ItaniumAbi.cs
  3. 65
      Mono.VisualC.Interop/ABI/Impl/MsvcAbi.cs
  4. 4
      Mono.VisualC.Interop/ABI/VTable.cs
  5. 4
      Mono.VisualC.Interop/ABI/VTableCOM.cs
  6. 8
      Mono.VisualC.Interop/ABI/VTableManaged.cs
  7. 26
      Mono.VisualC.Interop/Attributes.cs
  8. 30
      Mono.VisualC.Interop/CppType.cs
  9. 221
      Mono.VisualC.Interop/IEnumerableTransform.cs
  10. 7
      Mono.VisualC.Interop/Util.cs

9
Mono.VisualC.Interop/ABI/CppAbi.cs

@ -168,7 +168,7 @@ namespace Mono.VisualC.Interop.ABI { @@ -168,7 +168,7 @@ namespace Mono.VisualC.Interop.ABI {
// The members below must be implemented for a given C++ ABI:
public abstract string GetMangledMethodName (MethodInfo methodInfo);
public abstract CallingConvention DefaultCallingConvention { get; }
public abstract CallingConvention GetCallingConvention (MethodInfo methodInfo);
protected virtual void DefineImplType ()
{
@ -238,7 +238,8 @@ namespace Mono.VisualC.Interop.ABI { @@ -238,7 +238,8 @@ namespace Mono.VisualC.Interop.ABI {
MethodInfo nativeMethod;
if (Modifiers.IsVirtual (interfaceMethod))
nativeMethod = vtable.PrepareVirtualCall (interfaceMethod, il, vtable_field, nativePtr, index);
nativeMethod = vtable.PrepareVirtualCall (interfaceMethod, GetCallingConvention (interfaceMethod),
il, nativePtr, vtable_field, index);
else
nativeMethod = GetPInvokeForMethod (interfaceMethod);
@ -328,7 +329,7 @@ namespace Mono.VisualC.Interop.ABI { @@ -328,7 +329,7 @@ namespace Mono.VisualC.Interop.ABI {
if (targetMethod == null)
return null;
Type delegateType = Util.GetDelegateTypeForMethodInfo (impl_module, interfaceMethod);
Type delegateType = Util.GetDelegateTypeForMethodInfo (impl_module, interfaceMethod, GetCallingConvention (interfaceMethod));
Type[] parameterTypes = Util.GetMethodParameterTypes (interfaceMethod, true);
// TODO: According to http://msdn.microsoft.com/en-us/library/w16z8yc4.aspx
@ -405,7 +406,7 @@ namespace Mono.VisualC.Interop.ABI { @@ -405,7 +406,7 @@ namespace Mono.VisualC.Interop.ABI {
MethodBuilder builder = impl_type.DefinePInvokeMethod ("__$" + signature.Name + "_Impl", library, entryPoint,
MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.PinvokeImpl,
CallingConventions.Any, signature.ReturnType, parameterTypes,
DefaultCallingConvention, CharSet.Ansi);
GetCallingConvention (signature), CharSet.Ansi);
builder.SetImplementationFlags (builder.GetMethodImplementationFlags () | MethodImplAttributes.PreserveSig);
Util.ApplyMethodParameterAttributes (signature, builder, true);
return builder;

21
Mono.VisualC.Interop/ABI/Impl/ItaniumAbi.cs

@ -21,8 +21,9 @@ namespace Mono.VisualC.Interop.ABI { @@ -21,8 +21,9 @@ namespace Mono.VisualC.Interop.ABI {
{
}
public override CallingConvention DefaultCallingConvention {
get { return CallingConvention.Cdecl; }
public override CallingConvention GetCallingConvention (MethodInfo methodInfo)
{
return CallingConvention.Cdecl;
}
public override string GetMangledMethodName (MethodInfo methodInfo)
@ -48,11 +49,11 @@ namespace Mono.VisualC.Interop.ABI { @@ -48,11 +49,11 @@ namespace Mono.VisualC.Interop.ABI {
break;
}
nm.Append ("E");
nm.Append ('E');
int argStart = (Modifiers.IsStatic (methodInfo)? 0 : 1);
if (parameters.Length == argStart) // no args (other than C++ "this" object)
nm.Append ("v");
nm.Append ('v');
else
for (int i = argStart; i < parameters.Length; i++)
nm.Append (GetTypeCode (Modifiers.GetMangleType (parameters[i])));
@ -67,14 +68,17 @@ namespace Mono.VisualC.Interop.ABI { @@ -67,14 +68,17 @@ namespace Mono.VisualC.Interop.ABI {
StringBuilder code = new StringBuilder ();
var ptrOrRef = For.AnyInputIn (CppModifiers.Pointer, CppModifiers.Reference);
var modifierCode = modifiers.Reverse ().Transform (
For.AnyInputIn (CppModifiers.Pointer, CppModifiers.Array).Emit ("P"),
For.AnyInputIn (CppModifiers.Reference).Emit ("R"),
// Itanium mangled names do not include const or volatile unless
// they modify the type pointed to by pointer or reference.
Choose.TopOne (
For.AnyInputIn (CppModifiers.Pointer, CppModifiers.Reference).FollowedBy ().AllInputsIn (CppModifiers.Volatile, CppModifiers.Const).InAnyOrder ().Emit ("VK"),
For.AnyInputIn (CppModifiers.Pointer, CppModifiers.Reference).FollowedBy ().AnyInputIn(CppModifiers.Volatile).Emit ("V"),
For.AnyInputIn (CppModifiers.Pointer, CppModifiers.Reference).FollowedBy ().AnyInputIn(CppModifiers.Const).Emit ("K")
For.AllInputsIn (CppModifiers.Volatile, CppModifiers.Const).InAnyOrder ().After (ptrOrRef).Emit ("VK"),
For.AnyInputIn(CppModifiers.Volatile).After (ptrOrRef).Emit ("V"),
For.AnyInputIn(CppModifiers.Const).After (ptrOrRef).Emit ("K")
)
);
code.Append (string.Join(string.Empty, modifierCode.ToArray ()));
@ -89,6 +93,9 @@ namespace Mono.VisualC.Interop.ABI { @@ -89,6 +93,9 @@ namespace Mono.VisualC.Interop.ABI {
code.Append ('c');
break;
case CppTypes.Class:
case CppTypes.Struct:
case CppTypes.Union:
case CppTypes.Enum:
code.Append(mangleType.ElementTypeName.Length);
code.Append(mangleType.ElementTypeName);
break;

65
Mono.VisualC.Interop/ABI/Impl/MsvcAbi.cs

@ -12,21 +12,76 @@ using System.Text; @@ -12,21 +12,76 @@ using System.Text;
using System.Reflection;
using System.Runtime.InteropServices;
using Mono.VisualC.Interop;
namespace Mono.VisualC.Interop.ABI {
public class MsvcAbi : CppAbi {
public MsvcAbi ()
{
}
public override CallingConvention DefaultCallingConvention {
get {
throw new System.NotImplementedException ();
}
public override CallingConvention GetCallingConvention (MethodInfo methodInfo)
{
// FIXME: Varargs methods..?
if (Modifiers.IsStatic (methodInfo))
return CallingConvention.Cdecl;
else
return CallingConvention.ThisCall;
}
public override string GetMangledMethodName (MethodInfo methodInfo)
{
throw new System.NotImplementedException ();
string methodName = methodInfo.Name;
MethodType methodType = GetMethodType (methodInfo);
ParameterInfo [] parameters = methodInfo.GetParameters ();
StringBuilder nm = new StringBuilder ("?", 30);
// FIXME: This has to include not only the name of the immediate containing class,
// but also all names of containing classes and namespaces up the hierarchy.
nm.Append (methodName).Append ('@').Append (class_name).Append ("@@");
// function modifiers are a matrix of consecutive uppercase letters
// depending on access type and virtual (far)/static (far)/far modifiers
// first, access type
char funcModifier = 'Q'; // (public)
if (Modifiers.IsProtected (methodInfo))
funcModifier = 'I';
else if (Modifiers.IsPrivate (methodInfo))
funcModifier = 'A';
// now, offset based on other modifiers
if (Modifiers.IsStatic (methodInfo))
funcModifier += 2;
else if (Modifiers.IsVirtual (methodInfo)) // (do we need this?)
funcModifier += 4;
nm.Append (funcModifier);
// FIXME: deal with storage classes for "this" i.e. the "const" in -> int foo () const;
if (!Modifiers.IsStatic (methodInfo))
nm.Append ('A');
switch (GetCallingConvention (methodInfo)) {
case CallingConvention.Cdecl:
nm.Append ('A');
break;
case CallingConvention.ThisCall:
nm.Append ('E');
break;
case CallingConvention.StdCall:
nm.Append ('G');
break;
case CallingConvention.FastCall:
nm.Append ('I');
break;
}
// FIXME: handle const, volatile modifiers on return type
nm.Append ("?A");
}
}

4
Mono.VisualC.Interop/ABI/VTable.cs

@ -38,8 +38,8 @@ namespace Mono.VisualC.Interop.ABI { @@ -38,8 +38,8 @@ namespace Mono.VisualC.Interop.ABI {
get { return Marshal.SizeOf (typeof (IntPtr)); }
}
public abstract MethodInfo PrepareVirtualCall (MethodInfo target, ILGenerator callsite, FieldInfo vtableField,
LocalBuilder native, int vtableIndex);
public abstract MethodInfo PrepareVirtualCall (MethodInfo target, CallingConvention callingConvention, ILGenerator callsite,
LocalBuilder nativePtr, FieldInfo vtableField, int vtableIndex);
// Subclasses must allocate vtPtr!
public VTable (Delegate[] overrides)

4
Mono.VisualC.Interop/ABI/VTableCOM.cs

@ -29,8 +29,8 @@ namespace Mono.VisualC.Interop.ABI { @@ -29,8 +29,8 @@ namespace Mono.VisualC.Interop.ABI {
WriteOverrides (0);
}
public override MethodInfo PrepareVirtualCall (MethodInfo target, ILGenerator callsite, FieldInfo vtableField,
LocalBuilder native, int vtableIndex)
public override MethodInfo PrepareVirtualCall (MethodInfo target, CallingConvention callingConvention, ILGenerator callsite,
LocalBuilder nativePtr, FieldInfo vtableField, int vtableIndex)
{
throw new System.NotImplementedException ();
}

8
Mono.VisualC.Interop/ABI/VTableManaged.cs

@ -27,14 +27,14 @@ namespace Mono.VisualC.Interop.ABI { @@ -27,14 +27,14 @@ namespace Mono.VisualC.Interop.ABI {
WriteOverrides (0);
}
public override MethodInfo PrepareVirtualCall (MethodInfo target, ILGenerator callsite, FieldInfo vtableField,
LocalBuilder native, int vtableIndex)
public override MethodInfo PrepareVirtualCall (MethodInfo target, CallingConvention callingConvention, ILGenerator callsite,
LocalBuilder nativePtr, FieldInfo vtableField, int vtableIndex)
{
Type delegateType;
if (overrides [vtableIndex] != null)
delegateType = overrides [vtableIndex].GetType ();
else
delegateType = Util.GetDelegateTypeForMethodInfo (implModule, target);
delegateType = Util.GetDelegateTypeForMethodInfo (implModule, target, callingConvention);
MethodInfo getDelegate = typeof (VTableManaged).GetMethod ("GetDelegateForNative").MakeGenericMethod (delegateType);
@ -42,7 +42,7 @@ namespace Mono.VisualC.Interop.ABI { @@ -42,7 +42,7 @@ namespace Mono.VisualC.Interop.ABI {
callsite.Emit (OpCodes.Ldarg_0);
callsite.Emit (OpCodes.Ldfld, vtableField);
// call this._vtable.GetDelegateForNative(IntPtr native, int vtableIndex)
callsite.Emit (OpCodes.Ldloc_S, native);
callsite.Emit (OpCodes.Ldloc_S, nativePtr);
callsite.Emit (OpCodes.Ldc_I4, vtableIndex);
callsite.Emit (OpCodes.Callvirt, getDelegate);
// check for null

26
Mono.VisualC.Interop/Attributes.cs

@ -12,14 +12,16 @@ using System.Linq; @@ -12,14 +12,16 @@ using System.Linq;
using System.Reflection;
namespace Mono.VisualC.Interop {
#region Interface method attributes
[AttributeUsage (AttributeTargets.Method)]
public class VirtualAttribute : Attribute {}
[AttributeUsage (AttributeTargets.Method)]
public class StaticAttribute : Attribute {}
[AttributeUsage (AttributeTargets.Method)]
public class PrivateAttribute : Attribute {}
[AttributeUsage (AttributeTargets.Method)]
public class OverrideNativeAttribute : Attribute {}
public class ProtectedAttribute : Attribute {}
[AttributeUsage (AttributeTargets.Parameter | AttributeTargets.ReturnValue)]
public class MangleAsAttribute : Attribute {
@ -38,6 +40,10 @@ namespace Mono.VisualC.Interop { @@ -38,6 +40,10 @@ namespace Mono.VisualC.Interop {
this.MangleType = new CppType (cppTypeSpec);
}
}
#endregion
[AttributeUsage (AttributeTargets.Method)]
public class OverrideNativeAttribute : Attribute {}
public static class Modifiers {
@ -45,11 +51,18 @@ namespace Mono.VisualC.Interop { @@ -45,11 +51,18 @@ namespace Mono.VisualC.Interop {
{
return method.IsDefined (typeof (VirtualAttribute), false);
}
public static bool IsStatic (MethodInfo method)
{
return method.IsDefined (typeof (StaticAttribute), false);
}
public static bool IsPrivate (MethodInfo method)
{
return method.IsDefined (typeof (PrivateAttribute), false);
}
public static bool IsProtected (MethodInfo method)
{
return method.IsDefined (typeof (ProtectedAttribute), false);
}
public static CppType GetMangleType (ParameterInfo param)
{
@ -58,9 +71,10 @@ namespace Mono.VisualC.Interop { @@ -58,9 +71,10 @@ namespace Mono.VisualC.Interop {
if (maa != null)
mangleType = maa.MangleType;
// this means that only CppModifiers were applied .. apply CppType from managed parameter type
// this means that either no MangleAsAttribute was defined, or
// only CppModifiers were applied .. apply CppType from managed parameter type
if (mangleType.ElementType == CppTypes.Unknown && mangleType.ElementTypeName == null)
mangleType.Apply (CppType.ForManagedType (param.ParameterType));
mangleType.ApplyTo (CppType.ForManagedType (param.ParameterType));
else if (mangleType.ElementType == CppTypes.Unknown)
// FIXME: otherwise, we just assume it's CppTypes.Class for now.
mangleType.ElementType = CppTypes.Class;

30
Mono.VisualC.Interop/CppType.cs

@ -90,7 +90,6 @@ namespace Mono.VisualC.Interop { @@ -90,7 +90,6 @@ namespace Mono.VisualC.Interop {
// pointer types to C++ pointers
// array types to C++ arrays
(t) => {
if (t.GetElementType () == null) return CppTypes.Unknown;
CppType cppType = CppType.ForManagedType (t.GetElementType ());
if (t.IsByRef) cppType.Modifiers.Add (CppModifiers.Reference);
if (t.IsPointer) cppType.Modifiers.Add (CppModifiers.Pointer);
@ -105,7 +104,15 @@ namespace Mono.VisualC.Interop { @@ -105,7 +104,15 @@ namespace Mono.VisualC.Interop {
// this will contain the name of said type
public string ElementTypeName { get; set; }
public List<CppModifiers> Modifiers { get; private set; }
private List<CppModifiers> internalModifiers;
public List<CppModifiers> Modifiers {
get {
if (internalModifiers == null)
internalModifiers = new List<CppModifiers> ();
return internalModifiers;
}
}
// here, you can pass in things like "const char*" or "const Foo * const"
// DISCLAIMER: this is really just for convenience for now, and is not meant to be able
@ -119,8 +126,6 @@ namespace Mono.VisualC.Interop { @@ -119,8 +126,6 @@ namespace Mono.VisualC.Interop {
ElementType = CppTypes.Unknown;
ElementTypeName = null;
Modifiers = new List<CppModifiers> ();
Parse (cppTypeSpec);
}
@ -180,11 +185,10 @@ namespace Mono.VisualC.Interop { @@ -180,11 +185,10 @@ namespace Mono.VisualC.Interop {
return;
}
Type managedType = type as Type;
if (managedType != null) {
CppType mapped = CppType.ForManagedType (managedType);
Apply (mapped);
ApplyTo (mapped);
return;
}
}
@ -193,15 +197,16 @@ namespace Mono.VisualC.Interop { @@ -193,15 +197,16 @@ namespace Mono.VisualC.Interop {
// and combines its modifiers into this instance.
// Use when THIS instance may have attributes you want,
// but want the element type of the passed instance.
public void Apply (CppType type)
public void ApplyTo (CppType type)
{
ElementType = type.ElementType;
ElementTypeName = type.ElementTypeName;
if (Modifiers == null) Modifiers = new List<CppModifiers> ();
List<CppModifiers> oldModifiers = Modifiers;
Modifiers = type.Modifiers;
Modifiers.AddRange (oldModifiers);
List<CppModifiers> oldModifiers = internalModifiers;
internalModifiers = type.Modifiers;
if (oldModifiers != null)
Modifiers.AddRange (oldModifiers);
}
/*
@ -233,9 +238,6 @@ namespace Mono.VisualC.Interop { @@ -233,9 +238,6 @@ namespace Mono.VisualC.Interop {
where checkType (type).ElementType != CppTypes.Unknown
select checkType (type)).FirstOrDefault ();
if (mappedType.Modifiers == null)
mappedType.Modifiers = new List<CppModifiers> ();
return mappedType;
}

221
Mono.VisualC.Interop/IEnumerableTransform.cs

@ -5,20 +5,34 @@ using System.Collections.Generic; @@ -5,20 +5,34 @@ using System.Collections.Generic;
namespace Mono.VisualC.Interop {
public enum RuleResult {
NoMatch,
MatchEmit,
MatchNoEmit
}
public delegate bool EmitterFunc<TIn, TOut> (InputData<TIn> input, out TOut output);
public delegate RuleResult EmitterFunc<TIn, TOut> (InputData<TIn> input, out TOut output);
public struct InputData<TIn> {
public IEnumerable<TIn> AllValues;
public LookaheadEnumerator<TIn> Enumerator;
public CloneableEnumerator<TIn> Enumerator;
public List<IRule<TIn>> MatchedRules;
public InputData (IEnumerable<TIn> input, LookaheadEnumerator<TIn> enumerator)
public InputData (IEnumerable<TIn> input, CloneableEnumerator<TIn> enumerator)
{
this.AllValues = input;
this.Enumerator = enumerator;
this.MatchedRules = new List<IRule<TIn>> ();
}
public InputData<TIn> NewContext ()
{
InputData<TIn> nctx = new InputData<TIn> ();
nctx.AllValues = this.AllValues;
nctx.Enumerator = this.Enumerator.Clone ();
nctx.MatchedRules = this.MatchedRules;
return nctx;
}
public TIn Value {
get { return Enumerator.Current; }
}
@ -26,7 +40,7 @@ namespace Mono.VisualC.Interop { @@ -26,7 +40,7 @@ namespace Mono.VisualC.Interop {
#region Rules
public interface IRule<TIn> {
bool SatisfiedBy (InputData<TIn> input);
RuleResult SatisfiedBy (InputData<TIn> input);
}
// yields all inputs indescriminately
@ -34,9 +48,9 @@ namespace Mono.VisualC.Interop { @@ -34,9 +48,9 @@ namespace Mono.VisualC.Interop {
public AnyRule ()
{
}
public bool SatisfiedBy (InputData<TIn> input)
public RuleResult SatisfiedBy (InputData<TIn> input)
{
return true;
return RuleResult.MatchEmit;
}
}
@ -46,9 +60,9 @@ namespace Mono.VisualC.Interop { @@ -46,9 +60,9 @@ namespace Mono.VisualC.Interop {
public UnmatchedRule ()
{
}
public bool SatisfiedBy (InputData<TIn> input)
public RuleResult SatisfiedBy (InputData<TIn> input)
{
return !input.MatchedRules.Any ();
return !input.MatchedRules.Any ()? RuleResult.MatchEmit : RuleResult.NoMatch;
}
}
@ -58,13 +72,13 @@ namespace Mono.VisualC.Interop { @@ -58,13 +72,13 @@ namespace Mono.VisualC.Interop {
public FirstRule ()
{
}
public bool SatisfiedBy (InputData<TIn> input)
public RuleResult SatisfiedBy (InputData<TIn> input)
{
if (!triggered) {
triggered = true;
return true;
return RuleResult.MatchEmit;
}
return false;
return RuleResult.NoMatch;
}
}
@ -74,18 +88,27 @@ namespace Mono.VisualC.Interop { @@ -74,18 +88,27 @@ namespace Mono.VisualC.Interop {
public LastRule ()
{
}
public bool SatisfiedBy (InputData<TIn> input)
public RuleResult SatisfiedBy (InputData<TIn> input)
{
IEnumerator<TIn> item = input.Enumerator;
throw new NotImplementedException ();
}
}
while (item.MoveNext ()) {
foreach (var prevRule in input.MatchedRules) {
if (prevRule.SatisfiedBy (input))
return false;
}
}
// yields input if the specified previous rule has already been satisfied
public class AfterRule<TIn> : IRule<TIn> {
protected IRule<TIn> previousRule;
protected bool satisfied = false;
public AfterRule (IRule<TIn> previousRule)
{
this.previousRule = previousRule;
}
public RuleResult SatisfiedBy (InputData<TIn> input)
{
if (satisfied)
return RuleResult.MatchEmit;
return true;
satisfied = previousRule.SatisfiedBy (input) != RuleResult.NoMatch;
return RuleResult.NoMatch;
}
}
@ -101,9 +124,22 @@ namespace Mono.VisualC.Interop { @@ -101,9 +124,22 @@ namespace Mono.VisualC.Interop {
{
this.conditions = conditions;
}
public bool SatisfiedBy (InputData<TIn> input)
public RuleResult SatisfiedBy (InputData<TIn> input)
{
return conditions.Contains (input.Value);
return conditions.Contains (input.Value)? RuleResult.MatchEmit : RuleResult.NoMatch;
}
}
public class PredicateRule<TIn> : IRule<TIn> {
protected Func<TIn, bool> predicate;
public PredicateRule (Func<TIn, bool> predicate)
{
this.predicate = predicate;
}
public RuleResult SatisfiedBy (InputData<TIn> input)
{
return predicate (input.Value)? RuleResult.MatchEmit : RuleResult.NoMatch;
}
}
@ -124,11 +160,11 @@ namespace Mono.VisualC.Interop { @@ -124,11 +160,11 @@ namespace Mono.VisualC.Interop {
{
this.conditions = conditions;
}
public bool SatisfiedBy (InputData<TIn> inputData)
public RuleResult SatisfiedBy (InputData<TIn> inputData)
{
if (verified && verifiedItems.Count > 0) {
verifiedItems.Dequeue ();
return false;
return RuleResult.MatchNoEmit;
} else
verified = false;
@ -142,51 +178,51 @@ namespace Mono.VisualC.Interop { @@ -142,51 +178,51 @@ namespace Mono.VisualC.Interop {
if (verifiedItems.Count == conditions.Count ()) {
verified = true;
verifiedItems.Dequeue ();
return true;
return RuleResult.MatchEmit;
} else
verifiedItems.Clear ();
return false;
return RuleResult.NoMatch;
}
}
public class InOrderRule<TIn> : IRule<TIn> {
protected IEnumerable<IRule<TIn>> conditions;
protected IEnumerable<TIn> conditions;
protected bool verified = false;
protected int verifiedCount = 0;
public InOrderRule (params IRule<TIn> [] conditions)
public InOrderRule (params TIn [] conditions)
{
this.conditions = conditions;
}
public InOrderRule (IEnumerable<IRule<TIn>> conditions)
public InOrderRule (IEnumerable<TIn> conditions)
{
this.conditions = conditions;
}
public bool SatisfiedBy (InputData<TIn> inputData)
public RuleResult SatisfiedBy (InputData<TIn> inputData)
{
if (verified && verifiedCount > 0) {
verifiedCount--;
return false;
return RuleResult.MatchNoEmit;
} else
verified = false;
IEnumerator<IRule<TIn>> condition = conditions.GetEnumerator ();
IEnumerator<TIn> condition = conditions.GetEnumerator ();
IEnumerator<TIn> input = inputData.Enumerator;
while (condition.MoveNext () && condition.Current.SatisfiedBy (inputData)) {
while (condition.MoveNext () && condition.Equals (input.Current)) {
verifiedCount++;
if (!input.MoveNext ()) break;
}
if (verifiedCount == conditions.Count ()) {
verified = true;
verifiedCount--;
return true;
return RuleResult.MatchEmit;
} else
verifiedCount = 0;
return false;
return RuleResult.NoMatch;
}
}
@ -202,15 +238,19 @@ namespace Mono.VisualC.Interop { @@ -202,15 +238,19 @@ namespace Mono.VisualC.Interop {
{
this.rules = rules;
}
public bool SatisfiedBy (InputData<TIn> input)
public RuleResult SatisfiedBy (InputData<TIn> input)
{
RuleResult finalResult = RuleResult.NoMatch;
foreach (var rule in rules) {
if (!rule.SatisfiedBy (input))
return false;
RuleResult result = rule.SatisfiedBy (input.NewContext ());
if (result == RuleResult.NoMatch)
return RuleResult.NoMatch;
if (finalResult != RuleResult.MatchNoEmit)
finalResult = result;
input.MatchedRules.Add (rule);
}
return true;
return finalResult;
}
}
@ -226,18 +266,18 @@ namespace Mono.VisualC.Interop { @@ -226,18 +266,18 @@ namespace Mono.VisualC.Interop {
{
this.rules = rules;
}
public bool SatisfiedBy (InputData<TIn> input)
public RuleResult SatisfiedBy (InputData<TIn> input)
{
bool satisfied = false;
foreach (var rule in rules) {
if (!rule.SatisfiedBy (input))
continue;
satisfied = true;
input.MatchedRules.Add (rule);
RuleResult result = rule.SatisfiedBy (input.NewContext ());
if (result != RuleResult.NoMatch) {
input.MatchedRules.Add (rule);
return result;
}
}
return satisfied;
return RuleResult.NoMatch;
}
}
#endregion
@ -278,6 +318,11 @@ namespace Mono.VisualC.Interop { @@ -278,6 +318,11 @@ namespace Mono.VisualC.Interop {
});
}
public static IRule<TIn> InputsWhere<TIn> (Func<TIn, bool> predicate)
{
return new PredicateRule<TIn> (predicate);
}
public static IRule<TIn> AnyInput<TIn> ()
{
return new AnyRule<TIn> ();
@ -307,15 +352,21 @@ namespace Mono.VisualC.Interop { @@ -307,15 +352,21 @@ namespace Mono.VisualC.Interop {
public IRule<TIn> AnyInputIn (params TIn[] input)
{
return additionalRuleCallback(new InSetRule<TIn> (input));
return additionalRuleCallback (new InSetRule<TIn> (input));
}
public IRule<TIn> AnyInputIn (IEnumerable<TIn> input)
{
return additionalRuleCallback(new InSetRule<TIn> (input));
return additionalRuleCallback (new InSetRule<TIn> (input));
}
public IRule<TIn> InputsWhere (Func<TIn, bool> predicate)
{
return additionalRuleCallback (new PredicateRule<TIn> (predicate));
}
public IRule<TIn> AnyInput ()
{
return additionalRuleCallback(new AnyRule<TIn> ());
return additionalRuleCallback (new AnyRule<TIn> ());
}
}
@ -331,7 +382,7 @@ namespace Mono.VisualC.Interop { @@ -331,7 +382,7 @@ namespace Mono.VisualC.Interop {
public IRule<TIn> InThatOrder ()
{
return additionalRuleCallback (new InOrderRule<TIn> (sequence.Select (tin => (IRule<TIn>)new InSetRule<TIn> (tin))));
return additionalRuleCallback (new InOrderRule<TIn> (sequence));
}
public IRule<TIn> InAnyOrder ()
@ -347,64 +398,46 @@ namespace Mono.VisualC.Interop { @@ -347,64 +398,46 @@ namespace Mono.VisualC.Interop {
return delegate (InputData<TIn> input, out TOut output) {
output = default (TOut);
foreach (var rule in rules) {
if (rule (input, out output))
return true;
input.Enumerator.Validate ();
RuleResult result = rule (input.NewContext (), out output);
if (result != RuleResult.NoMatch)
return result;
}
return false;
return RuleResult.NoMatch;
};
}
}
public class LookaheadEnumerator<T> : IEnumerator<T> {
public class CloneableEnumerator<T> : IEnumerator<T> {
private IEnumerable<T> wrappedEnumerable;
private IEnumerator<T> wrappedEnumerator;
private int position;
private bool invalidated;
public LookaheadEnumerator (IEnumerable<T> enumerable, int position)
public CloneableEnumerator (IEnumerable<T> enumerable, int position)
{
this.wrappedEnumerable = enumerable;
this.position = position;
this.invalidated = true;
Validate ();
}
public void Reset ()
{
invalidated = true;
wrappedEnumerator.Reset ();
}
public void Validate ()
{
if (!invalidated) return;
wrappedEnumerator = wrappedEnumerable.GetEnumerator ();
this.wrappedEnumerator = wrappedEnumerable.GetEnumerator ();
for (int i = 0; i < position; i++)
wrappedEnumerator.MoveNext ();
}
invalidated = false;
public CloneableEnumerator<T> Clone () {
return new CloneableEnumerator<T> (this.wrappedEnumerable, this.position);
}
public bool ValidMoveNext ()
public void Reset ()
{
Validate ();
position++;
return wrappedEnumerator.MoveNext ();
wrappedEnumerator.Reset ();
}
public bool MoveNext ()
{
invalidated = true;
position++;
return wrappedEnumerator.MoveNext ();
}
public bool Invalidated {
get { return invalidated; }
}
public T Current {
get { return wrappedEnumerator.Current; }
}
@ -422,17 +455,16 @@ namespace Mono.VisualC.Interop { @@ -422,17 +455,16 @@ namespace Mono.VisualC.Interop {
public static IEnumerable<TOut> Transform<TIn, TOut> (this IEnumerable<TIn> input, params EmitterFunc<TIn, TOut> [] rules)
{
LookaheadEnumerator<TIn> enumerator = new LookaheadEnumerator<TIn> (input, 0);
while (enumerator.ValidMoveNext ()) {
CloneableEnumerator<TIn> enumerator = new CloneableEnumerator<TIn> (input, 0);
while (enumerator.MoveNext ()) {
InputData<TIn> inputData = new InputData<TIn> (input, enumerator);
foreach (var rule in rules) {
TOut output;
if (rule (inputData, out output))
if (rule (inputData.NewContext (), out output) == RuleResult.MatchEmit)
yield return output;
enumerator.Validate ();
}
}
@ -460,15 +492,14 @@ namespace Mono.VisualC.Interop { @@ -460,15 +492,14 @@ namespace Mono.VisualC.Interop {
});
}
public static IRule<TIn> FollowedBy<TIn> (this IRule<TIn> previousRules, IRule<TIn> parentheticalRules)
public static IRule<TIn> After<TIn> (this IRule<TIn> previousRules, IRule<TIn> parentheticalRules)
{
return new InOrderRule<TIn> (previousRules, parentheticalRules);
return new AndRule<TIn> (new AfterRule<TIn> (parentheticalRules), previousRules);
}
public static RuleCompound<TIn> FollowedBy<TIn> (this IRule<TIn> previousRules)
public static RuleCompound<TIn> After<TIn> (this IRule<TIn> previousRules)
{
return new RuleCompound<TIn> ((subsequentRules) => {
return FollowedBy<TIn> (previousRules, subsequentRules);
return After<TIn> (previousRules, subsequentRules);
});
}
@ -477,12 +508,14 @@ namespace Mono.VisualC.Interop { @@ -477,12 +508,14 @@ namespace Mono.VisualC.Interop {
return delegate (InputData<TIn> input, out TOut output) {
output = default (TOut);
TIn value = input.Value;
if (rule.SatisfiedBy (input)) {
RuleResult ruleResult = rule.SatisfiedBy (input);
if (ruleResult != RuleResult.NoMatch) {
input.MatchedRules.Add (rule);
output = result (value);
return true;
return ruleResult;
}
return false;
return RuleResult.NoMatch;
};
}
public static EmitterFunc<TIn, TOut> Emit<TIn, TOut> (this IRule<TIn> rule, TOut result)

7
Mono.VisualC.Interop/Util.cs

@ -13,7 +13,7 @@ namespace Mono.VisualC.Interop { @@ -13,7 +13,7 @@ namespace Mono.VisualC.Interop {
return delType.GetMethod ("Invoke");
}
public static Type GetDelegateTypeForMethodInfo (ModuleBuilder mod, MethodInfo targetMethod)
public static Type GetDelegateTypeForMethodInfo (ModuleBuilder mod, MethodInfo targetMethod, CallingConvention? callingConvention)
{
// TODO: Actually return the same delegate type instead of creating a new one if
// a suitable type already exists??
@ -24,6 +24,11 @@ namespace Mono.VisualC.Interop { @@ -24,6 +24,11 @@ namespace Mono.VisualC.Interop {
TypeAttributes typeAttr = TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.AnsiClass | TypeAttributes.AutoClass;
TypeBuilder del = mod.DefineType (delTypeName, typeAttr, typeof(MulticastDelegate));
if (callingConvention.HasValue) {
ConstructorInfo ufpa = typeof (UnmanagedFunctionPointerAttribute).GetConstructor (new Type [] { typeof (CallingConvention) });
CustomAttributeBuilder unmanagedPointer = new CustomAttributeBuilder (ufpa, new object [] { callingConvention.Value });
del.SetCustomAttribute (unmanagedPointer);
}
MethodAttributes ctorAttr = MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public;
ConstructorBuilder ctor = del.DefineConstructor (ctorAttr, CallingConventions.Standard, new Type[] { typeof(object), typeof(System.IntPtr) });

Loading…
Cancel
Save