Expression.cs 50 KB

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