ExpressionInterpreter.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. //
  2. // ExpressionInterpreter.cs
  3. //
  4. // (C) 2008 Mainsoft, Inc. (http://www.mainsoft.com)
  5. // (C) 2008 db4objects, Inc. (http://www.db4o.com)
  6. //
  7. // Permission is hereby granted, free of charge, to any person obtaining
  8. // a copy of this software and associated documentation files (the
  9. // "Software"), to deal in the Software without restriction, including
  10. // without limitation the rights to use, copy, modify, merge, publish,
  11. // distribute, sublicense, and/or sell copies of the Software, and to
  12. // permit persons to whom the Software is furnished to do so, subject to
  13. // the following conditions:
  14. //
  15. // The above copyright notice and this permission notice shall be
  16. // included in all copies or substantial portions of the Software.
  17. //
  18. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  21. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  22. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  23. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  24. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25. //
  26. using System;
  27. using System.Collections;
  28. using System.Collections.Generic;
  29. using System.Collections.ObjectModel;
  30. using System.Linq.Expressions;
  31. using System.Reflection;
  32. namespace System.Linq.jvm {
  33. class ExpressionInterpreter : ExpressionVisitor {
  34. LambdaExpression lambda;
  35. object [] arguments;
  36. Stack<object> stack = new Stack<object> ();
  37. void Push (object value)
  38. {
  39. stack.Push (value);
  40. }
  41. object Pop ()
  42. {
  43. return stack.Pop ();
  44. }
  45. public ExpressionInterpreter (LambdaExpression lambda, object [] arguments)
  46. {
  47. this.lambda = lambda;
  48. this.arguments = arguments;
  49. }
  50. private void VisitCoalesce (BinaryExpression binary)
  51. {
  52. Visit (binary.Left);
  53. var left = Pop ();
  54. if (left == null) {
  55. Visit (binary.Right);
  56. return;
  57. }
  58. if (binary.Conversion == null) {
  59. Push (left);
  60. return;
  61. }
  62. Push (Invoke (binary.Conversion.Compile (), new [] { left }));
  63. }
  64. void VisitAndAlso (BinaryExpression binary)
  65. {
  66. object left = null;
  67. object right = null;
  68. Visit (binary.Left);
  69. left = Pop ();
  70. if (left == null || ((bool) left)) {
  71. Visit (binary.Right);
  72. right = Pop ();
  73. }
  74. Push (Math.And (left, right));
  75. }
  76. void VisitUserDefinedAndAlso (BinaryExpression binary)
  77. {
  78. object left = null;
  79. object right = null;
  80. Visit (binary.Left);
  81. left = Pop ();
  82. if (InvokeFalseOperator (binary, left)) {
  83. Push (left);
  84. return;
  85. }
  86. Visit (binary.Right);
  87. right = Pop ();
  88. if (binary.IsLiftedToNull && right == null) {
  89. Push (null);
  90. return;
  91. }
  92. Push (InvokeMethod (binary.Method, null, new [] { left, right }));
  93. }
  94. static bool InvokeTrueOperator (BinaryExpression binary, object target)
  95. {
  96. return (bool) InvokeMethod (GetTrueOperator (binary), null, new [] { target });
  97. }
  98. static bool InvokeFalseOperator (BinaryExpression binary, object target)
  99. {
  100. return (bool) InvokeMethod (GetFalseOperator (binary), null, new [] { target });
  101. }
  102. static MethodInfo GetFalseOperator (BinaryExpression binary)
  103. {
  104. return Expression.GetFalseOperator (binary.Left.Type.GetNotNullableType ());
  105. }
  106. static MethodInfo GetTrueOperator (BinaryExpression binary)
  107. {
  108. return Expression.GetTrueOperator (binary.Left.Type.GetNotNullableType ());
  109. }
  110. void VisitOrElse (BinaryExpression binary)
  111. {
  112. object left = null;
  113. object right = null;
  114. Visit (binary.Left);
  115. left = Pop ();
  116. if (left == null || !((bool) left)) {
  117. Visit (binary.Right);
  118. right = Pop ();
  119. }
  120. Push (Math.Or (left, right));
  121. }
  122. void VisitUserDefinedOrElse (BinaryExpression binary)
  123. {
  124. object left = null;
  125. object right = null;
  126. Visit (binary.Left);
  127. left = Pop ();
  128. if (InvokeTrueOperator (binary, left)) {
  129. Push (left);
  130. return;
  131. }
  132. Visit (binary.Right);
  133. right = Pop ();
  134. if (binary.IsLiftedToNull && right == null) {
  135. Push (null);
  136. return;
  137. }
  138. Push (InvokeMethod (binary.Method, null, new [] { left, right }));
  139. }
  140. void VisitLogicalBinary (BinaryExpression binary)
  141. {
  142. Visit (binary.Left);
  143. Visit (binary.Right);
  144. var right = Pop ();
  145. var left = Pop ();
  146. Push (Math.Evaluate (left, right, binary.Type, binary.NodeType));
  147. }
  148. void VisitArithmeticBinary (BinaryExpression binary)
  149. {
  150. Visit (binary.Left);
  151. Visit (binary.Right);
  152. if (IsNullBinaryLifting (binary))
  153. return;
  154. var right = Pop ();
  155. var left = Pop ();
  156. switch (binary.NodeType) {
  157. case ExpressionType.RightShift:
  158. Push (Math.RightShift (left, Convert.ToInt32 (right), Type.GetTypeCode (binary.Type.GetNotNullableType ())));
  159. return;
  160. case ExpressionType.LeftShift:
  161. Push (Math.LeftShift (left, Convert.ToInt32 (right), Type.GetTypeCode (binary.Type.GetNotNullableType ())));
  162. return;
  163. default:
  164. Push (Math.Evaluate (left, right, binary.Type, binary.NodeType));
  165. break;
  166. }
  167. }
  168. bool IsNullRelationalBinaryLifting (BinaryExpression binary)
  169. {
  170. var right = Pop ();
  171. var left = Pop ();
  172. if (binary.IsLifted && (left == null || right == null)) {
  173. if (binary.IsLiftedToNull) {
  174. Push (null);
  175. return true;
  176. }
  177. switch (binary.NodeType) {
  178. case ExpressionType.Equal:
  179. Push (BinaryEqual (binary, left, right));
  180. break;
  181. case ExpressionType.NotEqual:
  182. Push (BinaryNotEqual (binary, left, right));
  183. break;
  184. default:
  185. Push (false);
  186. break;
  187. }
  188. return true;
  189. }
  190. Push (left);
  191. Push (right);
  192. return false;
  193. }
  194. void VisitRelationalBinary (BinaryExpression binary)
  195. {
  196. Visit (binary.Left);
  197. Visit (binary.Right);
  198. if (IsNullRelationalBinaryLifting (binary))
  199. return;
  200. var right = Pop ();
  201. var left = Pop ();
  202. switch (binary.NodeType) {
  203. case ExpressionType.Equal:
  204. Push (BinaryEqual (binary, left, right));
  205. return;
  206. case ExpressionType.NotEqual:
  207. Push (BinaryNotEqual (binary, left, right));
  208. return;
  209. case ExpressionType.LessThan:
  210. Push (Comparer.Default.Compare (left, right) < 0);
  211. return;
  212. case ExpressionType.LessThanOrEqual:
  213. Push (Comparer.Default.Compare (left, right) <= 0);
  214. return;
  215. case ExpressionType.GreaterThan:
  216. Push (Comparer.Default.Compare (left, right) > 0);
  217. return;
  218. case ExpressionType.GreaterThanOrEqual:
  219. Push (Comparer.Default.Compare (left, right) >= 0);
  220. return;
  221. }
  222. }
  223. void VisitLogicalShortCircuitBinary (BinaryExpression binary)
  224. {
  225. switch (binary.NodeType) {
  226. case ExpressionType.AndAlso:
  227. VisitAndAlso (binary);
  228. return;
  229. case ExpressionType.OrElse:
  230. VisitOrElse (binary);
  231. return;
  232. }
  233. }
  234. void VisitArrayIndex (BinaryExpression binary)
  235. {
  236. Visit (binary.Left);
  237. var left = Pop ();
  238. Visit (binary.Right);
  239. var right = Pop ();
  240. Push (((Array) left).GetValue ((int) right));
  241. }
  242. bool IsNullBinaryLifting (BinaryExpression binary)
  243. {
  244. var right = Pop ();
  245. var left = Pop ();
  246. if (binary.IsLifted && (right == null || left == null)) {
  247. if (binary.IsLiftedToNull)
  248. Push (null);
  249. else
  250. Push (GetDefaultValue (binary.Type));
  251. return true;
  252. }
  253. Push (left);
  254. Push (right);
  255. return false;
  256. }
  257. static object GetDefaultValue (Type type)
  258. {
  259. var array = (Array) Array.CreateInstance (type, 1);
  260. return array.GetValue (0);
  261. }
  262. void VisitUserDefinedBinary (BinaryExpression binary)
  263. {
  264. switch (binary.NodeType) {
  265. case ExpressionType.AndAlso:
  266. case ExpressionType.OrElse:
  267. VisitUserDefinedLogicalShortCircuitBinary (binary);
  268. return;
  269. case ExpressionType.Equal:
  270. case ExpressionType.NotEqual:
  271. VisitUserDefinedRelationalBinary (binary);
  272. return;
  273. default:
  274. VisitUserDefinedCommonBinary (binary);
  275. return;
  276. }
  277. }
  278. void VisitUserDefinedLogicalShortCircuitBinary (BinaryExpression binary)
  279. {
  280. switch (binary.NodeType) {
  281. case ExpressionType.AndAlso:
  282. VisitUserDefinedAndAlso (binary);
  283. return;
  284. case ExpressionType.OrElse:
  285. VisitUserDefinedOrElse (binary);
  286. return;
  287. }
  288. }
  289. void VisitUserDefinedRelationalBinary (BinaryExpression binary)
  290. {
  291. Visit (binary.Left);
  292. Visit (binary.Right);
  293. if (IsNullRelationalBinaryLifting (binary))
  294. return;
  295. var right = Pop ();
  296. var left = Pop ();
  297. Push (InvokeBinary (binary, left, right));
  298. }
  299. void VisitUserDefinedCommonBinary (BinaryExpression binary)
  300. {
  301. Visit (binary.Left);
  302. Visit (binary.Right);
  303. if (IsNullBinaryLifting (binary))
  304. return;
  305. var right = Pop ();
  306. var left = Pop ();
  307. Push (InvokeBinary (binary, left, right));
  308. }
  309. object InvokeBinary (BinaryExpression binary, object left, object right)
  310. {
  311. return InvokeMethod (binary.Method, null, new [] { left, right });
  312. }
  313. bool BinaryEqual (BinaryExpression binary, object left, object right)
  314. {
  315. if (typeof (ValueType).IsAssignableFrom (binary.Right.Type))
  316. return ValueType.Equals (left, right);
  317. else
  318. return left == right;
  319. }
  320. bool BinaryNotEqual (BinaryExpression binary, object left, object right)
  321. {
  322. if (typeof (ValueType).IsAssignableFrom (binary.Right.Type))
  323. return !ValueType.Equals (left, right);
  324. else
  325. return left != right;
  326. }
  327. protected override void VisitBinary (BinaryExpression binary)
  328. {
  329. if (binary.Method != null) {
  330. VisitUserDefinedBinary (binary);
  331. return;
  332. }
  333. switch (binary.NodeType) {
  334. case ExpressionType.ArrayIndex:
  335. VisitArrayIndex (binary);
  336. return;
  337. case ExpressionType.Coalesce:
  338. VisitCoalesce (binary);
  339. return;
  340. case ExpressionType.AndAlso:
  341. case ExpressionType.OrElse:
  342. VisitLogicalShortCircuitBinary (binary);
  343. return;
  344. case ExpressionType.Equal:
  345. case ExpressionType.NotEqual:
  346. case ExpressionType.GreaterThan:
  347. case ExpressionType.GreaterThanOrEqual:
  348. case ExpressionType.LessThan:
  349. case ExpressionType.LessThanOrEqual:
  350. VisitRelationalBinary (binary);
  351. return;
  352. case ExpressionType.And:
  353. case ExpressionType.Or:
  354. VisitLogicalBinary (binary);
  355. return;
  356. case ExpressionType.Power:
  357. case ExpressionType.Add:
  358. case ExpressionType.AddChecked:
  359. case ExpressionType.Divide:
  360. case ExpressionType.ExclusiveOr:
  361. case ExpressionType.LeftShift:
  362. case ExpressionType.Modulo:
  363. case ExpressionType.Multiply:
  364. case ExpressionType.MultiplyChecked:
  365. case ExpressionType.RightShift:
  366. case ExpressionType.Subtract:
  367. case ExpressionType.SubtractChecked:
  368. VisitArithmeticBinary (binary);
  369. return;
  370. }
  371. }
  372. void VisitTypeAs (UnaryExpression unary)
  373. {
  374. Visit (unary.Operand);
  375. var value = Pop ();
  376. if (value == null || !Math.IsType (unary.Type, value))
  377. Push (null);
  378. else
  379. Push (value);
  380. }
  381. void VisitArrayLength (UnaryExpression unary)
  382. {
  383. Visit (unary.Operand);
  384. var array = (Array) Pop ();
  385. Push (array.Length);
  386. }
  387. void VisitConvert (UnaryExpression unary)
  388. {
  389. if (unary.NodeType == ExpressionType.ConvertChecked)
  390. VisitConvertChecked (unary);
  391. else
  392. VisitConvertUnchecked (unary);
  393. }
  394. void VisitConvertChecked (UnaryExpression unary)
  395. {
  396. VisitConvert (unary, Math.ConvertToTypeChecked);
  397. }
  398. void VisitConvertUnchecked (UnaryExpression unary)
  399. {
  400. VisitConvert (unary, Math.ConvertToTypeUnchecked);
  401. }
  402. void VisitConvert (UnaryExpression unary, Func<object, Type, Type, object> converter)
  403. {
  404. Visit (unary.Operand);
  405. Push (converter (Pop (), unary.Operand.Type, unary.Type));
  406. }
  407. bool IsNullUnaryLifting (UnaryExpression unary)
  408. {
  409. var value = Pop ();
  410. if (unary.IsLifted && value == null) {
  411. if (unary.IsLiftedToNull) {
  412. Push (null);
  413. return true;
  414. } else {
  415. throw new InvalidOperationException ();
  416. }
  417. }
  418. Push (value);
  419. return false;
  420. }
  421. void VisitQuote (UnaryExpression unary)
  422. {
  423. Push (unary.Operand);
  424. }
  425. void VisitUserDefinedUnary (UnaryExpression unary)
  426. {
  427. Visit (unary.Operand);
  428. if (IsNullUnaryLifting (unary))
  429. return;
  430. var value = Pop ();
  431. Push (InvokeUnary (unary, value));
  432. }
  433. object InvokeUnary (UnaryExpression unary, object value)
  434. {
  435. return InvokeMethod (unary.Method, null, new [] { value });
  436. }
  437. void VisitArithmeticUnary (UnaryExpression unary)
  438. {
  439. Visit (unary.Operand);
  440. if (IsNullUnaryLifting (unary))
  441. return;
  442. var value = Pop ();
  443. switch (unary.NodeType) {
  444. case ExpressionType.Not:
  445. if (unary.Type.GetNotNullableType () == typeof (bool))
  446. Push (!Convert.ToBoolean (value));
  447. else
  448. Push (~Convert.ToInt32 (value));
  449. return;
  450. case ExpressionType.Negate:
  451. Push (Math.Negate (value, Type.GetTypeCode (unary.Type.GetNotNullableType ())));
  452. return;
  453. case ExpressionType.NegateChecked:
  454. Push (Math.NegateChecked (value, Type.GetTypeCode (unary.Type.GetNotNullableType ())));
  455. return;
  456. case ExpressionType.UnaryPlus:
  457. Push (value);
  458. return;
  459. }
  460. }
  461. protected override void VisitUnary (UnaryExpression unary)
  462. {
  463. if (unary.Method != null) {
  464. VisitUserDefinedUnary (unary);
  465. return;
  466. }
  467. switch (unary.NodeType) {
  468. case ExpressionType.Quote:
  469. VisitQuote (unary);
  470. return;
  471. case ExpressionType.TypeAs:
  472. VisitTypeAs (unary);
  473. return;
  474. case ExpressionType.ArrayLength:
  475. VisitArrayLength (unary);
  476. return;
  477. case ExpressionType.Convert:
  478. case ExpressionType.ConvertChecked:
  479. VisitConvert (unary);
  480. return;
  481. case ExpressionType.Negate:
  482. case ExpressionType.NegateChecked:
  483. case ExpressionType.Not:
  484. case ExpressionType.UnaryPlus:
  485. VisitArithmeticUnary (unary);
  486. return;
  487. default:
  488. throw new NotImplementedException (unary.NodeType.ToString ());
  489. }
  490. }
  491. protected override void VisitNew (NewExpression nex)
  492. {
  493. if (nex.Constructor == null)
  494. Push (Activator.CreateInstance (nex.Type));
  495. else
  496. Push (InvokeConstructor (nex.Constructor, VisitListExpressions (nex.Arguments)));
  497. }
  498. static object InvokeConstructor (ConstructorInfo constructor, object [] arguments)
  499. {
  500. try {
  501. return constructor.Invoke (arguments);
  502. } catch (TargetInvocationException e) {
  503. throw e.InnerException;
  504. }
  505. }
  506. protected override void VisitTypeIs (TypeBinaryExpression type)
  507. {
  508. Visit (type.Expression);
  509. Push (Math.IsType (type.TypeOperand, Pop ()));
  510. }
  511. void VisitMemberInfo (MemberInfo mi)
  512. {
  513. mi.OnFieldOrProperty (
  514. field => {
  515. object target = null;
  516. if (!field.IsStatic)
  517. target = Pop ();
  518. Push (field.GetValue (target));
  519. },
  520. property => {
  521. object target = null;
  522. var getter = property.GetGetMethod (true);
  523. if (!getter.IsStatic)
  524. target = Pop ();
  525. Push (property.GetValue (target, null));
  526. });
  527. }
  528. protected override void VisitMemberAccess (MemberExpression member)
  529. {
  530. Visit (member.Expression);
  531. VisitMemberInfo (member.Member);
  532. }
  533. protected override void VisitNewArray (NewArrayExpression newArray)
  534. {
  535. switch (newArray.NodeType) {
  536. case ExpressionType.NewArrayInit:
  537. VisitNewArrayInit (newArray);
  538. return;
  539. case ExpressionType.NewArrayBounds:
  540. VisitNewArrayBounds (newArray);
  541. return;
  542. }
  543. throw new NotSupportedException ();
  544. }
  545. void VisitNewArrayBounds (NewArrayExpression newArray)
  546. {
  547. var lengths = new int [newArray.Expressions.Count];
  548. for (int i = 0; i < lengths.Length; i++) {
  549. Visit (newArray.Expressions [i]);
  550. lengths [i] = (int) Pop ();
  551. }
  552. Push (Array.CreateInstance (newArray.Type.GetElementType (), lengths));
  553. }
  554. void VisitNewArrayInit (NewArrayExpression newArray)
  555. {
  556. var array = Array.CreateInstance (
  557. newArray.Type.GetElementType (),
  558. newArray.Expressions.Count);
  559. for (int i = 0; i < array.Length; i++) {
  560. Visit (newArray.Expressions [i]);
  561. array.SetValue (Pop (), i);
  562. }
  563. Push (array);
  564. }
  565. protected override void VisitConditional (ConditionalExpression conditional)
  566. {
  567. Visit (conditional.Test);
  568. if ((bool) Pop ())
  569. Visit (conditional.IfTrue);
  570. else
  571. Visit (conditional.IfFalse);
  572. }
  573. protected override void VisitMethodCall (MethodCallExpression call)
  574. {
  575. object instance = null;
  576. if (call.Object != null) {
  577. Visit (call.Object);
  578. instance = Pop ();
  579. }
  580. Push (InvokeMethod (call.Method, instance, VisitListExpressions (call.Arguments)));
  581. }
  582. protected override void VisitParameter (ParameterExpression parameter)
  583. {
  584. for (int i = 0; i < lambda.Parameters.Count; i++) {
  585. if (lambda.Parameters [i] != parameter)
  586. continue;
  587. Push (arguments [i]);
  588. return;
  589. }
  590. throw new ArgumentException ();
  591. }
  592. protected override void VisitConstant (ConstantExpression constant)
  593. {
  594. Push (constant.Value);
  595. }
  596. protected override void VisitInvocation (InvocationExpression invocation)
  597. {
  598. Visit (invocation.Expression);
  599. Push (Invoke ((Delegate) Pop (), VisitListExpressions (invocation.Arguments)));
  600. }
  601. static object Invoke (Delegate dlg, object [] arguments)
  602. {
  603. return InvokeMethod (dlg.Method, dlg.Target, arguments);
  604. }
  605. static object InvokeMethod (MethodBase method, object obj, object [] arguments)
  606. {
  607. try {
  608. return method.Invoke (obj, arguments);
  609. } catch (TargetInvocationException e) {
  610. throw e.InnerException;
  611. }
  612. }
  613. protected override void VisitMemberListBinding (MemberListBinding binding)
  614. {
  615. var value = Pop ();
  616. Push (value);
  617. VisitMemberInfo (binding.Member);
  618. VisitElementInitializerList (binding.Initializers);
  619. Pop (); // pop the member
  620. Push (value); // push the original target
  621. }
  622. protected override void VisitElementInitializer (ElementInit initializer)
  623. {
  624. object target = null;
  625. if (!initializer.AddMethod.IsStatic)
  626. target = Pop ();
  627. var arguments = VisitListExpressions (initializer.Arguments);
  628. InvokeMethod (initializer.AddMethod, target, arguments);
  629. if (!initializer.AddMethod.IsStatic)
  630. Push (target);
  631. }
  632. protected override void VisitMemberMemberBinding (MemberMemberBinding binding)
  633. {
  634. var value = Pop ();
  635. Push (value);
  636. VisitMemberInfo (binding.Member);
  637. VisitBindingList (binding.Bindings);
  638. Pop ();
  639. Push (value);
  640. }
  641. protected override void VisitMemberAssignment (MemberAssignment assignment)
  642. {
  643. Visit (assignment.Expression);
  644. var value = Pop ();
  645. assignment.Member.OnFieldOrProperty (
  646. field => {
  647. object target = null;
  648. if (!field.IsStatic)
  649. target = Pop ();
  650. field.SetValue (target, value);
  651. if (!field.IsStatic)
  652. Push (target);
  653. },
  654. property => {
  655. object target = null;
  656. var getter = property.GetGetMethod (true);
  657. if (!getter.IsStatic)
  658. target = Pop ();
  659. property.SetValue (target, value, null);
  660. if (!getter.IsStatic)
  661. Push (target);
  662. });
  663. }
  664. protected override void VisitLambda (LambdaExpression lambda)
  665. {
  666. Push (lambda.Compile ());
  667. }
  668. private object [] VisitListExpressions (ReadOnlyCollection<Expression> collection)
  669. {
  670. object [] results = new object [collection.Count];
  671. for (int i = 0; i < results.Length; i++) {
  672. Visit (collection [i]);
  673. results [i] = Pop ();
  674. }
  675. return results;
  676. }
  677. public static object Interpret (LambdaExpression lambda, object [] arguments)
  678. {
  679. var interpreter = new ExpressionInterpreter (lambda, arguments);
  680. interpreter.Visit (lambda.Body);
  681. if (lambda.GetReturnType () != typeof (void))
  682. return interpreter.Pop ();
  683. return null;
  684. }
  685. }
  686. }