Expression.cs 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481
  1. //
  2. // Expression.cs
  3. //
  4. // Author:
  5. // Jb Evain ([email protected])
  6. // Miguel de Icaza ([email protected])
  7. //
  8. // (C) 2008 Novell, Inc. (http://www.novell.com)
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining
  11. // a copy of this software and associated documentation files (the
  12. // "Software"), to deal in the Software without restriction, including
  13. // without limitation the rights to use, copy, modify, merge, publish,
  14. // distribute, sublicense, and/or sell copies of the Software, and to
  15. // permit persons to whom the Software is furnished to do so, subject to
  16. // the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be
  19. // included in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. using System;
  30. using System.Collections.Generic;
  31. using System.Collections.ObjectModel;
  32. using System.Linq;
  33. using System.Reflection;
  34. namespace System.Linq.Expressions {
  35. public abstract class Expression {
  36. ExpressionType node_type;
  37. Type type;
  38. static BindingFlags PublicInstance = BindingFlags.Public | BindingFlags.Instance;
  39. static BindingFlags PublicStatic = BindingFlags.Public | BindingFlags.Static;
  40. public ExpressionType NodeType {
  41. get { return node_type; }
  42. }
  43. public Type Type {
  44. get { return type; }
  45. }
  46. // TODO: remove when all Expression subtypes
  47. // have their constructor implemented
  48. protected Expression ()
  49. {
  50. }
  51. protected Expression (ExpressionType node_type, Type type)
  52. {
  53. this.node_type = node_type;
  54. this.type = type;
  55. }
  56. public override string ToString ()
  57. {
  58. return ExpressionPrinter.ToString (this);
  59. }
  60. static void CheckMethod (MethodInfo m)
  61. {
  62. }
  63. #region Binary Expressions
  64. static bool IsInt (Type t)
  65. {
  66. return t == typeof (byte) || t == typeof (sbyte) ||
  67. t == typeof (short) || t == typeof (ushort) ||
  68. t == typeof (int) || t == typeof (uint) ||
  69. t == typeof (long) || t == typeof (ulong);
  70. }
  71. static bool IsNumber (Type t)
  72. {
  73. if (IsInt (t))
  74. return true;
  75. return t == typeof (float) || t == typeof (double) || t == typeof (decimal);
  76. }
  77. static MethodInfo GetUnaryOperator (string oper_name, Type on_type, Expression expression)
  78. {
  79. var methods = on_type.GetMethods (PublicStatic);
  80. foreach (var method in methods) {
  81. if (method.Name != oper_name)
  82. continue;
  83. var parameters = method.GetParameters ();
  84. if (parameters.Length != 1)
  85. continue;
  86. if (!parameters [0].ParameterType.IsAssignableFrom (expression.Type))
  87. continue;
  88. return method;
  89. }
  90. return null;
  91. }
  92. static MethodInfo UnaryCoreCheck (string oper_name, Expression expression, MethodInfo method)
  93. {
  94. if (expression == null)
  95. throw new ArgumentNullException ("expression");
  96. if (method != null) {
  97. if (method.ReturnType == typeof (void))
  98. throw new ArgumentException ("Specified method must return a value", "method");
  99. if (!method.IsStatic)
  100. throw new ArgumentException ("Method must be static", "method");
  101. var parameters = method.GetParameters ();
  102. if (parameters.Length != 1)
  103. throw new ArgumentException ("Must have only one parameters", "method");
  104. if (!parameters [0].ParameterType.IsAssignableFrom (expression.Type))
  105. throw new InvalidOperationException ("left-side argument type does not match left expression type");
  106. return method;
  107. } else {
  108. if (IsNumber (expression.Type))
  109. return null;
  110. if (oper_name != null) {
  111. method = GetUnaryOperator (oper_name, expression.Type, expression);
  112. if (method != null)
  113. return method;
  114. }
  115. throw new InvalidOperationException (
  116. String.Format ("Operation {0} not defined for {1}", oper_name != null ? oper_name.Substring (3) : "is", expression.Type));
  117. }
  118. }
  119. static MethodInfo GetBinaryOperator (string oper_name, Type on_type, Expression left, Expression right)
  120. {
  121. MethodInfo [] methods = on_type.GetMethods (PublicStatic);
  122. foreach (MethodInfo m in methods){
  123. if (m.Name != oper_name)
  124. continue;
  125. ParameterInfo [] pi = m.GetParameters ();
  126. if (pi.Length != 2)
  127. continue;
  128. if (!pi [0].ParameterType.IsAssignableFrom (left.Type))
  129. continue;
  130. if (!pi [1].ParameterType.IsAssignableFrom (right.Type))
  131. continue;
  132. // Method has papers in order.
  133. return m;
  134. }
  135. return null;
  136. }
  137. //
  138. // Performs basic checks on the incoming expressions for binary expressions
  139. // and any provided MethodInfo.
  140. //
  141. static MethodInfo BinaryCoreCheck (string oper_name, Expression left, Expression right, MethodInfo method)
  142. {
  143. if (left == null)
  144. throw new ArgumentNullException ("left");
  145. if (right == null)
  146. throw new ArgumentNullException ("right");
  147. if (method != null){
  148. if (method.ReturnType == typeof (void))
  149. throw new ArgumentException ("Specified method must return a value", "method");
  150. if (!method.IsStatic)
  151. throw new ArgumentException ("Method must be static", "method");
  152. ParameterInfo [] pi = method.GetParameters ();
  153. if (pi.Length != 2)
  154. throw new ArgumentException ("Must have only two parameters", "method");
  155. Type ltype = left.Type.IsValueType && IsNullable (left.Type) ? GetNullableOf(left.Type) : left.Type;
  156. Type rtype = left.Type.IsValueType && IsNullable (right.Type) ? GetNullableOf(right.Type) :right.Type;
  157. if (ltype != pi [0].ParameterType)
  158. throw new InvalidOperationException ("left-side argument type does not match left expression type");
  159. if (rtype != pi [1].ParameterType)
  160. throw new InvalidOperationException ("right-side argument type does not match right expression type");
  161. return method;
  162. } else {
  163. Type ltype = left.Type;
  164. Type rtype = right.Type;
  165. Type ultype = left.Type;
  166. Type urtype = right.Type;
  167. if (IsNullable (ltype))
  168. ultype = GetNullableOf (ltype);
  169. if (IsNullable (rtype))
  170. urtype = GetNullableOf (rtype);
  171. if (oper_name == "op_BitwiseOr" || oper_name == "op_BitwiseAnd"){
  172. if (ultype == typeof (bool)){
  173. if (ultype == urtype && ltype == rtype)
  174. return null;
  175. }
  176. }
  177. // Use IsNumber to avoid expensive reflection.
  178. if (IsNumber (ultype)){
  179. if (ultype == urtype && ltype == rtype)
  180. return method;
  181. if (oper_name != null){
  182. method = GetBinaryOperator (oper_name, rtype, left, right);
  183. if (method != null)
  184. return method;
  185. }
  186. }
  187. if (oper_name != null){
  188. method = GetBinaryOperator (oper_name, ltype, left, right);
  189. if (method != null)
  190. return method;
  191. }
  192. //
  193. // == and != allow reference types without operators defined.
  194. //
  195. if (!ltype.IsValueType && !rtype.IsValueType &&
  196. (oper_name == "op_Equality" || oper_name == "op_Inequality"))
  197. return null;
  198. throw new InvalidOperationException (
  199. String.Format ("Operation {0} not defined for {1} and {2}", oper_name != null ? oper_name.Substring (3) : "is", ltype, rtype));
  200. }
  201. }
  202. //
  203. // This is like BinaryCoreCheck, but if no method is used adds the restriction that
  204. // only ints and bools are allowed
  205. //
  206. static MethodInfo BinaryBitwiseCoreCheck (string oper_name, Expression left, Expression right, MethodInfo method)
  207. {
  208. if (left == null)
  209. throw new ArgumentNullException ("left");
  210. if (right == null)
  211. throw new ArgumentNullException ("right");
  212. if (method == null){
  213. // avoid reflection shortcut and catches Ints/bools before we check Numbers in general
  214. if (left.Type == right.Type && (left.Type == typeof (bool) || IsInt (left.Type)))
  215. return method;
  216. }
  217. method = BinaryCoreCheck (oper_name, left, right, method);
  218. if (method == null){
  219. //
  220. // The check in BinaryCoreCheck allows a bit more than we do
  221. // (floats and doubles). Catch this here
  222. //
  223. if (left.Type == typeof(double) || left.Type == typeof(float))
  224. throw new InvalidOperationException ("Types not supported");
  225. }
  226. return method;
  227. }
  228. static BinaryExpression MakeSimpleBinary (ExpressionType et, Expression left, Expression right, MethodInfo method)
  229. {
  230. Type result = method == null ? left.Type : method.ReturnType;
  231. bool is_lifted;
  232. if (method == null){
  233. if (IsNullable (left.Type)){
  234. if (!IsNullable (right.Type))
  235. throw new Exception ("Assertion, internal error: left is nullable, requires right to be as well");
  236. is_lifted = true;
  237. } else
  238. is_lifted = false;
  239. } else {
  240. //
  241. // FIXME: implement
  242. //
  243. is_lifted = false;
  244. }
  245. return new BinaryExpression (et, result, left, right, false, is_lifted, method, null);
  246. }
  247. static UnaryExpression MakeSimpleUnary (ExpressionType et, Expression expression, MethodInfo method)
  248. {
  249. Type result = method == null ? expression.Type : method.ReturnType;
  250. return new UnaryExpression (et, expression, result, method);
  251. }
  252. static BinaryExpression MakeBoolBinary (ExpressionType et, Expression left, Expression right, bool liftToNull, MethodInfo method)
  253. {
  254. Type result;
  255. Type ltype = left.Type;
  256. Type rtype = right.Type;
  257. bool lnullable = IsNullable (ltype);
  258. bool rnullable = IsNullable (rtype);
  259. bool is_lifted;
  260. //
  261. // Implement the rules as described in "Expression.Equal" method.
  262. //
  263. if (method == null){
  264. if (lnullable == false && rnullable == false){
  265. is_lifted = false;
  266. result = typeof (bool);
  267. } else if (lnullable && rnullable){
  268. is_lifted = true;
  269. result = liftToNull ? typeof(bool?) : typeof (bool);
  270. } else
  271. throw new Exception ("Internal error: this should have been caught in BinaryCoreCheck");
  272. } else {
  273. ParameterInfo [] pi = method.GetParameters ();
  274. Type mltype = pi [0].ParameterType;
  275. Type mrtype = pi [1].ParameterType;
  276. if (ltype == mltype && rtype == mrtype){
  277. is_lifted = false;
  278. result = method.ReturnType;
  279. }
  280. else if (ltype.IsValueType && rtype.IsValueType &&
  281. ((lnullable && GetNullableOf (ltype) == mltype) ||
  282. (rnullable && GetNullableOf (rtype) == mrtype))){
  283. is_lifted = true;
  284. if (method.ReturnType == typeof(bool)){
  285. result = liftToNull ? typeof(bool?) : typeof(bool);
  286. } else {
  287. //
  288. // This behavior is not documented: what
  289. // happens if the result is not typeof(bool), but
  290. // the parameters are nullable: the result
  291. // becomes nullable<returntype>
  292. //
  293. // See:
  294. // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=323139
  295. result = typeof (Nullable<>).MakeGenericType (method.ReturnType);
  296. //Type.GetType ("System.Nullable`1[" + method.ReturnType.ToString () + "]");
  297. }
  298. } else {
  299. is_lifted = false;
  300. result = method.ReturnType;
  301. }
  302. }
  303. return new BinaryExpression (et, result, left, right, liftToNull, is_lifted, method, null);
  304. }
  305. //
  306. // Arithmetic
  307. //
  308. public static BinaryExpression Add (Expression left, Expression right)
  309. {
  310. return Add (left, right, null);
  311. }
  312. public static BinaryExpression Add (Expression left, Expression right, MethodInfo method)
  313. {
  314. method = BinaryCoreCheck ("op_Addition", left, right, method);
  315. return MakeSimpleBinary (ExpressionType.Add, left, right, method);
  316. }
  317. public static BinaryExpression AddChecked (Expression left, Expression right)
  318. {
  319. return AddChecked (left, right, null);
  320. }
  321. public static BinaryExpression AddChecked (Expression left, Expression right, MethodInfo method)
  322. {
  323. method = BinaryCoreCheck ("op_Addition", left, right, method);
  324. //
  325. // The check in BinaryCoreCheck allows a bit more than we do
  326. // (byte, sbyte). Catch that here
  327. //
  328. if (method == null){
  329. Type ltype = left.Type;
  330. if (ltype == typeof (byte) || ltype == typeof (sbyte))
  331. throw new InvalidOperationException (String.Format ("SubtractChecked not defined for {0} and {1}", left.Type, right.Type));
  332. }
  333. return MakeSimpleBinary (ExpressionType.AddChecked, left, right, method);
  334. }
  335. public static BinaryExpression Subtract (Expression left, Expression right)
  336. {
  337. return Subtract (left, right, null);
  338. }
  339. public static BinaryExpression Subtract (Expression left, Expression right, MethodInfo method)
  340. {
  341. method = BinaryCoreCheck ("op_Subtraction", left, right, method);
  342. return MakeSimpleBinary (ExpressionType.Subtract, left, right, method);
  343. }
  344. public static BinaryExpression SubtractChecked (Expression left, Expression right)
  345. {
  346. return SubtractChecked (left, right, null);
  347. }
  348. public static BinaryExpression SubtractChecked (Expression left, Expression right, MethodInfo method)
  349. {
  350. method = BinaryCoreCheck ("op_Subtraction", left, right, method);
  351. //
  352. // The check in BinaryCoreCheck allows a bit more than we do
  353. // (byte, sbyte). Catch that here
  354. //
  355. if (method == null){
  356. Type ltype = left.Type;
  357. if (ltype == typeof (byte) || ltype == typeof (sbyte))
  358. throw new InvalidOperationException (String.Format ("SubtractChecked not defined for {0} and {1}", left.Type, right.Type));
  359. }
  360. return MakeSimpleBinary (ExpressionType.SubtractChecked, left, right, method);
  361. }
  362. public static BinaryExpression Modulo (Expression left, Expression right)
  363. {
  364. return Modulo (left, right, null);
  365. }
  366. public static BinaryExpression Modulo (Expression left, Expression right, MethodInfo method)
  367. {
  368. method = BinaryCoreCheck ("op_Modulus", left, right, method);
  369. return MakeSimpleBinary (ExpressionType.Modulo, left, right, method);
  370. }
  371. public static BinaryExpression Multiply (Expression left, Expression right)
  372. {
  373. return Multiply (left, right, null);
  374. }
  375. public static BinaryExpression Multiply (Expression left, Expression right, MethodInfo method)
  376. {
  377. method = BinaryCoreCheck ("op_Multiply", left, right, method);
  378. return MakeSimpleBinary (ExpressionType.Multiply, left, right, method);
  379. }
  380. public static BinaryExpression MultiplyChecked (Expression left, Expression right)
  381. {
  382. return MultiplyChecked (left, right, null);
  383. }
  384. public static BinaryExpression MultiplyChecked (Expression left, Expression right, MethodInfo method)
  385. {
  386. method = BinaryCoreCheck ("op_Multiply", left, right, method);
  387. return MakeSimpleBinary (ExpressionType.MultiplyChecked, left, right, method);
  388. }
  389. public static BinaryExpression Divide (Expression left, Expression right)
  390. {
  391. return Divide (left, right, null);
  392. }
  393. public static BinaryExpression Divide (Expression left, Expression right, MethodInfo method)
  394. {
  395. method = BinaryCoreCheck ("op_Division", left, right, method);
  396. return MakeSimpleBinary (ExpressionType.Divide, left, right, method);
  397. }
  398. public static BinaryExpression Power (Expression left, Expression right)
  399. {
  400. return Power (left, right, null);
  401. }
  402. public static BinaryExpression Power (Expression left, Expression right, MethodInfo method)
  403. {
  404. method = BinaryCoreCheck (null, left, right, method);
  405. if (left.Type != typeof (double))
  406. throw new InvalidOperationException ("Power only supports double arguments");
  407. return MakeSimpleBinary (ExpressionType.Power, left, right, method);
  408. }
  409. //
  410. // Bitwise
  411. //
  412. public static BinaryExpression And (Expression left, Expression right)
  413. {
  414. return And (left, right, null);
  415. }
  416. public static BinaryExpression And (Expression left, Expression right, MethodInfo method)
  417. {
  418. method = BinaryBitwiseCoreCheck ("op_BitwiseAnd", left, right, method);
  419. return MakeSimpleBinary (ExpressionType.And, left, right, method);
  420. }
  421. public static BinaryExpression Or (Expression left, Expression right)
  422. {
  423. return Or (left, right, null);
  424. }
  425. public static BinaryExpression Or (Expression left, Expression right, MethodInfo method)
  426. {
  427. method = BinaryBitwiseCoreCheck ("op_BitwiseOr", left, right, method);
  428. return MakeSimpleBinary (ExpressionType.Or, left, right, method);
  429. }
  430. public static BinaryExpression ExclusiveOr (Expression left, Expression right)
  431. {
  432. return ExclusiveOr (left, right, null);
  433. }
  434. public static BinaryExpression ExclusiveOr (Expression left, Expression right, MethodInfo method)
  435. {
  436. method = BinaryBitwiseCoreCheck ("op_ExclusiveOr", left, right, method);
  437. return MakeSimpleBinary (ExpressionType.ExclusiveOr, left, right, method);
  438. }
  439. public static BinaryExpression LeftShift (Expression left, Expression right)
  440. {
  441. return LeftShift (left, right, null);
  442. }
  443. public static BinaryExpression LeftShift (Expression left, Expression right, MethodInfo method)
  444. {
  445. method = BinaryBitwiseCoreCheck ("op_LeftShift", left, right, method);
  446. return MakeSimpleBinary (ExpressionType.LeftShift, left, right, method);
  447. }
  448. public static BinaryExpression RightShift (Expression left, Expression right)
  449. {
  450. return RightShift (left, right, null);
  451. }
  452. public static BinaryExpression RightShift (Expression left, Expression right, MethodInfo method)
  453. {
  454. method = BinaryCoreCheck ("op_RightShift", left, right, method);
  455. return MakeSimpleBinary (ExpressionType.RightShift, left, right, method);
  456. }
  457. //
  458. // Short-circuit
  459. //
  460. public static BinaryExpression AndAlso (Expression left, Expression right)
  461. {
  462. return AndAlso (left, right, null);
  463. }
  464. public static BinaryExpression AndAlso (Expression left, Expression right, MethodInfo method)
  465. {
  466. method = BinaryCoreCheck ("op_BitwiseAnd", left, right, method);
  467. return MakeBoolBinary (ExpressionType.AndAlso, left, right, false, method);
  468. }
  469. public static BinaryExpression OrElse (Expression left, Expression right)
  470. {
  471. return OrElse (left, right, null);
  472. }
  473. public static BinaryExpression OrElse (Expression left, Expression right, MethodInfo method)
  474. {
  475. method = BinaryCoreCheck ("op_BitwiseOr", left, right, method);
  476. if (method == null){
  477. if (left.Type != typeof (bool))
  478. throw new InvalidOperationException ("Only booleans are allowed for OrElse");
  479. } else {
  480. // The method should have identical parameter and return types.
  481. if (left.Type != right.Type || method.ReturnType != left.Type)
  482. throw new ArgumentException ("left, right and return type must match");
  483. }
  484. return MakeBoolBinary (ExpressionType.OrElse, left, right, false, method);
  485. }
  486. //
  487. // Comparison
  488. //
  489. public static BinaryExpression Equal (Expression left, Expression right)
  490. {
  491. return Equal (left, right, false, null);
  492. }
  493. public static BinaryExpression Equal (Expression left, Expression right, bool liftToNull, MethodInfo method)
  494. {
  495. method = BinaryCoreCheck ("op_Equality", left, right, method);
  496. return MakeBoolBinary (ExpressionType.Equal, left, right, liftToNull, method);
  497. }
  498. public static BinaryExpression NotEqual (Expression left, Expression right)
  499. {
  500. return NotEqual (left, right, false, null);
  501. }
  502. public static BinaryExpression NotEqual (Expression left, Expression right, bool liftToNull, MethodInfo method)
  503. {
  504. method = BinaryCoreCheck ("op_Inequality", left, right, method);
  505. return MakeBoolBinary (ExpressionType.NotEqual, left, right, liftToNull, method);
  506. }
  507. public static BinaryExpression GreaterThan (Expression left, Expression right)
  508. {
  509. return GreaterThan (left, right, false, null);
  510. }
  511. public static BinaryExpression GreaterThan (Expression left, Expression right, bool liftToNull, MethodInfo method)
  512. {
  513. method = BinaryCoreCheck ("op_GreaterThan", left, right, method);
  514. return MakeBoolBinary (ExpressionType.GreaterThan, left, right, liftToNull, method);
  515. }
  516. public static BinaryExpression GreaterThanOrEqual (Expression left, Expression right)
  517. {
  518. return GreaterThanOrEqual (left, right, false, null);
  519. }
  520. public static BinaryExpression GreaterThanOrEqual (Expression left, Expression right, bool liftToNull, MethodInfo method)
  521. {
  522. method = BinaryCoreCheck ("op_GreaterThanOrEqual", left, right, method);
  523. return MakeBoolBinary (ExpressionType.GreaterThanOrEqual, left, right, liftToNull, method);
  524. }
  525. public static BinaryExpression LessThan (Expression left, Expression right)
  526. {
  527. return LessThan (left, right, false, null);
  528. }
  529. public static BinaryExpression LessThan (Expression left, Expression right, bool liftToNull, MethodInfo method)
  530. {
  531. method = BinaryCoreCheck ("op_LessThan", left, right, method);
  532. return MakeBoolBinary (ExpressionType.LessThan, left, right, liftToNull, method);
  533. }
  534. public static BinaryExpression LessThanOrEqual (Expression left, Expression right)
  535. {
  536. return LessThanOrEqual (left, right, false, null);
  537. }
  538. public static BinaryExpression LessThanOrEqual (Expression left, Expression right, bool liftToNull, MethodInfo method)
  539. {
  540. method = BinaryCoreCheck ("op_LessThanOrEqual", left, right, method);
  541. return MakeBoolBinary (ExpressionType.LessThanOrEqual, left, right, liftToNull, method);
  542. }
  543. //
  544. // Miscelaneous
  545. //
  546. static void ArrayCheck (Expression array)
  547. {
  548. if (array == null)
  549. throw new ArgumentNullException ("array");
  550. if (!array.Type.IsArray)
  551. throw new ArgumentException ("The array argument must be of type array");
  552. }
  553. public static BinaryExpression ArrayIndex (Expression array, Expression index)
  554. {
  555. ArrayCheck (array);
  556. if (index == null)
  557. throw new ArgumentNullException ("index");
  558. if (array.Type.GetArrayRank () != 1)
  559. throw new ArgumentException ("The array argument must be a single dimensional array");
  560. if (index.Type != typeof (int))
  561. throw new ArgumentException ("The index must be of type int");
  562. return new BinaryExpression (ExpressionType.ArrayIndex, array.Type.GetElementType (), array, index);
  563. }
  564. public static BinaryExpression Coalesce (Expression left, Expression right)
  565. {
  566. return Coalesce (left, right, null);
  567. }
  568. public static BinaryExpression Coalesce (Expression left, Expression right, LambdaExpression conversion)
  569. {
  570. if (left == null)
  571. throw new ArgumentNullException ("left");
  572. if (right == null)
  573. throw new ArgumentNullException ("right");
  574. //
  575. // First arg must ne nullable (either Nullable<T> or a reference type
  576. //
  577. if (left.Type.IsValueType && !IsNullable (left.Type))
  578. throw new InvalidOperationException ("Left expression can never be null");
  579. Type result = null;
  580. if (IsNullable (left.Type)){
  581. Type lbase = GetNullableOf (left.Type);
  582. if (!IsNullable (right.Type) && lbase.IsAssignableFrom (right.Type))
  583. result = lbase;
  584. }
  585. if (result == null && left.Type.IsAssignableFrom (right.Type))
  586. result = left.Type;
  587. if (result == null){
  588. if (IsNullable (left.Type) && right.Type.IsAssignableFrom (GetNullableOf (left.Type))){
  589. result = right.Type;
  590. }
  591. }
  592. if (result == null)
  593. throw new ArgumentException ("Incompatible argument types");
  594. //
  595. // FIXME: What do we do with "conversion"?
  596. //
  597. return new BinaryExpression (ExpressionType.Coalesce, result, left, right, false, false, null, conversion);
  598. }
  599. //
  600. // MakeBinary constructors
  601. //
  602. public static BinaryExpression MakeBinary (ExpressionType binaryType, Expression left, Expression right)
  603. {
  604. return MakeBinary (binaryType, left, right, false, null);
  605. }
  606. public static BinaryExpression MakeBinary (ExpressionType binaryType, Expression left, Expression right, bool liftToNull, MethodInfo method)
  607. {
  608. return MakeBinary (binaryType, left, right, liftToNull, method, null);
  609. }
  610. public static BinaryExpression MakeBinary (ExpressionType binaryType, Expression left, Expression right, bool liftToNull, MethodInfo method, LambdaExpression conversion)
  611. {
  612. switch (binaryType) {
  613. case ExpressionType.Add:
  614. return Add (left, right, method);
  615. case ExpressionType.AddChecked:
  616. return AddChecked (left, right, method);
  617. case ExpressionType.AndAlso:
  618. return AndAlso (left, right);
  619. case ExpressionType.Coalesce:
  620. return Coalesce (left, right, conversion);
  621. case ExpressionType.Divide:
  622. return Divide (left, right, method);
  623. case ExpressionType.Equal:
  624. return Equal (left, right, liftToNull, method);
  625. case ExpressionType.ExclusiveOr:
  626. return ExclusiveOr (left, right, method);
  627. case ExpressionType.GreaterThan:
  628. return GreaterThan (left, right, liftToNull, method);
  629. case ExpressionType.GreaterThanOrEqual:
  630. return GreaterThanOrEqual (left, right, liftToNull, method);
  631. case ExpressionType.LeftShift:
  632. return LeftShift (left, right, method);
  633. case ExpressionType.LessThan:
  634. return LessThan (left, right, liftToNull, method);
  635. case ExpressionType.LessThanOrEqual:
  636. return LessThanOrEqual (left, right, liftToNull, method);
  637. case ExpressionType.Modulo:
  638. return Modulo (left, right, method);
  639. case ExpressionType.Multiply:
  640. return Multiply (left, right, method);
  641. case ExpressionType.MultiplyChecked:
  642. return MultiplyChecked (left, right, method);
  643. case ExpressionType.NotEqual:
  644. return NotEqual (left, right, liftToNull, method);
  645. case ExpressionType.OrElse:
  646. return OrElse (left, right);
  647. case ExpressionType.Power:
  648. return Power (left, right, method);
  649. case ExpressionType.RightShift:
  650. return RightShift (left, right, method);
  651. case ExpressionType.Subtract:
  652. return Subtract (left, right, method);
  653. case ExpressionType.SubtractChecked:
  654. return SubtractChecked (left, right, method);
  655. case ExpressionType.And:
  656. return And (left, right, method);
  657. case ExpressionType.Or:
  658. return Or (left, right, method);
  659. }
  660. throw new ArgumentException ("MakeBinary expect a binary node type");
  661. }
  662. #endregion
  663. public static MethodCallExpression ArrayIndex (Expression array, params Expression [] indexes)
  664. {
  665. return ArrayIndex (array, indexes as IEnumerable<Expression>);
  666. }
  667. public static MethodCallExpression ArrayIndex (Expression array, IEnumerable<Expression> indexes)
  668. {
  669. ArrayCheck (array);
  670. if (indexes == null)
  671. throw new ArgumentNullException ("indexes");
  672. var args = indexes.ToReadOnlyCollection ();
  673. if (array.Type.GetArrayRank () != args.Count)
  674. throw new ArgumentException ("The number of arguments doesn't match the rank of the array");
  675. foreach (var arg in args)
  676. if (arg.Type != typeof (int))
  677. throw new ArgumentException ("The index must be of type int");
  678. return Call (array, array.Type.GetMethod ("Get", PublicInstance), args);
  679. }
  680. public static UnaryExpression ArrayLength (Expression array)
  681. {
  682. if (array == null)
  683. throw new ArgumentNullException ("array");
  684. if (!array.Type.IsArray)
  685. throw new ArgumentException ("The type of the expression must me Array");
  686. if (array.Type.GetArrayRank () != 1)
  687. throw new ArgumentException ("The array must be a single dimensional array");
  688. return new UnaryExpression (ExpressionType.ArrayLength, array, typeof (int));
  689. }
  690. [MonoTODO]
  691. public static MemberAssignment Bind (MemberInfo member, Expression expression)
  692. {
  693. throw new NotImplementedException ();
  694. }
  695. [MonoTODO]
  696. public static MemberAssignment Bind (MethodInfo propertyAccessor, Expression expression)
  697. {
  698. throw new NotImplementedException ();
  699. }
  700. public static MethodCallExpression Call (Expression instance, MethodInfo method)
  701. {
  702. return Call (instance, method, null as IEnumerable<Expression>);
  703. }
  704. public static MethodCallExpression Call (MethodInfo method, params Expression [] arguments)
  705. {
  706. return Call (null, method, arguments as IEnumerable<Expression>);
  707. }
  708. public static MethodCallExpression Call (Expression instance, MethodInfo method, params Expression [] arguments)
  709. {
  710. return Call (instance, method, arguments as IEnumerable<Expression>);
  711. }
  712. public static MethodCallExpression Call (Expression instance, MethodInfo method, IEnumerable<Expression> arguments)
  713. {
  714. if (method == null)
  715. throw new ArgumentNullException ("method");
  716. if (instance == null && !method.IsStatic)
  717. throw new ArgumentNullException ("instance");
  718. if (instance != null && !method.DeclaringType.IsAssignableFrom (instance.Type))
  719. throw new ArgumentException ("Type is not assignable to the declaring type of the method");
  720. var args = arguments.ToReadOnlyCollection ();
  721. var parameters = method.GetParameters ();
  722. if (args.Count != parameters.Length)
  723. throw new ArgumentException ("The number of arguments doesn't match the number of parameters");
  724. // TODO: check for assignability of the arguments on the parameters
  725. return new MethodCallExpression (instance, method, args);
  726. }
  727. [MonoTODO]
  728. public static MethodCallExpression Call (Expression instance, string methodName, Type [] typeArguments, params Expression [] arguments)
  729. {
  730. throw new NotImplementedException ();
  731. }
  732. [MonoTODO]
  733. public static MethodCallExpression Call (Type type, string methodName, Type [] typeArguments, params Expression [] arguments)
  734. {
  735. throw new NotImplementedException ();
  736. }
  737. public static ConditionalExpression Condition (Expression test, Expression ifTrue, Expression ifFalse)
  738. {
  739. if (test == null)
  740. throw new ArgumentNullException ("test");
  741. if (ifTrue == null)
  742. throw new ArgumentNullException ("ifTrue");
  743. if (ifFalse == null)
  744. throw new ArgumentNullException ("ifFalse");
  745. if (test.Type != typeof (bool))
  746. throw new ArgumentException ("Test expression should be of type bool");
  747. if (ifTrue.Type != ifFalse.Type)
  748. throw new ArgumentException ("The ifTrue and ifFalse type do not match");
  749. return new ConditionalExpression (test, ifTrue, ifFalse);
  750. }
  751. public static ConstantExpression Constant (object value)
  752. {
  753. if (value == null)
  754. return new ConstantExpression (null, typeof (object));
  755. return Constant (value, value.GetType ());
  756. }
  757. public static ConstantExpression Constant (object value, Type type)
  758. {
  759. if (type == null)
  760. throw new ArgumentNullException ("type");
  761. //
  762. // value must be compatible with type, no conversions
  763. // are allowed
  764. //
  765. if (value == null){
  766. if (type.IsValueType && !IsNullable (type))
  767. throw new ArgumentException ();
  768. } else {
  769. if (!(type.IsValueType && IsNullable (type)) && value.GetType () != type)
  770. throw new ArgumentException ();
  771. }
  772. return new ConstantExpression (value, type);
  773. }
  774. [MonoTODO]
  775. public static UnaryExpression Convert (Expression expression, Type type)
  776. {
  777. throw new NotImplementedException ();
  778. }
  779. [MonoTODO]
  780. public static UnaryExpression Convert (Expression expression, Type type, MethodInfo method)
  781. {
  782. throw new NotImplementedException ();
  783. }
  784. [MonoTODO]
  785. public static UnaryExpression ConvertChecked (Expression expression, Type type)
  786. {
  787. throw new NotImplementedException ();
  788. }
  789. [MonoTODO]
  790. public static UnaryExpression ConvertChecked (Expression expression, Type type, MethodInfo method)
  791. {
  792. throw new NotImplementedException ();
  793. }
  794. [MonoTODO]
  795. public static ElementInit ElementInit (MethodInfo addMethod, params Expression [] arguments)
  796. {
  797. throw new NotImplementedException ();
  798. }
  799. [MonoTODO]
  800. public static ElementInit ElementInit (MethodInfo addMethod, IEnumerable<Expression> arguments)
  801. {
  802. throw new NotImplementedException ();
  803. }
  804. [MonoTODO]
  805. public static MemberExpression Field (Expression expression, FieldInfo field)
  806. {
  807. throw new NotImplementedException ();
  808. }
  809. [MonoTODO]
  810. public static MemberExpression Field (Expression expression, string fieldName)
  811. {
  812. throw new NotImplementedException ();
  813. }
  814. public static Type GetActionType (params Type [] typeArgs)
  815. {
  816. if (typeArgs == null)
  817. throw new ArgumentNullException ("typeArgs");
  818. if (typeArgs.Length > 4)
  819. throw new ArgumentException ("No Action type of this arity");
  820. if (typeArgs.Length == 0)
  821. return typeof (Action);
  822. Type action = null;
  823. switch (typeArgs.Length) {
  824. case 1:
  825. action = typeof (Action<>);
  826. break;
  827. case 2:
  828. action = typeof (Action<,>);
  829. break;
  830. case 3:
  831. action = typeof (Action<,,>);
  832. break;
  833. case 4:
  834. action = typeof (Action<,,,>);
  835. break;
  836. }
  837. return action.MakeGenericType (typeArgs);
  838. }
  839. public static Type GetFuncType (params Type [] typeArgs)
  840. {
  841. if (typeArgs == null)
  842. throw new ArgumentNullException ("typeArgs");
  843. if (typeArgs.Length < 1 || typeArgs.Length > 5)
  844. throw new ArgumentException ("No Func type of this arity");
  845. Type func = null;
  846. switch (typeArgs.Length) {
  847. case 1:
  848. func = typeof (Func<>);
  849. break;
  850. case 2:
  851. func = typeof (Func<,>);
  852. break;
  853. case 3:
  854. func = typeof (Func<,,>);
  855. break;
  856. case 4:
  857. func = typeof (Func<,,,>);
  858. break;
  859. case 5:
  860. func = typeof (Func<,,,,>);
  861. break;
  862. }
  863. return func.MakeGenericType (typeArgs);
  864. }
  865. [MonoTODO]
  866. public static InvocationExpression Invoke (Expression expression, params Expression [] arguments)
  867. {
  868. throw new NotImplementedException ();
  869. }
  870. [MonoTODO]
  871. public static InvocationExpression Invoke (Expression expression, IEnumerable<Expression> arguments)
  872. {
  873. throw new NotImplementedException ();
  874. }
  875. public static Expression<TDelegate> Lambda<TDelegate> (Expression body, params ParameterExpression [] parameters)
  876. {
  877. if (body == null)
  878. throw new ArgumentNullException ("body");
  879. return new Expression<TDelegate> (body, parameters);
  880. }
  881. [MonoTODO]
  882. public static Expression<TDelegate> Lambda<TDelegate> (Expression body, IEnumerable<ParameterExpression> parameters)
  883. {
  884. throw new NotImplementedException ();
  885. }
  886. [MonoTODO]
  887. public static LambdaExpression Lambda (Expression body, params ParameterExpression [] parameters)
  888. {
  889. throw new NotImplementedException ();
  890. }
  891. public static LambdaExpression Lambda (Type delegateType, Expression body, params ParameterExpression [] parameters)
  892. {
  893. return Lambda (delegateType, body, parameters as IEnumerable<ParameterExpression>);
  894. }
  895. [MonoTODO]
  896. public static LambdaExpression Lambda (Type delegateType, Expression body, IEnumerable<ParameterExpression> parameters)
  897. {
  898. if (delegateType == null)
  899. throw new ArgumentNullException ("delegateType");
  900. if (body == null)
  901. throw new ArgumentNullException ("body");
  902. return new LambdaExpression (delegateType, body, parameters.ToReadOnlyCollection ());
  903. }
  904. public static MemberListBinding ListBind (MemberInfo member, params ElementInit [] initializers)
  905. {
  906. throw new NotImplementedException ();
  907. }
  908. [MonoTODO]
  909. public static MemberListBinding ListBind (MemberInfo member, IEnumerable<ElementInit> initializers)
  910. {
  911. throw new NotImplementedException ();
  912. }
  913. [MonoTODO]
  914. public static MemberListBinding ListBind (MethodInfo propertyAccessor, params ElementInit [] initializers)
  915. {
  916. throw new NotImplementedException ();
  917. }
  918. [MonoTODO]
  919. public static MemberListBinding ListBind (MethodInfo propertyAccessor, IEnumerable<ElementInit> initializers)
  920. {
  921. throw new NotImplementedException ();
  922. }
  923. [MonoTODO]
  924. public static ListInitExpression ListInit (NewExpression newExpression, params ElementInit [] initializers)
  925. {
  926. throw new NotImplementedException ();
  927. }
  928. [MonoTODO]
  929. public static ListInitExpression ListInit (NewExpression newExpression, IEnumerable<ElementInit> initializers)
  930. {
  931. throw new NotImplementedException ();
  932. }
  933. [MonoTODO]
  934. public static ListInitExpression ListInit (NewExpression newExpression, params Expression [] initializers)
  935. {
  936. throw new NotImplementedException ();
  937. }
  938. [MonoTODO]
  939. public static ListInitExpression ListInit (NewExpression newExpression, IEnumerable<Expression> initializers)
  940. {
  941. throw new NotImplementedException ();
  942. }
  943. [MonoTODO]
  944. public static ListInitExpression ListInit (NewExpression newExpression, MethodInfo addMethod, params Expression [] initializers)
  945. {
  946. throw new NotImplementedException ();
  947. }
  948. [MonoTODO]
  949. public static ListInitExpression ListInit (NewExpression newExpression, MethodInfo addMethod, IEnumerable<Expression> initializers)
  950. {
  951. throw new NotImplementedException ();
  952. }
  953. public static MemberExpression MakeMemberAccess (Expression expression, MemberInfo member)
  954. {
  955. if (expression == null)
  956. throw new ArgumentNullException ("expression");
  957. if (member == null)
  958. throw new ArgumentNullException ("member");
  959. var field = member as FieldInfo;
  960. if (field != null)
  961. return Field (expression, field);
  962. var property = member as PropertyInfo;
  963. if (property != null)
  964. return Property (expression, property);
  965. throw new ArgumentException ("Member should either be a field or a property");
  966. }
  967. public static UnaryExpression MakeUnary (ExpressionType unaryType, Expression operand, Type type)
  968. {
  969. return MakeUnary (unaryType, operand, type, null);
  970. }
  971. public static UnaryExpression MakeUnary (ExpressionType unaryType, Expression operand, Type type, MethodInfo method)
  972. {
  973. switch (unaryType) {
  974. case ExpressionType.ArrayLength:
  975. return ArrayLength (operand);
  976. case ExpressionType.Convert:
  977. return Convert (operand, type, method);
  978. case ExpressionType.ConvertChecked:
  979. return ConvertChecked (operand, type, method);
  980. case ExpressionType.Negate:
  981. return Negate (operand, method);
  982. case ExpressionType.NegateChecked:
  983. return NegateChecked (operand, method);
  984. case ExpressionType.Not:
  985. return Not (operand, method);
  986. case ExpressionType.Quote:
  987. return Quote (operand);
  988. case ExpressionType.TypeAs:
  989. return TypeAs (operand, type);
  990. case ExpressionType.UnaryPlus:
  991. return UnaryPlus (operand, method);
  992. }
  993. throw new ArgumentException ("MakeUnary expect an unary operator");
  994. }
  995. [MonoTODO]
  996. public static MemberMemberBinding MemberBind (MemberInfo member, params MemberBinding [] binding)
  997. {
  998. throw new NotImplementedException ();
  999. }
  1000. [MonoTODO]
  1001. public static MemberMemberBinding MemberBind (MemberInfo member, IEnumerable<MemberBinding> binding)
  1002. {
  1003. throw new NotImplementedException ();
  1004. }
  1005. [MonoTODO]
  1006. public static MemberMemberBinding MemberBind (MethodInfo propertyAccessor, params MemberBinding [] binding)
  1007. {
  1008. throw new NotImplementedException ();
  1009. }
  1010. [MonoTODO]
  1011. public static MemberMemberBinding MemberBind (MethodInfo propertyAccessor, IEnumerable<MemberBinding> binding)
  1012. {
  1013. throw new NotImplementedException ();
  1014. }
  1015. [MonoTODO]
  1016. public static MemberInitExpression MemberInit (NewExpression newExpression, params MemberBinding [] binding)
  1017. {
  1018. throw new NotImplementedException ();
  1019. }
  1020. [MonoTODO]
  1021. public static MemberInitExpression MemberInit (NewExpression newExpression, IEnumerable<MemberBinding> binding)
  1022. {
  1023. throw new NotImplementedException ();
  1024. }
  1025. public static UnaryExpression Negate (Expression expression)
  1026. {
  1027. return Negate (expression, null);
  1028. }
  1029. public static UnaryExpression Negate (Expression expression, MethodInfo method)
  1030. {
  1031. method = UnaryCoreCheck ("op_UnaryNegation", expression, method);
  1032. return MakeSimpleUnary (ExpressionType.Negate, expression, method);
  1033. }
  1034. public static UnaryExpression NegateChecked (Expression expression)
  1035. {
  1036. return NegateChecked (expression, null);
  1037. }
  1038. public static UnaryExpression NegateChecked (Expression expression, MethodInfo method)
  1039. {
  1040. method = UnaryCoreCheck ("op_UnaryNegation", expression, method);
  1041. return MakeSimpleUnary (ExpressionType.Negate, expression, method);
  1042. }
  1043. [MonoTODO]
  1044. public static NewExpression New (ConstructorInfo constructor)
  1045. {
  1046. throw new NotImplementedException ();
  1047. }
  1048. [MonoTODO]
  1049. public static NewExpression New (Type type)
  1050. {
  1051. throw new NotImplementedException ();
  1052. }
  1053. [MonoTODO]
  1054. public static NewExpression New (ConstructorInfo constructor, params Expression [] arguments)
  1055. {
  1056. throw new NotImplementedException ();
  1057. }
  1058. [MonoTODO]
  1059. public static NewExpression New (ConstructorInfo constructor, IEnumerable<Expression> arguments)
  1060. {
  1061. throw new NotImplementedException ();
  1062. }
  1063. [MonoTODO]
  1064. public static NewExpression New (ConstructorInfo constructor, IEnumerable<Expression> arguments, params MemberInfo [] members)
  1065. {
  1066. throw new NotImplementedException ();
  1067. }
  1068. [MonoTODO]
  1069. public static NewExpression New (ConstructorInfo constructor, IEnumerable<Expression> arguments, IEnumerable<MemberInfo> members)
  1070. {
  1071. throw new NotImplementedException ();
  1072. }
  1073. public static NewArrayExpression NewArrayBounds (Type type, params Expression [] bounds)
  1074. {
  1075. return NewArrayBounds (type, bounds as IEnumerable<Expression>);
  1076. }
  1077. public static NewArrayExpression NewArrayBounds (Type type, IEnumerable<Expression> bounds)
  1078. {
  1079. if (type == null)
  1080. throw new ArgumentNullException ("type");
  1081. if (bounds == null)
  1082. throw new ArgumentNullException ("bounds");
  1083. var array_bounds = bounds.ToReadOnlyCollection ();
  1084. foreach (var expression in array_bounds)
  1085. if (!IsInt (expression.Type))
  1086. throw new ArgumentException ("The bounds collection can only contain expression of integers types");
  1087. return new NewArrayExpression (ExpressionType.NewArrayBounds, type.MakeArrayType (array_bounds.Count), array_bounds);
  1088. }
  1089. public static NewArrayExpression NewArrayInit (Type type, params Expression [] initializers)
  1090. {
  1091. return NewArrayInit (type, initializers as IEnumerable<Expression>);
  1092. }
  1093. public static NewArrayExpression NewArrayInit (Type type, IEnumerable<Expression> initializers)
  1094. {
  1095. if (type == null)
  1096. throw new ArgumentNullException ("type");
  1097. if (initializers == null)
  1098. throw new ArgumentNullException ("initializers");
  1099. var array_initializers = initializers.ToReadOnlyCollection ();
  1100. foreach (var expression in initializers) {
  1101. if (expression == null)
  1102. throw new ArgumentNullException ("initializers");
  1103. if (!type.IsAssignableFrom (expression.Type))
  1104. throw new InvalidOperationException ();
  1105. // TODO: Quote elements if type == typeof (Expression)
  1106. }
  1107. return new NewArrayExpression (ExpressionType.NewArrayInit, type.MakeArrayType (), array_initializers);
  1108. }
  1109. public static UnaryExpression Not (Expression expression)
  1110. {
  1111. return Not (expression, null);
  1112. }
  1113. public static UnaryExpression Not (Expression expression, MethodInfo method)
  1114. {
  1115. method = UnaryCoreCheck ("op_LogicalNot", expression, method);
  1116. return MakeSimpleUnary (ExpressionType.Not, expression, method);
  1117. }
  1118. public static ParameterExpression Parameter (Type type, string name)
  1119. {
  1120. if (type == null)
  1121. throw new ArgumentNullException ("type");
  1122. return new ParameterExpression (type, name);
  1123. }
  1124. [MonoTODO]
  1125. public static MemberExpression Property (Expression expression, MethodInfo propertyAccessor)
  1126. {
  1127. throw new NotImplementedException ();
  1128. }
  1129. [MonoTODO]
  1130. public static MemberExpression Property (Expression expression, PropertyInfo property)
  1131. {
  1132. throw new NotImplementedException ();
  1133. }
  1134. [MonoTODO]
  1135. public static MemberExpression Property (Expression expression, string propertyName)
  1136. {
  1137. throw new NotImplementedException ();
  1138. }
  1139. [MonoTODO]
  1140. public static MemberExpression PropertyOrField (Expression expression, string propertyOrFieldName)
  1141. {
  1142. throw new NotImplementedException ();
  1143. }
  1144. public static UnaryExpression Quote (Expression expression)
  1145. {
  1146. if (expression == null)
  1147. throw new ArgumentNullException ("expression");
  1148. return new UnaryExpression (ExpressionType.Quote, expression, expression.GetType ());
  1149. }
  1150. public static UnaryExpression TypeAs (Expression expression, Type type)
  1151. {
  1152. if (expression == null)
  1153. throw new ArgumentNullException ("expression");
  1154. if (type == null)
  1155. throw new ArgumentNullException ("type");
  1156. if (type.IsValueType && !IsNullable (type))
  1157. throw new ArgumentException ("TypeAs expect a reference or a nullable type");
  1158. return new UnaryExpression (ExpressionType.TypeAs, expression, type);
  1159. }
  1160. public static TypeBinaryExpression TypeIs (Expression expression, Type type)
  1161. {
  1162. if (expression == null)
  1163. throw new ArgumentNullException ("expression");
  1164. if (type == null)
  1165. throw new ArgumentNullException ("type");
  1166. return new TypeBinaryExpression (ExpressionType.TypeIs, expression, type, typeof (bool));
  1167. }
  1168. public static UnaryExpression UnaryPlus (Expression expression)
  1169. {
  1170. return UnaryPlus (expression, null);
  1171. }
  1172. public static UnaryExpression UnaryPlus (Expression expression, MethodInfo method)
  1173. {
  1174. method = UnaryCoreCheck ("op_UnaryPlus", expression, method);
  1175. return MakeSimpleUnary (ExpressionType.UnaryPlus, expression, method);
  1176. }
  1177. internal static bool IsNullable (Type type)
  1178. {
  1179. return type.IsGenericType && type.GetGenericTypeDefinition () == typeof (Nullable<>);
  1180. }
  1181. internal static bool IsUnsigned (Type t)
  1182. {
  1183. if (t.IsPointer)
  1184. return IsUnsigned (t.GetElementType ());
  1185. return t == typeof (ushort) || t == typeof (uint) || t == typeof (ulong) || t == typeof (byte);
  1186. }
  1187. //
  1188. // returns the T in a a Nullable<T> type.
  1189. //
  1190. internal static Type GetNullableOf (Type type)
  1191. {
  1192. return type.GetGenericArguments () [0];
  1193. }
  1194. //
  1195. // This method must be overwritten by derived classes to
  1196. // compile the expression
  1197. //
  1198. internal abstract void Emit (EmitContext ec);
  1199. }
  1200. }