Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0bb5a45

Browse files
committed
a bit more refactoring of MethodBinder.Bind
1 parent a19b51b commit 0bb5a45

File tree

1 file changed

+92
-85
lines changed

1 file changed

+92
-85
lines changed

src/runtime/methodbinder.cs

Lines changed: 92 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
291291
{
292292
_methods = GetMethods();
293293
}
294-
Type clrtype;
294+
295295
// TODO: Clean up
296296
foreach (MethodBase mi in _methods)
297297
{
@@ -303,15 +303,14 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
303303
ArrayList defaultArgList;
304304
int arrayStart;
305305

306-
if (!MatchArgumentCount(pynargs, pi, out arrayStart, out defaultArgList)) {
306+
if (!MatchesArgumentCount(pynargs, pi, out arrayStart, out defaultArgList)) {
307307
continue;
308308
}
309309
var outs = 0;
310310
var margs = new object[pi.Length];
311311

312312
for (int paramIndex = 0; paramIndex < pi.Length; paramIndex++)
313313
{
314-
IntPtr op;
315314
if (paramIndex >= pynargs)
316315
{
317316
if (defaultArgList != null)
@@ -322,85 +321,21 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
322321
continue;
323322
}
324323

325-
if (arrayStart == paramIndex)
326-
{
324+
IntPtr op = (arrayStart == paramIndex)
327325
// map remaining Python arguments to a tuple since
328326
// the managed function accepts it - hopefully :]
329-
op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs);
330-
}
331-
else
332-
{
333-
op = Runtime.PyTuple_GetItem(args, paramIndex);
334-
}
335-
336-
// this logic below handles cases when multiple overloading methods
337-
// are ambiguous, hence comparison between Python and CLR types
338-
// is necessary
339-
clrtype = null;
340-
IntPtr pyoptype;
341-
if (_methods.Length > 1)
342-
{
343-
pyoptype = IntPtr.Zero;
344-
pyoptype = Runtime.PyObject_Type(op);
345-
Exceptions.Clear();
346-
if (pyoptype != IntPtr.Zero)
347-
{
348-
clrtype = Converter.GetTypeByAlias(pyoptype);
349-
}
350-
Runtime.XDecref(pyoptype);
351-
}
327+
? Runtime.PyTuple_GetSlice(args, arrayStart, pynargs)
328+
: Runtime.PyTuple_GetItem(args, paramIndex);
352329

330+
var parameter = pi[paramIndex];
353331

354-
if (clrtype != null)
355-
{
356-
var typematch = false;
357-
if ((pi[paramIndex].ParameterType != typeof(object)) && (pi[paramIndex].ParameterType != clrtype))
358-
{
359-
IntPtr pytype = Converter.GetPythonTypeByAlias(pi[paramIndex].ParameterType);
360-
pyoptype = Runtime.PyObject_Type(op);
361-
Exceptions.Clear();
362-
if (pyoptype != IntPtr.Zero)
363-
{
364-
if (pytype != pyoptype)
365-
{
366-
typematch = false;
367-
}
368-
else
369-
{
370-
typematch = true;
371-
clrtype = pi[paramIndex].ParameterType;
372-
}
373-
}
374-
if (!typematch)
375-
{
376-
// this takes care of enum values
377-
TypeCode argtypecode = Type.GetTypeCode(pi[paramIndex].ParameterType);
378-
TypeCode paramtypecode = Type.GetTypeCode(clrtype);
379-
if (argtypecode == paramtypecode)
380-
{
381-
typematch = true;
382-
clrtype = pi[paramIndex].ParameterType;
383-
}
384-
}
385-
Runtime.XDecref(pyoptype);
386-
if (!typematch)
387-
{
388-
margs = null;
389-
break;
390-
}
391-
}
392-
else
393-
{
394-
typematch = true;
395-
clrtype = pi[paramIndex].ParameterType;
396-
}
397-
}
398-
else
399-
{
400-
clrtype = pi[paramIndex].ParameterType;
332+
var clrtype = TryComputeClrArgumentType(parameter.ParameterType, op, needsResolution: _methods.Length > 1);
333+
if (clrtype == null) {
334+
margs = null;
335+
break;
401336
}
402337

403-
if (pi[paramIndex].IsOut || clrtype.IsByRef)
338+
if (parameter.IsOut || clrtype.IsByRef)
404339
{
405340
outs++;
406341
}
@@ -459,32 +394,104 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
459394
return null;
460395
}
461396

462-
static bool MatchArgumentCount(int pynargs, ParameterInfo[] pi, out int paramsArrayStart, out ArrayList defaultArgList)
397+
static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool needsResolution)
398+
{
399+
// this logic below handles cases when multiple overloading methods
400+
// are ambiguous, hence comparison between Python and CLR types
401+
// is necessary
402+
Type clrtype = null;
403+
IntPtr pyoptype;
404+
if (needsResolution)
405+
{
406+
// HACK: each overload should be weighted in some way instead
407+
pyoptype = Runtime.PyObject_Type(argument);
408+
Exceptions.Clear();
409+
if (pyoptype != IntPtr.Zero)
410+
{
411+
clrtype = Converter.GetTypeByAlias(pyoptype);
412+
}
413+
Runtime.XDecref(pyoptype);
414+
}
415+
416+
if (clrtype != null)
417+
{
418+
var typematch = false;
419+
if ((parameterType != typeof(object)) && (parameterType != clrtype))
420+
{
421+
IntPtr pytype = Converter.GetPythonTypeByAlias(parameterType);
422+
pyoptype = Runtime.PyObject_Type(argument);
423+
Exceptions.Clear();
424+
if (pyoptype != IntPtr.Zero)
425+
{
426+
if (pytype != pyoptype)
427+
{
428+
typematch = false;
429+
}
430+
else
431+
{
432+
typematch = true;
433+
clrtype = parameterType;
434+
}
435+
}
436+
if (!typematch)
437+
{
438+
// this takes care of enum values
439+
TypeCode argtypecode = Type.GetTypeCode(parameterType);
440+
TypeCode paramtypecode = Type.GetTypeCode(clrtype);
441+
if (argtypecode == paramtypecode)
442+
{
443+
typematch = true;
444+
clrtype = parameterType;
445+
}
446+
}
447+
Runtime.XDecref(pyoptype);
448+
if (!typematch)
449+
{
450+
return null;
451+
}
452+
}
453+
else
454+
{
455+
typematch = true;
456+
clrtype = parameterType;
457+
}
458+
}
459+
else
460+
{
461+
clrtype = parameterType;
462+
}
463+
464+
return clrtype;
465+
}
466+
467+
static bool MatchesArgumentCount(int argumentCount, ParameterInfo[] parameters,
468+
out int paramsArrayStart,
469+
out ArrayList defaultArgList)
463470
{
464471
defaultArgList = null;
465472
var match = false;
466473
paramsArrayStart = -1;
467474

468-
if (pynargs == pi.Length)
475+
if (argumentCount == parameters.Length)
469476
{
470477
match = true;
471-
} else if (pynargs < pi.Length)
478+
} else if (argumentCount < parameters.Length)
472479
{
473480
match = true;
474481
defaultArgList = new ArrayList();
475-
for (var v = pynargs; v < pi.Length; v++) {
476-
if (pi[v].DefaultValue == DBNull.Value) {
482+
for (var v = argumentCount; v < parameters.Length; v++) {
483+
if (parameters[v].DefaultValue == DBNull.Value) {
477484
match = false;
478485
} else {
479-
defaultArgList.Add(pi[v].DefaultValue);
486+
defaultArgList.Add(parameters[v].DefaultValue);
480487
}
481488
}
482-
} else if (pynargs > pi.Length && pi.Length > 0 &&
483-
Attribute.IsDefined(pi[pi.Length - 1], typeof(ParamArrayAttribute)))
489+
} else if (argumentCount > parameters.Length && parameters.Length > 0 &&
490+
Attribute.IsDefined(parameters[parameters.Length - 1], typeof(ParamArrayAttribute)))
484491
{
485492
// This is a `foo(params object[] bar)` style method
486493
match = true;
487-
paramsArrayStart = pi.Length - 1;
494+
paramsArrayStart = parameters.Length - 1;
488495
}
489496

490497
return match;

0 commit comments

Comments
 (0)