PageRenderTime 56ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/DICK.B1/IronPython/Runtime/Binding/MetaPythonType.Calls.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 780 lines | 606 code | 121 blank | 53 comment | 78 complexity | 26fa6a20c668ebdab2f5786d9ba6d3ec MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Microsoft Public License. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Microsoft Public License, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Microsoft Public License.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. #if !CLR2
  16. using System.Linq.Expressions;
  17. #else
  18. using Microsoft.Scripting.Ast;
  19. #endif
  20. using System;
  21. using System.Collections.Generic;
  22. using System.Diagnostics;
  23. using System.Dynamic;
  24. using System.Reflection;
  25. using Microsoft.Scripting;
  26. using Microsoft.Scripting.Actions;
  27. using Microsoft.Scripting.Generation;
  28. using Microsoft.Scripting.Runtime;
  29. using Microsoft.Scripting.Utils;
  30. using IronPython.Runtime.Operations;
  31. using IronPython.Runtime.Types;
  32. namespace IronPython.Runtime.Binding {
  33. using Ast = Expression;
  34. using AstUtils = Microsoft.Scripting.Ast.Utils;
  35. partial class MetaPythonType : MetaPythonObject, IPythonInvokable {
  36. #region IPythonInvokable Members
  37. public DynamicMetaObject/*!*/ Invoke(PythonInvokeBinder/*!*/ pythonInvoke, Expression/*!*/ codeContext, DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args) {
  38. DynamicMetaObject translated = BuiltinFunction.TranslateArguments(pythonInvoke, codeContext, target, args, false, Value.Name);
  39. if (translated != null) {
  40. return translated;
  41. }
  42. return InvokeWorker(pythonInvoke, args, codeContext);
  43. }
  44. #endregion
  45. #region MetaObject Overrides
  46. public override DynamicMetaObject/*!*/ BindInvokeMember(InvokeMemberBinder/*!*/ action, DynamicMetaObject/*!*/[]/*!*/ args) {
  47. foreach (PythonType pt in Value.ResolutionOrder) {
  48. PythonTypeSlot dummy;
  49. if (pt.IsSystemType) {
  50. return action.FallbackInvokeMember(this, args);
  51. } else if (
  52. pt.TryResolveSlot(DefaultContext.DefaultCLS, action.Name, out dummy) ||
  53. pt.IsOldClass) {
  54. break;
  55. }
  56. }
  57. return BindingHelpers.GenericInvokeMember(action, null, this, args);
  58. }
  59. public override DynamicMetaObject/*!*/ BindInvoke(InvokeBinder/*!*/ call, params DynamicMetaObject/*!*/[]/*!*/ args) {
  60. return InvokeWorker(call, args, PythonContext.GetCodeContext(call));
  61. }
  62. #endregion
  63. #region Invoke Implementation
  64. private DynamicMetaObject/*!*/ InvokeWorker(DynamicMetaObjectBinder/*!*/ call, DynamicMetaObject/*!*/[]/*!*/ args, Expression/*!*/ codeContext) {
  65. PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Type Invoke " + Value.UnderlyingSystemType.FullName + args.Length);
  66. PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "Type Invoke");
  67. if (this.NeedsDeferral()) {
  68. return call.Defer(ArrayUtils.Insert(this, args));
  69. }
  70. for (int i = 0; i < args.Length; i++) {
  71. if (args[i].NeedsDeferral()) {
  72. return call.Defer(ArrayUtils.Insert(this, args));
  73. }
  74. }
  75. DynamicMetaObject res;
  76. if (IsStandardDotNetType(call)) {
  77. res = MakeStandardDotNetTypeCall(call, codeContext, args);
  78. } else {
  79. res = MakePythonTypeCall(call, codeContext, args);
  80. }
  81. return BindingHelpers.AddPythonBoxing(res);
  82. }
  83. /// <summary>
  84. /// Creating a standard .NET type is easy - we just call it's constructor with the provided
  85. /// arguments.
  86. /// </summary>
  87. private DynamicMetaObject/*!*/ MakeStandardDotNetTypeCall(DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext, DynamicMetaObject/*!*/[]/*!*/ args) {
  88. CallSignature signature = BindingHelpers.GetCallSignature(call);
  89. PythonContext state = PythonContext.GetPythonContext(call);
  90. MethodBase[] ctors = CompilerHelpers.GetConstructors(Value.UnderlyingSystemType, state.Binder.PrivateBinding);
  91. if (ctors.Length > 0) {
  92. return state.Binder.CallMethod(
  93. new PythonOverloadResolver(
  94. state.Binder,
  95. args,
  96. signature,
  97. codeContext
  98. ),
  99. ctors,
  100. Restrictions.Merge(BindingRestrictions.GetInstanceRestriction(Expression, Value))
  101. );
  102. } else {
  103. string msg;
  104. if (Value.UnderlyingSystemType.IsAbstract) {
  105. msg = String.Format("Cannot create instances of {0} because it is abstract", Value.Name);
  106. }else{
  107. msg = String.Format("Cannot create instances of {0} because it has no public constructors", Value.Name);
  108. }
  109. return new DynamicMetaObject(
  110. Ast.Throw(
  111. Ast.New(
  112. typeof(ArgumentTypeException).GetConstructor(new Type[] { typeof(string) }),
  113. AstUtils.Constant(msg)
  114. )
  115. ),
  116. Restrictions.Merge(BindingRestrictions.GetInstanceRestriction(Expression, Value))
  117. );
  118. }
  119. }
  120. /// <summary>
  121. /// Creating a Python type involves calling __new__ and __init__. We resolve them
  122. /// and generate calls to either the builtin funcions directly or embed sites which
  123. /// call the slots at runtime.
  124. /// </summary>
  125. private DynamicMetaObject/*!*/ MakePythonTypeCall(DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext, DynamicMetaObject/*!*/[]/*!*/ args) {
  126. ValidationInfo valInfo = MakeVersionCheck();
  127. DynamicMetaObject self = new RestrictedMetaObject(
  128. AstUtils.Convert(Expression, LimitType),
  129. BindingRestrictionsHelpers.GetRuntimeTypeRestriction(Expression, LimitType),
  130. Value
  131. );
  132. CallSignature sig = BindingHelpers.GetCallSignature(call);
  133. ArgumentValues ai = new ArgumentValues(sig, self, args);
  134. NewAdapter newAdapter;
  135. InitAdapter initAdapter;
  136. if (TooManyArgsForDefaultNew(call, args)) {
  137. return MakeIncorrectArgumentsForCallError(call, ai, valInfo);
  138. } else if (Value.UnderlyingSystemType.IsGenericTypeDefinition) {
  139. return MakeGenericTypeDefinitionError(call, ai, valInfo);
  140. }
  141. DynamicMetaObject translated = BuiltinFunction.TranslateArguments(call, codeContext, self, args, false, Value.Name);
  142. if (translated != null) {
  143. return translated;
  144. }
  145. GetAdapters(ai, call, codeContext, out newAdapter, out initAdapter);
  146. PythonContext state = PythonContext.GetPythonContext(call);
  147. // get the expression for calling __new__
  148. DynamicMetaObject createExpr = newAdapter.GetExpression(state.Binder);
  149. if (createExpr.Expression.Type == typeof(void)) {
  150. return BindingHelpers.AddDynamicTestAndDefer(
  151. call,
  152. createExpr,
  153. args,
  154. valInfo
  155. );
  156. }
  157. Expression res;
  158. BindingRestrictions additionalRestrictions = BindingRestrictions.Empty;
  159. if (!Value.IsSystemType && (!(newAdapter is DefaultNewAdapter) || HasFinalizer(call))) {
  160. // we need to dynamically check the return value to see if it's a subtype of
  161. // the type that we are calling. If it is then we need to call __init__/__del__
  162. // for the actual returned type.
  163. res = Expression.Dynamic(
  164. Value.GetLateBoundInitBinder(sig),
  165. typeof(object),
  166. ArrayUtils.Insert(
  167. codeContext,
  168. Expression.Convert(createExpr.Expression, typeof(object)),
  169. DynamicUtils.GetExpressions(args)
  170. )
  171. );
  172. additionalRestrictions = createExpr.Restrictions;
  173. } else {
  174. // just call the __init__ method, built-in types currently have
  175. // no wacky return values which don't return the derived type.
  176. // then get the statement for calling __init__
  177. ParameterExpression allocatedInst = Ast.Variable(createExpr.GetLimitType(), "newInst");
  178. Expression tmpRead = allocatedInst;
  179. DynamicMetaObject initCall = initAdapter.MakeInitCall(
  180. state.Binder,
  181. new RestrictedMetaObject(
  182. AstUtils.Convert(allocatedInst, Value.UnderlyingSystemType),
  183. createExpr.Restrictions
  184. )
  185. );
  186. List<Expression> body = new List<Expression>();
  187. Debug.Assert(!HasFinalizer(call));
  188. // add the call to init if we need to
  189. if (initCall.Expression != tmpRead) {
  190. // init can fail but if __new__ returns a different type
  191. // no exception is raised.
  192. DynamicMetaObject initStmt = initCall;
  193. if (body.Count == 0) {
  194. body.Add(
  195. Ast.Assign(allocatedInst, createExpr.Expression)
  196. );
  197. }
  198. if (!Value.UnderlyingSystemType.IsAssignableFrom(createExpr.Expression.Type)) {
  199. // return type of object, we need to check the return type before calling __init__.
  200. body.Add(
  201. AstUtils.IfThen(
  202. Ast.TypeIs(allocatedInst, Value.UnderlyingSystemType),
  203. initStmt.Expression
  204. )
  205. );
  206. } else {
  207. // just call the __init__ method, no type check necessary (TODO: need null check?)
  208. body.Add(initStmt.Expression);
  209. }
  210. }
  211. // and build the target from everything we have
  212. if (body.Count == 0) {
  213. res = createExpr.Expression;
  214. } else {
  215. body.Add(allocatedInst);
  216. res = Ast.Block(body);
  217. }
  218. res = Ast.Block(new ParameterExpression[] { allocatedInst }, res);
  219. additionalRestrictions = initCall.Restrictions;
  220. }
  221. return BindingHelpers.AddDynamicTestAndDefer(
  222. call,
  223. new DynamicMetaObject(
  224. res,
  225. self.Restrictions.Merge(additionalRestrictions)
  226. ),
  227. ArrayUtils.Insert(this, args),
  228. valInfo
  229. );
  230. }
  231. #endregion
  232. #region Adapter support
  233. private void GetAdapters(ArgumentValues/*!*/ ai, DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext, out NewAdapter/*!*/ newAdapter, out InitAdapter/*!*/ initAdapter) {
  234. PythonTypeSlot newInst, init;
  235. Value.TryResolveSlot(PythonContext.GetPythonContext(call).SharedContext, "__new__", out newInst);
  236. Value.TryResolveSlot(PythonContext.GetPythonContext(call).SharedContext, "__init__", out init);
  237. // these are never null because we always resolve to __new__ or __init__ somewhere.
  238. Assert.NotNull(newInst, init);
  239. newAdapter = GetNewAdapter(ai, newInst, call, codeContext);
  240. initAdapter = GetInitAdapter(ai, init, call, codeContext);
  241. }
  242. private InitAdapter/*!*/ GetInitAdapter(ArgumentValues/*!*/ ai, PythonTypeSlot/*!*/ init, DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext) {
  243. PythonContext state = PythonContext.GetPythonContext(call);
  244. if (Value.IsMixedNewStyleOldStyle()) {
  245. return new MixedInitAdapter(ai, state, codeContext);
  246. } else if ((init == InstanceOps.Init && !HasFinalizer(call)) || (Value == TypeCache.PythonType && ai.Arguments.Length == 2)) {
  247. return new DefaultInitAdapter(ai, state, codeContext);
  248. } else if (init is BuiltinMethodDescriptor) {
  249. return new BuiltinInitAdapter(ai, ((BuiltinMethodDescriptor)init).Template, state, codeContext);
  250. } else if (init is BuiltinFunction) {
  251. return new BuiltinInitAdapter(ai, (BuiltinFunction)init, state, codeContext);
  252. } else {
  253. return new SlotInitAdapter(init, ai, state, codeContext);
  254. }
  255. }
  256. private NewAdapter/*!*/ GetNewAdapter(ArgumentValues/*!*/ ai, PythonTypeSlot/*!*/ newInst, DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext) {
  257. PythonContext state = PythonContext.GetPythonContext(call);
  258. if (Value.IsMixedNewStyleOldStyle()) {
  259. return new MixedNewAdapter(ai, state, codeContext);
  260. } else if (newInst == InstanceOps.New) {
  261. return new DefaultNewAdapter(ai, Value, state, codeContext);
  262. } else if (newInst is ConstructorFunction) {
  263. return new ConstructorNewAdapter(ai, Value, state, codeContext);
  264. } else if (newInst is BuiltinFunction) {
  265. return new BuiltinNewAdapter(ai, Value, ((BuiltinFunction)newInst), state, codeContext);
  266. }
  267. return new NewAdapter(ai, state, codeContext);
  268. }
  269. private class CallAdapter {
  270. private readonly ArgumentValues/*!*/ _argInfo;
  271. private readonly PythonContext/*!*/ _state;
  272. private readonly Expression/*!*/ _context;
  273. public CallAdapter(ArgumentValues/*!*/ ai, PythonContext/*!*/ state, Expression/*!*/ codeContext) {
  274. _argInfo = ai;
  275. _state = state;
  276. _context = codeContext;
  277. }
  278. protected PythonContext PythonContext {
  279. get {
  280. return _state;
  281. }
  282. }
  283. protected Expression CodeContext {
  284. get {
  285. return _context;
  286. }
  287. }
  288. protected ArgumentValues/*!*/ Arguments {
  289. get { return _argInfo; }
  290. }
  291. }
  292. private class ArgumentValues {
  293. public readonly DynamicMetaObject/*!*/ Self;
  294. public readonly DynamicMetaObject/*!*/[]/*!*/ Arguments;
  295. public readonly CallSignature Signature;
  296. public ArgumentValues(CallSignature signature, DynamicMetaObject/*!*/ self, DynamicMetaObject/*!*/[]/*!*/ args) {
  297. Self = self;
  298. Signature = signature;
  299. Arguments = args;
  300. }
  301. }
  302. #endregion
  303. #region __new__ adapters
  304. private class NewAdapter : CallAdapter {
  305. public NewAdapter(ArgumentValues/*!*/ ai, PythonContext/*!*/ state, Expression/*!*/ codeContext)
  306. : base(ai, state, codeContext) {
  307. }
  308. public virtual DynamicMetaObject/*!*/ GetExpression(PythonBinder/*!*/ binder) {
  309. return MakeDefaultNew(
  310. binder,
  311. Ast.Call(
  312. typeof(PythonOps).GetMethod("PythonTypeGetMember"),
  313. CodeContext,
  314. AstUtils.Convert(Arguments.Self.Expression, typeof(PythonType)),
  315. AstUtils.Constant(null),
  316. AstUtils.Constant("__new__")
  317. )
  318. );
  319. }
  320. protected DynamicMetaObject/*!*/ MakeDefaultNew(DefaultBinder/*!*/ binder, Expression/*!*/ function) {
  321. // calling theType.__new__(theType, args)
  322. List<Expression> args = new List<Expression>();
  323. args.Add(CodeContext);
  324. args.Add(function);
  325. AppendNewArgs(args);
  326. return new DynamicMetaObject(
  327. Ast.Dynamic(
  328. PythonContext.Invoke(
  329. GetDynamicNewSignature()
  330. ),
  331. typeof(object),
  332. args.ToArray()
  333. ),
  334. Arguments.Self.Restrictions
  335. );
  336. }
  337. private void AppendNewArgs(List<Expression> args) {
  338. // theType
  339. args.Add(Arguments.Self.Expression);
  340. // args
  341. foreach (DynamicMetaObject mo in Arguments.Arguments) {
  342. args.Add(mo.Expression);
  343. }
  344. }
  345. protected CallSignature GetDynamicNewSignature() {
  346. return Arguments.Signature.InsertArgument(Argument.Simple);
  347. }
  348. }
  349. private class DefaultNewAdapter : NewAdapter {
  350. private readonly PythonType/*!*/ _creating;
  351. public DefaultNewAdapter(ArgumentValues/*!*/ ai, PythonType/*!*/ creating, PythonContext/*!*/ state, Expression/*!*/ codeContext)
  352. : base(ai, state, codeContext) {
  353. _creating = creating;
  354. }
  355. public override DynamicMetaObject/*!*/ GetExpression(PythonBinder/*!*/ binder) {
  356. PythonOverloadResolver resolver;
  357. if (_creating.IsSystemType || _creating.HasSystemCtor) {
  358. resolver = new PythonOverloadResolver(binder, DynamicMetaObject.EmptyMetaObjects, new CallSignature(0), CodeContext);
  359. } else {
  360. resolver = new PythonOverloadResolver(binder, new[] { Arguments.Self }, new CallSignature(1), CodeContext);
  361. }
  362. return binder.CallMethod(resolver, _creating.UnderlyingSystemType.GetConstructors(), BindingRestrictions.Empty, _creating.Name);
  363. }
  364. }
  365. private class ConstructorNewAdapter : NewAdapter {
  366. private readonly PythonType/*!*/ _creating;
  367. public ConstructorNewAdapter(ArgumentValues/*!*/ ai, PythonType/*!*/ creating, PythonContext/*!*/ state, Expression/*!*/ codeContext)
  368. : base(ai, state, codeContext) {
  369. _creating = creating;
  370. }
  371. public override DynamicMetaObject/*!*/ GetExpression(PythonBinder/*!*/ binder) {
  372. PythonOverloadResolver resolve;
  373. if (_creating.IsSystemType || _creating.HasSystemCtor) {
  374. resolve = new PythonOverloadResolver(
  375. binder,
  376. Arguments.Arguments,
  377. Arguments.Signature,
  378. CodeContext
  379. );
  380. } else {
  381. resolve = new PythonOverloadResolver(
  382. binder,
  383. ArrayUtils.Insert(Arguments.Self, Arguments.Arguments),
  384. GetDynamicNewSignature(),
  385. CodeContext
  386. );
  387. }
  388. return binder.CallMethod(
  389. resolve,
  390. _creating.UnderlyingSystemType.GetConstructors(),
  391. Arguments.Self.Restrictions,
  392. _creating.Name
  393. );
  394. }
  395. }
  396. private class BuiltinNewAdapter : NewAdapter {
  397. private readonly PythonType/*!*/ _creating;
  398. private readonly BuiltinFunction/*!*/ _ctor;
  399. public BuiltinNewAdapter(ArgumentValues/*!*/ ai, PythonType/*!*/ creating, BuiltinFunction/*!*/ ctor, PythonContext/*!*/ state, Expression/*!*/ codeContext)
  400. : base(ai, state, codeContext) {
  401. _creating = creating;
  402. _ctor = ctor;
  403. }
  404. public override DynamicMetaObject/*!*/ GetExpression(PythonBinder/*!*/ binder) {
  405. return binder.CallMethod(
  406. new PythonOverloadResolver(
  407. binder,
  408. ArrayUtils.Insert(Arguments.Self, Arguments.Arguments),
  409. Arguments.Signature.InsertArgument(new Argument(ArgumentType.Simple)),
  410. CodeContext
  411. ),
  412. _ctor.Targets,
  413. _creating.Name
  414. );
  415. }
  416. }
  417. private class MixedNewAdapter : NewAdapter {
  418. public MixedNewAdapter(ArgumentValues/*!*/ ai, PythonContext/*!*/ state, Expression/*!*/ codeContext)
  419. : base(ai, state, codeContext) {
  420. }
  421. public override DynamicMetaObject/*!*/ GetExpression(PythonBinder/*!*/ binder) {
  422. return MakeDefaultNew(
  423. binder,
  424. Ast.Call(
  425. typeof(PythonOps).GetMethod("GetMixedMember"),
  426. CodeContext,
  427. Arguments.Self.Expression,
  428. AstUtils.Constant(null),
  429. AstUtils.Constant("__new__")
  430. )
  431. );
  432. }
  433. }
  434. #endregion
  435. #region __init__ adapters
  436. private abstract class InitAdapter : CallAdapter {
  437. protected InitAdapter(ArgumentValues/*!*/ ai, PythonContext/*!*/ state, Expression/*!*/ codeContext)
  438. : base(ai, state, codeContext) {
  439. }
  440. public abstract DynamicMetaObject/*!*/ MakeInitCall(PythonBinder/*!*/ binder, DynamicMetaObject/*!*/ createExpr);
  441. protected DynamicMetaObject/*!*/ MakeDefaultInit(PythonBinder/*!*/ binder, DynamicMetaObject/*!*/ createExpr, Expression/*!*/ init) {
  442. List<Expression> args = new List<Expression>();
  443. args.Add(CodeContext);
  444. args.Add(Expression.Convert(createExpr.Expression, typeof(object)));
  445. foreach (DynamicMetaObject mo in Arguments.Arguments) {
  446. args.Add(mo.Expression);
  447. }
  448. return new DynamicMetaObject(
  449. Expression.Dynamic(
  450. ((PythonType)Arguments.Self.Value).GetLateBoundInitBinder(Arguments.Signature),
  451. typeof(object),
  452. args.ToArray()
  453. ),
  454. Arguments.Self.Restrictions.Merge(createExpr.Restrictions)
  455. );
  456. }
  457. }
  458. private class SlotInitAdapter : InitAdapter {
  459. private readonly PythonTypeSlot/*!*/ _slot;
  460. public SlotInitAdapter(PythonTypeSlot/*!*/ slot, ArgumentValues/*!*/ ai, PythonContext/*!*/ state, Expression/*!*/ codeContext)
  461. : base(ai, state, codeContext) {
  462. _slot = slot;
  463. }
  464. public override DynamicMetaObject/*!*/ MakeInitCall(PythonBinder/*!*/ binder, DynamicMetaObject/*!*/ createExpr) {
  465. Expression init = Ast.Call(
  466. typeof(PythonOps).GetMethod("GetInitSlotMember"),
  467. CodeContext,
  468. Ast.Convert(Arguments.Self.Expression, typeof(PythonType)),
  469. Ast.Convert(AstUtils.WeakConstant(_slot), typeof(PythonTypeSlot)),
  470. AstUtils.Convert(createExpr.Expression, typeof(object))
  471. );
  472. return MakeDefaultInit(binder, createExpr, init);
  473. }
  474. }
  475. private class DefaultInitAdapter : InitAdapter {
  476. public DefaultInitAdapter(ArgumentValues/*!*/ ai, PythonContext/*!*/ state, Expression/*!*/ codeContext)
  477. : base(ai, state, codeContext) {
  478. }
  479. public override DynamicMetaObject/*!*/ MakeInitCall(PythonBinder/*!*/ binder, DynamicMetaObject/*!*/ createExpr) {
  480. // default init, we can just return the value from __new__
  481. return createExpr;
  482. }
  483. }
  484. private class BuiltinInitAdapter : InitAdapter {
  485. private readonly BuiltinFunction/*!*/ _method;
  486. public BuiltinInitAdapter(ArgumentValues/*!*/ ai, BuiltinFunction/*!*/ method, PythonContext/*!*/ state, Expression/*!*/ codeContext)
  487. : base(ai, state, codeContext) {
  488. _method = method;
  489. }
  490. public override DynamicMetaObject/*!*/ MakeInitCall(PythonBinder/*!*/ binder, DynamicMetaObject/*!*/ createExpr) {
  491. if (_method == InstanceOps.Init.Template) {
  492. // we have a default __init__, don't call it.
  493. return createExpr;
  494. }
  495. return binder.CallMethod(
  496. new PythonOverloadResolver(
  497. binder,
  498. createExpr,
  499. Arguments.Arguments,
  500. Arguments.Signature,
  501. CodeContext
  502. ),
  503. _method.Targets,
  504. Arguments.Self.Restrictions
  505. );
  506. }
  507. }
  508. private class MixedInitAdapter : InitAdapter {
  509. public MixedInitAdapter(ArgumentValues/*!*/ ai, PythonContext/*!*/ state, Expression/*!*/ codeContext)
  510. : base(ai, state, codeContext) {
  511. }
  512. public override DynamicMetaObject/*!*/ MakeInitCall(PythonBinder/*!*/ binder, DynamicMetaObject/*!*/ createExpr) {
  513. Expression init = Ast.Call(
  514. typeof(PythonOps).GetMethod("GetMixedMember"),
  515. CodeContext,
  516. Ast.Convert(Arguments.Self.Expression, typeof(PythonType)),
  517. AstUtils.Convert(createExpr.Expression, typeof(object)),
  518. AstUtils.Constant("__init__")
  519. );
  520. return MakeDefaultInit(binder, createExpr, init);
  521. }
  522. }
  523. #endregion
  524. #region Helpers
  525. private DynamicMetaObject/*!*/ MakeIncorrectArgumentsForCallError(DynamicMetaObjectBinder/*!*/ call, ArgumentValues/*!*/ ai, ValidationInfo/*!*/ valInfo) {
  526. string message;
  527. if (Value.IsSystemType) {
  528. if (Value.UnderlyingSystemType.GetConstructors().Length == 0) {
  529. // this is a type we can't create ANY instances of, give the user a half-way decent error message
  530. message = "cannot create instances of " + Value.Name;
  531. } else {
  532. message = InstanceOps.ObjectNewNoParameters;
  533. }
  534. } else {
  535. message = InstanceOps.ObjectNewNoParameters;
  536. }
  537. return BindingHelpers.AddDynamicTestAndDefer(
  538. call,
  539. new DynamicMetaObject(
  540. Ast.Throw(
  541. Ast.New(
  542. typeof(ArgumentTypeException).GetConstructor(new Type[] { typeof(string) }),
  543. AstUtils.Constant(message)
  544. )
  545. ),
  546. GetErrorRestrictions(ai)
  547. ),
  548. ai.Arguments,
  549. valInfo
  550. );
  551. }
  552. private DynamicMetaObject/*!*/ MakeGenericTypeDefinitionError(DynamicMetaObjectBinder/*!*/ call, ArgumentValues/*!*/ ai, ValidationInfo/*!*/ valInfo) {
  553. Debug.Assert(Value.IsSystemType);
  554. string message = "cannot create instances of " + Value.Name + " because it is a generic type definition";
  555. return BindingHelpers.AddDynamicTestAndDefer(
  556. call,
  557. new DynamicMetaObject(
  558. Ast.Throw(
  559. Ast.New(
  560. typeof(ArgumentTypeException).GetConstructor(new Type[] { typeof(string) }),
  561. AstUtils.Constant(message)
  562. ),
  563. typeof(object)
  564. ),
  565. GetErrorRestrictions(ai)
  566. ),
  567. ai.Arguments,
  568. valInfo
  569. );
  570. }
  571. private BindingRestrictions/*!*/ GetErrorRestrictions(ArgumentValues/*!*/ ai) {
  572. BindingRestrictions res = Restrict(this.GetRuntimeType()).Restrictions;
  573. res = res.Merge(GetInstanceRestriction(ai));
  574. foreach (DynamicMetaObject mo in ai.Arguments) {
  575. if (mo.HasValue) {
  576. res = res.Merge(mo.Restrict(mo.GetRuntimeType()).Restrictions);
  577. }
  578. }
  579. return res;
  580. }
  581. private static BindingRestrictions GetInstanceRestriction(ArgumentValues ai) {
  582. return BindingRestrictions.GetInstanceRestriction(ai.Self.Expression, ai.Self.Value);
  583. }
  584. private bool HasFinalizer(DynamicMetaObjectBinder/*!*/ action) {
  585. // only user types have finalizers...
  586. if (Value.IsSystemType) return false;
  587. PythonTypeSlot del;
  588. bool hasDel = Value.TryResolveSlot(PythonContext.GetPythonContext(action).SharedContext, "__del__", out del);
  589. return hasDel;
  590. }
  591. private bool HasDefaultNew(DynamicMetaObjectBinder/*!*/ action) {
  592. PythonTypeSlot newInst;
  593. Value.TryResolveSlot(PythonContext.GetPythonContext(action).SharedContext, "__new__", out newInst);
  594. return newInst == InstanceOps.New;
  595. }
  596. private bool HasDefaultInit(DynamicMetaObjectBinder/*!*/ action) {
  597. PythonTypeSlot init;
  598. Value.TryResolveSlot(PythonContext.GetPythonContext(action).SharedContext, "__init__", out init);
  599. return init == InstanceOps.Init;
  600. }
  601. private bool HasDefaultNewAndInit(DynamicMetaObjectBinder/*!*/ action) {
  602. return HasDefaultNew(action) && HasDefaultInit(action);
  603. }
  604. /// <summary>
  605. /// Checks if we have a default new and init - in this case if we have any
  606. /// arguments we don't allow the call.
  607. /// </summary>
  608. private bool TooManyArgsForDefaultNew(DynamicMetaObjectBinder/*!*/ action, DynamicMetaObject/*!*/[]/*!*/ args) {
  609. if (args.Length > 0 && HasDefaultNewAndInit(action)) {
  610. Argument[] infos = BindingHelpers.GetCallSignature(action).GetArgumentInfos();
  611. for (int i = 0; i < infos.Length; i++) {
  612. Argument curArg = infos[i];
  613. switch(curArg.Kind) {
  614. case ArgumentType.List:
  615. // Deferral?
  616. if (((IList<object>)args[i].Value).Count > 0) {
  617. return true;
  618. }
  619. break;
  620. case ArgumentType.Dictionary:
  621. // Deferral?
  622. if (PythonOps.Length(args[i].Value) > 0) {
  623. return true;
  624. }
  625. break;
  626. default:
  627. return true;
  628. }
  629. }
  630. }
  631. return false;
  632. }
  633. /// <summary>
  634. /// Creates a test which tests the specific version of the type.
  635. /// </summary>
  636. private ValidationInfo/*!*/ MakeVersionCheck() {
  637. int version = Value.Version;
  638. return new ValidationInfo(
  639. Ast.Equal(
  640. Ast.Call(
  641. typeof(PythonOps).GetMethod("GetTypeVersion"),
  642. Ast.Convert(Expression, typeof(PythonType))
  643. ),
  644. AstUtils.Constant(version)
  645. )
  646. );
  647. }
  648. private bool IsStandardDotNetType(DynamicMetaObjectBinder/*!*/ action) {
  649. PythonContext bState = PythonContext.GetPythonContext(action);
  650. return
  651. Value.IsSystemType &&
  652. !Value.IsPythonType &&
  653. !bState.Binder.HasExtensionTypes(Value.UnderlyingSystemType) &&
  654. !typeof(Delegate).IsAssignableFrom(Value.UnderlyingSystemType) &&
  655. !Value.UnderlyingSystemType.IsArray;
  656. }
  657. #endregion
  658. }
  659. }